This commit is contained in:
fmodf 2024-08-12 21:29:16 +02:00
parent 77ade86bb1
commit 95652a7f3b
4 changed files with 89 additions and 16 deletions

View file

@ -9,9 +9,11 @@ final class ClientsStore: ObservableObject {
@Published private(set) var ready = false @Published private(set) var ready = false
@Published private(set) var clients: [Client] = [] @Published private(set) var clients: [Client] = []
@Published private(set) var actualRosters: [Roster] = [] @Published private(set) var actualRosters: [Roster] = []
@Published private(set) var actualChats: [Chat] = []
private var credentialsCancellable: AnyCancellable? private var credentialsCancellable: AnyCancellable?
private var rostersCancellable: AnyCancellable? private var rostersCancellable: AnyCancellable?
private var chatsCancellable: AnyCancellable?
init() { init() {
credentialsCancellable = ValueObservation credentialsCancellable = ValueObservation
@ -44,6 +46,8 @@ final class ClientsStore: ObservableObject {
} }
resubscribeRosters() resubscribeRosters()
resubscribeChats()
reconnectAll()
} }
private func client(for credentials: Credentials) -> Client? { private func client(for credentials: Credentials) -> Client? {
@ -62,7 +66,7 @@ extension ClientsStore {
try? await client.credentials.save() try? await client.credentials.save()
} }
func reconnectAll() { private func reconnectAll() {
Task { Task {
await withTaskGroup(of: Void.self) { taskGroup in await withTaskGroup(of: Void.self) { taskGroup in
for client in clients { for client in clients {
@ -116,3 +120,22 @@ extension ClientsStore {
try await client.deleteRoster(roster) try await client.deleteRoster(roster)
} }
} }
extension ClientsStore {
private func resubscribeChats() {
let clientsJids = clients
.filter { $0.state != .disabled }
.map { $0.credentials.bareJid }
chatsCancellable = ValueObservation.tracking { db in
try Chat
.filter(clientsJids.contains(Column("account")))
.fetchAll(db)
}
.publisher(in: Database.shared.dbQueue)
.catch { _ in Just([]) }
.sink { [weak self] chats in
self?.actualChats = chats
}
}
}

View file

@ -41,6 +41,8 @@
"Contacts.Delete.message" = "You can delete contact from this device (contact will be available on other devices), or delete it completely"; "Contacts.Delete.message" = "You can delete contact from this device (contact will be available on other devices), or delete it completely";
"Contacts.Delete.error" = "Contact not deleted. Server returns error."; "Contacts.Delete.error" = "Contact not deleted. Server returns error.";
// MARK: Chats list screen
"ChatsList.title" = "Chats";
@ -48,10 +50,6 @@
// MARK: Chats screen
//"Chats.title" = "Chats";
//"Chat.title" = "Chat";
//"Chat.textfieldPrompt" = "Type a message"; //"Chat.textfieldPrompt" = "Type a message";
//"Chats.Create.Main.title" = "Create"; //"Chats.Create.Main.title" = "Create";

View file

@ -0,0 +1,56 @@
import SwiftUI
struct ChatsListScreen: View {
@EnvironmentObject var clientsStore: ClientsStore
var body: some View {
ZStack {
// Background color
Color.Material.Background.light
.ignoresSafeArea()
// Content
VStack(spacing: 0) {
// Header
SharedNavigationBar(
centerText: .init(text: L10n.ChatsList.title),
rightButton: .init(
image: Image(systemName: "square.and.pencil"),
action: {
// isCretePanelPresented = true
}
)
)
// Chats list
if !clientsStore.actualChats.isEmpty {
List {
ForEach(clientsStore.actualChats) { chat in
ChatsRow(chat: chat)
}
}
.listStyle(.plain)
.background(Color.Material.Background.light)
} else {
Spacer()
}
}
}
// .fullScreenCover(isPresented: $isCretePanelPresented) {
// ChatsCreateMainScreen(isPresented: $isCretePanelPresented)
// }
}
}
private struct ChatsRow: View {
// @EnvironmentObject var store: AppStore
var chat: Chat
var body: some View {
SharedListRow(iconType: .charCircle(chat.participant), text: chat.participant)
.onTapGesture {
// store.dispatch(.chatsAction(.startChat(accountJid: chat.account, participantJid: chat.participant)))
}
}
}

View file

@ -3,7 +3,7 @@ import SwiftfulRouting
import SwiftUI import SwiftUI
private enum Tab { private enum Tab {
case conversations case chats
case contacts case contacts
case settings case settings
} }
@ -11,7 +11,7 @@ private enum Tab {
struct MainTabScreen: View { struct MainTabScreen: View {
@EnvironmentObject var clientsStore: ClientsStore @EnvironmentObject var clientsStore: ClientsStore
@State private var selectedTab: Tab = .conversations @State private var selectedTab: Tab = .chats
var body: some View { var body: some View {
ZStack { ZStack {
@ -22,9 +22,8 @@ struct MainTabScreen: View {
// Content // Content
VStack(spacing: 0) { VStack(spacing: 0) {
switch selectedTab { switch selectedTab {
case .conversations: case .chats:
Color.red ChatsListScreen()
// ConversationsScreen()
case .contacts: case .contacts:
ContactsScreen() ContactsScreen()
@ -38,9 +37,6 @@ struct MainTabScreen: View {
TabBar(selectedTab: $selectedTab) TabBar(selectedTab: $selectedTab)
} }
} }
.onLoad {
clientsStore.reconnectAll()
}
} }
} }
@ -55,7 +51,7 @@ private struct TabBar: View {
.foregroundColor(.Material.Shape.separator) .foregroundColor(.Material.Shape.separator)
HStack(spacing: 0) { HStack(spacing: 0) {
TabBarButton(buttonType: .contacts, selectedTab: $selectedTab) TabBarButton(buttonType: .contacts, selectedTab: $selectedTab)
TabBarButton(buttonType: .conversations, selectedTab: $selectedTab) TabBarButton(buttonType: .chats, selectedTab: $selectedTab)
TabBarButton(buttonType: .settings, selectedTab: $selectedTab) TabBarButton(buttonType: .settings, selectedTab: $selectedTab)
} }
.background(Color.Material.Background.dark) .background(Color.Material.Background.dark)
@ -93,7 +89,7 @@ private struct TabBarButton: View {
case .contacts: case .contacts:
return Image(systemName: "person.2.fill") return Image(systemName: "person.2.fill")
case .conversations: case .chats:
return Image(systemName: "bubble.left.fill") return Image(systemName: "bubble.left.fill")
case .settings: case .settings:
@ -106,7 +102,7 @@ private struct TabBarButton: View {
case .contacts: case .contacts:
return L10n.Tabs.Name.contacts return L10n.Tabs.Name.contacts
case .conversations: case .chats:
return L10n.Tabs.Name.conversations return L10n.Tabs.Name.conversations
case .settings: case .settings: