mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-24 03:55:23 -04:00
fix(network): fix excessive network prompting on failures, add VPN
connection statuses
This commit is contained in:
@@ -689,23 +689,19 @@ Item {
|
||||
target: NetworkService
|
||||
|
||||
function onCredentialsNeeded(token, ssid, setting, fields, hints, reason, connType, connName, vpnService, fieldsInfo) {
|
||||
const now = Date.now();
|
||||
const timeSinceLastPrompt = now - lastCredentialsTime;
|
||||
const alreadyShown = wifiPasswordModalLoader.item && wifiPasswordModalLoader.item.shouldBeVisible;
|
||||
if (alreadyShown && token === lastCredentialsToken)
|
||||
return;
|
||||
|
||||
wifiPasswordModalLoader.active = true;
|
||||
if (!wifiPasswordModalLoader.item)
|
||||
return;
|
||||
|
||||
if (wifiPasswordModalLoader.item.shouldBeVisible && timeSinceLastPrompt < 1000) {
|
||||
if (alreadyShown && lastCredentialsToken !== "" && lastCredentialsToken !== token)
|
||||
NetworkService.cancelCredentials(lastCredentialsToken);
|
||||
lastCredentialsToken = token;
|
||||
lastCredentialsTime = now;
|
||||
wifiPasswordModalLoader.item.showFromPrompt(token, ssid, setting, fields, hints, reason, connType, connName, vpnService, fieldsInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
lastCredentialsToken = token;
|
||||
lastCredentialsTime = now;
|
||||
lastCredentialsTime = Date.now();
|
||||
wifiPasswordModalLoader.item.showFromPrompt(token, ssid, setting, fields, hints, reason, connType, connName, vpnService, fieldsInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,22 @@ PluginComponent {
|
||||
service: DMSNetworkService
|
||||
}
|
||||
|
||||
readonly property bool vpnActivating: DMSNetworkService.vpnIsBusy || DMSNetworkService.activeState === "activating"
|
||||
readonly property bool vpnActivated: DMSNetworkService.connected && DMSNetworkService.activeState === "activated"
|
||||
|
||||
ccWidgetIcon: "vpn_key"
|
||||
ccWidgetPrimaryText: I18n.tr("VPN")
|
||||
ccWidgetSecondaryText: {
|
||||
if (!DMSNetworkService.connected)
|
||||
if (vpnActivating)
|
||||
return I18n.tr("Connecting…");
|
||||
if (!vpnActivated)
|
||||
return I18n.tr("Disconnected");
|
||||
const names = DMSNetworkService.activeNames || [];
|
||||
if (names.length <= 1)
|
||||
return names[0] || I18n.tr("Connected");
|
||||
return names[0] + " +" + (names.length - 1);
|
||||
}
|
||||
ccWidgetIsActive: DMSNetworkService.connected
|
||||
ccWidgetIsActive: vpnActivated
|
||||
|
||||
onCcWidgetToggled: DMSNetworkService.toggleVpn()
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ Singleton {
|
||||
property string lastConnectedVpnUuid: ""
|
||||
property string pendingVpnUuid: ""
|
||||
property var vpnBusyStartTime: 0
|
||||
property string vpnError: ""
|
||||
property string vpnErrorUuid: ""
|
||||
|
||||
property var profiles: {
|
||||
const mergedProfiles = vpnProfiles ? vpnProfiles.slice() : [];
|
||||
@@ -137,6 +139,17 @@ Singleton {
|
||||
property alias isBusy: root.vpnIsBusy
|
||||
property alias connected: root.vpnConnected
|
||||
|
||||
function vpnStateForUuid(uuid) {
|
||||
if (!uuid)
|
||||
return "";
|
||||
const match = vpnActive.find(v => v.uuid === uuid);
|
||||
return match ? (match.state || "") : "";
|
||||
}
|
||||
|
||||
function isVpnConnectingUuid(uuid) {
|
||||
return vpnStateForUuid(uuid) === "activating" || (vpnIsBusy && pendingVpnUuid === uuid);
|
||||
}
|
||||
|
||||
property string networkInfoSSID: ""
|
||||
property string networkInfoDetails: ""
|
||||
property bool networkInfoLoading: false
|
||||
@@ -372,6 +385,17 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
const incomingVpnError = state.vpnError || "";
|
||||
if (incomingVpnError && incomingVpnError !== vpnError) {
|
||||
vpnIsBusy = false;
|
||||
pendingVpnUuid = "";
|
||||
vpnBusyStartTime = 0;
|
||||
const failedName = (vpnProfiles.find(p => p.uuid === state.vpnErrorUuid)?.name) || I18n.tr("VPN");
|
||||
ToastService.showError(I18n.tr("%1: %2").arg(failedName).arg(incomingVpnError));
|
||||
}
|
||||
vpnError = incomingVpnError;
|
||||
vpnErrorUuid = state.vpnErrorUuid || "";
|
||||
|
||||
isConnecting = state.isConnecting || false;
|
||||
connectingSSID = state.connectingSSID || "";
|
||||
connectionError = state.lastError || "";
|
||||
|
||||
@@ -25,6 +25,7 @@ Singleton {
|
||||
signal importComplete(string uuid, string name)
|
||||
signal configLoaded(var config)
|
||||
signal configUpdated
|
||||
signal credentialsSet(string uuid)
|
||||
signal vpnDeleted(string uuid)
|
||||
|
||||
Component.onCompleted: {
|
||||
@@ -149,6 +150,28 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function setCredentials(uuid, username, password, save = true) {
|
||||
if (!available)
|
||||
return;
|
||||
const params = {
|
||||
uuid: uuid,
|
||||
save: save
|
||||
};
|
||||
if (username)
|
||||
params.username = username;
|
||||
if (password)
|
||||
params.password = password;
|
||||
|
||||
DMSService.sendRequest("network.vpn.setCredentials", params, response => {
|
||||
if (response.error) {
|
||||
ToastService.showError(I18n.tr("Failed to save VPN credentials"), response.error);
|
||||
return;
|
||||
}
|
||||
ToastService.showInfo(I18n.tr("VPN credentials saved"));
|
||||
credentialsSet(uuid);
|
||||
});
|
||||
}
|
||||
|
||||
function deleteVpn(uuidOrName) {
|
||||
if (!available)
|
||||
return;
|
||||
|
||||
@@ -18,7 +18,9 @@ Rectangle {
|
||||
signal toggleExpand
|
||||
signal deleteRequested
|
||||
|
||||
readonly property bool isActive: DMSNetworkService.activeUuids?.includes(profile?.uuid) ?? false
|
||||
readonly property bool isActive: DMSNetworkService.vpnStateForUuid(profile?.uuid) === "activated"
|
||||
readonly property bool isConnecting: DMSNetworkService.isVpnConnectingUuid(profile?.uuid)
|
||||
readonly property bool hasError: !isConnecting && DMSNetworkService.vpnError !== "" && DMSNetworkService.vpnErrorUuid === (profile?.uuid ?? "")
|
||||
readonly property bool isHovered: rowArea.containsMouse || expandBtn.containsMouse || deleteBtn.containsMouse
|
||||
readonly property var configData: (!isTransient && isExpanded) ? VPNService.editConfig : null
|
||||
readonly property var configFields: buildConfigFields()
|
||||
@@ -28,7 +30,7 @@ Rectangle {
|
||||
color: isHovered ? Theme.primaryHoverLight : (isActive ? Theme.primaryPressed : Theme.surfaceLight)
|
||||
border.width: isActive ? 2 : 1
|
||||
border.color: isActive ? Theme.primary : Theme.outlineLight
|
||||
opacity: DMSNetworkService.isBusy ? 0.5 : 1.0
|
||||
opacity: (DMSNetworkService.isBusy && !isConnecting) ? 0.5 : 1.0
|
||||
clip: true
|
||||
|
||||
function buildConfigFields() {
|
||||
@@ -107,10 +109,20 @@ Rectangle {
|
||||
height: 46 - Theme.spacingS * 2
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankSpinner {
|
||||
size: 18
|
||||
strokeWidth: 2
|
||||
color: Theme.warning
|
||||
running: root.isConnecting
|
||||
visible: root.isConnecting
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: isActive ? "vpn_lock" : "vpn_key_off"
|
||||
visible: !root.isConnecting
|
||||
name: isActive ? "vpn_lock" : (root.hasError ? "error" : "vpn_key_off")
|
||||
size: 20
|
||||
color: isActive ? Theme.primary : Theme.surfaceText
|
||||
color: root.hasError ? Theme.error : (isActive ? Theme.primary : Theme.surfaceText)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
@@ -130,9 +142,9 @@ Rectangle {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: VPNService.getVpnTypeFromProfile(profile)
|
||||
text: root.isConnecting ? I18n.tr("Connecting...") : (root.hasError ? DMSNetworkService.vpnError : VPNService.getVpnTypeFromProfile(profile))
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceTextMedium
|
||||
color: root.isConnecting ? Theme.warning : (root.hasError ? Theme.error : Theme.surfaceTextMedium)
|
||||
wrapMode: Text.NoWrap
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
@@ -271,6 +283,45 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
visible: !isTransient && !VPNService.configLoading && profile?.type !== "wireguard"
|
||||
|
||||
StyledText {
|
||||
text: root.hasError ? DMSNetworkService.vpnError : I18n.tr("Credentials")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: root.hasError ? Theme.error : Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: usernameField
|
||||
width: parent.width
|
||||
placeholderText: I18n.tr("Username")
|
||||
text: (configData && (configData.username || (configData.data && configData.data.username))) || ""
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: passwordField
|
||||
width: parent.width
|
||||
placeholderText: I18n.tr("Password")
|
||||
echoMode: TextInput.Password
|
||||
showPasswordToggle: true
|
||||
normalBorderColor: root.hasError ? Theme.error : Theme.outlineMedium
|
||||
}
|
||||
|
||||
DankButton {
|
||||
text: I18n.tr("Save credentials")
|
||||
opacity: passwordField.text.length > 0 ? 1 : 0.5
|
||||
onClicked: {
|
||||
if (passwordField.text.length === 0)
|
||||
return;
|
||||
VPNService.setCredentials(profile.uuid, usernameField.text, passwordField.text, true);
|
||||
passwordField.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
height: Theme.spacingXS
|
||||
|
||||
Reference in New Issue
Block a user