diff --git a/storybook/pages/ManageTokensPanelPage.qml b/storybook/pages/ManageAssetsPanelPage.qml similarity index 95% rename from storybook/pages/ManageTokensPanelPage.qml rename to storybook/pages/ManageAssetsPanelPage.qml index 88600b1f4f..5c9b390fac 100644 --- a/storybook/pages/ManageTokensPanelPage.qml +++ b/storybook/pages/ManageAssetsPanelPage.qml @@ -24,8 +24,9 @@ SplitView { StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml SplitView.fillWidth: true - SplitView.preferredHeight: 500 - ManageTokensPanel { + SplitView.fillHeight: true + Component.onCompleted: forceActiveFocus() + ManageAssetsPanel { id: showcasePanel width: 500 baseModel: ctrlEmptyModel.checked ? null : assetsModel diff --git a/storybook/pages/ManageCollectiblesPanelPage.qml b/storybook/pages/ManageCollectiblesPanelPage.qml index 041c8b0416..2f26504701 100644 --- a/storybook/pages/ManageCollectiblesPanelPage.qml +++ b/storybook/pages/ManageCollectiblesPanelPage.qml @@ -26,6 +26,9 @@ SplitView { StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml SplitView.fillWidth: true SplitView.fillHeight: true + + Component.onCompleted: forceActiveFocus() + ManageCollectiblesPanel { id: showcasePanel width: 500 diff --git a/ui/StatusQ/src/StatusQ/Core/StatusScrollView.qml b/ui/StatusQ/src/StatusQ/Core/StatusScrollView.qml index ff90e10adc..8828b75085 100644 --- a/ui/StatusQ/src/StatusQ/Core/StatusScrollView.qml +++ b/ui/StatusQ/src/StatusQ/Core/StatusScrollView.qml @@ -181,6 +181,43 @@ T.ScrollView { applyFlickableFix() } + Keys.onPressed: { + switch (event.key) { + case Qt.Key_Home: + scrollHome() + event.accepted = true + break + case Qt.Key_End: + scrollEnd() + event.accepted = true + break + case Qt.Key_PageUp: + scrollPageUp() + event.accepted = true + break + case Qt.Key_PageDown: + scrollPageDown() + event.accepted = true + break + } + } + + function scrollHome() { + flickable.contentY = 0 + } + + function scrollEnd() { + flickable.contentY = flickable.contentHeight - flickable.height + } + + function scrollPageUp() { + root.ScrollBar.vertical.decrease() + } + + function scrollPageDown() { + root.ScrollBar.vertical.increase() + } + ScrollBar.vertical: StatusScrollBar { parent: root x: root.mirrored ? 1 : root.width - width - 1 diff --git a/ui/StatusQ/src/wallet/managetokenscontroller.cpp b/ui/StatusQ/src/wallet/managetokenscontroller.cpp index 5e9b482a5a..ea9bccf9e3 100644 --- a/ui/StatusQ/src/wallet/managetokenscontroller.cpp +++ b/ui/StatusQ/src/wallet/managetokenscontroller.cpp @@ -126,7 +126,7 @@ void ManageTokensController::saveSettings() result.insert(m_hiddenTokensModel->save(false)); // save to QSettings - m_settings.beginGroup(QStringLiteral("ManageTokens-%1").arg(m_settingsKey)); + m_settings.beginGroup(settingsGroupName()); m_settings.beginWriteArray(m_settingsKey); SerializedTokenData::const_key_value_iterator it = result.constKeyValueBegin(); for (auto i = 0; it != result.constKeyValueEnd() && i < result.size(); it++, i++) { @@ -151,7 +151,7 @@ void ManageTokensController::clearSettings() Q_ASSERT(!m_settingsKey.isEmpty()); // clear the relevant QSettings group - m_settings.beginGroup(QStringLiteral("ManageTokens-%1").arg(m_settingsKey)); + m_settings.beginGroup(settingsGroupName()); m_settings.remove(QString()); m_settings.endGroup(); m_settings.sync(); @@ -164,7 +164,7 @@ void ManageTokensController::loadSettings() m_settingsData.clear(); // load from QSettings - m_settings.beginGroup(QStringLiteral("ManageTokens-%1").arg(m_settingsKey)); + m_settings.beginGroup(settingsGroupName()); const auto size = m_settings.beginReadArray(m_settingsKey); for (auto i = 0; i < size; i++) { m_settings.setArrayIndex(i); @@ -187,6 +187,36 @@ void ManageTokensController::revert() parseSourceModel(); } +QString ManageTokensController::settingsGroupName() const +{ + return QStringLiteral("ManageTokens-%1").arg(m_settingsKey); +} + +bool ManageTokensController::hasSettings() const +{ + Q_ASSERT(!m_settingsKey.isEmpty()); + const auto groups = m_settings.childGroups(); + return !groups.isEmpty() && groups.contains(settingsGroupName()); +} + +bool ManageTokensController::lessThan(const QString& lhsSymbol, const QString& rhsSymbol) const +{ + auto [leftPos, leftVisible, leftGroup] = m_settingsData.value(lhsSymbol, {INT_MAX, false, QString()}); + auto [rightPos, rightVisible, rightGroup] = m_settingsData.value(rhsSymbol, {INT_MAX, false, QString()}); + + // check if visible + leftPos = leftVisible ? leftPos : INT_MAX; + rightPos = rightVisible ? rightPos : INT_MAX; + + return leftPos <= rightPos; +} + +bool ManageTokensController::filterAcceptsSymbol(const QString& symbol) const +{ + const auto& [pos, visible, groupId] = m_settingsData.value(symbol, {INT_MAX, false, QString()}); + return visible; +} + void ManageTokensController::classBegin() { // empty on purpose diff --git a/ui/StatusQ/src/wallet/managetokenscontroller.h b/ui/StatusQ/src/wallet/managetokenscontroller.h index 908baf2520..567aa47e70 100644 --- a/ui/StatusQ/src/wallet/managetokenscontroller.h +++ b/ui/StatusQ/src/wallet/managetokenscontroller.h @@ -36,10 +36,10 @@ public: Q_INVOKABLE void saveSettings(); Q_INVOKABLE void clearSettings(); Q_INVOKABLE void revert(); + Q_INVOKABLE bool hasSettings() const; - // TODO: to be used by SFPM on the main wallet page as an "expressionRole" - // bool lessThan(lhsSymbol, rhsSymbol) const; - // bool filterAcceptsRow(index or symbol?) const; + Q_INVOKABLE bool lessThan(const QString& lhsSymbol, const QString& rhsSymbol) const; + Q_INVOKABLE bool filterAcceptsSymbol(const QString& symbol) const; protected: void classBegin() override; @@ -85,6 +85,7 @@ private: QString m_settingsKey; QString settingsKey() const; + QString settingsGroupName() const; void setSettingsKey(const QString& newSettingsKey); QSettings m_settings; void loadSettings(); diff --git a/ui/StatusQ/src/wallet/managetokensmodel.h b/ui/StatusQ/src/wallet/managetokensmodel.h index d32e79c13b..73e6c7b0f2 100644 --- a/ui/StatusQ/src/wallet/managetokensmodel.h +++ b/ui/StatusQ/src/wallet/managetokensmodel.h @@ -23,6 +23,7 @@ const auto kEnabledNetworkCurrencyBalanceRoleName = QByteArrayLiteral("enabledNe const auto kCustomSortOrderNoRoleName = QByteArrayLiteral("customSortOrderNo"); const auto kTokenImageRoleName = QByteArrayLiteral("imageUrl"); const auto kBackgroundColorRoleName = QByteArrayLiteral("backgroundColor"); +// TODO add communityPrivilegesLevel for collectibles } // namespace struct TokenData { diff --git a/ui/app/AppLayouts/Communities/popups/CreateCommunityPopup.qml b/ui/app/AppLayouts/Communities/popups/CreateCommunityPopup.qml index b0e5615d58..4f7d3eff2f 100644 --- a/ui/app/AppLayouts/Communities/popups/CreateCommunityPopup.qml +++ b/ui/app/AppLayouts/Communities/popups/CreateCommunityPopup.qml @@ -123,8 +123,8 @@ StatusStackModal { } IssuePill { id: issuePill - type: root.communitiesStore.discordImportErrorsCount ? IssuePill.Type.Error : IssuePill.Type.Warning - count: root.communitiesStore.discordImportErrorsCount || root.communitiesStore.discordImportWarningsCount || 0 + type: root.store.discordImportErrorsCount ? IssuePill.Type.Error : IssuePill.Type.Warning + count: root.store.discordImportErrorsCount || root.store.discordImportWarningsCount || 0 visible: !!count && !fileListView.fileListModelEmpty } StatusButton { diff --git a/ui/app/AppLayouts/Profile/ProfileLayout.qml b/ui/app/AppLayouts/Profile/ProfileLayout.qml index f0b23f5b58..3b09c34e29 100644 --- a/ui/app/AppLayouts/Profile/ProfileLayout.qml +++ b/ui/app/AppLayouts/Profile/ProfileLayout.qml @@ -80,7 +80,7 @@ StatusSectionLayout { store: root.store anchors.fill: parent onMenuItemClicked: { - if (profileContainer.currentItem.dirty) { + if (profileContainer.currentItem.dirty && !profileContainer.currentItem.ignoreDirty) { event.accepted = true; profileContainer.currentItem.notifyDirty(); } diff --git a/ui/app/AppLayouts/Profile/panels/SupportedTokenListsPanel.qml b/ui/app/AppLayouts/Profile/panels/SupportedTokenListsPanel.qml index 05e5e9c89b..6c02118bc4 100644 --- a/ui/app/AppLayouts/Profile/panels/SupportedTokenListsPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/SupportedTokenListsPanel.qml @@ -21,11 +21,12 @@ StatusListView { signal itemClicked(string key) + implicitHeight: contentHeight model: root.sourcesOfTokensModel spacing: 8 delegate: StatusListItem { height: 76 - width: parent.width + width: ListView.view.width title: model.name subTitle: qsTr("%n token(s) · Last updated %1 @%2", "", diff --git a/ui/app/AppLayouts/Profile/views/SettingsContentBase.qml b/ui/app/AppLayouts/Profile/views/SettingsContentBase.qml index 6cb4534bcd..e33af57d71 100644 --- a/ui/app/AppLayouts/Profile/views/SettingsContentBase.qml +++ b/ui/app/AppLayouts/Profile/views/SettingsContentBase.qml @@ -9,7 +9,7 @@ import StatusQ.Core 0.1 import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 -Item { +FocusScope { id: root property string sectionTitle @@ -24,10 +24,13 @@ Item { property alias titleLayout: titleLayout property bool dirty: false + property bool ignoreDirty // ignore dirty state and do not notifyDirty() property bool saveChangesButtonEnabled: false + readonly property alias toast: settingsDirtyToastMessage signal baseAreaClicked() signal saveChangesClicked() + signal saveForLaterClicked() signal resetChangesClicked() function notifyDirty() { @@ -112,15 +115,17 @@ Item { Column { id: contentWrapper + onVisibleChanged: if (visible) forceActiveFocus() } } Item { // This is a settingsDirtyToastMessage placeholder width: settingsDirtyToastMessage.implicitWidth - height: settingsDirtyToastMessage.active ? settingsDirtyToastMessage.implicitHeight : 0 + height: settingsDirtyToastMessage.active && !root.ignoreDirty ? settingsDirtyToastMessage.implicitHeight : 0 Behavior on implicitHeight { + enabled: !root.ignoreDirty NumberAnimation { duration: 150 easing.type: Easing.InOutQuad @@ -133,11 +138,13 @@ Item { SettingsDirtyToastMessage { id: settingsDirtyToastMessage anchors.bottom: scrollView.bottom + anchors.bottomMargin: root.ignoreDirty ? 40 : 0 anchors.horizontalCenter: scrollView.horizontalCenter active: root.dirty - flickable: scrollView.flickable + flickable: root.ignoreDirty ? null : scrollView.flickable saveChangesButtonEnabled: root.saveChangesButtonEnabled onResetChangesClicked: root.resetChangesClicked() onSaveChangesClicked: root.saveChangesClicked() + onSaveForLaterClicked: root.saveForLaterClicked() } } diff --git a/ui/app/AppLayouts/Profile/views/WalletView.qml b/ui/app/AppLayouts/Profile/views/WalletView.qml index 79c56b5e82..dd0286d1a6 100644 --- a/ui/app/AppLayouts/Profile/views/WalletView.qml +++ b/ui/app/AppLayouts/Profile/views/WalletView.qml @@ -29,11 +29,11 @@ SettingsContentBase { property var walletStore required property TokensStore tokensStore - readonly property int mainViewIndex: 0; - readonly property int networksViewIndex: 1; - readonly property int editNetworksViewIndex: 2; - readonly property int accountOrderViewIndex: 3; - readonly property int accountViewIndex: 4; + readonly property int mainViewIndex: 0 + readonly property int networksViewIndex: 1 + readonly property int editNetworksViewIndex: 2 + readonly property int accountOrderViewIndex: 3 + readonly property int accountViewIndex: 4 readonly property int manageTokensViewIndex: 5 readonly property string walletSectionTitle: qsTr("Wallet") @@ -48,6 +48,34 @@ SettingsContentBase { } } + dirty: manageTokensView.dirty + ignoreDirty: stackContainer.currentIndex === manageTokensViewIndex + saveChangesButtonEnabled: dirty + toast.type: SettingsDirtyToastMessage.Type.Info + toast.cancelButtonVisible: false + toast.saveForLaterButtonVisible: dirty + toast.saveChangesText: qsTr("Apply to my Wallet") + toast.changesDetectedText: qsTr("New custom sort order created") + + onSaveForLaterClicked: { + manageTokensView.saveChanges() + } + onSaveChangesClicked: { + manageTokensView.saveChanges() + Global.displayToastMessage( + qsTr("Your new custom asset order has been applied to your %1", "Go to Wallet") + .arg(`` + qsTr("Wallet", "Go to Wallet") + ""), + "", + "checkmark-circle", + false, + Constants.ephemeralNotificationType.success, + "" + ) + } + onResetChangesClicked: { + manageTokensView.resetChanges() + } + StackLayout { id: stackContainer @@ -55,7 +83,9 @@ SettingsContentBase { height: stackContainer.currentIndex === root.mainViewIndex ? main.height: stackContainer.currentIndex === root.networksViewIndex ? networksView.height: stackContainer.currentIndex === root.editNetworksViewIndex ? editNetwork.height: - stackContainer.currentIndex === root.accountOrderViewIndex ? accountOrderView.height: accountView.height + stackContainer.currentIndex === root.accountOrderViewIndex ? accountOrderView.height: + stackContainer.currentIndex === root.manageTokensViewIndex ? manageTokensView.implicitHeight : + accountView.height currentIndex: mainViewIndex onCurrentIndexChanged: { @@ -218,12 +248,15 @@ SettingsContentBase { } ManageTokensView { - Layout.fillWidth: true - Layout.leftMargin: Style.current.padding - Layout.rightMargin: Style.current.padding - + id: manageTokensView sourcesOfTokensModel: tokensStore.sourcesOfTokensModel tokensListModel: tokensStore.extendedFlatTokensModel + baseWalletAssetsModel: RootStore.assets // TODO include community assets (#12369) + baseWalletCollectiblesModel: { + RootStore.setFillterAllAddresses() // FIXME no other way to get _all_ collectibles? + // TODO concat proxy model to include community collectibles (#12519) + return RootStore.collectiblesStore.ownedCollectibles + } } DappPermissionsView { diff --git a/ui/app/AppLayouts/Profile/views/wallet/AccountOrderView.qml b/ui/app/AppLayouts/Profile/views/wallet/AccountOrderView.qml index e105e2a7d6..b86c3de898 100644 --- a/ui/app/AppLayouts/Profile/views/wallet/AccountOrderView.qml +++ b/ui/app/AppLayouts/Profile/views/wallet/AccountOrderView.qml @@ -1,5 +1,4 @@ import QtQuick 2.15 -import SortFilterProxyModel 0.2 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 @@ -38,7 +37,6 @@ ColumnLayout { text: accountsList.count > 1? qsTr("Move your most frequently used accounts to the top of your wallet list") : qsTr("This account looks a little lonely. Add another account to enable re-ordering.") color: Theme.palette.baseColor1 - font.pixelSize: Style.current.primaryTextFontSize } StatusListView { @@ -102,7 +100,6 @@ ColumnLayout { icon.height: 40 icon.name: model.emoji icon.color: Utils.getColorForId(model.colorId) - actions: [] } } } diff --git a/ui/app/AppLayouts/Profile/views/wallet/MainView.qml b/ui/app/AppLayouts/Profile/views/wallet/MainView.qml index 9cb51573da..aef20c8b6f 100644 --- a/ui/app/AppLayouts/Profile/views/wallet/MainView.qml +++ b/ui/app/AppLayouts/Profile/views/wallet/MainView.qml @@ -1,14 +1,13 @@ import QtQuick 2.13 -import SortFilterProxyModel 0.2 -import utils 1.0 -import shared.status 1.0 -import shared.panels 1.0 import StatusQ.Core.Theme 0.1 import StatusQ.Core 0.1 import StatusQ.Controls 0.1 import StatusQ.Components 0.1 +import utils 1.0 +import shared.status 1.0 +import shared.panels 1.0 import shared.popups 1.0 import shared.popups.addaccount 1.0 diff --git a/ui/app/AppLayouts/Profile/views/wallet/ManageTokensView.qml b/ui/app/AppLayouts/Profile/views/wallet/ManageTokensView.qml index 9238b78863..6dcf8543d2 100644 --- a/ui/app/AppLayouts/Profile/views/wallet/ManageTokensView.qml +++ b/ui/app/AppLayouts/Profile/views/wallet/ManageTokensView.qml @@ -4,8 +4,10 @@ import QtQuick.Layouts 1.15 import StatusQ.Controls 0.1 import shared.controls 1.0 +import utils 1.0 import AppLayouts.Profile.panels 1.0 +import AppLayouts.Wallet.panels 1.0 ColumnLayout { id: root @@ -13,6 +15,58 @@ ColumnLayout { required property var sourcesOfTokensModel // Expected roles: key, name, updatedAt, source, version, tokensCount, image required property var tokensListModel // Expected roles: name, symbol, image, chainName, explorerUrl + required property var baseWalletAssetsModel + required property var baseWalletCollectiblesModel + + readonly property bool dirty: { + if (!loader.item) + return false + if (tabBar.currentIndex > d.collectiblesTabIndex) + return false + if (tabBar.currentIndex === d.collectiblesTabIndex && baseCollectiblesModel.isFetching) + return false + return loader.item && loader.item.dirty + } + + function saveChanges() { + if (tabBar.currentIndex > d.collectiblesTabIndex) + return + loader.item.saveSettings() + } + + function resetChanges() { + if (tabBar.currentIndex > d.collectiblesTabIndex) + return + loader.item.revert() + } + + QtObject { + id: d + + readonly property int assetsTabIndex: 0 + readonly property int collectiblesTabIndex: 1 + readonly property int tokenSourcesTabIndex: 2 + + function checkLoadMoreCollectibles() { + if (tabBar.currentIndex !== collectiblesTabIndex) + return + // If there is no more items to load or we're already fetching, return + if (!root.baseCollectiblesModel.hasMore || root.baseCollectiblesModel.isFetching) + return + root.baseCollectiblesModel.loadMore() + } + } + + Connections { + target: root.baseCollectiblesModel + function onHasMoreChanged() { + d.checkLoadMoreCollectibles() + } + function onIsFetchingChanged() { + d.checkLoadMoreCollectibles() + } + } + StatusTabBar { id: tabBar @@ -20,49 +74,60 @@ ColumnLayout { Layout.topMargin: 5 StatusTabButton { - id: assetsTab + leftPadding: 0 width: implicitWidth text: qsTr("Assets") } StatusTabButton { - id: collectiblesTab width: implicitWidth - text: qsTr("Collectibles ") + text: qsTr("Collectibles") } StatusTabButton { - id: tokensListTab width: implicitWidth text: qsTr("Token lists") } } - StackLayout { - id: stackLayout - + // NB: we want to discard any pending unsaved changes when switching tabs or navigating away + Loader { + id: loader Layout.fillWidth: true Layout.fillHeight: true - currentIndex: tabBar.currentIndex + active: visible - ShapeRectangle { - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.width - 4 // The rectangular path is rendered outside - Layout.maximumHeight: 44 - text: qsTr("You’ll be able to manage the display of your assets here") + sourceComponent: { + switch (tabBar.currentIndex) { + case d.assetsTabIndex: + return tokensPanel + case d.collectiblesTabIndex: + return collectiblesPanel + case d.tokenSourcesTabIndex: + return supportedTokensListPanel + } } + } - ShapeRectangle { - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.width - 4 // The rectangular path is rendered outside - Layout.maximumHeight: 44 - text: qsTr("You’ll be able to manage the display of your collectibles here") + Component { + id: tokensPanel + ManageAssetsPanel { + baseModel: root.baseWalletAssetsModel } + // TODO #12611 add Advanced section + } + Component { + id: collectiblesPanel + ManageCollectiblesPanel { + baseModel: root.baseWalletCollectiblesModel + Component.onCompleted: d.checkLoadMoreCollectibles() + } + } + + Component { + id: supportedTokensListPanel SupportedTokenListsPanel { - Layout.fillWidth: true - Layout.fillHeight: true - sourcesOfTokensModel: root.sourcesOfTokensModel tokensListModel: root.tokensListModel } diff --git a/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml b/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml index 92f5ce081a..326164a0a9 100644 --- a/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml +++ b/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml @@ -13,6 +13,7 @@ DropArea { objectName: "manageTokensDelegate-%1".arg(index) // expected roles: symbol, name, communityId, communityName, communityImage, collectionName, imageUrl + // + enabledNetworkBalance, enabledNetworkCurrencyBalance -> TODO might get dropped/renamed in the future!!! property var controller property int visualIndex: index @@ -71,7 +72,7 @@ DropArea { : LocaleUtils.currencyAmountToLocaleString(model.enabledNetworkBalance) bgRadius: priv.bgRadius hasImage: true - icon.source: root.isCollectible ? model.imageUrl : Constants.tokenIcon(model.symbol) // TODO unify via backend model for both assets and collectibles + icon.source: root.isCollectible ? model.imageUrl : Constants.tokenIcon(model.symbol) // TODO unify via backend model for both assets and collectibles; handle communityPrivilegesLevel icon.width: priv.iconSize icon.height: priv.iconSize spacing: 12 diff --git a/ui/app/AppLayouts/Wallet/panels/ManageTokensPanel.qml b/ui/app/AppLayouts/Wallet/panels/ManageAssetsPanel.qml similarity index 100% rename from ui/app/AppLayouts/Wallet/panels/ManageTokensPanel.qml rename to ui/app/AppLayouts/Wallet/panels/ManageAssetsPanel.qml diff --git a/ui/app/AppLayouts/Wallet/panels/WalletTxProgressBlock.qml b/ui/app/AppLayouts/Wallet/panels/WalletTxProgressBlock.qml index 4f94e1f48a..d56587ce4c 100644 --- a/ui/app/AppLayouts/Wallet/panels/WalletTxProgressBlock.qml +++ b/ui/app/AppLayouts/Wallet/panels/WalletTxProgressBlock.qml @@ -18,8 +18,8 @@ ColumnLayout { property int outNetworkLayer: 0 property int inNetworkLayer: 0 - property int outNetworkTimestamp: 0 - property int inNetworkTimestamp: 0 + property double outNetworkTimestamp: 0 + property double inNetworkTimestamp: 0 property string outChainName property string inChainName diff --git a/ui/app/AppLayouts/Wallet/panels/qmldir b/ui/app/AppLayouts/Wallet/panels/qmldir index dbdec0d9fb..96bd4be6cb 100644 --- a/ui/app/AppLayouts/Wallet/panels/qmldir +++ b/ui/app/AppLayouts/Wallet/panels/qmldir @@ -2,5 +2,5 @@ WalletHeader 1.0 WalletHeader.qml WalletTxProgressBlock 1.0 WalletTxProgressBlock.qml WalletNftPreview 1.0 WalletNftPreview.qml ActivityFilterPanel 1.0 ActivityFilterPanel.qml -ManageTokensPanel 1.0 ManageTokensPanel.qml +ManageAssetsPanel 1.0 ManageAssetsPanel.qml ManageCollectiblesPanel 1.0 ManageCollectiblesPanel.qml diff --git a/ui/app/AppLayouts/Wallet/stores/RootStore.qml b/ui/app/AppLayouts/Wallet/stores/RootStore.qml index 36e4ad90e5..ff589d7174 100644 --- a/ui/app/AppLayouts/Wallet/stores/RootStore.qml +++ b/ui/app/AppLayouts/Wallet/stores/RootStore.qml @@ -38,7 +38,8 @@ QtObject { property CollectiblesStore collectiblesStore: CollectiblesStore {} - property var areTestNetworksEnabled: networksModule.areTestNetworksEnabled + readonly property bool areTestNetworksEnabled: networksModule.areTestNetworksEnabled + readonly property bool isSepoliaEnabled: networksModule.isSepoliaEnabled property var savedAddresses: SortFilterProxyModel { sourceModel: walletSectionSavedAddresses.model diff --git a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml index 93eac5c293..68136b2b38 100644 --- a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml +++ b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml @@ -40,7 +40,6 @@ Item { anchors.horizontalCenter: parent.horizontalCenter color: Style.current.secondaryText text: qsTr("Collectibles will appear here") - font.pixelSize: 15 } } } @@ -65,7 +64,7 @@ Item { isLoading: !!model.isLoading privilegesLevel: model.communityPrivilegesLevel ?? Constants.TokenPrivilegesLevel.Community ornamentColor: model.communityColor ?? "transparent" - communityId: model.communityId + communityId: model.communityId ?? "" onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId, model.uid) } diff --git a/ui/app/AppLayouts/Wallet/views/RightTabView.qml b/ui/app/AppLayouts/Wallet/views/RightTabView.qml index b6b80cc61f..96b0efcbc4 100644 --- a/ui/app/AppLayouts/Wallet/views/RightTabView.qml +++ b/ui/app/AppLayouts/Wallet/views/RightTabView.qml @@ -49,13 +49,13 @@ Item { id: d function getBackButtonText(index) { switch(index) { - case 1: + case 1: return qsTr("Collectibles") - case 2: + case 2: return qsTr("Assets") - case 3: + case 3: return qsTr("Activity") - default: + default: return "" } } @@ -156,8 +156,6 @@ Item { } } CollectibleDetailView { - Layout.fillWidth: true - Layout.fillHeight: true collectible: RootStore.collectiblesStore.detailedCollectible isCollectibleLoading: RootStore.collectiblesStore.isDetailedCollectibleLoading @@ -169,8 +167,6 @@ Item { AssetsDetailView { id: assetDetailView - Layout.fillWidth: true - Layout.fillHeight: true visible: (stack.currentIndex === 2) assetsLoading: RootStore.assetsLoading @@ -186,8 +182,6 @@ Item { TransactionDetailView { id: transactionDetailView - Layout.fillWidth: true - Layout.fillHeight: true onVisibleChanged: { if (!visible) transaction = null diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index c0c7bb83c2..29da009af0 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -1612,6 +1612,7 @@ Item { this.open = false } onLinkActivated: { + this.open = false if(actionRequired) { toastsManager.doAction(model.actionType, model.actionData) return diff --git a/ui/imports/shared/popups/SettingsDirtyToastMessage.qml b/ui/imports/shared/popups/SettingsDirtyToastMessage.qml index b9a61f3ddb..7714548c17 100644 --- a/ui/imports/shared/popups/SettingsDirtyToastMessage.qml +++ b/ui/imports/shared/popups/SettingsDirtyToastMessage.qml @@ -1,6 +1,6 @@ -import QtQuick 2.14 -import QtQuick.Layouts 1.14 -import QtGraphicalEffects 1.13 +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtGraphicalEffects 1.15 import utils 1.0 @@ -12,14 +12,24 @@ Rectangle { id: root property bool active: false + property bool cancelButtonVisible: true property bool saveChangesButtonEnabled: false + property bool saveForLaterButtonVisible property alias saveChangesText: saveChangesButton.text + property alias saveForLaterText: saveForLaterButton.text property alias cancelChangesText: cancelChangesButton.text property alias changesDetectedText: changesDetectedTextItem.text property Flickable flickable: null + enum Type { + Danger, + Info + } + property int type: SettingsDirtyToastMessage.Type.Danger + signal saveChangesClicked + signal saveForLaterClicked signal resetChangesClicked function notifyDirty() { @@ -33,8 +43,9 @@ Rectangle { opacity: active ? 1 : 0 color: Theme.palette.statusToastMessage.backgroundColor radius: 8 - border.color: Theme.palette.dangerColor2 + border.color: type === SettingsDirtyToastMessage.Type.Danger ? Theme.palette.dangerColor2 : Theme.palette.primaryColor2 border.width: 2 + layer.enabled: true layer.effect: DropShadow { verticalOffset: 3 @@ -42,7 +53,7 @@ Rectangle { samples: 15 fast: true cached: true - color: Theme.palette.dangerColor2 + color: root.border.color spread: 0.1 } @@ -104,7 +115,6 @@ Rectangle { StatusBaseText { id: changesDetectedTextItem - Layout.columnSpan: 2 Layout.fillWidth: true padding: 8 horizontalAlignment: Text.AlignHCenter @@ -116,10 +126,19 @@ Rectangle { id: cancelChangesButton text: qsTr("Cancel") enabled: root.active + visible: root.cancelButtonVisible type: StatusBaseButton.Type.Danger onClicked: root.resetChangesClicked() } + StatusFlatButton { + id: saveForLaterButton + text: qsTr("Save for later") + enabled: root.active && root.saveChangesButtonEnabled + visible: root.saveForLaterButtonVisible + onClicked: root.saveForLaterClicked() + } + StatusButton { id: saveChangesButton objectName: "settingsDirtyToastMessageSaveButton"