wip
This commit is contained in:
parent
ad7a2b4f59
commit
d1e3bc54bf
|
@ -1411,7 +1411,7 @@
|
|||
name = tools;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
29B97314FDCFA39411CA2CEA = {
|
||||
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8414ADF92A7ABAC900EFFCCC /* Packages */,
|
||||
|
@ -2064,7 +2064,7 @@
|
|||
eu,
|
||||
"es-AR",
|
||||
);
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA;
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
|
||||
packageReferences = (
|
||||
C1F5C7AD2777638B0001F295 /* XCRemoteSwiftPackageReference "swift-collections" */,
|
||||
841898A82957712000FEC77D /* XCRemoteSwiftPackageReference "ViewExtractor" */,
|
||||
|
|
|
@ -11,7 +11,7 @@ struct AddContactOrChannelScreen: View {
|
|||
|
||||
@FocusState private var focus: Field?
|
||||
|
||||
// @State private var ownerCredentials: Credentials?
|
||||
@State private var ownerAccount: Account?
|
||||
@State private var contactJID: String = ""
|
||||
|
||||
var body: some View {
|
||||
|
@ -56,13 +56,13 @@ struct AddContactOrChannelScreen: View {
|
|||
.frame(alignment: .leading)
|
||||
Spacer()
|
||||
}
|
||||
// UniversalInputCollection.DropDownMenu(
|
||||
// prompt: "Use account",
|
||||
// elements: activeClientsCredentials,
|
||||
// selected: $ownerCredentials,
|
||||
// focus: $focus,
|
||||
// fieldType: .account
|
||||
// )
|
||||
UniversalInputCollection.DropDownMenu(
|
||||
prompt: "Use account",
|
||||
elements: wrapper.accounts,
|
||||
selected: $ownerAccount,
|
||||
focus: $focus,
|
||||
fieldType: .account
|
||||
)
|
||||
|
||||
// Contact text input
|
||||
HStack(spacing: 0) {
|
||||
|
@ -72,18 +72,18 @@ struct AddContactOrChannelScreen: View {
|
|||
.frame(alignment: .leading)
|
||||
Spacer()
|
||||
}
|
||||
// UniversalInputCollection.TextField(
|
||||
// prompt: "Contact or channel JID",
|
||||
// text: $contactJID,
|
||||
// focus: $focus,
|
||||
// fieldType: .contact,
|
||||
// contentType: .emailAddress,
|
||||
// keyboardType: .emailAddress,
|
||||
// submitLabel: .done,
|
||||
// action: {
|
||||
// focus = .account
|
||||
// }
|
||||
// )
|
||||
UniversalInputCollection.TextField(
|
||||
prompt: "Contact or channel JID",
|
||||
text: $contactJID,
|
||||
focus: $focus,
|
||||
fieldType: .contact,
|
||||
contentType: .emailAddress,
|
||||
keyboardType: .emailAddress,
|
||||
submitLabel: .done,
|
||||
action: {
|
||||
focus = .account
|
||||
}
|
||||
)
|
||||
|
||||
// Save button
|
||||
Button {
|
||||
|
@ -94,7 +94,7 @@ struct AddContactOrChannelScreen: View {
|
|||
Text(L10n.Global.save)
|
||||
}
|
||||
.buttonStyle(PrimaryButtonStyle())
|
||||
// .disabled(!inputValid)
|
||||
.disabled(!inputValid)
|
||||
.padding(.top)
|
||||
Spacer()
|
||||
}
|
||||
|
@ -102,24 +102,18 @@ struct AddContactOrChannelScreen: View {
|
|||
}
|
||||
}
|
||||
.onAppear {
|
||||
// if let exists = activeClientsCredentials.first {
|
||||
// ownerCredentials = exists
|
||||
// }
|
||||
if let exists = wrapper.accounts.first {
|
||||
ownerAccount = exists
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private var activeClientsCredentials: [Credentials] {
|
||||
// clientsStore.clients
|
||||
// .filter { $0.state != .disabled }
|
||||
// .map { $0.credentials }
|
||||
// }
|
||||
private var inputValid: Bool {
|
||||
ownerAccount != nil && !contactJID.isEmpty && UniversalInputCollection.Validators.isEmail(contactJID)
|
||||
}
|
||||
|
||||
// private var inputValid: Bool {
|
||||
// ownerCredentials != nil && !contactJID.isEmpty && UniversalInputCollection.Validators.isEmail(contactJID)
|
||||
// }
|
||||
//
|
||||
private func save() async {
|
||||
// guard let ownerCredentials = ownerCredentials else { return }
|
||||
guard let ownerAccount = ownerAccount else { return }
|
||||
|
||||
router.showModal {
|
||||
LoadingScreen()
|
||||
|
|
|
@ -26,94 +26,68 @@ struct ContactsScreen: View {
|
|||
)
|
||||
|
||||
// Contacts list
|
||||
// if !clientsStore.actualRosters.isEmpty {
|
||||
// List {
|
||||
// ForEach(elements.indices, id: \.self) { index in
|
||||
// let element = elements[index]
|
||||
// if let roster = element as? Roster {
|
||||
// ContactsScreenRow(
|
||||
// roster: roster
|
||||
// )
|
||||
// } else if let bareJid = element as? String {
|
||||
// SharedSectionTitle(text: bareJid)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .listStyle(.plain)
|
||||
// .background(Color.Material.Background.light)
|
||||
// } else {
|
||||
// Spacer()
|
||||
// }
|
||||
if !wrapper.contacts.isEmpty {
|
||||
List {
|
||||
ForEach(wrapper.contacts) {
|
||||
ContactsScreenRow(contact: $0)
|
||||
}
|
||||
}
|
||||
.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 {
|
||||
@EnvironmentObject var wrapper: MonalXmppWrapper
|
||||
@Environment(\.router) var router
|
||||
|
||||
// var roster: Roster
|
||||
var contact: Contact
|
||||
|
||||
var body: some View {
|
||||
Text("nothing for now")
|
||||
// SharedListRow(
|
||||
// iconType: .charCircle(roster.name?.firstLetter ?? roster.contactBareJid.firstLetter),
|
||||
// text: roster.contactBareJid,
|
||||
// controlType: .none
|
||||
// )
|
||||
// .onTapGesture {
|
||||
// startChat()
|
||||
// }
|
||||
// .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") {
|
||||
// startChat()
|
||||
// }
|
||||
// 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
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
SharedListRow(
|
||||
iconType: .charCircle(contact.name?.firstLetter ?? contact.contactJid.firstLetter),
|
||||
text: contact.contactJid,
|
||||
controlType: .none
|
||||
)
|
||||
.onTapGesture {
|
||||
startChat()
|
||||
}
|
||||
.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") {
|
||||
startChat()
|
||||
}
|
||||
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 {
|
||||
|
|
|
@ -27,8 +27,7 @@ struct MainTabScreen: View {
|
|||
// ChatsListScreen()
|
||||
|
||||
case .contacts:
|
||||
Text("contacts")
|
||||
// ContactsScreen()
|
||||
ContactsScreen()
|
||||
|
||||
case .settings:
|
||||
Text("settings")
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import Foundation
|
||||
import monalxmpp
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Account
|
||||
enum AccountsAvailability {
|
||||
case noAccounts
|
||||
case allDisabled
|
||||
|
@ -32,8 +35,22 @@ struct Account: Identifiable {
|
|||
}
|
||||
}
|
||||
|
||||
struct Contact: Identifiable {
|
||||
let jid: String
|
||||
|
||||
var id: String { jid }
|
||||
extension Account: UniversalInputSelectionElement {
|
||||
var icon: Image? { nil }
|
||||
var text: 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ final class MonalXmppWrapper: ObservableObject {
|
|||
private let db: DataLayer
|
||||
|
||||
private var notificationObservers: [AnyObject] = []
|
||||
private var isInitialized: Bool = false
|
||||
|
||||
init() {
|
||||
// here is some inits (just for now)
|
||||
|
@ -88,33 +87,43 @@ private final class LoginTry {
|
|||
// MARK: - Handle notifications
|
||||
private extension MonalXmppWrapper {
|
||||
func subscribeToUpdates() {
|
||||
// General
|
||||
let generalRefresh = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalRefresh), object: nil, queue: .main) { [weak self] _ in
|
||||
// get accounts
|
||||
let accounts = self?.db.accountList()
|
||||
.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
|
||||
//
|
||||
self?.refreshAccounts()
|
||||
self?.refreshContacts()
|
||||
}
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue