feat: improve dash perf placeholder & battery tank

This commit is contained in:
2 * r + 2 * t 2026-04-26 14:06:37 +10:00
parent 8f472f4a05
commit 76b4a0b63c
3 changed files with 161 additions and 142 deletions

View file

@ -1,10 +1,8 @@
import "performance" import "performance"
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Services.UPower import Quickshell.Services.UPower
import Caelestia.Config import Caelestia.Config
import Caelestia.Internal
import Caelestia.Services import Caelestia.Services
import qs.components import qs.components
import qs.services import qs.services
@ -12,27 +10,17 @@ import qs.services
Item { Item {
id: root id: root
readonly property int minWidth: 400 + 400 + Tokens.spacing.medium + 120 + Tokens.padding.extraLargeIncreased implicitWidth: placeholder.active ? Tokens.sizes.dashboard.perfPlaceholderWidth : content.implicitWidth
implicitHeight: placeholder.active ? placeholder.implicitHeight + Tokens.padding.extraLarge * 2 : content.implicitHeight
function displayTemp(temp: real): string { Loader {
return `${Math.ceil(GlobalConfig.services.useFahrenheitPerformance ? temp * 1.8 + 32 : temp)}°${GlobalConfig.services.useFahrenheitPerformance ? "F" : "C"}`;
}
implicitWidth: Math.max(minWidth, content.implicitWidth)
implicitHeight: placeholder.visible ? placeholder.height : content.implicitHeight
StyledRect {
id: placeholder id: placeholder
anchors.centerIn: parent anchors.centerIn: parent
width: 400 active: !Config.dashboard.performance.showCpu && !(Config.dashboard.performance.showGpu && Gpu.type !== Gpu.None) && !Config.dashboard.performance.showMemory && !Config.dashboard.performance.showStorage && !Config.dashboard.performance.showNetwork && !(UPower.displayDevice.isLaptopBattery && Config.dashboard.performance.showBattery)
height: 350 asynchronous: true
radius: Tokens.rounding.extraLarge
color: Colours.tPalette.m3surfaceContainer
visible: !Config.dashboard.performance.showCpu && !(Config.dashboard.performance.showGpu && Gpu.type !== Gpu.None) && !Config.dashboard.performance.showMemory && !Config.dashboard.performance.showStorage && !Config.dashboard.performance.showNetwork && !(UPower.displayDevice.isLaptopBattery && Config.dashboard.performance.showBattery)
ColumnLayout { sourceComponent: ColumnLayout {
anchors.centerIn: parent
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
MaterialIcon { MaterialIcon {
@ -43,15 +31,16 @@ Item {
} }
StyledText { StyledText {
Layout.topMargin: -Tokens.spacing.small
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
text: qsTr("No widgets enabled") text: qsTr("No widgets enabled")
font: Tokens.font.body.large font: Tokens.font.title.large
color: Colours.palette.m3onSurface color: Colours.palette.m3onSurface
} }
StyledText { StyledText {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
text: qsTr("Enable widgets in dashboard settings") text: qsTr("Enable widgets in the dashboard settings")
font: Tokens.font.body.small font: Tokens.font.body.small
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
} }
@ -64,7 +53,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
visible: !placeholder.visible visible: !placeholder.active
ServiceRef { ServiceRef {
service: root.Config.dashboard.performance.showCpu ? Cpu : null service: root.Config.dashboard.performance.showCpu ? Cpu : null
@ -132,127 +121,8 @@ Item {
} }
BatteryTank { BatteryTank {
Layout.preferredWidth: 120 Layout.fillHeight: true
Layout.preferredHeight: mainColumn.implicitHeight
visible: UPower.displayDevice.isLaptopBattery && Config.dashboard.performance.showBattery visible: UPower.displayDevice.isLaptopBattery && Config.dashboard.performance.showBattery
} }
} }
component BatteryTank: StyledClippingRect {
id: batteryTank
property real percentage: UPower.displayDevice.percentage
property bool isCharging: UPower.displayDevice.state === UPowerDeviceState.Charging
property color accentColor: Colours.palette.m3primary
property real animatedPercentage: 0
color: Colours.tPalette.m3surfaceContainer
radius: Tokens.rounding.extraLarge
Component.onCompleted: animatedPercentage = percentage
onPercentageChanged: animatedPercentage = percentage
// Background Fill
StyledRect {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: parent.height * batteryTank.animatedPercentage
color: Qt.alpha(batteryTank.accentColor, 0.15)
}
ColumnLayout {
anchors.fill: parent
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.small
// Header Section
ColumnLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.small
MaterialIcon {
text: {
if (!UPower.displayDevice.isLaptopBattery) {
if (PowerProfiles.profile === PowerProfile.PowerSaver)
return "energy_savings_leaf";
if (PowerProfiles.profile === PowerProfile.Performance)
return "rocket_launch";
return "balance";
}
if (UPower.displayDevice.state === UPowerDeviceState.FullyCharged)
return "battery_full";
const perc = UPower.displayDevice.percentage;
const charging = [UPowerDeviceState.Charging, UPowerDeviceState.PendingCharge].includes(UPower.displayDevice.state);
if (perc >= 0.99)
return "battery_full";
let level = Math.floor(perc * 7);
if (charging && (level === 4 || level === 1))
level--;
return charging ? `battery_charging_${(level + 3) * 10}` : `battery_${level}_bar`;
}
fontStyle: Tokens.font.icon.large
color: batteryTank.accentColor
}
StyledText {
Layout.fillWidth: true
text: qsTr("Battery")
font: Tokens.font.body.medium
color: Colours.palette.m3onSurface
}
}
Item {
Layout.fillHeight: true
}
// Bottom Info Section
ColumnLayout {
Layout.fillWidth: true
spacing: -4
StyledText {
Layout.alignment: Qt.AlignRight
text: `${Math.round(batteryTank.percentage * 100)}%`
font: Tokens.font.body.builders.large.size(28).weight(Font.Medium).build()
color: batteryTank.accentColor
}
StyledText {
Layout.alignment: Qt.AlignRight
text: {
if (UPower.displayDevice.state === UPowerDeviceState.FullyCharged)
return qsTr("Full");
if (batteryTank.isCharging)
return qsTr("Charging");
const s = UPower.displayDevice.timeToEmpty;
if (s === 0)
return qsTr("...");
const hr = Math.floor(s / 3600);
const min = Math.floor((s % 3600) / 60);
if (hr > 0)
return `${hr}h ${min}m`;
return `${min}m`;
}
font: Tokens.font.body.small
color: Colours.palette.m3onSurfaceVariant
}
}
}
Behavior on animatedPercentage {
Anim {
type: Anim.StandardLarge
}
}
}
} }

View file

@ -0,0 +1,145 @@
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.UPower
import Caelestia.Config
import Caelestia.Services
import qs.components
import qs.services
StyledClippingRect {
id: root
color: Colours.palette.m3secondaryContainer
radius: Tokens.rounding.large
implicitWidth: Config.dashboard.performance.showCpu || (Config.dashboard.performance.showGpu && Gpu.type !== Gpu.None) || Config.dashboard.performance.showStorage || Config.dashboard.performance.showMemory ? Tokens.sizes.dashboard.perfBattWidth : Tokens.sizes.dashboard.perfBattWidthSingle
implicitHeight: Tokens.sizes.dashboard.perfBattHeight
Contents {
id: layout
anchors.fill: parent
anchors.margins: Tokens.padding.medium
accentColour: Colours.palette.m3primary
textColour: Colours.palette.m3onSurface
subTextColour: Colours.palette.m3onSurfaceVariant
}
StyledRect {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
implicitHeight: parent.height * UPower.displayDevice.percentage
color: Colours.palette.m3secondary
radius: Tokens.rounding.extraSmall
clip: true
Behavior on implicitHeight {
Anim {}
}
Contents {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: layout.anchors.margins
height: layout.height
accentColour: Colours.palette.m3primaryContainer
textColour: Colours.palette.m3onSecondary
subTextColour: Colours.palette.m3secondaryContainer
}
}
component Contents: ColumnLayout {
id: contents
required property color accentColour
required property color textColour
required property color subTextColour
readonly property bool charging: [UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged, UPowerDeviceState.PendingCharge].includes(UPower.displayDevice.state)
spacing: 0
MaterialIcon {
Layout.leftMargin: -Tokens.padding.extraSmall
text: "battery_full"
color: contents.accentColour
fontStyle: Tokens.font.icon.large
}
StyledText {
Layout.fillWidth: true
text: qsTr("Battery")
color: contents.textColour
font: Tokens.font.body.medium
}
Item {
Layout.fillHeight: true
}
StyledText {
Layout.alignment: Qt.AlignRight
text: {
if (UPower.displayDevice.state === UPowerDeviceState.FullyCharged)
return qsTr("Full");
if (contents.charging)
return qsTr("Charging");
const s = UPower.displayDevice.timeToEmpty;
if (s === 0)
return qsTr("...");
const hr = Math.floor(s / 3600);
const min = Math.floor((s % 3600) / 60);
if (hr > 0)
return `${hr}h ${min}m`;
return `${min}m`;
}
color: contents.subTextColour
font: Tokens.font.body.small
animate: true
}
RowLayout {
Layout.topMargin: -Tokens.padding.extraSmall
Layout.bottomMargin: -Tokens.padding.small
Layout.rightMargin: -Tokens.padding.extraSmall
Layout.alignment: Qt.AlignRight
spacing: Tokens.spacing.extraSmall
MaterialIcon {
text: "bolt"
color: contents.accentColour
fontStyle: Tokens.font.icon.large
fill: 1
scale: contents.charging ? 1 : 0
opacity: contents.charging ? 1 : 0
Behavior on scale {
Anim {
type: Anim.FastSpatial
}
}
Behavior on opacity {
Anim {
type: Anim.FastEffects
}
}
}
StyledText {
text: `${Math.round(UPower.displayDevice.percentage * 100)}%`
color: contents.accentColour
font: Tokens.font.headline.medium
}
}
}
}

View file

@ -192,8 +192,12 @@ class DashboardTokens : public ConfigObject {
CONFIG_PROPERTY(int, perfHeroCardWidth, 400) CONFIG_PROPERTY(int, perfHeroCardWidth, 400)
CONFIG_PROPERTY(int, perfUsageShapeSize, 100) CONFIG_PROPERTY(int, perfUsageShapeSize, 100)
CONFIG_PROPERTY(int, perfStorageTextWidth, 160) CONFIG_PROPERTY(int, perfStorageTextWidth, 160)
CONFIG_PROPERTY(int, perfNetworkCardWidth, 280) CONFIG_PROPERTY(int, perfNetworkCardWidth, 390)
CONFIG_PROPERTY(int, perfNetworkCardHeight, 220) CONFIG_PROPERTY(int, perfNetworkCardHeight, 220)
CONFIG_PROPERTY(int, perfBattWidth, 150)
CONFIG_PROPERTY(int, perfBattWidthSingle, 400)
CONFIG_PROPERTY(int, perfBattHeight, 160)
CONFIG_PROPERTY(int, perfPlaceholderWidth, 700)
public: public:
explicit DashboardTokens(QObject* parent = nullptr) explicit DashboardTokens(QObject* parent = nullptr)