qml: many UI updates and additions
This commit is contained in:
31
electrum/gui/qml/components/BalanceSummary.qml
Normal file
31
electrum/gui/qml/components/BalanceSummary.qml
Normal file
@@ -0,0 +1,31 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
Item {
|
||||
height: layout.height
|
||||
|
||||
GridLayout {
|
||||
id: layout
|
||||
|
||||
columns: 3
|
||||
Label {
|
||||
Layout.columnSpan: 3
|
||||
font.pointSize: 14
|
||||
text: 'Balance: ' + Daemon.currentWallet.confirmedBalance //'5.6201 mBTC'
|
||||
}
|
||||
Label {
|
||||
font.pointSize: 8
|
||||
text: 'Confirmed: ' + Daemon.currentWallet.confirmedBalance
|
||||
}
|
||||
Label {
|
||||
font.pointSize: 8
|
||||
text: 'Unconfirmed: ' + Daemon.currentWallet.unconfirmedBalance
|
||||
}
|
||||
Label {
|
||||
font.pointSize: 8
|
||||
text: 'Lightning: ?'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,132 +2,146 @@ import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
Item {
|
||||
import Electrum 1.0
|
||||
|
||||
Pane {
|
||||
id: rootItem
|
||||
visible: Daemon.currentWallet !== undefined
|
||||
clip: true
|
||||
|
||||
property string title: 'History'
|
||||
|
||||
Column {
|
||||
ListView {
|
||||
id: listview
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
ListView {
|
||||
width: parent.width
|
||||
height: 200
|
||||
model: Daemon.currentWallet.historyModel
|
||||
|
||||
model: Daemon.currentWallet.historyModel
|
||||
delegate: Item {
|
||||
id: delegate
|
||||
width: ListView.view.width
|
||||
height: txinfo.height
|
||||
header: Item {
|
||||
id: header
|
||||
width: ListView.view.width
|
||||
height: balance.height
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: delegate
|
||||
onClicked: extinfo.visible = !extinfo.visible
|
||||
BalanceSummary {
|
||||
id: balance
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
id: delegate
|
||||
width: ListView.view.width
|
||||
height: txinfo.height
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: delegate
|
||||
onClicked: extinfo.visible = !extinfo.visible
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: txinfo
|
||||
columns: 4
|
||||
|
||||
x: 6
|
||||
width: delegate.width - 12
|
||||
|
||||
Item {
|
||||
id: indicator
|
||||
Layout.fillHeight: true
|
||||
Layout.rowSpan: 2
|
||||
Rectangle {
|
||||
width: 3
|
||||
color: model.incoming ? 'green' : 'red'
|
||||
y: 2
|
||||
height: parent.height - 4
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
readonly property variant tx_icons : [
|
||||
"../../../gui/icons/unconfirmed.png",
|
||||
"../../../gui/icons/clock1.png",
|
||||
"../../../gui/icons/clock2.png",
|
||||
"../../../gui/icons/clock3.png",
|
||||
"../../../gui/icons/clock4.png",
|
||||
"../../../gui/icons/clock5.png",
|
||||
"../../../gui/icons/confirmed.png"
|
||||
]
|
||||
|
||||
sourceSize.width: 48
|
||||
sourceSize.height: 48
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
source: tx_icons[Math.min(6,model.confirmations)]
|
||||
}
|
||||
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Label {
|
||||
font.pointSize: 12
|
||||
text: model.label !== '' ? model.label : '<no label>'
|
||||
color: model.label !== '' ? 'black' : 'gray'
|
||||
font.bold: model.label !== '' ? true : false
|
||||
}
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
text: model.date
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: valuefee
|
||||
Label {
|
||||
font.pointSize: 12
|
||||
text: model.bc_value
|
||||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
font.pointSize: 6
|
||||
text: 'fee: ' + (model.fee !== undefined ? model.fee : '0')
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: txinfo
|
||||
columns: 4
|
||||
id: extinfo
|
||||
visible: false
|
||||
columns: 2
|
||||
Layout.columnSpan: 3
|
||||
|
||||
x: 6
|
||||
width: delegate.width - 12
|
||||
|
||||
Item {
|
||||
id: indicator
|
||||
Layout.fillHeight: true
|
||||
Layout.rowSpan: 2
|
||||
Rectangle {
|
||||
width: 3
|
||||
color: model.incoming ? 'green' : 'red'
|
||||
y: 2
|
||||
height: parent.height - 4
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
readonly property variant tx_icons : [
|
||||
"../../../gui/icons/unconfirmed.png",
|
||||
"../../../gui/icons/clock1.png",
|
||||
"../../../gui/icons/clock2.png",
|
||||
"../../../gui/icons/clock3.png",
|
||||
"../../../gui/icons/clock4.png",
|
||||
"../../../gui/icons/clock5.png",
|
||||
"../../../gui/icons/confirmed.png"
|
||||
]
|
||||
|
||||
sourceSize.width: 32
|
||||
sourceSize.height: 32
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
source: tx_icons[Math.min(6,model.confirmations)]
|
||||
}
|
||||
|
||||
Column {
|
||||
Label { text: 'txid' }
|
||||
Label {
|
||||
font.pointSize: 6
|
||||
text: model.txid
|
||||
elide: Text.ElideMiddle
|
||||
Layout.fillWidth: true
|
||||
|
||||
Label {
|
||||
text: model.label !== '' ? model.label : '<no label>'
|
||||
color: model.label !== '' ? 'black' : 'gray'
|
||||
font.bold: model.label !== '' ? true : false
|
||||
}
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
text: model.date
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: valuefee
|
||||
Label {
|
||||
text: model.bc_value
|
||||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
font.pointSize: 6
|
||||
text: 'fee: ' + (model.fee !== undefined ? model.fee : '0')
|
||||
}
|
||||
Label { text: 'height' }
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
text: model.height
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: extinfo
|
||||
visible: false
|
||||
columns: 2
|
||||
Layout.columnSpan: 3
|
||||
|
||||
Label { text: 'txid' }
|
||||
Label {
|
||||
font.pointSize: 6
|
||||
text: model.txid
|
||||
elide: Text.ElideMiddle
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Label { text: 'height' }
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
text: model.height
|
||||
}
|
||||
Label { text: 'confirmations' }
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
text: model.confirmations
|
||||
}
|
||||
Label { text: 'address' }
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
elide: Text.ElideMiddle
|
||||
Layout.fillWidth: true
|
||||
text: {
|
||||
for (var i=0; i < Object.keys(model.outputs).length; i++) {
|
||||
if (model.outputs[i].value === model.bc_value) {
|
||||
return model.outputs[i].address
|
||||
}
|
||||
Label { text: 'confirmations' }
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
text: model.confirmations
|
||||
}
|
||||
Label { text: 'address' }
|
||||
Label {
|
||||
font.pointSize: 7
|
||||
elide: Text.ElideMiddle
|
||||
Layout.fillWidth: true
|
||||
text: {
|
||||
for (var i=0; i < Object.keys(model.outputs).length; i++) {
|
||||
if (model.outputs[i].value === model.bc_value) {
|
||||
return model.outputs[i].address
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // delegate
|
||||
}
|
||||
|
||||
}
|
||||
} // delegate
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,14 @@ import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
Item {
|
||||
Pane {
|
||||
property string title: qsTr('Network')
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
|
||||
Label { text: qsTr("Network: "); color: Material.primaryHighlightedTextColor; font.bold: true }
|
||||
Label { text: Network.networkName }
|
||||
Label { text: qsTr("Server: "); color: Material.primaryHighlightedTextColor; font.bold: true }
|
||||
Label { text: Network.server }
|
||||
Label { text: qsTr("Local Height: "); color: Material.primaryHighlightedTextColor; font.bold: true }
|
||||
|
||||
@@ -4,11 +4,10 @@ import QtQuick.Controls 2.0
|
||||
Item {
|
||||
|
||||
property bool toolbar: false
|
||||
property string title: 'scan'
|
||||
|
||||
QRScan {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: button.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,16 @@ import QtQuick 2.6
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.0
|
||||
|
||||
Item {
|
||||
Pane {
|
||||
id: rootItem
|
||||
|
||||
property string title: 'Send'
|
||||
|
||||
GridLayout {
|
||||
width: rootItem.width - 12
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width
|
||||
columns: 4
|
||||
|
||||
Label {
|
||||
BalanceSummary {
|
||||
Layout.columnSpan: 4
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: "Current Balance: 0 mBTC"
|
||||
//Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -47,20 +43,31 @@ Item {
|
||||
placeholderText: 'sat/vB'
|
||||
}
|
||||
|
||||
Column {
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 4
|
||||
|
||||
Button {
|
||||
Row {
|
||||
spacing: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: 'Pay'
|
||||
onClicked: {
|
||||
var i_amount = parseInt(amount.text)
|
||||
if (isNaN(i_amount))
|
||||
return
|
||||
var result = Daemon.currentWallet.send_onchain(address.text, i_amount, undefined, false)
|
||||
if (result)
|
||||
app.stack.pop()
|
||||
Button {
|
||||
// anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: 'Pay'
|
||||
enabled: address.text != '' && amount.text != '' && fee.text != '' // TODO proper validation
|
||||
onClicked: {
|
||||
var i_amount = parseInt(amount.text)
|
||||
if (isNaN(i_amount))
|
||||
return
|
||||
var result = Daemon.currentWallet.send_onchain(address.text, i_amount, undefined, false)
|
||||
if (result)
|
||||
app.stack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: 'Scan QR Code'
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
onClicked: app.stack.push(Qt.resolvedUrl('Scan.qml'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,42 +2,104 @@ import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
Item {
|
||||
Pane {
|
||||
id: rootItem
|
||||
|
||||
property string title: 'Wallets'
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
ListView {
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
model: Daemon.availableWallets
|
||||
|
||||
delegate: Item {
|
||||
width: ListView.view.width
|
||||
height: 50
|
||||
Item {
|
||||
width: parent.width
|
||||
height: detailsLayout.height
|
||||
|
||||
RowLayout {
|
||||
x: 20
|
||||
spacing: 20
|
||||
|
||||
Image {
|
||||
source: "../../../gui/kivy/theming/light/wallet.png"
|
||||
GridLayout {
|
||||
id: detailsLayout
|
||||
width: parent.width
|
||||
columns: 4
|
||||
|
||||
Label { text: 'Wallet'; Layout.columnSpan: 2 }
|
||||
Label { text: Daemon.walletName; Layout.columnSpan: 2 }
|
||||
|
||||
Label { text: 'txinType' }
|
||||
Label { text: Daemon.currentWallet.txinType }
|
||||
|
||||
Label { text: 'is deterministic' }
|
||||
Label { text: Daemon.currentWallet.isDeterministic }
|
||||
|
||||
Label { text: 'is watch only' }
|
||||
Label { text: Daemon.currentWallet.isWatchOnly }
|
||||
|
||||
Label { text: 'is Encrypted' }
|
||||
Label { text: Daemon.currentWallet.isEncrypted }
|
||||
|
||||
Label { text: 'is Hardware' }
|
||||
Label { text: Daemon.currentWallet.isHardware }
|
||||
|
||||
Label { text: 'derivation path (BIP32)'; visible: Daemon.currentWallet.isDeterministic }
|
||||
Label { text: Daemon.currentWallet.derivationPath; visible: Daemon.currentWallet.isDeterministic }
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
Label {
|
||||
font.pointSize: model.active ? 14 : 13
|
||||
font.bold: model.active
|
||||
text: model.name
|
||||
Layout.fillWidth: true
|
||||
Item {
|
||||
width: parent.width
|
||||
// height: detailsFrame.height
|
||||
Layout.fillHeight: true
|
||||
Frame {
|
||||
id: detailsFrame
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
ListView {
|
||||
id: listview
|
||||
width: parent.width
|
||||
// Layout.fillHeight: true
|
||||
height: parent.height
|
||||
clip:true
|
||||
model: Daemon.availableWallets
|
||||
|
||||
// header: sadly seems to be buggy
|
||||
|
||||
delegate: AbstractButton {
|
||||
width: ListView.view.width
|
||||
height: 50
|
||||
onClicked: console.log('delegate clicked')
|
||||
RowLayout {
|
||||
x: 20
|
||||
spacing: 20
|
||||
|
||||
Image {
|
||||
source: "../../../gui/kivy/theming/light/wallet.png"
|
||||
}
|
||||
|
||||
Label {
|
||||
font.pointSize: 12
|
||||
text: model.name
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Button {
|
||||
text: 'Load'
|
||||
onClicked: {
|
||||
Daemon.load_wallet(model.path, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}}}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: openMenu()
|
||||
Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: 'Create Wallet'
|
||||
onClicked: {
|
||||
var dialog = app.newWalletWizard.createObject(rootItem)
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,59 +1,87 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQml 2.6
|
||||
|
||||
Item {
|
||||
id: rootItem
|
||||
|
||||
property string title: 'Network'
|
||||
property string title: Daemon.walletName
|
||||
|
||||
property QtObject menu: Menu {
|
||||
MenuItem { text: 'Wallets'; onTriggered: stack.push(Qt.resolvedUrl('Wallets.qml')) }
|
||||
MenuItem { text: 'Network'; onTriggered: stack.push(Qt.resolvedUrl('NetworkStats.qml')) }
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Button {
|
||||
text: 'Scan QR Code'
|
||||
onClicked: app.stack.push(Qt.resolvedUrl('Scan.qml'))
|
||||
}
|
||||
|
||||
Button {
|
||||
text: 'Send'
|
||||
onClicked: app.stack.push(Qt.resolvedUrl('Send.qml'))
|
||||
}
|
||||
|
||||
Button {
|
||||
text: 'Show TX History'
|
||||
onClicked: app.stack.push(Qt.resolvedUrl('History.qml'))
|
||||
}
|
||||
|
||||
Button {
|
||||
text: 'Create Wallet'
|
||||
onClicked: {
|
||||
var dialog = newWalletWizard.createObject(rootItem)
|
||||
dialog.open()
|
||||
TabBar {
|
||||
id: tabbar
|
||||
Layout.fillWidth: true
|
||||
currentIndex: swipeview.currentIndex
|
||||
TabButton {
|
||||
text: qsTr('Receive')
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr('History')
|
||||
}
|
||||
TabButton {
|
||||
enabled: !Daemon.currentWallet.isWatchOnly
|
||||
text: qsTr('Send')
|
||||
}
|
||||
}
|
||||
|
||||
SwipeView {
|
||||
id: swipeview
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
currentIndex: tabbar.currentIndex
|
||||
|
||||
Item {
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
y: 20
|
||||
spacing: 20
|
||||
|
||||
Button {
|
||||
onClicked: stack.push(Qt.resolvedUrl('Wallets.qml'))
|
||||
text: 'Wallets'
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Button {
|
||||
text: 'Create Wallet'
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
onClicked: {
|
||||
var dialog = app.newWalletWizard.createObject(rootItem)
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
History {
|
||||
id: history
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
enabled: !Daemon.currentWallet.isWatchOnly
|
||||
Send {
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: newWalletWizard
|
||||
NewWalletWizard {
|
||||
parent: Overlay.overlay
|
||||
x: 12
|
||||
y: 12
|
||||
width: parent.width - 24
|
||||
height: parent.height - 24
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: "#aa000000"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
@@ -25,15 +25,50 @@ ApplicationWindow
|
||||
anchors.fill: parent
|
||||
ToolButton {
|
||||
text: qsTr("‹")
|
||||
enabled: stack.currentItem.StackView.index > 0
|
||||
enabled: stack.depth > 1
|
||||
onClicked: stack.pop()
|
||||
}
|
||||
Item {
|
||||
width: column.width
|
||||
height: column.height
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
var dialog = app.messageDialog.createObject(app, {'message':
|
||||
'Electrum is currently on ' + Network.networkName + ''
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
visible: Network.isTestNet
|
||||
Image {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 16
|
||||
height: 16
|
||||
source: "../../icons/info.png"
|
||||
}
|
||||
|
||||
Label {
|
||||
id: networkNameLabel
|
||||
text: Network.networkName
|
||||
color: Material.accentColor //'orange'
|
||||
font.pointSize: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: stack.currentItem.title
|
||||
elide: Label.ElideRight
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
font.pointSize: 10
|
||||
font.bold: true
|
||||
}
|
||||
ToolButton {
|
||||
text: qsTr("⋮")
|
||||
@@ -55,7 +90,7 @@ ApplicationWindow
|
||||
|
||||
Timer {
|
||||
id: splashTimer
|
||||
interval: 1000
|
||||
interval: 10
|
||||
onTriggered: {
|
||||
splash.opacity = 0
|
||||
}
|
||||
@@ -73,8 +108,49 @@ ApplicationWindow
|
||||
}
|
||||
}
|
||||
|
||||
property alias newWalletWizard: _newWalletWizard
|
||||
Component {
|
||||
id: _newWalletWizard
|
||||
NewWalletWizard {
|
||||
parent: Overlay.overlay
|
||||
x: 12
|
||||
y: 12
|
||||
width: parent.width - 24
|
||||
height: parent.height - 24
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: "#aa000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property alias messageDialog: _messageDialog
|
||||
Component {
|
||||
id: _messageDialog
|
||||
Dialog {
|
||||
parent: Overlay.overlay
|
||||
modal: true
|
||||
x: (parent.width - width) / 2
|
||||
y: (parent.height - height) / 2
|
||||
|
||||
title: "Message"
|
||||
property alias message: messageLabel.text
|
||||
Label {
|
||||
id: messageLabel
|
||||
text: "Lorem ipsum dolor sit amet..."
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Daemon.load_wallet()
|
||||
splashTimer.start()
|
||||
}
|
||||
|
||||
onClosing: {
|
||||
// destroy most GUI components so that we don't dump so many null reference warnings on exit
|
||||
app.header.visible = false
|
||||
mainStackView.clear()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user