diff --git a/apps/ios/Shared/ContentView.swift b/apps/ios/Shared/ContentView.swift index b9e7fb066d..d791153197 100644 --- a/apps/ios/Shared/ContentView.swift +++ b/apps/ios/Shared/ContentView.swift @@ -18,6 +18,7 @@ struct ContentView: View { .onAppear { do { try apiStartChat() + try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path) chatModel.userSMPServers = try getUserSMPServers() chatModel.chats = try apiGetChats() } catch { diff --git a/apps/ios/Shared/FileUtils.swift b/apps/ios/Shared/FileUtils.swift new file mode 100644 index 0000000000..7dd82828e8 --- /dev/null +++ b/apps/ios/Shared/FileUtils.swift @@ -0,0 +1,17 @@ +// +// FileUtils.swift +// SimpleX (iOS) +// +// Created by JRoberts on 15.04.2022. +// Copyright © 2022 SimpleX Chat. All rights reserved. +// + +import Foundation + +func getDocumentsDirectory() -> URL { + return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! +} + +func getAppFilesDirectory() -> URL { + return getDocumentsDirectory().appendingPathComponent("app_files", isDirectory: true) +} diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 150b33d930..185644b4d3 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -19,6 +19,7 @@ enum ChatCommand { case showActiveUser case createActiveUser(profile: Profile) case startChat + case setFilesFolder(filesFolder: String) case apiGetChats case apiGetChat(type: ChatType, id: Int64) case apiSendMessage(type: ChatType, id: Int64, file: String?, quotedItemId: Int64?, msg: MsgContent) @@ -45,6 +46,7 @@ enum ChatCommand { case .showActiveUser: return "/u" case let .createActiveUser(profile): return "/u \(profile.displayName) \(profile.fullName)" case .startChat: return "/_start" + case let .setFilesFolder(filesFolder): return "/_files_folder \(filesFolder)" case .apiGetChats: return "/_get chats" case let .apiGetChat(type, id): return "/_get chat \(ref(type, id)) count=100" case let .apiSendMessage(type, id, file, quotedItemId, mc): @@ -80,6 +82,7 @@ enum ChatCommand { case .showActiveUser: return "showActiveUser" case .createActiveUser: return "createActiveUser" case .startChat: return "startChat" + case .setFilesFolder: return "setFilesFolder" case .apiGetChats: return "apiGetChats" case .apiGetChat: return "apiGetChat" case .apiSendMessage: return "apiSendMessage" @@ -106,7 +109,7 @@ enum ChatCommand { func ref(_ type: ChatType, _ id: Int64) -> String { "\(type.rawValue)\(id)" } - + func smpServersStr(smpServers: [String]) -> String { smpServers.isEmpty ? "default" : smpServers.joined(separator: ",") } @@ -200,7 +203,7 @@ enum ChatResponse: Decodable, Error { } } } - + var details: String { get { switch self { @@ -379,6 +382,12 @@ func apiStartChat() throws { throw r } +func apiSetFilesFolder(filesFolder: String) throws { + let r = chatSendCmdSync(.setFilesFolder(filesFolder: filesFolder)) + if case .cmdOk = r { return } + throw r +} + func apiGetChats() throws -> [Chat] { let r = chatSendCmdSync(.apiGetChats) if case let .apiChats(chats) = r { return chats.map { Chat.init($0) } } @@ -741,7 +750,7 @@ private func chatResponse(_ cjson: UnsafeMutablePointer) -> ChatResponse } catch { logger.error("chatResponse jsonDecoder.decode error: \(error.localizedDescription)") } - + var type: String? var json: String? if let j = try? JSONSerialization.jsonObject(with: d) as? NSDictionary { @@ -763,7 +772,7 @@ func prettyJSON(_ obj: NSDictionary) -> String? { private func getChatCtrl() -> chat_ctrl { if let controller = chatController { return controller } - let dataDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.path + "/mobile_v1" + let dataDir = getDocumentsDirectory().path + "/mobile_v1" var cstr = dataDir.cString(using: .utf8)! logger.debug("getChatCtrl: chat_init") ChatModel.shared.terminalItems.append(.cmd(.now, .string("chat_init"))) diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 6957ad5f35..cd34f49f48 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -261,11 +261,11 @@ struct ChatView: View { let dataResized = Data(base64Encoded: dropImagePrefix(imageResized)), let jpegData = UIImage(data: dataResized)?.jpegData(compressionQuality: 1) { let millisecondsSince1970 = Int64((Date().timeIntervalSince1970 * 1000.0).rounded()) - let imageName = "image_\(millisecondsSince1970).jpg" - let filename = getDocumentsDirectory().appendingPathComponent(imageName) + let fileToSave = "image_\(millisecondsSince1970).jpg" + let filePath = getAppFilesDirectory().appendingPathComponent(fileToSave) do { - try jpegData.write(to: filename) - return filename.path + try jpegData.write(to: filePath) + return fileToSave } catch { logger.error("ChatView.saveImage error: \(error.localizedDescription)") return nil @@ -273,13 +273,6 @@ struct ChatView: View { } return nil } - - func getDocumentsDirectory() -> URL { - let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! - return path -// let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) -// return paths[0] - } func deleteMessage(_ mode: CIDeleteMode) { logger.debug("ChatView deleteMessage") diff --git a/apps/ios/Shared/Views/Helpers/ChatItemImageView.swift b/apps/ios/Shared/Views/Helpers/ChatItemImageView.swift index 4c2866a3aa..a480de1f3f 100644 --- a/apps/ios/Shared/Views/Helpers/ChatItemImageView.swift +++ b/apps/ios/Shared/Views/Helpers/ChatItemImageView.swift @@ -16,7 +16,8 @@ struct ChatItemImageView: View { var body: some View { VStack(alignment: .center, spacing: 6) { if let file = file, - let filePath = file.filePath, + let savedFile = file.filePath, + let filePath = getAppFilesDirectory().path + "/" + savedFile, file.stored, // TODO more advanced approach would be to send progressive jpeg and only check for filepath let uiImage = UIImage(contentsOfFile: filePath) { Image(uiImage: uiImage) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index f065e92a44..714ec35d54 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -119,6 +119,7 @@ 64AA1C6A27EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; }; 64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; }; 64AA1C6D27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; }; + 64DAE1512809D9F5000DA960 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64DAE1502809D9F5000DA960 /* FileUtils.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -207,6 +208,7 @@ 649BCDA12805D6EF00C3A862 /* ChatItemImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemImageView.swift; sourceTree = ""; }; 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextItemView.swift; sourceTree = ""; }; 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedItemView.swift; sourceTree = ""; }; + 64DAE1502809D9F5000DA960 /* FileUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -231,8 +233,6 @@ files = ( 5C764E85279C748C000C6508 /* libz.tbd in Frameworks */, 5C764E84279C748C000C6508 /* libiconv.tbd in Frameworks */, - 5C411599280048E90054D6CB /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a in Frameworks */, - 5C41159B280048E90054D6CB /* libffi.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -350,6 +350,7 @@ children = ( 5CA059C3279559F40002BEB4 /* SimpleXApp.swift */, 5CA059C4279559F40002BEB4 /* ContentView.swift */, + 64DAE1502809D9F5000DA960 /* FileUtils.swift */, 5C764E87279CBC8E000C6508 /* Model */, 5C2E260D27A30E2400F70299 /* Views */, 5CA059C5279559F40002BEB4 /* Assets.xcassets */, @@ -661,6 +662,7 @@ 649BCDA22805D6EF00C3A862 /* ChatItemImageView.swift in Sources */, 5CCD403A27A5F9BE00368C90 /* CreateGroupView.swift in Sources */, 5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */, + 64DAE1512809D9F5000DA960 /* FileUtils.swift in Sources */, 5C764E89279CBCB3000C6508 /* ChatModel.swift in Sources */, 5C971E1D27AEBEF600C8A3CE /* ChatInfoView.swift in Sources */, 5CC1C99527A6CF7F000D9FF6 /* ShareSheet.swift in Sources */,