Files
arthur-os/shell/plugins/panels/dropbox/Service.qml
T

184 lines
5.5 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Io
import qs.Commons
import "Model.js" as Model
Item {
id: root
property var settings: ({})
property string omarchyPath: Quickshell.env("OMARCHY_PATH")
property bool installed: false
property bool running: false
property bool authenticated: false
property bool refreshing: false
property string statusText: "Checking…"
property string accountPath: ""
property string plan: ""
property double usedBytes: 0
property double quotaBytes: 0
property double usagePercent: 0
property bool quotaKnown: false
property var files: []
property string actionStatus: ""
property string lastError: ""
readonly property int refreshIntervalSec: intSetting("refreshIntervalSec", 60, 10, 3600)
readonly property bool busy: statusProcess.running || loginProcess.running
readonly property string helperPath: (omarchyPath || "") + "/shell/plugins/panels/dropbox/status.py"
property string _statusOutput: ""
property string _statusError: ""
property string _loginOutput: ""
property string _loginError: ""
property bool _loginUrlOpened: false
function setting(name, fallback) {
var value = settings ? settings[name] : undefined
return value === undefined || value === null ? fallback : value
}
function intSetting(name, fallback, min, max) {
var n = parseInt(String(setting(name, fallback)), 10)
if (!isFinite(n)) n = fallback
if (n < min) n = min
if (n > max) n = max
return n
}
function refresh() {
if (statusProcess.running || helperPath === "/shell/plugins/panels/dropbox/status.py") return
_statusOutput = ""
_statusError = ""
refreshing = true
statusProcess.command = ["python3", helperPath, "25"]
statusProcess.running = true
}
function applyStatus(raw) {
var parsed = Model.parseStatus(raw)
if (!parsed.ok) {
lastError = parsed.lastError || "Failed to read Dropbox status"
return
}
installed = parsed.installed === true
running = parsed.running === true
authenticated = parsed.authenticated === true
statusText = String(parsed.statusText || (installed ? "Stopped" : "Not installed"))
accountPath = String(parsed.accountPath || "")
plan = String(parsed.plan || "")
usedBytes = Number(parsed.usedBytes || 0)
quotaBytes = Number(parsed.quotaBytes || 0)
usagePercent = Number(parsed.usagePercent || 0)
quotaKnown = parsed.quotaKnown === true
files = parsed.files || []
lastError = ""
}
function elideStatus(text) {
var value = String(text || "").replace(/\s+/g, " ").trim()
return value.length > 140 ? value.substring(0, 137) + "…" : value
}
function login() {
if (!installed || loginProcess.running) return
_loginOutput = ""
_loginError = ""
_loginUrlOpened = false
actionStatus = "Starting Dropbox login…"
loginProcess.command = ["dropbox-cli", "start"]
loginProcess.running = true
}
function openFile(file) {
if (!file || !file.path) return
Quickshell.execDetached(["uwsm-app", "--", "nautilus", "--select", fileUri(String(file.path))])
}
function fileUri(path) {
var parts = String(path || "").split("/")
for (var i = 0; i < parts.length; i++) parts[i] = encodeURIComponent(parts[i])
return "file://" + parts.join("/")
}
function openAuthUrlFrom(text) {
if (_loginUrlOpened) return true
var match = String(text || "").match(/https?:\/\/\S+/)
if (match && match[0]) {
_loginUrlOpened = true
Qt.openUrlExternally(match[0])
actionStatus = "Opened Dropbox login"
actionStatusTimer.restart()
return true
}
return false
}
function handleLoginOutput(data, isError) {
var text = String(data || "")
if (isError) _loginError += text + "\n"
else _loginOutput += text + "\n"
openAuthUrlFrom(text)
}
Timer {
id: refreshTimer
interval: root.refreshIntervalSec * 1000
repeat: true
running: true
triggeredOnStart: true
onTriggered: root.refresh()
}
Timer {
id: delayedRefresh
interval: 1000
repeat: false
onTriggered: root.refresh()
}
Timer {
id: actionStatusTimer
interval: 2200
repeat: false
onTriggered: root.actionStatus = ""
}
Process {
id: statusProcess
running: false
command: []
stdout: StdioCollector { id: statusStdout; waitForEnd: true; onStreamFinished: root._statusOutput = text }
stderr: StdioCollector { id: statusStderr; waitForEnd: true; onStreamFinished: root._statusError = text }
onExited: function(exitCode) {
root.refreshing = false
var stdout = String(statusStdout.text || root._statusOutput || "")
var stderr = String(statusStderr.text || root._statusError || "")
if (exitCode === 0) root.applyStatus(stdout)
else root.lastError = root.elideStatus(stderr || stdout || "Could not read Dropbox status")
}
}
Process {
id: loginProcess
running: false
command: []
stdout: SplitParser { onRead: function(data) { root.handleLoginOutput(data, false) } }
stderr: SplitParser { onRead: function(data) { root.handleLoginOutput(data, true) } }
onExited: function(exitCode) {
var combined = String(root._loginOutput || "") + "\n" + String(root._loginError || "")
var opened = root.openAuthUrlFrom(combined)
if (exitCode !== 0 && !opened) {
root.lastError = root.elideStatus(combined || "Dropbox login failed")
root.actionStatus = root.lastError
} else if (!opened) {
root.actionStatus = ""
root.lastError = ""
}
delayedRefresh.restart()
}
}
}