From 9d84ddc214a142b8a79dcd349999b9e2430d9b1d Mon Sep 17 00:00:00 2001 From: JRoberts <8711996+jr-simplex@users.noreply.github.com> Date: Mon, 11 Apr 2022 14:30:07 +0400 Subject: [PATCH] ios api --- apps/ios/Shared/Model/ChatModel.swift | 42 +++++++++++++----- apps/ios/Shared/Model/SimpleXAPI.swift | 22 +++++----- apps/ios/Shared/Views/Chat/ChatView.swift | 1 + apps/ios/SimpleX.xcodeproj/project.pbxproj | 50 +++++++++------------- 4 files changed, 62 insertions(+), 53 deletions(-) diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index b70aecf771..9141b77834 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -579,6 +579,7 @@ struct ChatItem: Identifiable, Decodable { var content: CIContent var formattedText: [FormattedText]? var quotedItem: CIQuote? + var file: CIFile? var id: Int64 { get { meta.itemId } } @@ -615,12 +616,13 @@ struct ChatItem: Identifiable, Decodable { } } - static func getSample (_ id: Int64, _ dir: CIDirection, _ ts: Date, _ text: String, _ status: CIStatus = .sndNew, quotedItem: CIQuote? = nil, _ itemDeleted: Bool = false, _ itemEdited: Bool = false, _ editable: Bool = true) -> ChatItem { + static func getSample (_ id: Int64, _ dir: CIDirection, _ ts: Date, _ text: String, _ status: CIStatus = .sndNew, quotedItem: CIQuote? = nil, file: CIFile? = nil, _ itemDeleted: Bool = false, _ itemEdited: Bool = false, _ editable: Bool = true) -> ChatItem { ChatItem( chatDir: dir, meta: CIMeta.getSample(id, ts, text, status, itemDeleted, itemEdited, editable), content: .sndMsgContent(msgContent: .text(text)), - quotedItem: quotedItem + quotedItem: quotedItem, + file: file ) } @@ -629,7 +631,8 @@ struct ChatItem: Identifiable, Decodable { chatDir: dir, meta: CIMeta.getSample(id, ts, text, status, false, false, false), content: .rcvDeleted(deleteMode: .cidmBroadcast), - quotedItem: nil + quotedItem: nil, + file: nil ) } } @@ -711,8 +714,6 @@ enum CIContent: Decodable, ItemContent { case rcvMsgContent(msgContent: MsgContent) case sndDeleted(deleteMode: CIDeleteMode) case rcvDeleted(deleteMode: CIDeleteMode) - case sndFileInvitation(fileId: Int64, filePath: String) - case rcvFileInvitation(rcvFileTransfer: RcvFileTransfer) var text: String { get { @@ -721,8 +722,6 @@ enum CIContent: Decodable, ItemContent { case let .rcvMsgContent(mc): return mc.text case .sndDeleted: return "deleted" case .rcvDeleted: return "deleted" - case .sndFileInvitation: return "sending files is not supported yet" - case .rcvFileInvitation: return "receiving files is not supported yet" } } } @@ -737,10 +736,6 @@ enum CIContent: Decodable, ItemContent { } } -struct RcvFileTransfer: Decodable { - -} - struct CIQuote: Decodable, ItemContent { var chatDir: CIDirection? var itemId: Int64? @@ -768,9 +763,31 @@ struct CIQuote: Decodable, ItemContent { } } +struct CIFile: Decodable { + var fileId: Int64 + var fileName: String + var fileSize: Int64 + var filePath: String? + var fileStatus: CIFileStatus + + static func getSample(_ fileId: Int64, _ fileName: String, _ fileSize: Int64, filePath: String?, fileStatus: CIFileStatus = .sndStored) -> CIFile { + CIFile(fileId: fileId, fileName: fileName, fileSize: fileSize, filePath: filePath, fileStatus: fileStatus) + } +} + +enum CIFileStatus: Decodable { + case sndStored + case sndCancelled + case rcvInvitation + case rcvTransfer + case rcvComplete + case rcvCancelled +} + enum MsgContent { case text(String) case link(text: String, preview: LinkPreview) + case image(text: String, image: String) // TODO include original JSON, possibly using https://github.com/zoul/generic-json-swift case unknown(type: String, text: String) @@ -779,6 +796,7 @@ enum MsgContent { switch self { case let .text(text): return text case let .link(text, _): return text + case let .image(text, _): return text case let .unknown(_, text): return text } } @@ -790,6 +808,8 @@ enum MsgContent { case let .text(text): return "text \(text)" case let .link(text: text, preview: preview): return "json {\"type\":\"link\",\"text\":\(encodeJSON(text)),\"preview\":\(encodeJSON(preview))}" + case let .image(text: text, image: image): + return "json {\"type\":\"image\",\"text\":\(encodeJSON(text)),\"image\":\(encodeJSON(image))}" default: return "" } } diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index f87a178dc1..150b33d930 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -21,8 +21,7 @@ enum ChatCommand { case startChat case apiGetChats case apiGetChat(type: ChatType, id: Int64) - case apiSendMessage(type: ChatType, id: Int64, msg: MsgContent) - case apiSendMessageQuote(type: ChatType, id: Int64, itemId: Int64, msg: MsgContent) + case apiSendMessage(type: ChatType, id: Int64, file: String?, quotedItemId: Int64?, msg: MsgContent) case apiUpdateChatItem(type: ChatType, id: Int64, itemId: Int64, msg: MsgContent) case apiDeleteChatItem(type: ChatType, id: Int64, itemId: Int64, mode: CIDeleteMode) case getUserSMPServers @@ -48,8 +47,13 @@ enum ChatCommand { case .startChat: return "/_start" case .apiGetChats: return "/_get chats" case let .apiGetChat(type, id): return "/_get chat \(ref(type, id)) count=100" - case let .apiSendMessage(type, id, mc): return "/_send \(ref(type, id)) \(mc.cmdString)" - case let .apiSendMessageQuote(type, id, itemId, mc): return "/_send_quote \(ref(type, id)) \(itemId) \(mc.cmdString)" + case let .apiSendMessage(type, id, file, quotedItemId, mc): + switch (file, quotedItemId) { + case (nil, nil): return "/_send \(ref(type, id)) \(mc.cmdString)" + case let (.some(file), nil): return "/_send \(ref(type, id)) file \(file) \(mc.cmdString)" + case let (nil, .some(quotedItemId)): return "/_send \(ref(type, id)) quoted \(quotedItemId) \(mc.cmdString)" + case let (.some(file), .some(quotedItemId)): return "/_send \(ref(type, id)) file \(file) quoted \(quotedItemId) \(mc.cmdString)" + } case let .apiUpdateChatItem(type, id, itemId, mc): return "/_update item \(ref(type, id)) \(itemId) \(mc.cmdString)" case let .apiDeleteChatItem(type, id, itemId, mode): return "/_delete item \(ref(type, id)) \(itemId) \(mode.rawValue)" case .getUserSMPServers: return "/smp_servers" @@ -79,7 +83,6 @@ enum ChatCommand { case .apiGetChats: return "apiGetChats" case .apiGetChat: return "apiGetChat" case .apiSendMessage: return "apiSendMessage" - case .apiSendMessageQuote: return "apiSendMessageQuote" case .apiUpdateChatItem: return "apiUpdateChatItem" case .apiDeleteChatItem: return "apiDeleteChatItem" case .getUserSMPServers: return "getUserSMPServers" @@ -388,14 +391,9 @@ func apiGetChat(type: ChatType, id: Int64) throws -> Chat { throw r } -func apiSendMessage(type: ChatType, id: Int64, quotedItemId: Int64?, msg: MsgContent) async throws -> ChatItem { +func apiSendMessage(type: ChatType, id: Int64, file: String?, quotedItemId: Int64?, msg: MsgContent) async throws -> ChatItem { let chatModel = ChatModel.shared - let cmd: ChatCommand - if let itemId = quotedItemId { - cmd = .apiSendMessageQuote(type: type, id: id, itemId: itemId, msg: msg) - } else { - cmd = .apiSendMessage(type: type, id: id, msg: msg) - } + let cmd: ChatCommand = .apiSendMessage(type: type, id: id, file: file, quotedItemId: quotedItemId, msg: msg) let r: ChatResponse if type == .direct { var cItem: ChatItem! diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index ee638d8bf2..a4742f8ded 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -229,6 +229,7 @@ struct ChatView: View { let chatItem = try await apiSendMessage( type: chat.chatInfo.chatType, id: chat.chatInfo.apiId, + file: nil, quotedItemId: quotedItem?.meta.itemId, msg: mc ) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 87261c7cc5..488be1ec2e 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -33,16 +33,6 @@ 5C3A88CF27DF50170060F1C2 /* DetermineWidth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C3A88CD27DF50170060F1C2 /* DetermineWidth.swift */; }; 5C3A88D127DF57800060F1C2 /* FramedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C3A88D027DF57800060F1C2 /* FramedItemView.swift */; }; 5C3A88D227DF57800060F1C2 /* FramedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C3A88D027DF57800060F1C2 /* FramedItemView.swift */; }; - 5C41158927FF2D400054D6CB /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158427FF2D400054D6CB /* libgmpxx.a */; }; - 5C41158A27FF2D400054D6CB /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158427FF2D400054D6CB /* libgmpxx.a */; }; - 5C41158B27FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158527FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a */; }; - 5C41158C27FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158527FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a */; }; - 5C41158D27FF2D400054D6CB /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158627FF2D400054D6CB /* libgmp.a */; }; - 5C41158E27FF2D400054D6CB /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158627FF2D400054D6CB /* libgmp.a */; }; - 5C41158F27FF2D400054D6CB /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158727FF2D400054D6CB /* libffi.a */; }; - 5C41159027FF2D400054D6CB /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158727FF2D400054D6CB /* libffi.a */; }; - 5C41159127FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158827FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a */; }; - 5C41159227FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C41158827FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a */; }; 5C5346A827B59A6A004DF848 /* ChatHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5346A727B59A6A004DF848 /* ChatHelp.swift */; }; 5C5346A927B59A6A004DF848 /* ChatHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5346A727B59A6A004DF848 /* ChatHelp.swift */; }; 5C577F7D27C83AA10006112D /* MarkdownHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C577F7C27C83AA10006112D /* MarkdownHelp.swift */; }; @@ -118,6 +108,11 @@ 5CEACCEE27DEA495000BD591 /* MsgContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */; }; 640F50E327CF991C001E05C2 /* SMPServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640F50E227CF991C001E05C2 /* SMPServers.swift */; }; 640F50E427CF991C001E05C2 /* SMPServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640F50E227CF991C001E05C2 /* SMPServers.swift */; }; + 649BCD9A280430D100C3A862 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD95280430D100C3A862 /* libffi.a */; }; + 649BCD9B280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD96280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx-ghc8.10.7.a */; }; + 649BCD9C280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD97280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a */; }; + 649BCD9D280430D100C3A862 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD98280430D100C3A862 /* libgmp.a */; }; + 649BCD9E280430D100C3A862 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD99280430D100C3A862 /* libgmpxx.a */; }; 64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; }; 64AA1C6A27EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; }; 64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; }; @@ -155,11 +150,6 @@ 5C35CFCA27B2E91D00FB6C6D /* NtfManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NtfManager.swift; sourceTree = ""; }; 5C3A88CD27DF50170060F1C2 /* DetermineWidth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineWidth.swift; sourceTree = ""; }; 5C3A88D027DF57800060F1C2 /* FramedItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramedItemView.swift; sourceTree = ""; }; - 5C41158427FF2D400054D6CB /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - 5C41158527FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a"; sourceTree = ""; }; - 5C41158627FF2D400054D6CB /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; - 5C41158727FF2D400054D6CB /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 5C41158827FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a"; sourceTree = ""; }; 5C422A7C27A9A6FA0097A1E1 /* SimpleX (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SimpleX (iOS).entitlements"; sourceTree = ""; }; 5C5346A727B59A6A004DF848 /* ChatHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatHelp.swift; sourceTree = ""; }; 5C577F7C27C83AA10006112D /* MarkdownHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownHelp.swift; sourceTree = ""; }; @@ -206,6 +196,11 @@ 5CEACCE227DE9246000BD591 /* ComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeView.swift; sourceTree = ""; }; 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MsgContentView.swift; sourceTree = ""; }; 640F50E227CF991C001E05C2 /* SMPServers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMPServers.swift; sourceTree = ""; }; + 649BCD95280430D100C3A862 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; + 649BCD96280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx-ghc8.10.7.a"; sourceTree = ""; }; + 649BCD97280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a"; sourceTree = ""; }; + 649BCD98280430D100C3A862 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + 649BCD99280430D100C3A862 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; 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 = ""; }; /* End PBXFileReference section */ @@ -215,14 +210,14 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5C41158927FF2D400054D6CB /* libgmpxx.a in Frameworks */, - 5C41158B27FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a in Frameworks */, 5C8F01CD27A6F0D8007D2C8D /* CodeScanner in Frameworks */, + 649BCD9D280430D100C3A862 /* libgmp.a in Frameworks */, + 649BCD9B280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx-ghc8.10.7.a in Frameworks */, 5C764E83279C748B000C6508 /* libz.tbd in Frameworks */, - 5C41158F27FF2D400054D6CB /* libffi.a in Frameworks */, - 5C41158D27FF2D400054D6CB /* libgmp.a in Frameworks */, + 649BCD9E280430D100C3A862 /* libgmpxx.a in Frameworks */, 5C764E82279C748B000C6508 /* libiconv.tbd in Frameworks */, - 5C41159127FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a in Frameworks */, + 649BCD9A280430D100C3A862 /* libffi.a in Frameworks */, + 649BCD9C280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -230,12 +225,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5C41158A27FF2D400054D6CB /* libgmpxx.a in Frameworks */, - 5C41159027FF2D400054D6CB /* libffi.a in Frameworks */, - 5C41158E27FF2D400054D6CB /* libgmp.a in Frameworks */, 5C764E85279C748C000C6508 /* libz.tbd in Frameworks */, - 5C41159227FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a in Frameworks */, - 5C41158C27FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a in Frameworks */, 5C764E84279C748C000C6508 /* libiconv.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -288,11 +278,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5C41158727FF2D400054D6CB /* libffi.a */, - 5C41158627FF2D400054D6CB /* libgmp.a */, - 5C41158427FF2D400054D6CB /* libgmpxx.a */, - 5C41158827FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn-ghc8.10.7.a */, - 5C41158527FF2D400054D6CB /* libHSsimplex-chat-1.5.0-7pZO7WHlcmIHepHvDs8mvn.a */, + 649BCD95280430D100C3A862 /* libffi.a */, + 649BCD98280430D100C3A862 /* libgmp.a */, + 649BCD99280430D100C3A862 /* libgmpxx.a */, + 649BCD96280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx-ghc8.10.7.a */, + 649BCD97280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a */, ); path = Libraries; sourceTree = "";