feat: Integrate the new manage assets/collectibles panels into Settings

- display a customized floating bubble to save/apply the settings
- display a toast message on Apply with an action to jump to Wallet main
page
- add home/end/pgup/pgdown keyboard shortcuts to StatusScrollView to be
able to navigate more easily in long list views
- some smaller fixes and cleanups in wallet and settings related views

Fixes https://github.com/status-im/status-desktop/issues/12762
This commit is contained in:
Lukáš Tinkl 2023-11-17 15:08:43 +01:00 committed by Lukáš Tinkl
parent 77197040a4
commit 8791d028e6
23 changed files with 266 additions and 76 deletions

View File

@ -24,8 +24,9 @@ SplitView {
StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml
SplitView.fillWidth: true SplitView.fillWidth: true
SplitView.preferredHeight: 500 SplitView.fillHeight: true
ManageTokensPanel { Component.onCompleted: forceActiveFocus()
ManageAssetsPanel {
id: showcasePanel id: showcasePanel
width: 500 width: 500
baseModel: ctrlEmptyModel.checked ? null : assetsModel baseModel: ctrlEmptyModel.checked ? null : assetsModel

View File

@ -26,6 +26,9 @@ SplitView {
StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml
SplitView.fillWidth: true SplitView.fillWidth: true
SplitView.fillHeight: true SplitView.fillHeight: true
Component.onCompleted: forceActiveFocus()
ManageCollectiblesPanel { ManageCollectiblesPanel {
id: showcasePanel id: showcasePanel
width: 500 width: 500

View File

@ -181,6 +181,43 @@ T.ScrollView {
applyFlickableFix() 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 { ScrollBar.vertical: StatusScrollBar {
parent: root parent: root
x: root.mirrored ? 1 : root.width - width - 1 x: root.mirrored ? 1 : root.width - width - 1

View File

@ -126,7 +126,7 @@ void ManageTokensController::saveSettings()
result.insert(m_hiddenTokensModel->save(false)); result.insert(m_hiddenTokensModel->save(false));
// save to QSettings // save to QSettings
m_settings.beginGroup(QStringLiteral("ManageTokens-%1").arg(m_settingsKey)); m_settings.beginGroup(settingsGroupName());
m_settings.beginWriteArray(m_settingsKey); m_settings.beginWriteArray(m_settingsKey);
SerializedTokenData::const_key_value_iterator it = result.constKeyValueBegin(); SerializedTokenData::const_key_value_iterator it = result.constKeyValueBegin();
for (auto i = 0; it != result.constKeyValueEnd() && i < result.size(); it++, i++) { for (auto i = 0; it != result.constKeyValueEnd() && i < result.size(); it++, i++) {
@ -151,7 +151,7 @@ void ManageTokensController::clearSettings()
Q_ASSERT(!m_settingsKey.isEmpty()); Q_ASSERT(!m_settingsKey.isEmpty());
// clear the relevant QSettings group // clear the relevant QSettings group
m_settings.beginGroup(QStringLiteral("ManageTokens-%1").arg(m_settingsKey)); m_settings.beginGroup(settingsGroupName());
m_settings.remove(QString()); m_settings.remove(QString());
m_settings.endGroup(); m_settings.endGroup();
m_settings.sync(); m_settings.sync();
@ -164,7 +164,7 @@ void ManageTokensController::loadSettings()
m_settingsData.clear(); m_settingsData.clear();
// load from QSettings // load from QSettings
m_settings.beginGroup(QStringLiteral("ManageTokens-%1").arg(m_settingsKey)); m_settings.beginGroup(settingsGroupName());
const auto size = m_settings.beginReadArray(m_settingsKey); const auto size = m_settings.beginReadArray(m_settingsKey);
for (auto i = 0; i < size; i++) { for (auto i = 0; i < size; i++) {
m_settings.setArrayIndex(i); m_settings.setArrayIndex(i);
@ -187,6 +187,36 @@ void ManageTokensController::revert()
parseSourceModel(); 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() void ManageTokensController::classBegin()
{ {
// empty on purpose // empty on purpose

View File

@ -36,10 +36,10 @@ public:
Q_INVOKABLE void saveSettings(); Q_INVOKABLE void saveSettings();
Q_INVOKABLE void clearSettings(); Q_INVOKABLE void clearSettings();
Q_INVOKABLE void revert(); Q_INVOKABLE void revert();
Q_INVOKABLE bool hasSettings() const;
// TODO: to be used by SFPM on the main wallet page as an "expressionRole" Q_INVOKABLE bool lessThan(const QString& lhsSymbol, const QString& rhsSymbol) const;
// bool lessThan(lhsSymbol, rhsSymbol) const; Q_INVOKABLE bool filterAcceptsSymbol(const QString& symbol) const;
// bool filterAcceptsRow(index or symbol?) const;
protected: protected:
void classBegin() override; void classBegin() override;
@ -85,6 +85,7 @@ private:
QString m_settingsKey; QString m_settingsKey;
QString settingsKey() const; QString settingsKey() const;
QString settingsGroupName() const;
void setSettingsKey(const QString& newSettingsKey); void setSettingsKey(const QString& newSettingsKey);
QSettings m_settings; QSettings m_settings;
void loadSettings(); void loadSettings();

View File

@ -23,6 +23,7 @@ const auto kEnabledNetworkCurrencyBalanceRoleName = QByteArrayLiteral("enabledNe
const auto kCustomSortOrderNoRoleName = QByteArrayLiteral("customSortOrderNo"); const auto kCustomSortOrderNoRoleName = QByteArrayLiteral("customSortOrderNo");
const auto kTokenImageRoleName = QByteArrayLiteral("imageUrl"); const auto kTokenImageRoleName = QByteArrayLiteral("imageUrl");
const auto kBackgroundColorRoleName = QByteArrayLiteral("backgroundColor"); const auto kBackgroundColorRoleName = QByteArrayLiteral("backgroundColor");
// TODO add communityPrivilegesLevel for collectibles
} // namespace } // namespace
struct TokenData { struct TokenData {

View File

@ -123,8 +123,8 @@ StatusStackModal {
} }
IssuePill { IssuePill {
id: issuePill id: issuePill
type: root.communitiesStore.discordImportErrorsCount ? IssuePill.Type.Error : IssuePill.Type.Warning type: root.store.discordImportErrorsCount ? IssuePill.Type.Error : IssuePill.Type.Warning
count: root.communitiesStore.discordImportErrorsCount || root.communitiesStore.discordImportWarningsCount || 0 count: root.store.discordImportErrorsCount || root.store.discordImportWarningsCount || 0
visible: !!count && !fileListView.fileListModelEmpty visible: !!count && !fileListView.fileListModelEmpty
} }
StatusButton { StatusButton {

View File

@ -80,7 +80,7 @@ StatusSectionLayout {
store: root.store store: root.store
anchors.fill: parent anchors.fill: parent
onMenuItemClicked: { onMenuItemClicked: {
if (profileContainer.currentItem.dirty) { if (profileContainer.currentItem.dirty && !profileContainer.currentItem.ignoreDirty) {
event.accepted = true; event.accepted = true;
profileContainer.currentItem.notifyDirty(); profileContainer.currentItem.notifyDirty();
} }

View File

@ -21,11 +21,12 @@ StatusListView {
signal itemClicked(string key) signal itemClicked(string key)
implicitHeight: contentHeight
model: root.sourcesOfTokensModel model: root.sourcesOfTokensModel
spacing: 8 spacing: 8
delegate: StatusListItem { delegate: StatusListItem {
height: 76 height: 76
width: parent.width width: ListView.view.width
title: model.name title: model.name
subTitle: qsTr("%n token(s) · Last updated %1 @%2", subTitle: qsTr("%n token(s) · Last updated %1 @%2",
"", "",

View File

@ -9,7 +9,7 @@ import StatusQ.Core 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
Item { FocusScope {
id: root id: root
property string sectionTitle property string sectionTitle
@ -24,10 +24,13 @@ Item {
property alias titleLayout: titleLayout property alias titleLayout: titleLayout
property bool dirty: false property bool dirty: false
property bool ignoreDirty // ignore dirty state and do not notifyDirty()
property bool saveChangesButtonEnabled: false property bool saveChangesButtonEnabled: false
readonly property alias toast: settingsDirtyToastMessage
signal baseAreaClicked() signal baseAreaClicked()
signal saveChangesClicked() signal saveChangesClicked()
signal saveForLaterClicked()
signal resetChangesClicked() signal resetChangesClicked()
function notifyDirty() { function notifyDirty() {
@ -112,15 +115,17 @@ Item {
Column { Column {
id: contentWrapper id: contentWrapper
onVisibleChanged: if (visible) forceActiveFocus()
} }
} }
Item { Item {
// This is a settingsDirtyToastMessage placeholder // This is a settingsDirtyToastMessage placeholder
width: settingsDirtyToastMessage.implicitWidth width: settingsDirtyToastMessage.implicitWidth
height: settingsDirtyToastMessage.active ? settingsDirtyToastMessage.implicitHeight : 0 height: settingsDirtyToastMessage.active && !root.ignoreDirty ? settingsDirtyToastMessage.implicitHeight : 0
Behavior on implicitHeight { Behavior on implicitHeight {
enabled: !root.ignoreDirty
NumberAnimation { NumberAnimation {
duration: 150 duration: 150
easing.type: Easing.InOutQuad easing.type: Easing.InOutQuad
@ -133,11 +138,13 @@ Item {
SettingsDirtyToastMessage { SettingsDirtyToastMessage {
id: settingsDirtyToastMessage id: settingsDirtyToastMessage
anchors.bottom: scrollView.bottom anchors.bottom: scrollView.bottom
anchors.bottomMargin: root.ignoreDirty ? 40 : 0
anchors.horizontalCenter: scrollView.horizontalCenter anchors.horizontalCenter: scrollView.horizontalCenter
active: root.dirty active: root.dirty
flickable: scrollView.flickable flickable: root.ignoreDirty ? null : scrollView.flickable
saveChangesButtonEnabled: root.saveChangesButtonEnabled saveChangesButtonEnabled: root.saveChangesButtonEnabled
onResetChangesClicked: root.resetChangesClicked() onResetChangesClicked: root.resetChangesClicked()
onSaveChangesClicked: root.saveChangesClicked() onSaveChangesClicked: root.saveChangesClicked()
onSaveForLaterClicked: root.saveForLaterClicked()
} }
} }

View File

@ -29,11 +29,11 @@ SettingsContentBase {
property var walletStore property var walletStore
required property TokensStore tokensStore required property TokensStore tokensStore
readonly property int mainViewIndex: 0; readonly property int mainViewIndex: 0
readonly property int networksViewIndex: 1; readonly property int networksViewIndex: 1
readonly property int editNetworksViewIndex: 2; readonly property int editNetworksViewIndex: 2
readonly property int accountOrderViewIndex: 3; readonly property int accountOrderViewIndex: 3
readonly property int accountViewIndex: 4; readonly property int accountViewIndex: 4
readonly property int manageTokensViewIndex: 5 readonly property int manageTokensViewIndex: 5
readonly property string walletSectionTitle: qsTr("Wallet") 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(`<a style="text-decoration:none" href="#${Constants.appSection.wallet}">` + qsTr("Wallet", "Go to Wallet") + "</a>"),
"",
"checkmark-circle",
false,
Constants.ephemeralNotificationType.success,
""
)
}
onResetChangesClicked: {
manageTokensView.resetChanges()
}
StackLayout { StackLayout {
id: stackContainer id: stackContainer
@ -55,7 +83,9 @@ SettingsContentBase {
height: stackContainer.currentIndex === root.mainViewIndex ? main.height: height: stackContainer.currentIndex === root.mainViewIndex ? main.height:
stackContainer.currentIndex === root.networksViewIndex ? networksView.height: stackContainer.currentIndex === root.networksViewIndex ? networksView.height:
stackContainer.currentIndex === root.editNetworksViewIndex ? editNetwork.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 currentIndex: mainViewIndex
onCurrentIndexChanged: { onCurrentIndexChanged: {
@ -218,12 +248,15 @@ SettingsContentBase {
} }
ManageTokensView { ManageTokensView {
Layout.fillWidth: true id: manageTokensView
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
sourcesOfTokensModel: tokensStore.sourcesOfTokensModel sourcesOfTokensModel: tokensStore.sourcesOfTokensModel
tokensListModel: tokensStore.extendedFlatTokensModel 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 { DappPermissionsView {

View File

@ -1,5 +1,4 @@
import QtQuick 2.15 import QtQuick 2.15
import SortFilterProxyModel 0.2
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.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") : 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.") qsTr("This account looks a little lonely. Add another account to enable re-ordering.")
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
font.pixelSize: Style.current.primaryTextFontSize
} }
StatusListView { StatusListView {
@ -102,7 +100,6 @@ ColumnLayout {
icon.height: 40 icon.height: 40
icon.name: model.emoji icon.name: model.emoji
icon.color: Utils.getColorForId(model.colorId) icon.color: Utils.getColorForId(model.colorId)
actions: []
} }
} }
} }

View File

@ -1,14 +1,13 @@
import QtQuick 2.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.Theme 0.1
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Components 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 1.0
import shared.popups.addaccount 1.0 import shared.popups.addaccount 1.0

View File

@ -4,8 +4,10 @@ import QtQuick.Layouts 1.15
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import shared.controls 1.0 import shared.controls 1.0
import utils 1.0
import AppLayouts.Profile.panels 1.0 import AppLayouts.Profile.panels 1.0
import AppLayouts.Wallet.panels 1.0
ColumnLayout { ColumnLayout {
id: root id: root
@ -13,6 +15,58 @@ ColumnLayout {
required property var sourcesOfTokensModel // Expected roles: key, name, updatedAt, source, version, tokensCount, image 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 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 { StatusTabBar {
id: tabBar id: tabBar
@ -20,49 +74,60 @@ ColumnLayout {
Layout.topMargin: 5 Layout.topMargin: 5
StatusTabButton { StatusTabButton {
id: assetsTab leftPadding: 0
width: implicitWidth width: implicitWidth
text: qsTr("Assets") text: qsTr("Assets")
} }
StatusTabButton { StatusTabButton {
id: collectiblesTab
width: implicitWidth width: implicitWidth
text: qsTr("Collectibles") text: qsTr("Collectibles")
} }
StatusTabButton { StatusTabButton {
id: tokensListTab
width: implicitWidth width: implicitWidth
text: qsTr("Token lists") text: qsTr("Token lists")
} }
} }
StackLayout { // NB: we want to discard any pending unsaved changes when switching tabs or navigating away
id: stackLayout Loader {
id: loader
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
currentIndex: tabBar.currentIndex active: visible
ShapeRectangle { sourceComponent: {
Layout.alignment: Qt.AlignHCenter switch (tabBar.currentIndex) {
Layout.preferredWidth: parent.width - 4 // The rectangular path is rendered outside case d.assetsTabIndex:
Layout.maximumHeight: 44 return tokensPanel
text: qsTr("Youll be able to manage the display of your assets here") case d.collectiblesTabIndex:
return collectiblesPanel
case d.tokenSourcesTabIndex:
return supportedTokensListPanel
}
}
} }
ShapeRectangle { Component {
Layout.alignment: Qt.AlignHCenter id: tokensPanel
Layout.preferredWidth: parent.width - 4 // The rectangular path is rendered outside ManageAssetsPanel {
Layout.maximumHeight: 44 baseModel: root.baseWalletAssetsModel
text: qsTr("Youll be able to manage the display of your collectibles here") }
// TODO #12611 add Advanced section
} }
Component {
id: collectiblesPanel
ManageCollectiblesPanel {
baseModel: root.baseWalletCollectiblesModel
Component.onCompleted: d.checkLoadMoreCollectibles()
}
}
Component {
id: supportedTokensListPanel
SupportedTokenListsPanel { SupportedTokenListsPanel {
Layout.fillWidth: true
Layout.fillHeight: true
sourcesOfTokensModel: root.sourcesOfTokensModel sourcesOfTokensModel: root.sourcesOfTokensModel
tokensListModel: root.tokensListModel tokensListModel: root.tokensListModel
} }

View File

@ -13,6 +13,7 @@ DropArea {
objectName: "manageTokensDelegate-%1".arg(index) objectName: "manageTokensDelegate-%1".arg(index)
// expected roles: symbol, name, communityId, communityName, communityImage, collectionName, imageUrl // expected roles: symbol, name, communityId, communityName, communityImage, collectionName, imageUrl
// + enabledNetworkBalance, enabledNetworkCurrencyBalance -> TODO might get dropped/renamed in the future!!!
property var controller property var controller
property int visualIndex: index property int visualIndex: index
@ -71,7 +72,7 @@ DropArea {
: LocaleUtils.currencyAmountToLocaleString(model.enabledNetworkBalance) : LocaleUtils.currencyAmountToLocaleString(model.enabledNetworkBalance)
bgRadius: priv.bgRadius bgRadius: priv.bgRadius
hasImage: true 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.width: priv.iconSize
icon.height: priv.iconSize icon.height: priv.iconSize
spacing: 12 spacing: 12

View File

@ -18,8 +18,8 @@ ColumnLayout {
property int outNetworkLayer: 0 property int outNetworkLayer: 0
property int inNetworkLayer: 0 property int inNetworkLayer: 0
property int outNetworkTimestamp: 0 property double outNetworkTimestamp: 0
property int inNetworkTimestamp: 0 property double inNetworkTimestamp: 0
property string outChainName property string outChainName
property string inChainName property string inChainName

View File

@ -2,5 +2,5 @@ WalletHeader 1.0 WalletHeader.qml
WalletTxProgressBlock 1.0 WalletTxProgressBlock.qml WalletTxProgressBlock 1.0 WalletTxProgressBlock.qml
WalletNftPreview 1.0 WalletNftPreview.qml WalletNftPreview 1.0 WalletNftPreview.qml
ActivityFilterPanel 1.0 ActivityFilterPanel.qml ActivityFilterPanel 1.0 ActivityFilterPanel.qml
ManageTokensPanel 1.0 ManageTokensPanel.qml ManageAssetsPanel 1.0 ManageAssetsPanel.qml
ManageCollectiblesPanel 1.0 ManageCollectiblesPanel.qml ManageCollectiblesPanel 1.0 ManageCollectiblesPanel.qml

View File

@ -38,7 +38,8 @@ QtObject {
property CollectiblesStore collectiblesStore: CollectiblesStore {} 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 { property var savedAddresses: SortFilterProxyModel {
sourceModel: walletSectionSavedAddresses.model sourceModel: walletSectionSavedAddresses.model

View File

@ -40,7 +40,6 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
color: Style.current.secondaryText color: Style.current.secondaryText
text: qsTr("Collectibles will appear here") text: qsTr("Collectibles will appear here")
font.pixelSize: 15
} }
} }
} }
@ -65,7 +64,7 @@ Item {
isLoading: !!model.isLoading isLoading: !!model.isLoading
privilegesLevel: model.communityPrivilegesLevel ?? Constants.TokenPrivilegesLevel.Community privilegesLevel: model.communityPrivilegesLevel ?? Constants.TokenPrivilegesLevel.Community
ornamentColor: model.communityColor ?? "transparent" ornamentColor: model.communityColor ?? "transparent"
communityId: model.communityId communityId: model.communityId ?? ""
onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId, model.uid) onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId, model.uid)
} }

View File

@ -156,8 +156,6 @@ Item {
} }
} }
CollectibleDetailView { CollectibleDetailView {
Layout.fillWidth: true
Layout.fillHeight: true
collectible: RootStore.collectiblesStore.detailedCollectible collectible: RootStore.collectiblesStore.detailedCollectible
isCollectibleLoading: RootStore.collectiblesStore.isDetailedCollectibleLoading isCollectibleLoading: RootStore.collectiblesStore.isDetailedCollectibleLoading
@ -169,8 +167,6 @@ Item {
AssetsDetailView { AssetsDetailView {
id: assetDetailView id: assetDetailView
Layout.fillWidth: true
Layout.fillHeight: true
visible: (stack.currentIndex === 2) visible: (stack.currentIndex === 2)
assetsLoading: RootStore.assetsLoading assetsLoading: RootStore.assetsLoading
@ -186,8 +182,6 @@ Item {
TransactionDetailView { TransactionDetailView {
id: transactionDetailView id: transactionDetailView
Layout.fillWidth: true
Layout.fillHeight: true
onVisibleChanged: { onVisibleChanged: {
if (!visible) if (!visible)
transaction = null transaction = null

View File

@ -1612,6 +1612,7 @@ Item {
this.open = false this.open = false
} }
onLinkActivated: { onLinkActivated: {
this.open = false
if(actionRequired) { if(actionRequired) {
toastsManager.doAction(model.actionType, model.actionData) toastsManager.doAction(model.actionType, model.actionData)
return return

View File

@ -1,6 +1,6 @@
import QtQuick 2.14 import QtQuick 2.15
import QtQuick.Layouts 1.14 import QtQuick.Layouts 1.15
import QtGraphicalEffects 1.13 import QtGraphicalEffects 1.15
import utils 1.0 import utils 1.0
@ -12,14 +12,24 @@ Rectangle {
id: root id: root
property bool active: false property bool active: false
property bool cancelButtonVisible: true
property bool saveChangesButtonEnabled: false property bool saveChangesButtonEnabled: false
property bool saveForLaterButtonVisible
property alias saveChangesText: saveChangesButton.text property alias saveChangesText: saveChangesButton.text
property alias saveForLaterText: saveForLaterButton.text
property alias cancelChangesText: cancelChangesButton.text property alias cancelChangesText: cancelChangesButton.text
property alias changesDetectedText: changesDetectedTextItem.text property alias changesDetectedText: changesDetectedTextItem.text
property Flickable flickable: null property Flickable flickable: null
enum Type {
Danger,
Info
}
property int type: SettingsDirtyToastMessage.Type.Danger
signal saveChangesClicked signal saveChangesClicked
signal saveForLaterClicked
signal resetChangesClicked signal resetChangesClicked
function notifyDirty() { function notifyDirty() {
@ -33,8 +43,9 @@ Rectangle {
opacity: active ? 1 : 0 opacity: active ? 1 : 0
color: Theme.palette.statusToastMessage.backgroundColor color: Theme.palette.statusToastMessage.backgroundColor
radius: 8 radius: 8
border.color: Theme.palette.dangerColor2 border.color: type === SettingsDirtyToastMessage.Type.Danger ? Theme.palette.dangerColor2 : Theme.palette.primaryColor2
border.width: 2 border.width: 2
layer.enabled: true layer.enabled: true
layer.effect: DropShadow { layer.effect: DropShadow {
verticalOffset: 3 verticalOffset: 3
@ -42,7 +53,7 @@ Rectangle {
samples: 15 samples: 15
fast: true fast: true
cached: true cached: true
color: Theme.palette.dangerColor2 color: root.border.color
spread: 0.1 spread: 0.1
} }
@ -104,7 +115,6 @@ Rectangle {
StatusBaseText { StatusBaseText {
id: changesDetectedTextItem id: changesDetectedTextItem
Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
padding: 8 padding: 8
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
@ -116,10 +126,19 @@ Rectangle {
id: cancelChangesButton id: cancelChangesButton
text: qsTr("Cancel") text: qsTr("Cancel")
enabled: root.active enabled: root.active
visible: root.cancelButtonVisible
type: StatusBaseButton.Type.Danger type: StatusBaseButton.Type.Danger
onClicked: root.resetChangesClicked() onClicked: root.resetChangesClicked()
} }
StatusFlatButton {
id: saveForLaterButton
text: qsTr("Save for later")
enabled: root.active && root.saveChangesButtonEnabled
visible: root.saveForLaterButtonVisible
onClicked: root.saveForLaterClicked()
}
StatusButton { StatusButton {
id: saveChangesButton id: saveChangesButton
objectName: "settingsDirtyToastMessageSaveButton" objectName: "settingsDirtyToastMessageSaveButton"