wry, many thing

This commit is contained in:
atagen 2026-04-08 11:43:10 +10:00
parent 6e62eccfba
commit 848ed62c5d
47 changed files with 1598 additions and 1201 deletions

View file

@ -182,6 +182,11 @@ Singleton {
id: clickableEntry
required property DesktopEntry modelData
onClicked: {
// console.log(modelData.command);
// Quickshell.execDetached({
// command: ["systemd-run", "--slice-inherit", "--user", "-t", "-G"].concat(modelData.command),
// workingDirectory: modelData.workingDirectory
// });
modelData.execute();
launcherData.open = false;
}

View file

@ -136,7 +136,6 @@ Singleton {
verticalCenter: parent.verticalCenter
}
width: parent.width / 3 * 2
height: parent.height / 6 * 5
Repeater {
model: topLevel.buttons.length
Button {

View file

@ -1,18 +1,56 @@
pragma Singleton
import Quickshell
import Quickshell.Wayland
import Quickshell.Services.Notifications
import QtQuick
Singleton {
id: root
NotificationServer {
id: notifications
id: server
actionsSupported: true
bodyHyperlinksSupported: true
// bodyImagesSupported: true
bodyMarkupSupported: true
imageSupported: true
imageSupported: true
onNotification: noti => {
noti.tracked = true
}
}
LazyLoader {
active: server.trackedNotifications.values.length > 0
WlrLayershell {
anchors {
top: true
right: true
}
implicitWidth: 344
implicitHeight: notiColumn.implicitHeight + 24
color: "transparent"
layer: WlrLayer.Overlay
namespace: "shell:noti"
exclusionMode: ExclusionMode.Ignore
Column {
id: notiColumn
anchors {
top: parent.top
right: parent.right
topMargin: 12
rightMargin: 12
}
spacing: 8
width: 320
Repeater {
model: server.trackedNotifications
NotiCard {
required property var modelData
notification: modelData
}
}
}
}
}
}

View file

@ -0,0 +1,142 @@
import QtQuick
import QtQuick.Controls
import Quickshell.Services.Notifications
Item {
id: root
required property var notification
width: 320
implicitHeight: card.implicitHeight * heightScale
property string borderColor: {
switch (notification.urgency) {
case NotificationUrgency.Critical: return "#C46056"
case NotificationUrgency.Low: return "#8CC4C9"
default: return "#FFAB5B"
}
}
// --- slide-in/out ---
property real slideProgress: 0.0
opacity: slideProgress
transform: Translate { x: (1.0 - root.slideProgress) * 32 }
Behavior on slideProgress {
NumberAnimation { duration: 300; easing.type: Easing.InOutExpo }
}
// --- height collapse (after slide-out, before model removal) ---
property real heightScale: 1.0
Behavior on heightScale {
NumberAnimation { duration: 200; easing.type: Easing.InOutExpo }
}
property bool dismissing: false
function beginDismiss() {
if (root.dismissing) return
root.dismissing = true
root.slideProgress = 0.0
collapseTimer.start()
}
// wait for slide-out, then collapse height
Timer {
id: collapseTimer
interval: 310
onTriggered: {
root.heightScale = 0.0
removeTimer.start()
}
}
// wait for height collapse, then remove from model
Timer {
id: removeTimer
interval: 210
onTriggered: root.notification.dismiss()
}
Component.onCompleted: root.slideProgress = 1.0
// auto-dismiss
Timer {
id: dismissTimer
interval: notification.expireTimeout > 0 ? notification.expireTimeout : 5000
running: !(notification.urgency === NotificationUrgency.Critical && notification.expireTimeout <= 0)
repeat: false
onTriggered: root.beginDismiss()
}
Rectangle {
id: card
width: parent.width
implicitHeight: content.implicitHeight + 32
color: "#1B2021"
border.color: root.borderColor
border.width: 2
// sharp on the screen-edge diagonal (top-right), rounded on the inner diagonal
topRightRadius: 0
bottomLeftRadius: 0
topLeftRadius: 10
bottomRightRadius: 10
MouseArea {
anchors.fill: parent
onClicked: root.beginDismiss()
}
Column {
id: content
anchors {
fill: parent
margins: 16
}
spacing: 6
Text {
text: notification.summary
color: "#CECBCA"
font { family: "MS W98 UI"; pointSize: 12; bold: true }
width: parent.width
elide: Text.ElideRight
}
Text {
text: notification.body
visible: notification.body !== ""
color: "#CECBCA"
font { family: "MS W98 UI"; pointSize: 12 }
width: parent.width
wrapMode: Text.WordWrap
}
Row {
spacing: 6
visible: notification.actions.length > 0
topPadding: 4
Repeater {
model: notification.actions
Button {
required property var modelData
text: modelData.text
font { family: "MS W98 UI"; pointSize: 11 }
palette.buttonText: "#FFAB5B"
background: Rectangle {
color: parent.hovered ? "#FFAB5B" : "#272A2A"
border.color: "#FFAB5B"
border.width: 2
radius: 6
Behavior on color { ColorAnimation { duration: 150 } }
}
onClicked: modelData.invoke()
}
}
}
}
}
}

View file

@ -0,0 +1,163 @@
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import QtQuick
Singleton {
id: root
property real value: 0.0
property string mode: "volume"
property bool muted: false
property bool shown: false
property real showProgress: root.shown ? 1.0 : 0.0
Behavior on showProgress {
NumberAnimation { duration: 200; easing.type: Easing.InOutExpo }
}
function show(newMode, newValue, newMuted) {
mode = newMode
value = Math.max(0.0, Math.min(1.0, newValue))
muted = newMuted
shown = true
hideTimer.restart()
}
function parseVolume(line) {
let parts = line.trim().split(/\s+/)
let vol = parseFloat(parts[1])
if (isNaN(vol)) return
root.show("volume", vol, line.includes("[MUTED]"))
}
function parseBrightness(line) {
let parts = line.trim().split(/\s+/)
let cur = parseInt(parts[0])
let max = parseInt(parts[1])
if (isNaN(cur) || isNaN(max) || max === 0) return
root.show("brightness", cur / max, false)
}
Timer {
id: hideTimer
interval: 1500
repeat: false
onTriggered: root.shown = false
}
IpcHandler {
target: "osd"
function volumeUp(): void { volumeUpCmd.running = true }
function volumeDown(): void { volumeDownCmd.running = true }
function toggleMute(): void { toggleMuteCmd.running = true }
function brightnessUp(): void { brightnessUpCmd.running = true }
function brightnessDown(): void { brightnessDownCmd.running = true }
}
Process {
id: volumeUpCmd
command: ["sh", "-c", "wpctl set-volume -l 1.0 @DEFAULT_SINK@ 5%+ && wpctl get-volume @DEFAULT_SINK@"]
stdout: SplitParser { onRead: line => root.parseVolume(line) }
}
Process {
id: volumeDownCmd
command: ["sh", "-c", "wpctl set-volume @DEFAULT_SINK@ 5%- && wpctl get-volume @DEFAULT_SINK@"]
stdout: SplitParser { onRead: line => root.parseVolume(line) }
}
Process {
id: toggleMuteCmd
command: ["sh", "-c", "wpctl set-mute @DEFAULT_SINK@ toggle && wpctl get-volume @DEFAULT_SINK@"]
stdout: SplitParser { onRead: line => root.parseVolume(line) }
}
Process {
id: brightnessUpCmd
command: ["sh", "-c", "brightnessctl s 5%+ > /dev/null; printf '%s %s' \"$(brightnessctl g)\" \"$(brightnessctl m)\""]
stdout: SplitParser { onRead: line => root.parseBrightness(line) }
}
Process {
id: brightnessDownCmd
command: ["sh", "-c", "brightnessctl s 5%- > /dev/null; printf '%s %s' \"$(brightnessctl g)\" \"$(brightnessctl m)\""]
stdout: SplitParser { onRead: line => root.parseBrightness(line) }
}
WlrLayershell {
anchors { bottom: true; left: true; right: true }
implicitHeight: 90
color: "transparent"
visible: root.showProgress > 0
layer: WlrLayer.Overlay
namespace: "shell:osd"
exclusionMode: ExclusionMode.Ignore
Item {
id: osdItem
anchors.centerIn: parent
width: 260
height: osdCard.implicitHeight
opacity: root.showProgress
transform: Translate { y: (1.0 - root.showProgress) * 10 }
Rectangle {
id: osdCard
width: parent.width
implicitHeight: osdContent.implicitHeight + 24
color: "#1B2021"
border.color: root.muted ? "#C46056" : "#FFAB5B"
border.width: 2
topLeftRadius: 0
bottomRightRadius: 0
topRightRadius: 10
bottomLeftRadius: 10
Behavior on border.color {
ColorAnimation { duration: 150 }
}
Column {
id: osdContent
anchors { fill: parent; margins: 12 }
spacing: 8
Item {
width: parent.width
height: modeLabel.height
Text {
id: modeLabel
anchors.left: parent.left
text: root.muted ? "Muted" : (root.mode === "brightness" ? "Brightness" : "Volume")
color: "#CECBCA"
font { family: "MS W98 UI"; pointSize: 12 }
}
Text {
anchors.right: parent.right
text: Math.round(root.value * 100) + "%"
color: root.muted ? "#C46056" : "#FFAB5B"
font { family: "MS W98 UI"; pointSize: 12 }
Behavior on color { ColorAnimation { duration: 150 } }
}
}
Rectangle {
width: parent.width
height: 6
color: "#272A2A"
radius: 3
Rectangle {
width: parent.width * root.value
height: parent.height
color: root.muted ? "#C46056" : "#FFAB5B"
radius: 3
Behavior on width { NumberAnimation { duration: 80; easing.type: Easing.OutCubic } }
Behavior on color { ColorAnimation { duration: 150 } }
}
}
}
}
}
}
}

View file

@ -1,34 +0,0 @@
pragma Singleton
import Quickshell
Singleton {
property var c: {
"bg": "#1b2021",
"fg": "#cecbca",
"black": "#272a2a",
"black_b": "#202e2f",
"red": "#c43325",
"red_b": "#c46056",
"green": "#8cc992",
"green_b": "#c2dab0",
"yellow": "#ffb852",
"yellow_b": "#ffab5b",
"blue": "#5299ff",
"blue_b": "#92beff",
"magenta": "#645ac9",
"magenta_b": "#928cc9",
"cyan": "#5abfc9",
"cyan_b": "#8cc4c9",
"white": "#b0c2da",
"white_b": "#caccce",
}
}

View file

@ -0,0 +1 @@
/nix/store/bc2v8k5620k5p57ggrxy6i5w6pay9kis-Colours.qml

View file

@ -4,8 +4,10 @@ import "launcher" as Launcher
import "logout" as Logout
// singletons
import "title"
import "tags"
import "tags"
import "rice"
import "noti" as Noti
import "osd" as Osd
import Quickshell
import Quickshell.Wayland
@ -244,6 +246,9 @@ ShellRoot {
// }//invisible rect
// }
Noti.Noti {}
Osd.Osd {}
// pops up on current monitor
Launcher.Launcher {
width: 190
@ -273,4 +278,5 @@ ShellRoot {
command: "systemctl reboot"
}
}
}