Currently on master the qml fee histogram colours are calculated for feerates clamped to [1, 600] sat/vbyte. I want to extend it to now cover [0, 600] sat/vbyte.
I would like to extend it in a way that does not change the existing colour meanings/mapping, so not just e.g. doing an offset.
follow-up bd6dfc53a2
339 lines
12 KiB
QML
339 lines
12 KiB
QML
import QtQuick
|
|
import QtQuick.Layouts
|
|
import QtQuick.Controls
|
|
import QtQuick.Controls.Material
|
|
|
|
import "controls"
|
|
|
|
Pane {
|
|
id: root
|
|
objectName: 'NetworkOverview'
|
|
|
|
padding: 0
|
|
|
|
property string title: qsTr("Network")
|
|
|
|
function _getFeerateColor(sat_per_vbyte) {
|
|
// To display a nice quickly graspable view of the mempool fee histogram, we map
|
|
// feerates to fixed colors. E.g. when the histogram is full of red, the user can
|
|
// instantly see fees are high.
|
|
// In the 1-600 s/b range, play with hue:
|
|
var hsv_hue = (2/3-(2/3*(
|
|
Math.log(
|
|
Math.min(600, Math.max(sat_per_vbyte, 1))
|
|
)
|
|
/Math.log(600))
|
|
))
|
|
// In the 0-1 s/b range, play with value:
|
|
var hsv_value = Math.min(sat_per_vbyte, 1)
|
|
return Qt.hsva(hsv_hue, 0.8, hsv_value, 1)
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
spacing: 0
|
|
|
|
Flickable {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
Layout.topMargin: constants.paddingLarge
|
|
Layout.leftMargin: constants.paddingLarge
|
|
Layout.rightMargin: constants.paddingLarge
|
|
|
|
contentHeight: contentLayout.height
|
|
clip: true
|
|
interactive: height < contentHeight
|
|
|
|
GridLayout {
|
|
id: contentLayout
|
|
width: parent.width
|
|
columns: 2
|
|
Heading {
|
|
Layout.columnSpan: 2
|
|
text: qsTr('On-chain')
|
|
}
|
|
Label {
|
|
text: qsTr('Network') + ':'
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
text: Network.networkName
|
|
}
|
|
Label {
|
|
text: qsTr('Status') + ':'
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
text: Network.status
|
|
}
|
|
Label {
|
|
text: qsTr('Server') + ':'
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
text: Network.serverWithStatus
|
|
wrapMode: Text.WrapAnywhere
|
|
Layout.fillWidth: true
|
|
}
|
|
Label {
|
|
text: qsTr('Local Height:');
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
text: Network.height
|
|
}
|
|
Label {
|
|
text: qsTr('Server Height:');
|
|
color: Material.accentColor
|
|
visible: Network.serverHeight != 0 && Network.serverHeight != Network.height
|
|
}
|
|
Label {
|
|
text: Network.serverHeight + " " + (Network.serverHeight < Network.height ? "(lagging)" : "(syncing...)")
|
|
visible: Network.serverHeight != 0 && Network.serverHeight != Network.height
|
|
}
|
|
Label {
|
|
text: qsTr('Chain tips:');
|
|
color: Material.accentColor
|
|
visible: opacity > 0
|
|
opacity: Network.chaintips > 1 ? 1 : 0
|
|
Behavior on opacity { NumberAnimation { duration: 1000 } }
|
|
}
|
|
RowLayout {
|
|
visible: opacity > 0
|
|
opacity: Network.chaintips > 1 ? 1 : 0
|
|
Behavior on opacity { NumberAnimation { duration: 1000 } }
|
|
OnchainNetworkStatusIndicator {
|
|
sourceSize.width: constants.iconSizeSmall
|
|
sourceSize.height: constants.iconSizeSmall
|
|
}
|
|
Label {
|
|
text: Network.chaintips
|
|
}
|
|
}
|
|
Heading {
|
|
Layout.columnSpan: 2
|
|
text: qsTr('Mempool fees')
|
|
}
|
|
Item {
|
|
id: histogramRoot
|
|
Layout.columnSpan: 2
|
|
Layout.fillWidth: true
|
|
implicitHeight: histogramLayout.height
|
|
|
|
ColumnLayout {
|
|
id: histogramLayout
|
|
width: parent.width
|
|
spacing: 0
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
height: 28
|
|
spacing: 0
|
|
Repeater {
|
|
model: Network.feeHistogram.histogram
|
|
Rectangle {
|
|
Layout.preferredWidth: 300 * (modelData[1] / Network.feeHistogram.total)
|
|
Layout.fillWidth: true
|
|
height: parent.height
|
|
color: _getFeerateColor(modelData[0])
|
|
ToolTip.text: (qsTr("%1 around depth %2")
|
|
.arg(modelData[0] + " " + UI_UNIT_NAME.FEERATE_SAT_PER_VB)
|
|
.arg((modelData[2]/1000000).toFixed(2) + " " + UI_UNIT_NAME.MEMPOOL_MB)
|
|
)
|
|
ToolTip.visible: ma.containsMouse
|
|
MouseArea {
|
|
id: ma
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
height: 3
|
|
spacing: 0
|
|
|
|
Repeater {
|
|
model: Network.feeHistogram.total / 1000000
|
|
RowLayout {
|
|
height: parent.height
|
|
spacing: 0
|
|
Rectangle {
|
|
Layout.preferredWidth: 1
|
|
Layout.fillWidth: false
|
|
height: parent.height
|
|
width: 1
|
|
color: 'white'
|
|
}
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: parent.height
|
|
}
|
|
}
|
|
}
|
|
Rectangle {
|
|
Layout.preferredWidth: 1
|
|
Layout.fillWidth: false
|
|
height: parent.height
|
|
width: 1
|
|
color: 'white'
|
|
}
|
|
}
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
Label {
|
|
text: '<-- ' + Math.ceil(Network.feeHistogram.max_fee) + " " + UI_UNIT_NAME.FEERATE_SAT_PER_VB
|
|
font.pixelSize: constants.fontSizeXSmall
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
Layout.fillWidth: true
|
|
horizontalAlignment: Text.AlignRight
|
|
text: Math.floor(Network.feeHistogram.min_fee) + " " + UI_UNIT_NAME.FEERATE_SAT_PER_VB + ' -->'
|
|
font.pixelSize: constants.fontSizeXSmall
|
|
color: Material.accentColor
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Heading {
|
|
Layout.columnSpan: 2
|
|
text: qsTr('Lightning')
|
|
}
|
|
|
|
Label {
|
|
text: (Config.useGossip ? qsTr('Gossip') : qsTr('Trampoline')) + ':'
|
|
color: Material.accentColor
|
|
}
|
|
ColumnLayout {
|
|
visible: Config.useGossip
|
|
Label {
|
|
text: qsTr('%1 peers').arg(Network.gossipInfo.peers)
|
|
}
|
|
Label {
|
|
text: qsTr('%1 channels to fetch').arg(Network.gossipInfo.unknown_channels)
|
|
}
|
|
Label {
|
|
text: qsTr('%1 nodes, %2 channels').arg(Network.gossipInfo.db_nodes).arg(Network.gossipInfo.db_channels)
|
|
}
|
|
}
|
|
Label {
|
|
text: qsTr('enabled');
|
|
visible: !Config.useGossip
|
|
}
|
|
|
|
Label {
|
|
visible: Daemon.currentWallet.isLightning
|
|
text: qsTr('Channel peers:');
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
visible: Daemon.currentWallet.isLightning
|
|
text: Daemon.currentWallet.lightningNumPeers
|
|
}
|
|
|
|
Heading {
|
|
Layout.columnSpan: 2
|
|
text: qsTr('Proxy')
|
|
}
|
|
|
|
Label {
|
|
text: qsTr('Proxy') + ':'
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
text: Network.proxy.enabled ? qsTr('enabled') : qsTr('disabled')
|
|
}
|
|
|
|
Label {
|
|
visible: Network.proxy.enabled
|
|
text: qsTr('Proxy server:');
|
|
color: Material.accentColor
|
|
}
|
|
Label {
|
|
visible: Network.proxy.enabled
|
|
text: Network.proxy.host ? Network.proxy.host + ':' + Network.proxy.port : ''
|
|
}
|
|
|
|
Label {
|
|
visible: Network.proxy.enabled
|
|
text: qsTr('Proxy type:');
|
|
color: Material.accentColor
|
|
}
|
|
RowLayout {
|
|
Image {
|
|
visible: Network.isProxyTor
|
|
Layout.preferredWidth: constants.iconSizeMedium
|
|
Layout.preferredHeight: constants.iconSizeMedium
|
|
source: '../../icons/tor_logo.png'
|
|
}
|
|
Label {
|
|
visible: Network.proxy.enabled
|
|
text: Network.isProxyTor ? 'TOR' : (Network.proxy.mode || '')
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ButtonContainer {
|
|
Layout.fillWidth: true
|
|
|
|
FlatButton {
|
|
Layout.fillWidth: true
|
|
Layout.preferredWidth: 1
|
|
text: qsTr('Server Settings');
|
|
icon.source: '../../icons/network.png'
|
|
onClicked: {
|
|
var dialog = serverConfig.createObject(root)
|
|
dialog.open()
|
|
}
|
|
}
|
|
|
|
FlatButton {
|
|
Layout.fillWidth: true
|
|
Layout.preferredWidth: 1
|
|
text: qsTr('Proxy Settings');
|
|
icon.source: '../../icons/status_connected_proxy.png'
|
|
onClicked: {
|
|
var dialog = proxyConfig.createObject(root)
|
|
dialog.open()
|
|
}
|
|
}
|
|
FlatButton {
|
|
Layout.fillWidth: true
|
|
Layout.preferredWidth: 1
|
|
text: qsTr('Nostr Settings');
|
|
icon.source: '../../icons/nostr.png'
|
|
onClicked: {
|
|
var dialog = nostrConfig.createObject(root)
|
|
dialog.open()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: serverConfig
|
|
ServerConfigDialog {
|
|
onClosed: destroy()
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: proxyConfig
|
|
ProxyConfigDialog {
|
|
onClosed: destroy()
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: nostrConfig
|
|
NostrConfigDialog {
|
|
onClosed: destroy()
|
|
}
|
|
}
|
|
}
|