nova-shell/shell/dock/AppletDock.qml

472 lines
14 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Services.Mpris
import "." as D
import "../services" as S
import "../applets" as C
import "../modules" as M
import NovaStats as NS
PanelWindow {
id: root
visible: _winVisible
color: "transparent"
property bool _winVisible: false
WlrLayershell.layer: S.DockState.mode === "pinned" ? WlrLayer.Bottom : WlrLayer.Overlay
WlrLayershell.exclusiveZone: S.DockState.mode === "pinned" ? _dockWidth : 0
WlrLayershell.namespace: "nova-dock"
anchors.top: true
anchors.right: true
anchors.bottom: true
// Counteract the bar's exclusive zone so the dock extends to the top of the screen
margins.top: -NS.ThemeService.barHeight
readonly property int _dockWidth: NS.ModulesService.dockWidth ?? 300
readonly property color _accent: NS.ThemeService.base0C
implicitWidth: _dockWidth
// Set reserved width for bar/corners when pinned
onVisibleChanged: {
if (S.DockState.mode === "pinned")
S.DockState.reservedWidth = _dockWidth;
}
Connections {
target: S.DockState
function onModeChanged() {
if (S.DockState.mode === "pinned")
S.DockState.reservedWidth = root._dockWidth;
}
}
// Slide animation - managed manually so window stays visible during hide
property real _slideX: _dockWidth
Connections {
target: S.DockState
function onOpenChanged() {
if (S.DockState.open) {
root._winVisible = true;
_hideAnim.stop();
if (S.ThemeUtil.reducedMotion) {
root._slideX = 0;
} else {
_showAnim.start();
}
} else {
_showAnim.stop();
if (S.ThemeUtil.reducedMotion) {
root._slideX = root._dockWidth;
root._winVisible = false;
} else {
_hideAnim.start();
}
}
}
}
NumberAnimation {
id: _showAnim
target: root
property: "_slideX"
to: 0
duration: 200
easing.type: Easing.OutCubic
}
NumberAnimation {
id: _hideAnim
target: root
property: "_slideX"
to: root._dockWidth
duration: 200
easing.type: Easing.OutCubic
onFinished: root._winVisible = false
}
// Overlay mode: close when cursor leaves
HoverHandler {
id: _dockHover
onHoveredChanged: {
if (!hovered && S.DockState.mode === "overlay")
_overlayCloseTimer.restart();
else
_overlayCloseTimer.stop();
}
}
Timer {
id: _overlayCloseTimer
interval: 200
onTriggered: if (S.DockState.mode === "overlay")
S.DockState.close()
}
// Background - fully opaque when pinned, semi-transparent in overlay
Rectangle {
id: _bg
anchors.fill: parent
color: NS.ThemeService.base00
opacity: S.DockState.mode === "pinned" ? 1.0 : Math.max(NS.ThemeService.barOpacity, 0.85)
transform: Translate {
x: root._slideX
}
}
// Left edge line - marks the virtual screen edge, matches bar border width.
// Uses base09 (rightmost bar gradient color).
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 1
color: NS.ThemeService.base09
opacity: _bg.opacity
transform: Translate {
x: root._slideX
}
}
// Dock bar - mirrors main bar style, hosts dock toggle when pinned
Item {
id: _dockBar
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: NS.ThemeService.barHeight
visible: S.DockState.mode === "pinned"
transform: Translate {
x: root._slideX
}
Rectangle {
anchors.fill: parent
color: NS.ThemeService.base00
}
// Bottom border - gradient matching bar style (base0C to base09, but just the right end)
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
color: NS.ThemeService.base09
}
// Dock toggle
M.BarGroup {
anchors.centerIn: parent
M.BarModule {
tooltip: "Unpin dock"
onTapped: S.DockState.toggle()
M.BarIcon {
icon: "\uDB80\uDD8B"
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
// Content - inset past the edge line + gap
Flickable {
id: _flickable
anchors.top: _dockBar.visible ? _dockBar.bottom : parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.leftMargin: NS.ThemeService.groupSpacing + 1
contentHeight: _column.height
clip: true
boundsBehavior: Flickable.StopAtBounds
transform: Translate {
x: root._slideX
}
Column {
id: _column
width: root._dockWidth
spacing: 8
topPadding: 8
bottomPadding: 8
leftPadding: 8
rightPadding: 8
// Clock
D.DockCard {
visible: NS.ModulesService.dockAppletClock
icon: "\uF017"
title: "Clock"
accentColor: root._accent
width: parent.width - 16
C.ClockApplet {
width: parent.width
accentColor: root._accent
currentDate: _clock.date
}
}
// CPU
D.DockCard {
id: _cpuCard
visible: NS.ModulesService.dockAppletCpu
icon: "\uF2DB"
title: "CPU"
accentColor: root._accent
width: parent.width - 16
C.CpuApplet {
width: parent.width
processes: _cpuProcs.processes
accentColor: root._accent
active: _cpuCard.expanded
}
}
// GPU
D.DockCard {
visible: (NS.ModulesService.dockAppletGpu) && S.SystemStats.gpuAvailable
icon: "\uEB4C"
title: "GPU"
accentColor: root._accent
width: parent.width - 16
C.GpuApplet {
width: parent.width
active: parent.expanded
accentColor: root._accent
}
}
// Memory
D.DockCard {
id: _memCard
visible: NS.ModulesService.dockAppletMemory
icon: "\uEFC5"
title: "Memory"
accentColor: root._accent
width: parent.width - 16
C.MemoryApplet {
width: parent.width
percent: S.SystemStats.memPercent
usedGb: S.SystemStats.memUsedGb
totalGb: S.SystemStats.memTotalGb
availGb: S.SystemStats.memAvailGb
cachedGb: S.SystemStats.memCachedGb
buffersGb: S.SystemStats.memBuffersGb
processes: _memProcs.processes
accentColor: root._accent
active: _memCard.expanded
}
}
// Temperature
D.DockCard {
visible: NS.ModulesService.dockAppletTemperature
icon: "\uF2C9"
title: "Temperature"
accentColor: root._accent
width: parent.width - 16
C.TemperatureApplet {
width: parent.width
temp: S.SystemStats.tempCelsius
warm: NS.ModulesService.temperatureWarm || 80
hot: NS.ModulesService.temperatureHot || 90
history: S.SystemStats.tempHistory
devices: S.SystemStats.tempDevices
accentColor: root._accent
deviceFilter: NS.ModulesService.temperatureDevice || ""
active: parent.expanded
}
}
// Disk
D.DockCard {
visible: NS.ModulesService.dockAppletDisk
icon: "\uF0C9"
title: "Disk"
accentColor: root._accent
width: parent.width - 16
C.DiskApplet {
width: parent.width
mounts: S.SystemStats.diskMounts
accentColor: root._accent
}
}
// Battery
D.DockCard {
visible: (NS.ModulesService.dockAppletBattery) && S.BatteryService.available
icon: "\uDB80\uDC84"
title: "Battery"
accentColor: root._accent
width: parent.width - 16
C.BatteryApplet {
width: parent.width
active: parent.expanded
accentColor: root._accent
}
}
// Network
D.DockCard {
visible: NS.ModulesService.dockAppletNetwork
icon: "\uF1EB"
title: "Network"
accentColor: root._accent
width: parent.width - 16
C.NetworkApplet {
width: parent.width
accentColor: root._accent
active: parent.expanded
}
}
// Bluetooth
D.DockCard {
visible: (NS.ModulesService.dockAppletBluetooth) && S.BluetoothService.state !== "unavailable"
icon: "\uF294"
title: "Bluetooth"
accentColor: root._accent
width: parent.width - 16
C.BluetoothApplet {
width: parent.width
accentColor: root._accent
active: parent.expanded
}
}
// Volume
D.DockCard {
visible: NS.ModulesService.dockAppletVolume
icon: "\uF028"
title: "Sound"
accentColor: root._accent
width: parent.width - 16
C.VolumeApplet {
width: parent.width
accentColor: root._accent
}
}
// Backlight
D.DockCard {
visible: (NS.ModulesService.dockAppletBacklight) && S.BacklightService.available
icon: "\uF185"
title: "Brightness"
accentColor: root._accent
width: parent.width - 16
C.BacklightApplet {
width: parent.width
percent: S.BacklightService.percent
accentColor: root._accent
onSetPercent: pct => S.BacklightService.setPercent(pct)
}
}
// Weather
D.DockCard {
visible: (NS.ModulesService.dockAppletWeather) && S.WeatherService.available
icon: S.WeatherService.icon
title: "Weather"
accentColor: root._accent
width: parent.width - 16
C.WeatherApplet {
width: parent.width
accentColor: root._accent
}
}
// Now Playing
D.DockCard {
visible: (NS.ModulesService.dockAppletMpris) && S.MprisService.player !== null
icon: "\uF04B"
title: "Now Playing"
accentColor: root._accent
width: parent.width - 16
C.MprisApplet {
width: parent.width
accentColor: root._accent
}
}
// Notifications
D.DockCard {
visible: NS.ModulesService.dockAppletNotifications
icon: "\uDB80\uDC9C"
title: "Notifications"
accentColor: root._accent
width: parent.width - 16
C.NotifApplet {
width: parent.width
contentWidth: root._dockWidth - 16
accentColor: root._accent
}
}
// Power
D.DockCard {
visible: NS.ModulesService.dockAppletPower
icon: "\uF011"
title: "Power"
accentColor: root._accent
width: parent.width - 16
C.PowerApplet {
width: parent.width
accentColor: root._accent
onRunCommand: cmd => {
_runner.command = cmd;
_runner.running = true;
}
onDismiss: S.DockState.close()
}
}
}
}
// Shared resources
SystemClock {
id: _clock
precision: SystemClock.Seconds
}
M.ProcessList {
id: _cpuProcs
sortBy: "cpu"
active: _cpuCard.expanded && S.DockState.open
}
M.ProcessList {
id: _memProcs
sortBy: "mem"
active: _memCard.expanded && S.DockState.open
}
Process {
id: _runner
}
}