Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Draft]: Rewrite the Account Settings view in SwiftUI #1283

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
425 changes: 425 additions & 0 deletions Monal/Classes/AccountSettings.swift

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Monal/Classes/DataLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ extern NSString* const kMessageTypeFiletransfer;
-(NSNumber*) enabledAccountCnts;
-(NSArray*) enabledAccountList;
-(BOOL) isAccountEnabled:(NSNumber*) accountID;
-(BOOL) disableAccountForAccountID:(NSNumber*) accountID;
-(BOOL) enableAccountForAccountID:(NSNumber*) accountID;
-(BOOL) doesAccountExistUser:(NSString*) user andDomain:(NSString *) domain;
-(NSNumber* _Nullable) accountIDForUser:(NSString*) user andDomain:(NSString *) domain;

Expand Down
14 changes: 14 additions & 0 deletions Monal/Classes/DataLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,20 @@ -(BOOL) isAccountEnabled:(NSNumber*) accountID
}];
}

-(BOOL) disableAccountForAccountID:(NSNumber*) accountID
{
return [self.db boolReadTransaction:^{
return [self.db executeNonQuery:@"UPDATE account SET enabled=0 WHERE account_id=?;" andArguments:@[accountID]];
}];
}

-(BOOL) enableAccountForAccountID:(NSNumber*) accountID
{
return [self.db boolReadTransaction:^{
return [self.db executeNonQuery:@"UPDATE account SET enabled=1 WHERE account_id=?;" andArguments:@[accountID]];
}];
}

-(NSNumber*) accountIDForUser:(NSString*) user andDomain:(NSString*) domain
{
if(!user && !domain)
Expand Down
4 changes: 2 additions & 2 deletions Monal/Classes/GeneralSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,8 @@ struct SecuritySettings: View {
259200: NSLocalizedString("3 days", comment:"Message autdelete time"),
604800: NSLocalizedString("1 week", comment:"Message autdelete time"),
2419200: NSLocalizedString("4 weeks", comment:"Message autdelete time"),
5184000: NSLocalizedString("2 month", comment:"Message autdelete time"), //based on 30 days per month
7776000: NSLocalizedString("3 month", comment:"Message autdelete time"), //based on 30 days per month
5184000: NSLocalizedString("2 months", comment:"Message autdelete time"), //based on 30 days per month
7776000: NSLocalizedString("3 months", comment:"Message autdelete time"), //based on 30 days per month
]

init() {
Expand Down
148 changes: 148 additions & 0 deletions Monal/Classes/LoginCredentials.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
//
// LoginCredentials.swift
// Monal
//
// Created by lissine on 2/11/2024.
// Copyright © 2024 monal-im.org. All rights reserved.
//

import SAMKeychain

struct LoginCredentials: View {
@Environment(\.presentationMode) var presentationMode
let accountID: NSNumber?
let jid: String
let resource: String
@State private var password: String
@State private var hardcodedServer: String
@State private var hardcodedPort: String
@State private var allowPlainAuth: Bool
@State private var forceDirectTLS: Bool

init(accountID: NSNumber?) {
self.accountID = accountID
guard accountID != nil,
let settings = DataLayer.sharedInstance().details(forAccount: accountID!) else {
self.jid = ""
self.resource = ""
self.hardcodedServer = ""
self.hardcodedPort = "5222"
self.allowPlainAuth = false
self.forceDirectTLS = false
self.password = ""
return
}

self.jid = "\(settings["username"]!)@\(settings["domain"]!)"
self.resource = settings["resource"] as? String ?? ""
_hardcodedServer = State(initialValue: settings["server"] as? String ?? "")
_hardcodedPort = State(initialValue: "\(settings["other_port"] ?? 5222)")
_allowPlainAuth = State(initialValue: settings["plain_activated"] as? Bool ?? false)
_forceDirectTLS = State(initialValue: settings["directTLS"] as? Bool ?? false)
_password = State(initialValue: SAMKeychain.password(forService: kMonalKeychainName, account: self.accountID!.stringValue) ?? "")
}

var body: some View {
Form {
Section(header: Text("")) {
HStack {
Text("XMPP ID")
Spacer()
Text(self.jid)
}
HStack {
Text("Password")
Spacer()
#if IS_QUICKSY
TextField("Password", text: $password)
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
#else
SecureField("Password", text: $password)
#endif
}
}

Section(header: Text("Advanced")) {
HStack {
Text("Server")
Spacer()
TextField("Optional Hardcoded Hostname", text: $hardcodedServer)
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
}

if !hardcodedServer.isEmpty {
HStack {
Text("Port")
Spacer()
TextField("Optional Hardcoded Port", text: $hardcodedPort)
.keyboardType(.numberPad)
.onDisappear {
hardcodedPort = "5222"
}
}

Toggle(isOn: $forceDirectTLS) {
Text("Always use direct TLS, not STARTTLS")
}
.multilineTextAlignment(.leading)
.onDisappear {
forceDirectTLS = false
}
}

Toggle(isOn: $allowPlainAuth) {
Text("Allow MITM-prone PLAIN authentication")
}
// The plain auth setting is read only, to prevent downgrades. TODO: allow upgrading this setting using the SCRAM preload list
.disabled(true)
.multilineTextAlignment(.leading)

HStack {
Text("Resource")
Spacer()
Text(self.resource)
}
}

}
.multilineTextAlignment(.trailing)
.navigationTitle("Login Credetials")
.navigationBarBackButtonHidden()
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Abort") {
self.presentationMode.wrappedValue.dismiss()
}
}
ToolbarItem(placement: .confirmationAction) {
Button("Done") {
guard accountID != nil else {
self.presentationMode.wrappedValue.dismiss()
return
}

var settings = DataLayer.sharedInstance().details(forAccount: accountID!) as! [String: Any]
settings["plain_activated"] = self.allowPlainAuth
settings["directTLS"] = self.forceDirectTLS
settings["server"] = self.hardcodedServer
settings["other_port"] = self.hardcodedPort
// Save the updated settings in the DB
DataLayer.sharedInstance().updateAccoun(with: settings)
// Save the password in the Keychain
if !self.password.isEmpty {
MLXMPPManager.sharedInstance().updatePassword(self.password, forAccount: self.accountID!)
}
self.presentationMode.wrappedValue.dismiss()

// Disconnect and reconnect so the new credentials / settings take effect
MLXMPPManager.sharedInstance().disconnectAccount(self.accountID!, withExplicitLogout: true)
MLXMPPManager.sharedInstance().connectAccount(self.accountID!)
}
// the jid can be empty if this view was somehow accessed while accountID is nil
.disabled(password.isEmpty || jid.isEmpty)
}
}
}
}
1 change: 1 addition & 0 deletions Monal/Classes/MLConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ static inline NSString* _Nonnull LocalizationNotNeeded(NSString* _Nonnull s)

#define kMonalRefresh @"kMonalRefresh"
#define kMonalContactRefresh @"kMonalContactRefresh"
#define kMonalAccountSettingsRefresh @"kMonalAccountSettingsRefresh"
#define kMonalXmppUserSoftWareVersionRefresh @"kMonalXmppUserSoftWareVersionRefresh"
#define kMonalBlockListRefresh @"kMonalBlockListRefresh"
#define kMonalContactRemoved @"kMonalContactRemoved"
Expand Down
16 changes: 0 additions & 16 deletions Monal/Classes/MLMAMPrefTableViewController.h

This file was deleted.

110 changes: 0 additions & 110 deletions Monal/Classes/MLMAMPrefTableViewController.m

This file was deleted.

31 changes: 31 additions & 0 deletions Monal/Classes/MLPubSubProcessor.m
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ @implementation MLPubSubProcessor
[[MLNotificationQueue currentQueue] postNotificationName:kMonalContactRefresh object:account userInfo:@{
@"contact": [MLContact createContactFromJid:jid andAccountID:account.accountID]
}];
if ([jid isEqualToString:account.connectionProperties.identity.jid])
{
[[MLNotificationQueue currentQueue] postNotificationName:kMonalAccountSettingsRefresh object:account userInfo:@{
@"accountID": account.accountID
}];
}
DDLogInfo(@"Avatar of '%@' fetched and updated successfully", jid);
}
else
Expand All @@ -184,6 +190,10 @@ @implementation MLPubSubProcessor
NSMutableDictionary* accountDic = [[NSMutableDictionary alloc] initWithDictionary:[[DataLayer sharedInstance] detailsForAccount:account.accountID] copyItems:YES];
accountDic[kRosterName] = [data[itemId] findFirst:@"{http://jabber.org/protocol/nick}nick#"];
[[DataLayer sharedInstance] updateAccounWithDictionary:accountDic];
//TODO: post a notification here so the view can refresh
[[MLNotificationQueue currentQueue] postNotificationName:kMonalAccountSettingsRefresh object:account userInfo:@{
@"accountID": account.accountID
}];
}
else //roster name of contact
{
Expand Down Expand Up @@ -211,6 +221,14 @@ @implementation MLPubSubProcessor
NSMutableDictionary* accountDic = [[NSMutableDictionary alloc] initWithDictionary:[[DataLayer sharedInstance] detailsForAccount:account.accountID] copyItems:NO];
accountDic[kRosterName] = @"";
[[DataLayer sharedInstance] updateAccounWithDictionary:accountDic];

//delete cache to make sure the image will be regenerated
[[MLImageManager sharedInstance] purgeCacheForContact:account.connectionProperties.identity.jid andAccount:account.accountID];
//TODO: post a notification here so the view can refresh
[[MLNotificationQueue currentQueue] postNotificationName:kMonalAccountSettingsRefresh object:account userInfo:@{
@"accountID": account.accountID
}];

}
else
{
Expand Down Expand Up @@ -777,6 +795,13 @@ @implementation MLPubSubProcessor
return;
}
DDLogDebug(@"Removed avatar from pep");

//delete cache to make sure the image will be regenerated
[[MLImageManager sharedInstance] purgeCacheForContact:account.connectionProperties.identity.jid andAccount:account.accountID];
//post notification
[[MLNotificationQueue currentQueue] postNotificationName:kMonalAccountSettingsRefresh object:account userInfo:@{
@"accountID": account.accountID
}];
$$

$$class_handler(avatarMetadataPublished, $$ID(xmpp*, account), $$BOOL(success), $_ID(XMPPIQ*, errorIq), $_ID(NSString*, errorReason))
Expand All @@ -787,6 +812,12 @@ @implementation MLPubSubProcessor
return;
}
DDLogDebug(@"Published avatar metadata to pep");
//delete cache to make sure the image will be regenerated
[[MLImageManager sharedInstance] purgeCacheForContact:account.connectionProperties.identity.jid andAccount:account.accountID];

//[[MLNotificationQueue currentQueue] postNotificationName:kMonalAccountSettingsRefresh object:account userInfo:@{
// @"accountID": account.accountID
//}];
$$

$$class_handler(avatarDataPublished, $$ID(xmpp*, account), $$BOOL(success), $_ID(XMPPIQ*, errorIq), $_ID(NSString*, errorReason), $$ID(NSString*, imageHash), $$UINTEGER(imageBytesLen))
Expand Down
Loading