mv-experiment #1
|
@ -76,21 +76,6 @@ 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() {
|
||||
let clientsJids = clients
|
||||
.filter { $0.state != .disabled }
|
||||
|
@ -108,4 +93,26 @@ extension ClientsStore {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,14 @@
|
|||
"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.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
|
||||
//"Chats.title" = "Chats";
|
||||
|
@ -72,21 +59,7 @@
|
|||
//"Chats.Create.Main.createPrivateGroup" = "Create private 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
|
||||
//"Attachment.Prompt.main" = "Select attachment";
|
||||
|
|
|
@ -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 {
|
||||
@Environment(\.router) var router
|
||||
@EnvironmentObject var clientsStore: ClientsStore
|
||||
|
||||
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 {
|
||||
SharedListRow(
|
||||
|
@ -93,67 +58,93 @@ private struct ContactsScreenRow: View {
|
|||
.onTapGesture {
|
||||
// store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid)))
|
||||
}
|
||||
// .onLongPressGesture {
|
||||
// isShowingMenu.toggle()
|
||||
// }
|
||||
// .swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||
// Button {
|
||||
// isDeleteAlertPresented = true
|
||||
// } label: {
|
||||
// Label(L10n.Contacts.sendMessage, systemImage: "trash")
|
||||
// }
|
||||
// .tint(Color.red)
|
||||
// }
|
||||
// .contextMenu {
|
||||
// Button(L10n.Contacts.sendMessage, systemImage: "message") {
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||
Button {
|
||||
router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) {
|
||||
deleteConfirmation
|
||||
}
|
||||
} label: {
|
||||
Label("", systemImage: "trash")
|
||||
}
|
||||
.tint(Color.red)
|
||||
}
|
||||
.contextMenu {
|
||||
Button(L10n.Contacts.sendMessage, systemImage: "message") {
|
||||
// store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid)))
|
||||
// }
|
||||
// Divider()
|
||||
//
|
||||
// Button(L10n.Contacts.editContact) {
|
||||
// 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()
|
||||
// }
|
||||
}
|
||||
Divider()
|
||||
|
||||
Button(L10n.Contacts.editContact) {
|
||||
print("Edit contact")
|
||||
}
|
||||
|
||||
// private func endOfDeleting() {
|
||||
// if isShowingLoader {
|
||||
// isShowingLoader = false
|
||||
// if let error = store.state.rostersState.deleteRosterError {
|
||||
// errorAlertMessage = error
|
||||
// isErrorAlertPresented = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Button(L10n.Contacts.selectContact) {
|
||||
print("Select contact")
|
||||
}
|
||||
|
||||
Divider()
|
||||
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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,7 @@ struct MainTabScreen: View {
|
|||
// ConversationsScreen()
|
||||
|
||||
case .contacts:
|
||||
RouterView { _ in
|
||||
ContactsScreen()
|
||||
}
|
||||
|
||||
case .settings:
|
||||
Color.green
|
||||
|
|
Loading…
Reference in a new issue