another.im-ios/ConversationsClassic/View/Main/Contacts/ContactsScreen.swift

178 lines
4.9 KiB
Swift
Raw Normal View History

2024-08-11 00:28:01 +00:00
import SwiftUI
struct ContactsScreen: View {
2024-08-11 15:10:58 +00:00
@Environment(\.router) var router
2024-08-11 00:28:01 +00:00
@EnvironmentObject var clientsStore: ClientsStore
2024-08-11 20:33:04 +00:00
2024-08-11 00:28:01 +00:00
var body: some View {
ZStack {
// Background color
Color.Material.Background.light
.ignoresSafeArea()
// Content
VStack(spacing: 0) {
// Header
SharedNavigationBar(
centerText: .init(text: L10n.Contacts.title),
rightButton: .init(
image: Image(systemName: "plus"),
action: {
2024-08-11 15:10:58 +00:00
router.showScreen(.fullScreenCover) { _ in
2024-08-11 21:52:01 +00:00
AddContactOrChannelScreen()
2024-08-11 15:10:58 +00:00
}
2024-08-11 00:28:01 +00:00
}
)
)
// Contacts list
2024-08-11 22:30:01 +00:00
if !clientsStore.actualRosters.isEmpty {
2024-08-11 00:28:01 +00:00
List {
2024-08-11 22:30:01 +00:00
ForEach(clientsStore.actualRosters) { roster in
2024-08-11 00:28:01 +00:00
ContactsScreenRow(
roster: roster
)
}
}
.listStyle(.plain)
.background(Color.Material.Background.light)
} else {
Spacer()
}
}
}
}
}
private struct ContactsScreenRow: View {
2024-08-11 23:16:09 +00:00
@Environment(\.router) var router
@EnvironmentObject var clientsStore: ClientsStore
2024-08-11 00:28:01 +00:00
var roster: Roster
var body: some View {
SharedListRow(
iconType: .charCircle(roster.name?.firstLetter ?? roster.contactBareJid.firstLetter),
text: roster.contactBareJid
)
2024-08-11 17:07:02 +00:00
.onTapGesture {
2024-08-13 08:40:27 +00:00
startChat()
2024-08-11 17:07:02 +00:00
}
2024-08-11 23:16:09 +00:00
.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") {
2024-08-13 08:40:27 +00:00
startChat()
2024-08-11 23:16:09 +00:00
}
Divider()
Button(L10n.Contacts.editContact) {
print("Edit contact")
}
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)
}
2024-08-11 00:28:01 +00:00
}
2024-08-11 23:16:09 +00:00
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) {}
}
}
}
2024-08-13 08:40:27 +00:00
private func startChat() {
Task {
router.showModal {
LoadingScreen()
}
defer {
router.dismissModal()
}
do {
2024-08-17 16:15:05 +00:00
let conversation = try await clientsStore.conversation(for: roster)
2024-08-13 08:40:27 +00:00
router.showScreen(.push) { _ in
2024-08-17 16:15:05 +00:00
ConversationScreen(conversation: conversation)
2024-08-13 08:40:27 +00:00
.navigationBarHidden(true)
}
} catch {
router.showAlert(
.alert,
title: L10n.Global.Error.title,
subtitle: L10n.Conversation.startError
) {
Button(L10n.Global.ok, role: .cancel) {}
}
}
}
}
2024-08-11 00:28:01 +00:00
}