From edc1add87a304fc556f949ed1d5a2c1bca8771e1 Mon Sep 17 00:00:00 2001 From: Levitating Pineapple Date: Mon, 2 Sep 2024 20:15:12 +0300 Subject: [PATCH] ios: show received messages using checkmark with slash --- .../checkmark.slash.symbolset/Contents.json | 12 ++ .../checkmark.slash.svg | 154 ++++++++++++++++++ .../checkmark.space.symbolset/Contents.json | 12 ++ .../checkmark.space.svg | 151 +++++++++++++++++ .../Views/Chat/ChatItem/CIMetaView.swift | 59 ++----- apps/ios/SimpleXChat/ChatTypes.swift | 48 ++++-- 6 files changed, 379 insertions(+), 57 deletions(-) create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/Contents.json create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/checkmark.slash.svg create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.space.symbolset/Contents.json create mode 100644 apps/ios/Shared/Assets.xcassets/checkmark.space.symbolset/checkmark.space.svg diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/Contents.json b/apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/Contents.json new file mode 100644 index 0000000000..867b238f3d --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "symbols" : [ + { + "filename" : "checkmark.slash.svg", + "idiom" : "universal" + } + ] +} diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/checkmark.slash.svg b/apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/checkmark.slash.svg new file mode 100644 index 0000000000..8cae8426e6 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.slash.symbolset/checkmark.slash.svg @@ -0,0 +1,154 @@ + + + checkmark.slash + + + + + + + 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.space.symbolset/Contents.json b/apps/ios/Shared/Assets.xcassets/checkmark.space.symbolset/Contents.json new file mode 100644 index 0000000000..1aad1111ad --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.space.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "symbols" : [ + { + "filename" : "checkmark.space.svg", + "idiom" : "universal" + } + ] +} diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.space.symbolset/checkmark.space.svg b/apps/ios/Shared/Assets.xcassets/checkmark.space.symbolset/checkmark.space.svg new file mode 100644 index 0000000000..9c67bfd853 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.space.symbolset/checkmark.space.svg @@ -0,0 +1,151 @@ + + + checkmark.slash + + + + + + + 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..3a2e15b691 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,12 @@ 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 + if let icon = meta.itemStatus.statusIcon(color, primaryColor) { + let image = switch icon.source { + case let .system(name): Image(systemName: name) + case let .bundled(name): Image(name) } - r = r + Text(" ") + r = r + Text(image).foregroundColor(icon.color) } else if !meta.disappearing { r = r + statusIconText("circlebadge.fill", .clear) + Text(" ") } diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 07340bb963..9802ca4b3c 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,43 @@ public enum CIStatus: Decodable, Hashable { } } - public func statusIcon(_ metaColor: Color/* = .secondary*/, _ primaryColor: Color = .accentColor) -> (String, Color)? { + public var sndProgress: SndCIStatusProgress? { switch self { - case .sndNew: return nil - case .sndSent: return ("checkmark", metaColor) + case let .sndSent(sndProgress): sndProgress + case let .sndRcvd(_ , sndProgress): sndProgress + default: nil + } + } + + public struct Icon { + public enum Source { + case system(String) + case bundled(String) + } + public let source: Source + public let color: Color + + init(_ source: Source, in color: Color) { + self.source = source + self.color = color + } + } + + public func statusIcon(_ metaColor: Color, _ primaryColor: Color = .accentColor) -> Icon? { + switch self { + case .sndNew: nil + case .sndSent: Icon(.bundled("checkmark.space"), in: metaColor) case let .sndRcvd(msgRcptStatus, _): switch msgRcptStatus { - case .ok: return ("checkmark", metaColor) - case .badMsgHash: return ("checkmark", .red) + case .ok: Icon(.bundled("checkmark.slash"), in: metaColor) + case .badMsgHash: Icon(.bundled("checkmark.slash"), in: .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: Icon(.system("multiply"), in: .red) + case .sndError: Icon(.system("multiply"), in: .red) + case .sndWarning: Icon(.system("exclamationmark.triangle.fill"), in: .orange) + case .rcvNew: Icon(.system("circlebadge.fill"), in: primaryColor) + case .rcvRead: nil + case .invalid: Icon(.system("questionmark"), in: metaColor) } }