mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 11:38:30 -04:00
173 lines
5.4 KiB
QML
173 lines
5.4 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
readonly property bool connected: backend.connected && backend.subscribed
|
|
readonly property bool initialized: backend.initialized
|
|
readonly property int apiVersion: backend.apiVersion
|
|
readonly property var capabilities: backend.capabilities
|
|
readonly property var devices: backend.devices
|
|
readonly property var devicesById: backend.devicesById
|
|
readonly property string lastError: backend.lastError
|
|
readonly property var primaryDevice: _selectPrimaryDevice()
|
|
property var pairingRequest: null
|
|
property bool _openAppPending: false
|
|
|
|
Component.onCompleted: backend.launch()
|
|
|
|
onConnectedChanged: {
|
|
if (!connected) {
|
|
pairingRequest = null;
|
|
return;
|
|
}
|
|
if (_openAppPending) {
|
|
_openAppPending = false;
|
|
_launchAttachedApp();
|
|
}
|
|
}
|
|
|
|
function _selectPrimaryDevice() {
|
|
let selected = null;
|
|
let selectedScore = -1;
|
|
for (const device of devices) {
|
|
const score = (device.isPaired ? 2 : 0) + (device.isReachable ? 1 : 0);
|
|
if (score <= selectedScore)
|
|
continue;
|
|
selected = device;
|
|
selectedScore = score;
|
|
}
|
|
return selected;
|
|
}
|
|
|
|
function _syncPairingRequest() {
|
|
for (const device of devices) {
|
|
if (!device.isPairRequestedByPeer)
|
|
continue;
|
|
pairingRequest = {
|
|
"deviceId": device.id,
|
|
"name": device.name || "",
|
|
"verificationKey": device.verificationKey || ""
|
|
};
|
|
return;
|
|
}
|
|
if (initialized)
|
|
pairingRequest = null;
|
|
}
|
|
|
|
function _handleEvent(topic, data) {
|
|
if (topic !== "pairing" || !data?.deviceId)
|
|
return;
|
|
pairingRequest = {
|
|
"deviceId": data.deviceId,
|
|
"name": data.name || "",
|
|
"verificationKey": data.verificationKey || ""
|
|
};
|
|
}
|
|
|
|
function supports(deviceOrId, packetType) {
|
|
return backend.supports(deviceOrId, packetType);
|
|
}
|
|
|
|
function canRing(deviceOrId) {
|
|
const device = typeof deviceOrId === "string" ? backend.getDevice(deviceOrId) : deviceOrId;
|
|
return connected && !!device?.isPaired && !!device?.isReachable && backend.hasCapability("device") && supports(device, "kdeconnect.findmyphone.request");
|
|
}
|
|
|
|
function canPing(deviceOrId) {
|
|
const device = typeof deviceOrId === "string" ? backend.getDevice(deviceOrId) : deviceOrId;
|
|
return connected && !!device?.isPaired && !!device?.isReachable && backend.hasCapability("ping") && supports(device, "kdeconnect.ping");
|
|
}
|
|
|
|
function canSendClipboard(deviceOrId) {
|
|
const device = typeof deviceOrId === "string" ? backend.getDevice(deviceOrId) : deviceOrId;
|
|
return connected && !!device?.isPaired && !!device?.isReachable && backend.hasCapability("clipboard") && supports(device, "kdeconnect.clipboard");
|
|
}
|
|
|
|
function ringDevice(deviceId, callback) {
|
|
if (!canRing(deviceId)) {
|
|
callback?.({
|
|
"error": "ring unavailable"
|
|
});
|
|
return -1;
|
|
}
|
|
return backend.request("device.ring", {
|
|
"deviceId": deviceId
|
|
}, callback);
|
|
}
|
|
|
|
function pingDevice(deviceId, callback) {
|
|
if (!canPing(deviceId)) {
|
|
callback?.({
|
|
"error": "ping unavailable"
|
|
});
|
|
return -1;
|
|
}
|
|
return backend.request("ping.send", {
|
|
"deviceId": deviceId
|
|
}, callback);
|
|
}
|
|
|
|
function sendClipboard(deviceId, callback) {
|
|
if (!canSendClipboard(deviceId)) {
|
|
callback?.({
|
|
"error": "clipboard unavailable"
|
|
});
|
|
return -1;
|
|
}
|
|
return backend.request("clipboard.send", {
|
|
"deviceId": deviceId,
|
|
"content": ""
|
|
}, callback);
|
|
}
|
|
|
|
function acceptPairing(deviceId, callback) {
|
|
return _respondToPairing("pairing.accept", deviceId, callback);
|
|
}
|
|
|
|
function rejectPairing(deviceId, callback) {
|
|
return _respondToPairing("pairing.reject", deviceId, callback);
|
|
}
|
|
|
|
function openApp() {
|
|
if (!connected) {
|
|
_openAppPending = true;
|
|
backend.launch();
|
|
return;
|
|
}
|
|
_launchAttachedApp();
|
|
}
|
|
|
|
function _launchAttachedApp() {
|
|
Quickshell.execDetached(["sh", "-c", "if command -v dankconnect >/dev/null 2>&1; then exec dankconnect app; elif command -v flatpak >/dev/null 2>&1 && flatpak info com.danklinux.dankconnect >/dev/null 2>&1; then exec flatpak run --command=dankconnect com.danklinux.dankconnect app; fi"]);
|
|
}
|
|
|
|
function _respondToPairing(method, deviceId, callback) {
|
|
if (!connected || !backend.hasCapability("pairing") || !deviceId) {
|
|
callback?.({
|
|
"error": "pairing unavailable"
|
|
});
|
|
return -1;
|
|
}
|
|
return backend.request(method, {
|
|
"deviceId": deviceId
|
|
}, response => {
|
|
if (!response.error && pairingRequest?.deviceId === deviceId)
|
|
pairingRequest = null;
|
|
callback?.(response);
|
|
});
|
|
}
|
|
|
|
DankConnectBackend {
|
|
id: backend
|
|
|
|
enabled: true
|
|
onDevicesChanged: root._syncPairingRequest()
|
|
onEventReceived: (topic, data) => root._handleEvent(topic, data)
|
|
}
|
|
}
|