mirror of
https://github.com/status-im/status-app.git
synced 2026-08-27 07:01:14 +00:00
chore(AppMain): unify the global banner
- extract to a separate component, based on simple properties and signals - fix some layout issues in the underlying ModuleWarning component - removed a duplicate seedphrase banner from the wallet section itself - add to storybook, covered with QML tests Fixes #18339
This commit is contained in:
@@ -39,9 +39,6 @@ proc init*(self: Controller) =
|
||||
proc getCurrency*(self: Controller): string =
|
||||
return self.settingsService.getCurrency()
|
||||
|
||||
proc isMnemonicBackedUp*(self: Controller): bool =
|
||||
return self.settingsService.getMnemonic().len > 0
|
||||
|
||||
proc getTotalCurrencyBalance*(self: Controller, addresses: seq[string], chainIds: seq[int]): CurrencyAmount =
|
||||
return currencyAmountToItem(self.walletAccountService.getTotalCurrencyBalance(addresses, chainIds), self.currencyService.getCurrencyFormat(self.getCurrency()))
|
||||
|
||||
|
||||
@@ -399,8 +399,6 @@ proc checkIfModuleDidLoad(self: Module) =
|
||||
if(not self.networksModule.isLoaded()):
|
||||
return
|
||||
|
||||
let mnemonicBackedUp = self.controller.isMnemonicBackedUp()
|
||||
self.view.setData(mnemonicBackedUp)
|
||||
self.setTotalCurrencyBalance()
|
||||
self.filter.setAddresses(self.getWalletAddressesNotHidden())
|
||||
self.filter.load()
|
||||
|
||||
@@ -15,7 +15,6 @@ QtObject:
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
totalCurrencyBalance: CurrencyAmount
|
||||
isMnemonicBackedUp: bool
|
||||
tmpAmount: float # shouldn't be used anywhere except in prepare*/getPrepared* procs
|
||||
tmpSymbol: string # shouldn't be used anywhere except in prepare*/getPrepared* procs
|
||||
activityController: activityc.Controller
|
||||
@@ -79,12 +78,6 @@ QtObject:
|
||||
read = getTotalCurrencyBalance
|
||||
notify = totalCurrencyBalanceChanged
|
||||
|
||||
proc getIsMnemonicBackedUp(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.isMnemonicBackedUp)
|
||||
|
||||
QtProperty[QVariant] isMnemonicBackedUp:
|
||||
read = getIsMnemonicBackedUp
|
||||
|
||||
proc addressFiltersChanged*(self: View) {.signal.}
|
||||
proc setAddressFilters*(self: View, address: string) =
|
||||
self.addressFilters = address
|
||||
@@ -122,9 +115,6 @@ QtObject:
|
||||
self.tmpSymbol = "ERROR"
|
||||
return newQVariant(currencyAmount)
|
||||
|
||||
proc setData*(self: View, mnemonicBackedUp: bool) =
|
||||
self.isMnemonicBackedUp = mnemonicBackedUp
|
||||
|
||||
proc runAddAccountPopup*(self: View, addingWatchOnlyAccount: bool) {.slot.} =
|
||||
self.delegate.runAddAccountPopup(addingWatchOnlyAccount)
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Storybook
|
||||
|
||||
import utils
|
||||
import mainui
|
||||
|
||||
SplitView {
|
||||
Logs { id: logs }
|
||||
|
||||
orientation: Qt.Vertical
|
||||
SplitView.fillWidth: true
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property bool userDeclinedBackupBanner
|
||||
property bool testnetEnabled
|
||||
}
|
||||
|
||||
Item {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
ColumnLayout {
|
||||
width: ctrlWidth.value
|
||||
anchors.centerIn: parent
|
||||
|
||||
Label {
|
||||
text: "Online > Testnet > Seedphrase"
|
||||
}
|
||||
Label {
|
||||
text: "Width: %1; visible: %2".arg(parent.width).arg(banner.visible ? "true" : "false")
|
||||
}
|
||||
|
||||
GlobalBanner {
|
||||
id: banner
|
||||
Tracer { border.color: "blue" }
|
||||
|
||||
Layout.fillWidth: true
|
||||
isOnline: ctrlIsOnline.checked
|
||||
testnetEnabled: d.testnetEnabled
|
||||
seedphraseBackedUp: d.userDeclinedBackupBanner
|
||||
|
||||
onOpenTestnetPopupRequested: {
|
||||
logs.logEvent("onOpenTestnetPopupRequested")
|
||||
d.testnetEnabled = false
|
||||
}
|
||||
onOpenBackUpSeedPopupRequested: {
|
||||
logs.logEvent("onOpenBackUpSeedPopupRequested")
|
||||
}
|
||||
onUserDeclinedBackupBannerRequested: {
|
||||
logs.logEvent("onUserDeclinedBackupBannerRequested")
|
||||
d.userDeclinedBackupBanner = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogsAndControlsPanel {
|
||||
SplitView.minimumHeight: 150
|
||||
SplitView.preferredHeight: 150
|
||||
|
||||
logsView.logText: logs.logText
|
||||
|
||||
RowLayout {
|
||||
Switch {
|
||||
id: ctrlIsOnline
|
||||
text: "Online"
|
||||
checked: true
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: ctrlTestnetEnabled
|
||||
text: "Testnet"
|
||||
checked: d.testnetEnabled
|
||||
onToggled: d.testnetEnabled = checked
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: ctrlUserDeclinedBackupBanner
|
||||
text: "Seedphrase backed up"
|
||||
checked: d.userDeclinedBackupBanner
|
||||
onToggled: d.userDeclinedBackupBanner = checked
|
||||
}
|
||||
|
||||
ToolSeparator {}
|
||||
|
||||
Label { text: "Width:" }
|
||||
Slider {
|
||||
id: ctrlWidth
|
||||
from: 100
|
||||
to: 1000
|
||||
value: 600
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// category: Components
|
||||
// status: good
|
||||
@@ -0,0 +1,123 @@
|
||||
import QtQuick
|
||||
import QtTest
|
||||
|
||||
import mainui
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 800
|
||||
height: 600
|
||||
|
||||
Component {
|
||||
id: componentUnderTest
|
||||
GlobalBanner {
|
||||
anchors.centerIn: parent
|
||||
width: 600
|
||||
isOnline: false
|
||||
testnetEnabled: false
|
||||
seedphraseBackedUp: false
|
||||
}
|
||||
}
|
||||
|
||||
SignalSpy {
|
||||
id: testNetButtonSignalSpy
|
||||
target: controlUnderTest
|
||||
signalName: "openTestnetPopupRequested"
|
||||
}
|
||||
|
||||
SignalSpy {
|
||||
id: seedphraseButtonSignalSpy
|
||||
target: controlUnderTest
|
||||
signalName: "openBackUpSeedPopupRequested"
|
||||
}
|
||||
|
||||
SignalSpy {
|
||||
id: seedphraseCloseButtonSignalSpy
|
||||
target: controlUnderTest
|
||||
signalName: "userDeclinedBackupBannerRequested"
|
||||
}
|
||||
|
||||
property GlobalBanner controlUnderTest: null
|
||||
|
||||
TestCase {
|
||||
name: "GlobalBanner"
|
||||
when: windowShown
|
||||
|
||||
function init() {
|
||||
testNetButtonSignalSpy.clear()
|
||||
seedphraseButtonSignalSpy.clear()
|
||||
seedphraseCloseButtonSignalSpy.clear()
|
||||
}
|
||||
|
||||
function test_basicGeometry() {
|
||||
controlUnderTest = createTemporaryObject(componentUnderTest, root)
|
||||
verify(!!controlUnderTest)
|
||||
tryVerify(() => controlUnderTest.width > 0)
|
||||
tryVerify(() => controlUnderTest.height > 0)
|
||||
}
|
||||
|
||||
// assert that at most 1 banner is displayed at any given time, and it's the correct one
|
||||
// "1. Offline/online > 2. Testnet > 3. Seedphrase"
|
||||
function test_variations_data() {
|
||||
return [
|
||||
// offline/online banner
|
||||
{isOnline: false, testnetEnabled: false, seedphraseBackedUp: false, banner: "connectionInfoBanner"},
|
||||
{isOnline: false, testnetEnabled: true, seedphraseBackedUp: false, banner: "connectionInfoBanner"},
|
||||
{isOnline: false, testnetEnabled: false, seedphraseBackedUp: true, banner: "connectionInfoBanner"},
|
||||
{isOnline: false, testnetEnabled: true, seedphraseBackedUp: true, banner: "connectionInfoBanner"},
|
||||
|
||||
// testnet banner
|
||||
{isOnline: true, testnetEnabled: true, seedphraseBackedUp: false, banner: "testnetBanner"},
|
||||
{isOnline: true, testnetEnabled: true, seedphraseBackedUp: true, banner: "testnetBanner"},
|
||||
|
||||
// seedphrase banner
|
||||
{isOnline: true, testnetEnabled: false, seedphraseBackedUp: false, banner: "secureYourSeedPhraseBanner"},
|
||||
|
||||
// no banner
|
||||
{isOnline: true, testnetEnabled: false, seedphraseBackedUp: true, banner: ""},
|
||||
]
|
||||
}
|
||||
|
||||
function test_variations(data) {
|
||||
controlUnderTest = createTemporaryObject(componentUnderTest, root, data)
|
||||
verify(!!controlUnderTest)
|
||||
if (!!data.banner) {
|
||||
tryCompare(controlUnderTest.item, "objectName", data.banner)
|
||||
tryCompare(controlUnderTest.item, "visible", true)
|
||||
} else {
|
||||
tryVerify(() => controlUnderTest.item === null) // no banner, not visible at all
|
||||
}
|
||||
}
|
||||
|
||||
// test that the testnet banner's button emits the right signal to open the resp. popup
|
||||
function test_testnet_button() {
|
||||
controlUnderTest = createTemporaryObject(componentUnderTest, root,
|
||||
{isOnline: true, testnetEnabled: true, seedphraseBackedUp: false})
|
||||
verify(!!controlUnderTest)
|
||||
tryCompare(controlUnderTest.item, "objectName", "testnetBanner")
|
||||
|
||||
const btn = findChild(controlUnderTest.item, "actionButton")
|
||||
verify(!!btn)
|
||||
mouseClick(btn)
|
||||
compare(testNetButtonSignalSpy.count, 1)
|
||||
}
|
||||
|
||||
// test that the seedphrase banner's buttons emit the right signals to open the resp. popup
|
||||
function test_seedphrase_buttons() {
|
||||
controlUnderTest = createTemporaryObject(componentUnderTest, root,
|
||||
{isOnline: true, testnetEnabled: false, seedphraseBackedUp: false})
|
||||
verify(!!controlUnderTest)
|
||||
tryCompare(controlUnderTest.item, "objectName", "secureYourSeedPhraseBanner")
|
||||
|
||||
const btn = findChild(controlUnderTest.item, "actionButton")
|
||||
verify(!!btn)
|
||||
mouseClick(btn)
|
||||
compare(seedphraseButtonSignalSpy.count, 1)
|
||||
|
||||
const closeBtn = findChild(controlUnderTest.item, "closeButton")
|
||||
verify(!!closeBtn)
|
||||
mouseClick(closeBtn)
|
||||
compare(seedphraseCloseButtonSignalSpy.count, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ QtObject {
|
||||
property var privacyModule
|
||||
|
||||
// Module Properties
|
||||
property bool mnemonicBackedUp: privacyModule.mnemonicBackedUp
|
||||
readonly property bool mnemonicBackedUp: privacyModule.mnemonicBackedUp
|
||||
readonly property string keyUid: userProfile.keyUid
|
||||
|
||||
// The following properties wrap Privacy and Security View related properties:
|
||||
|
||||
@@ -24,7 +24,7 @@ QtObject {
|
||||
property string preferredName: userProfile.preferredName
|
||||
property string profileLargeImage: userProfile.largeImage
|
||||
property string icon: userProfile.icon
|
||||
property bool userDeclinedBackupBanner: Global.appIsReady? localAccountSensitiveSettings.userDeclinedBackupBanner : false
|
||||
readonly property bool userDeclinedBackupBanner: Global.appIsReady? localAccountSensitiveSettings.userDeclinedBackupBanner : false
|
||||
readonly property string keyUid: userProfile.keyUid
|
||||
readonly property bool isKeycardUser: userProfile.isKeycardUser
|
||||
readonly property int currentUserStatus: userProfile.currentUserStatus
|
||||
@@ -143,9 +143,7 @@ QtObject {
|
||||
root.profileModule.setIsFirstShowcaseInteraction()
|
||||
}
|
||||
|
||||
onUserDeclinedBackupBannerChanged: {
|
||||
if (userDeclinedBackupBanner !== localAccountSensitiveSettings.userDeclinedBackupBanner) {
|
||||
localAccountSensitiveSettings.userDeclinedBackupBanner = userDeclinedBackupBanner
|
||||
}
|
||||
function setUserDeclinedBackupBanner(value = true) {
|
||||
localAccountSensitiveSettings.userDeclinedBackupBanner = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,12 +213,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
SeedPhraseBackupWarning {
|
||||
id: seedPhraseWarning
|
||||
width: parent.width
|
||||
anchors.top: parent.top
|
||||
}
|
||||
|
||||
Component {
|
||||
id: cmpSavedAddresses
|
||||
SavedAddressesView {
|
||||
@@ -281,9 +275,7 @@ Item {
|
||||
StatusSectionLayout {
|
||||
id: walletSectionLayout
|
||||
navBar: root.navBar
|
||||
anchors.top: seedPhraseWarning.bottom
|
||||
height: root.height - seedPhraseWarning.height
|
||||
width: root.width
|
||||
anchors.fill: parent
|
||||
backButtonName: RootStore.backButtonName
|
||||
notificationCount: activityCenterStore.unreadNotificationsCount
|
||||
hasUnseenNotifications: activityCenterStore.hasUnseenNotifications
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import StatusQ.Core
|
||||
import StatusQ.Core.Theme
|
||||
|
||||
import utils
|
||||
import shared
|
||||
import shared.panels
|
||||
import "../stores"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
height: visible ? 32 : 0
|
||||
visible: !RootStore.mnemonicBackedUp
|
||||
color: Theme.palette.dangerColor1
|
||||
|
||||
Row {
|
||||
spacing: Theme.halfPadding
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Back up your recovery phrase")
|
||||
font.pixelSize: Theme.additionalTextSize
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Theme.palette.white
|
||||
}
|
||||
|
||||
Button {
|
||||
width: 58
|
||||
height: 24
|
||||
contentItem: Item {
|
||||
anchors.fill: parent
|
||||
Text {
|
||||
text: qsTr("Back up")
|
||||
font.pixelSize: Theme.additionalTextSize
|
||||
font.weight: Font.Medium
|
||||
font.family: Theme.baseFont.name
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: Theme.palette.white
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
border.color: Theme.palette.white
|
||||
color: "#19FFFFFF"
|
||||
}
|
||||
StatusMouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: Global.openBackUpSeedPopup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SVGImage {
|
||||
id: closeImg
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 18
|
||||
source: Theme.svg("close-white")
|
||||
height: 20
|
||||
width: 20
|
||||
}
|
||||
ColorOverlay {
|
||||
anchors.fill: closeImg
|
||||
source: closeImg
|
||||
color: Theme.palette.white
|
||||
opacity: 0.7
|
||||
}
|
||||
StatusMouseArea {
|
||||
anchors.fill: closeImg
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: ParallelAnimation {
|
||||
PropertyAnimation { target: root; property: "visible"; to: false; }
|
||||
PropertyAnimation { target: root; property: "y"; to: -1 * root.height }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,6 @@ QtObject {
|
||||
/* This property holds address of currently selected account in Wallet Main layout */
|
||||
readonly property var addressFilters: walletSectionInst.addressFilters
|
||||
readonly property var keypairImportModule: walletSectionInst.keypairImportModule
|
||||
readonly property string mnemonicBackedUp: walletSectionInst.isMnemonicBackedUp
|
||||
|
||||
readonly property var transactionActivityStatus: walletSectionInst.activityController.status
|
||||
|
||||
|
||||
+20
-163
@@ -3,7 +3,6 @@ import QtQml
|
||||
import QtQuick
|
||||
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Window
|
||||
import QtQuick.Layouts
|
||||
import QtQml.Models
|
||||
|
||||
@@ -827,6 +826,8 @@ Item {
|
||||
|
||||
property var activityCenterPopupObj: null
|
||||
|
||||
readonly property int activeSectionType: appMain.rootStore.activeSectionType
|
||||
|
||||
function openActivityCenterPopup() {
|
||||
if (!activityCenterPopupObj) {
|
||||
activityCenterPopupObj = activityCenterPopupComponent.createObject(appMain)
|
||||
@@ -1449,78 +1450,31 @@ Item {
|
||||
id: bannersLayout
|
||||
|
||||
enabled: !localAppSettings.testEnvironment
|
||||
&& appMain.rootStore.activeSectionType !== Constants.appSection.homePage
|
||||
&& d.activeSectionType !== Constants.appSection.homePage
|
||||
&& !SQUtils.Utils.isMobile // Temp disable until we have proper way to handle banners on mobile
|
||||
visible: enabled
|
||||
|
||||
property var updateBanner: null
|
||||
property var connectedBanner: null
|
||||
readonly property bool isConnected: appMain.rootStore.isOnline
|
||||
|
||||
function processUpdateAvailable() {
|
||||
if (!updateBanner)
|
||||
updateBanner = updateBannerComponent.createObject(this)
|
||||
}
|
||||
|
||||
function processConnected() {
|
||||
if (!connectedBanner)
|
||||
connectedBanner = connectedBannerComponent.createObject(this)
|
||||
}
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
// apply left/right margins when we remove the window titlebar
|
||||
Layout.leftMargin: Qt.platform.os === SQUtils.Utils.mac ? appMain.Window.SafeArea.margins.left : 0
|
||||
Layout.rightMargin: Qt.platform.os === SQUtils.Utils.mac ? appMain.Window.SafeArea.margins.right : 0
|
||||
|
||||
Layout.maximumHeight: implicitHeight
|
||||
spacing: 1
|
||||
|
||||
onIsConnectedChanged: {
|
||||
processConnected()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!isConnected)
|
||||
processConnected()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: rootStore.aboutModuleInst
|
||||
function onAppVersionFetched(available: bool, version: string, url: string) {
|
||||
rootStore.setLatestVersionInfo(available, version, url);
|
||||
// TODO when we re-implement check for updates, uncomment this
|
||||
// bannersLayout.processUpdateAvailable()
|
||||
}
|
||||
}
|
||||
|
||||
ModuleWarning {
|
||||
id: testnetBanner
|
||||
objectName: "testnetBanner"
|
||||
GlobalBanner {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Testnet mode enabled. All balances, transactions and dApp interactions will be on testnets.")
|
||||
buttonText: qsTr("Turn off")
|
||||
type: ModuleWarning.Warning
|
||||
iconName: "warning"
|
||||
active: appMain.networksStore.areTestNetworksEnabled
|
||||
delay: false
|
||||
onClicked: Global.openTestnetPopup()
|
||||
closeBtnVisible: false
|
||||
|
||||
isOnline: appMain.rootStore.isOnline
|
||||
testnetEnabled: appMain.networksStore.areTestNetworksEnabled
|
||||
seedphraseBackedUp: appMain.privacyStore.mnemonicBackedUp || appMain.profileStore.userDeclinedBackupBanner
|
||||
|
||||
onOpenTestnetPopupRequested: Global.openTestnetPopup()
|
||||
onOpenBackUpSeedPopupRequested: popups.openBackUpSeedPopup()
|
||||
onUserDeclinedBackupBannerRequested: appMain.profileStore.setUserDeclinedBackupBanner()
|
||||
}
|
||||
|
||||
ModuleWarning {
|
||||
id: secureYourSeedPhrase
|
||||
objectName: "secureYourSeedPhraseBanner"
|
||||
Layout.fillWidth: true
|
||||
active: !appMain.profileStore.userDeclinedBackupBanner
|
||||
&& !appMain.privacyStore.mnemonicBackedUp
|
||||
type: ModuleWarning.Danger
|
||||
text: qsTr("Secure your recovery phrase")
|
||||
buttonText: qsTr("Back up now")
|
||||
delay: false
|
||||
onClicked: popups.openBackUpSeedPopup()
|
||||
|
||||
onCloseClicked: {
|
||||
appMain.profileStore.userDeclinedBackupBanner = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ModuleWarning {
|
||||
Layout.fillWidth: true
|
||||
readonly property int progress: appMain.communitiesStore.discordImportProgress
|
||||
@@ -1576,16 +1530,6 @@ Item {
|
||||
onCloseClicked: hide()
|
||||
}
|
||||
|
||||
ModuleWarning {
|
||||
id: downloadingArchivesBanner
|
||||
Layout.fillWidth: true
|
||||
active: appMain.communitiesStore.downloadingCommunityHistoryArchives
|
||||
type: ModuleWarning.Danger
|
||||
text: qsTr("Downloading message history archives, DO NOT CLOSE THE APP until this banner disappears.")
|
||||
closeBtnVisible: false
|
||||
delay: false
|
||||
}
|
||||
|
||||
ModuleWarning {
|
||||
id: mailserverConnectionBanner
|
||||
type: ModuleWarning.Warning
|
||||
@@ -1594,91 +1538,6 @@ Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Component {
|
||||
id: connectedBannerComponent
|
||||
|
||||
ModuleWarning {
|
||||
id: connectedBanner
|
||||
property bool isConnected: true
|
||||
|
||||
objectName: "connectionInfoBanner"
|
||||
Layout.fillWidth: true
|
||||
text: isConnected ? qsTr("You are back online") : qsTr("Internet connection lost. Reconnect to ensure everything is up to date.")
|
||||
type: isConnected ? ModuleWarning.Success : ModuleWarning.Danger
|
||||
|
||||
function updateState() {
|
||||
if (isConnected)
|
||||
showFor()
|
||||
else
|
||||
show();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
connectedBanner.isConnected = Qt.binding(() => bannersLayout.isConnected);
|
||||
}
|
||||
onIsConnectedChanged: {
|
||||
updateState();
|
||||
}
|
||||
onCloseClicked: {
|
||||
hide();
|
||||
}
|
||||
onHideFinished: {
|
||||
destroy()
|
||||
bannersLayout.connectedBanner = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: updateBannerComponent
|
||||
|
||||
ModuleWarning {
|
||||
readonly property string version: appMain.rootStore.latestVersion
|
||||
readonly property bool updateAvailable: appMain.rootStore.newVersionAvailable
|
||||
|
||||
objectName: "appVersionUpdateBanner"
|
||||
Layout.fillWidth: true
|
||||
type: ModuleWarning.Success
|
||||
delay: false
|
||||
text: updateAvailable ? qsTr("A new version of Status (%1) is available").arg(version)
|
||||
: qsTr("Your version is up to date")
|
||||
|
||||
buttonText: updateAvailable ? qsTr("Update")
|
||||
: qsTr("Close")
|
||||
|
||||
function updateState() {
|
||||
if (updateAvailable)
|
||||
show()
|
||||
else
|
||||
showFor(5000)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
updateState()
|
||||
}
|
||||
onUpdateAvailableChanged: {
|
||||
updateState();
|
||||
}
|
||||
onClicked: {
|
||||
if (updateAvailable)
|
||||
Global.openDownloadModal(appMain.rootStore.newVersionAvailable,
|
||||
appMain.rootStore.latestVersion,
|
||||
appMain.rootStore.downloadURL)
|
||||
else
|
||||
close()
|
||||
}
|
||||
onCloseClicked: {
|
||||
if (updateAvailable)
|
||||
appMain.rootStore.resetLastVersion();
|
||||
hide()
|
||||
}
|
||||
onHideFinished: {
|
||||
destroy()
|
||||
bannersLayout.updateBanner = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionWarnings {
|
||||
id: walletBlockchainConnectionBanner
|
||||
objectName: "walletBlockchainConnectionBanner"
|
||||
@@ -1810,8 +1669,7 @@ Item {
|
||||
anchors.fill: parent
|
||||
|
||||
currentIndex: {
|
||||
const activeSectionType = appMain.rootStore.activeSectionType
|
||||
switch (activeSectionType) {
|
||||
switch (d.activeSectionType) {
|
||||
case Constants.appSection.homePage:
|
||||
return Constants.appViewStackIndex.homePage
|
||||
case Constants.appSection.chat:
|
||||
@@ -1824,7 +1682,7 @@ Item {
|
||||
}
|
||||
}
|
||||
// Should never be here, correct index must be returned from the for loop above
|
||||
console.error("Wrong section type:", activeSectionType,
|
||||
console.error("Wrong section type:", d.activeSectionType,
|
||||
"or section id: ", appMain.rootStore.activeSectionId)
|
||||
return Constants.appViewStackIndex.community
|
||||
case Constants.appSection.communitiesPortal:
|
||||
@@ -1843,8 +1701,7 @@ Item {
|
||||
}
|
||||
}
|
||||
onCurrentIndexChanged: {
|
||||
const sectionType = appMain.rootStore.activeSectionType
|
||||
if (sectionType !== Constants.appSection.profile && sectionType !== Constants.appSection.wallet) {
|
||||
if (d.activeSectionType !== Constants.appSection.profile && d.activeSectionType !== Constants.appSection.wallet) {
|
||||
d.maybeDisplayIntroduceYourselfPopup()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import QtQuick
|
||||
|
||||
import shared.panels
|
||||
|
||||
Loader {
|
||||
id: root
|
||||
|
||||
required property bool isOnline
|
||||
required property bool testnetEnabled
|
||||
required property bool seedphraseBackedUp
|
||||
|
||||
signal openTestnetPopupRequested()
|
||||
signal openBackUpSeedPopupRequested()
|
||||
signal userDeclinedBackupBannerRequested()
|
||||
|
||||
sourceComponent: {
|
||||
if (d.showConnectedBanner)
|
||||
return connectedBannerComponent
|
||||
if (testnetEnabled)
|
||||
return testnetBannerComponent
|
||||
if (!seedphraseBackedUp)
|
||||
return secureYourSeedPhraseComponent
|
||||
}
|
||||
|
||||
visible: !!item
|
||||
|
||||
onLoaded: item.show()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property bool showConnectedBanner: !root.isOnline // initially, we don't want to show the "You are online" banner
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onIsOnlineChanged() {
|
||||
if (!root.isOnline) {
|
||||
d.showConnectedBanner = !root.isOnline // show the banner again if we are offline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: connectedBannerComponent
|
||||
ModuleWarning {
|
||||
id: connectedBanner
|
||||
|
||||
objectName: "connectionInfoBanner"
|
||||
text: root.isOnline ? qsTr("You are back online") : qsTr("Internet connection lost. Reconnect to ensure everything is up to date.")
|
||||
type: root.isOnline ? ModuleWarning.Success : ModuleWarning.Danger
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onIsOnlineChanged() {
|
||||
if (root.isOnline) { // keep showing the connectedBanner for 3 more seconds
|
||||
d.showConnectedBanner = true
|
||||
connectedBanner.showFor(3000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delay: false
|
||||
onCloseClicked: {
|
||||
d.showConnectedBanner = true // keep showing the connectedBanner until the hide animation is done
|
||||
hide()
|
||||
}
|
||||
|
||||
onHideFinished: d.showConnectedBanner = false // close the banner until the next offline event
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: testnetBannerComponent
|
||||
ModuleWarning {
|
||||
objectName: "testnetBanner"
|
||||
text: qsTr("Testnet mode enabled. All balances, transactions and dApp interactions will be on testnets.")
|
||||
buttonText: qsTr("Turn off")
|
||||
type: ModuleWarning.Warning
|
||||
iconName: "warning"
|
||||
delay: false
|
||||
onClicked: root.openTestnetPopupRequested()
|
||||
closeBtnVisible: false
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: secureYourSeedPhraseComponent
|
||||
ModuleWarning {
|
||||
objectName: "secureYourSeedPhraseBanner"
|
||||
type: ModuleWarning.Type.Danger
|
||||
text: qsTr("Secure your recovery phrase")
|
||||
buttonText: qsTr("Back up now")
|
||||
delay: false
|
||||
onClicked: root.openBackUpSeedPopupRequested()
|
||||
onCloseClicked: root.userDeclinedBackupBannerRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
AppMain 1.0 AppMain.qml
|
||||
GlobalBanner 1.0 GlobalBanner.qml
|
||||
SplashScreen 1.0 SplashScreen.qml
|
||||
Popups 1.0 Popups.qml
|
||||
StatusTrayIcon 1.0 StatusTrayIcon.qml
|
||||
|
||||
+1
-12
@@ -14553,17 +14553,6 @@ to load</translation>
|
||||
<translation>The next screen contains your recovery phrase.<br/><b>Anyone</b> who sees it can use it to access to your funds.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SeedPhraseBackupWarning</name>
|
||||
<message>
|
||||
<source>Back up your recovery phrase</source>
|
||||
<translation>Back up your recovery phrase</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back up</source>
|
||||
<translation>Back up</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SeedphrasePage</name>
|
||||
<message>
|
||||
@@ -18890,4 +18879,4 @@ If a transaction with a lower nonce is pending, higher nonce transactions will r
|
||||
<translation>This is not a valid account name</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
</TS>
|
||||
|
||||
@@ -132,20 +132,21 @@ Item {
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 150
|
||||
duration: Theme.AnimationDuration.Fast
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
|
||||
spacing: 12
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.halfPadding
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Theme.halfPadding
|
||||
anchors.rightMargin: Theme.halfPadding
|
||||
|
||||
StatusRoundIcon {
|
||||
Layout.preferredHeight: 16
|
||||
Layout.preferredWidth: 16
|
||||
Layout.rightMargin: -8
|
||||
visible: !!root.iconName
|
||||
asset.name: root.iconName
|
||||
asset.bgColor: Theme.palette.indirectColor1
|
||||
@@ -153,27 +154,56 @@ Item {
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
objectName: "bannerText"
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: root.text
|
||||
font.pixelSize: Theme.additionalTextSize
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.indirectColor1
|
||||
linkColor: color
|
||||
onLinkActivated: root.linkActivated(link)
|
||||
onLinkActivated: (link) => root.linkActivated(link)
|
||||
HoverHandler {
|
||||
id: handler1
|
||||
cursorShape: hovered && parent.hoveredLink ? Qt.PointingHandCursor : undefined
|
||||
}
|
||||
StatusMouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: handler1.hovered && parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("%1%").arg(progressBar.value)
|
||||
visible: progressBar.visible
|
||||
font.pixelSize: Theme.tertiaryTextFontSize
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.white
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: progressBar
|
||||
from: 0
|
||||
to: 100
|
||||
visible: root.progressValue > -1
|
||||
value: root.progressValue
|
||||
background: Rectangle {
|
||||
implicitWidth: 64
|
||||
implicitHeight: 8
|
||||
radius: 8
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Theme.palette.white
|
||||
}
|
||||
contentItem: Rectangle {
|
||||
width: progressBar.width*progressBar.position
|
||||
implicitHeight: 8
|
||||
radius: 8
|
||||
color: Theme.palette.white
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button
|
||||
visible: text != ""
|
||||
objectName: "actionButton"
|
||||
visible: !!text
|
||||
focusPolicy: Qt.NoFocus
|
||||
padding: 5
|
||||
onClicked: {
|
||||
root.clicked()
|
||||
}
|
||||
@@ -192,68 +222,28 @@ Item {
|
||||
border.color: Theme.palette.indirectColor3
|
||||
color: Theme.palette.getColor("white", button.hovered ? 0.4 : 0.1)
|
||||
}
|
||||
StatusMouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
HoverHandler {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: progressBar.left
|
||||
anchors.rightMargin: Theme.halfPadding
|
||||
text: qsTr("%1%").arg(progressBar.value)
|
||||
visible: progressBar.visible
|
||||
font.pixelSize: Theme.tertiaryTextFontSize
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.white
|
||||
}
|
||||
StatusIcon {
|
||||
id: closeImg
|
||||
objectName: "closeButton"
|
||||
height: 20
|
||||
width: 20
|
||||
icon: "close-circle"
|
||||
color: Theme.palette.indirectColor1
|
||||
opacity: closeButtonMouseArea.containsMouse ? 1 : 0.7
|
||||
|
||||
ProgressBar {
|
||||
id: progressBar
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: closeImg.left
|
||||
anchors.rightMargin: Theme.bigPadding
|
||||
from: 0
|
||||
to: 100
|
||||
visible: root.progressValue > -1
|
||||
value: root.progressValue
|
||||
background: Rectangle {
|
||||
implicitWidth: 64
|
||||
implicitHeight: 8
|
||||
radius: 8
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Theme.palette.white
|
||||
}
|
||||
contentItem: Rectangle {
|
||||
width: progressBar.width*progressBar.position
|
||||
implicitHeight: 8
|
||||
radius: 8
|
||||
color: Theme.palette.white
|
||||
}
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
id: closeImg
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 18
|
||||
height: 20
|
||||
width: 20
|
||||
icon: "close-circle"
|
||||
color: Theme.palette.indirectColor1
|
||||
opacity: closeButtonMouseArea.containsMouse ? 1 : 0.7
|
||||
|
||||
StatusMouseArea {
|
||||
id: closeButtonMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.closeClicked()
|
||||
StatusMouseArea {
|
||||
id: closeButtonMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.closeClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user