From 33895b0330fd9e32dc9bc1e69bc15d54a9207cb2 Mon Sep 17 00:00:00 2001 From: Arturs Krumins Date: Tue, 3 Sep 2024 09:59:40 +0300 Subject: [PATCH] ios: show received messages using checkmark with slash (#4816) * ios: show received messages using checkmark with slash * update message info view * cleanup * remove dead arguments * Revert "remove dead arguments" This reverts commit 1fc07669c785dde960c77ee54026004871706acf. * remove status icon * cleanup * update assets * tweak checkmark * fix space, rename --------- Co-authored-by: Evgeny Poberezkin --- .../checkmark.2.symbolset/Contents.json | 12 + .../checkmark.2.symbolset/checkmark.2.svg | 227 ++++++++++++++++++ .../checkmark.wide.symbolset/Contents.json | 12 + .../checkmark.wide.svg | 218 +++++++++++++++++ .../Views/Chat/ChatItem/CIMetaView.swift | 57 ++--- .../Shared/Views/Chat/ChatItemInfoView.swift | 16 +- apps/ios/SimpleXChat/ChatTypes.swift | 54 +++-- 7 files changed, 514 insertions(+), 82 deletions(-) create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/Contents.json create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/checkmark.2.svg create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/Contents.json create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/checkmark.wide.svg diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/Contents.json b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/Contents.json new file mode 100644 index 0000000000..8e38b499dd --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info": { + "author": "xcode", + "version": 1 + }, + "symbols": [ + { + "filename": "checkmark.2.svg", + "idiom": "universal" + } + ] +} \ No newline at end of file diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/checkmark.2.svg b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/checkmark.2.svg new file mode 100644 index 0000000000..577fa1db76 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/checkmark.2.svg @@ -0,0 +1,227 @@ + + + checkmark.2 + + + + + + + Weight/Scale Variations + + + Ultralight + + + Thin + + + Light + + + Regular + + + Medium + + + Semibold + + + Bold + + + Heavy + + + Black + + + + + + + + + + + + + Design Variations + + + Symbols are supported in up to nine weights and three scales. + + + For optimal layout with text and other symbols, vertically align + + + symbols with the adjacent text. + + + + + + + + + Margins + + + Leading and trailing margins on the left and right side of each symbol + + + + can be adjusted by modifying the x-location of the margin guidelines. + + + + Modifications are automatically applied proportionally to all + + + scales and weights. + + + + + + Exporting + + + Symbols should be outlined when exporting to ensure the + + + design is preserved when submitting to Xcode. + + + Template v.5.0 + + + Requires Xcode 15 or greater + + + Generated from double.checkmark + + + Typeset at 100.0 points + + + Small + + + Medium + + + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/Contents.json b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/Contents.json new file mode 100644 index 0000000000..11a91cb811 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info": { + "author": "xcode", + "version": 1 + }, + "symbols": [ + { + "filename": "checkmark.wide.svg", + "idiom": "universal" + } + ] +} \ No newline at end of file diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/checkmark.wide.svg b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/checkmark.wide.svg new file mode 100644 index 0000000000..b5dfc6b3de --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/checkmark.wide.svg @@ -0,0 +1,218 @@ + + + checkmark.wide + + + + + + + Weight/Scale Variations + + + Ultralight + + + Thin + + + Light + + + Regular + + + Medium + + + Semibold + + + Bold + + + Heavy + + + Black + + + + + + + + + + + + + Design Variations + + + Symbols are supported in up to nine weights and three scales. + + + For optimal layout with text and other symbols, vertically align + + + symbols with the adjacent text. + + + + + + + + + Margins + + + Leading and trailing margins on the left and right side of each symbol + + + + can be adjusted by modifying the x-location of the margin guidelines. + + + + Modifications are automatically applied proportionally to all + + + scales and weights. + + + + + + Exporting + + + Symbols should be outlined when exporting to ensure the + + + design is preserved when submitting to Xcode. + + + Template v.5.0 + + + Requires Xcode 15 or greater + + + Generated from double.checkmark + + + Typeset at 100.0 points + + + Small + + + Medium + + + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift index 3f2ec8f38e..719c1cabd0 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift @@ -25,41 +25,22 @@ struct CIMetaView: View { if chatItem.isDeletedContent { chatItem.timestampText.font(.caption).foregroundColor(metaColor) } else { - let meta = chatItem.meta - let ttl = chat.chatInfo.timedMessagesTTL - let encrypted = chatItem.encryptedFile - switch meta.itemStatus { - case let .sndSent(sndProgress): - switch sndProgress { - case .complete: ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, sent: .sent, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) - case .partial: ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: paleMetaColor, sent: .sent, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) - } - case let .sndRcvd(_, sndProgress): - switch sndProgress { - case .complete: - ZStack { - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, sent: .rcvd1, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, sent: .rcvd2, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) - } - case .partial: - ZStack { - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: paleMetaColor, sent: .rcvd1, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: paleMetaColor, sent: .rcvd2, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) - } - } - default: - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) - } + ciMetaText( + chatItem.meta, + chatTTL: chat.chatInfo.timedMessagesTTL, + encrypted: chatItem.encryptedFile, + color: chatItem.meta.itemStatus.sndProgress == .partial + ? paleMetaColor + : metaColor, + showStatus: showStatus, + showEdited: showEdited, + showViaProxy: showSentViaProxy, + showTimesamp: showTimestamp + ) } } } -enum SentCheckmark { - case sent - case rcvd1 - case rcvd2 -} - func ciMetaText( _ meta: CIMeta, chatTTL: Int?, @@ -67,7 +48,6 @@ func ciMetaText( color: Color = .clear, primaryColor: Color = .accentColor, transparent: Bool = false, - sent: SentCheckmark? = nil, showStatus: Bool = true, showEdited: Bool = true, showViaProxy: Bool, @@ -89,17 +69,8 @@ func ciMetaText( r = r + statusIconText("arrow.forward", color.opacity(0.67)).font(.caption2) } if showStatus { - if let (icon, statusColor) = meta.statusIcon(color, primaryColor) { - let t = Text(Image(systemName: icon)).font(.caption2) - let gap = Text(" ").kerning(-1.25) - let t1 = t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) - switch sent { - case nil: r = r + t1 - case .sent: r = r + t1 + gap - case .rcvd1: r = r + t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) + gap - case .rcvd2: r = r + gap + t1 - } - r = r + Text(" ") + if let (image, statusColor) = meta.itemStatus.statusIcon(color, primaryColor) { + r = r + Text(image).foregroundColor(transparent ? .clear : statusColor) + Text(" ") } else if !meta.disappearing { r = r + statusIconText("circlebadge.fill", .clear) + Text(" ") } diff --git a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift index f6a856dad1..62ea607d27 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift @@ -450,20 +450,8 @@ struct ChatItemInfoView: View { .foregroundColor(theme.colors.secondary).opacity(0.67) } let v = Group { - let (icon, statusColor) = status.statusIcon(theme.colors.secondary, theme.colors.primary) - switch status { - case .rcvd: - ZStack(alignment: .trailing) { - Image(systemName: icon) - .foregroundColor(statusColor.opacity(0.67)) - .padding(.trailing, 6) - Image(systemName: icon) - .foregroundColor(statusColor.opacity(0.67)) - } - default: - Image(systemName: icon) - .foregroundColor(statusColor) - } + let (image, statusColor) = status.statusIcon(theme.colors.secondary, theme.colors.primary) + image.foregroundColor(statusColor) } if let (title, text) = status.statusInfo { diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 07340bb963..105edd725f 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -2723,10 +2723,6 @@ public struct CIMeta: Decodable, Hashable { return false } - public func statusIcon(_ metaColor: Color/* = .secondary*/, _ primaryColor: Color = .accentColor) -> (String, Color)? { - itemStatus.statusIcon(metaColor, primaryColor) - } - public static func getSample(_ id: Int64, _ ts: Date, _ text: String, _ status: CIStatus = .sndNew, itemDeleted: CIDeleted? = nil, itemEdited: Bool = false, itemLive: Bool = false, deletable: Bool = true, editable: Bool = true) -> CIMeta { CIMeta( itemId: id, @@ -2794,21 +2790,29 @@ public enum CIStatus: Decodable, Hashable { } } - public func statusIcon(_ metaColor: Color/* = .secondary*/, _ primaryColor: Color = .accentColor) -> (String, Color)? { + public func statusIcon(_ metaColor: Color, _ primaryColor: Color = .accentColor) -> (Image, Color)? { switch self { - case .sndNew: return nil - case .sndSent: return ("checkmark", metaColor) + case .sndNew: nil + case .sndSent: (Image("checkmark.wide"), metaColor) case let .sndRcvd(msgRcptStatus, _): switch msgRcptStatus { - case .ok: return ("checkmark", metaColor) - case .badMsgHash: return ("checkmark", .red) + case .ok: (Image("checkmark.2"), metaColor) + case .badMsgHash: (Image("checkmark.2"), .red) } - case .sndErrorAuth: return ("multiply", .red) - case .sndError: return ("multiply", .red) - case .sndWarning: return ("exclamationmark.triangle.fill", .orange) - case .rcvNew: return ("circlebadge.fill", primaryColor) - case .rcvRead: return nil - case .invalid: return ("questionmark", metaColor) + case .sndErrorAuth: (Image(systemName: "multiply"), .red) + case .sndError: (Image(systemName: "multiply"), .red) + case .sndWarning: (Image(systemName: "exclamationmark.triangle.fill"), .orange) + case .rcvNew: (Image(systemName: "circlebadge.fill"), primaryColor) + case .rcvRead: nil + case .invalid: (Image(systemName: "questionmark"), metaColor) + } + } + + public var sndProgress: SndCIStatusProgress? { + switch self { + case let .sndSent(sndProgress): sndProgress + case let .sndRcvd(_ , sndProgress): sndProgress + default: nil } } @@ -2903,20 +2907,20 @@ public enum GroupSndStatus: Decodable, Hashable { case warning(agentError: SndError) case invalid(text: String) - public func statusIcon(_ metaColor: Color/* = .secondary*/, _ primaryColor: Color = .accentColor) -> (String, Color) { + public func statusIcon(_ metaColor: Color, _ primaryColor: Color = .accentColor) -> (Image, Color) { switch self { - case .new: return ("ellipsis", metaColor) - case .forwarded: return ("chevron.forward.2", metaColor) - case .inactive: return ("person.badge.minus", metaColor) - case .sent: return ("checkmark", metaColor) + case .new: (Image(systemName: "ellipsis"), metaColor) + case .forwarded: (Image(systemName: "chevron.forward.2"), metaColor) + case .inactive: (Image(systemName: "person.badge.minus"), metaColor) + case .sent: (Image("checkmark.wide"), metaColor) case let .rcvd(msgRcptStatus): switch msgRcptStatus { - case .ok: return ("checkmark", metaColor) - case .badMsgHash: return ("checkmark", .red) + case .ok: (Image("checkmark.2"), metaColor) + case .badMsgHash: (Image("checkmark.2"), .red) } - case .error: return ("multiply", .red) - case .warning: return ("exclamationmark.triangle.fill", .orange) - case .invalid: return ("questionmark", metaColor) + case .error: (Image(systemName: "multiply"), .red) + case .warning: (Image(systemName: "exclamationmark.triangle.fill"), .orange) + case .invalid: (Image(systemName: "questionmark"), metaColor) } }