mirror of
https://github.com/belsabbagh/dotfiles.git
synced 2026-04-11 09:36:46 +00:00
quickshell and hyprland additions
This commit is contained in:
179
.config/quickshell/caelestia/services/VPN.qml
Normal file
179
.config/quickshell/caelestia/services/VPN.qml
Normal file
@@ -0,0 +1,179 @@
|
||||
pragma Singleton
|
||||
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import QtQuick
|
||||
import qs.config
|
||||
import Caelestia
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property bool connected: false
|
||||
|
||||
readonly property bool connecting: connectProc.running || disconnectProc.running
|
||||
readonly property bool enabled: Config.utilities.vpn.provider.some(p => typeof p === "object" ? (p.enabled === true) : false)
|
||||
readonly property var providerInput: {
|
||||
const enabledProvider = Config.utilities.vpn.provider.find(p => typeof p === "object" ? (p.enabled === true) : false);
|
||||
return enabledProvider || "wireguard";
|
||||
}
|
||||
readonly property bool isCustomProvider: typeof providerInput === "object"
|
||||
readonly property string providerName: isCustomProvider ? (providerInput.name || "custom") : String(providerInput)
|
||||
readonly property string interfaceName: isCustomProvider ? (providerInput.interface || "") : ""
|
||||
readonly property var currentConfig: {
|
||||
const name = providerName;
|
||||
const iface = interfaceName;
|
||||
const defaults = getBuiltinDefaults(name, iface);
|
||||
|
||||
if (isCustomProvider) {
|
||||
const custom = providerInput;
|
||||
return {
|
||||
connectCmd: custom.connectCmd || defaults.connectCmd,
|
||||
disconnectCmd: custom.disconnectCmd || defaults.disconnectCmd,
|
||||
interface: custom.interface || defaults.interface,
|
||||
displayName: custom.displayName || defaults.displayName
|
||||
};
|
||||
}
|
||||
|
||||
return defaults;
|
||||
}
|
||||
|
||||
function getBuiltinDefaults(name, iface) {
|
||||
const builtins = {
|
||||
"wireguard": {
|
||||
connectCmd: ["pkexec", "wg-quick", "up", iface],
|
||||
disconnectCmd: ["pkexec", "wg-quick", "down", iface],
|
||||
interface: iface,
|
||||
displayName: iface
|
||||
},
|
||||
"warp": {
|
||||
connectCmd: ["warp-cli", "connect"],
|
||||
disconnectCmd: ["warp-cli", "disconnect"],
|
||||
interface: "CloudflareWARP",
|
||||
displayName: "Warp"
|
||||
},
|
||||
"netbird": {
|
||||
connectCmd: ["netbird", "up"],
|
||||
disconnectCmd: ["netbird", "down"],
|
||||
interface: "wt0",
|
||||
displayName: "NetBird"
|
||||
},
|
||||
"tailscale": {
|
||||
connectCmd: ["tailscale", "up"],
|
||||
disconnectCmd: ["tailscale", "down"],
|
||||
interface: "tailscale0",
|
||||
displayName: "Tailscale"
|
||||
}
|
||||
};
|
||||
|
||||
return builtins[name] || {
|
||||
connectCmd: [name, "up"],
|
||||
disconnectCmd: [name, "down"],
|
||||
interface: iface || name,
|
||||
displayName: name
|
||||
};
|
||||
}
|
||||
|
||||
function connect(): void {
|
||||
if (!connected && !connecting && root.currentConfig && root.currentConfig.connectCmd) {
|
||||
connectProc.exec(root.currentConfig.connectCmd);
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect(): void {
|
||||
if (connected && !connecting && root.currentConfig && root.currentConfig.disconnectCmd) {
|
||||
disconnectProc.exec(root.currentConfig.disconnectCmd);
|
||||
}
|
||||
}
|
||||
|
||||
function toggle(): void {
|
||||
if (connected) {
|
||||
disconnect();
|
||||
} else {
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
function checkStatus(): void {
|
||||
if (root.enabled) {
|
||||
statusProc.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
onConnectedChanged: {
|
||||
if (!Config.utilities.toasts.vpnChanged)
|
||||
return;
|
||||
|
||||
const displayName = root.currentConfig ? (root.currentConfig.displayName || "VPN") : "VPN";
|
||||
if (connected) {
|
||||
Toaster.toast(qsTr("VPN connected"), qsTr("Connected to %1").arg(displayName), "vpn_key");
|
||||
} else {
|
||||
Toaster.toast(qsTr("VPN disconnected"), qsTr("Disconnected from %1").arg(displayName), "vpn_key_off");
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: root.enabled && statusCheckTimer.start()
|
||||
|
||||
Process {
|
||||
id: nmMonitor
|
||||
|
||||
running: root.enabled
|
||||
command: ["nmcli", "monitor"]
|
||||
stdout: SplitParser {
|
||||
onRead: statusCheckTimer.restart()
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: statusProc
|
||||
|
||||
command: ["ip", "link", "show"]
|
||||
environment: ({
|
||||
LANG: "C.UTF-8",
|
||||
LC_ALL: "C.UTF-8"
|
||||
})
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const iface = root.currentConfig ? root.currentConfig.interface : "";
|
||||
root.connected = iface && text.includes(iface + ":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: connectProc
|
||||
|
||||
onExited: statusCheckTimer.start()
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const error = text.trim();
|
||||
if (error && !error.includes("[#]") && !error.includes("already exists")) {
|
||||
console.warn("VPN connection error:", error);
|
||||
} else if (error.includes("already exists")) {
|
||||
root.connected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: disconnectProc
|
||||
|
||||
onExited: statusCheckTimer.start()
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const error = text.trim();
|
||||
if (error && !error.includes("[#]")) {
|
||||
console.warn("VPN disconnection error:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: statusCheckTimer
|
||||
|
||||
interval: 500
|
||||
onTriggered: root.checkStatus()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user