mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-11 07:52:50 -05:00
VPN multi-active: toggle per row fixes reconnection, add Quick Connect + Disconnect All, header/tooltips summarize multiple active; default allow multiple active
This commit is contained in:
@@ -77,7 +77,12 @@ Rectangle {
|
|||||||
Text {
|
Text {
|
||||||
id: tooltipText
|
id: tooltipText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: VpnService.connected ? ("VPN Connected • " + (VpnService.activeName || "")) : "VPN Disconnected"
|
text: {
|
||||||
|
if (!VpnService.connected) return "VPN Disconnected"
|
||||||
|
const names = VpnService.activeNames || []
|
||||||
|
if (names.length <= 1) return "VPN Connected • " + (names[0] || "")
|
||||||
|
return "VPN Connected • " + names[0] + " +" + (names.length - 1)
|
||||||
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,32 +162,59 @@ DankPopout {
|
|||||||
|
|
||||||
Item { Layout.fillWidth: true; height: 1 }
|
Item { Layout.fillWidth: true; height: 1 }
|
||||||
|
|
||||||
// Quick connect when not connected
|
// Quick connect
|
||||||
// Rectangle {
|
Rectangle {
|
||||||
// height: 28
|
height: 28
|
||||||
// radius: 14
|
radius: 14
|
||||||
// color: quickBtnArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight
|
color: quickBtnArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight
|
||||||
// visible: !VpnService.connected && VpnService.profiles.length > 0
|
visible: VpnService.profiles.length > 0
|
||||||
// width: 120
|
width: 120
|
||||||
// Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
// border.width: 1
|
border.width: 1
|
||||||
// border.color: Theme.outlineLight
|
border.color: Theme.outlineLight
|
||||||
//
|
|
||||||
// Row {
|
Row {
|
||||||
// anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
// spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
// DankIcon { name: "link"; size: Theme.fontSizeSmall; color: Theme.surfaceText }
|
DankIcon { name: "link"; size: Theme.fontSizeSmall; color: Theme.surfaceText }
|
||||||
// StyledText { text: "Connect"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceText; font.weight: Font.Medium }
|
StyledText { text: "Connect"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceText; font.weight: Font.Medium }
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// MouseArea {
|
MouseArea {
|
||||||
// id: quickBtnArea
|
id: quickBtnArea
|
||||||
// anchors.fill: parent
|
anchors.fill: parent
|
||||||
// hoverEnabled: true
|
hoverEnabled: true
|
||||||
// cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
// onClicked: VpnService.toggle()
|
onClicked: VpnService.toggle()
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
// Disconnect all (visible when any active)
|
||||||
|
Rectangle {
|
||||||
|
height: 28
|
||||||
|
radius: 14
|
||||||
|
color: discAllArea.containsMouse ? Theme.errorHover : Theme.surfaceLight
|
||||||
|
visible: VpnService.connected
|
||||||
|
width: 130
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
|
border.width: 1
|
||||||
|
border.color: Theme.outlineLight
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
DankIcon { name: "link_off"; size: Theme.fontSizeSmall; color: Theme.surfaceText }
|
||||||
|
StyledText { text: "Disconnect All"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceText; font.weight: Font.Medium }
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: discAllArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: VpnService.disconnectAllActive()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle { height: 1; width: parent.width; color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) }
|
Rectangle { height: 1; width: parent.width; color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) }
|
||||||
@@ -255,13 +282,7 @@ DankPopout {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: VpnService.toggle(modelData.uuid)
|
||||||
if (modelData.uuid === VpnService.activeUuid) {
|
|
||||||
VpnService.disconnect(modelData.uuid)
|
|
||||||
} else {
|
|
||||||
VpnService.connect(modelData.uuid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ Singleton {
|
|||||||
// [{ name, uuid, type }]
|
// [{ name, uuid, type }]
|
||||||
property var profiles: []
|
property var profiles: []
|
||||||
|
|
||||||
// Enforce single active VPN at a time
|
// Allow multiple active VPNs (set true to allow concurrent connections)
|
||||||
property bool singleActive: true
|
// Default: allow multiple, to align with NetworkManager capability
|
||||||
|
property bool singleActive: false
|
||||||
|
|
||||||
// Active VPN connections (may be multiple)
|
// Active VPN connections (may be multiple)
|
||||||
// Full list and convenience projections
|
// Full list and convenience projections
|
||||||
@@ -160,11 +161,12 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggle(uuid) {
|
function toggle(uuid) {
|
||||||
if (root.activeUuid && (uuid === undefined || uuid === root.activeUuid)) {
|
if (uuid) {
|
||||||
disconnect(root.activeUuid)
|
if (isActiveUuid(uuid)) disconnect(uuid)
|
||||||
} else if (uuid) {
|
else connect(uuid)
|
||||||
connect(uuid)
|
return
|
||||||
} else if (root.profiles.length > 0) {
|
}
|
||||||
|
if (root.profiles.length > 0) {
|
||||||
connect(root.profiles[0].uuid)
|
connect(root.profiles[0].uuid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,6 +211,14 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function disconnectAllActive() {
|
||||||
|
if (root.isBusy) return
|
||||||
|
root.isBusy = true
|
||||||
|
const script = `nmcli -t -f UUID,TYPE connection show --active | awk -F: '$2 ~ /^(vpn|wireguard)$/ {print $1}' | while read u; do [ -n \"$u\" ] && nmcli connection down uuid \"$u\" || true; done`
|
||||||
|
vpnSwitch.command = ["bash", "-lc", script]
|
||||||
|
vpnSwitch.running = true
|
||||||
|
}
|
||||||
|
|
||||||
// Sequenced down/up using a single shell for exclusive switch
|
// Sequenced down/up using a single shell for exclusive switch
|
||||||
Process {
|
Process {
|
||||||
id: vpnSwitch
|
id: vpnSwitch
|
||||||
|
|||||||
Reference in New Issue
Block a user