diff --git a/apps/ios/Shared/Model/ImageUtils.swift b/apps/ios/Shared/Model/ImageUtils.swift index 90070e74d..41d741e7e 100644 --- a/apps/ios/Shared/Model/ImageUtils.swift +++ b/apps/ios/Shared/Model/ImageUtils.swift @@ -195,18 +195,18 @@ func moveTempFileFromURL(_ url: URL) -> CryptoFile? { } } -func generateNewFileName(_ prefix: String, _ ext: String) -> String { - uniqueCombine("\(prefix)_\(getTimestamp()).\(ext)") +func generateNewFileName(_ prefix: String, _ ext: String, fullPath: Bool = false) -> String { + uniqueCombine("\(prefix)_\(getTimestamp()).\(ext)", fullPath: fullPath) } -private func uniqueCombine(_ fileName: String) -> String { +private func uniqueCombine(_ fileName: String, fullPath: Bool = false) -> String { func tryCombine(_ fileName: String, _ n: Int) -> String { let ns = fileName as NSString let name = ns.deletingPathExtension let ext = ns.pathExtension let suffix = (n == 0) ? "" : "_\(n)" let f = "\(name)\(suffix).\(ext)" - return (FileManager.default.fileExists(atPath: getAppFilePath(f).path)) ? tryCombine(fileName, n + 1) : f + return (FileManager.default.fileExists(atPath: fullPath ? f : getAppFilePath(f).path)) ? tryCombine(fileName, n + 1) : f } return tryCombine(fileName, 0) } diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift index 057282177..4001edffb 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift @@ -384,10 +384,10 @@ struct ComposeView: View { } } .sheet(isPresented: $showMediaPicker) { - LibraryMediaListPicker(media: $chosenMedia, selectionLimit: 10) { itemsSelected in - showMediaPicker = false - if itemsSelected { - DispatchQueue.main.async { + LibraryMediaListPicker(addMedia: addMediaContent, selectionLimit: 10) { itemsSelected in + await MainActor.run { + showMediaPicker = false + if itemsSelected { composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: [])) } } @@ -488,6 +488,21 @@ struct ComposeView: View { } } + private func addMediaContent(_ content: UploadContent) async { + if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) { + var newMedia: [(String, UploadContent?)] = [] + if case var .mediaPreviews(media) = composeState.preview { + media.append((img, content)) + newMedia = media + } else { + newMedia = [(img, content)] + } + await MainActor.run { + composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: newMedia)) + } + } + } + private var maxFileSize: Int64 { getMaxFileSize(.xftp) } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift b/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift index 7e123c389..18cc3f4d8 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift @@ -103,8 +103,10 @@ struct GroupProfileView: View { } } .sheet(isPresented: $showImagePicker) { - LibraryImagePicker(image: $chosenImage) { - didSelectItem in showImagePicker = false + LibraryImagePicker(image: $chosenImage) { _ in + await MainActor.run { + showImagePicker = false + } } } .onChange(of: chosenImage) { image in diff --git a/apps/ios/Shared/Views/Helpers/ImagePicker.swift b/apps/ios/Shared/Views/Helpers/ImagePicker.swift index 1b44c2313..0e3f8082b 100644 --- a/apps/ios/Shared/Views/Helpers/ImagePicker.swift +++ b/apps/ios/Shared/Views/Helpers/ImagePicker.swift @@ -13,112 +13,122 @@ import SimpleXChat struct LibraryImagePicker: View { @Binding var image: UIImage? - var didFinishPicking: (_ didSelectItems: Bool) -> Void - @State var images: [UploadContent] = [] + var didFinishPicking: (_ didSelectImage: Bool) async -> Void + @State var mediaAdded = false var body: some View { - LibraryMediaListPicker(media: $images, selectionLimit: 1, didFinishPicking: didFinishPicking) - .onChange(of: images) { _ in - if let img = images.first { - image = img.uiImage - } - } + LibraryMediaListPicker(addMedia: addMedia, selectionLimit: 1, didFinishPicking: didFinishPicking) + } + + private func addMedia(_ content: UploadContent) async { + if mediaAdded { return } + await MainActor.run { + mediaAdded = true + image = content.uiImage + } } } struct LibraryMediaListPicker: UIViewControllerRepresentable { typealias UIViewControllerType = PHPickerViewController - @Binding var media: [UploadContent] + var addMedia: (_ content: UploadContent) async -> Void var selectionLimit: Int - var didFinishPicking: (_ didSelectItems: Bool) -> Void + var didFinishPicking: (_ didSelectItems: Bool) async -> Void class Coordinator: PHPickerViewControllerDelegate { let parent: LibraryMediaListPicker let dispatchQueue = DispatchQueue(label: "chat.simplex.app.LibraryMediaListPicker") - var media: [UploadContent] = [] - var mediaCount: Int = 0 init(_ parent: LibraryMediaListPicker) { self.parent = parent } func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { - parent.didFinishPicking(!results.isEmpty) - guard !results.isEmpty else { - return + Task { + await parent.didFinishPicking(!results.isEmpty) + if results.isEmpty { return } + for r in results { + await loadItem(r.itemProvider) + } } + } - parent.media = [] - media = [] - mediaCount = results.count - for result in results { - logger.log("LibraryMediaListPicker result") - let p = result.itemProvider - if p.hasItemConformingToTypeIdentifier(UTType.movie.identifier) { - p.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in - if let url = url { - let tempUrl = URL(fileURLWithPath: getTempFilesDirectory().path + "/" + generateNewFileName("video", url.pathExtension)) - if ((try? FileManager.default.copyItem(at: url, to: tempUrl)) != nil) { - ChatModel.shared.filesToDelete.insert(tempUrl) - self.loadVideo(url: tempUrl, error: error) + private func loadItem(_ p: NSItemProvider) async { + logger.debug("LibraryMediaListPicker result") + if p.hasItemConformingToTypeIdentifier(UTType.movie.identifier) { + if let video = await loadVideo(p) { + await self.parent.addMedia(video) + logger.debug("LibraryMediaListPicker: added video") + } + } else if p.hasItemConformingToTypeIdentifier(UTType.data.identifier) { + if let img = await loadImageData(p) { + await self.parent.addMedia(img) + logger.debug("LibraryMediaListPicker: added image") + } + } else if p.canLoadObject(ofClass: UIImage.self) { + if let img = await loadImage(p) { + await self.parent.addMedia(.simpleImage(image: img)) + logger.debug("LibraryMediaListPicker: added image") + } + } + } + + private func loadImageData(_ p: NSItemProvider) async -> UploadContent? { + await withCheckedContinuation { cont in + loadFileURL(p, type: UTType.data) { url in + if let url = url { + let img = UploadContent.loadFromURL(url: url) + cont.resume(returning: img) + } else { + cont.resume(returning: nil) + } + } + } + } + + private func loadImage(_ p: NSItemProvider) async -> UIImage? { + await withCheckedContinuation { cont in + p.loadObject(ofClass: UIImage.self) { obj, err in + if let err = err { + logger.error("LibraryMediaListPicker result image error: \(err.localizedDescription)") + cont.resume(returning: nil) + } else { + cont.resume(returning: obj as? UIImage) + } + } + } + } + + private func loadVideo(_ p: NSItemProvider) async -> UploadContent? { + await withCheckedContinuation { cont in + loadFileURL(p, type: UTType.movie) { url in + if let url = url { + let tempUrl = URL(fileURLWithPath: generateNewFileName(getTempFilesDirectory().path + "/" + "video", url.pathExtension, fullPath: true)) + do { +// logger.debug("LibraryMediaListPicker copyItem \(url) to \(tempUrl)") + try FileManager.default.copyItem(at: url, to: tempUrl) + DispatchQueue.main.async { + _ = ChatModel.shared.filesToDelete.insert(tempUrl) } + let video = UploadContent.loadVideoFromURL(url: tempUrl) + cont.resume(returning: video) + return + } catch let err { + logger.error("LibraryMediaListPicker copyItem error: \(err.localizedDescription)") } } - } else if p.hasItemConformingToTypeIdentifier(UTType.data.identifier) { - p.loadFileRepresentation(forTypeIdentifier: UTType.data.identifier) { url, error in - self.loadImage(object: url, error: error) - } - } else if p.canLoadObject(ofClass: UIImage.self) { - p.loadObject(ofClass: UIImage.self) { image, error in - DispatchQueue.main.async { - self.loadImage(object: image, error: error) - } - } + cont.resume(returning: nil) + } + } + } + + private func loadFileURL(_ p: NSItemProvider, type: UTType, completion: @escaping (URL?) -> Void) { + p.loadFileRepresentation(forTypeIdentifier: type.identifier) { url, err in + if let err = err { + logger.error("LibraryMediaListPicker loadFileURL error: \(err.localizedDescription)") + completion(nil) } else { - dispatchQueue.sync { self.mediaCount -= 1} - } - } - DispatchQueue.main.asyncAfter(deadline: .now() + 10) { - self.dispatchQueue.sync { - if self.parent.media.count == 0 { - logger.log("LibraryMediaListPicker: added \(self.media.count) images out of \(results.count)") - self.parent.media = self.media - } - } - } - } - - func loadImage(object: Any?, error: Error? = nil) { - if let error = error { - logger.error("LibraryMediaListPicker: couldn't load image with error: \(error.localizedDescription)") - } else if let image = object as? UIImage { - media.append(.simpleImage(image: image)) - logger.log("LibraryMediaListPicker: added image") - } else if let url = object as? URL, let image = UploadContent.loadFromURL(url: url) { - media.append(image) - } - dispatchQueue.sync { - self.mediaCount -= 1 - if self.mediaCount == 0 && self.parent.media.count == 0 { - logger.log("LibraryMediaListPicker: added all media") - self.parent.media = self.media - self.media = [] - } - } - } - - func loadVideo(url: URL?, error: Error? = nil) { - if let error = error { - logger.error("LibraryMediaListPicker: couldn't load video with error: \(error.localizedDescription)") - } else if let url = url as URL?, let video = UploadContent.loadVideoFromURL(url: url) { - media.append(video) - } - dispatchQueue.sync { - self.mediaCount -= 1 - if self.mediaCount == 0 && self.parent.media.count == 0 { - logger.log("LibraryMediaListPicker: added all media") - self.parent.media = self.media - self.media = [] + completion(url) } } } diff --git a/apps/ios/Shared/Views/NewChat/AddGroupView.swift b/apps/ios/Shared/Views/NewChat/AddGroupView.swift index 2d7f31c58..6c7919669 100644 --- a/apps/ios/Shared/Views/NewChat/AddGroupView.swift +++ b/apps/ios/Shared/Views/NewChat/AddGroupView.swift @@ -130,8 +130,10 @@ struct AddGroupView: View { } } .sheet(isPresented: $showImagePicker) { - LibraryImagePicker(image: $chosenImage) { - didSelectItem in showImagePicker = false + LibraryImagePicker(image: $chosenImage) { _ in + await MainActor.run { + showImagePicker = false + } } } .alert(isPresented: $showInvalidNameAlert) { diff --git a/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift b/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift index 8e8885b51..9da3bac00 100644 --- a/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift +++ b/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift @@ -51,9 +51,9 @@ struct AdvancedNetworkSettings: View { } .disabled(currentNetCfg == NetCfg.proxyDefaults) - timeoutSettingPicker("TCP connection timeout", selection: $netCfg.tcpConnectTimeout, values: [5_000000, 7_500000, 10_000000, 15_000000, 20_000000, 30_000000, 45_000000], label: secondsLabel) - timeoutSettingPicker("Protocol timeout", selection: $netCfg.tcpTimeout, values: [3_000000, 5_000000, 7_000000, 10_000000, 15_000000, 20_000000, 30_000000], label: secondsLabel) - timeoutSettingPicker("Protocol timeout per KB", selection: $netCfg.tcpTimeoutPerKb, values: [15_000, 30_000, 60_000, 90_000, 120_000], label: secondsLabel) + timeoutSettingPicker("TCP connection timeout", selection: $netCfg.tcpConnectTimeout, values: [7_500000, 10_000000, 15_000000, 20_000000, 30_000000, 45_000000], label: secondsLabel) + timeoutSettingPicker("Protocol timeout", selection: $netCfg.tcpTimeout, values: [5_000000, 7_000000, 10_000000, 15_000000, 20_000000, 30_000000], label: secondsLabel) + timeoutSettingPicker("Protocol timeout per KB", selection: $netCfg.tcpTimeoutPerKb, values: [15_000, 30_000, 45_000, 60_000, 90_000, 120_000], label: secondsLabel) timeoutSettingPicker("PING interval", selection: $netCfg.smpPingInterval, values: [120_000000, 300_000000, 600_000000, 1200_000000, 2400_000000, 3600_000000], label: secondsLabel) intSettingPicker("PING count", selection: $netCfg.smpPingCount, values: [1, 2, 3, 5, 8], label: "") Toggle("Enable TCP keep-alive", isOn: $enableKeepAlive) diff --git a/apps/ios/Shared/Views/UserSettings/UserProfile.swift b/apps/ios/Shared/Views/UserSettings/UserProfile.swift index b64ec21de..e5ec23178 100644 --- a/apps/ios/Shared/Views/UserSettings/UserProfile.swift +++ b/apps/ios/Shared/Views/UserSettings/UserProfile.swift @@ -120,8 +120,10 @@ struct UserProfile: View { } } .sheet(isPresented: $showImagePicker) { - LibraryImagePicker(image: $chosenImage) { - didSelectItem in showImagePicker = false + LibraryImagePicker(image: $chosenImage) { _ in + await MainActor.run { + showImagePicker = false + } } } .onChange(of: chosenImage) { image in diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 01696ad9e..42f76fd48 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -63,11 +63,6 @@ 5C7505A527B679EE00BE3227 /* NavLinkPlain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A427B679EE00BE3227 /* NavLinkPlain.swift */; }; 5C7505A827B6D34800BE3227 /* ChatInfoToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A727B6D34800BE3227 /* ChatInfoToolbar.swift */; }; 5C764E89279CBCB3000C6508 /* ChatModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C764E88279CBCB3000C6508 /* ChatModel.swift */; }; - 5C8EA13D2B25206A001DE5E4 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C8EA1382B25206A001DE5E4 /* libgmp.a */; }; - 5C8EA13E2B25206A001DE5E4 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C8EA1392B25206A001DE5E4 /* libgmpxx.a */; }; - 5C8EA13F2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C8EA13A2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX-ghc9.6.3.a */; }; - 5C8EA1402B25206A001DE5E4 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C8EA13B2B25206A001DE5E4 /* libffi.a */; }; - 5C8EA1412B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C8EA13C2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX.a */; }; 5C8F01CD27A6F0D8007D2C8D /* CodeScanner in Frameworks */ = {isa = PBXBuildFile; productRef = 5C8F01CC27A6F0D8007D2C8D /* CodeScanner */; }; 5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C93292E29239A170090FFF9 /* ProtocolServersView.swift */; }; 5C93293129239BED0090FFF9 /* ProtocolServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C93293029239BED0090FFF9 /* ProtocolServerView.swift */; }; @@ -121,6 +116,11 @@ 5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; }; 5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */; }; 5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; }; + 5CCD1A602B27927E001A4199 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD1A5B2B27927E001A4199 /* libgmpxx.a */; }; + 5CCD1A612B27927E001A4199 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD1A5C2B27927E001A4199 /* libgmp.a */; }; + 5CCD1A622B27927E001A4199 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD1A5D2B27927E001A4199 /* libffi.a */; }; + 5CCD1A632B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD1A5E2B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4.a */; }; + 5CCD1A642B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD1A5F2B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4-ghc8.10.7.a */; }; 5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; }; 5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; }; 5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD67B8D2B0E858A00C510B1 /* hs_init.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -338,11 +338,6 @@ 5C8B41C929AF41BC00888272 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 5C8B41CB29AF44CF00888272 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = "cs.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; }; 5C8B41CC29AF44CF00888272 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/InfoPlist.strings; sourceTree = ""; }; - 5C8EA1382B25206A001DE5E4 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; - 5C8EA1392B25206A001DE5E4 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - 5C8EA13A2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX-ghc9.6.3.a"; sourceTree = ""; }; - 5C8EA13B2B25206A001DE5E4 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 5C8EA13C2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX.a"; sourceTree = ""; }; 5C93292E29239A170090FFF9 /* ProtocolServersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolServersView.swift; sourceTree = ""; }; 5C93293029239BED0090FFF9 /* ProtocolServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolServerView.swift; sourceTree = ""; }; 5C93293E2928E0FD0090FFF9 /* AudioRecPlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecPlay.swift; sourceTree = ""; }; @@ -412,6 +407,11 @@ 5CC2C0FE2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = "ru.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; }; 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIRcvDecryptionError.swift; sourceTree = ""; }; 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavStackCompat.swift; sourceTree = ""; }; + 5CCD1A5B2B27927E001A4199 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 5CCD1A5C2B27927E001A4199 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + 5CCD1A5D2B27927E001A4199 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; + 5CCD1A5E2B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4.a"; sourceTree = ""; }; + 5CCD1A5F2B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4-ghc8.10.7.a"; sourceTree = ""; }; 5CCD403327A5F6DF00368C90 /* AddContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactView.swift; sourceTree = ""; }; 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanToConnectView.swift; sourceTree = ""; }; 5CD67B8D2B0E858A00C510B1 /* hs_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hs_init.h; sourceTree = ""; }; @@ -527,13 +527,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5C8EA13F2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX-ghc9.6.3.a in Frameworks */, - 5C8EA1402B25206A001DE5E4 /* libffi.a in Frameworks */, - 5C8EA13E2B25206A001DE5E4 /* libgmpxx.a in Frameworks */, + 5CCD1A602B27927E001A4199 /* libgmpxx.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5C8EA13D2B25206A001DE5E4 /* libgmp.a in Frameworks */, - 5C8EA1412B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX.a in Frameworks */, + 5CCD1A612B27927E001A4199 /* libgmp.a in Frameworks */, + 5CCD1A622B27927E001A4199 /* libffi.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, + 5CCD1A642B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4-ghc8.10.7.a in Frameworks */, + 5CCD1A632B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -595,11 +595,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5C8EA13B2B25206A001DE5E4 /* libffi.a */, - 5C8EA1382B25206A001DE5E4 /* libgmp.a */, - 5C8EA1392B25206A001DE5E4 /* libgmpxx.a */, - 5C8EA13A2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX-ghc9.6.3.a */, - 5C8EA13C2B25206A001DE5E4 /* libHSsimplex-chat-5.4.0.7-1uCDT6bmj7t4ctyD1vFaZX.a */, + 5CCD1A5D2B27927E001A4199 /* libffi.a */, + 5CCD1A5C2B27927E001A4199 /* libgmp.a */, + 5CCD1A5B2B27927E001A4199 /* libgmpxx.a */, + 5CCD1A5F2B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4-ghc8.10.7.a */, + 5CCD1A5E2B27927E001A4199 /* libHSsimplex-chat-5.4.0.7-EoJ0xKOyE47DlSpHXf0V4.a */, ); path = Libraries; sourceTree = ""; diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index 4d1446965..a199966ba 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -1207,9 +1207,9 @@ public struct NetCfg: Codable, Equatable { public static let defaults: NetCfg = NetCfg( socksProxy: nil, sessionMode: TransportSessionMode.user, - tcpConnectTimeout: 15_000_000, - tcpTimeout: 10_000_000, - tcpTimeoutPerKb: 30_000, + tcpConnectTimeout: 20_000_000, + tcpTimeout: 15_000_000, + tcpTimeoutPerKb: 45_000, tcpKeepAlive: KeepAliveOpts.defaults, smpPingInterval: 1200_000_000, smpPingCount: 3, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 6c01aff5d..ad897c60f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -2800,9 +2800,9 @@ data class NetCfg( hostMode = HostMode.OnionViaSocks, requiredHostMode = false, sessionMode = TransportSessionMode.User, - tcpConnectTimeout = 15_000_000, - tcpTimeout = 10_000_000, - tcpTimeoutPerKb = 30_000, + tcpConnectTimeout = 20_000_000, + tcpTimeout = 15_000_000, + tcpTimeoutPerKb = 45_000, tcpKeepAlive = KeepAliveOpts.defaults, smpPingInterval = 1200_000_000, smpPingCount = 3 diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt index 584917820..5fb8bfb03 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt @@ -154,20 +154,20 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) { SectionItemView { TimeoutSettingRow( stringResource(MR.strings.network_option_tcp_connection_timeout), networkTCPConnectTimeout, - listOf(5_000000, 7_500000, 10_000000, 15_000000, 20_000000, 30_000_000, 45_000_000), secondsLabel + listOf(7_500000, 10_000000, 15_000000, 20_000000, 30_000_000, 45_000_000), secondsLabel ) } SectionItemView { TimeoutSettingRow( stringResource(MR.strings.network_option_protocol_timeout), networkTCPTimeout, - listOf(3_000000, 5_000000, 7_000000, 10_000000, 15_000000, 20_000_000, 30_000_000), secondsLabel + listOf(5_000000, 7_000000, 10_000000, 15_000000, 20_000_000, 30_000_000), secondsLabel ) } SectionItemView { // can't be higher than 130ms to avoid overflow on 32bit systems TimeoutSettingRow( stringResource(MR.strings.network_option_protocol_timeout_per_kb), networkTCPTimeoutPerKb, - listOf(15_000, 30_000, 60_000, 90_000, 120_000), secondsLabel + listOf(15_000, 30_000, 45_000, 60_000, 90_000, 120_000), secondsLabel ) } SectionItemView { diff --git a/cabal.project b/cabal.project index b0dbaab3e..4c3b3bb70 100644 --- a/cabal.project +++ b/cabal.project @@ -11,7 +11,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 560dc553127851fa1fb201d0a9c80dcf1ad6e5dc + tag: f576260594b9898e26dbac1bcb4b5061fa4fa242 source-repository-package type: git diff --git a/docs/DOWNLOADS.md b/docs/DOWNLOADS.md index a43a69409..5362e4f2c 100644 --- a/docs/DOWNLOADS.md +++ b/docs/DOWNLOADS.md @@ -7,7 +7,7 @@ revision: 25.11.2023 | Updated 25.11.2023 | Languages: EN | # Download SimpleX apps -The latest stable version is v5.4.0. +The latest stable version is v5.4.1. You can get the latest beta releases from [GitHub](https://github.com/simplex-chat/simplex-chat/releases). @@ -21,24 +21,24 @@ You can get the latest beta releases from [GitHub](https://github.com/simplex-ch Using the same profile as on mobile device is not yet supported – you need to create a separate profile to use desktop apps. -**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-ubuntu-22_04-x86_64.deb). +**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-ubuntu-22_04-x86_64.deb). -**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). +**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). -**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-desktop-windows-x86_64.msi). +**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-windows-x86_64.msi). ## Mobile apps **iOS**: [App store](https://apps.apple.com/us/app/simplex-chat/id1605771084), [TestFlight](https://testflight.apple.com/join/DWuT2LQu). -**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-armv7a.apk). +**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-armv7a.apk). ## Terminal (console) app See [Using terminal app](/docs/CLI.md). -**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-ubuntu-22_04-x86-64). +**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-ubuntu-22_04-x86-64). -**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-macos-x86-64), aarch64 - [compile from source](./CLI.md#). +**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-macos-x86-64), aarch64 - [compile from source](./CLI.md#). -**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.0/simplex-chat-windows-x86-64). +**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-windows-x86-64). diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index f4953a57a..e4306124f 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."560dc553127851fa1fb201d0a9c80dcf1ad6e5dc" = "1xz3lw5dsh7gm136jzwmsbqjigsqsnjlbhg38mpc6lm586lg8f9x"; + "https://github.com/simplex-chat/simplexmq.git"."f576260594b9898e26dbac1bcb4b5061fa4fa242" = "0lmfncha6dxxg5ck9f4a155kyd6267k5m9w5mli121lir6ikvk7z"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/kazu-yamamoto/http2.git"."f5525b755ff2418e6e6ecc69e877363b0d0bcaeb" = "0fyx0047gvhm99ilp212mmz37j84cwrfnpmssib5dw363fyb88b6"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "0kiwhvml42g9anw4d2v0zd1fpc790pj9syg5x3ik4l97fnkbbwpp";