arch/private_dot_config/DankMaterialShell/plugins/desktopCommand/Widget.qml
lew b18328bbad Add .config/DankMaterialShell/firefox.css
Add .config/DankMaterialShell/plugin_settings.json
Add .config/DankMaterialShell/plugins/dankDesktopWeather.meta
Add .config/DankMaterialShell/plugins/dankHooks.meta
Add .config/DankMaterialShell/plugins/desktopCommand/LICENSE
Add .config/DankMaterialShell/plugins/desktopCommand/README.md
Add .config/DankMaterialShell/plugins/desktopCommand/Settings.qml
Add .config/DankMaterialShell/plugins/desktopCommand/Widget.qml
Add .config/DankMaterialShell/plugins/desktopCommand/assets/screenshot.jpg
Add .config/DankMaterialShell/plugins/desktopCommand/.git/HEAD
Add .config/DankMaterialShell/plugins/desktopCommand/.git/config
Add .config/DankMaterialShell/plugins/desktopCommand/.git/index
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/pack/pack-c2ca48eacecc3ab45931476641d058a89d755775.idx
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/pack/pack-c2ca48eacecc3ab45931476641d058a89d755775.rev
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/pack/pack-c2ca48eacecc3ab45931476641d058a89d755775.pack
Add .config/DankMaterialShell/plugins/desktopCommand/.git/refs/heads/main
Add .config/DankMaterialShell/plugins/desktopCommand/.git/refs/remotes/origin/main
Add .config/DankMaterialShell/plugins/desktopCommand/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/desktopCommand/.gitignore
Add .config/DankMaterialShell/plugins/desktopCommand/wrapCommand
Add .config/DankMaterialShell/plugins/desktopCommand/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/DankActionsSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/DankActionsWidget.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/DankBatteryAlerts.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/DankBatteryAlertsSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankDesktopWeather/DankDesktopWeather.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankDesktopWeather/DankDesktopWeatherSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankDesktopWeather/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/DankHooks.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/DankHooksSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/README.md
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/DankPomodoroSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/DankPomodoroWidget.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/LICENSE
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/README.md
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/HEAD
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/config
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/index
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.idx
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.rev
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-9aca069a8b76b40fcc472eba1ed9b8219a87776b.idx
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-9aca069a8b76b40fcc472eba1ed9b8219a87776b.rev
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-e6f6cdfe9914bfb4a5717ef6036821794d59ab4b.idx
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-e6f6cdfe9914bfb4a5717ef6036821794d59ab4b.rev
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.pack
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-9aca069a8b76b40fcc472eba1ed9b8219a87776b.pack
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-e6f6cdfe9914bfb4a5717ef6036821794d59ab4b.pack
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/heads/master
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/remotes/origin/master
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.gitignore
Add .config/DankMaterialShell/plugins/emojiLauncher/EmojiLauncher.qml
Add .config/DankMaterialShell/plugins/emojiLauncher/EmojiLauncherSettings.qml
Add .config/DankMaterialShell/plugins/emojiLauncher/LICENSE
Add .config/DankMaterialShell/plugins/emojiLauncher/README.md
Add .config/DankMaterialShell/plugins/emojiLauncher/catalog.js
Add .config/DankMaterialShell/plugins/emojiLauncher/data/emojis.txt
Add .config/DankMaterialShell/plugins/emojiLauncher/data/math.txt
Add .config/DankMaterialShell/plugins/emojiLauncher/data/nerdfont.txt
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/HEAD
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/config
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/index
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.idx
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.rev
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.pack
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/heads/main
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/remotes/origin/main
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/emojiLauncher/plugin.json
Add .config/DankMaterialShell/plugins/emojiLauncher/screenshot.png
Add .config/DankMaterialShell/plugins/emojiLauncher/scripts/generate_catalog.py
Add .config/DankMaterialShell/plugins/mediaPlayer/MediaPlayerSettings.qml
Add .config/DankMaterialShell/plugins/mediaPlayer/MediaPlayerTab.qml
Add .config/DankMaterialShell/plugins/mediaPlayer/README.md
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/HEAD
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/config
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/index
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/pack/pack-0b9cb33f7da23f6ff361ee3aa5117928714bc3be.idx
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/pack/pack-0b9cb33f7da23f6ff361ee3aa5117928714bc3be.rev
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/pack/pack-0b9cb33f7da23f6ff361ee3aa5117928714bc3be.pack
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/refs/heads/main
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/refs/remotes/origin/main
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/mediaPlayer/plugin.json
Add .config/DankMaterialShell/plugins/mediaPlayer/screenshot_8.png
Add .config/DankMaterialShell/plugins/dankDesktopWeather
Add .config/DankMaterialShell/plugins/dankHooks
Add .config/DankMaterialShell/settings.json
2026-01-07 15:09:11 +00:00

229 lines
7.1 KiB
QML

import QtQuick
import QtQml
import Quickshell
import Quickshell.Io
import qs.Common
import qs.Modules.Plugins
DesktopPluginComponent {
id: root
property string command: pluginData.command ?? ""
property real refreshInterval: normalizeRefreshInterval(pluginData.refreshInterval)
property bool autoRefresh: pluginData.autoRefresh ?? false
property real commandTimeout: normalizeCommandTimeout(pluginData.commandTimeout) // seconds
property bool hasRunInitial: false
property string output: ""
property int rows: 0
property int cols: 0
property var windowRef: null
property int fontSizePx: normalizeFontSize(pluginData.fontSize)
property bool useDank16: (pluginData.useDank16 ?? true) && Theme.dank16 !== null
property real backgroundOpacity: (pluginData.backgroundOpacity ?? 50) / 100
property string pluginUrl: ""
property string pluginDir: ""
property string wrapCommandPath: ""
property var dank16: Theme.isLightMode ? Theme.dank16.light : Theme.dank16.dark
FontMetrics {
id: fontMetrics
font.pixelSize: root.fontSizePx
font.family: Theme.monoFontFamily
}
Timer {
id: timer
interval: root.refreshInterval
repeat: true
running: false
onTriggered: runCommand()
}
// workaround for widget being spawned with weird size initially
Timer {
id: initialRunTimer
interval: 1000
repeat: false
running: false
onTriggered: root.handleVisibilityChange("timer")
}
Component.onCompleted: {
root.windowRef = Window.window ?? null
root.handleVisibilityChange("completed")
const url = Qt.resolvedUrl("Widget.qml") || (typeof __qmlfile__ !== "undefined" ? __qmlfile__ : "")
const cleanedUrl = String(url ?? "")
const cleanedPath = cleanedUrl.startsWith("file://") ? cleanedUrl.slice("file://".length) : cleanedUrl
const lastSlash = cleanedPath.lastIndexOf("/")
root.pluginUrl = cleanedUrl
root.pluginDir = lastSlash !== -1 ? cleanedPath.slice(0, lastSlash) : ""
const resolvedWrapUrl = Qt.resolvedUrl("wrapCommand")
const resolvedWrap = String(resolvedWrapUrl ?? "")
root.wrapCommandPath = resolvedWrap
? resolvedWrap.replace(/^file:\/\//, "")
: (root.pluginDir ? `${root.pluginDir}/wrapCommand` : "wrapCommand")
}
onVisibleChanged: {
root.handleVisibilityChange("root.visible")
}
onWidgetWidthChanged: root.handleVisibilityChange("sizeChanged")
onWidgetHeightChanged: root.handleVisibilityChange("sizeChanged")
Component.onDestruction: {
root.stopAllActivity("destruction")
}
onCommandChanged: {
handleVisibilityChange("commandChanged")
}
onAutoRefreshChanged: {
timer.running = root.autoRefresh && root.isRunnable()
if (root.autoRefresh && root.hasRunInitial && root.isRunnable()) {
timer.restart()
}
}
onRefreshIntervalChanged: {
if (timer.running) {
timer.restart()
}
}
function normalizeRefreshInterval(value) {
const parsed = Number(value)
if (!isFinite(parsed) || parsed <= 0) {
return 60000
}
return parsed * 1000
}
function normalizeCommandTimeout(value) {
const parsed = Number(value)
if (!isFinite(parsed) || parsed <= 0) {
return 5
}
return parsed
}
function normalizeFontSize(value) {
const parsed = parseInt(value, 10)
if (!isFinite(parsed) || parsed <= 0) {
return Theme.fontSizeSmall
}
return parsed
}
function isRunnable() {
const win = root.windowRef
const winVisible = win === null ? true : !!win.visible
// in other weird cases, it will just start on timer with 2s delay
return root.visible && winVisible && root.widgetWidth > 0 && root.widgetHeight > 0
}
function isStartingEdgeCase(){
if (root.widgetWidth == 500 || root.widgetWidth == 200) {
initialRunTimer.start()
return true
}
if (root.widgetHeight == 500 || root.widgetHeight == 200) {
initialRunTimer.start()
return true
}
return false
}
function handleVisibilityChange(source) {
if(source == "commandChanged" || source == "root.visible"){
root.hasRunInitial = false
}
if (!root.isRunnable()) {
root.stopAllActivity(source)
return
}
if (!root.hasRunInitial) {
if(root.isStartingEdgeCase() && source != "timer"){
return
}
root.hasRunInitial = true
initialRunTimer.stop()
runCommand()
}
if (root.autoRefresh) {
timer.start()
}
}
function runCommand() {
if (!root.isRunnable()) {
console.warn(`[desktopCommand] runCommand skipped; not runnable (visible=${root.visible} winVisible=${root.windowRef ? root.windowRef.visible : "n/a"}`)
return
}
if (process.running) {
console.warn(`[desktopCommand] runCommand skipped; process already running; command="${root.command}"`)
return
}
root.updateTerminalSize()
let command = `"${root.wrapCommandPath}" --width=${root.cols} --height=${root.rows} --timeout=${root.commandTimeout} `
if (root.useDank16) {
command += `--colors='${JSON.stringify(root.dank16)}' `
}
command += `-- ${JSON.stringify(root.command)}`
process.command = ["sh", "-c", command]
process.running = true
}
function updateTerminalSize() {
const horizontalMargin = 0
const verticalMargin = 8
const availableWidth = Math.max(200, (root.widgetWidth ?? root.width) - horizontalMargin)
const availableHeight = Math.max(200, (root.widgetHeight ?? root.height) - verticalMargin)
root.cols = Math.max(1, Math.floor(availableWidth / Math.max(1, fontMetrics.averageCharacterWidth)))
root.rows = Math.max(1, Math.floor(availableHeight / Math.max(1, fontMetrics.lineSpacing)))
}
function stopAllActivity(reason) {
timer.stop()
process.running = false
root.output = ""
}
Process {
id: process
stdout: StdioCollector {
onStreamFinished: {
root.output = this.text
}
}
}
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, root.backgroundOpacity)
visible: root.visible
Text {
anchors.fill: parent
anchors.margins: 8
text: root.output
textFormat: Text.RichText
wrapMode: Text.NoWrap
color: useDank16? Theme.surfaceText : "#c0c0c0"
font.pixelSize: root.fontSizePx
font.family: Theme.monoFontFamily
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignTop
}
}
}