diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 08182e08c2..2e68bb148f 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -296,8 +296,10 @@ func getNetworkConfig() async throws -> NetCfg? { throw r } -func setNetworkConfig(cfg: NetCfg) async throws { - try await sendCommandOkResp(.apiSetNetworkConfig(networkConfig: cfg)) +func setNetworkConfig(_ cfg: NetCfg) throws { + let r = chatSendCmdSync(.apiSetNetworkConfig(networkConfig: cfg)) + if case .cmdOk = r { return } + throw r } func apiContactInfo(contactId: Int64) async throws -> ConnectionStats? { @@ -657,6 +659,7 @@ func initializeChat(start: Bool) throws { func startChat() throws { logger.debug("startChat") let m = ChatModel.shared + try setNetworkConfig(getNetCfg()) let justStarted = try apiStartChat() if justStarted { m.userAddress = try apiGetUserAddress() diff --git a/apps/ios/Shared/SimpleXApp.swift b/apps/ios/Shared/SimpleXApp.swift index 657ee382f0..949a10bda5 100644 --- a/apps/ios/Shared/SimpleXApp.swift +++ b/apps/ios/Shared/SimpleXApp.swift @@ -26,6 +26,7 @@ struct SimpleXApp: App { hs_init(0, nil) UserDefaults.standard.register(defaults: appDefaults) setGroupDefaults() + registerGroupDefaults() setDbContainer() BGManager.shared.register() NtfManager.shared.registerCategories() diff --git a/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift b/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift new file mode 100644 index 0000000000..5504870ded --- /dev/null +++ b/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift @@ -0,0 +1,164 @@ +// +// AdvancedNetworkSettings.swift +// SimpleX (iOS) +// +// Created by Evgeny on 02/08/2022. +// Copyright © 2022 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +private let secondsLabel = NSLocalizedString("sec", comment: "network option") + +enum NetworkSettingsAlert: Identifiable { + case update + case error(err: String) + + var id: String { + switch self { + case .update: return "update" + case let .error(err): return "error \(err)" + } + } +} + +struct AdvancedNetworkSettings: View { + @State private var netCfg = NetCfg.defaults + @State private var currentNetCfg = NetCfg.defaults + @State private var cfgLoaded = false + @State private var enableKeepAlive = true + @State private var keepAliveOpts = KeepAliveOpts.defaults + @State private var showSettingsAlert: NetworkSettingsAlert? + + var body: some View { + VStack { + List { + Section { + Button { + updateNetCfgView(NetCfg.defaults) + showSettingsAlert = .update + } label: { + Text("Reset to defaults") + } + .disabled(currentNetCfg == NetCfg.defaults) + + Button { + updateNetCfgView(NetCfg.proxyDefaults) + showSettingsAlert = .update + } label: { + Text("Set timeouts for proxy/VPN") + } + .disabled(currentNetCfg == NetCfg.proxyDefaults) + + timeoutSettingPicker("TCP connection timeout", selection: $netCfg.tcpConnectTimeout, values: [2_500000, 5_000000, 7_500000, 10_000000, 15_000000, 20_000000], label: secondsLabel) + timeoutSettingPicker("Protocol timeout", selection: $netCfg.tcpTimeout, values: [1_500000, 3_000000, 5_000000, 7_000000, 10_000000, 15_000000], label: secondsLabel) + timeoutSettingPicker("PING interval", selection: $netCfg.smpPingInterval, values: [120_000000, 300_000000, 600_000000, 1200_000000, 2400_000000], label: secondsLabel) + Toggle("Enable TCP keep-alive", isOn: $enableKeepAlive) + + if enableKeepAlive { + intSettingPicker("TCP_KEEPIDLE", selection: $keepAliveOpts.keepIdle, values: [15, 30, 60, 120, 180], label: secondsLabel) + intSettingPicker("TCP_KEEPINTVL", selection: $keepAliveOpts.keepIntvl, values: [5, 10, 15, 30, 60], label: secondsLabel) + intSettingPicker("TCP_KEEPCNT", selection: $keepAliveOpts.keepCnt, values: [1, 2, 4, 6, 8], label: "") + } else { + Group { + Text("TCP_KEEPIDLE") + Text("TCP_KEEPINTVL") + Text("TCP_KEEPCNT") + } + .foregroundColor(.secondary) + } + } header: { + Text("") + } footer: { + HStack { + Button { + updateNetCfgView(currentNetCfg) + } label: { + Label("Revert", systemImage: "arrow.counterclockwise").font(.callout) + } + + Spacer() + + Button { + showSettingsAlert = .update + } label: { + Label("Save", systemImage: "checkmark").font(.callout) + } + } + .disabled(netCfg == currentNetCfg) + } + } + } + .onChange(of: keepAliveOpts) { opts in + netCfg.tcpKeepAlive = keepAliveOpts + } + .onChange(of: enableKeepAlive) { on in + netCfg.tcpKeepAlive = on ? (currentNetCfg.tcpKeepAlive ?? KeepAliveOpts.defaults) : nil + } + .onAppear { + if cfgLoaded { return } + cfgLoaded = true + currentNetCfg = getNetCfg() + updateNetCfgView(currentNetCfg) + } + .alert(item: $showSettingsAlert) { a in + switch a { + case .update: + return Alert( + title: Text("Update network settings?"), + message: Text("Updating settings will re-connect the client to all servers."), + primaryButton: .default(Text("Ok")) { + saveNetCfg() + }, + secondaryButton: .cancel() + ) + case let .error(err): + return Alert( + title: Text("Error updating settings"), + message: Text(err) + ) + } + } + } + + private func updateNetCfgView(_ cfg: NetCfg) { + netCfg = cfg + enableKeepAlive = currentNetCfg.enableKeepAlive + keepAliveOpts = currentNetCfg.tcpKeepAlive ?? KeepAliveOpts.defaults + } + + private func saveNetCfg() { + do { + try setNetworkConfig(netCfg) + currentNetCfg = netCfg + setNetCfg(netCfg) + } catch let error { + let err = responseError(error) + showSettingsAlert = .error(err: err) + logger.error("\(err)") + } + } + + private func intSettingPicker(_ title: LocalizedStringKey, selection: Binding, values: [Int], label: String) -> some View { + Picker(title, selection: selection) { + ForEach(values, id: \.self) { value in + Text("\(value) \(label)") + } + } + } + + private func timeoutSettingPicker(_ title: LocalizedStringKey, selection: Binding, values: [Int], label: String) -> some View { + Picker(title, selection: selection) { + ForEach(values, id: \.self) { value in + Text("\(String(format: "%g", (Double(value) / 1000000))) \(secondsLabel)") + } + } + } +} + +struct AdvancedNetworkSettings_Previews: PreviewProvider { + static var previews: some View { + AdvancedNetworkSettings() + } +} diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift new file mode 100644 index 0000000000..8969dd95f4 --- /dev/null +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift @@ -0,0 +1,43 @@ +// +// NetworkServersView.swift +// SimpleX (iOS) +// +// Created by Evgeny on 02/08/2022. +// Copyright © 2022 SimpleX Chat. All rights reserved. +// + +import SwiftUI + +struct NetworkAndServers: View { + @AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false + + var body: some View { + VStack { + List { + Section("") { + NavigationLink { + SMPServers() + .navigationTitle("Your SMP servers") + } label: { + settingsRow("server.rack") { Text("SMP servers") } + } + + if developerTools { + NavigationLink { + AdvancedNetworkSettings() + .navigationTitle("Network settings") + } label: { + settingsRow("app.connected.to.app.below.fill") { Text("Advanced network settings") } + } + } + } + } + } + } +} + +struct NetworkServersView_Previews: PreviewProvider { + static var previews: some View { + NetworkAndServers() + } +} diff --git a/apps/ios/Shared/Views/UserSettings/SettingsView.swift b/apps/ios/Shared/Views/UserSettings/SettingsView.swift index ef96939799..fcb805c774 100644 --- a/apps/ios/Shared/Views/UserSettings/SettingsView.swift +++ b/apps/ios/Shared/Views/UserSettings/SettingsView.swift @@ -121,10 +121,10 @@ struct SettingsView: View { Toggle("Show pending connections", isOn: $pendingConnections) } NavigationLink { - SMPServers() - .navigationTitle("Your SMP servers") + NetworkAndServers() + .navigationTitle("Network & servers") } label: { - settingsRow("server.rack") { Text("SMP servers") } + settingsRow("externaldrive.connected.to.line.below") { Text("Network & servers") } } } .disabled(chatModel.chatRunning != true) diff --git a/apps/ios/SimpleX NSE/NotificationService.swift b/apps/ios/SimpleX NSE/NotificationService.swift index 504a8e42b9..4733f699ee 100644 --- a/apps/ios/SimpleX NSE/NotificationService.swift +++ b/apps/ios/SimpleX NSE/NotificationService.swift @@ -150,6 +150,7 @@ func startChat() -> User? { if let user = apiGetActiveUser() { logger.debug("active user \(String(describing: user))") do { + try setNetworkConfig(getNetCfg()) let justStarted = try apiStartChat() if justStarted { try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path) @@ -257,6 +258,12 @@ func apiReceiveFile(fileId: Int64) -> AChatItem? { return nil } +func setNetworkConfig(_ cfg: NetCfg) throws { + let r = sendSimpleXCmd(.apiSetNetworkConfig(networkConfig: cfg)) + if case .cmdOk = r { return } + throw r +} + struct NtfMessages { var connEntity: ConnectionEntity? var msgTs: Date? diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index c6ea25938f..b397267682 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -56,6 +56,8 @@ 5C9C2DA228929B6900CC63B1 /* libHSsimplex-chat-3.1.0-FNUbBjLYHjnDjt6ldpTolw-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C9C2D9D28929B6900CC63B1 /* libHSsimplex-chat-3.1.0-FNUbBjLYHjnDjt6ldpTolw-ghc8.10.7.a */; }; 5C9C2DA328929B6900CC63B1 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C9C2D9E28929B6900CC63B1 /* libgmpxx.a */; }; 5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9C2DA42894777E00CC63B1 /* GroupProfileView.swift */; }; + 5C9C2DA7289957AE00CC63B1 /* AdvancedNetworkSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9C2DA6289957AE00CC63B1 /* AdvancedNetworkSettings.swift */; }; + 5C9C2DA92899DA6F00CC63B1 /* NetworkAndServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9C2DA82899DA6F00CC63B1 /* NetworkAndServers.swift */; }; 5C9D13A3282187BB00AB8B43 /* WebRTC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9D13A2282187BB00AB8B43 /* WebRTC.swift */; }; 5C9FD96E27A5D6ED0075386C /* SendMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9FD96D27A5D6ED0075386C /* SendMessageView.swift */; }; 5CA059DC279559F40002BEB4 /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CA059DB279559F40002BEB4 /* Tests_iOS.swift */; }; @@ -236,6 +238,8 @@ 5C9C2D9D28929B6900CC63B1 /* libHSsimplex-chat-3.1.0-FNUbBjLYHjnDjt6ldpTolw-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-3.1.0-FNUbBjLYHjnDjt6ldpTolw-ghc8.10.7.a"; sourceTree = ""; }; 5C9C2D9E28929B6900CC63B1 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; 5C9C2DA42894777E00CC63B1 /* GroupProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupProfileView.swift; sourceTree = ""; }; + 5C9C2DA6289957AE00CC63B1 /* AdvancedNetworkSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedNetworkSettings.swift; sourceTree = ""; }; + 5C9C2DA82899DA6F00CC63B1 /* NetworkAndServers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkAndServers.swift; sourceTree = ""; }; 5C9D13A2282187BB00AB8B43 /* WebRTC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRTC.swift; sourceTree = ""; }; 5C9FD96A27A56D4D0075386C /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; 5C9FD96D27A5D6ED0075386C /* SendMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMessageView.swift; sourceTree = ""; }; @@ -531,6 +535,8 @@ 5CB924D327A853F100ACCCDD /* SettingsButton.swift */, 5CB924D627A8563F00ACCCDD /* SettingsView.swift */, 5CB346E62868D76D001FD2EF /* NotificationsView.swift */, + 5C9C2DA6289957AE00CC63B1 /* AdvancedNetworkSettings.swift */, + 5C9C2DA82899DA6F00CC63B1 /* NetworkAndServers.swift */, 5C05DF522840AA1D00C683F9 /* CallSettings.swift */, 5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */, 5CB924E327A8683A00ACCCDD /* UserAddress.swift */, @@ -886,6 +892,7 @@ 5C55A921283CCCB700C4E99E /* IncomingCallView.swift in Sources */, 6454036F2822A9750090DDFF /* ComposeFileView.swift in Sources */, 5C5F2B6D27EBC3FE006A9D5F /* ImagePicker.swift in Sources */, + 5C9C2DA92899DA6F00CC63B1 /* NetworkAndServers.swift in Sources */, 5C577F7D27C83AA10006112D /* MarkdownHelp.swift in Sources */, 5CA059EB279559F40002BEB4 /* SimpleXApp.swift in Sources */, 5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */, @@ -912,6 +919,7 @@ 5C3F1D5A2844B4DE00EC8A82 /* ExperimentalFeaturesView.swift in Sources */, 5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */, 64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */, + 5C9C2DA7289957AE00CC63B1 /* AdvancedNetworkSettings.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index d75701e924..b0c6f9c51b 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -500,9 +500,38 @@ public struct ArchiveConfig: Encodable { } } -public struct NetCfg: Codable { - var socksProxy: String? = nil - var tcpTimeout: Int +public struct NetCfg: Codable, Equatable { + public var socksProxy: String? = nil + public var tcpConnectTimeout: Int // microseconds + public var tcpTimeout: Int // microseconds + public var tcpKeepAlive: KeepAliveOpts? + public var smpPingInterval: Int // microseconds + + public static let defaults: NetCfg = NetCfg( + socksProxy: nil, + tcpConnectTimeout: 7_500_000, + tcpTimeout: 5_000_000, + tcpKeepAlive: KeepAliveOpts.defaults, + smpPingInterval: 600_000_000 + ) + + public static let proxyDefaults: NetCfg = NetCfg( + socksProxy: nil, + tcpConnectTimeout: 15_000_000, + tcpTimeout: 10_000_000, + tcpKeepAlive: KeepAliveOpts.defaults, + smpPingInterval: 600_000_000 + ) + + public var enableKeepAlive: Bool { tcpKeepAlive != nil } +} + +public struct KeepAliveOpts: Codable, Equatable { + public var keepIdle: Int // seconds + public var keepIntvl: Int // seconds + public var keepCnt: Int // times + + public static let defaults: KeepAliveOpts = KeepAliveOpts(keepIdle: 30, keepIntvl: 15, keepCnt: 4) } public struct ConnectionStats: Codable { diff --git a/apps/ios/SimpleXChat/AppGroup.swift b/apps/ios/SimpleXChat/AppGroup.swift index 7e0138acc7..b63db62154 100644 --- a/apps/ios/SimpleXChat/AppGroup.swift +++ b/apps/ios/SimpleXChat/AppGroup.swift @@ -15,11 +15,30 @@ public let GROUP_DEFAULT_CHAT_LAST_START = "chatLastStart" let GROUP_DEFAULT_NTF_PREVIEW_MODE = "ntfPreviewMode" let GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES = "privacyAcceptImages" let GROUP_DEFAULT_NTF_BADGE_COUNT = "ntgBadgeCount" +let GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT = "networkTCPConnectTimeout" +let GROUP_DEFAULT_NETWORK_TCP_TIMEOUT = "networkTCPTimeout" +let GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL = "networkSMPPingInterval" +let GROUP_DEFAULT_NETWORK_ENABLE_KEEP_ALIVE = "networkEnableKeepAlive" +let GROUP_DEFAULT_NETWORK_TCP_KEEP_IDLE = "networkTCPKeepIdle" +let GROUP_DEFAULT_NETWORK_TCP_KEEP_INTVL = "networkTCPKeepIntvl" +let GROUP_DEFAULT_NETWORK_TCP_KEEP_CNT = "networkTCPKeepCnt" let APP_GROUP_NAME = "group.chat.simplex.app" public let groupDefaults = UserDefaults(suiteName: APP_GROUP_NAME)! +public func registerGroupDefaults() { + groupDefaults.register(defaults: [ + GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT: NetCfg.defaults.tcpConnectTimeout, + GROUP_DEFAULT_NETWORK_TCP_TIMEOUT: NetCfg.defaults.tcpTimeout, + GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL: NetCfg.defaults.smpPingInterval, + GROUP_DEFAULT_NETWORK_ENABLE_KEEP_ALIVE: NetCfg.defaults.enableKeepAlive, + GROUP_DEFAULT_NETWORK_TCP_KEEP_IDLE: KeepAliveOpts.defaults.keepIdle, + GROUP_DEFAULT_NETWORK_TCP_KEEP_INTVL: KeepAliveOpts.defaults.keepIntvl, + GROUP_DEFAULT_NETWORK_TCP_KEEP_CNT: KeepAliveOpts.defaults.keepCnt + ]) +} + public enum AppState: String { case active case bgRefresh @@ -136,3 +155,40 @@ public class Default { defaults.synchronize() } } + +public func getNetCfg() -> NetCfg { + let tcpConnectTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT) + let tcpTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT) + let smpPingInterval = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL) + let enableKeepAlive = groupDefaults.bool(forKey: GROUP_DEFAULT_NETWORK_ENABLE_KEEP_ALIVE) + var tcpKeepAlive: KeepAliveOpts? + if enableKeepAlive { + let keepIdle = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_KEEP_IDLE) + let keepIntvl = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_KEEP_INTVL) + let keepCnt = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_KEEP_CNT) + tcpKeepAlive = KeepAliveOpts(keepIdle: keepIdle, keepIntvl: keepIntvl, keepCnt: keepCnt) + } else { + tcpKeepAlive = nil + } + return NetCfg( + tcpConnectTimeout: tcpConnectTimeout, + tcpTimeout: tcpTimeout, + tcpKeepAlive: tcpKeepAlive, + smpPingInterval: smpPingInterval + ) +} + +public func setNetCfg(_ cfg: NetCfg) { + groupDefaults.set(cfg.tcpConnectTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT) + groupDefaults.set(cfg.tcpTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT) + groupDefaults.set(cfg.smpPingInterval, forKey: GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL) + if let tcpKeepAlive = cfg.tcpKeepAlive { + groupDefaults.set(true, forKey: GROUP_DEFAULT_NETWORK_ENABLE_KEEP_ALIVE) + groupDefaults.set(tcpKeepAlive.keepIdle, forKey: GROUP_DEFAULT_NETWORK_TCP_KEEP_IDLE) + groupDefaults.set(tcpKeepAlive.keepIntvl, forKey: GROUP_DEFAULT_NETWORK_TCP_KEEP_INTVL) + groupDefaults.set(tcpKeepAlive.keepCnt, forKey: GROUP_DEFAULT_NETWORK_TCP_KEEP_CNT) + } else { + groupDefaults.set(false, forKey: GROUP_DEFAULT_NETWORK_ENABLE_KEEP_ALIVE) + } + groupDefaults.synchronize() +} diff --git a/cabal.project b/cabal.project index 832c98f037..1b7635644a 100644 --- a/cabal.project +++ b/cabal.project @@ -5,7 +5,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: e9db0a1162a0858b0acb1880a6ef261242adc356 + tag: 7d99c4b35cf2dc531219bc83146b714c9bae429c source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 9975570217..64d384c741 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."e9db0a1162a0858b0acb1880a6ef261242adc356" = "1klakvm93qsgwbg00xbq6s32sqcqww8x4ln4m8bjss0mracgrnki"; + "https://github.com/simplex-chat/simplexmq.git"."7d99c4b35cf2dc531219bc83146b714c9bae429c" = "037a0p7cdi4lrsbh21b4gldwdcj1sk8wz4wjsph6bnv2jyid11gk"; "https://github.com/simplex-chat/aeson.git"."3eb66f9a68f103b5f1489382aad89f5712a64db7" = "0kilkx59fl6c3qy3kjczqvm8c3f4n3p0bdk9biyflf51ljnzp4yp"; "https://github.com/simplex-chat/haskell-terminal.git"."f708b00009b54890172068f168bf98508ffcd495" = "0zmq7lmfsk8m340g47g5963yba7i88n4afa6z93sg9px5jv1mijj"; "https://github.com/zw3rk/android-support.git"."3c3a5ab0b8b137a072c98d3d0937cbdc96918ddb" = "1r6jyxbim3dsvrmakqfyxbd6ms6miaghpbwyl0sr6dzwpgaprz97"; diff --git a/stack.yaml b/stack.yaml index 59a9e97775..56b03e35fc 100644 --- a/stack.yaml +++ b/stack.yaml @@ -49,7 +49,7 @@ extra-deps: # - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561 # - ../simplexmq - github: simplex-chat/simplexmq - commit: e9db0a1162a0858b0acb1880a6ef261242adc356 + commit: 7d99c4b35cf2dc531219bc83146b714c9bae429c # - terminal-0.2.0.0@sha256:de6770ecaae3197c66ac1f0db5a80cf5a5b1d3b64a66a05b50f442de5ad39570,2977 - github: simplex-chat/aeson commit: 3eb66f9a68f103b5f1489382aad89f5712a64db7