Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

quickshell/nuguland/Bluetooth.qml

Raw
import QtQuick
import Quickshell.Bluetooth
import "bluetoothNative.js" as BluetoothNative

Item {
    id: root

    property string error: ""
    property var lastAction: ({})
    property int refreshTicks: 0
    signal refreshed
    readonly property string nativeApi: "Quickshell.Bluetooth.Bluetooth.defaultAdapter BluetoothAdapter BluetoothDevice"
    readonly property var boundedActions: ["scan", "toggle", "connect", "disconnect", "pair", "forget", "trust", "block"]
    readonly property bool nativeActionRoute: true
    function nativeAdapter() {
        return BluetoothNative.defaultAdapter(Bluetooth);
    }

    function deviceId(device) {
        return String(device.id || device.address || device.deviceName || device.name || "device");
    }

    function deviceName(device) {
        return String(device.name || device.deviceName || device.address || device.id || "device");
    }

    function cloneDevice(device) {
        return {
            "id": deviceId(device),
            "name": deviceName(device),
            "type": String(device.type || device.icon || "device"),
            "connected": !!device.connected,
            "paired": !!device.paired,
            "trusted": !!device.trusted,
            "blocked": !!device.blocked,
            "battery": Number(device.batteryAvailable === false ? -1 : (device.battery ?? -1))
        };
    }

    function nativeDevices() {
        return BluetoothNative.devices(Bluetooth).map(device => {
            return ({
                    "id": deviceId(device),
                    "name": deviceName(device),
                    "type": String(device.icon || "device"),
                    "connected": !!device.connected,
                    "paired": !!device.paired,
                    "trusted": !!device.trusted,
                    "blocked": !!device.blocked,
                    "battery": Number(device.batteryAvailable ? Math.round(Number(device.battery || 0) * 100) : -1),
                    "nativeObject": device
                });
        });
    }

    function sortedDevices(rows) {
        return rows.slice(0).sort((a, b) => {
            if (!!a.connected !== !!b.connected)
                return a.connected ? -1 : 1;

            if (!!a.paired !== !!b.paired)
                return a.paired ? -1 : 1;

            return deviceName(a).localeCompare(deviceName(b));
        });
    }

    function devicesList() {
        return sortedDevices(nativeDevices());
    }

    function devicesById() {
        const indexed = {};
        const list = devicesList();
        for (let i = 0; i < list.length; i++)
            indexed[deviceId(list[i])] = cloneDevice(list[i]);
        return indexed;
    }

    function adapterEnabled() {
        const adapter = nativeAdapter();
        return !!(adapter && adapter.enabled);
    }

    function discovering() {
        const adapter = nativeAdapter();
        return !!(adapter && adapter.discovering);
    }

    function role() {
        if (error.length > 0)
            return "error";

        if (!adapterEnabled())
            return "ui.minor";

        return discovering() ? "warning" : "ui.accent";
    }

    function connectedCount() {
        let count = 0;
        const list = devicesList();
        for (let i = 0; i < list.length; i++)
            if (list[i].connected) {
                count++;
            }
        return count;
    }

    function stateObject() {
        return {
            "backend": "Bluetooth.qml",
            "usesNativeQuickshellBluetooth": true,
            "nativeApi": nativeApi,
            "nativeActionRoute": nativeActionRoute,
            "nativeAdapterAvailable": !!nativeAdapter(),
            "nativeAdapterName": nativeAdapter() ? String(nativeAdapter().name) : "",
            "helperProcesses": [],
            "serviceOwnedActions": true,
            "boundedActions": boundedActions,
            "error": error,
            "adapter": {
                "id": !nativeAdapter() ? "" : String(nativeAdapter().adapterId || ""),
                "state": adapterEnabled() ? "powered" : "disabled",
                "discovering": discovering(),
                "discoverable": !nativeAdapter() ? false : !!nativeAdapter().discoverable,
                "pairable": !nativeAdapter() ? false : !!nativeAdapter().pairable
            },
            "devices": devicesList().map(device => {
                return cloneDevice(device);
            }),
            "devicesById": devicesById(),
            "compact": {
                "label": adapterEnabled() ? String(connectedCount()) + " connected" : "bluetooth off",
                "role": role()
            },
            "lastAction": lastAction
        };
    }

    function stateJson() {
        return JSON.stringify(stateObject());
    }

    function scheduleRefresh() {
        refreshTicks = 8;
        refreshTimer.restart();
    }

    function scan() {
        const adapter = nativeAdapter();
        const wasEnabled = adapterEnabled();
        if (adapter) {
            adapter.enabled = true;
            if (wasEnabled)
                adapter.discovering = true;
        }
        error = "";
        lastAction = {
            "kind": "scan",
            "poweredBeforeScan": wasEnabled,
            "nativeActionRoute": nativeActionRoute
        };
        scheduleRefresh();
        return stateJson();
    }

    function toggle(on) {
        if (nativeAdapter()) {
            nativeAdapter().enabled = !!on;
            if (!on)
                nativeAdapter().discovering = false;
        }
        error = "";
        lastAction = {
            "kind": "toggle",
            "enabled": adapterEnabled(),
            "nativeActionRoute": nativeActionRoute
        };
        scheduleRefresh();
        return stateJson();
    }

    function deviceAction(kind, id) {
        const actionName = String(kind);
        const deviceIdValue = String(id);
        {
            const list = devicesList();
            for (let i = 0; i < list.length; i++) {
                if (deviceId(list[i]) !== deviceIdValue || !list[i].nativeObject)
                    continue;

                const device = list[i].nativeObject;
                if (actionName === "connect")
                    device.connect();

                if (actionName === "disconnect")
                    device.disconnect();

                if (actionName === "pair")
                    device.pair();

                if (actionName === "forget")
                    device.forget();

                if (actionName === "trust")
                    device.trusted = true;

                if (actionName === "block")
                    device.blocked = true;
            }
        }
        error = "";
        lastAction = {
            "kind": actionName,
            "id": deviceIdValue,
            "nativeActionRoute": nativeActionRoute
        };
        scheduleRefresh();
        return stateJson();
    }

    Timer {
        id: refreshTimer
        interval: 500
        repeat: true
        onTriggered: {
            root.refreshed();
            root.refreshTicks -= 1;
            if (root.refreshTicks <= 0)
                stop();
        }
    }
}