refactor(@desktop/general): managing local settings added on the nim side

From now on we are able to access local settings (settings and global settings)
on the nim side, not only through the qml.

This change is required as part of the feature issue-2675.
This commit is contained in:
Sale Djenic 2021-09-13 13:50:24 +02:00 committed by Iuri Matias
parent 590e4dd632
commit e0c53b7012
12 changed files with 183 additions and 147 deletions

View File

@ -1,8 +1,8 @@
import NimQml, Tables, json, nimcrypto, strformat, json_serialization, chronicles import NimQml, Tables, json, nimcrypto, strformat, json_serialization, chronicles
import status/accounts as AccountModel import status/accounts as AccountModel
import status/types/[account, rpc_response] import status/types/[account, rpc_response]
import status/[status]
import ../onboarding/views/account_info import ../onboarding/views/account_info
import status/status
type type
AccountRoles {.pure.} = enum AccountRoles {.pure.} = enum
@ -46,6 +46,7 @@ QtObject:
keyUid: currNodeAcct.keyUid, keyUid: currNodeAcct.keyUid,
identityImage: currNodeAcct.identityImage identityImage: currNodeAcct.identityImage
)) ))
self.status.events.emit("currentAccountUpdated", AccountArgs(account: currNodeAcct))
QtProperty[QVariant] currentAccount: QtProperty[QVariant] currentAccount:
read = getCurrentAccount read = getCurrentAccount

View File

@ -35,6 +35,9 @@ proc delete*(self: ProfileController) =
delete self.variant delete self.variant
delete self.view delete self.view
proc setSettingsFile*(self: ProfileController, username: string) =
self.view.setSettingsFile(username)
proc init*(self: ProfileController, account: Account) = proc init*(self: ProfileController, account: Account) =
let profile = account.toProfileModel() let profile = account.toProfileModel()

View File

@ -1,5 +1,5 @@
import NimQml, sequtils, strutils, sugar, os, json, chronicles import NimQml, sequtils, strutils, sugar, os, json, chronicles
import views/[mailservers_list, ens_manager, contacts, devices, mailservers, mnemonic, network, fleets, profile_info, device_list, dapp_list, profile_picture, profile_settings, muted_chats] import views/[mailservers_list, ens_manager, contacts, devices, mailservers, mnemonic, network, fleets, profile_info, device_list, dapp_list, profile_picture, muted_chats]
import chronicles import chronicles
import ../chat/views/channels_list import ../chat/views/channels_list
import status/statusgo_backend/accounts as status_accounts import status/statusgo_backend/accounts as status_accounts
@ -23,7 +23,6 @@ QtObject:
type ProfileView* = ref object of QObject type ProfileView* = ref object of QObject
profile*: ProfileInfoView profile*: ProfileInfoView
profilePicture*: ProfilePictureView profilePicture*: ProfilePictureView
profileSettings*: ProfileSettingsView
mutedChats*: MutedChatsView mutedChats*: MutedChatsView
contacts*: ContactsView contacts*: ContactsView
devices*: DevicesView devices*: DevicesView
@ -45,7 +44,6 @@ QtObject:
if not self.devices.isNil: self.devices.delete if not self.devices.isNil: self.devices.delete
if not self.ens.isNil: self.ens.delete if not self.ens.isNil: self.ens.delete
if not self.profilePicture.isNil: self.profilePicture.delete if not self.profilePicture.isNil: self.profilePicture.delete
if not self.profileSettings.isNil: self.profileSettings.delete
if not self.mutedChats.isNil: self.mutedChats.delete if not self.mutedChats.isNil: self.mutedChats.delete
if not self.profile.isNil: self.profile.delete if not self.profile.isNil: self.profile.delete
if not self.dappList.isNil: self.dappList.delete if not self.dappList.isNil: self.dappList.delete
@ -60,7 +58,6 @@ QtObject:
result = ProfileView() result = ProfileView()
result.profile = newProfileInfoView() result.profile = newProfileInfoView()
result.profilePicture = newProfilePictureView(status, result.profile) result.profilePicture = newProfilePictureView(status, result.profile)
result.profileSettings = newProfileSettingsView(status, result.profile)
result.mutedChats = newMutedChatsView(status) result.mutedChats = newMutedChatsView(status)
result.contacts = newContactsView(status, appService) result.contacts = newContactsView(status, appService)
result.devices = newDevicesView(status) result.devices = newDevicesView(status)
@ -84,7 +81,6 @@ QtObject:
proc setNewProfile*(self: ProfileView, profile: Profile) = proc setNewProfile*(self: ProfileView, profile: Profile) =
self.profile.setProfile(profile) self.profile.setProfile(profile)
self.profileSettings.removeUnknownAccountSettings()
self.profileChanged() self.profileChanged()
QtProperty[QVariant] profile: QtProperty[QVariant] profile:
@ -186,11 +182,28 @@ QtObject:
QtProperty[QVariant] picture: QtProperty[QVariant] picture:
read = getProfilePicture read = getProfilePicture
proc getProfileSettings*(self: ProfileView): QVariant {.slot.} = proc settingsFileChanged*(self: ProfileView) {.signal.}
newQVariant(self.profileSettings)
proc getSettingsFile*(self: ProfileView): string {.slot.} =
self.appService.localSettingsService.getSettingsFilePath
proc setSettingsFile*(self: ProfileView, username: string) =
if(username.len == 0 or
self.appService.localSettingsService.getSettingsFilePath.endsWith(username)):
return
QtProperty[QVariant] settings: self.appService.localSettingsService.updateSettingsFilePath(username)
read = getProfileSettings self.settingsFileChanged()
QtProperty[string] settingsFile:
read = getSettingsFile
notify = settingsFileChanged
proc getGlobalSettingsFile*(self: ProfileView): string {.slot.} =
self.appService.localSettingsService.getGlobalSettingsFilePath
QtProperty[string] globalSettingsFile:
read = getGlobalSettingsFile
proc getMutedChats*(self: ProfileView): QVariant {.slot.} = proc getMutedChats*(self: ProfileView): QVariant {.slot.} =
newQVariant(self.mutedChats) newQVariant(self.mutedChats)

View File

@ -1,61 +0,0 @@
import NimQml, os
import chronicles
import profile_info
import status/status
import ../../../constants
logScope:
topics = "profile-settings-view"
const UNKNOWN_ACCOUNT = "unknownAccount"
QtObject:
type ProfileSettingsView* = ref object of QObject
status*: Status
profile*: ProfileInfoView
proc setup(self: ProfileSettingsView) =
self.QObject.setup
proc delete*(self: ProfileSettingsView) =
self.QObject.delete
proc newProfileSettingsView*(status: Status, profile: ProfileInfoView): ProfileSettingsView =
new(result, delete)
result.status = status
result.profile = profile
result.setup
proc settingsFileChanged*(self: ProfileSettingsView) {.signal.}
proc getSettingsFile(self: ProfileSettingsView): string {.slot.} =
let pubkey =
if (self.profile.pubKey == ""):
UNKNOWN_ACCOUNT
else:
self.profile.pubKey
return os.joinPath(DATADIR, "qt", pubkey)
QtProperty[string] settingsFile:
read = getSettingsFile
notify = settingsFileChanged
proc getGlobalSettingsFile(self: ProfileSettingsView): string {.slot.} =
return os.joinPath(DATADIR, "qt", "global")
proc globalSettingsFileChanged*(self: ProfileSettingsView) {.signal.}
QtProperty[string] globalSettingsFile:
read = getGlobalSettingsFile
notify = globalSettingsFileChanged
proc removeUnknownAccountSettings*(self: ProfileSettingsView) =
# Remove old 'unknownAccount' settings file if it was created
self.settingsFileChanged()
let unknownSettingsPath = os.joinPath(DATADIR, "qt", UNKNOWN_ACCOUNT)
if (not unknownSettingsPath.tryRemoveFile):
# Only fails if the file exists and an there was an error removing it
# More info: https://nim-lang.org/docs/os.html#tryRemoveFile%2Cstring
warn "Failed to remove unused settings file", file=unknownSettingsPath

View File

@ -6,12 +6,13 @@ import
./tasks/threadpool, ./tasks/threadpool,
./signals/signal_controller ./signals/signal_controller
import service/local_settings/service as local_settings_service
import service/os_notification/service as os_notification_service import service/os_notification/service as os_notification_service
import async_service/chat/service as chat_async_service import async_service/chat/service as chat_async_service
import async_service/wallet/service as wallet_async_service import async_service/wallet/service as wallet_async_service
export marathon, task_runner, signal_controller export marathon, task_runner, signal_controller
export os_notification_service export local_settings_service, os_notification_service
export chat_async_service, wallet_async_service export chat_async_service, wallet_async_service
logScope: logScope:
@ -23,6 +24,7 @@ type AppService* = ref object
marathon*: Marathon marathon*: Marathon
signalController*: SignalsController signalController*: SignalsController
# services # services
localSettingsService*: LocalSettingsService
osNotificationService*: OsNotificationService osNotificationService*: OsNotificationService
# async services # async services
chatService*: ChatService chatService*: ChatService
@ -33,6 +35,7 @@ proc newAppService*(status: Status, worker: MarathonWorker): AppService =
result.threadpool = newThreadPool() result.threadpool = newThreadPool()
result.marathon = newMarathon(worker) result.marathon = newMarathon(worker)
result.signalController = newSignalsController(status) result.signalController = newSignalsController(status)
result.localSettingsService = newLocalSettingsService()
result.osNotificationService = newOsNotificationService(status) result.osNotificationService = newOsNotificationService(status)
result.chatService = newChatService(status, result.threadpool) result.chatService = newChatService(status, result.threadpool)
result.walletService = newWalletService(status, result.threadpool) result.walletService = newWalletService(status, result.threadpool)
@ -41,6 +44,7 @@ proc delete*(self: AppService) =
self.threadpool.teardown() self.threadpool.teardown()
self.marathon.teardown() self.marathon.teardown()
self.signalController.delete() self.signalController.delete()
self.localSettingsService.delete()
self.osNotificationService.delete() self.osNotificationService.delete()
self.chatService.delete() self.chatService.delete()
self.walletService.delete() self.walletService.delete()

View File

@ -0,0 +1,73 @@
import NimQml, os, chronicles
import ../../../constants
# Local Settings keys:
const LS_KEY_STORE_TO_KEYCHAIN* = "storeToKeychain"
# Local Settings values:
const LS_VALUE_STORE* = "store"
const UNKNOWN_ACCOUNT = "unknownAccount"
logScope:
topics = "local-settings"
QtObject:
type LocalSettingsService* = ref object of QObject
settingsFilePath: string
settings: QSettings
globalSettingsFilePath: string
globalSettings: QSettings
proc setup(self: LocalSettingsService) =
self.settingsFilePath = os.joinPath(DATADIR, "qt", UNKNOWN_ACCOUNT)
self.settings = newQSettings(self.settingsFilePath, QSettingsFormat.IniFormat)
self.globalSettingsFilePath = os.joinPath(DATADIR, "qt", "global")
self.globalSettings = newQSettings(self.globalSettingsFilePath, QSettingsFormat.IniFormat)
self.QObject.setup
proc delete*(self: LocalSettingsService) =
self.settings.delete
self.globalSettings.delete
self.QObject.delete
proc newLocalSettingsService*(): LocalSettingsService =
new(result, delete)
result.setup
proc getGlobalSettingsFilePath*(self: LocalSettingsService): string =
return self.globalSettingsFilePath
proc getSettingsFilePath*(self: LocalSettingsService): string =
return self.settingsFilePath
proc updateSettingsFilePath*(self: LocalSettingsService, username: string) =
if (username.len > 0):
let unknownSettingsPath = os.joinPath(DATADIR, "qt", UNKNOWN_ACCOUNT)
if (not unknownSettingsPath.tryRemoveFile):
# Only fails if the file exists and an there was an error removing it
# More info: https://nim-lang.org/docs/os.html#tryRemoveFile%2Cstring
warn "Failed to remove unused settings file", file=unknownSettingsPath
self.settings.delete
self.settingsFilePath = os.joinPath(DATADIR, "qt", username)
self.settings = newQSettings(self.settingsFilePath, QSettingsFormat.IniFormat)
proc setValue*(self: LocalSettingsService, key: string, value: QVariant) =
self.settings.setValue(key, value)
proc getValue*(self: LocalSettingsService, key: string,
defaultValue: QVariant = newQVariant()): QVariant =
self.settings.value(key, defaultValue)
proc removeValue*(self: LocalSettingsService, key: string) =
self.settings.remove(key)
proc setGlobalValue*(self: LocalSettingsService, key: string, value: QVariant) =
self.globalSettings.setValue(key, value)
proc getGlobalValue*(self: LocalSettingsService, key: string,
defaultValue: QVariant = newQVariant()): QVariant =
self.globalSettings.value(key, defaultValue)
proc removeGlobalValue*(self: LocalSettingsService, key: string) =
self.globalSettings.remove(key)

View File

@ -10,12 +10,12 @@ logScope:
QtObject: QtObject:
type OsNotificationService* = ref object of QObject type OsNotificationService* = ref object of QObject
status: Status status: Status
notification: StatusOSNotificationObject notification: StatusOSNotification
proc setup(self: OsNotificationService, status: Status) = proc setup(self: OsNotificationService, status: Status) =
self.QObject.setup self.QObject.setup
self.status = status self.status = status
self.notification = newStatusOSNotificationObject() self.notification = newStatusOSNotification()
signalConnect(self.notification, "notificationClicked(QString)", self, signalConnect(self.notification, "notificationClicked(QString)", self,
"onNotificationClicked(QString)", 2) "onNotificationClicked(QString)", 2)

View File

@ -186,7 +186,7 @@ proc mainProc() =
defer: provider.delete() defer: provider.delete()
engine.setRootContextProperty("web3Provider", provider.variant) engine.setRootContextProperty("web3Provider", provider.variant)
var login = login.newController(status) var login = login.newController(status, appService)
defer: login.delete() defer: login.delete()
var onboarding = onboarding.newController(status) var onboarding = onboarding.newController(status)
defer: onboarding.delete() defer: onboarding.delete()
@ -204,9 +204,17 @@ proc mainProc() =
onboarding.moveToAppState() onboarding.moveToAppState()
status.events.emit("loginCompleted", args) status.events.emit("loginCompleted", args)
proc updateProfileSettings(account: Account) =
profile.setSettingsFile(account.name)
status.events.on("currentAccountUpdated") do(a: Args):
var args = AccountArgs(a)
updateProfileSettings(args.account)
status.events.once("loginCompleted") do(a: Args): status.events.once("loginCompleted") do(a: Args):
var args = AccountArgs(a) var args = AccountArgs(a)
updateProfileSettings(args.account)
status.startMessenger() status.startMessenger()
profile.init(args.account) profile.init(args.account)
wallet.init() wallet.init()

View File

@ -27,7 +27,6 @@ Item {
id: appMain id: appMain
anchors.fill: parent anchors.fill: parent
property alias appSettings: appSettings
property alias appLayout: appLayout property alias appLayout: appLayout
property var newVersionJSON: JSON.parse(utilsModel.newVersion) property var newVersionJSON: JSON.parse(utilsModel.newVersion)
property bool profilePopupOpened: false property bool profilePopupOpened: false
@ -149,67 +148,6 @@ Item {
} }
} }
Settings {
id: appSettings
fileName: profileModel.settings.settingsFile
property var chatSplitView
property var walletSplitView
property var profileSplitView
property bool communitiesEnabled: false
property bool isWalletEnabled: false
property bool isWalletV2Enabled: false
property bool nodeManagementEnabled: false
property bool isBrowserEnabled: false
property bool isActivityCenterEnabled: false
property bool showOnlineUsers: false
property bool expandUsersList: false
property bool isGifWidgetEnabled: false
property bool isTenorWarningAccepted: false
property bool displayChatImages: false
property bool useCompactMode: true
property bool timelineEnabled: true
property var recentEmojis: []
property var hiddenCommunityWelcomeBanners: []
property var hiddenCommunityBackUpBanners: []
property real volume: 0.2
property int notificationSetting: Constants.notifyAllMessages
property bool notificationSoundsEnabled: true
property bool useOSNotifications: true
property int notificationMessagePreviewSetting: Constants.notificationPreviewNameAndMessage
property bool notifyOnNewRequests: true
property var whitelistedUnfurlingSites: ({})
property bool neverAskAboutUnfurlingAgain: false
property bool hideChannelSuggestions: false
property int fontSize: Constants.fontSizeM
property bool hideSignPhraseModal: false
property bool onlyShowContactsProfilePics: true
property bool quitOnClose: false
property string skinColor: ""
property bool showDeleteMessageWarning: true
property bool downloadChannelMessagesEnabled: false
// Browser settings
property bool showBrowserSelector: true
property bool openLinksInStatus: true
property bool shouldShowFavoritesBar: true
property string browserHomepage: ""
property int shouldShowBrowserSearchEngine: Constants.browserSearchEngineDuckDuckGo
property int useBrowserEthereumExplorer: Constants.browserEthereumExplorerEtherscan
property bool autoLoadImages: true
property bool javaScriptEnabled: true
property bool errorPageEnabled: true
property bool pluginsEnabled: true
property bool autoLoadIconsForPage: true
property bool touchIconsEnabled: true
property bool webRTCPublicInterfacesOnly: false
property bool devToolsEnabled: false
property bool pdfViewerEnabled: true
property bool compatibilityMode: true
// Ropsten settings
property bool stickersEnsRopsten: false
}
ErrorSound { ErrorSound {
id: errorSound id: errorSound
} }
@ -562,10 +500,8 @@ Item {
Connections { Connections {
target: profileModel.settings target: profileModel
onGlobalSettingsFileChanged: {
profileModel.changeLocale(globalSettings.locale)
}
onSettingsFileChanged: { onSettingsFileChanged: {
// Since https://github.com/status-im/status-desktop/commit/93668ff75 // Since https://github.com/status-im/status-desktop/commit/93668ff75
// we're hiding the setting to change appearance for compact normal mode // we're hiding the setting to change appearance for compact normal mode

View File

@ -29,7 +29,7 @@ StatusWindow {
Settings { Settings {
id: globalSettings id: globalSettings
category: "global" category: "global"
fileName: profileModel.settings.globalSettingsFile fileName: profileModel.globalSettingsFile
property string locale: "en" property string locale: "en"
property int theme: 2 property int theme: 2
@ -38,6 +38,66 @@ StatusWindow {
} }
} }
Settings {
id: appSettings
fileName: profileModel.settingsFile
property var chatSplitView
property var walletSplitView
property var profileSplitView
property bool communitiesEnabled: false
property bool isWalletEnabled: false
property bool isWalletV2Enabled: false
property bool nodeManagementEnabled: false
property bool isBrowserEnabled: false
property bool isActivityCenterEnabled: false
property bool showOnlineUsers: false
property bool isGifWidgetEnabled: false
property bool isTenorWarningAccepted: false
property bool displayChatImages: false
property bool useCompactMode: true
property bool timelineEnabled: true
property var recentEmojis: []
property var hiddenCommunityWelcomeBanners: []
property var hiddenCommunityBackUpBanners: []
property real volume: 0.2
property int notificationSetting: Constants.notifyAllMessages
property bool notificationSoundsEnabled: true
property bool useOSNotifications: true
property int notificationMessagePreviewSetting: Constants.notificationPreviewNameAndMessage
property bool notifyOnNewRequests: true
property var whitelistedUnfurlingSites: ({})
property bool neverAskAboutUnfurlingAgain: false
property bool hideChannelSuggestions: false
property int fontSize: Constants.fontSizeM
property bool hideSignPhraseModal: false
property bool onlyShowContactsProfilePics: true
property bool quitOnClose: false
property string skinColor: ""
property bool showDeleteMessageWarning: true
// Browser settings
property bool showBrowserSelector: true
property bool openLinksInStatus: true
property bool shouldShowFavoritesBar: true
property string browserHomepage: ""
property int shouldShowBrowserSearchEngine: Constants.browserSearchEngineDuckDuckGo
property int useBrowserEthereumExplorer: Constants.browserEthereumExplorerEtherscan
property bool autoLoadImages: true
property bool javaScriptEnabled: true
property bool errorPageEnabled: true
property bool pluginsEnabled: true
property bool autoLoadIconsForPage: true
property bool touchIconsEnabled: true
property bool webRTCPublicInterfacesOnly: false
property bool devToolsEnabled: false
property bool pdfViewerEnabled: true
property bool compatibilityMode: true
// Ropsten settings
property bool stickersEnsRopsten: false
}
id: applicationWindow id: applicationWindow
objectName: "mainWindow" objectName: "mainWindow"
minimumWidth: 900 minimumWidth: 900
@ -102,7 +162,7 @@ StatusWindow {
close.accepted = false close.accepted = false
} }
else if (loader.sourceComponent == app) { else if (loader.sourceComponent == app) {
if (loader.item.appSettings.quitOnClose) { if (appSettings.quitOnClose) {
close.accepted = true close.accepted = true
} else { } else {
applicationWindow.visible = false applicationWindow.visible = false
@ -310,7 +370,6 @@ StatusWindow {
Loader { Loader {
id: loader id: loader
anchors.fill: parent anchors.fill: parent
property var appSettings
} }
DropArea { DropArea {
@ -470,7 +529,7 @@ StatusWindow {
Qt.quit(); Qt.quit();
} }
else if (loader.sourceComponent == app) { else if (loader.sourceComponent == app) {
if (loader.item.appSettings.quitOnClose) { if (appSettings.quitOnClose) {
Qt.quit(); Qt.quit();
} else { } else {
applicationWindow.visible = false; applicationWindow.visible = false;

2
vendor/DOtherSide vendored

@ -1 +1 @@
Subproject commit 0bebd4cc2a67ed3c42f0615450cc0de86c790915 Subproject commit 0f8ed95fc7a47e4d3efb218ef961d36e60610cb3

2
vendor/nimqml vendored

@ -1 +1 @@
Subproject commit ca381eb8a20cf02f712a423f85b22901e14fa982 Subproject commit 00ee27ca52bcf5216c0de0e19e594ddfc1790452