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
229 lines
7.1 KiB
QML
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
|
|
}
|
|
}
|
|
}
|