This commit is contained in:
Woit 2024-11-22 14:12:09 +01:00
parent ad7a2b4f59
commit d1e3bc54bf
6 changed files with 138 additions and 145 deletions

View file

@ -1411,7 +1411,7 @@
name = tools; name = tools;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
29B97314FDCFA39411CA2CEA = { 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
8414ADF92A7ABAC900EFFCCC /* Packages */, 8414ADF92A7ABAC900EFFCCC /* Packages */,
@ -2064,7 +2064,7 @@
eu, eu,
"es-AR", "es-AR",
); );
mainGroup = 29B97314FDCFA39411CA2CEA; mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
packageReferences = ( packageReferences = (
C1F5C7AD2777638B0001F295 /* XCRemoteSwiftPackageReference "swift-collections" */, C1F5C7AD2777638B0001F295 /* XCRemoteSwiftPackageReference "swift-collections" */,
841898A82957712000FEC77D /* XCRemoteSwiftPackageReference "ViewExtractor" */, 841898A82957712000FEC77D /* XCRemoteSwiftPackageReference "ViewExtractor" */,

View file

@ -11,7 +11,7 @@ struct AddContactOrChannelScreen: View {
@FocusState private var focus: Field? @FocusState private var focus: Field?
// @State private var ownerCredentials: Credentials? @State private var ownerAccount: Account?
@State private var contactJID: String = "" @State private var contactJID: String = ""
var body: some View { var body: some View {
@ -56,13 +56,13 @@ struct AddContactOrChannelScreen: View {
.frame(alignment: .leading) .frame(alignment: .leading)
Spacer() Spacer()
} }
// UniversalInputCollection.DropDownMenu( UniversalInputCollection.DropDownMenu(
// prompt: "Use account", prompt: "Use account",
// elements: activeClientsCredentials, elements: wrapper.accounts,
// selected: $ownerCredentials, selected: $ownerAccount,
// focus: $focus, focus: $focus,
// fieldType: .account fieldType: .account
// ) )
// Contact text input // Contact text input
HStack(spacing: 0) { HStack(spacing: 0) {
@ -72,18 +72,18 @@ struct AddContactOrChannelScreen: View {
.frame(alignment: .leading) .frame(alignment: .leading)
Spacer() Spacer()
} }
// UniversalInputCollection.TextField( UniversalInputCollection.TextField(
// prompt: "Contact or channel JID", prompt: "Contact or channel JID",
// text: $contactJID, text: $contactJID,
// focus: $focus, focus: $focus,
// fieldType: .contact, fieldType: .contact,
// contentType: .emailAddress, contentType: .emailAddress,
// keyboardType: .emailAddress, keyboardType: .emailAddress,
// submitLabel: .done, submitLabel: .done,
// action: { action: {
// focus = .account focus = .account
// } }
// ) )
// Save button // Save button
Button { Button {
@ -94,7 +94,7 @@ struct AddContactOrChannelScreen: View {
Text(L10n.Global.save) Text(L10n.Global.save)
} }
.buttonStyle(PrimaryButtonStyle()) .buttonStyle(PrimaryButtonStyle())
// .disabled(!inputValid) .disabled(!inputValid)
.padding(.top) .padding(.top)
Spacer() Spacer()
} }
@ -102,24 +102,18 @@ struct AddContactOrChannelScreen: View {
} }
} }
.onAppear { .onAppear {
// if let exists = activeClientsCredentials.first { if let exists = wrapper.accounts.first {
// ownerCredentials = exists ownerAccount = exists
// } }
} }
} }
// private var activeClientsCredentials: [Credentials] { private var inputValid: Bool {
// clientsStore.clients ownerAccount != nil && !contactJID.isEmpty && UniversalInputCollection.Validators.isEmail(contactJID)
// .filter { $0.state != .disabled } }
// .map { $0.credentials }
// }
// private var inputValid: Bool {
// ownerCredentials != nil && !contactJID.isEmpty && UniversalInputCollection.Validators.isEmail(contactJID)
// }
//
private func save() async { private func save() async {
// guard let ownerCredentials = ownerCredentials else { return } guard let ownerAccount = ownerAccount else { return }
router.showModal { router.showModal {
LoadingScreen() LoadingScreen()

View file

@ -26,94 +26,68 @@ struct ContactsScreen: View {
) )
// Contacts list // Contacts list
// if !clientsStore.actualRosters.isEmpty { if !wrapper.contacts.isEmpty {
// List { List {
// ForEach(elements.indices, id: \.self) { index in ForEach(wrapper.contacts) {
// let element = elements[index] ContactsScreenRow(contact: $0)
// if let roster = element as? Roster { }
// ContactsScreenRow( }
// roster: roster .listStyle(.plain)
// ) .background(Color.Material.Background.light)
// } else if let bareJid = element as? String { } else {
// SharedSectionTitle(text: bareJid) Spacer()
// } }
// }
// }
// .listStyle(.plain)
// .background(Color.Material.Background.light)
// } else {
// Spacer()
// }
} }
} }
} }
private var elements: [Any] {
[]
// if clientsStore.clients.filter({ $0.credentials.isActive }).count == 1 {
// return clientsStore.actualRosters
// } else {
// var result: [Any] = []
// for roster in clientsStore.actualRosters {
// if result.isEmpty {
// result.append(roster.bareJid)
// } else if let last = result.last as? Roster, last.bareJid != roster.bareJid {
// result.append(roster.bareJid)
// }
// result.append(roster)
// }
// return result
// }
}
} }
private struct ContactsScreenRow: View { private struct ContactsScreenRow: View {
@EnvironmentObject var wrapper: MonalXmppWrapper @EnvironmentObject var wrapper: MonalXmppWrapper
@Environment(\.router) var router @Environment(\.router) var router
// var roster: Roster var contact: Contact
var body: some View { var body: some View {
Text("nothing for now") SharedListRow(
// SharedListRow( iconType: .charCircle(contact.name?.firstLetter ?? contact.contactJid.firstLetter),
// iconType: .charCircle(roster.name?.firstLetter ?? roster.contactBareJid.firstLetter), text: contact.contactJid,
// text: roster.contactBareJid, controlType: .none
// controlType: .none )
// ) .onTapGesture {
// .onTapGesture { startChat()
// startChat() }
// } .swipeActions(edge: .trailing, allowsFullSwipe: false) {
// .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button {
// Button { router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) {
// router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) { deleteConfirmation
// deleteConfirmation }
// } } label: {
// } label: { Label("", systemImage: "trash")
// Label("", systemImage: "trash") }
// } .tint(Color.red)
// .tint(Color.red) }
// } .contextMenu {
// .contextMenu { Button(L10n.Contacts.sendMessage, systemImage: "message") {
// Button(L10n.Contacts.sendMessage, systemImage: "message") { startChat()
// startChat() }
// } Divider()
// Divider()
// Button(L10n.Contacts.editContact) {
// Button(L10n.Contacts.editContact) { print("Edit contact")
// print("Edit contact") }
// }
// Button(L10n.Contacts.selectContact) {
// Button(L10n.Contacts.selectContact) { print("Select contact")
// print("Select contact") }
// }
// Divider()
// Divider() Button(L10n.Contacts.deleteContact, systemImage: "trash", role: .destructive) {
// Button(L10n.Contacts.deleteContact, systemImage: "trash", role: .destructive) { router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) {
// router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) { deleteConfirmation
// deleteConfirmation }
// } }
// } }
// }
} }
@ViewBuilder private var deleteConfirmation: some View { @ViewBuilder private var deleteConfirmation: some View {

View file

@ -27,8 +27,7 @@ struct MainTabScreen: View {
// ChatsListScreen() // ChatsListScreen()
case .contacts: case .contacts:
Text("contacts") ContactsScreen()
// ContactsScreen()
case .settings: case .settings:
Text("settings") Text("settings")

View file

@ -1,5 +1,8 @@
import Foundation import Foundation
import monalxmpp
import SwiftUI
// MARK: - Account
enum AccountsAvailability { enum AccountsAvailability {
case noAccounts case noAccounts
case allDisabled case allDisabled
@ -32,8 +35,22 @@ struct Account: Identifiable {
} }
} }
struct Contact: Identifiable { extension Account: UniversalInputSelectionElement {
let jid: String var icon: Image? { nil }
var text: String? { jid }
var id: String { jid } }
// MARK: - Contact
struct Contact: Identifiable {
let ownerId: Int
let contactJid: String
let name: String?
var id: String { contactJid }
init?(_ obj: MLContact) {
ownerId = obj.accountID.intValue
contactJid = obj.contactJid
name = obj.nickName
}
} }

View file

@ -10,7 +10,6 @@ final class MonalXmppWrapper: ObservableObject {
private let db: DataLayer private let db: DataLayer
private var notificationObservers: [AnyObject] = [] private var notificationObservers: [AnyObject] = []
private var isInitialized: Bool = false
init() { init() {
// here is some inits (just for now) // here is some inits (just for now)
@ -88,33 +87,43 @@ private final class LoginTry {
// MARK: - Handle notifications // MARK: - Handle notifications
private extension MonalXmppWrapper { private extension MonalXmppWrapper {
func subscribeToUpdates() { func subscribeToUpdates() {
// General
let generalRefresh = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalRefresh), object: nil, queue: .main) { [weak self] _ in let generalRefresh = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalRefresh), object: nil, queue: .main) { [weak self] _ in
// get accounts self?.refreshAccounts()
let accounts = self?.db.accountList() self?.refreshContacts()
.compactMap { dict -> Account? in
guard let dict = dict as? NSDictionary else { return nil }
return Account(dict)
} ?? []
self?.accounts = accounts
// start connect if it initialization process
if !(self?.isInitialized ?? true) {
self?.xmpp.reconnectAll()
self?.isInitialized = true
}
// mark accounts availability
if accounts.isEmpty {
self?.accountsAvailability = .noAccounts
} else if !accounts.filter({ $0.isEnabled }).isEmpty {
self?.accountsAvailability = .allDisabled
} else {
self?.accountsAvailability = .someEnabled
}
// get contacts for active accounts
//
} }
notificationObservers.append(generalRefresh) notificationObservers.append(generalRefresh)
// For contacts
let contactRefresh = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRefresh), object: nil, queue: .main) { [weak self] _ in
self?.refreshContacts()
}
let contactRemove = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRemoved), object: nil, queue: .main) { [weak self] _ in
self?.refreshContacts()
}
notificationObservers.append(contentsOf: [contactRefresh, contactRemove])
}
func refreshAccounts() {
let accounts = db.accountList()
.compactMap { dict -> Account? in
guard let dict = dict as? NSDictionary else { return nil }
return Account(dict)
}
self.accounts = accounts
xmpp.connectIfNecessary()
// mark accounts availability
if accounts.isEmpty {
accountsAvailability = .noAccounts
} else if accounts.filter({ $0.isEnabled }).isEmpty {
accountsAvailability = .allDisabled
} else {
accountsAvailability = .someEnabled
}
}
func refreshContacts() {
contacts = db.contactList().compactMap { Contact($0) }
} }
} }