-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Spec complete for sending and receiving messages
- Loading branch information
1 parent
03a436f
commit 924e103
Showing
30 changed files
with
978 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
import Ably | ||
import AblyChat | ||
import SwiftUI | ||
|
||
// TODO: This entire file can be removed and replaced with the actual example app we're going with. Leaving it here as a reference to something that is currently working. | ||
|
||
let clientId = "" // Set any string as a ClientID here e.g. "John" | ||
let apiKey = "" // Set your Ably API Key here | ||
|
||
struct MessageCell: View { | ||
var contentMessage: String | ||
var isCurrentUser: Bool | ||
|
||
var body: some View { | ||
Text(contentMessage) | ||
.padding(12) | ||
.foregroundColor(isCurrentUser ? Color.white : Color.black) | ||
.background(isCurrentUser ? Color.blue : Color.gray) | ||
.cornerRadius(12) | ||
} | ||
} | ||
|
||
struct MessageView: View { | ||
var currentMessage: Message | ||
|
||
var body: some View { | ||
HStack(alignment: .bottom) { | ||
if let messageClientId = currentMessage.clientID { | ||
if messageClientId == clientId { | ||
Spacer() | ||
} else {} | ||
MessageCell( | ||
contentMessage: currentMessage.text, | ||
isCurrentUser: messageClientId == clientId | ||
) | ||
} | ||
} | ||
.frame(maxWidth: .infinity, alignment: .leading) | ||
.padding(.horizontal, 16) | ||
.padding(.vertical, 4) | ||
} | ||
} | ||
|
||
struct MessageDemoView: View { | ||
@State private var messages: [Message] = [] // Store the chat messages | ||
@State private var newMessage: String = "" // Store the message user is typing | ||
@State private var room: Room? // Keep track of the chat room | ||
|
||
var clientOptions: ARTClientOptions { | ||
let options = ARTClientOptions() | ||
options.clientId = clientId | ||
options.key = apiKey | ||
return options | ||
} | ||
|
||
var body: some View { | ||
VStack { | ||
ScrollViewReader { proxy in | ||
ScrollView { | ||
LazyVStack(spacing: 0) { | ||
ForEach(messages, id: \.self) { message in | ||
MessageView(currentMessage: message) | ||
.id(message) | ||
} | ||
} | ||
.onChange(of: messages.count) { | ||
withAnimation { | ||
proxy.scrollTo(messages.last, anchor: .bottom) | ||
} | ||
} | ||
.onAppear { | ||
withAnimation { | ||
proxy.scrollTo(messages.last, anchor: .bottom) | ||
} | ||
} | ||
} | ||
|
||
// send new message | ||
HStack { | ||
TextField("Send a message", text: $newMessage) | ||
#if !os(tvOS) | ||
.textFieldStyle(.roundedBorder) | ||
#endif | ||
Button(action: sendMessage) { | ||
Image(systemName: "paperplane") | ||
} | ||
} | ||
.padding() | ||
} | ||
.task { | ||
await startChat() | ||
} | ||
} | ||
} | ||
|
||
func startChat() async { | ||
let realtime = ARTRealtime(options: clientOptions) | ||
|
||
let chatClient = DefaultChatClient( | ||
realtime: realtime, | ||
clientOptions: nil | ||
) | ||
|
||
do { | ||
// Get the chat room | ||
room = try await chatClient.rooms.get(roomID: "umairsDemoRoom1", options: .init()) | ||
|
||
// attach to room | ||
try await room?.attach() | ||
|
||
// subscribe to messages | ||
let subscription = try await room?.messages.subscribe(bufferingPolicy: .unbounded) | ||
|
||
// use subscription to get previous messages | ||
let prevMessages = try await subscription?.getPreviousMessages(params: .init(orderBy: .oldestFirst)) | ||
|
||
// init local messages array with previous messages | ||
messages = .init(prevMessages?.items ?? []) | ||
|
||
// append new messages to local messages array as they are emitted | ||
if let subscription { | ||
for await message in subscription { | ||
messages.append(message) | ||
} | ||
} | ||
} catch { | ||
print("Error starting chat: \(error)") | ||
} | ||
} | ||
|
||
func sendMessage() { | ||
guard !newMessage.isEmpty else { | ||
return | ||
} | ||
Task { | ||
do { | ||
_ = try await room?.messages.send(params: .init(text: newMessage)) | ||
|
||
// Clear the text field after sending | ||
newMessage = "" | ||
} catch { | ||
print("Error sending message: \(error)") | ||
} | ||
} | ||
} | ||
} | ||
|
||
#Preview { | ||
MessageDemoView() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// swift-tools-version: 6.0 | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "AblyChat", | ||
platforms: [ | ||
.macOS(.v12), | ||
.iOS(.v14), | ||
.tvOS(.v14), | ||
], | ||
products: [ | ||
.library( | ||
name: "AblyChat", | ||
targets: [ | ||
"AblyChat", | ||
] | ||
), | ||
], | ||
dependencies: [ | ||
.package( | ||
url: "https://github.com/ably/ably-cocoa", | ||
branch: "main" | ||
), | ||
.package( | ||
url: "https://github.com/apple/swift-argument-parser", | ||
from: "1.5.0" | ||
), | ||
.package( | ||
url: "https://github.com/apple/swift-async-algorithms", | ||
from: "1.0.1" | ||
), | ||
], | ||
targets: [ | ||
.target( | ||
name: "AblyChat", | ||
dependencies: [ | ||
.product( | ||
name: "Ably", | ||
package: "ably-cocoa" | ||
), | ||
] | ||
), | ||
.testTarget( | ||
name: "AblyChatTests", | ||
dependencies: [ | ||
"AblyChat", | ||
.product( | ||
name: "AsyncAlgorithms", | ||
package: "swift-async-algorithms" | ||
), | ||
] | ||
), | ||
.executableTarget( | ||
name: "BuildTool", | ||
dependencies: [ | ||
.product( | ||
name: "ArgumentParser", | ||
package: "swift-argument-parser" | ||
), | ||
.product( | ||
name: "AsyncAlgorithms", | ||
package: "swift-async-algorithms" | ||
), | ||
] | ||
), | ||
] | ||
) |
Oops, something went wrong.