1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00

vpn: various state management fixes

This commit is contained in:
bbedward
2025-10-27 14:17:29 -04:00
parent f0a1cb6525
commit 033f96a4b0
8 changed files with 138 additions and 37 deletions

View File

@@ -134,6 +134,7 @@ Singleton {
property bool weatherEnabled: true
property string networkPreference: "auto"
property string vpnLastConnected: ""
property string iconTheme: "System Default"
property var availableIconThemes: ["System Default"]
@@ -1398,6 +1399,11 @@ Singleton {
saveSettings()
}
function setVpnLastConnected(uuid) {
vpnLastConnected = uuid
saveSettings()
}
function setIconTheme(themeName) {
iconTheme = themeName
updateGtkIconTheme(themeName)

View File

@@ -213,10 +213,26 @@ Item {
}
}
property string lastCredentialsToken: ""
property var lastCredentialsTime: 0
Connections {
target: NetworkService
function onCredentialsNeeded(token, ssid, setting, fields, hints, reason, connType, connName, vpnService) {
const now = Date.now()
const timeSinceLastPrompt = now - lastCredentialsTime
if (wifiPasswordModal.shouldBeVisible && timeSinceLastPrompt < 1000) {
NetworkService.cancelCredentials(lastCredentialsToken)
lastCredentialsToken = token
lastCredentialsTime = now
wifiPasswordModal.showFromPrompt(token, ssid, setting, fields, hints, reason, connType, connName, vpnService)
return
}
lastCredentialsToken = token
lastCredentialsTime = now
wifiPasswordModal.showFromPrompt(token, ssid, setting, fields, hints, reason, connType, connName, vpnService)
}
}

View File

@@ -13,6 +13,7 @@ PluginComponent {
service: DMSNetworkService
}
ccWidgetIcon: DMSNetworkService.isBusy ? "sync" : (DMSNetworkService.connected ? "vpn_lock" : "vpn_key_off")
ccWidgetPrimaryText: "VPN"
ccWidgetSecondaryText: {
@@ -26,11 +27,7 @@ PluginComponent {
ccWidgetIsActive: DMSNetworkService.connected
onCcWidgetToggled: {
if (DMSNetworkService.connected) {
DMSNetworkService.disconnectAllActive()
} else if (DMSNetworkService.profiles.length > 0) {
DMSNetworkService.connect(DMSNetworkService.profiles[0].uuid)
}
DMSNetworkService.toggleVpn()
}
ccDetailContent: Component {
@@ -62,10 +59,10 @@ PluginComponent {
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Item {
elide: Text.ElideRight
wrapMode: Text.NoWrap
Layout.fillWidth: true
Layout.maximumWidth: parent.width - 120
}
Rectangle {
@@ -75,6 +72,7 @@ PluginComponent {
visible: DMSNetworkService.connected
width: 110
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
opacity: DMSNetworkService.isBusy ? 0.5 : 1.0
Row {
anchors.centerIn: parent
@@ -98,7 +96,8 @@ PluginComponent {
id: discAllArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: DMSNetworkService.isBusy ? Qt.BusyCursor : Qt.PointingHandCursor
enabled: !DMSNetworkService.isBusy
onClicked: DMSNetworkService.disconnectAllActive()
}
}
@@ -165,6 +164,7 @@ PluginComponent {
color: rowArea.containsMouse ? Theme.primaryHoverLight : (DMSNetworkService.isActiveUuid(modelData.uuid) ? Theme.primaryPressed : Theme.surfaceLight)
border.width: DMSNetworkService.isActiveUuid(modelData.uuid) ? 2 : 1
border.color: DMSNetworkService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.outlineLight
opacity: DMSNetworkService.isBusy ? 0.5 : 1.0
RowLayout {
anchors.left: parent.left
@@ -183,11 +183,15 @@ PluginComponent {
Column {
spacing: 2
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeMedium
color: DMSNetworkService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.surfaceText
elide: Text.ElideRight
wrapMode: Text.NoWrap
width: parent.width
}
StyledText {
@@ -233,7 +237,8 @@ PluginComponent {
id: rowArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: DMSNetworkService.isBusy ? Qt.BusyCursor : Qt.PointingHandCursor
enabled: !DMSNetworkService.isBusy
onClicked: DMSNetworkService.toggle(modelData.uuid)
}
}

View File

@@ -17,6 +17,15 @@ DankPopout {
service: DMSNetworkService
}
property bool wasVisible: false
onShouldBeVisibleChanged: {
if (shouldBeVisible && !wasVisible) {
DMSNetworkService.getState()
}
wasVisible = shouldBeVisible
}
property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) {
@@ -175,11 +184,10 @@ DankPopout {
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Item {
elide: Text.ElideRight
wrapMode: Text.NoWrap
Layout.fillWidth: true
height: 1
Layout.maximumWidth: parent.width - 140
}
// Removed Quick Connect for clarity
@@ -198,6 +206,7 @@ DankPopout {
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
border.width: 0
border.color: Theme.outlineLight
opacity: DMSNetworkService.isBusy ? 0.5 : 1.0
Row {
anchors.centerIn: parent
@@ -223,7 +232,8 @@ DankPopout {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: DMSNetworkService.isBusy ? Qt.BusyCursor : Qt.PointingHandCursor
enabled: !DMSNetworkService.isBusy
onClicked: DMSNetworkService.disconnectAllActive()
}
@@ -295,6 +305,7 @@ DankPopout {
color: rowArea.containsMouse ? Theme.primaryHoverLight : (DMSNetworkService.isActiveUuid(modelData.uuid) ? Theme.primaryPressed : Theme.surfaceLight)
border.width: DMSNetworkService.isActiveUuid(modelData.uuid) ? 2 : 1
border.color: DMSNetworkService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.outlineLight
opacity: DMSNetworkService.isBusy ? 0.5 : 1.0
RowLayout {
anchors.left: parent.left
@@ -313,11 +324,15 @@ DankPopout {
Column {
spacing: 2
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeMedium
color: DMSNetworkService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.surfaceText
elide: Text.ElideRight
wrapMode: Text.NoWrap
width: parent.width
}
StyledText {
@@ -391,7 +406,8 @@ DankPopout {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: DMSNetworkService.isBusy ? Qt.BusyCursor : Qt.PointingHandCursor
enabled: !DMSNetworkService.isBusy
onClicked: DMSNetworkService.toggle(modelData.uuid)
}

View File

@@ -31,7 +31,7 @@ BasePill {
return "sync"
}
if (NetworkService.networkStatus === "ethernet") {
if (NetworkService.networkStatus === "ethernet" || (NetworkService.networkStatus === "vpn" && NetworkService.ethernetConnected)) {
return "lan"
}
@@ -128,7 +128,7 @@ BasePill {
return "sync";
}
if (NetworkService.networkStatus === "ethernet") {
if (NetworkService.networkStatus === "ethernet" || (NetworkService.networkStatus === "vpn" && NetworkService.ethernetConnected)) {
return "lan";
}

View File

@@ -25,10 +25,18 @@ BasePill {
DankIcon {
id: icon
name: DMSNetworkService.isBusy ? "sync" : (DMSNetworkService.connected ? "vpn_lock" : "vpn_key_off")
name: DMSNetworkService.connected ? "vpn_lock" : "vpn_key_off"
size: Theme.barIconSize(root.barThickness, -4)
color: DMSNetworkService.connected ? Theme.primary : Theme.surfaceText
opacity: DMSNetworkService.isBusy ? 0.5 : 1.0
anchors.centerIn: parent
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.InOutQuad
}
}
}
}
}
@@ -44,8 +52,9 @@ BasePill {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: DMSNetworkService.isBusy ? Qt.BusyCursor : Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton
enabled: !DMSNetworkService.isBusy
onPressed: {
if (popoutTarget && popoutTarget.setTriggerPosition) {
const globalPos = root.visualContent.mapToGlobal(0, 0)
@@ -65,9 +74,15 @@ BasePill {
} else {
const names = DMSNetworkService.activeNames || []
if (names.length <= 1) {
tooltipText = "VPN Connected • " + (names[0] || "")
const name = names[0] || ""
const maxLength = 25
const displayName = name.length > maxLength ? name.substring(0, maxLength) + "..." : name
tooltipText = "VPN Connected • " + displayName
} else {
tooltipText = "VPN Connected • " + names[0] + " +" + (names.length - 1)
const name = names[0]
const maxLength = 20
const displayName = name.length > maxLength ? name.substring(0, maxLength) + "..." : name
tooltipText = "VPN Connected • " + displayName + " +" + (names.length - 1)
}
}

View File

@@ -73,6 +73,9 @@ Singleton {
property var vpnActive: []
property bool vpnAvailable: false
property bool vpnIsBusy: false
property string lastConnectedVpnUuid: ""
property string pendingVpnUuid: ""
property var vpnBusyStartTime: 0
property alias profiles: root.vpnProfiles
property alias activeConnections: root.vpnActive
@@ -118,6 +121,7 @@ Singleton {
Component.onCompleted: {
root.userPreference = SettingsData.networkPreference
lastConnectedVpnUuid = SettingsData.vpnLastConnected || ""
if (socketPath && socketPath.length > 0) {
checkDMSCapabilities()
}
@@ -271,8 +275,41 @@ Singleton {
vpnProfiles = state.vpnProfiles
}
const previousVpnActive = vpnActive
vpnActive = state.vpnActive || []
if (vpnConnected && activeUuid) {
lastConnectedVpnUuid = activeUuid
SettingsData.setVpnLastConnected(activeUuid)
}
if (vpnIsBusy) {
const busyDuration = Date.now() - vpnBusyStartTime
const timeout = 30000
if (busyDuration > timeout) {
console.warn("DMSNetworkService: VPN operation timed out after", timeout, "ms")
vpnIsBusy = false
pendingVpnUuid = ""
vpnBusyStartTime = 0
} else if (pendingVpnUuid) {
const isPendingVpnActive = activeUuids.includes(pendingVpnUuid)
if (isPendingVpnActive) {
vpnIsBusy = false
pendingVpnUuid = ""
vpnBusyStartTime = 0
}
} else {
const previousCount = previousVpnActive ? previousVpnActive.length : 0
const currentCount = vpnActive ? vpnActive.length : 0
if (previousCount !== currentCount) {
vpnIsBusy = false
vpnBusyStartTime = 0
}
}
}
userPreference = state.preference || "auto"
isConnecting = state.isConnecting || false
connectingSSID = state.connectingSSID || ""
@@ -726,10 +763,12 @@ Singleton {
})
}
function connectVpn(uuidOrName, singleActive = false) {
function connectVpn(uuidOrName, singleActive = true) {
if (!vpnAvailable || vpnIsBusy) return
vpnIsBusy = true
pendingVpnUuid = uuidOrName
vpnBusyStartTime = Date.now()
const params = {
uuidOrName: uuidOrName,
@@ -737,12 +776,11 @@ Singleton {
}
DMSService.sendRequest("network.vpn.connect", params, response => {
vpnIsBusy = false
if (response.error) {
vpnIsBusy = false
pendingVpnUuid = ""
vpnBusyStartTime = 0
ToastService.showError(I18n.tr("Failed to connect VPN"))
} else {
Qt.callLater(() => getState())
}
})
}
@@ -755,18 +793,18 @@ Singleton {
if (!vpnAvailable || vpnIsBusy) return
vpnIsBusy = true
pendingVpnUuid = ""
vpnBusyStartTime = Date.now()
const params = {
uuidOrName: uuidOrName
}
DMSService.sendRequest("network.vpn.disconnect", params, response => {
vpnIsBusy = false
if (response.error) {
vpnIsBusy = false
vpnBusyStartTime = 0
ToastService.showError(I18n.tr("Failed to disconnect VPN"))
} else {
Qt.callLater(() => getState())
}
})
}
@@ -779,14 +817,12 @@ Singleton {
if (!vpnAvailable || vpnIsBusy) return
vpnIsBusy = true
pendingVpnUuid = ""
DMSService.sendRequest("network.vpn.disconnectAll", null, response => {
vpnIsBusy = false
if (response.error) {
vpnIsBusy = false
ToastService.showError(I18n.tr("Failed to disconnect VPNs"))
} else {
Qt.callLater(() => getState())
}
})
}
@@ -805,8 +841,14 @@ Singleton {
return
}
if (vpnProfiles.length > 0) {
connectVpn(vpnProfiles[0].uuid)
if (vpnConnected) {
disconnectAllVpns()
return
}
const targetUuid = lastConnectedVpnUuid || (vpnProfiles.length > 0 ? vpnProfiles[0].uuid : "")
if (targetUuid) {
connectVpn(targetUuid)
}
}

View File

@@ -47,6 +47,7 @@ Item {
"yaml": "\u{e8eb}",
"yml": "\u{e8eb}",
"xml": "\u{F09EE}",
"sql": "\u{f1c0}",
// --- scripts / shells ---
"sh": "\u{F08A9}",