This commit is contained in:
fmodf 2024-08-12 01:16:09 +02:00
parent 882501782e
commit 6df18d361f
4 changed files with 121 additions and 152 deletions

View file

@ -76,21 +76,6 @@ extension ClientsStore {
} }
extension ClientsStore { extension ClientsStore {
func addRoster(_ credentials: Credentials, contactJID: String, name: String?, groups: [String]) async throws {
// check that roster exist in db as locally deleted and undelete it
let deletedLocally = try await Roster.fetchDeletedLocally()
if var roster = deletedLocally.first(where: { $0.contactBareJid == contactJID }) {
try await roster.setLocallyDeleted(false)
return
}
// add new roster
guard let client = client(for: credentials) else {
throw ClientStoreError.clientNotFound
}
try await client.addRoster(contactJID, name: name, groups: groups)
}
private func resubscribeRosters() { private func resubscribeRosters() {
let clientsJids = clients let clientsJids = clients
.filter { $0.state != .disabled } .filter { $0.state != .disabled }
@ -108,4 +93,26 @@ extension ClientsStore {
self?.actualRosters = rosters self?.actualRosters = rosters
} }
} }
func addRoster(_ credentials: Credentials, contactJID: String, name: String?, groups: [String]) async throws {
// check that roster exist in db as locally deleted and undelete it
let deletedLocally = try await Roster.fetchDeletedLocally()
if var roster = deletedLocally.first(where: { $0.contactBareJid == contactJID }) {
try await roster.setLocallyDeleted(false)
return
}
// add new roster
guard let client = client(for: credentials) else {
throw ClientStoreError.clientNotFound
}
try await client.addRoster(contactJID, name: name, groups: groups)
}
func deleteRoster(_ roster: Roster) async throws {
guard let client = clients.first(where: { $0.credentials.bareJid == roster.bareJid }) else {
throw ClientStoreError.clientNotFound
}
try await client.deleteRoster(roster)
}
} }

View file

@ -32,6 +32,14 @@
"Contacts.Add.title" = "Add Contact"; "Contacts.Add.title" = "Add Contact";
"Contacts.Add.explanation" = "Contact or group/channel name are usually JID in format name@domain.ltd (like email)"; "Contacts.Add.explanation" = "Contact or group/channel name are usually JID in format name@domain.ltd (like email)";
"Contacts.Add.serverError" = "Contact adding dailed. Server returned error"; "Contacts.Add.serverError" = "Contact adding dailed. Server returned error";
"Contacts.deleteContact" = "Delete contact";
"Contacts.Delete.deleteFromDevice" = "Delete from device";
"Contacts.Delete.deleteCompletely" = "Delete completely";
"Contacts.sendMessage" = "Send message";
"Contacts.editContact" = "Edit contact";
"Contacts.selectContact" = "Select contact";
"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.";
@ -39,27 +47,6 @@
// MARK: Onboar screen
//"Login.title" = "Let\'s go!";
//"Login.subtitle" = "Enter your JID, it should looks like email address";
//"Login.Hint.jid" = "user@domain.im";
//"Login.Hint.password" = "password";
//"Login.btn" = "Continue";
//"Login.Error.wrongPassword" = "Wrong password or JID";
//"Login.Error.noServer" = "Server not exists";
//"Login.Error.serverError" = "Server error. Check internet connection";
// MARK: Contacts screen
//"Contacts.sendMessage" = "Send message";
//"Contacts.editContact" = "Edit contact";
//"Contacts.selectContact" = "Select contact";
//"Contacts.deleteContact" = "Delete contact";
//"Contacts.Delete.title" = "Delete contact";
//"Contacts.Delete.message" = "You can delete contact from this device (contact will be available on other devices), or delete it completely";
//"Contacts.Delete.deleteFromDevice" = "Delete from device";
//"Contacts.Delete.deleteCompletely" = "Delete completely";
//"Contacts.Delete.error" = "Contact not deleted. Server returns error.";
// MARK: Chats screen // MARK: Chats screen
//"Chats.title" = "Chats"; //"Chats.title" = "Chats";
@ -72,21 +59,7 @@
//"Chats.Create.Main.createPrivateGroup" = "Create private group"; //"Chats.Create.Main.createPrivateGroup" = "Create private group";
//"Chats.Create.Main.findGroup" = "Find public group"; //"Chats.Create.Main.findGroup" = "Find public group";
// MARK: Accounts add screen
//"Accounts.Add.or" = "or";
//"Accounts.Add.Exist.title" = "Add existing\naccount";
//"Accounts.Add.Exist.Prompt.jid" = "Enter your XMPP ID";
//"Accounts.Add.Exist.Prompt.password" = "Enter password";
//"Accounts.Add.Exist.Hint.jid" = "user@domain.im";
//"Accounts.Add.Exist.Hint.password" = "password";
//"Accounts.Add.Exist.Btn.link" = "create a new one";
//"Accounts.Add.Exist.Btn.main" = "Continue";
//"Accounts.Add.Exist.loginError" = "Wrong login or password";
// MARK: Server connecting indicator
//"ServerConnectingIndicator.State.connecting" = "Connecting to server";
//"ServerConnectingIndicator.State.connected" = "Connected";
//"ServerConnectingIndicator.State.error" = "Server unreachable. Check internet connection and server name";
// MARK: Attachments // MARK: Attachments
//"Attachment.Prompt.main" = "Select attachment"; //"Attachment.Prompt.main" = "Select attachment";

View file

@ -41,49 +41,14 @@ struct ContactsScreen: View {
} }
} }
} }
// .task {
// rosters = await clientsStore.actualRosters
// }
// .alert(isPresented: $isErrorAlertPresented) {
// Alert(
// title: Text(L10n.Global.Error.title),
// message: Text(errorAlertMessage),
// dismissButton: .default(Text(L10n.Global.ok))
// )
// }
} }
// private func fetchRosters() async {
// let jids = clientsStore.clients
// .filter { $0.state != .disabled }
// .map { $0.credentials.bareJid }
//
// do {
// try await withThrowingTaskGroup(of: [Roster].self) { group in
// for jid in jids {
// group.addTask {
// try await Roster.fetchAll(for: jid)
// }
// }
//
// var allRosters: [Roster] = []
// for try await rosters in group {
// allRosters.append(contentsOf: rosters)
// }
// self.rosters = allRosters.sorted { $0.contactBareJid < $1.contactBareJid }
// }
// } catch {}
// }
} }
private struct ContactsScreenRow: View { private struct ContactsScreenRow: View {
@Environment(\.router) var router
@EnvironmentObject var clientsStore: ClientsStore
var roster: Roster var roster: Roster
// @State private var isShowingMenu = false
// @State private var isDeleteAlertPresented = false
//
// @Binding var isErrorAlertPresented: Bool
// @Binding var errorAlertMessage: String
// @Binding var isShowingLoader: Bool
var body: some View { var body: some View {
SharedListRow( SharedListRow(
@ -93,67 +58,93 @@ private struct ContactsScreenRow: View {
.onTapGesture { .onTapGesture {
// store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid))) // store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid)))
} }
// .onLongPressGesture { .swipeActions(edge: .trailing, allowsFullSwipe: false) {
// isShowingMenu.toggle() Button {
// } router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) {
// .swipeActions(edge: .trailing, allowsFullSwipe: false) { deleteConfirmation
// Button { }
// isDeleteAlertPresented = true } label: {
// } label: { Label("", systemImage: "trash")
// Label(L10n.Contacts.sendMessage, systemImage: "trash") }
// } .tint(Color.red)
// .tint(Color.red) }
// } .contextMenu {
// .contextMenu { Button(L10n.Contacts.sendMessage, systemImage: "message") {
// Button(L10n.Contacts.sendMessage, systemImage: "message") {
// store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid))) // store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid)))
// } }
// Divider() Divider()
//
// Button(L10n.Contacts.editContact) { Button(L10n.Contacts.editContact) {
// print("Edit contact") print("Edit contact")
// }
//
// Button(L10n.Contacts.selectContact) {
// print("Select contact")
// }
//
// Divider()
// Button(L10n.Contacts.deleteContact, systemImage: "trash", role: .destructive) {
// isDeleteAlertPresented = true
// }
// }
// .actionSheet(isPresented: $isDeleteAlertPresented) {
// ActionSheet(
// title: Text(L10n.Contacts.Delete.title),
// message: Text(L10n.Contacts.Delete.message),
// buttons: [
// .destructive(Text(L10n.Contacts.Delete.deleteFromDevice)) {
// store.dispatch(.rostersAction(.markRosterAsLocallyDeleted(ownerJID: roster.bareJid, contactJID: roster.contactBareJid)))
// },
// .destructive(Text(L10n.Contacts.Delete.deleteCompletely)) {
// isShowingLoader = true
// store.dispatch(.rostersAction(.deleteRoster(ownerJID: roster.bareJid, contactJID: roster.contactBareJid)))
// },
// .cancel(Text(L10n.Global.cancel))
// ]
// )
// }
// .onChange(of: store.state.rostersState.rosters) { _ in
// endOfDeleting()
// }
// .onChange(of: store.state.rostersState.deleteRosterError) { _ in
// endOfDeleting()
// }
} }
// private func endOfDeleting() { Button(L10n.Contacts.selectContact) {
// if isShowingLoader { print("Select contact")
// isShowingLoader = false }
// if let error = store.state.rostersState.deleteRosterError {
// errorAlertMessage = error Divider()
// isErrorAlertPresented = true Button(L10n.Contacts.deleteContact, systemImage: "trash", role: .destructive) {
// } router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) {
// } deleteConfirmation
// } }
}
}
}
@ViewBuilder private var deleteConfirmation: some View {
Button(role: .destructive) {
Task {
await deleteFromDevice()
}
} label: {
Text(L10n.Contacts.Delete.deleteFromDevice)
}
Button(role: .destructive) {
Task {
await deleteCompletely()
}
} label: {
Text(L10n.Contacts.Delete.deleteCompletely)
}
Button(role: .cancel) {} label: {
Text(L10n.Global.cancel)
}
}
private func deleteFromDevice() async {
router.showModal {
LoadingScreen()
}
defer {
router.dismissModal()
}
var roster = roster
try? await roster.setLocallyDeleted(true)
}
private func deleteCompletely() async {
router.showModal {
LoadingScreen()
}
defer {
router.dismissModal()
}
do {
try await clientsStore.deleteRoster(roster)
} catch {
router.showAlert(
.alert,
title: L10n.Global.Error.title,
subtitle: L10n.Contacts.Delete.error
) {
Button(L10n.Global.ok, role: .cancel) {}
}
}
}
} }

View file

@ -27,9 +27,7 @@ struct MainTabScreen: View {
// ConversationsScreen() // ConversationsScreen()
case .contacts: case .contacts:
RouterView { _ in
ContactsScreen() ContactsScreen()
}
case .settings: case .settings:
Color.green Color.green