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 @@
+
+
\ 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 @@
+
+
\ 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)
}
}
diff --git a/apps/multiplatform/common/build.gradle.kts b/apps/multiplatform/common/build.gradle.kts
index a1afb655e2..1670672753 100644
--- a/apps/multiplatform/common/build.gradle.kts
+++ b/apps/multiplatform/common/build.gradle.kts
@@ -102,7 +102,7 @@ kotlin {
implementation("com.github.Dansoftowner:jSystemThemeDetector:3.8")
implementation("com.sshtools:two-slices:0.9.0-SNAPSHOT")
implementation("org.slf4j:slf4j-simple:2.0.12")
- implementation("uk.co.caprica:vlcj:4.8.2")
+ implementation("uk.co.caprica:vlcj:4.8.3")
implementation("com.github.NanoHttpd.nanohttpd:nanohttpd:efb2ebf85a")
implementation("com.github.NanoHttpd.nanohttpd:nanohttpd-websocket:efb2ebf85a")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
diff --git a/apps/multiplatform/desktop/build.gradle.kts b/apps/multiplatform/desktop/build.gradle.kts
index 401c2938d5..e39ba48a0b 100644
--- a/apps/multiplatform/desktop/build.gradle.kts
+++ b/apps/multiplatform/desktop/build.gradle.kts
@@ -18,7 +18,6 @@ kotlin {
dependencies {
implementation(project(":common"))
implementation(compose.desktop.currentOs)
- implementation("net.java.dev.jna:jna:5.14.0")
}
}
val jvmTest by getting
diff --git a/docs/TRANSPARENCY.md b/docs/TRANSPARENCY.md
index 43fdd12ac5..bae7a4f781 100644
--- a/docs/TRANSPARENCY.md
+++ b/docs/TRANSPARENCY.md
@@ -17,8 +17,8 @@ This page will include any and all reports on requests for user data.
Our objective is to consistently ensure that no user data and absolute minimum of the metadata required for the network to function is available for disclosure by any infrastructure operators, under any circumstances.
**Helpful resources**:
-- [Privacy policy](../PRIVACY.md)
-- [Privacy and security: technical details and limitations](../README.md#privacy-and-security-technical-details-and-limitations)
+- [Privacy policy](/PRIVACY.md)
+- [Privacy and security: technical details and limitations](https://github.com/simplex-chat/simplex-chat/blob/stable/README.md#privacy-and-security-technical-details-and-limitations)
- Whitepaper:
- [Trust in servers](https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md#trust-in-servers)
- [Encryption Primitives Used](https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md#encryption-primitives-used)