Keeps the Takemi geometry — the lean, the chamfer, the slabs — and swaps the palette wholesale. Mocha carries the ground; blue is the accent for anything live (focus, selection, borders, hover) and pink is the alarm for anything destructive or failed, so one hue no longer has to mean both 'active' and 'wrong'. Destructive controls rest as a pink keyline and fill solid only when hovered or selected: Mocha's pink is a pastel, and a resting slab of it reads as washed-out red rather than as a warning. The load ramp climbs text -> blue -> pink for the same reason, instead of fading straight through a muddy mid-tone. Surfaces covered: quickshell, Hyprland borders, alacritty, fish, dunst, and nvim (via the catppuccin plugin, submodule branch catppuccin-mocha). GTK 3/4, Qt and xsettingsd move to catppuccin-mocha-blue and are now tracked, since nothing else makes non-shell apps match the rice; the previous Takemi copies are in theme-repair-backups/. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
102 lines
3.7 KiB
QML
102 lines
3.7 KiB
QML
pragma Singleton
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Services.UPower
|
|
import "root:/config"
|
|
import "root:/services"
|
|
|
|
// Battery and power-profile state. UPower gives live percentage and time
|
|
// estimates; Sys.powerDetail adds the TLP/AC line fluxo reports.
|
|
Singleton {
|
|
id: root
|
|
|
|
readonly property UPowerDevice device: UPower.displayDevice
|
|
readonly property bool available: device !== null && device.isLaptopBattery && device.isPresent
|
|
readonly property bool onBattery: UPower.onBattery
|
|
|
|
readonly property real percent: device?.percentage !== undefined ? device.percentage * 100 : 0
|
|
readonly property int state: device?.state ?? UPowerDeviceState.Unknown
|
|
|
|
readonly property bool charging: state === UPowerDeviceState.Charging
|
|
|| state === UPowerDeviceState.PendingCharge
|
|
readonly property bool full: state === UPowerDeviceState.FullyCharged
|
|
|
|
readonly property real changeRate: device?.changeRate ?? 0 // watts
|
|
readonly property real health: device?.healthSupported ? (device?.healthPercentage ?? 0) : 0
|
|
|
|
readonly property bool low: available && !charging && percent <= 20
|
|
readonly property bool critical: available && !charging && percent <= 10
|
|
|
|
readonly property real secondsLeft: charging
|
|
? (device?.timeToFull ?? 0)
|
|
: (device?.timeToEmpty ?? 0)
|
|
|
|
readonly property string timeLabel: {
|
|
if (root.full) return "Full";
|
|
if (!(root.secondsLeft > 0)) return charging ? "Charging" : "Estimating…";
|
|
const mins = Math.round(root.secondsLeft / 60);
|
|
const h = Math.floor(mins / 60);
|
|
const m = mins % 60;
|
|
const dur = h > 0 ? h + "h " + m + "m" : m + "m";
|
|
return root.charging ? dur + " to full" : dur + " left";
|
|
}
|
|
|
|
readonly property string detail: Sys.powerDetail
|
|
|
|
// Ten-step battery glyph ramp, plus the charging variants.
|
|
readonly property string icon: {
|
|
if (!root.available) return "";
|
|
const p = Math.max(0, Math.min(100, root.percent));
|
|
const step = Math.min(10, Math.floor(p / 10));
|
|
if (root.charging) {
|
|
const charge = ["", "", "", "", "", "", "", "", "", "", ""];
|
|
return charge[step];
|
|
}
|
|
const drain = ["", "", "", "", "", "", "", "", "", "", ""];
|
|
return drain[step];
|
|
}
|
|
|
|
readonly property color tint: {
|
|
if (root.charging || root.full) return Theme.ok;
|
|
if (root.critical) return Theme.alarm;
|
|
if (root.low) return Theme.warn;
|
|
return Theme.primary;
|
|
}
|
|
|
|
// ------------------------------------------------------- power profiles
|
|
readonly property bool hasPerformance: PowerProfiles.hasPerformanceProfile
|
|
readonly property int profile: PowerProfiles.profile
|
|
|
|
readonly property string profileLabel: {
|
|
switch (root.profile) {
|
|
case PowerProfile.PowerSaver: return "Power Saver";
|
|
case PowerProfile.Performance: return "Performance";
|
|
default: return "Balanced";
|
|
}
|
|
}
|
|
|
|
readonly property string profileIcon: {
|
|
switch (root.profile) {
|
|
case PowerProfile.PowerSaver: return "";
|
|
case PowerProfile.Performance: return "";
|
|
default: return "";
|
|
}
|
|
}
|
|
|
|
function setProfile(p: int) {
|
|
PowerProfiles.profile = p;
|
|
}
|
|
|
|
function cycleProfile() {
|
|
if (root.profile === PowerProfile.PowerSaver) {
|
|
root.setProfile(PowerProfile.Balanced);
|
|
} else if (root.profile === PowerProfile.Balanced
|
|
&& PowerProfiles.hasPerformanceProfile) {
|
|
root.setProfile(PowerProfile.Performance);
|
|
} else {
|
|
root.setProfile(PowerProfile.PowerSaver);
|
|
}
|
|
}
|
|
}
|