fix(@desktop/settings): content on the right side for all subsections need to have the same geometry

Structure of the all subsection of the settings section has the same
high level structure

Fixes #5650
This commit is contained in:
Sale Djenic 2022-05-07 13:45:15 +02:00 committed by saledjenic
parent 2046eb0e4b
commit 2904018173
25 changed files with 1672 additions and 1609 deletions

View File

@ -10,6 +10,7 @@ import "popups"
import "views"
import StatusQ.Layout 0.1
import StatusQ.Controls 0.1
StatusAppTwoPanelLayout {
id: profileView
@ -24,10 +25,14 @@ StatusAppTwoPanelLayout {
}
QtObject {
id: _internal
readonly property int contentMaxWidth: 624
readonly property int contentMinWidth: 450
property int profileContentWidth: Math.max(contentMinWidth, Math.min(profileContainer.width * 0.8, contentMaxWidth))
id: d
readonly property int topMargin: 0
readonly property int bottomMargin: 56
readonly property int leftMargin: 48
readonly property int rightMargin: 48
readonly property int contentWidth: 560
}
leftPanel: LeftTabView {
@ -36,100 +41,194 @@ StatusAppTwoPanelLayout {
anchors.fill: parent
}
rightPanel: StackLayout {
id: profileContainer
rightPanel: Item {
anchors.fill: parent
currentIndex: Global.settingsSubsection
onCurrentIndexChanged: {
if(visibleChildren[0] === ensContainer){
ensContainer.goToStart();
StatusBanner {
id: banner
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
visible: profileContainer.currentIndex === Constants.settingsSubsection.wallet &&
profileView.store.walletStore.areTestNetworksEnabled
type: StatusBanner.Type.Danger
statusText: {
if(profileContainer.currentIndex === Constants.settingsSubsection.wallet &&
profileView.store.walletStore.areTestNetworksEnabled)
return qsTr("Testnet mode is enabled. All balances, transactions and dApp interactions will be on testnets.")
return ""
}
}
MyProfileView {
Layout.fillWidth: true
Layout.fillHeight: true
StackLayout {
id: profileContainer
profileStore: profileView.store.profileStore
profileContentWidth: _internal.profileContentWidth
}
anchors.top: banner.visible? banner.bottom : parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.topMargin: d.topMargin
anchors.bottomMargin: d.bottomMargin
anchors.leftMargin: d.leftMargin
anchors.rightMargin: d.rightMargin
ContactsView {
contactsStore: profileView.store.contactsStore
profileContentWidth: _internal.profileContentWidth
}
currentIndex: Global.settingsSubsection
EnsView {
id: ensContainer
ensUsernamesStore: profileView.store.ensUsernamesStore
contactsStore: profileView.store.contactsStore
stickersStore: profileView.store.stickersStore
profileContentWidth: _internal.profileContentWidth
}
onCurrentIndexChanged: {
if(visibleChildren[0] === ensContainer){
ensContainer.goToStart();
}
}
MessagingView {
id: messagingView
messagingStore: profileView.store.messagingStore
profileContentWidth: _internal.profileContentWidth
}
MyProfileView {
Layout.fillWidth: true
Layout.fillHeight: true
WalletView {
id: walletView
walletStore: profileView.store.walletStore
emojiPopup: profileView.emojiPopup
}
profileStore: profileView.store.profileStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.profile)
contentWidth: d.contentWidth
}
PrivacyView {
privacyStore: profileView.store.privacyStore
profileContentWidth: _internal.profileContentWidth
}
ContactsView {
Layout.fillWidth: true
Layout.fillHeight: true
AppearanceView {
appearanceStore: profileView.store.appearanceStore
profileContentWidth: _internal.profileContentWidth
systemPalette: profileView.systemPalette
}
contactsStore: profileView.store.contactsStore
sectionTitle: qsTr("Contacts")
contentWidth: d.contentWidth
SoundsView {
profileContentWidth: _internal.profileContentWidth
}
backButtonName: profileView.store.getNameForSubsection(Constants.settingsSubsection.messaging)
LanguageView {
languageStore: profileView.store.languageStore
currencyStore: profileView.store.walletStore.currencyStore
profileContentWidth: _internal.profileContentWidth
}
onBackButtonClicked: {
Global.changeAppSectionBySectionType(Constants.appSection.profile, Constants.settingsSubsection.messaging)
}
}
NotificationsView {
notificationsStore: profileView.store.notificationsStore
profileContentWidth: _internal.profileContentWidth
}
EnsView {
// TODO: we need to align structure for the entire this part using `SettingsContentBase` as root component
DevicesView {
devicesStore: profileView.store.devicesStore
}
// TODO: handle structure for this subsection to match style used in onther sections
// using `SettingsContentBase` component as base.
id: ensContainer
Layout.fillWidth: true
Layout.fillHeight: true
BrowserView {
store: profileView.store
profileContentWidth: _internal.profileContentWidth
}
ensUsernamesStore: profileView.store.ensUsernamesStore
contactsStore: profileView.store.contactsStore
stickersStore: profileView.store.stickersStore
AdvancedView {
advancedStore: profileView.store.advancedStore
profileContentWidth: _internal.profileContentWidth
}
profileContentWidth: d.contentWidth
}
HelpView {
profileContentWidth: _internal.profileContentWidth
}
MessagingView {
Layout.fillWidth: true
Layout.fillHeight: true
AboutView {
store: profileView.store
globalStore: profileView.globalStore
profileContentWidth: _internal.profileContentWidth
messagingStore: profileView.store.messagingStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.messaging)
contentWidth: d.contentWidth
}
WalletView {
Layout.fillWidth: true
Layout.fillHeight: true
walletStore: profileView.store.walletStore
emojiPopup: profileView.emojiPopup
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.wallet)
contentWidth: d.contentWidth
}
PrivacyView {
Layout.fillWidth: true
Layout.fillHeight: true
privacyStore: profileView.store.privacyStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.privacyAndSecurity)
contentWidth: d.contentWidth
}
AppearanceView {
Layout.fillWidth: true
Layout.fillHeight: true
appearanceStore: profileView.store.appearanceStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.appearance)
contentWidth: d.contentWidth
systemPalette: profileView.systemPalette
}
SoundsView {
Layout.fillWidth: true
Layout.fillHeight: true
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.sound)
contentWidth: d.contentWidth
}
LanguageView {
Layout.fillWidth: true
Layout.fillHeight: true
languageStore: profileView.store.languageStore
currencyStore: profileView.store.walletStore.currencyStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.language)
contentWidth: d.contentWidth
}
NotificationsView {
Layout.fillWidth: true
Layout.fillHeight: true
notificationsStore: profileView.store.notificationsStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.notifications)
contentWidth: d.contentWidth
}
DevicesView {
Layout.fillWidth: true
Layout.fillHeight: true
devicesStore: profileView.store.devicesStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.devicesSettings)
contentWidth: d.contentWidth
}
BrowserView {
Layout.fillWidth: true
Layout.fillHeight: true
store: profileView.store
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.browserSettings)
contentWidth: d.contentWidth
}
AdvancedView {
Layout.fillWidth: true
Layout.fillHeight: true
advancedStore: profileView.store.advancedStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.advanced)
contentWidth: d.contentWidth
}
HelpView {
Layout.fillWidth: true
Layout.fillHeight: true
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.needHelp)
contentWidth: d.contentWidth
}
AboutView {
Layout.fillWidth: true
Layout.fillHeight: true
store: profileView.store
globalStore: profileView.globalStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.about)
contentWidth: d.contentWidth
}
}
}
}

View File

@ -1,15 +1,16 @@
import utils 1.0
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
StatusListItem {
property var network
title: network.chainName
icon.isLetterIdenticon: true
width: parent.width
leftPadding: 0
rightPadding: 0
leftPadding: Style.current.padding
rightPadding: Style.current.padding
components: [
StatusIcon {
icon: "chevron-down"
@ -17,4 +18,4 @@ StatusListItem {
color: Theme.palette.baseColor1
}
]
}
}

View File

@ -36,6 +36,7 @@ Item {
id: title
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
visible: contactListRoot.title !== ""
text: contactListRoot.title
font.weight: Font.Medium

View File

@ -139,4 +139,33 @@ QtObject {
function checkForUpdates() {
aboutModuleInst.checkForUpdates()
}
function getNameForSubsection(subsection) {
let i = 0;
for (; i < mainMenuItems.count; i++) {
let elem = mainMenuItems.get(i)
if(elem.subsection === subsection)
return elem.text
}
for (i=0; i < appsMenuItems.count; i++) {
let elem = appsMenuItems.get(i)
if(elem.subsection === subsection)
return elem.text
}
for (i=0; i < settingsMenuItems.count; i++) {
let elem = settingsMenuItems.get(i)
if(elem.subsection === subsection)
return elem.text
}
for (i=0; i < extraMenuItems.count; i++) {
let elem = extraMenuItems.get(i)
if(elem.subsection === subsection)
return elem.text
}
return ""
}
}

View File

@ -10,26 +10,21 @@ import utils 1.0
import shared 1.0
import shared.status 1.0
Item {
SettingsContentBase {
id: root
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
property var store
property var globalStore
property int profileContentWidth
Column {
id: generalColumn
spacing: Style.current.bigPadding
anchors.top: parent.top
anchors.topMargin: 46
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
ColumnLayout {
spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth
// TODO: replace with StatusListItem
StatusSectionDescItem {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "App version"
name: qsTrId("version")
//% "Version: %1"
@ -40,6 +35,9 @@ Item {
// TODO: replace with StatusListItem
StatusSectionDescItem {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Node version "
name: qsTrId("node-version-")
description: root.store.nodeVersion()
@ -47,16 +45,20 @@ Item {
}
StatusFlatButton {
Layout.fillWidth: true
leftPadding: Style.current.padding
rightPadding: Style.current.padding
//% "Check for updates"
text: qsTrId("check-for-updates")
loading: root.store.fetchingUpdate
onClicked: root.store.checkForUpdates()
icon.width: 0
anchors.left: parent.left
anchors.leftMargin: -leftPadding
}
StatusBaseText {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Privacy Policy"
text: qsTrId("privacy-policy")
font.pixelSize: 15

View File

@ -14,33 +14,26 @@ import "../controls"
import "../popups"
import "../panels"
ScrollView {
SettingsContentBase {
id: root
property int profileContentWidth
height: parent.height
width: parent.width
contentHeight: advancedContainer.height + 100
clip: true
property AdvancedStore advancedStore
Item {
id: advancedContainer
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
width: root.contentWidth
height: generalColumn.height
Column {
id: generalColumn
anchors.top: parent.top
anchors.topMargin: 64
anchors.left: parent.left
anchors.right: parent.right
width: root.contentWidth
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Network"
text: qsTrId("network")
visible: !localAccountSensitiveSettings.isMultiNetworkEnabled
@ -50,6 +43,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Fleet"
text: qsTrId("fleet")
currentValue: root.advancedStore.fleet
@ -58,6 +53,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Minimize on close"
text: qsTrId("minimize-on-close")
isSwitch: true
@ -69,6 +66,10 @@ ScrollView {
// TODO: replace with StatusQ component
StyledText {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
//% "Application Logs"
text: qsTr("Application Logs")
font.pixelSize: 15
@ -94,14 +95,14 @@ ScrollView {
}
Separator {
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
width: parent.width
}
StatusSectionHeadline {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
//% "Experimental features"
text: qsTrId("experimental-features")
topPadding: Style.current.bigPadding
@ -110,6 +111,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Wallet"
text: qsTrId("wallet")
isSwitch: true
@ -126,6 +129,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Dapp Browser"
text: qsTrId("dapp-browser")
isSwitch: true
@ -142,6 +147,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Communities"
text: qsTrId("communities")
isSwitch: true
@ -157,6 +164,8 @@ ScrollView {
}
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Communities"
text: qsTrId("Community History Archive Protocol")
isSwitch: true
@ -173,6 +182,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Activity Center"
text: qsTrId("activity-center")
isSwitch: true
@ -189,6 +200,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Node Management"
text: qsTrId("node-management")
isSwitch: true
@ -205,6 +218,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Multi network")
isSwitch: true
switchChecked: localAccountSensitiveSettings.isMultiNetworkEnabled
@ -220,6 +235,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Keycard"
text: qsTr("Keycard")
isSwitch: true
@ -230,6 +247,10 @@ ScrollView {
}
StatusSectionHeadline {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
visible: !root.advancedStore.isWakuV2
//% "Bloom filter level"
text: qsTrId("bloom-filter-level")
@ -238,6 +259,10 @@ ScrollView {
}
Row {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
visible: !root.advancedStore.isWakuV2
spacing: 11
@ -316,6 +341,10 @@ ScrollView {
}
StatusSectionHeadline {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
visible: root.advancedStore.isWakuV2
text: qsTr("WakuV2 mode")
topPadding: Style.current.bigPadding
@ -323,6 +352,10 @@ ScrollView {
}
Row {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
spacing: 11
visible: root.advancedStore.isWakuV2
Component {
@ -382,21 +415,23 @@ ScrollView {
}
}
StatusSectionHeadline {
StatusSectionHeadline {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
text: qsTr("Developer features")
topPadding: Style.current.bigPadding
bottomPadding: Style.current.padding
}
Separator {
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
width: parent.width
}
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Full developer mode")
isEnabled: {
return !localAccountSensitiveSettings.downloadChannelMessagesEnabled ||
@ -410,15 +445,13 @@ ScrollView {
}
Separator {
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
width: parent.width
}
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Download messages")
isSwitch: true
switchChecked: localAccountSensitiveSettings.downloadChannelMessagesEnabled
@ -429,6 +462,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Telemetry")
isSwitch: true
switchChecked: root.advancedStore.isTelemetryEnabled
@ -439,6 +474,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Debug")
isSwitch: true
switchChecked: root.advancedStore.isDebugEnabled
@ -449,6 +486,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Auto message")
isSwitch: true
switchChecked: root.advancedStore.isAutoMessageEnabled
@ -459,6 +498,8 @@ ScrollView {
// TODO: replace with StatusQ component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Stickers/ENS on ropsten")
visible: root.advancedStore.currentNetworkId === Constants.networkRopsten
isSwitch: true

View File

@ -16,17 +16,12 @@ import StatusQ.Controls 0.1 as StatusQ
import "../popups"
import "../stores"
ScrollView {
SettingsContentBase {
id: appearanceView
height: parent.height
width: parent.width
contentHeight: appearanceContainer.height
clip: true
property AppearanceStore appearanceStore
property var systemPalette
property int profileContentWidth
enum Theme {
Light,
@ -49,9 +44,9 @@ ScrollView {
Item {
id: appearanceContainer
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
width: appearanceView.contentWidth - 2 * Style.current.padding
height: this.childrenRect.height + 100
ButtonGroup {
@ -69,6 +64,7 @@ ScrollView {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 0
}
Rectangle {
@ -76,9 +72,7 @@ ScrollView {
anchors.top: sectionHeadlinePreview.bottom
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
height: paceholderMessage.height + Style.current.padding*4
radius: Style.current.radius
border.color: Style.current.border
@ -313,9 +307,7 @@ ScrollView {
anchors.top: sectionHeadlineAppearance.bottom
anchors.topMargin: Style.current.padding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
StatusImageRadioButton {
padding: Style.current.smallPadding

View File

@ -17,52 +17,38 @@ import "../stores"
import "browser"
import "wallet"
ScrollView {
SettingsContentBase {
id: root
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
property ProfileSectionStore store
property real profileContentWidth
property Component searchEngineModal: SearchEngineModal {}
contentHeight: rootItem.height
Item {
id: rootItem
width: parent.width
width: root.contentWidth
height: childrenRect.height
Column {
id: layout
anchors.top: parent.top
anchors.topMargin: 24
anchors.left: parent.left
anchors.leftMargin: 48
width: profileContentWidth
width: parent.width
spacing: 10
StatusBaseText {
id: titleText
text: qsTr("Browser")
font.weight: Font.Bold
font.pixelSize: 28
color: Theme.palette.directColor1
}
Item {
height: 25
width: 1
}
HomePageView {
id: homePageView
homepage: localAccountSensitiveSettings.browserHomepage
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
}
// TODO: Replace with StatusQ StatusListItem component
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Search engine used in the address bar"
text: qsTrId("search-engine-used-in-the-address-bar")
currentValue: {
@ -80,12 +66,15 @@ ScrollView {
DefaultDAppExplorerView {
id: dAppExplorerView
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
}
StatusListItem {
id: showFavouritesItem
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width + Style.current.padding * 2
width: parent.width
title: qsTr("Show Favorites Bar")
components: [
StatusSwitch {
@ -99,22 +88,26 @@ ScrollView {
Separator {
id: separator1
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
width: parent.width
}
StatusBaseText {
text: qsTr("Connected DApps")
font.pixelSize: 15
color: Theme.palette.baseColor1
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
}
PermissionsListView {
id: permissionListView
width: parent.width
walletStore: root.store.walletStore
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
}
} // Column
} // Item

View File

@ -20,75 +20,42 @@ import "../popups"
// TODO remove this import when the ContactRequestPanel is moved to the the Profile completely
import "../../Chat/panels"
Item {
SettingsContentBase {
id: root
property ContactsStore contactsStore
property int profileContentWidth
property alias searchStr: searchBox.text
property bool isPending: false
height: parent.height
Layout.fillWidth: true
clip: true
Item {
height: parent.height
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
StatusFlatButton {
icon.name: "arrow-left"
icon.width: 20
icon.height: 20
text: qsTr("Messaging")
size: StatusBaseButton.Size.Large
anchors.top: parent.top
anchors.topMargin: 8
anchors.left: parent.left
anchors.leftMargin: -40
onClicked: Global.changeAppSectionBySectionType(Constants.appSection.profile,
Constants.settingsSubsection.messaging)
}
RowLayout {
id: contactsHeader
anchors.top: parent.top
anchors.topMargin: 56
anchors.left: parent.left
anchors.right: parent.right
StatusBaseText {
Layout.fillWidth: true
text: qsTr("Contacts")
font.weight: Font.Bold
font.pixelSize: 28
color: Theme.palette.directColor1
}
StatusButton {
text: qsTr("Send contact request to chat key")
onClicked: {
sendContactRequest.open()
}
headerComponents: [
StatusButton {
text: qsTr("Send contact request to chat key")
onClicked: {
sendContactRequest.open()
}
}
]
ColumnLayout {
spacing: 0
width: root.contentWidth
SearchBox {
id: searchBox
anchors.top: contactsHeader.bottom
anchors.topMargin: 32
width: parent.width
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
input.implicitHeight: 44
input.placeholderText: qsTr("Search by a display name or chat key")
}
TabBar {
id: contactsTabBar
width: parent.width
anchors.top: searchBox.bottom
anchors.topMargin: Style.current.padding
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
Layout.topMargin: Style.current.padding
height: contactsBtn.height
background: Rectangle {
color: Style.current.transparent
@ -107,13 +74,13 @@ Item {
badge.value: contactList.count
}
// Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
// StatusTabButton {
// id: rejectedRequestsBtn
// addToWidth: Style.current.bigPadding
// enabled: root.contactsStore.receivedButRejectedContactRequestsModel.count > 0 ||
// root.contactsStore.sentButRejectedContactRequestsModel.count > 0
// btnText: qsTr("Rejected Requests")
// }
// StatusTabButton {
// id: rejectedRequestsBtn
// addToWidth: Style.current.bigPadding
// enabled: root.contactsStore.receivedButRejectedContactRequestsModel.count > 0 ||
// root.contactsStore.sentButRejectedContactRequestsModel.count > 0
// btnText: qsTr("Rejected Requests")
// }
StatusTabButton {
id: blockedBtn
addToWidth: Style.current.bigPadding
@ -124,10 +91,8 @@ Item {
StackLayout {
id: stackLayout
width: parent.width
anchors.bottom: parent.bottom
anchors.top: contactsTabBar.bottom
anchors.topMargin: Style.current.padding
Layout.fillWidth: true
Layout.fillHeight: true
currentIndex: contactsTabBar.currentIndex
// CONTACTS
@ -140,7 +105,7 @@ Item {
ContactsListPanel {
Layout.fillWidth: true
Layout.preferredHeight: parent.height * 0.5
Layout.preferredHeight: root.height * 0.5
contactsModel: root.contactsStore.myContactsModel
clip: true
title: qsTr("Identity Verified Contacts")
@ -162,7 +127,7 @@ Item {
ContactsListPanel {
Layout.fillWidth: true
Layout.preferredHeight: parent.height * 0.5
Layout.preferredHeight: root.height * 0.5
contactsModel: root.contactsStore.myContactsModel
clip: true
title: qsTr("Contacts")
@ -207,7 +172,7 @@ Item {
ContactsListPanel {
Layout.fillWidth: true
Layout.preferredHeight: parent.height * 0.5
Layout.preferredHeight: root.height * 0.5
clip: true
title: qsTr("Received")
searchString: searchBox.text
@ -233,7 +198,7 @@ Item {
ContactsListPanel {
Layout.fillWidth: true
Layout.preferredHeight: parent.height * 0.5
Layout.preferredHeight: root.height * 0.5
clip: true
title: qsTr("Sent")
searchString: searchBox.text
@ -257,60 +222,60 @@ Item {
}
// Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
// // REJECTED REQUESTS
// Item {
// Layout.fillWidth: true
// Layout.fillHeight: true
// // REJECTED REQUESTS
// Item {
// Layout.fillWidth: true
// Layout.fillHeight: true
// ColumnLayout {
// anchors.fill: parent
// ColumnLayout {
// anchors.fill: parent
// ContactsListPanel {
// Layout.fillWidth: true
// Layout.preferredHeight: parent.height * 0.5
// clip: true
// title: qsTr("Received")
// searchString: searchBox.text
// contactsModel: root.contactsStore.receivedButRejectedContactRequestsModel
// panelUsage: Constants.contactsPanelUsage.rejectedReceivedContactRequest
// ContactsListPanel {
// Layout.fillWidth: true
// Layout.preferredHeight: root.height * 0.5
// clip: true
// title: qsTr("Received")
// searchString: searchBox.text
// contactsModel: root.contactsStore.receivedButRejectedContactRequestsModel
// panelUsage: Constants.contactsPanelUsage.rejectedReceivedContactRequest
// onOpenProfilePopup: {
// Global.openProfilePopup(publicKey)
// }
// onOpenProfilePopup: {
// Global.openProfilePopup(publicKey)
// }
// onOpenChangeNicknamePopup: {
// Global.openProfilePopup(publicKey, null, true)
// }
// onOpenChangeNicknamePopup: {
// Global.openProfilePopup(publicKey, null, true)
// }
// onRejectionRemoved: {
// root.contactsStore.removeContactRequestRejection(publicKey)
// }
// }
// onRejectionRemoved: {
// root.contactsStore.removeContactRequestRejection(publicKey)
// }
// }
// ContactsListPanel {
// Layout.fillWidth: true
// Layout.preferredHeight: parent.height * 0.5
// clip: true
// title: qsTr("Sent")
// searchString: searchBox.text
// contactsModel: root.contactsStore.sentButRejectedContactRequestsModel
// panelUsage: Constants.contactsPanelUsage.rejectedSentContactRequest
// ContactsListPanel {
// Layout.fillWidth: true
// Layout.preferredHeight: root.height * 0.5
// clip: true
// title: qsTr("Sent")
// searchString: searchBox.text
// contactsModel: root.contactsStore.sentButRejectedContactRequestsModel
// panelUsage: Constants.contactsPanelUsage.rejectedSentContactRequest
// onOpenProfilePopup: {
// Global.openProfilePopup(publicKey)
// }
// onOpenProfilePopup: {
// Global.openProfilePopup(publicKey)
// }
// onOpenChangeNicknamePopup: {
// Global.openProfilePopup(publicKey, null, true)
// }
// }
// onOpenChangeNicknamePopup: {
// Global.openProfilePopup(publicKey, null, true)
// }
// }
// Item {
// Layout.fillWidth: true
// Layout.fillHeight: true
// }
// }
// }
// Item {
// Layout.fillWidth: true
// Layout.fillHeight: true
// }
// }
// }
// BLOCKED
ContactsListPanel {
@ -335,51 +300,51 @@ Item {
height: 12
}
}
}
// TODO: Make BlockContactConfirmationDialog a dynamic component on a future refactor
BlockContactConfirmationDialog {
id: blockContactConfirmationDialog
onBlockButtonClicked: {
root.contactsStore.blockContact(blockContactConfirmationDialog.contactAddress)
blockContactConfirmationDialog.close()
}
}
// TODO: Make ConfirmationDialog a dynamic component on a future refactor
ConfirmationDialog {
id: removeContactConfirmationDialog
//% "Remove contact"
header.title: qsTrId("remove-contact")
//% "Are you sure you want to remove this contact?"
confirmationText: qsTrId("are-you-sure-you-want-to-remove-this-contact-")
onConfirmButtonClicked: {
if (Utils.getContactDetailsAsJson(removeContactConfirmationDialog.value).isContact) {
root.contactsStore.removeContact(removeContactConfirmationDialog.value);
// TODO: Make BlockContactConfirmationDialog a dynamic component on a future refactor
BlockContactConfirmationDialog {
id: blockContactConfirmationDialog
onBlockButtonClicked: {
root.contactsStore.blockContact(blockContactConfirmationDialog.contactAddress)
blockContactConfirmationDialog.close()
}
removeContactConfirmationDialog.close()
}
}
Loader {
id: sendContactRequest
active: false
function open() {
active = true
sendContactRequest.item.open()
}
function close() {
active = false
}
sourceComponent: SendContactRequestModal {
anchors.centerIn: parent
contactsStore: root.contactsStore
onClosed: {
sendContactRequest.close();
// TODO: Make ConfirmationDialog a dynamic component on a future refactor
ConfirmationDialog {
id: removeContactConfirmationDialog
//% "Remove contact"
header.title: qsTrId("remove-contact")
//% "Are you sure you want to remove this contact?"
confirmationText: qsTrId("are-you-sure-you-want-to-remove-this-contact-")
onConfirmButtonClicked: {
if (Utils.getContactDetailsAsJson(removeContactConfirmationDialog.value).isContact) {
root.contactsStore.removeContact(removeContactConfirmationDialog.value);
}
removeContactConfirmationDialog.close()
}
}
Loader {
id: sendContactRequest
active: false
function open() {
active = true
sendContactRequest.item.open()
}
function close() {
active = false
}
sourceComponent: SendContactRequestModal {
anchors.centerIn: root
contactsStore: root.contactsStore
onClosed: {
sendContactRequest.close();
}
}
}
}

View File

@ -14,234 +14,231 @@ import shared.controls 1.0
import "../stores"
Item {
SettingsContentBase {
id: root
property DevicesStore devicesStore
property bool isSyncing: false
width: 200
height: 200
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
Item {
id: firstTimeSetup
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.top: parent.top
anchors.topMargin: 24
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
visible: !root.devicesStore.isDeviceSetup
height: visible ? childrenRect.height : 0
width: root.contentWidth
height: this.childrenRect.height
StatusBaseText {
id: deviceNameLbl
//% "Please set a name for your device."
text: qsTrId("pairing-please-set-a-name")
font.pixelSize: 14
color: Theme.palette.directColor1
}
Input {
id: deviceNameTxt
//% "Specify a name"
placeholderText: qsTrId("specify-name")
anchors.top: deviceNameLbl.bottom
anchors.topMargin: Style.current.padding
}
// TODO: replace with StatusQ component
StatusButton {
anchors.top: deviceNameTxt.bottom
anchors.topMargin: 10
anchors.right: deviceNameTxt.right
//% "Continue"
text: qsTrId("continue")
enabled: deviceNameTxt.text !== ""
onClicked : root.devicesStore.setName(deviceNameTxt.text.trim())
}
}
Item {
id: advertiseDeviceItem
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.top: firstTimeSetup.visible ? firstTimeSetup.bottom : parent.top
anchors.topMargin: Style.current.padding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
visible: root.devicesStore.isDeviceSetup
height: visible ? childrenRect.height : 0
Rectangle {
id: advertiseDevice
height: childrenRect.height
width: 500
Item {
id: firstTimeSetup
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.top: parent.top
anchors.right: parent.right
color: Style.current.transparent
SVGImage {
id: advertiseImg
height: 32
width: 32
anchors.left: parent.left
fillMode: Image.PreserveAspectFit
source: Style.svg("messageActive")
ColorOverlay {
anchors.fill: parent
source: parent
color: Style.current.blue
}
}
anchors.rightMargin: Style.current.padding
visible: !root.devicesStore.isDeviceSetup
height: visible ? childrenRect.height : 0
StatusBaseText {
id: advertiseDeviceTitle
//% "Advertise device"
text: qsTrId("pair-this-device")
font.pixelSize: 18
font.weight: Font.Bold
color: Theme.palette.primaryColor1
anchors.left: advertiseImg.right
anchors.leftMargin: Style.current.padding
}
StatusBaseText {
id: advertiseDeviceDesk
//% "Pair your devices to sync contacts and chats between them"
text: qsTrId("pair-this-device-description")
id: deviceNameLbl
//% "Please set a name for your device."
text: qsTrId("pairing-please-set-a-name")
font.pixelSize: 14
anchors.top: advertiseDeviceTitle.bottom
anchors.topMargin: 6
anchors.left: advertiseImg.right
anchors.leftMargin: Style.current.padding
color: Theme.palette.directColor1
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: root.devicesStore.advertise()
Input {
id: deviceNameTxt
//% "Specify a name"
placeholderText: qsTrId("specify-name")
anchors.top: deviceNameLbl.bottom
anchors.topMargin: Style.current.padding
}
}
StatusBaseText {
anchors.top: advertiseDevice.bottom
anchors.topMargin: Style.current.padding
//% "Learn more"
text: qsTrId("learn-more")
font.pixelSize: 16
color: Theme.palette.primaryColor1
anchors.left: parent.left
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: Global.openLink("https://status.im/user_guides/pairing_devices.html")
}
}
}
Item {
id: deviceListItem
anchors.left: root.left
anchors.leftMargin: Style.current.padding
anchors.top: advertiseDeviceItem.visible ? advertiseDeviceItem.bottom : parent.top
anchors.topMargin: Style.current.padding * 2
anchors.bottom: syncAllBtn.top
anchors.bottomMargin: Style.current.padding
anchors.right: root.right
anchors.rightMargin: Style.current.padding
visible: root.devicesStore.isDeviceSetup
StatusBaseText {
id: deviceListLbl
//% "Paired devices"
text: qsTrId("paired-devices")
font.pixelSize: 16
font.weight: Font.Bold
color: Theme.palette.directColor1
}
ListView {
id: listView
anchors.bottom: parent.bottom
anchors.top: deviceListLbl.bottom
anchors.topMargin: Style.current.padding
spacing: 5
anchors.right: parent.right
anchors.left: parent.left
// TODO: replace with StatusQ component
delegate: Item {
StatusButton {
anchors.top: deviceNameTxt.bottom
anchors.topMargin: 10
anchors.right: deviceNameTxt.right
//% "Continue"
text: qsTrId("continue")
enabled: deviceNameTxt.text !== ""
onClicked : root.devicesStore.setName(deviceNameTxt.text.trim())
}
}
Item {
id: advertiseDeviceItem
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.top: firstTimeSetup.visible ? firstTimeSetup.bottom : parent.top
anchors.topMargin: Style.current.padding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
visible: root.devicesStore.isDeviceSetup
height: visible ? childrenRect.height : 0
Rectangle {
id: advertiseDevice
height: childrenRect.height
width: 500
anchors.left: parent.left
anchors.right: parent.right
color: Style.current.transparent
SVGImage {
id: enabledIcon
source: Style.svg(devicePairedSwitch.checked ? "messageActive" : "message")
height: 24
width: 24
id: advertiseImg
height: 32
width: 32
anchors.left: parent.left
fillMode: Image.PreserveAspectFit
source: Style.svg("messageActive")
ColorOverlay {
anchors.fill: parent
source: parent
color: Style.current.blue
}
}
StatusBaseText {
id: deviceItemLbl
text: {
let deviceId = model.installationId.split("-")[0].substr(0, 5)
//% "No info"
let labelText = `${model.name || qsTrId("pairing-no-info")} ` +
//% "you"
`(${model.isCurrentDevice ? qsTrId("you") + ", ": ""}${deviceId})`;
return labelText;
}
elide: Text.ElideRight
id: advertiseDeviceTitle
//% "Advertise device"
text: qsTrId("pair-this-device")
font.pixelSize: 18
font.weight: Font.Bold
color: Theme.palette.primaryColor1
anchors.left: advertiseImg.right
anchors.leftMargin: Style.current.padding
}
StatusBaseText {
id: advertiseDeviceDesk
//% "Pair your devices to sync contacts and chats between them"
text: qsTrId("pair-this-device-description")
font.pixelSize: 14
anchors.left: enabledIcon.right
anchors.top: advertiseDeviceTitle.bottom
anchors.topMargin: 6
anchors.left: advertiseImg.right
anchors.leftMargin: Style.current.padding
color: Theme.palette.directColor1
}
StatusSwitch {
id: devicePairedSwitch
visible: !model.isCurrentDevice
checked: model.enabled
anchors.left: deviceItemLbl.right
anchors.leftMargin: Style.current.padding
anchors.top: deviceItemLbl.top
onClicked: root.devicesStore.enableDevice(model.installationId, devicePairedSwitch)
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: root.devicesStore.advertise()
}
}
model: root.devicesStore.devicesModel
StatusBaseText {
anchors.top: advertiseDevice.bottom
anchors.topMargin: Style.current.padding
//% "Learn more"
text: qsTrId("learn-more")
font.pixelSize: 16
color: Theme.palette.primaryColor1
anchors.left: parent.left
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: Global.openLink("https://status.im/user_guides/pairing_devices.html")
}
}
}
Item {
id: deviceListItem
anchors.left: root.left
anchors.leftMargin: Style.current.padding
anchors.top: advertiseDeviceItem.visible ? advertiseDeviceItem.bottom : parent.top
anchors.topMargin: Style.current.padding * 2
anchors.bottom: syncAllBtn.top
anchors.bottomMargin: Style.current.padding
anchors.right: root.right
anchors.rightMargin: Style.current.padding
visible: root.devicesStore.isDeviceSetup
StatusBaseText {
id: deviceListLbl
//% "Paired devices"
text: qsTrId("paired-devices")
font.pixelSize: 16
font.weight: Font.Bold
color: Theme.palette.directColor1
}
ListView {
id: listView
anchors.bottom: parent.bottom
anchors.top: deviceListLbl.bottom
anchors.topMargin: Style.current.padding
spacing: 5
anchors.right: parent.right
anchors.left: parent.left
// TODO: replace with StatusQ component
delegate: Item {
height: childrenRect.height
SVGImage {
id: enabledIcon
source: Style.svg(devicePairedSwitch.checked ? "messageActive" : "message")
height: 24
width: 24
ColorOverlay {
anchors.fill: parent
source: parent
color: Style.current.blue
}
}
StatusBaseText {
id: deviceItemLbl
text: {
let deviceId = model.installationId.split("-")[0].substr(0, 5)
//% "No info"
let labelText = `${model.name || qsTrId("pairing-no-info")} ` +
//% "you"
`(${model.isCurrentDevice ? qsTrId("you") + ", ": ""}${deviceId})`;
return labelText;
}
elide: Text.ElideRight
font.pixelSize: 14
anchors.left: enabledIcon.right
anchors.leftMargin: Style.current.padding
color: Theme.palette.directColor1
}
StatusSwitch {
id: devicePairedSwitch
visible: !model.isCurrentDevice
checked: model.enabled
anchors.left: deviceItemLbl.right
anchors.leftMargin: Style.current.padding
anchors.top: deviceItemLbl.top
onClicked: root.devicesStore.enableDevice(model.installationId, devicePairedSwitch)
}
}
model: root.devicesStore.devicesModel
}
}
StatusButton {
id: syncAllBtn
anchors.bottom: parent.bottom
anchors.bottomMargin: Style.current.padding
anchors.horizontalCenter: parent.horizontalCenter
text: isSyncing ?
//% "Syncing..."
qsTrId("sync-in-progress") :
//% "Sync all devices"
qsTrId("sync-all-devices")
enabled: !isSyncing
onClicked : {
isSyncing = true;
root.devicesStore.syncAll()
// Currently we don't know how long it takes, so we just disable for 10s, to avoid spamming
timer.setTimeout(function(){
isSyncing = false
}, 10000);
}
}
Timer {
id: timer
}
}
StatusButton {
id: syncAllBtn
anchors.bottom: root.bottom
anchors.bottomMargin: Style.current.padding
anchors.horizontalCenter: parent.horizontalCenter
text: isSyncing ?
//% "Syncing..."
qsTrId("sync-in-progress") :
//% "Sync all devices"
qsTrId("sync-all-devices")
enabled: !isSyncing
onClicked : {
isSyncing = true;
root.devicesStore.syncAll()
// Currently we don't know how long it takes, so we just disable for 10s, to avoid spamming
timer.setTimeout(function(){
isSyncing = false
}, 10000);
}
}
Timer {
id: timer
}
}

View File

@ -12,208 +12,184 @@ import shared.status 1.0
import "../panels"
Item {
id: helpContainer
SettingsContentBase {
id: root
property int profileContentWidth
ColumnLayout {
spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth
height: parent.height
Layout.fillWidth: true
clip: true
ScrollView {
height: parent.height
width: parent.width
contentHeight: glossary.height + linksSection.height + Style.current.bigPadding * 4
clip: true
Item {
id: glossary
anchors.top: parent.top
height: this.childrenRect.height
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
StatusSectionHeadline {
id: glossaryTitle
//% "Glossary"
text: qsTrId("glossary")
anchors.left: parent.left
anchors.top: parent.top
}
GlossaryEntry {
id: entryAccount
anchors.top: glossaryTitle.bottom
anchors.topMargin: Style.current.padding
//% "Account"
name: qsTrId("account-title")
//% "A"
//: This letter corresponds to the section title above, so here it is "A" because the title above is "Account"
letter: qsTrId("a")
//% "Your Status account, accessed by the seed phrase that you create or import during onboarding. A Status account can hold more than one Ethereum address, in addition to the one created during onboarding. We refer to these as additional accounts within the wallet"
description: qsTrId("your-status-account--accessed-by-the-seed-phrase-that-you-create-or-import-during-onboarding--a-status-account-can-hold-more-than-one-ethereum-address--in-addition-to-the-one-created-during-onboarding--we-refer-to-these-as-additional-accounts-within-the-wallet")
}
GlossaryEntry {
id: entryChatKey
anchors.top: entryAccount.bottom
anchors.topMargin: Style.current.padding
//% "Chat Key"
name: qsTrId("chat-key-title")
//% "C"
//: This letter corresponds to the section title above, so here it is "C" because the title above is "Chat Key"
letter: qsTrId("c")
//% "Messages on the Status chat protocol are sent and received using encryption keys. The public chat key is a string of characters you share with others so they can send you messages in Status."
description: qsTrId("chat-key-content")
}
GlossaryEntry {
id: entryChatName
anchors.top: entryChatKey.bottom
anchors.topMargin: Style.current.padding
//% "Chat Name"
name: qsTrId("chat-name-title")
//% "Three random words, derived algorithmically from your chat key and used as your default alias in chat. Chat names are completely unique; no other user can have the same three words."
description: qsTrId("chat-name-content")
}
GlossaryEntry {
id: entryENSName
anchors.top: entryChatName.bottom
anchors.topMargin: Style.current.padding
//% "ENS Name"
name: qsTrId("ens-name-title")
//% "E"
//: This letter corresponds to the section title above, so here it is "E" because the title above is "ENS Name"
letter: qsTrId("e")
//% "Custom alias for your chat key that you can register using the Ethereum Name Service. ENS names are decentralized usernames."
description: qsTrId("ens-name-content")
}
GlossaryEntry {
id: entryMailserver
anchors.top: entryENSName.bottom
anchors.topMargin: Style.current.padding
//% "Mailserver"
name: qsTrId("mailserver-title")
//% "M"
//: This letter corresponds to the section title above, so here it is "M" because the title above is "Mailserver"
letter: qsTrId("m")
//% "A node in the Status network that routes and stores messages, for up to 30 days."
description: qsTrId("mailserver-content")
}
GlossaryEntry {
id: entryPeer
anchors.top: entryMailserver.bottom
anchors.topMargin: Style.current.padding
//% "Peer"
name: qsTrId("peer-title")
//% "P"
//: This letter corresponds to the section title above, so here it is "P" because the title above is "Peer"
letter: qsTrId("p")
//% "A device connected to the Status chat network. Each user can represent one or more peers, depending on their number of devices"
description: qsTrId("a-device-connected-to-the-status-chat-network--each-user-can-represent-one-or-more-peers--depending-on-their-number-of-devices")
}
GlossaryEntry {
id: entrySeedPhrase
anchors.top: entryPeer.bottom
anchors.topMargin: Style.current.padding
//% "Seed Phrase"
name: qsTrId("seed-phrase-title")
//% "S"
//: This letter corresponds to the section title above, so here it is "S" because the title above is "Seed Phrase"
letter: qsTrId("s")
//% "A 64 character hex address based on the Ethereum standard and beginning with 0x. Public-facing, your wallet key is shared with others when you want to receive funds. Also referred to as an Ethereum address or wallet address."
description: qsTrId("a-64-character-hex-address-based-on-the-ethereum-standard-and-beginning-with-0x--public-facing--your-wallet-key-is-shared-with-others-when-you-want-to-receive-funds--also-referred-to-as-an--ethereum-address--or--wallet-address-")
}
GlossaryEntry {
id: entryAccount
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Account"
name: qsTrId("account-title")
//% "A"
//: This letter corresponds to the section title above, so here it is "A" because the title above is "Account"
letter: qsTrId("a")
//% "Your Status account, accessed by the seed phrase that you create or import during onboarding. A Status account can hold more than one Ethereum address, in addition to the one created during onboarding. We refer to these as additional accounts within the wallet"
description: qsTrId("your-status-account--accessed-by-the-seed-phrase-that-you-create-or-import-during-onboarding--a-status-account-can-hold-more-than-one-ethereum-address--in-addition-to-the-one-created-during-onboarding--we-refer-to-these-as-additional-accounts-within-the-wallet")
}
GlossaryEntry {
id: entryChatKey
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Chat Key"
name: qsTrId("chat-key-title")
//% "C"
//: This letter corresponds to the section title above, so here it is "C" because the title above is "Chat Key"
letter: qsTrId("c")
//% "Messages on the Status chat protocol are sent and received using encryption keys. The public chat key is a string of characters you share with others so they can send you messages in Status."
description: qsTrId("chat-key-content")
}
Item {
id: linksSection
anchors.top: glossary.bottom
anchors.topMargin: Style.current.bigPadding * 2
height: this.childrenRect.height
width: profileContentWidth
GlossaryEntry {
id: entryChatName
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Chat Name"
name: qsTrId("chat-name-title")
//% "Three random words, derived algorithmically from your chat key and used as your default alias in chat. Chat names are completely unique; no other user can have the same three words."
description: qsTrId("chat-name-content")
}
anchors.horizontalCenter: parent.horizontalCenter
GlossaryEntry {
id: entryENSName
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "ENS Name"
name: qsTrId("ens-name-title")
//% "E"
//: This letter corresponds to the section title above, so here it is "E" because the title above is "ENS Name"
letter: qsTrId("e")
//% "Custom alias for your chat key that you can register using the Ethereum Name Service. ENS names are decentralized usernames."
description: qsTrId("ens-name-content")
}
StatusBaseText {
id: faqLink
//% "Frequently asked questions"
text: qsTrId("faq")
font.pixelSize: 15
color: Theme.palette.primaryColor1
anchors.topMargin: Style.current.bigPadding
anchors.top: parent.top
GlossaryEntry {
id: entryMailserver
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Mailserver"
name: qsTrId("mailserver-title")
//% "M"
//: This letter corresponds to the section title above, so here it is "M" because the title above is "Mailserver"
letter: qsTrId("m")
//% "A node in the Status network that routes and stores messages, for up to 30 days."
description: qsTrId("mailserver-content")
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
parent.font.underline = true
}
onExited: {
parent.font.underline = false
}
onClicked: {
Global.openLink("https://status.im/docs/FAQs.html")
}
GlossaryEntry {
id: entryPeer
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Peer"
name: qsTrId("peer-title")
//% "P"
//: This letter corresponds to the section title above, so here it is "P" because the title above is "Peer"
letter: qsTrId("p")
//% "A device connected to the Status chat network. Each user can represent one or more peers, depending on their number of devices"
description: qsTrId("a-device-connected-to-the-status-chat-network--each-user-can-represent-one-or-more-peers--depending-on-their-number-of-devices")
}
GlossaryEntry {
id: entrySeedPhrase
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Seed Phrase"
name: qsTrId("seed-phrase-title")
//% "S"
//: This letter corresponds to the section title above, so here it is "S" because the title above is "Seed Phrase"
letter: qsTrId("s")
//% "A 64 character hex address based on the Ethereum standard and beginning with 0x. Public-facing, your wallet key is shared with others when you want to receive funds. Also referred to as an Ethereum address or wallet address."
description: qsTrId("a-64-character-hex-address-based-on-the-ethereum-standard-and-beginning-with-0x--public-facing--your-wallet-key-is-shared-with-others-when-you-want-to-receive-funds--also-referred-to-as-an--ethereum-address--or--wallet-address-")
}
StatusBaseText {
id: faqLink
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Frequently asked questions"
text: qsTrId("faq")
font.pixelSize: 15
color: Theme.palette.primaryColor1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
parent.font.underline = true
}
}
StatusBaseText {
id: issueLink
//% "Submit a bug"
text: qsTrId("submit-bug")
font.pixelSize: 15
color: Theme.palette.primaryColor1
anchors.topMargin: Style.current.bigPadding
anchors.top: faqLink.bottom
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
parent.font.underline = true
}
onExited: {
parent.font.underline = false
}
onClicked: {
Global.openLink("https://github.com/status-im/nim-status-client/issues/new")
}
onExited: {
parent.font.underline = false
}
}
StatusBaseText {
//% "Request a feature"
text: qsTrId("request-feature")
font.pixelSize: 15
color: Theme.palette.primaryColor1
anchors.topMargin: Style.current.bigPadding
anchors.top: issueLink.bottom
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
parent.font.underline = true
}
onExited: {
parent.font.underline = false
}
onClicked: {
Global.openLink("https://discuss.status.im/c/features/51")
}
onClicked: {
Global.openLink("https://status.im/docs/FAQs.html")
}
}
}
StatusBaseText {
id: issueLink
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Submit a bug"
text: qsTrId("submit-bug")
font.pixelSize: 15
color: Theme.palette.primaryColor1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
parent.font.underline = true
}
onExited: {
parent.font.underline = false
}
onClicked: {
Global.openLink("https://github.com/status-im/nim-status-client/issues/new")
}
}
}
StatusBaseText {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Request a feature"
text: qsTrId("request-feature")
font.pixelSize: 15
color: Theme.palette.primaryColor1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
parent.font.underline = true
}
onExited: {
parent.font.underline = false
}
onClicked: {
Global.openLink("https://discuss.status.im/c/features/51")
}
}
}
}
}

View File

@ -13,28 +13,11 @@ import StatusQ.Components 0.1
import "../popups"
import "../stores"
Item {
SettingsContentBase {
id: root
property LanguageStore languageStore
property var currencyStore
property int profileContentWidth
QtObject {
id: d
property int margins: 64
property int zOnTop: 100
function setViewIdleState() {
currencyPicker.close()
languagePicker.close()
}
}
z: d.zOnTop
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
onVisibleChanged: { if(!visible) d.setViewIdleState()}
@ -43,150 +26,145 @@ Item {
root.languageStore.initializeLanguageModel()
}
Column {
z: d.zOnTop
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: d.margins
anchors.left: parent.left
spacing: 45
ColumnLayout {
spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth
StatusBaseText {
id: title
text: qsTr("Language & Currency")
font.weight: Font.Bold
font.pixelSize: 22
color: Theme.palette.directColor1
QtObject {
id: d
property int margins: 64
property int zOnTop: 100
function setViewIdleState() {
currencyPicker.close()
languagePicker.close()
}
}
Column {
z: d.zOnTop
width: 560 - (2 * Style.current.padding)
spacing: 26
Item {
id: currency
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
height: 38
z: d.zOnTop + 1
Item {
id: currency
width: parent.width
height: 38
z: d.zOnTop + 1
StatusBaseText {
text: qsTr("Set Display Currency")
anchors.left: parent.left
font.pixelSize: 15
color: Theme.palette.directColor1
}
StatusListPicker {
id: currencyPicker
property string newKey
Timer {
id: currencyPause
interval: 100
onTriggered: {
// updateCurrency function operation blocks a little bit the UI so getting around it with a small pause (timer) in order to get the desired visual behavior
root.currencyStore.updateCurrency(currencyPicker.newKey)
}
}
z: d.zOnTop + 1
width: 104
height: parent.height
anchors.right: parent.right
inputList: root.currencyStore.currenciesModel
printSymbol: true
placeholderSearchText: qsTr("Search Currencies")
onItemPickerChanged: {
if(selected) {
currencyPicker.newKey = key
currencyPause.start()
}
}
}
}
Item {
id: language
width: parent.width
height: 38
z: d.zOnTop
StatusBaseText {
text: qsTr("Language")
anchors.left: parent.left
font.pixelSize: 15
color: Theme.palette.directColor1
}
StatusListPicker {
id: languagePicker
property string newKey
Timer {
id: languagePause
interval: 100
onTriggered: {
// changeLocale function operation blocks a little bit the UI so getting around it with a small pause (timer) in order to get the desired visual behavior
root.languageStore.changeLocale(languagePicker.newKey)
}
}
z: d.zOnTop
width: 104
height: parent.height
anchors.right: parent.right
inputList: root.languageStore.languageModel
placeholderSearchText: qsTr("Search Languages")
onItemPickerChanged: {
if(selected && localAppSettings.locale !== key) {
// TEMPORARY: It should be removed as it is only used in Linux OS but it must be investigated how to change language in execution time, as well, in Linux (will be addressed in another task)
if (Qt.platform.os === Constants.linux) {
linuxConfirmationDialog.active = true
linuxConfirmationDialog.item.newLocale = key
linuxConfirmationDialog.item.open()
}
else {
languagePicker.newKey = key
languagePause.start()
}
}
}
}
}
Separator {
StatusBaseText {
text: qsTr("Set Display Currency")
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
font.pixelSize: 15
color: Theme.palette.directColor1
}
StatusListPicker {
id: currencyPicker
property string newKey
Timer {
id: currencyPause
interval: 100
onTriggered: {
// updateCurrency function operation blocks a little bit the UI so getting around it with a small pause (timer) in order to get the desired visual behavior
root.currencyStore.updateCurrency(currencyPicker.newKey)
}
}
z: d.zOnTop + 1
width: 104
height: parent.height
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
inputList: root.currencyStore.currenciesModel
printSymbol: true
placeholderSearchText: qsTr("Search Currencies")
onItemPickerChanged: {
if(selected) {
currencyPicker.newKey = key
currencyPause.start()
}
}
}
}
}
// TEMPORARY: It should be removed as it is only used in Linux OS but it must be investigated how to change language in execution time, as well, in Linux (will be addressed in another task)
Loader {
id: linuxConfirmationDialog
active: false
sourceComponent: ConfirmationDialog {
property string newLocale
Item {
id: language
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
height: 38
z: d.zOnTop
header.title: qsTr("Change language")
confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.")
confirmButtonLabel: qsTr("Close the app now")
onConfirmButtonClicked: {
root.languageStore.changeLocale(newLocale)
loader.active = false
Qt.quit()
}
}
}
StatusBaseText {
text: qsTr("Language")
anchors.left: parent.left
font.pixelSize: 15
color: Theme.palette.directColor1
}
StatusListPicker {
id: languagePicker
// Outsite area
MouseArea {
anchors.fill: parent
onClicked: { d.setViewIdleState() }
property string newKey
Timer {
id: languagePause
interval: 100
onTriggered: {
// changeLocale function operation blocks a little bit the UI so getting around it with a small pause (timer) in order to get the desired visual behavior
root.languageStore.changeLocale(languagePicker.newKey)
}
}
z: d.zOnTop
width: 104
height: parent.height
anchors.right: parent.right
inputList: root.languageStore.languageModel
placeholderSearchText: qsTr("Search Languages")
onItemPickerChanged: {
if(selected && localAppSettings.locale !== key) {
// TEMPORARY: It should be removed as it is only used in Linux OS but it must be investigated how to change language in execution time, as well, in Linux (will be addressed in another task)
if (Qt.platform.os === Constants.linux) {
linuxConfirmationDialog.active = true
linuxConfirmationDialog.item.newLocale = key
linuxConfirmationDialog.item.open()
}
else {
languagePicker.newKey = key
languagePause.start()
}
}
}
}
}
Separator {
Layout.fillWidth: true
}
// TEMPORARY: It should be removed as it is only used in Linux OS but it must be investigated how to change language in execution time, as well, in Linux (will be addressed in another task)
Loader {
id: linuxConfirmationDialog
active: false
sourceComponent: ConfirmationDialog {
property string newLocale
header.title: qsTr("Change language")
confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.")
confirmButtonLabel: qsTr("Close the app now")
onConfirmButtonClicked: {
root.languageStore.changeLocale(newLocale)
loader.active = false
Qt.quit()
}
}
}
// Outsite area
MouseArea {
anchors.fill: parent
onClicked: { d.setViewIdleState() }
}
}
}

View File

@ -20,23 +20,15 @@ import "../controls"
import "../popups"
import "../panels"
ScrollView {
SettingsContentBase {
id: root
property int profileContentWidth
height: parent.height
width: parent.width
contentHeight: advancedContainer.height + 100
clip: true
property MessagingStore messagingStore
Item {
id: advancedContainer
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
height: generalColumn.height
ColumnLayout {
id: generalColumn
spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth
ButtonGroup {
id: showProfilePictureToGroup
@ -50,395 +42,406 @@ ScrollView {
id: browserGroup
}
StatusListItem {
id: allowNewContactRequest
Layout.fillWidth: true
implicitHeight: 64
//% "Allow new contact requests"
title: qsTrId("allow-new-contact-requests")
components: [
StatusSwitch {
id: switch3
checked: !root.messagingStore.privacyModule.messagesFromContactsOnly
onCheckedChanged: {
// messagesFromContactsOnly needs to be accessed from the module (view),
// because otherwise doing `messagesFromContactsOnly = value` only changes the bool property on QML
if (root.messagingStore.privacyModule.messagesFromContactsOnly === checked) {
root.messagingStore.privacyModule.messagesFromContactsOnly = !checked
}
}
}
]
sensor.onClicked: {
switch3.checked = !switch3.checked
}
}
// SHOW PROFILE PICTURE TO
StatusBaseText {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Show My Profile Picture To")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Everyone")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.everyone
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.everyone
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Contacts")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.contactsOnly
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.contactsOnly
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("No One")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.noOne
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.noOne
)
}
Item {
id: spacer1
Layout.fillWidth: true
Layout.preferredHeight: 6
}
// SEE PROFILTE PICTURES FROM
StatusBaseText {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("See Profile Pictures From")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Everyone")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.everyone
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.everyone
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Contacts")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.contactsOnly
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.contactsOnly
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("No One")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.noOne
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.noOne
)
}
Item {
id: spacer2
Layout.fillWidth: true
Layout.preferredHeight: 6
}
// Open Message Links With
StatusBaseText {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Open Message Links With")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Status Browser")
group: browserGroup
checked: localAccountSensitiveSettings.openLinksInStatus
onClicked: {
localAccountSensitiveSettings.openLinksInStatus = true
}
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("System Default Browser")
group: browserGroup
checked: !localAccountSensitiveSettings.openLinksInStatus
onClicked: {
localAccountSensitiveSettings.openLinksInStatus = false
}
}
Separator {
id: separator1
Layout.fillWidth: true
}
// CONTACTS SECTION
StatusContactRequestsIndicatorListItem {
Layout.fillWidth: true
title: qsTr("Contacts, Requests, and Blocked Users")
requestsCount: root.messagingStore.contactRequestsModel.count
sensor.onClicked: Global.changeAppSectionBySectionType(Constants.appSection.profile,
Constants.settingsSubsection.contacts)
}
Separator {
id: separator2
Layout.fillWidth: true
}
// MESSAGE LINK PREVIEWS
StatusListItem {
Layout.fillWidth: true
title: qsTr("Display Message Link Previews")
implicitHeight: 64
components: [
StatusSwitch {
id: showMessageLinksSwitch
checked: false
onCheckedChanged: {
if (checked === false) {
// Switch all the whitelists to false
imageSwitch.checked = false
for (let i = 0; i < sitesListView.count; i++) {
let item = sitesListView.itemAt(i)
item.whitelistSwitch.checked = false
}
}
}
}
]
sensor.onClicked: {
showMessageLinksSwitch.checked = !showMessageLinksSwitch.checked
}
}
function populatePreviewableSites() {
let whitelistAsString = root.messagingStore.getLinkPreviewWhitelist()
if(whitelistAsString == "")
return
let whitelist = JSON.parse(whitelistAsString)
if (!localAccountSensitiveSettings.whitelistedUnfurlingSites) {
localAccountSensitiveSettings.whitelistedUnfurlingSites = {}
}
previewableSites.clear()
var oneEntryIsActive = false
whitelist.forEach(entry => {
entry.isWhitelisted = localAccountSensitiveSettings.whitelistedUnfurlingSites[entry.address] || false
if (entry.isWhitelisted) {
oneEntryIsActive = true
}
previewableSites.append(entry)
})
if (oneEntryIsActive) {
showMessageLinksSwitch.checked = true
}
}
Component.onCompleted: {
populatePreviewableSites()
}
StatusSectionHeadline {
id: labelWebsites
visible: showMessageLinksSwitch.checked
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Fine tune which sites to allow link previews")
}
Column {
id: generalColumn
spacing: 18
anchors.top: parent.top
anchors.topMargin: 24
anchors.left: parent.left
anchors.right: parent.right
id: siteColumn
visible: showMessageLinksSwitch.checked
Layout.fillWidth: true
StatusBaseText {
id: titleText
text: qsTr("Messaging")
font.weight: Font.Bold
font.pixelSize: 28
color: Theme.palette.directColor1
ListModel {
id: previewableSites
}
Connections {
target: Global
onSettingsLoaded: {
generalColumn.populatePreviewableSites()
}
}
// Manually add switch for the image unfurling
StatusListItem {
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
//% "Allow new contact requests"
title: qsTrId("allow-new-contact-requests")
width: parent.width
implicitHeight: 64
title: qsTr("Image unfurling")
subTitle: qsTr("All images (links that contain an image extension) will be downloaded and displayed")
// TODO find a better icon for this
image.source: Style.svg('globe')
Component.onCompleted: {
if (localAccountSensitiveSettings.displayChatImages) {
showMessageLinksSwitch.checked = true
}
}
components: [
StatusSwitch {
id: switch3
checked: !root.messagingStore.privacyModule.messagesFromContactsOnly
id: imageSwitch
checked: localAccountSensitiveSettings.displayChatImages
onCheckedChanged: {
// messagesFromContactsOnly needs to be accessed from the module (view),
// because otherwise doing `messagesFromContactsOnly = value` only changes the bool property on QML
if (root.messagingStore.privacyModule.messagesFromContactsOnly === checked) {
root.messagingStore.privacyModule.messagesFromContactsOnly = !checked
if (localAccountSensitiveSettings.displayChatImages !== checked) {
localAccountSensitiveSettings.displayChatImages = checked
}
}
}
]
sensor.onClicked: {
switch3.checked = !switch3.checked
imageSwitch.checked = !imageSwitch.checked
}
}
// SHOW PROFILE PICTURE TO
StatusBaseText {
text: qsTr("Show My Profile Picture To")
font.pixelSize: 15
color: Theme.palette.directColor1
}
Repeater {
id: sitesListView
model: previewableSites
SettingsRadioButton {
label: qsTr("Everyone")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.everyone
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.everyone
)
}
SettingsRadioButton {
label: qsTr("Contacts")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.contactsOnly
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.contactsOnly
)
}
SettingsRadioButton {
label: qsTr("No One")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.noOne
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.noOne
)
}
Item {
id: spacer1
width: parent.width
height: 6
}
// SEE PROFILTE PICTURES FROM
StatusBaseText {
text: qsTr("See Profile Pictures From")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
label: qsTr("Everyone")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.everyone
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.everyone
)
}
SettingsRadioButton {
label: qsTr("Contacts")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.contactsOnly
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.contactsOnly
)
}
SettingsRadioButton {
label: qsTr("No One")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.noOne
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.noOne
)
}
Item {
id: spacer2
width: parent.width
height: 6
}
// Open Message Links With
StatusBaseText {
text: qsTr("Open Message Links With")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
label: qsTr("Status Browser")
group: browserGroup
checked: localAccountSensitiveSettings.openLinksInStatus
onClicked: {
localAccountSensitiveSettings.openLinksInStatus = true
}
}
SettingsRadioButton {
label: qsTr("System Default Browser")
group: browserGroup
checked: !localAccountSensitiveSettings.openLinksInStatus
onClicked: {
localAccountSensitiveSettings.openLinksInStatus = false
}
}
Separator {
id: separator1
}
// CONTACTS SECTION
StatusContactRequestsIndicatorListItem {
title: qsTr("Contacts, Requests, and Blocked Users")
requestsCount: root.messagingStore.contactRequestsModel.count
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
sensor.onClicked: Global.changeAppSectionBySectionType(Constants.appSection.profile,
Constants.settingsSubsection.contacts)
}
Separator {
id: separator2
}
// MESSAGE LINK PREVIEWS
StatusListItem {
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
title: qsTr("Display Message Link Previews")
implicitHeight: 64
components: [
StatusSwitch {
id: showMessageLinksSwitch
checked: false
onCheckedChanged: {
if (checked === false) {
// Switch all the whitelists to false
imageSwitch.checked = false
for (let i = 0; i < sitesListView.count; i++) {
let item = sitesListView.itemAt(i)
item.whitelistSwitch.checked = false
}
delegate: Component {
StatusListItem {
property alias whitelistSwitch: siteSwitch
width: parent.width
implicitHeight: 64
title: model.title
subTitle: model.address
image.source: {
let filename;
switch (model.title.toLowerCase()) {
case "youtube":
case "youtube shortener":
filename = "youtube"; break;
case "github":
filename = "github"; break;
case "medium":
filename = "medium"; break;
case "tenor gifs":
filename = "tenor"; break;
case "giphy gifs":
case "giphy gifs shortener":
case "giphy gifs subdomain":
filename = "giphy"; break;
case "github":
filename = "github"; break;
case "status":
filename = "status"; break;
// TODO get a good default icon
default: filename = "../globe"
}
return Style.svg(`linkPreviewThumbnails/${filename}`)
}
}
]
sensor.onClicked: {
showMessageLinksSwitch.checked = !showMessageLinksSwitch.checked
}
}
components: [
StatusSwitch {
id: siteSwitch
checked: !!model.isWhitelisted
onCheckedChanged: {
let settings = localAccountSensitiveSettings.whitelistedUnfurlingSites
function populatePreviewableSites() {
let whitelistAsString = root.messagingStore.getLinkPreviewWhitelist()
if(whitelistAsString == "")
return
let whitelist = JSON.parse(whitelistAsString)
if (!localAccountSensitiveSettings.whitelistedUnfurlingSites) {
localAccountSensitiveSettings.whitelistedUnfurlingSites = {}
}
previewableSites.clear()
var oneEntryIsActive = false
whitelist.forEach(entry => {
entry.isWhitelisted = localAccountSensitiveSettings.whitelistedUnfurlingSites[entry.address] || false
if (entry.isWhitelisted) {
oneEntryIsActive = true
}
previewableSites.append(entry)
})
if (oneEntryIsActive) {
showMessageLinksSwitch.checked = true
}
}
Component.onCompleted: {
populatePreviewableSites()
}
Column {
id: siteColumn
visible: showMessageLinksSwitch.checked
width: parent.width
StatusSectionHeadline {
id: labelWebsites
text: qsTr("Fine tune which sites to allow link previews")
width: parent.width
}
ListModel {
id: previewableSites
}
Connections {
target: Global
onSettingsLoaded: {
generalColumn.populatePreviewableSites()
}
}
// Manually add switch for the image unfurling
StatusListItem {
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
implicitHeight: 64
title: qsTr("Image unfurling")
subTitle: qsTr("All images (links that contain an image extension) will be downloaded and displayed")
// TODO find a better icon for this
image.source: Style.svg('globe')
Component.onCompleted: {
if (localAccountSensitiveSettings.displayChatImages) {
showMessageLinksSwitch.checked = true
}
}
components: [
StatusSwitch {
id: imageSwitch
checked: localAccountSensitiveSettings.displayChatImages
onCheckedChanged: {
if (localAccountSensitiveSettings.displayChatImages !== checked) {
localAccountSensitiveSettings.displayChatImages = checked
}
}
}
]
sensor.onClicked: {
imageSwitch.checked = !imageSwitch.checked
}
}
Repeater {
id: sitesListView
model: previewableSites
delegate: Component {
StatusListItem {
property alias whitelistSwitch: siteSwitch
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
implicitHeight: 64
title: model.title
subTitle: model.address
image.source: {
let filename;
switch (model.title.toLowerCase()) {
case "youtube":
case "youtube shortener":
filename = "youtube"; break;
case "github":
filename = "github"; break;
case "medium":
filename = "medium"; break;
case "tenor gifs":
filename = "tenor"; break;
case "giphy gifs":
case "giphy gifs shortener":
case "giphy gifs subdomain":
filename = "giphy"; break;
case "github":
filename = "github"; break;
case "status":
filename = "status"; break;
// TODO get a good default icon
default: filename = "../globe"
}
return Style.svg(`linkPreviewThumbnails/${filename}`)
}
components: [
StatusSwitch {
id: siteSwitch
checked: !!model.isWhitelisted
onCheckedChanged: {
let settings = localAccountSensitiveSettings.whitelistedUnfurlingSites
if (!settings) {
settings = {}
}
if (settings[address] === this.checked) {
return
}
settings[address] = this.checked
localAccountSensitiveSettings.whitelistedUnfurlingSites = settings
if (!settings) {
settings = {}
}
if (settings[address] === this.checked) {
return
}
settings[address] = this.checked
localAccountSensitiveSettings.whitelistedUnfurlingSites = settings
}
]
sensor.onClicked: {
siteSwitch.checked = !siteSwitch.checked
}
]
sensor.onClicked: {
siteSwitch.checked = !siteSwitch.checked
}
}
}
} // Site Column
Separator {
id: separator3
visible: siteColumn.visible
}
} // Site Column
// SYNC WAKU SECTION
StatusSectionHeadline {
text: qsTr("Message syncing")
width: parent.width
}
Separator {
id: separator3
visible: siteColumn.visible
Layout.fillWidth: true
}
StatusListItem {
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
title: qsTr("Waku nodes")
label: root.messagingStore.getMailserverNameForNodeAddress(root.messagingStore.activeMailserver)
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
sensor.onClicked: Global.openPopup(wakuNodeModalComponent)
}
// SYNC WAKU SECTION
StatusSectionHeadline {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Message syncing")
}
Component {
id: wakuNodeModalComponent
WakuNodesModal {
messagingStore: root.messagingStore
StatusListItem {
Layout.fillWidth: true
title: qsTr("Waku nodes")
label: root.messagingStore.getMailserverNameForNodeAddress(root.messagingStore.activeMailserver)
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
}
]
sensor.onClicked: Global.openPopup(wakuNodeModalComponent)
}
StatusSectionHeadline {
text: qsTr("For security reasons, private chat history won't be synced.")
width: parent.width
Component {
id: wakuNodeModalComponent
WakuNodesModal {
messagingStore: root.messagingStore
}
} // Column
} // Item
} // ScrollView
}
StatusSectionHeadline {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("For security reasons, private chat history won't be synced.")
}
}
}

View File

@ -1,7 +1,6 @@
import QtQuick 2.13
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.13
import utils 1.0
import shared 1.0
@ -17,170 +16,168 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
ColumnLayout {
SettingsContentBase {
id: root
property ProfileStore profileStore
property int profileContentWidth
clip: true
spacing: 16
ColumnLayout {
spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth
Item {
Layout.preferredHeight: 32
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
RowLayout {
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: root.profileContentWidth
StatusBaseText {
id: profileName
text: root.profileStore.name
font.weight: Font.Bold
font.pixelSize: 20
color: Theme.palette.directColor1
}
StatusBaseText {
id: profileName
StatusButton {
text: "Edit"
onClicked: Global.openPopup(displayNamePopupComponent)
}
text: root.profileStore.name
font.weight: Font.Bold
font.pixelSize: 20
color: Theme.palette.directColor1
Item {
Layout.fillWidth: true
}
StatusFlatRoundButton {
id: qrCodeButton
Layout.preferredWidth: 32
Layout.preferredHeight: 32
icon.name: "qr"
type: StatusFlatRoundButton.Type.Quaternary
onClicked: qrCodePopup.open()
}
}
StatusButton {
text: "Edit"
onClicked: Global.openPopup(displayNamePopupComponent)
}
Item {
Separator {
Layout.fillWidth: true
}
StatusFlatRoundButton {
id: qrCodeButton
ProfileHeader {
id: profileImgNameContainer
Layout.preferredWidth: 32
Layout.preferredHeight: 32
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
icon.name: "qr"
type: StatusFlatRoundButton.Type.Quaternary
onClicked: qrCodePopup.open()
}
}
displayName: profileStore.name
pubkey: profileStore.pubkey
icon: profileStore.icon
Separator {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: root.profileContentWidth
}
displayNameVisible: false
pubkeyVisible: false
ProfileHeader {
id: profileImgNameContainer
imageWidth: 80
imageHeight: 80
emojiSize: Qt.size(20,20)
supersampling: true
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: root.profileContentWidth
imageOverlay: Item {
StatusFlatRoundButton {
width: 24
height: 24
displayName: profileStore.name
pubkey: profileStore.pubkey
icon: profileStore.icon
anchors {
right: parent.right
bottom: parent.bottom
rightMargin: -8
}
displayNameVisible: false
pubkeyVisible: false
type: StatusFlatRoundButton.Type.Secondary
icon.name: "pencil"
icon.color: Theme.palette.directColor1
icon.width: 12.5
icon.height: 12.5
imageWidth: 80
imageHeight: 80
emojiSize: Qt.size(20,20)
supersampling: true
imageOverlay: Item {
StatusFlatRoundButton {
width: 24
height: 24
anchors {
right: parent.right
bottom: parent.bottom
rightMargin: -8
onClicked: Global.openChangeProfilePicPopup()
}
}
}
type: StatusFlatRoundButton.Type.Secondary
icon.name: "pencil"
icon.color: Theme.palette.directColor1
icon.width: 12.5
icon.height: 12.5
StatusDescriptionListItem {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
onClicked: Global.openChangeProfilePicPopup()
title: qsTr("ENS username")
subTitle: root.profileStore.ensName
tooltip.text: qsTr("Copy to clipboard")
icon.name: "copy"
visible: !!root.profileStore.ensName
iconButton.onClicked: {
root.profileStore.copyToClipboard(root.profileStore.ensName)
tooltip.visible = !tooltip.visible
}
}
StatusDescriptionListItem {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
title: qsTr("Chat key")
subTitle: Utils.getCompressedPk(root.profileStore.pubkey)
subTitleComponent.elide: Text.ElideMiddle
subTitleComponent.width: 320
subTitleComponent.font.family: Theme.palette.monoFont.name
tooltip.text: qsTr("Copy to clipboard")
icon.name: "copy"
iconButton.onClicked: {
root.profileStore.copyToClipboard(subTitle)
tooltip.visible = !tooltip.visible
}
}
StatusDescriptionListItem {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
title: qsTr("Share Profile URL")
subTitle: `${Constants.userLinkPrefix}${root.profileStore.ensName !== "" ? root.profileStore.ensName : (root.profileStore.pubkey.substring(0, 5) + "..." + root.profileStore.pubkey.substring(root.profileStore.pubkey.length - 5))}`
tooltip.text: qsTr("Copy to clipboard")
icon.name: "copy"
iconButton.onClicked: {
root.profileStore.copyToClipboard(Constants.userLinkPrefix + (root.profileStore.ensName !== "" ? root.profileStore.ensName : root.profileStore.pubkey))
tooltip.visible = !tooltip.visible
}
}
Component {
id: displayNamePopupComponent
DisplayNamePopup {
profileStore: root.profileStore
anchors.centerIn: Overlay.overlay
onClosed: { destroy() }
}
}
ModalPopup {
id: qrCodePopup
width: 420
height: 420
Image {
asynchronous: true
fillMode: Image.PreserveAspectFit
source: root.profileStore.getQrCodeSource(root.profileStore.pubkey)
anchors.verticalCenterOffset: 20
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
height: 312
width: 312
mipmap: true
smooth: false
}
}
}
StatusDescriptionListItem {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: root.profileContentWidth
title: qsTr("ENS username")
subTitle: root.profileStore.ensName
tooltip.text: qsTr("Copy to clipboard")
icon.name: "copy"
visible: !!root.profileStore.ensName
iconButton.onClicked: {
root.profileStore.copyToClipboard(root.profileStore.ensName)
tooltip.visible = !tooltip.visible
}
}
StatusDescriptionListItem {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: root.profileContentWidth
title: qsTr("Chat key")
subTitle: Utils.getCompressedPk(root.profileStore.pubkey)
subTitleComponent.elide: Text.ElideMiddle
subTitleComponent.width: 320
subTitleComponent.font.family: Theme.palette.monoFont.name
tooltip.text: qsTr("Copy to clipboard")
icon.name: "copy"
iconButton.onClicked: {
root.profileStore.copyToClipboard(subTitle)
tooltip.visible = !tooltip.visible
}
}
StatusDescriptionListItem {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: root.profileContentWidth
title: qsTr("Share Profile URL")
subTitle: `${Constants.userLinkPrefix}${root.profileStore.ensName !== "" ? root.profileStore.ensName : (root.profileStore.pubkey.substring(0, 5) + "..." + root.profileStore.pubkey.substring(root.profileStore.pubkey.length - 5))}`
tooltip.text: qsTr("Copy to clipboard")
icon.name: "copy"
iconButton.onClicked: {
root.profileStore.copyToClipboard(Constants.userLinkPrefix + (root.profileStore.ensName !== "" ? root.profileStore.ensName : root.profileStore.pubkey))
tooltip.visible = !tooltip.visible
}
}
Component {
id: displayNamePopupComponent
DisplayNamePopup {
profileStore: root.profileStore
anchors.centerIn: Overlay.overlay
onClosed: { destroy() }
}
}
ModalPopup {
id: qrCodePopup
width: 420
height: 420
Image {
asynchronous: true
fillMode: Image.PreserveAspectFit
source: root.profileStore.getQrCodeSource(root.profileStore.pubkey)
anchors.verticalCenterOffset: 20
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
height: 312
width: 312
mipmap: true
smooth: false
}
}
}

View File

@ -17,22 +17,14 @@ import "../popups"
import "../panels"
import "./"
ScrollView {
SettingsContentBase {
id: root
property NotificationsStore notificationsStore
property int profileContentWidth
height: parent.height
width: parent.width
contentHeight: notificationsContainer.height
clip: true
Item {
id: notificationsContainer
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
width: root.contentWidth
height: this.childrenRect.height + 100
property Component mutedChatsModalComponent: MutedChatsModal {}
@ -50,23 +42,15 @@ ScrollView {
id: messageSetting
}
StatusSectionHeadline {
id: sectionHeadlineNotifications
//% "Notification preferences"
text: qsTrId("notifications-preferences")
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
}
Column {
id: column
anchors.top: sectionHeadlineNotifications.bottom
anchors.topMargin: Style.current.smallPadding
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
RadioButtonSelector {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "All messages"
title: qsTrId("all-messages")
buttonGroup: notificationSetting
@ -79,6 +63,8 @@ ScrollView {
}
RadioButtonSelector {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Just @mentions"
title: qsTrId("just--mentions")
buttonGroup: notificationSetting
@ -91,6 +77,8 @@ ScrollView {
}
RadioButtonSelector {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Nothing"
title: qsTrId("nothing")
buttonGroup: notificationSetting
@ -108,9 +96,7 @@ ScrollView {
anchors.top: column.bottom
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
}
StatusSectionHeadline {
@ -120,6 +106,8 @@ ScrollView {
anchors.top: separator.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
}
Column {
@ -132,6 +120,8 @@ ScrollView {
// TODO: replace with StatusListItem
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Play a sound when receiving a notification"
text: qsTrId("play-a-sound-when-receiving-a-notification")
isSwitch: true
@ -143,6 +133,8 @@ ScrollView {
// TODO: replace with StatusListItem
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Use your operating system's notifications"
text: qsTrId("use-your-operating-system-s-notifications")
isSwitch: true
@ -181,12 +173,13 @@ ScrollView {
font.pixelSize: 15
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
color: Theme.palette.directColor1
}
Column {
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
spacing: 10
@ -241,6 +234,8 @@ ScrollView {
text: qsTrId("no-preview-or-advanced--go-to-notification-center")
font.pixelSize: 15
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
color: Theme.palette.directColor1
}
}
@ -250,9 +245,7 @@ ScrollView {
anchors.top: column3.bottom
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
}
StatusSectionHeadline {
@ -262,6 +255,8 @@ ScrollView {
anchors.top: separator2.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
}
Column {
@ -274,6 +269,8 @@ ScrollView {
// TODO: replace with StatusListItem
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Notify on new requests"
text: qsTrId("notify-on-new-requests")
isSwitch: true
@ -285,6 +282,8 @@ ScrollView {
// TODO: replace with StatusListItem
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Muted users"
text: qsTrId("muted-users")
currentValue: root.notificationsStore.mutedContactsModel.count > 0 ?
@ -309,6 +308,8 @@ ScrollView {
// TODO: replace with StatusListItem
StatusSettingsLineButton {
anchors.leftMargin: 0
anchors.rightMargin: 0
//% "Muted chats"
text: qsTrId("muted-chats")
currentValue: root.notificationsStore.mutedChatsModel.count > 0 ?
@ -350,9 +351,7 @@ ScrollView {
anchors.top: column4.bottom
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
}
Column {
@ -365,6 +364,10 @@ ScrollView {
width: parent.width
StatusBaseText {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
//% "Reset notification settings"
text: qsTrId("reset-notification-settings")
font.pixelSize: 15
@ -389,6 +392,10 @@ ScrollView {
}
StatusBaseText {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
//% "Restore default notification settings and unmute all chats and users"
text: qsTrId("restore-default-notification-settings-and-unmute-all-chats-and-users")
font.pixelSize: 15

View File

@ -15,37 +15,18 @@ import StatusQ.Controls 0.1 as StatusQControls
import "../popups"
import "../stores"
Item {
SettingsContentBase {
id: root
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
property PrivacyStore privacyStore
property int profileContentWidth
Column {
id: containerColumn
anchors.top: parent.top
anchors.topMargin: 64
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
StatusSectionHeadline {
id: labelSecurity
//% "Security"
text: qsTrId("security")
bottomPadding: Style.current.halfPadding
}
ColumnLayout {
spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth
StatusListItem {
id: backupSeedPhrase
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
Layout.fillWidth: true
//% "Backup Seed Phrase"
title: qsTrId("backup-seed-phrase")
enabled: !root.privacyStore.mnemonicBackedUp
@ -66,10 +47,7 @@ Item {
}
StatusListItem {
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
Layout.fillWidth: true
title: qsTr("Change password")
implicitHeight: 52
components: [
@ -83,10 +61,7 @@ Item {
}
StatusListItem {
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
Layout.fillWidth: true
title: qsTr("Store pass to Keychain")
implicitHeight: 52
visible: Qt.platform.os == "osx" // For now, this is available only on MacOS

View File

@ -0,0 +1,98 @@
import QtQuick 2.13
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.13
import utils 1.0
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
Item {
id: root
property string sectionTitle
property int contentWidth
property string backButtonName: ""
property alias titleRowComponentLoader: loader
property list<Item> headerComponents
default property Item content
signal backButtonClicked()
QtObject {
id: d
readonly property int topHeaderHeight: 56
readonly property int titleRowHeight: 56
}
Component.onCompleted: {
content.parent = contentWrapper
if (headerComponents.length) {
for (let i in headerComponents) {
headerComponents[i].parent = titleRow
}
}
}
Item {
id: topHeader
anchors.left: parent.left
anchors.top: parent.top
anchors.leftMargin: -Style.current.padding
width: root.contentWidth + Style.current.padding
height: d.topHeaderHeight
StatusFlatButton {
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: Style.current.halfPadding
visible: root.backButtonName != ""
icon.name: "arrow-left"
icon.width: 20
icon.height: 20
text: root.backButtonName
size: StatusBaseButton.Size.Large
onClicked: root.backButtonClicked()
}
}
RowLayout {
id: titleRow
anchors.left: parent.left
anchors.top: topHeader.bottom
anchors.leftMargin: Style.current.padding
width: root.contentWidth - 2 * Style.current.padding
height: d.titleRowHeight
visible: root.sectionTitle !== ""
StatusBaseText {
Layout.fillWidth: true
text: root.sectionTitle
font.weight: Font.Bold
font.pixelSize: Constants.settingsSection.mainHeaderFontSize
color: Theme.palette.directColor1
}
Loader {
id: loader
}
}
ScrollView {
anchors.top: titleRow.visible? titleRow.bottom : topHeader.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: Style.current.bigPadding
clip: true
Column {
id: contentWrapper
}
}
}

View File

@ -8,27 +8,18 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Item {
id: soundsContainer
SettingsContentBase {
id: root
property var store
property int profileContentWidth
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
Item {
width: profileContentWidth
anchors.horizontalCenter: parent.horizontalCenter
ColumnLayout {
spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth
StatusBaseText {
id: labelVolume
anchors.top: parent.top
anchors.topMargin: 24
anchors.left: parent.left
anchors.leftMargin: 24
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
//% "Sound volume"
text: qsTrId("sound-volume") + " " + volume.value.toPrecision(1)
font.pixelSize: 15
@ -37,10 +28,9 @@ Item {
StatusSlider {
id: volume
anchors.top: labelVolume.bottom
anchors.topMargin: Style.current.padding
anchors.left: parent.left
anchors.leftMargin: 24
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
from: 0.0
to: 1.0
stepSize: 0.1

View File

@ -17,82 +17,96 @@ import "../popups"
import "../panels"
import "./wallet"
Item {
SettingsContentBase {
id: root
property var emojiPopup
property WalletStore walletStore
anchors.fill: parent
readonly property int mainViewIndex: 0;
readonly property int networksViewIndex: 1;
readonly property int accountViewIndex: 2;
readonly property int dappPermissionViewIndex: 3;
StatusBanner {
id: banner
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
visible: walletStore.areTestNetworksEnabled
type: StatusBanner.Type.Danger
statusText: qsTr("Testnet mode is enabled. All balances, transactions and dApp interactions will be on testnets.")
onBackButtonClicked: {
stackContainer.currentIndex = mainViewIndex
}
ScrollView {
StackLayout {
id: stackContainer
anchors.top: banner.visible ? banner.bottom: parent.top
anchors.bottom: parent.bottom
clip: true
width: root.contentWidth
currentIndex: mainViewIndex
StackLayout {
id: stackContainer
onCurrentIndexChanged: {
root.backButtonName = ""
root.sectionTitle = qsTr("Wallet")
root.titleRowComponentLoader.sourceComponent = undefined
anchors.fill: parent
currentIndex: mainViewIndex
if(currentIndex == root.networksViewIndex) {
root.backButtonName = qsTr("Wallet")
root.sectionTitle = qsTr("Networks")
MainView {
id: main
Layout.preferredWidth: 560
leftPadding: 64
topPadding: 64
walletStore: root.walletStore
root.titleRowComponentLoader.sourceComponent = testnetModeSwitchComponent
}
else if(currentIndex == root.accountViewIndex) {
root.backButtonName = qsTr("Wallet")
root.sectionTitle = ""
}
else if(currentIndex == root.dappPermissionViewIndex) {
root.backButtonName = qsTr("Wallet")
root.sectionTitle = qsTr("DApp Permissions")
}
}
onGoToNetworksView: {
stackContainer.currentIndex = networksViewIndex
}
MainView {
id: main
onGoToAccountView: {
root.walletStore.switchAccountByAddress(address)
stackContainer.currentIndex = accountViewIndex
}
Layout.fillWidth: true
onGoToDappPermissionsView: {
stackContainer.currentIndex = dappPermissionViewIndex
}
walletStore: root.walletStore
onGoToNetworksView: {
stackContainer.currentIndex = networksViewIndex
}
NetworksView {
walletStore: root.walletStore
onGoBack: {
stackContainer.currentIndex = mainViewIndex
}
onGoToAccountView: {
root.walletStore.switchAccountByAddress(address)
stackContainer.currentIndex = accountViewIndex
}
AccountView {
walletStore: root.walletStore
emojiPopup: root.emojiPopup
onGoBack: {
stackContainer.currentIndex = mainViewIndex
}
onGoToDappPermissionsView: {
stackContainer.currentIndex = dappPermissionViewIndex
}
}
DappPermissionsView {
walletStore: root.walletStore
onGoBack: {
stackContainer.currentIndex = mainViewIndex
}
NetworksView {
walletStore: root.walletStore
onGoBack: {
stackContainer.currentIndex = mainViewIndex
}
}
AccountView {
walletStore: root.walletStore
emojiPopup: root.emojiPopup
onGoBack: {
stackContainer.currentIndex = mainViewIndex
}
}
DappPermissionsView {
walletStore: root.walletStore
}
Component {
id: testnetModeSwitchComponent
StatusSwitch {
text: qsTr("Testnet Mode")
checked: walletStore.areTestNetworksEnabled
onClicked: walletStore.toggleTestNetworksEnabled()
}
}
}

View File

@ -19,28 +19,13 @@ Item {
property WalletStore walletStore
property var emojiPopup
StatusFlatButton {
id: backButton
anchors.top: parent.top
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.bigPadding
icon.name: "arrow-left"
icon.height: 13.5
icon.width: 17.5
text: qsTr("Wallet")
onClicked: {
root.goBack()
}
}
Column {
id: column
anchors.topMargin: Style.current.xlPadding
anchors.top: backButton.bottom
anchors.leftMargin: Style.current.xlPadding * 2
anchors.left: root.left
width: 560
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
Row {
id: header

View File

@ -12,46 +12,15 @@ import "../../controls"
Item {
id: root
signal goBack
property WalletStore walletStore
StatusFlatButton {
id: backButton
anchors.top: parent.top
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.bigPadding
icon.name: "arrow-left"
icon.height: 13.5
icon.width: 17.5
text: qsTr("Wallet")
onClicked: {
root.goBack()
}
}
Column {
id: column
anchors.topMargin: Style.current.xlPadding
anchors.top: backButton.bottom
anchors.leftMargin: Style.current.xlPadding * 2
anchors.left: root.left
width: 560
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
StatusBaseText {
id: titleText
text: qsTr("DApp Permissions")
font.weight: Font.Bold
font.pixelSize: 28
color: Theme.palette.directColor1
}
Item {
height: Style.current.bigPadding
width: parent.width
}
PermissionsListView {
id: permissionsList
width: parent.width

View File

@ -20,19 +20,6 @@ Column {
signal goToAccountView(address: string)
signal goToDappPermissionsView()
StatusBaseText {
id: titleText
text: qsTr("Wallet")
font.weight: Font.Bold
font.pixelSize: 28
color: Theme.palette.directColor1
}
Item {
height: Style.current.bigPadding
width: parent.width
}
StatusListItem {
title: qsTr("Manage Assets & List")
height: 64

View File

@ -15,52 +15,11 @@ Item {
property WalletStore walletStore
StatusFlatButton {
id: backButton
anchors.top: parent.top
anchors.topMargin: Style.current.bigPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.bigPadding
icon.name: "arrow-left"
icon.height: 13.5
icon.width: 17.5
text: qsTr("Wallet")
onClicked: {
root.goBack()
}
}
Column {
id: column
anchors.topMargin: Style.current.xlPadding
anchors.top: backButton.bottom
anchors.leftMargin: Style.current.xlPadding * 2
anchors.left: root.left
width: 560
Row {
spacing: 200
StatusBaseText {
id: titleText
text: qsTr("Networks")
font.weight: Font.Bold
font.pixelSize: 28
color: Theme.palette.directColor1
}
StatusSwitch {
text: qsTr("Testnet Mode")
checked: walletStore.areTestNetworksEnabled
onClicked: walletStore.toggleTestNetworksEnabled()
}
}
Item {
height: Style.current.bigPadding
width: parent.width
}
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
Repeater {
id: layer1List
@ -71,6 +30,8 @@ Item {
}
StatusSectionHeadline {
leftPadding: Style.current.padding
rightPadding: Style.current.padding
text: qsTr("Layer 2")
topPadding: Style.current.bigPadding
bottomPadding: Style.current.padding

View File

@ -13,8 +13,6 @@ Column {
property WalletStore walletStore
width: 560
Repeater {
id: permissionsList
model: walletStore.dappList

View File

@ -149,6 +149,11 @@ QtObject {
]
}
readonly property QtObject settingsSection: QtObject {
readonly property int itemSpacing: 10
readonly property int mainHeaderFontSize: 28
}
readonly property int communityImported: 0
readonly property int communityImportingInProgress: 1
readonly property int communityImportingError: 2