feat: add authenticated durable native Hope chat
This commit is contained in:
1 parent
74d2b63614
commit
7dcd06c911
15 files changed
+1675
-9
No files matched your search
@@ -11,7 +11,8 @@ struct ConversationView: View {
|
||||
@State private var activeServerURL: String
|
||||
@State private var pendingServerURL: String?
|
||||
@State private var isReplacingSession = false
|
||||
@State private var selectedTab = 0
|
||||
@State private var selectedTab = 2
|
||||
@StateObject private var chat: ChatStore
|
||||
|
||||
init(settings: SettingsStore, auth: AuthStore, user: AuthUser, bearerToken: String) {
|
||||
self.auth = auth
|
||||
@@ -21,6 +22,11 @@ struct ConversationView: View {
|
||||
let url = settings.trimmedServerURL
|
||||
_activeServerURL = State(initialValue: url)
|
||||
_session = State(initialValue: Self.makeSession(url, settings: settings, bearerToken: bearerToken, userID: user.id))
|
||||
let api: ChatTransport = auth.fixture ? OfflineChatAPI() : ChatAPI(config: auth.config, token: bearerToken)
|
||||
_chat = StateObject(wrappedValue: ChatStore(api: api))
|
||||
#if DEBUG
|
||||
if auth.fixture && !ProcessInfo.processInfo.arguments.contains("--ui-chat") { _selectedTab = State(initialValue: 0) }
|
||||
#endif
|
||||
}
|
||||
|
||||
private static func makeSession(_ url: String, settings: SettingsStore, bearerToken: String, userID: String) -> VoiceSession {
|
||||
@@ -49,6 +55,14 @@ struct ConversationView: View {
|
||||
|
||||
var body: some View {
|
||||
TabView(selection: $selectedTab) {
|
||||
NativeChatView(store: chat, talk: { id in
|
||||
await session.bindConversation(id)
|
||||
selectedTab = 0
|
||||
}, logout: {
|
||||
await auth.logout { chat.close(); await session.disconnect() }
|
||||
})
|
||||
.tabItem { Label("Chats", systemImage: "bubble.left.and.text.bubble.right") }
|
||||
.tag(2)
|
||||
NavigationStack {
|
||||
ConversationContent(settings: settings, session: session, displayName: user.displayName ?? user.username)
|
||||
.toolbar {
|
||||
@@ -56,7 +70,7 @@ struct ConversationView: View {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Menu {
|
||||
Button("Sign out", role: .destructive) {
|
||||
Task { await auth.logout { await session.disconnect() } }
|
||||
Task { await auth.logout { chat.close(); await session.disconnect() } }
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "person.crop.circle")
|
||||
@@ -72,7 +86,8 @@ struct ConversationView: View {
|
||||
ActivityTab(taskStore: session.taskStore, settings: settings, session: session)
|
||||
.tag(1)
|
||||
}
|
||||
.tint(Nearlight.rosewood)
|
||||
.tint(HopeTheme.color(.accent, palette: HopePalette(rawValue: chat.preferences.palette) ?? .opal))
|
||||
.preferredColorScheme(chat.preferences.appearance == "system" ? nil : (chat.preferences.appearance == "dark" ? .dark : .light))
|
||||
.onChange(of: settings.textMode) { _, enabled in
|
||||
Task { await session.applyTextMode(enabled) }
|
||||
}
|
||||
@@ -80,10 +95,13 @@ struct ConversationView: View {
|
||||
if auth.fixture { replaceServer(value) }
|
||||
}
|
||||
.onAppear {
|
||||
auth.disconnectAccount = { [weak session] in await session?.disconnect() }
|
||||
session.onUnauthorized = { [weak auth, weak session] in
|
||||
await auth?.logout { await session?.disconnect() }
|
||||
auth.disconnectAccount = { [weak session, weak chat] in chat?.close(); await session?.disconnect() }
|
||||
let unauthorized: () async -> Void = { [weak auth, weak session, weak chat] in
|
||||
await auth?.logout { chat?.close(); await session?.disconnect() }
|
||||
}
|
||||
session.onUnauthorized = unauthorized
|
||||
chat.onUnauthorized = unauthorized
|
||||
chat.features.onUnauthorized = unauthorized
|
||||
}
|
||||
.disabled(auth.isBusy || auth.token == nil)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user