diff --git a/Kordophone/Shared/ConversationView.swift b/Kordophone/Shared/ConversationView.swift index f3361ef..3d41a39 100644 --- a/Kordophone/Shared/ConversationView.swift +++ b/Kordophone/Shared/ConversationView.swift @@ -5,8 +5,12 @@ import KordophoneKit struct ConversationView : View { var conversation: Conversation var messages: [Message] + var sendAction: (String) -> Void - var body: some View { + @State private var inputText = "" + + @ViewBuilder + private var transcript: some View { ScrollViewReader { proxy in ScrollView { LazyVStack { @@ -22,12 +26,33 @@ struct ConversationView : View { } } } - .navigationTitle(conversation.effectiveDisplayName) .onChange(of: messages) { newValue in proxy.scrollTo(newValue.last, anchor: .bottom) } } } + + @ViewBuilder + private var inputView: some View { + TextField.init(text: $inputText) { + Text("Message") + } + .padding() + .onSubmit { + if inputText.count > 0 { + sendAction(inputText) + inputText = "" + } + } + } + + var body: some View { + VStack(spacing: 0) { + transcript + inputView + } + .navigationTitle(conversation.effectiveDisplayName) + } } struct ConversationViewWrapper : View { @@ -36,19 +61,23 @@ struct ConversationViewWrapper : View { @EnvironmentObject private var connection: Connection private func refresh() { - messages.removeAll() Task { self.messages = await connection.messages(in: conversation) ?? .init() } } var body: some View { - ConversationView(conversation: conversation, messages: messages) - .onChange(of: conversation, perform: { newValue in - refresh() - }) - .onAppear { - refresh() + ConversationView(conversation: conversation, messages: messages) { sent in + Task { + await connection.send(text: sent, in: conversation) } + refresh() + } + .onChange(of: conversation, perform: { newValue in + refresh() + }) + .onAppear { + refresh() + } } } diff --git a/KordophoneKit/Sources/KordophoneKit/Connection.swift b/KordophoneKit/Sources/KordophoneKit/Connection.swift index 3b947d7..e4eea83 100644 --- a/KordophoneKit/Sources/KordophoneKit/Connection.swift +++ b/KordophoneKit/Sources/KordophoneKit/Connection.swift @@ -9,8 +9,10 @@ public class Connection { public init() { } - private func authenticatedGET(service: String, - queryItems: [String : String] = .init()) + private func authenticatedRequest(service: String, + method: String = "GET", + body: Data? = nil, + queryItems: [String : String] = .init()) async -> Data? { guard let token = token else { return nil @@ -24,7 +26,8 @@ public class Connection { let finalURL = urlComponents.url! var request = URLRequest(url: finalURL) - request.httpMethod = "GET" + request.httpMethod = method + request.httpBody = body request.setValue("Bearer: \(token)", forHTTPHeaderField: "Authorization") return try? await URLSession.shared.data(for: request).0 @@ -55,7 +58,7 @@ public class Connection { } public func conversations() async -> [Conversation]? { - if let data = await authenticatedGET(service: "conversations") { + if let data = await authenticatedRequest(service: "conversations") { if let conversations = try? JSONDecoder().decode([RawConversation].self, from: data) { return conversations.map { $0.conversation @@ -67,7 +70,7 @@ public class Connection { } public func messages(in conversation: Conversation) async -> [Message]? { - if let data = await authenticatedGET(service: "messages", queryItems: ["guid" : conversation.guid]) { + if let data = await authenticatedRequest(service: "messages", queryItems: ["guid" : conversation.guid]) { if let messages = try? JSONDecoder().decode([RawMessage].self, from: data) { return messages.map { $0.message @@ -77,6 +80,17 @@ public class Connection { return nil } + + public func send(text: String, in conversation: Conversation) async { + var body = [String : String]() + body["guid"] = conversation.guid + body["body"] = text + let bodyData = try! JSONEncoder().encode(body) + + let _ = await authenticatedRequest(service: "sendMessage", + method: "POST", + body: bodyData) + } } extension Connection {