wry, many thing
This commit is contained in:
parent
6e62eccfba
commit
848ed62c5d
47 changed files with 1598 additions and 1201 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ Singleton {
|
|||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
width: parent.width / 3 * 2
|
||||
height: parent.height / 6 * 5
|
||||
Repeater {
|
||||
model: topLevel.buttons.length
|
||||
Button {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
142
graphical/desktop/quickshell/noti/NotiCard.qml
Normal file
142
graphical/desktop/quickshell/noti/NotiCard.qml
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
163
graphical/desktop/quickshell/osd/Osd.qml
Normal file
163
graphical/desktop/quickshell/osd/Osd.qml
Normal 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 } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
||||
}
|
||||
}
|
||||
1
graphical/desktop/quickshell/rice/Colours.qml
Symbolic link
1
graphical/desktop/quickshell/rice/Colours.qml
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/nix/store/bc2v8k5620k5p57ggrxy6i5w6pay9kis-Colours.qml
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue