Launches seafile-applet from startup.lua and adds it to PinnedTray between Bitwarden and Sunshine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
111 lines
3.7 KiB
QML
111 lines
3.7 KiB
QML
import QtQuick
|
|
import QtQuick.Layouts
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import Quickshell.Services.SystemTray
|
|
import Quickshell.Widgets
|
|
import "../../config"
|
|
|
|
|
|
RowLayout {
|
|
id: root
|
|
spacing: Appearance.spacing * 1.
|
|
|
|
|
|
readonly property var pinned: [
|
|
{
|
|
name: "Bitwarden",
|
|
icon: Qt.resolvedUrl("../../assets/bitwarden.png"),
|
|
binary: "bitwarden",
|
|
launch: ["bitwarden"],
|
|
secondary: ["pkill", "bitwarden"]
|
|
},
|
|
{
|
|
name: "Seafile",
|
|
icon: "seafile",
|
|
binary: "seafile-applet",
|
|
launch: ["seafile-applet"],
|
|
secondary: ["pkill", "seafile-applet"]
|
|
},
|
|
{
|
|
name: "Sunshine",
|
|
icon: Qt.resolvedUrl("../../assets/sunshine.svg"),
|
|
binary: "sunshine",
|
|
launch: ["systemctl", "--user", "start", "app-dev.lizardbyte.app.Sunshine.service"],
|
|
secondary: ["xdg-open", "https://xol.twhomelab.local:47990"],
|
|
},
|
|
]
|
|
|
|
function findTrayItem(name) {
|
|
const needle = name.toLowerCase()
|
|
for (const item of SystemTray.items.values) {
|
|
if (item.id.toLowerCase().includes(needle) || item.title.toLowerCase().includes(needle))
|
|
return item
|
|
}
|
|
return null
|
|
}
|
|
|
|
Repeater {
|
|
model: root.pinned
|
|
|
|
delegate: Item {
|
|
id: slot
|
|
required property var modelData
|
|
readonly property var trayItem: root.findTrayItem(modelData.name)
|
|
readonly property bool running: trayItem !== null
|
|
property bool installed: false // Application installation check
|
|
|
|
visible: slot.installed
|
|
implicitWidth: Appearance.iconSize
|
|
implicitHeight: Appearance.iconSize
|
|
|
|
Process {
|
|
running: true
|
|
command: ["which", slot.modelData.binary]
|
|
onExited: (exitCode) => slot.installed = exitCode === 0
|
|
}
|
|
|
|
IconImage {
|
|
anchors.fill: parent
|
|
// modelData.icon is a QUrl when it comes from
|
|
// Qt.resolvedUrl() (Bitwarden/Sunshine's local assets), not
|
|
// a QString — coerce to string before using String methods
|
|
// on it, or this throws instead of ever matching.
|
|
source: slot.running
|
|
? slot.trayItem.icon
|
|
: (String(slot.modelData.icon).includes("://")
|
|
? slot.modelData.icon
|
|
: Quickshell.iconPath(slot.modelData.icon))
|
|
opacity: slot.running ? 1.0 : 0.5
|
|
}
|
|
|
|
Process { id: launcher }
|
|
Process { id: secondaryProc }
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
anchors.margins: -4
|
|
cursorShape: Qt.PointingHandCursor
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
onClicked: (mouse) => {
|
|
if (mouse.button === Qt.RightButton) {
|
|
if (slot.modelData.secondary) {
|
|
if (!secondaryProc.running) {
|
|
secondaryProc.command = slot.modelData.secondary
|
|
secondaryProc.running = true
|
|
}
|
|
} else if (slot.running) {
|
|
slot.trayItem.secondaryActivate()
|
|
}
|
|
} else if (slot.running) {
|
|
slot.trayItem.activate()
|
|
} else if (!launcher.running) {
|
|
launcher.command = slot.modelData.launch
|
|
launcher.running = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|