Tbh idk what the issue was, but the entire implementation is extremely scuffed and we need to remake it completely
232 lines
8.1 KiB
QML
232 lines
8.1 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import ".."
|
|
import "../components"
|
|
import qs.components
|
|
import qs.components.controls
|
|
import qs.components.containers
|
|
import qs.components.effects
|
|
import qs.services
|
|
import qs.config
|
|
import Quickshell
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
|
|
ColumnLayout {
|
|
id: root
|
|
|
|
required property Session session
|
|
|
|
spacing: Appearance.spacing.normal
|
|
|
|
SettingsHeader {
|
|
icon: "vpn_key"
|
|
title: qsTr("VPN Settings")
|
|
}
|
|
|
|
SectionHeader {
|
|
Layout.topMargin: Appearance.spacing.large
|
|
title: qsTr("General")
|
|
description: qsTr("VPN configuration")
|
|
}
|
|
|
|
SectionContainer {
|
|
ToggleRow {
|
|
label: qsTr("VPN enabled")
|
|
checked: Config.utilities.vpn.enabled
|
|
toggle.onToggled: {
|
|
Config.utilities.vpn.enabled = checked;
|
|
Config.save();
|
|
}
|
|
}
|
|
}
|
|
|
|
SectionHeader {
|
|
Layout.topMargin: Appearance.spacing.large
|
|
title: qsTr("Providers")
|
|
description: qsTr("Manage VPN providers")
|
|
}
|
|
|
|
SectionContainer {
|
|
contentSpacing: Appearance.spacing.normal
|
|
|
|
ListView {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: contentHeight
|
|
|
|
interactive: false
|
|
spacing: Appearance.spacing.smaller
|
|
|
|
model: ScriptModel {
|
|
values: Config.utilities.vpn.provider.map((provider, index) => {
|
|
const isObject = typeof provider === "object";
|
|
const name = isObject ? (provider.name || "custom") : String(provider);
|
|
const displayName = isObject ? (provider.displayName || name) : name;
|
|
const iface = isObject ? (provider.interface || "") : "";
|
|
|
|
return {
|
|
index: index,
|
|
name: name,
|
|
displayName: displayName,
|
|
interface: iface,
|
|
provider: provider,
|
|
isActive: index === 0
|
|
};
|
|
})
|
|
}
|
|
|
|
delegate: Component {
|
|
StyledRect {
|
|
required property var modelData
|
|
required property int index
|
|
|
|
width: ListView.view ? ListView.view.width : undefined
|
|
color: Colours.tPalette.m3surfaceContainerHigh
|
|
radius: Appearance.rounding.normal
|
|
|
|
RowLayout {
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.margins: Appearance.padding.normal
|
|
spacing: Appearance.spacing.normal
|
|
|
|
MaterialIcon {
|
|
text: modelData.isActive ? "vpn_key" : "vpn_key_off"
|
|
font.pointSize: Appearance.font.size.large
|
|
color: modelData.isActive ? Colours.palette.m3primary : Colours.palette.m3outline
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 0
|
|
|
|
StyledText {
|
|
text: modelData.displayName
|
|
font.weight: modelData.isActive ? 500 : 400
|
|
}
|
|
|
|
StyledText {
|
|
text: qsTr("%1 • %2").arg(modelData.name).arg(modelData.interface || qsTr("No interface"))
|
|
font.pointSize: Appearance.font.size.small
|
|
color: Colours.palette.m3outline
|
|
}
|
|
}
|
|
|
|
IconButton {
|
|
icon: modelData.isActive ? "arrow_downward" : "arrow_upward"
|
|
visible: !modelData.isActive || Config.utilities.vpn.provider.length > 1
|
|
onClicked: {
|
|
if (modelData.isActive && index < Config.utilities.vpn.provider.length - 1) {
|
|
// Move down
|
|
const providers = [...Config.utilities.vpn.provider];
|
|
const temp = providers[index];
|
|
providers[index] = providers[index + 1];
|
|
providers[index + 1] = temp;
|
|
Config.utilities.vpn.provider = providers;
|
|
Config.save();
|
|
} else if (!modelData.isActive) {
|
|
// Make active (move to top)
|
|
const providers = [...Config.utilities.vpn.provider];
|
|
const provider = providers.splice(index, 1)[0];
|
|
providers.unshift(provider);
|
|
Config.utilities.vpn.provider = providers;
|
|
Config.save();
|
|
}
|
|
}
|
|
}
|
|
|
|
IconButton {
|
|
icon: "delete"
|
|
onClicked: {
|
|
const providers = [...Config.utilities.vpn.provider];
|
|
providers.splice(index, 1);
|
|
Config.utilities.vpn.provider = providers;
|
|
Config.save();
|
|
}
|
|
}
|
|
}
|
|
|
|
implicitHeight: 60
|
|
}
|
|
}
|
|
}
|
|
|
|
TextButton {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Appearance.spacing.normal
|
|
text: qsTr("+ Add Provider")
|
|
inactiveColour: Colours.palette.m3primaryContainer
|
|
inactiveOnColour: Colours.palette.m3onPrimaryContainer
|
|
|
|
onClicked: {
|
|
addProviderDialog.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
SectionHeader {
|
|
Layout.topMargin: Appearance.spacing.large
|
|
title: qsTr("Quick Add")
|
|
description: qsTr("Add common VPN providers")
|
|
}
|
|
|
|
SectionContainer {
|
|
contentSpacing: Appearance.spacing.smaller
|
|
|
|
TextButton {
|
|
Layout.fillWidth: true
|
|
text: qsTr("+ Add NetBird")
|
|
inactiveColour: Colours.tPalette.m3surfaceContainerHigh
|
|
inactiveOnColour: Colours.palette.m3onSurface
|
|
|
|
onClicked: {
|
|
const providers = [...Config.utilities.vpn.provider];
|
|
providers.push({
|
|
name: "netbird",
|
|
displayName: "NetBird",
|
|
interface: "wt0"
|
|
});
|
|
Config.utilities.vpn.provider = providers;
|
|
Config.save();
|
|
}
|
|
}
|
|
|
|
TextButton {
|
|
Layout.fillWidth: true
|
|
text: qsTr("+ Add Tailscale")
|
|
inactiveColour: Colours.tPalette.m3surfaceContainerHigh
|
|
inactiveOnColour: Colours.palette.m3onSurface
|
|
|
|
onClicked: {
|
|
const providers = [...Config.utilities.vpn.provider];
|
|
providers.push({
|
|
name: "tailscale",
|
|
displayName: "Tailscale",
|
|
interface: "tailscale0"
|
|
});
|
|
Config.utilities.vpn.provider = providers;
|
|
Config.save();
|
|
}
|
|
}
|
|
|
|
TextButton {
|
|
Layout.fillWidth: true
|
|
text: qsTr("+ Add Cloudflare WARP")
|
|
inactiveColour: Colours.tPalette.m3surfaceContainerHigh
|
|
inactiveOnColour: Colours.palette.m3onSurface
|
|
|
|
onClicked: {
|
|
const providers = [...Config.utilities.vpn.provider];
|
|
providers.push({
|
|
name: "warp",
|
|
displayName: "Cloudflare WARP",
|
|
interface: "CloudflareWARP"
|
|
});
|
|
Config.utilities.vpn.provider = providers;
|
|
Config.save();
|
|
}
|
|
}
|
|
}
|
|
}
|