chore(@desktop/wallet): Use transparent background and add scroll shadow (#11118)
This commit is contained in:
parent
47c76714db
commit
5d7a4723bf
|
@ -575,9 +575,11 @@ Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: detailsColumn.childrenRect.height
|
height: detailsColumn.childrenRect.height
|
||||||
default property alias content: detailsColumn.children
|
default property alias content: detailsColumn.children
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: tileBackground
|
id: tileBackground
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
color: Style.current.transparent
|
||||||
radius: 8
|
radius: 8
|
||||||
border.width: 1
|
border.width: 1
|
||||||
border.color: Style.current.separator
|
border.color: Style.current.separator
|
||||||
|
@ -590,7 +592,12 @@ Item {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
layer.effect: OpacityMask {
|
layer.effect: OpacityMask {
|
||||||
maskSource: tileBackground
|
// Separate rectangle is used as mask because background rectangle must be transaprent
|
||||||
|
maskSource: Rectangle {
|
||||||
|
width: tileBackground.width
|
||||||
|
height: tileBackground.height
|
||||||
|
radius: tileBackground.radius
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ 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 utils 1.0
|
||||||
import shared.panels 1.0
|
import shared.panels 1.0
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -61,6 +62,7 @@ StatusListItem {
|
||||||
height: visible ? implicitHeight + bottomPadding : 0
|
height: visible ? implicitHeight + bottomPadding : 0
|
||||||
radius: 0
|
radius: 0
|
||||||
sensor.cursorShape: Qt.ArrowCursor
|
sensor.cursorShape: Qt.ArrowCursor
|
||||||
|
color: sensor.containsMouse ? Theme.palette.baseColor5 : Style.current.transparent
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
statusListItemTitle.customColor: Theme.palette.directColor5
|
statusListItemTitle.customColor: Theme.palette.directColor5
|
||||||
|
|
|
@ -399,7 +399,7 @@ StatusListItem {
|
||||||
|
|
||||||
rightPadding: 16
|
rightPadding: 16
|
||||||
enabled: !loading
|
enabled: !loading
|
||||||
color: sensor.containsMouse ? Theme.palette.baseColor5 : Theme.palette.statusListItem.backgroundColor
|
color: sensor.containsMouse ? Theme.palette.baseColor5 : Style.current.transparent
|
||||||
|
|
||||||
statusListItemIcon.active: (loading || root.asset.name)
|
statusListItemIcon.active: (loading || root.asset.name)
|
||||||
asset {
|
asset {
|
||||||
|
|
|
@ -74,129 +74,141 @@ ColumnLayout {
|
||||||
store: WalletStores.RootStore
|
store: WalletStores.RootStore
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator {
|
Item {
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: filterComponent.visible
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusListView {
|
|
||||||
id: transactionListRoot
|
|
||||||
objectName: "walletAccountTransactionList"
|
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
Layout.topMargin: nonArchivalNodeError.visible || noTxs.visible ? Style.current.padding : 0
|
Layout.topMargin: nonArchivalNodeError.visible || noTxs.visible ? Style.current.padding : 0
|
||||||
Layout.bottomMargin: Style.current.padding
|
Layout.bottomMargin: Style.current.padding
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
property string firstSection
|
Rectangle { // Shadow behind delegates when scrolling
|
||||||
|
anchors.top: topListSeparator.bottom
|
||||||
|
width: parent.width
|
||||||
|
height: 4
|
||||||
|
color: Style.current.separator
|
||||||
|
visible: topListSeparator.visible
|
||||||
|
}
|
||||||
|
|
||||||
model: SortFilterProxyModel {
|
StatusListView {
|
||||||
id: txModel
|
id: transactionListRoot
|
||||||
|
objectName: "walletAccountTransactionList"
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
sourceModel: RootStore.historyTransactions
|
property string firstSection
|
||||||
|
|
||||||
// LocaleUtils is not accessable from inside expression, but local function works
|
model: SortFilterProxyModel {
|
||||||
property var formatDate: (ms) => LocaleUtils.formatDate(ms, Locale.ShortFormat)
|
id: txModel
|
||||||
proxyRoles: ExpressionRole {
|
|
||||||
name: "date"
|
sourceModel: RootStore.historyTransactions
|
||||||
expression: {
|
|
||||||
return model.activityEntry.timestamp > 0 ? txModel.formatDate(model.activityEntry.timestamp * 1000) : (d.isLoading ? " " : "") // not empty, because section will not be displayed when loading if empty
|
// LocaleUtils is not accessable from inside expression, but local function works
|
||||||
|
property var formatDate: (ms) => LocaleUtils.formatDate(ms, Locale.ShortFormat)
|
||||||
|
proxyRoles: ExpressionRole {
|
||||||
|
name: "date"
|
||||||
|
expression: {
|
||||||
|
return model.activityEntry.timestamp > 0 ? txModel.formatDate(model.activityEntry.timestamp * 1000) : (d.isLoading ? " " : "") // not empty, because section will not be displayed when loading if empty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
delegate: transactionDelegate
|
delegate: transactionDelegate
|
||||||
|
|
||||||
footer: footerComp
|
footer: footerComp
|
||||||
|
|
||||||
displaced: Transition { // TODO Remove animation when ordered fetching of transactions is implemented
|
displaced: Transition { // TODO Remove animation when ordered fetching of transactions is implemented
|
||||||
NumberAnimation { properties: "y"; duration: 250; easing.type: Easing.Linear; alwaysRunToEnd: true }
|
NumberAnimation { properties: "y"; duration: 250; easing.type: Easing.Linear; alwaysRunToEnd: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property point lastVisibleItemPos: Qt.point(0, contentY + height - 1)
|
readonly property point lastVisibleItemPos: Qt.point(0, contentY + height - 1)
|
||||||
property int lastVisibleIndex: indexAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
property int lastVisibleIndex: indexAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
||||||
|
|
||||||
|
onCountChanged: {
|
||||||
|
// Preserve last visible item in view when more items added at the end or
|
||||||
|
// inbetween
|
||||||
|
// TODO Remove this logic, when new activity design is implemented
|
||||||
|
// and items are loaded in order
|
||||||
|
const lastVisibleItem = itemAtIndex(lastVisibleIndex)
|
||||||
|
const newItem = itemAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
||||||
|
const lastVisibleItemY = lastVisibleItem ? lastVisibleItem.y : -1
|
||||||
|
if (newItem) {
|
||||||
|
if (newItem.y < lastVisibleItemY) { // item inserted higher than last visible
|
||||||
|
lastVisibleIndex = indexAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentIndex: 0
|
||||||
|
|
||||||
|
property bool userScrolled: false
|
||||||
|
|
||||||
onCountChanged: {
|
|
||||||
// Preserve last visible item in view when more items added at the end or
|
|
||||||
// inbetween
|
|
||||||
// TODO Remove this logic, when new activity design is implemented
|
// TODO Remove this logic, when new activity design is implemented
|
||||||
// and items are loaded in order
|
// and items are loaded in order
|
||||||
const lastVisibleItem = itemAtIndex(lastVisibleIndex)
|
onMovingVerticallyChanged: {
|
||||||
const newItem = itemAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
if (!userScrolled) {
|
||||||
const lastVisibleItemY = lastVisibleItem ? lastVisibleItem.y : -1
|
userScrolled = true
|
||||||
if (newItem) {
|
currentIndex = Qt.binding(() => lastVisibleIndex >= 0 ? lastVisibleIndex : (count - 1))
|
||||||
if (newItem.y < lastVisibleItemY) { // item inserted higher than last visible
|
|
||||||
lastVisibleIndex = indexAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
currentIndex: 0
|
|
||||||
|
|
||||||
property bool userScrolled: false
|
lastVisibleIndex = indexAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
||||||
|
|
||||||
// TODO Remove this logic, when new activity design is implemented
|
|
||||||
// and items are loaded in order
|
|
||||||
onMovingVerticallyChanged: {
|
|
||||||
if (!userScrolled) {
|
|
||||||
userScrolled = true
|
|
||||||
currentIndex = Qt.binding(() => lastVisibleIndex >= 0 ? lastVisibleIndex : (count - 1))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastVisibleIndex = indexAt(lastVisibleItemPos.x, lastVisibleItemPos.y)
|
ScrollBar.vertical: StatusScrollBar {}
|
||||||
}
|
|
||||||
|
|
||||||
ScrollBar.vertical: StatusScrollBar {}
|
section.property: "date"
|
||||||
|
topMargin: -20 // Top margin for first section. Section cannot have different sizes
|
||||||
|
section.delegate: ColumnLayout {
|
||||||
|
id: sectionDelegate
|
||||||
|
|
||||||
section.property: "date"
|
readonly property bool isFirstSection: ListView.view.firstSection === section
|
||||||
topMargin: -20 // Top margin for first section. Section cannot have different sizes
|
|
||||||
section.delegate: ColumnLayout {
|
|
||||||
id: sectionDelegate
|
|
||||||
|
|
||||||
readonly property bool isFirstSection: ListView.view.firstSection === section
|
width: ListView.view.width
|
||||||
|
// display always first section. Other sections when more items are being fetched must not be visible
|
||||||
|
// 1 because we don't use empty for loading state
|
||||||
|
// Additionaly height must be defined so all sections use same height to to glitch sections when updating model
|
||||||
|
height: isFirstSection || section.length > 1 ? 58 : 0
|
||||||
|
visible: height > 0 // display always first section. Other sections when more items are being fetched must not be visible
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
width: ListView.view.width
|
required property string section
|
||||||
// display always first section. Other sections when more items are being fetched must not be visible
|
|
||||||
// 1 because we don't use empty for loading state
|
|
||||||
// Additionaly height must be defined so all sections use same height to to glitch sections when updating model
|
|
||||||
height: isFirstSection || section.length > 1 ? 58 : 0
|
|
||||||
visible: height > 0 // display always first section. Other sections when more items are being fetched must not be visible
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
required property string section
|
Separator {
|
||||||
|
Layout.fillWidth: true
|
||||||
Separator {
|
Layout.topMargin: 20
|
||||||
Layout.fillWidth: true
|
implicitHeight: 1
|
||||||
Layout.topMargin: 20
|
|
||||||
implicitHeight: 1
|
|
||||||
visible: !sectionDelegate.isFirstSection
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusTextWithLoadingState {
|
|
||||||
id: sectionText
|
|
||||||
Layout.alignment: Qt.AlignBottom
|
|
||||||
leftPadding: 16
|
|
||||||
bottomPadding: 8
|
|
||||||
text: loading ? "dummy" : parent.section // dummy text because loading component height depends on text height, and not visible with height == 0
|
|
||||||
Binding on width {
|
|
||||||
when: sectionText.loading
|
|
||||||
value: 56
|
|
||||||
restoreMode: Binding.RestoreBindingOrValue
|
|
||||||
}
|
}
|
||||||
customColor: Theme.palette.baseColor1
|
|
||||||
font.pixelSize: 13
|
StatusTextWithLoadingState {
|
||||||
verticalAlignment: Qt.AlignBottom
|
id: sectionText
|
||||||
loading: { // First section must be loading when first item in the list is loading. Other sections are never visible until have date value
|
Layout.alignment: Qt.AlignBottom
|
||||||
if (parent.ListView.view.count > 0) {
|
leftPadding: 16
|
||||||
const firstItem = parent.ListView.view.itemAtIndex(0)
|
bottomPadding: 8
|
||||||
if (sectionDelegate.isFirstSection && firstItem && firstItem.loading) {
|
text: loading ? "dummy" : parent.section // dummy text because loading component height depends on text height, and not visible with height == 0
|
||||||
return true
|
Binding on width {
|
||||||
}
|
when: sectionText.loading
|
||||||
|
value: 56
|
||||||
|
restoreMode: Binding.RestoreBindingOrValue
|
||||||
|
}
|
||||||
|
customColor: Theme.palette.baseColor1
|
||||||
|
font.pixelSize: 13
|
||||||
|
verticalAlignment: Qt.AlignBottom
|
||||||
|
loading: { // First section must be loading when first item in the list is loading. Other sections are never visible until have date value
|
||||||
|
if (parent.ListView.view.count > 0) {
|
||||||
|
const firstItem = parent.ListView.view.itemAtIndex(0)
|
||||||
|
if (sectionDelegate.isFirstSection && firstItem && firstItem.loading) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onAtYEndChanged: if(atYEnd) RootStore.fetchMoreTransactions()
|
||||||
|
}
|
||||||
|
|
||||||
|
Separator {
|
||||||
|
id: topListSeparator
|
||||||
|
width: parent.width
|
||||||
|
visible: !transactionListRoot.atYBeginning
|
||||||
}
|
}
|
||||||
onAtYEndChanged: if(atYEnd) RootStore.fetchMoreTransactions()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusMenu {
|
StatusMenu {
|
||||||
|
|
Loading…
Reference in New Issue