mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-26 05:26:00 +00:00
feat: Profile Showcase: Proof of concept for own Profile Dialog
- the goal of this PR is to get some bsais UI building blocks done for the followup PRs - the order of showcase tabs now is: Communities/Accounts/Collectibles/Assets - there will be further changes to accomodate for different types of backend models as those get developed (for other users' profiles) Fixes #9664
This commit is contained in:
parent
2204273a22
commit
5c0f1981ad
@ -67,7 +67,11 @@
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A17655",
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A17087",
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23525",
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23932"
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23932",
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23932&t=h8DUW6Eysawqe5u0-0",
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=724%3A15511&t=h8DUW6Eysawqe5u0-0",
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=6%3A16845&t=h8DUW6Eysawqe5u0-0",
|
||||
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A25437&t=h8DUW6Eysawqe5u0-0"
|
||||
],
|
||||
"StatusCommunityCard": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416159",
|
||||
|
@ -2,13 +2,15 @@ import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import Storybook 1.0
|
||||
|
||||
import utils 1.0
|
||||
import shared.views 1.0
|
||||
import mainui 1.0
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Core.Utils 0.1 as CoreUtils
|
||||
|
||||
import Storybook 1.0
|
||||
import Models 1.0
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
@ -55,7 +57,7 @@ SplitView {
|
||||
alias: "Mock Alias Triplet",
|
||||
lastUpdated: Date.now(),
|
||||
lastUpdatedLocally: Date.now(),
|
||||
localNickname: "MockNickname",
|
||||
localNickname: localNickname.text,
|
||||
thumbnailImage: "",
|
||||
largeImage: userImage.checked ? Style.png("status-logo") : "",
|
||||
isContact: isContact.checked,
|
||||
@ -74,8 +76,8 @@ SplitView {
|
||||
text: "__twitter",
|
||||
url: "https://twitter.com/ethstatus",
|
||||
icon: "twitter"
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
text: "__github",
|
||||
url: "https://github.com/status-im",
|
||||
icon: "github"
|
||||
@ -122,6 +124,8 @@ SplitView {
|
||||
|
||||
publicKey: switchOwnProfile.checked ? "0xdeadbeef" : "0xrandomguy"
|
||||
|
||||
onCloseRequested: logs.logEvent("closeRequested()")
|
||||
|
||||
profileStore: QtObject {
|
||||
readonly property string pubkey: "0xdeadbeef"
|
||||
readonly property string ensName: name.text
|
||||
@ -169,6 +173,209 @@ SplitView {
|
||||
logs.logEvent("contactsStore::verifiedUntrustworthy", ["publicKey"], arguments)
|
||||
}
|
||||
}
|
||||
|
||||
communitiesModel: ListModel {
|
||||
ListElement {
|
||||
name: "Not the cool gang"
|
||||
amISectionAdmin: false
|
||||
description: "Nothing to write home about"
|
||||
color: "indigo"
|
||||
image: ""
|
||||
joined: true
|
||||
members: [
|
||||
ListElement { displayName: "Joe" }
|
||||
]
|
||||
}
|
||||
ListElement {
|
||||
name: "Awesome bunch"
|
||||
amISectionAdmin: true
|
||||
description: "Where the cool guys hang out & Nothing to write home about"
|
||||
color: "green"
|
||||
image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
joined: true
|
||||
members: [
|
||||
ListElement { displayName: "Alex" },
|
||||
ListElement { displayName: "AlexJb" },
|
||||
ListElement { displayName: "Michal" },
|
||||
ListElement { displayName: "Noelia" },
|
||||
ListElement { displayName: "Lukáš" }
|
||||
]
|
||||
}
|
||||
ListElement {
|
||||
name: "Invisible community (should not display!)"
|
||||
amISectionAdmin: false
|
||||
description: "Get outta here"
|
||||
color: "red"
|
||||
image: ""
|
||||
joined: false
|
||||
members: []
|
||||
}
|
||||
}
|
||||
|
||||
walletStore: QtObject {
|
||||
function switchAccountByAddress(address) {
|
||||
logs.logEvent("walletStore::switchAccountByAddress", ["address"], arguments)
|
||||
}
|
||||
|
||||
function selectCollectible(slug, id) {
|
||||
logs.logEvent("walletStore::selectCollectible", ["slug", "id"], arguments)
|
||||
}
|
||||
|
||||
readonly property var accounts: ListModel {
|
||||
ListElement {
|
||||
name: "My Status Account"
|
||||
address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7420"
|
||||
color: "aliceblue"
|
||||
emoji: "🇨🇿"
|
||||
walletType: ""
|
||||
}
|
||||
ListElement {
|
||||
name: "testing (no emoji, colored, saved, seed)"
|
||||
address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7000"
|
||||
color: "olive"
|
||||
walletType: "seed"
|
||||
}
|
||||
ListElement {
|
||||
name: "My Bro's Account"
|
||||
address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7421"
|
||||
color: "ghostwhite"
|
||||
emoji: "🇸🇰"
|
||||
walletType: "watch"
|
||||
}
|
||||
ListElement {
|
||||
name: "Keycard"
|
||||
address: "0xdeadbeef"
|
||||
color: "red"
|
||||
emoji: ""
|
||||
walletType: "key"
|
||||
}
|
||||
}
|
||||
|
||||
function getNameForSavedWalletAddress(address) {
|
||||
return CoreUtils.ModelUtils.getByKey(savedAddresses, "address", address, "name") ?? ""
|
||||
}
|
||||
|
||||
function createOrUpdateSavedAddress(name, address, favourite) {
|
||||
logs.logEvent("walletStore::createOrUpdateSavedAddress", ["name", "address", "favourite"], arguments)
|
||||
savedAddresses.append({name, address, favourite, ens: false})
|
||||
return "" // no error
|
||||
}
|
||||
|
||||
readonly property var savedAddresses: ListModel {
|
||||
ListElement {
|
||||
name: "My Status Saved Account"
|
||||
address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7000"
|
||||
favourite: true
|
||||
ens: false
|
||||
}
|
||||
}
|
||||
|
||||
readonly property var currentAccount: QtObject {
|
||||
readonly property var assets: ListModel {
|
||||
readonly property var data: [
|
||||
{
|
||||
symbol: "MANA",
|
||||
enabledNetworkBalance: {
|
||||
amount: 301,
|
||||
symbol: "MANA"
|
||||
},
|
||||
changePct24hour: -2.1,
|
||||
visibleForNetworkWithPositiveBalance: true
|
||||
},
|
||||
{
|
||||
symbol: "AAVE",
|
||||
enabledNetworkBalance: {
|
||||
amount: 23.3,
|
||||
symbol: "AAVE"
|
||||
},
|
||||
changePct24hour: 4.56,
|
||||
visibleForNetworkWithPositiveBalance: true
|
||||
},
|
||||
{
|
||||
symbol: "POLY",
|
||||
enabledNetworkBalance: {
|
||||
amount: 3590,
|
||||
symbol: "POLY"
|
||||
},
|
||||
changePct24hour: -11.6789,
|
||||
visibleForNetworkWithPositiveBalance: true
|
||||
},
|
||||
{
|
||||
symbol: "CDT",
|
||||
enabledNetworkBalance: {
|
||||
amount: 1000,
|
||||
symbol: "CDT"
|
||||
},
|
||||
changePct24hour: 0,
|
||||
visibleForNetworkWithPositiveBalance: true
|
||||
},
|
||||
{
|
||||
symbol: "MKR",
|
||||
enabledNetworkBalance: {
|
||||
amount: 1.3,
|
||||
symbol: "MKR"
|
||||
},
|
||||
//changePct24hour: undefined // NB 'undefined' on purpose
|
||||
visibleForNetworkWithPositiveBalance: true
|
||||
},
|
||||
{
|
||||
symbol: "InvisibleHere",
|
||||
enabledNetworkBalance: {},
|
||||
changePct24hour: 0,
|
||||
visibleForNetworkWithPositiveBalance: false
|
||||
}
|
||||
]
|
||||
Component.onCompleted: append(data)
|
||||
}
|
||||
}
|
||||
|
||||
readonly property var flatCollectibles: ListModel {
|
||||
readonly property var data: [
|
||||
{
|
||||
//id: 123,
|
||||
name: "Crypto Kitties",
|
||||
description: "Super Crypto Kitty",
|
||||
backgroundColor: "",
|
||||
imageUrl: ModelsData.collectibles.cryptoKitties,
|
||||
permalink: ""
|
||||
},
|
||||
{
|
||||
id: 34545656768,
|
||||
name: "Kitty 1",
|
||||
description: "",
|
||||
backgroundColor: "green",
|
||||
imageUrl: ModelsData.collectibles.kitty1Big,
|
||||
permalink: ""
|
||||
},
|
||||
{
|
||||
id: 123456,
|
||||
name: "Kitty 2",
|
||||
description: "",
|
||||
backgroundColor: "",
|
||||
imageUrl: ModelsData.collectibles.kitty2Big,
|
||||
permalink: ""
|
||||
},
|
||||
{
|
||||
id: 12345645459537432,
|
||||
name: "",
|
||||
description: "Kitty 3 description",
|
||||
backgroundColor: "oink",
|
||||
imageUrl: ModelsData.collectibles.kitty3Big,
|
||||
permalink: ""
|
||||
},
|
||||
{
|
||||
id: 691,
|
||||
name: "KILLABEAR #691",
|
||||
description: "Please note that weapons are not yet reflected in the rarity stats.",
|
||||
backgroundColor: "#807c56",
|
||||
imageUrl: "https://assets.killabears.com/content/killabears/img/691-e81f892696a8ae700e0dbc62eb072060679a2046d1ef5eb2671bdb1fad1f68e3.png",
|
||||
permalink: "https://opensea.io/assets/ethereum/0xc99c679c50033bbc5321eb88752e89a93e9e83c5/691"
|
||||
}
|
||||
]
|
||||
Component.onCompleted: append(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,6 +399,12 @@ SplitView {
|
||||
}
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Label { text: "localNickname:" }
|
||||
TextField {
|
||||
id: localNickname
|
||||
text: "MockNickname"
|
||||
placeholderText: "Local Nickname"
|
||||
}
|
||||
Label { text: "displayName:" }
|
||||
TextField {
|
||||
id: displayName
|
||||
@ -237,7 +450,7 @@ SplitView {
|
||||
TextField {
|
||||
id: name
|
||||
enabled: ensVerified.checked
|
||||
text: ensVerified.checked ? "mock-ens-name" : ""
|
||||
text: ensVerified.checked ? "mock-ens-name.eth" : ""
|
||||
placeholderText: "ENS name"
|
||||
}
|
||||
}
|
||||
@ -290,6 +503,7 @@ SplitView {
|
||||
TextField {
|
||||
Layout.fillWidth: true
|
||||
id: bio
|
||||
selectByMouse: true
|
||||
text: "Hi, I am Alex. I'm an indie developer who mainly works on web products.
|
||||
|
||||
I worked for several different companies and created a couple of my own products from scratch. Currently building Telescope and Prepacked.
|
||||
|
@ -140,7 +140,7 @@ Control {
|
||||
This signal is emitted when the ToastMessage contains a url and this url
|
||||
is clicked by the user.
|
||||
*/
|
||||
signal linkActivated(var link)
|
||||
signal linkActivated(string link)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
@ -70,7 +70,7 @@ Item {
|
||||
textSelectedAddress.text = selectedAccount.address
|
||||
}
|
||||
if (selectedAccount.currencyBalance) {
|
||||
textSelectedAddressFiatBalance.text = selectedAccount.currencyBalance + " " + currency.toUpperCase()
|
||||
textSelectedAddressFiatBalance.text = LocaleUtils.currencyAmountToLocaleString(selectedAccount.currencyBalance)
|
||||
}
|
||||
if (selectedAccount.assets && showBalanceForAssetSymbol) {
|
||||
assetFound = Utils.findAssetByChainAndSymbol(root.chainId, selectedAccount.assets, showBalanceForAssetSymbol)
|
||||
@ -239,7 +239,7 @@ Item {
|
||||
id: txtFiatBalance
|
||||
Layout.rightMargin: 4
|
||||
font.pixelSize: 15
|
||||
text: currencyBalance
|
||||
text: LocaleUtils.currencyAmountToLocaleString(currencyBalance, {onlyAmount: true})
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
|
@ -18,11 +18,8 @@ ToolTip {
|
||||
property int offset: 0
|
||||
property alias arrow: arrow
|
||||
|
||||
implicitWidth: Math.min(maxWidth, contentItem.implicitWidth + 16)
|
||||
leftPadding: 8
|
||||
rightPadding: 8
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
implicitWidth: Math.min(maxWidth, implicitContentWidth + 16)
|
||||
padding: 8
|
||||
delay: 200
|
||||
background: Item {
|
||||
id: statusToolTipBackground
|
||||
@ -73,6 +70,6 @@ ToolTip {
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
bottomPadding: 8
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,8 +71,7 @@ SettingsPageLayout {
|
||||
}
|
||||
}
|
||||
|
||||
readonly property string initialState: root.permissionsModel.count > 0
|
||||
? d.permissionsViewState : d.welcomeViewState
|
||||
readonly property string initialState: d.permissionsExist ? d.permissionsViewState : d.welcomeViewState
|
||||
|
||||
function initializeData() {
|
||||
holdingsToEditModel = emptyModel
|
||||
|
@ -101,7 +101,7 @@ QtObject {
|
||||
}
|
||||
|
||||
function setActiveCommunity(communityId) {
|
||||
mainModule.setActiveSectionById(communityId);
|
||||
root.mainModuleInst.setActiveSectionById(communityId);
|
||||
}
|
||||
|
||||
function navigateToCommunity(communityId) {
|
||||
|
@ -107,6 +107,7 @@ StatusSectionLayout {
|
||||
profileStore: root.store.profileStore
|
||||
privacyStore: root.store.privacyStore
|
||||
contactsStore: root.store.contactsStore
|
||||
communitiesModel: root.store.communitiesList
|
||||
sectionTitle: root.store.getNameForSubsection(Constants.settingsSubsection.profile)
|
||||
contentWidth: d.contentWidth
|
||||
}
|
||||
|
2
ui/app/AppLayouts/Profile/controls/qmldir
Normal file
2
ui/app/AppLayouts/Profile/controls/qmldir
Normal file
@ -0,0 +1,2 @@
|
||||
CommunityDelegate 1.0 CommunityDelegate.qml
|
||||
WalletAccountDelegate 1.0 WalletAccountDelegate.qml
|
@ -25,6 +25,7 @@ SettingsContentBase {
|
||||
property ProfileStore profileStore
|
||||
property PrivacyStore privacyStore
|
||||
property ContactsStore contactsStore
|
||||
property var communitiesModel
|
||||
|
||||
titleRowComponentLoader.sourceComponent: StatusButton {
|
||||
objectName: "profileSettingsChangePasswordButton"
|
||||
@ -72,6 +73,7 @@ SettingsContentBase {
|
||||
profileStore: root.profileStore
|
||||
privacyStore: root.privacyStore
|
||||
walletStore: root.walletStore
|
||||
communitiesModel: root.communitiesModel
|
||||
|
||||
onVisibleChanged: if (visible) stackLayout.Layout.preferredHeight = settingsView.implicitHeight
|
||||
Component.onCompleted: stackLayout.Layout.preferredHeight = Qt.binding(() => settingsView.implicitHeight)
|
||||
@ -82,6 +84,7 @@ SettingsContentBase {
|
||||
|
||||
profileStore: root.profileStore
|
||||
contactsStore: root.contactsStore
|
||||
communitiesModel: root.communitiesModel
|
||||
dirtyValues: settingsView.dirtyValues
|
||||
dirty: settingsView.dirty
|
||||
|
||||
|
@ -8,6 +8,7 @@ import StatusQ.Core.Theme 0.1
|
||||
Item {
|
||||
property alias profileStore: profilePreview.profileStore
|
||||
property alias contactsStore: profilePreview.contactsStore
|
||||
property alias communitiesModel: profilePreview.communitiesModel
|
||||
property alias dirtyValues: profilePreview.dirtyValues
|
||||
property alias dirty: profilePreview.dirty
|
||||
|
||||
|
@ -26,6 +26,7 @@ ColumnLayout {
|
||||
property PrivacyStore privacyStore
|
||||
property ProfileStore profileStore
|
||||
property WalletStore walletStore
|
||||
property var communitiesModel
|
||||
|
||||
property QtObject dirtyValues: QtObject {
|
||||
property string displayName: descriptionPanel.displayName.text
|
||||
@ -158,7 +159,7 @@ ColumnLayout {
|
||||
|
||||
StatusListItem {
|
||||
Layout.fillWidth: true
|
||||
visible: Qt.platform.os == "osx"
|
||||
visible: Qt.platform.os === Constants.mac
|
||||
title: qsTr("Biometric login and transaction authentication")
|
||||
asset.name: "touch-id"
|
||||
components: [ StatusSwitch {
|
||||
@ -218,13 +219,13 @@ ColumnLayout {
|
||||
|
||||
Repeater {
|
||||
id: communitiesRepeater
|
||||
model: communitiesModule.model
|
||||
model: root.communitiesModel
|
||||
|
||||
CommunityDelegate {
|
||||
width: parent.width
|
||||
visible: joined
|
||||
community: model
|
||||
enabled: false
|
||||
sensor.enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,7 +247,7 @@ ColumnLayout {
|
||||
width: parent.width
|
||||
account: model
|
||||
showShevronIcon: false
|
||||
enabled: false
|
||||
sensor.enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +141,10 @@ QtObject {
|
||||
walletSection.switchAccount(newIndex)
|
||||
}
|
||||
|
||||
function switchAccountByAddress(address) {
|
||||
walletSection.switchAccountByAddress(address)
|
||||
}
|
||||
|
||||
function generateNewAccount(password, accountName, color, emoji, path, derivedFrom) {
|
||||
return walletSectionAccounts.generateNewAccount(password, accountName, color, emoji, path, derivedFrom)
|
||||
}
|
||||
@ -198,6 +202,10 @@ QtObject {
|
||||
walletSectionCurrentCollectible.update(slug, id)
|
||||
}
|
||||
|
||||
function getNameForSavedWalletAddress(address) {
|
||||
return walletSectionSavedAddresses.getNameByAddress(address)
|
||||
}
|
||||
|
||||
function createOrUpdateSavedAddress(name, address, favourite, chainShortNames, ens) {
|
||||
return walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address, favourite, chainShortNames, ens)
|
||||
}
|
||||
|
@ -169,9 +169,9 @@ Rectangle {
|
||||
components: [
|
||||
StatusIcon {
|
||||
icon: {
|
||||
if (model.walletType == "watch")
|
||||
if (model.walletType === Constants.watchWalletType)
|
||||
return "show"
|
||||
else if (model.walletType == "key")
|
||||
if (model.walletType === Constants.keyWalletType)
|
||||
return "keycard"
|
||||
|
||||
return ""
|
||||
|
@ -163,6 +163,14 @@ Item {
|
||||
Global.settingsSubsection = subsection;
|
||||
}
|
||||
}
|
||||
|
||||
function onOpenSendModal(address: string) {
|
||||
sendModal.open(address)
|
||||
}
|
||||
|
||||
function onSwitchToCommunity(communityId: string) {
|
||||
communitiesPortalLayoutContainer.communitiesStore.setActiveCommunity(communityId)
|
||||
}
|
||||
}
|
||||
|
||||
function changeAppSectionBySectionId(sectionId) {
|
||||
@ -1119,7 +1127,10 @@ Item {
|
||||
this.open = false
|
||||
}
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link);
|
||||
if (link.startsWith("#")) // internal link to section
|
||||
globalConns.onAppSectionBySectionTypeChanged(link.substring(1))
|
||||
else
|
||||
Global.openLink(link)
|
||||
}
|
||||
|
||||
onClose: {
|
||||
|
@ -287,6 +287,7 @@ QtObject {
|
||||
id: profilePopup
|
||||
profileStore: rootStore.profileSectionStore.profileStore
|
||||
contactsStore: rootStore.profileSectionStore.contactsStore
|
||||
communitiesModel: rootStore.profileSectionStore.communitiesList
|
||||
|
||||
onClosed: {
|
||||
if (profilePopup.parentPopup) {
|
||||
|
@ -14,8 +14,6 @@ import StatusQ.Core.Backpressure 1.0
|
||||
import shared.controls 1.0
|
||||
import utils 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import "../controls"
|
||||
|
||||
Item {
|
||||
|
@ -13,6 +13,7 @@ StatusDialog {
|
||||
|
||||
property var profileStore
|
||||
property var contactsStore
|
||||
property var communitiesModel
|
||||
|
||||
width: 640
|
||||
padding: 0
|
||||
@ -24,6 +25,7 @@ StatusDialog {
|
||||
publicKey: root.publicKey
|
||||
profileStore: root.profileStore
|
||||
contactsStore: root.contactsStore
|
||||
communitiesModel: root.communitiesModel
|
||||
onCloseRequested: root.close()
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,8 @@ Item {
|
||||
id: assetListView
|
||||
objectName: "assetViewStatusListView"
|
||||
anchors.fill: parent
|
||||
model: RootStore.tokensLoading ? 25 : filteredModel
|
||||
model: RootStore.tokensLoading ? Constants.dummyModelItems : filteredModel
|
||||
delegate: RootStore.tokensLoading ? loadingTokenDelegate : tokenDelegate
|
||||
ScrollBar.vertical: StatusScrollBar {}
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtGraphicalEffects 1.14
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
@ -9,6 +9,7 @@ import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
import utils 1.0
|
||||
import shared.controls 1.0
|
||||
@ -16,16 +17,23 @@ import shared.panels 1.0
|
||||
import shared.popups 1.0
|
||||
import shared.controls.chat 1.0
|
||||
import shared.controls.chat.menuItems 1.0
|
||||
import shared.views.profile 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import AppLayouts.Wallet.stores 1.0 as WalletNS
|
||||
|
||||
Pane {
|
||||
id: root
|
||||
|
||||
property bool readOnly
|
||||
property bool readOnly // inside settings/profile/preview
|
||||
|
||||
property string publicKey: contactsStore.myPublicKey
|
||||
|
||||
property var profileStore
|
||||
property var contactsStore
|
||||
property var walletStore: WalletNS.RootStore
|
||||
property var communitiesModel
|
||||
|
||||
property QtObject dirtyValues: null
|
||||
property bool dirty: false
|
||||
@ -547,8 +555,10 @@ Pane {
|
||||
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
implicitWidth: contentWidth + leftPadding + rightPadding
|
||||
implicitHeight: contentHeight + topPadding + bottomPadding
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: contentHeight + topPadding + bottomPadding
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: -column.anchors.leftMargin
|
||||
Layout.rightMargin: -column.anchors.rightMargin
|
||||
Layout.topMargin: -column.spacing
|
||||
@ -562,8 +572,7 @@ Pane {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: column.anchors.leftMargin + Style.current.halfPadding
|
||||
Layout.rightMargin: column.anchors.rightMargin + Style.current.halfPadding
|
||||
bio: root.dirty ? root.dirtyValues.bio
|
||||
: d.contactDetails.bio
|
||||
bio: root.dirty ? root.dirtyValues.bio : d.contactDetails.bio
|
||||
userSocialLinksJson: root.dirty ? root.profileStore.temporarySocialLinksJson
|
||||
: d.contactDetails.socialLinks
|
||||
}
|
||||
@ -666,26 +675,17 @@ Pane {
|
||||
height: width
|
||||
mipmap: true
|
||||
smooth: false
|
||||
source: root.profileStore.getQrCodeSource(root.profileStore.pubkey)
|
||||
source: root.profileStore.getQrCodeSource(Utils.getCompressedPk(root.profileStore.pubkey))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusTabBar {
|
||||
id: showcaseTabBar
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: column.anchors.leftMargin
|
||||
Layout.rightMargin: column.anchors.rightMargin
|
||||
bottomPadding: -4
|
||||
|
||||
StatusTabButton {
|
||||
leftPadding: 0
|
||||
width: implicitWidth
|
||||
text: qsTr("Assets")
|
||||
}
|
||||
StatusTabButton {
|
||||
width: implicitWidth
|
||||
text: qsTr("Collectibles")
|
||||
}
|
||||
StatusTabButton {
|
||||
width: implicitWidth
|
||||
text: qsTr("Communities")
|
||||
@ -694,27 +694,32 @@ Pane {
|
||||
width: implicitWidth
|
||||
text: qsTr("Accounts")
|
||||
}
|
||||
StatusTabButton {
|
||||
width: implicitWidth
|
||||
text: qsTr("Collectibles")
|
||||
}
|
||||
StatusTabButton {
|
||||
leftPadding: 0
|
||||
width: implicitWidth
|
||||
text: qsTr("Assets")
|
||||
}
|
||||
}
|
||||
|
||||
StatusDialogBackground {
|
||||
// Profile Showcase
|
||||
ProfileShowcaseView {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -column.spacing
|
||||
Layout.preferredHeight: 300
|
||||
color: Theme.palette.baseColor4
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
height: parent.radius
|
||||
color: parent.color
|
||||
}
|
||||
currentTabIndex: showcaseTabBar.currentIndex
|
||||
isCurrentUser: d.isCurrentUser
|
||||
mainDisplayName: d.mainDisplayName
|
||||
readOnly: root.readOnly
|
||||
profileStore: root.profileStore
|
||||
walletStore: root.walletStore
|
||||
communitiesModel: root.communitiesModel
|
||||
|
||||
StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("More content to appear here soon...")
|
||||
}
|
||||
onCloseRequested: root.closeRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,6 +159,7 @@ Column {
|
||||
anchors.centerIn: parent
|
||||
text: "GIF"
|
||||
font.pixelSize: 13
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
395
ui/imports/shared/views/profile/ProfileShowcaseView.qml
Normal file
395
ui/imports/shared/views/profile/ProfileShowcaseView.qml
Normal file
@ -0,0 +1,395 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
import utils 1.0
|
||||
import shared.controls 1.0 // Timer
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
property alias currentTabIndex: stackLayout.currentIndex
|
||||
property bool isCurrentUser
|
||||
property string mainDisplayName
|
||||
property bool readOnly
|
||||
property var profileStore
|
||||
property var walletStore
|
||||
property var communitiesModel
|
||||
|
||||
signal closeRequested()
|
||||
|
||||
horizontalPadding: readOnly ? 20 : 40 // smaller in settings/preview
|
||||
topPadding: Style.current.bigPadding
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property string copyLiteral: qsTr("Copy")
|
||||
|
||||
readonly property var timer: Timer {
|
||||
id: timer
|
||||
}
|
||||
}
|
||||
|
||||
background: StatusDialogBackground {
|
||||
color: Theme.palette.baseColor4
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
height: parent.radius
|
||||
color: parent.color
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: StackLayout {
|
||||
id: stackLayout
|
||||
|
||||
// communities
|
||||
ColumnLayout {
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
visible: communitiesView.count == 0
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("%1 hasn't joined any communities yet").arg(root.mainDisplayName)
|
||||
}
|
||||
|
||||
StatusGridView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
id: communitiesView
|
||||
rightMargin: Style.current.halfPadding
|
||||
cellWidth: (width-rightMargin)/2
|
||||
cellHeight: cellWidth/2
|
||||
visible: count
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: root.isCurrentUser ? root.communitiesModel : null // TODO show other users too
|
||||
filters: ValueFilter {
|
||||
roleName: "joined"
|
||||
value: true
|
||||
}
|
||||
sorters: [
|
||||
RoleSorter {
|
||||
roleName: "amISectionAdmin"
|
||||
sortOrder: Qt.DescendingOrder // admin first
|
||||
},
|
||||
StringSorter {
|
||||
roleName: "name"
|
||||
caseSensitivity: Qt.CaseInsensitive
|
||||
}
|
||||
]
|
||||
}
|
||||
ScrollBar.vertical: StatusScrollBar { }
|
||||
delegate: StatusListItem { // TODO custom delegate
|
||||
width: GridView.view.cellWidth - Style.current.smallPadding
|
||||
height: GridView.view.cellHeight - Style.current.smallPadding
|
||||
title: model.name
|
||||
statusListItemTitle.font.pixelSize: 17
|
||||
statusListItemTitle.font.bold: true
|
||||
subTitle: model.description
|
||||
tertiaryTitle: qsTr("%n member(s)", "", model.members.count)
|
||||
asset.name: model.image ?? model.name
|
||||
asset.isImage: asset.name.startsWith("data:image/")
|
||||
asset.isLetterIdenticon: !model.image
|
||||
asset.color: model.color
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
border.width: 1
|
||||
border.color: Theme.palette.baseColor2
|
||||
components: [
|
||||
StatusIcon {
|
||||
visible: model.amISectionAdmin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon: "crown"
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
if (root.readOnly)
|
||||
return
|
||||
root.closeRequested()
|
||||
Global.switchToCommunity(model.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wallets/accounts
|
||||
ColumnLayout {
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
visible: accountsView.count == 0
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("%1 doesn't have any wallet accounts yet").arg(root.mainDisplayName)
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
id: accountsView
|
||||
spacing: Style.current.halfPadding
|
||||
visible: count
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: root.isCurrentUser ? root.walletStore.accounts : null // TODO show other users too
|
||||
filters: ValueFilter { // everything except keycards
|
||||
roleName: "walletType"
|
||||
value: Constants.keyWalletType
|
||||
inverted: true
|
||||
}
|
||||
}
|
||||
delegate: StatusListItem {
|
||||
id: accountDelegate
|
||||
property bool saved: root.walletStore.getNameForSavedWalletAddress(model.address) !== ""
|
||||
border.width: 1
|
||||
border.color: Theme.palette.baseColor2
|
||||
width: ListView.view.width
|
||||
title: model.name
|
||||
subTitle: StatusQUtils.Utils.elideText(model.address, 6, 4).replace("0x", "0×")
|
||||
asset.color: model.color
|
||||
asset.emoji: model.emoji ?? ""
|
||||
asset.name: asset.emoji || "filled-account"
|
||||
asset.isLetterIdenticon: asset.emoji
|
||||
asset.letterSize: 14
|
||||
asset.bgColor: Theme.palette.primaryColor3
|
||||
asset.isImage: asset.emoji
|
||||
components: [
|
||||
StatusIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: model.walletType === Constants.watchWalletType
|
||||
icon: "show"
|
||||
color: Theme.palette.directColor1
|
||||
},
|
||||
StatusFlatButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: StatusBaseButton.Size.Small
|
||||
enabled: !accountDelegate.saved
|
||||
text: accountDelegate.saved ? qsTr("Address saved") : qsTr("Save Address")
|
||||
onClicked: {
|
||||
accountDelegate.saved = root.walletStore.createOrUpdateSavedAddress(model.name, model.address, false) === ""
|
||||
Global.displayToastMessage(qsTr("%1 saved to your wallet").arg(accountDelegate.subTitle),
|
||||
qsTr("Go to your wallet"),
|
||||
"wallet",
|
||||
false,
|
||||
Constants.ephemeralNotificationType.normal,
|
||||
`#${Constants.appSection.wallet}` // internal link to wallet section
|
||||
)
|
||||
}
|
||||
},
|
||||
StatusFlatRoundButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
icon.name: "send"
|
||||
tooltip.text: qsTr("Send")
|
||||
onClicked: {
|
||||
root.walletStore.switchAccountByAddress(model.address)
|
||||
Global.openSendModal(model.address)
|
||||
}
|
||||
},
|
||||
StatusFlatRoundButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
icon.name: "copy"
|
||||
tooltip.text: d.copyLiteral
|
||||
onClicked: {
|
||||
tooltip.text = qsTr("Copied")
|
||||
root.profileStore.copyToClipboard(model.address)
|
||||
d.timer.setTimeout(function() {
|
||||
tooltip.text = d.copyLiteral
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
if (root.readOnly)
|
||||
return
|
||||
root.walletStore.switchAccountByAddress(model.address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collectibles/NFTs
|
||||
ColumnLayout {
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
visible: collectiblesView.count == 0
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("%1 doesn't have any collectibles/NFTs yet").arg(root.mainDisplayName)
|
||||
}
|
||||
|
||||
StatusGridView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
id: collectiblesView
|
||||
rightMargin: Style.current.halfPadding
|
||||
cellWidth: (width-rightMargin)/4
|
||||
cellHeight: cellWidth
|
||||
visible: count
|
||||
model: root.isCurrentUser ? root.walletStore.flatCollectibles : null // TODO show other users too
|
||||
ScrollBar.vertical: StatusScrollBar { }
|
||||
delegate: StatusRoundedImage {
|
||||
width: GridView.view.cellWidth - Style.current.smallPadding
|
||||
height: GridView.view.cellHeight - Style.current.smallPadding
|
||||
border.width: 1
|
||||
border.color: Theme.palette.directColor7
|
||||
color: !!model.backgroundColor ? model.backgroundColor : "transparent"
|
||||
radius: Style.current.radius
|
||||
showLoadingIndicator: model.isLoading
|
||||
image.fillMode: Image.PreserveAspectCrop
|
||||
image.source: model.imageUrl ?? ""
|
||||
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.halfPadding
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: Style.current.halfPadding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.halfPadding
|
||||
|
||||
Control {
|
||||
Layout.maximumWidth: parent.width
|
||||
horizontalPadding: Style.current.halfPadding
|
||||
verticalPadding: Style.current.halfPadding/2
|
||||
visible: !!model.id
|
||||
|
||||
background: Rectangle {
|
||||
radius: Style.current.halfPadding/2
|
||||
color: Theme.palette.indirectColor2
|
||||
}
|
||||
contentItem: StatusBaseText {
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
maximumLineCount: 1
|
||||
elide: Text.ElideRight
|
||||
text: `#${model.id}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: hhandler.hovered && (!!model.name || !!model.description)
|
||||
text: {
|
||||
const name = model.name
|
||||
const descr = model.description
|
||||
const sep = !!name && !!descr ? "<br>" : ""
|
||||
return `<b>${name}</b>${sep}${descr}`
|
||||
}
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: hhandler
|
||||
cursorShape: hovered ? Qt.PointingHandCursor : undefined
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onSingleTapped: {
|
||||
Global.openLink(model.permalink)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assets/tokens
|
||||
ColumnLayout {
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
visible: assetsView.count == 0
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("%1 doesn't have any assets/tokens yet").arg(root.mainDisplayName)
|
||||
}
|
||||
|
||||
StatusGridView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
id: assetsView
|
||||
rightMargin: Style.current.halfPadding
|
||||
cellWidth: (width-rightMargin)/3
|
||||
cellHeight: cellWidth/2.5
|
||||
visible: count
|
||||
model: SortFilterProxyModel {
|
||||
// TODO show assets for all accounts, not just the current one?
|
||||
sourceModel: root.isCurrentUser ? root.walletStore.currentAccount.assets : null // TODO show other users too
|
||||
filters: ValueFilter {
|
||||
roleName: "visibleForNetworkWithPositiveBalance"
|
||||
value: true
|
||||
}
|
||||
sorters: [
|
||||
StringSorter {
|
||||
roleName: "name"
|
||||
},
|
||||
StringSorter {
|
||||
roleName: "symbol"
|
||||
}
|
||||
]
|
||||
}
|
||||
ScrollBar.vertical: StatusScrollBar { }
|
||||
delegate: StatusListItem {
|
||||
readonly property double changePct24hour: model.changePct24hour ?? 0
|
||||
readonly property string textColor: changePct24hour === 0
|
||||
? Theme.palette.baseColor1 : changePct24hour < 0
|
||||
? Theme.palette.dangerColor1 : Theme.palette.successColor1
|
||||
readonly property string arrow: changePct24hour === 0 ? "" : changePct24hour < 0 ? "↓" : "↑"
|
||||
|
||||
width: GridView.view.cellWidth - Style.current.halfPadding
|
||||
height: GridView.view.cellHeight - Style.current.halfPadding
|
||||
title: LocaleUtils.currencyAmountToLocaleString(model.enabledNetworkBalance)
|
||||
statusListItemTitle.font.weight: Font.Medium
|
||||
tertiaryTitle: qsTr("%1% today %2")
|
||||
.arg(LocaleUtils.numberToLocaleString(changePct24hour, changePct24hour === 0 ? 0 : 2)).arg(arrow)
|
||||
statusListItemTertiaryTitle.color: textColor
|
||||
statusListItemTertiaryTitle.font.pixelSize: Theme.asideTextFontSize
|
||||
statusListItemTertiaryTitle.anchors.topMargin: 6
|
||||
leftPadding: Style.current.halfPadding
|
||||
rightPadding: Style.current.halfPadding
|
||||
border.width: 1
|
||||
border.color: Theme.palette.baseColor2
|
||||
components: [
|
||||
Image {
|
||||
width: 40
|
||||
height: 40
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: Style.png("tokens/" + model.symbol)
|
||||
onStatusChanged: {
|
||||
if (status === Image.Error) {
|
||||
source = Style.png("tokens/DEFAULT-TOKEN")
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
if (root.readOnly)
|
||||
return
|
||||
// TODO what to do here?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
ui/imports/shared/views/profile/qmldir
Normal file
1
ui/imports/shared/views/profile/qmldir
Normal file
@ -0,0 +1 @@
|
||||
ProfileShowcaseView 1.0 ProfileShowcaseView.qml
|
@ -47,6 +47,9 @@ QtObject {
|
||||
signal setNthEnabledSectionActive(int nthSection)
|
||||
signal appSectionBySectionTypeChanged(int sectionType, int subsection)
|
||||
|
||||
signal openSendModal(string address)
|
||||
signal switchToCommunity(string communityId)
|
||||
|
||||
signal playSendMessageSound()
|
||||
signal playNotificationSound()
|
||||
signal playErrorSound()
|
||||
|
Loading…
x
Reference in New Issue
Block a user