1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

network: big feature enrichment

- Dedicated view in settings
- VPN profile management
- Ethernet disconnection
- Turn prompts into floating windows
This commit is contained in:
bbedward
2025-11-29 10:00:05 -05:00
parent 9c887fbe63
commit 1d3fe81ff7
51 changed files with 9807 additions and 2500 deletions

View File

@@ -18,6 +18,7 @@ Singleton {
property string ethernetInterface: ""
property bool ethernetConnected: false
property string ethernetConnectionUuid: ""
property var ethernetDevices: []
property var wiredConnections: []
@@ -116,7 +117,7 @@ Singleton {
signal networksUpdated
signal connectionChanged
signal credentialsNeeded(string token, string ssid, string setting, var fields, var hints, string reason, string connType, string connName, string vpnService)
signal credentialsNeeded(string token, string ssid, string setting, var fields, var hints, string reason, string connType, string connName, string vpnService, var fieldsInfo)
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
@@ -197,8 +198,9 @@ Singleton {
const connType = data.connType || "";
const connName = data.name || data.connectionId || "";
const vpnService = data.vpnService || "";
const fInfo = data.fieldsInfo || [];
credentialsNeeded(credentialsToken, credentialsSSID, credentialsSetting, credentialsFields, credentialsHints, credentialsReason, connType, connName, vpnService);
credentialsNeeded(credentialsToken, credentialsSSID, credentialsSetting, credentialsFields, credentialsHints, credentialsReason, connType, connName, vpnService, fInfo);
}
function addRef() {
@@ -244,6 +246,7 @@ Singleton {
ethernetInterface = state.ethernetDevice || "";
ethernetConnected = state.ethernetConnected || false;
ethernetConnectionUuid = state.ethernetConnectionUuid || "";
ethernetDevices = state.ethernetDevices || [];
wiredConnections = state.wiredConnections || [];
@@ -618,7 +621,7 @@ Singleton {
if (!networkAvailable)
return;
if (type === "ethernet") {
if (networkStatus === "ethernet") {
if (ethernetConnected) {
DMSService.sendRequest("network.ethernet.disconnect", null, null);
} else {
DMSService.sendRequest("network.ethernet.connect", null, null);
@@ -626,6 +629,14 @@ Singleton {
}
}
function disconnectEthernetDevice(deviceName) {
if (!networkAvailable)
return;
DMSService.sendRequest("network.ethernet.disconnect", {
device: deviceName
}, null);
}
function startAutoScan() {
autoScan = true;
autoRefreshEnabled = true;

View File

@@ -176,15 +176,6 @@ Singleton {
}
}
Connections {
target: SessionService
function onPrepareForSleep() {
if (SettingsData.lockBeforeSuspend) {
root.lockRequested();
}
}
}
Connections {
target: SettingsData
function onPreventIdleForMediaChanged() {

View File

@@ -16,6 +16,7 @@ Singleton {
property string ethernetInterface: activeService?.ethernetInterface ?? ""
property bool ethernetConnected: activeService?.ethernetConnected ?? false
property string ethernetConnectionUuid: activeService?.ethernetConnectionUuid ?? ""
property var ethernetDevices: activeService?.ethernetDevices ?? []
property var wiredConnections: activeService?.wiredConnections ?? []
@@ -88,7 +89,7 @@ Singleton {
signal networksUpdated
signal connectionChanged
signal credentialsNeeded(string token, string ssid, string setting, var fields, var hints, string reason, string connType, string connName, string vpnService)
signal credentialsNeeded(string token, string ssid, string setting, var fields, var hints, string reason, string connType, string connName, string vpnService, var fieldsInfo)
property bool usingLegacy: false
property var activeService: null
@@ -230,6 +231,12 @@ Singleton {
}
}
function disconnectEthernetDevice(deviceName) {
if (activeService && activeService.disconnectEthernetDevice) {
activeService.disconnectEthernetDevice(deviceName);
}
}
function startAutoScan() {
if (activeService && activeService.startAutoScan) {
activeService.startAutoScan();

View File

@@ -1,7 +1,7 @@
import QtQuick
import Quickshell
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
Singleton {
id: root
@@ -23,6 +23,7 @@ Singleton {
property var colorPickerModal: null
property var notificationModal: null
property var wifiPasswordModal: null
property var polkitAuthModal: null
property var bluetoothPairingModal: null
property var networkInfoModal: null
@@ -30,267 +31,267 @@ Singleton {
function setPosition(popout, x, y, width, section, screen) {
if (popout && popout.setTriggerPosition && arguments.length >= 6) {
popout.setTriggerPosition(x, y, width, section, screen)
popout.setTriggerPosition(x, y, width, section, screen);
}
}
function openControlCenter(x, y, width, section, screen) {
if (controlCenterPopout) {
setPosition(controlCenterPopout, x, y, width, section, screen)
controlCenterPopout.open()
setPosition(controlCenterPopout, x, y, width, section, screen);
controlCenterPopout.open();
}
}
function closeControlCenter() {
controlCenterPopout?.close()
controlCenterPopout?.close();
}
function toggleControlCenter(x, y, width, section, screen) {
if (controlCenterPopout) {
setPosition(controlCenterPopout, x, y, width, section, screen)
controlCenterPopout.toggle()
setPosition(controlCenterPopout, x, y, width, section, screen);
controlCenterPopout.toggle();
}
}
function openNotificationCenter(x, y, width, section, screen) {
if (notificationCenterPopout) {
setPosition(notificationCenterPopout, x, y, width, section, screen)
notificationCenterPopout.open()
setPosition(notificationCenterPopout, x, y, width, section, screen);
notificationCenterPopout.open();
}
}
function closeNotificationCenter() {
notificationCenterPopout?.close()
notificationCenterPopout?.close();
}
function toggleNotificationCenter(x, y, width, section, screen) {
if (notificationCenterPopout) {
setPosition(notificationCenterPopout, x, y, width, section, screen)
notificationCenterPopout.toggle()
setPosition(notificationCenterPopout, x, y, width, section, screen);
notificationCenterPopout.toggle();
}
}
function openAppDrawer(x, y, width, section, screen) {
if (appDrawerPopout) {
setPosition(appDrawerPopout, x, y, width, section, screen)
appDrawerPopout.open()
setPosition(appDrawerPopout, x, y, width, section, screen);
appDrawerPopout.open();
}
}
function closeAppDrawer() {
appDrawerPopout?.close()
appDrawerPopout?.close();
}
function toggleAppDrawer(x, y, width, section, screen) {
if (appDrawerPopout) {
setPosition(appDrawerPopout, x, y, width, section, screen)
appDrawerPopout.toggle()
setPosition(appDrawerPopout, x, y, width, section, screen);
appDrawerPopout.toggle();
}
}
function openProcessList(x, y, width, section, screen) {
if (processListPopout) {
setPosition(processListPopout, x, y, width, section, screen)
processListPopout.open()
setPosition(processListPopout, x, y, width, section, screen);
processListPopout.open();
}
}
function closeProcessList() {
processListPopout?.close()
processListPopout?.close();
}
function toggleProcessList(x, y, width, section, screen) {
if (processListPopout) {
setPosition(processListPopout, x, y, width, section, screen)
processListPopout.toggle()
setPosition(processListPopout, x, y, width, section, screen);
processListPopout.toggle();
}
}
function openDankDash(tabIndex, x, y, width, section, screen) {
if (dankDashPopout) {
if (arguments.length >= 6) {
setPosition(dankDashPopout, x, y, width, section, screen)
setPosition(dankDashPopout, x, y, width, section, screen);
}
dankDashPopout.currentTabIndex = tabIndex || 0
dankDashPopout.dashVisible = true
dankDashPopout.currentTabIndex = tabIndex || 0;
dankDashPopout.dashVisible = true;
}
}
function closeDankDash() {
if (dankDashPopout) {
dankDashPopout.dashVisible = false
dankDashPopout.dashVisible = false;
}
}
function toggleDankDash(tabIndex, x, y, width, section, screen) {
if (dankDashPopout) {
if (arguments.length >= 6) {
setPosition(dankDashPopout, x, y, width, section, screen)
setPosition(dankDashPopout, x, y, width, section, screen);
}
if (dankDashPopout.dashVisible) {
dankDashPopout.dashVisible = false
dankDashPopout.dashVisible = false;
} else {
dankDashPopout.currentTabIndex = tabIndex || 0
dankDashPopout.dashVisible = true
dankDashPopout.currentTabIndex = tabIndex || 0;
dankDashPopout.dashVisible = true;
}
}
}
function openBattery(x, y, width, section, screen) {
if (batteryPopout) {
setPosition(batteryPopout, x, y, width, section, screen)
batteryPopout.open()
setPosition(batteryPopout, x, y, width, section, screen);
batteryPopout.open();
}
}
function closeBattery() {
batteryPopout?.close()
batteryPopout?.close();
}
function toggleBattery(x, y, width, section, screen) {
if (batteryPopout) {
setPosition(batteryPopout, x, y, width, section, screen)
batteryPopout.toggle()
setPosition(batteryPopout, x, y, width, section, screen);
batteryPopout.toggle();
}
}
function openVpn(x, y, width, section, screen) {
if (vpnPopout) {
setPosition(vpnPopout, x, y, width, section, screen)
vpnPopout.open()
setPosition(vpnPopout, x, y, width, section, screen);
vpnPopout.open();
}
}
function closeVpn() {
vpnPopout?.close()
vpnPopout?.close();
}
function toggleVpn(x, y, width, section, screen) {
if (vpnPopout) {
setPosition(vpnPopout, x, y, width, section, screen)
vpnPopout.toggle()
setPosition(vpnPopout, x, y, width, section, screen);
vpnPopout.toggle();
}
}
function openSystemUpdate(x, y, width, section, screen) {
if (systemUpdatePopout) {
setPosition(systemUpdatePopout, x, y, width, section, screen)
systemUpdatePopout.open()
setPosition(systemUpdatePopout, x, y, width, section, screen);
systemUpdatePopout.open();
}
}
function closeSystemUpdate() {
systemUpdatePopout?.close()
systemUpdatePopout?.close();
}
function toggleSystemUpdate(x, y, width, section, screen) {
if (systemUpdatePopout) {
setPosition(systemUpdatePopout, x, y, width, section, screen)
systemUpdatePopout.toggle()
setPosition(systemUpdatePopout, x, y, width, section, screen);
systemUpdatePopout.toggle();
}
}
function openSettings() {
settingsModal?.show()
settingsModal?.show();
}
function closeSettings() {
settingsModal?.close()
settingsModal?.close();
}
function openClipboardHistory() {
clipboardHistoryModal?.show()
clipboardHistoryModal?.show();
}
function closeClipboardHistory() {
clipboardHistoryModal?.close()
clipboardHistoryModal?.close();
}
function openSpotlight() {
spotlightModal?.show()
spotlightModal?.show();
}
function closeSpotlight() {
spotlightModal?.close()
spotlightModal?.close();
}
function openPowerMenu() {
powerMenuModal?.openCentered()
powerMenuModal?.openCentered();
}
function closePowerMenu() {
powerMenuModal?.close()
powerMenuModal?.close();
}
function togglePowerMenu() {
if (powerMenuModal) {
if (powerMenuModal.shouldBeVisible) {
powerMenuModal.close()
powerMenuModal.close();
} else {
powerMenuModal.openCentered()
powerMenuModal.openCentered();
}
}
}
function showProcessListModal() {
processListModal?.show()
processListModal?.show();
}
function hideProcessListModal() {
processListModal?.hide()
processListModal?.hide();
}
function toggleProcessListModal() {
processListModal?.toggle()
processListModal?.toggle();
}
function showColorPicker() {
colorPickerModal?.show()
colorPickerModal?.show();
}
function hideColorPicker() {
colorPickerModal?.close()
colorPickerModal?.close();
}
function showNotificationModal() {
notificationModal?.show()
notificationModal?.show();
}
function hideNotificationModal() {
notificationModal?.close()
notificationModal?.close();
}
function showWifiPasswordModal() {
wifiPasswordModal?.show()
wifiPasswordModal?.show();
}
function hideWifiPasswordModal() {
wifiPasswordModal?.close()
wifiPasswordModal?.hide();
}
function showNetworkInfoModal() {
networkInfoModal?.show()
networkInfoModal?.show();
}
function hideNetworkInfoModal() {
networkInfoModal?.close()
networkInfoModal?.close();
}
function openNotepad() {
if (notepadSlideouts.length > 0) {
notepadSlideouts[0]?.show()
notepadSlideouts[0]?.show();
}
}
function closeNotepad() {
if (notepadSlideouts.length > 0) {
notepadSlideouts[0]?.hide()
notepadSlideouts[0]?.hide();
}
}
function toggleNotepad() {
if (notepadSlideouts.length > 0) {
notepadSlideouts[0]?.toggle()
notepadSlideouts[0]?.toggle();
}
}
}

View File

@@ -0,0 +1,220 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Common
Singleton {
id: root
readonly property bool available: DMSNetworkService.vpnAvailable
property var plugins: []
property var allExtensions: []
property bool importing: false
property string importError: ""
property var editConfig: null
property bool configLoading: false
property bool pluginsLoading: false
signal importComplete(string uuid, string name)
signal configLoaded(var config)
signal configUpdated
signal vpnDeleted(string uuid)
Component.onCompleted: {
if (available) {
fetchPlugins();
}
}
Connections {
target: DMSNetworkService
function onVpnAvailableChanged() {
if (DMSNetworkService.vpnAvailable && plugins.length === 0) {
fetchPlugins();
}
}
}
function fetchPlugins() {
if (!available || pluginsLoading)
return;
pluginsLoading = true;
DMSService.sendRequest("network.vpn.plugins", null, response => {
pluginsLoading = false;
if (response.error) {
console.warn("VPNService: Failed to fetch plugins:", response.error);
return;
}
if (!response.result)
return;
plugins = response.result;
const extSet = new Set();
for (const plugin of response.result) {
for (const ext of plugin.fileExtensions || []) {
extSet.add(ext);
}
}
allExtensions = Array.from(extSet);
});
}
function importVpn(filePath, name = "") {
if (!available || importing)
return;
importing = true;
importError = "";
const params = {
file: filePath
};
if (name)
params.name = name;
DMSService.sendRequest("network.vpn.import", params, response => {
importing = false;
if (response.error) {
importError = response.error;
ToastService.showError(I18n.tr("Failed to import VPN"));
return;
}
if (!response.result)
return;
if (response.result.success) {
ToastService.showInfo(I18n.tr("VPN imported: ") + (response.result.name || ""));
DMSNetworkService.refreshVpnProfiles();
importComplete(response.result.uuid || "", response.result.name || "");
return;
}
importError = response.result.error || "Import failed";
ToastService.showError(importError);
});
}
function getConfig(uuidOrName) {
if (!available)
return;
configLoading = true;
editConfig = null;
DMSService.sendRequest("network.vpn.getConfig", {
uuid: uuidOrName
}, response => {
configLoading = false;
if (response.error) {
ToastService.showError(I18n.tr("Failed to load VPN config"));
return;
}
if (response.result) {
editConfig = response.result;
configLoaded(response.result);
}
});
}
function updateConfig(uuid, updates) {
if (!available)
return;
const params = {
uuid: uuid
};
if (updates.name !== undefined)
params.name = updates.name;
if (updates.autoconnect !== undefined)
params.autoconnect = updates.autoconnect;
if (updates.data !== undefined)
params.data = updates.data;
DMSService.sendRequest("network.vpn.updateConfig", params, response => {
if (response.error) {
ToastService.showError(I18n.tr("Failed to update VPN"));
return;
}
ToastService.showInfo(I18n.tr("VPN configuration updated"));
DMSNetworkService.refreshVpnProfiles();
configUpdated();
});
}
function deleteVpn(uuidOrName) {
if (!available)
return;
DMSService.sendRequest("network.vpn.delete", {
uuid: uuidOrName
}, response => {
if (response.error) {
ToastService.showError(I18n.tr("Failed to delete VPN"));
return;
}
ToastService.showInfo(I18n.tr("VPN deleted"));
DMSNetworkService.refreshVpnProfiles();
vpnDeleted(uuidOrName);
});
}
function getFileFilter() {
if (allExtensions.length === 0) {
return ["*.ovpn", "*.conf"];
}
return allExtensions.map(e => "*" + e);
}
function getExtensionsForPlugin(serviceType) {
const plugin = plugins.find(p => p.serviceType === serviceType);
if (!plugin)
return ["*.conf"];
return (plugin.fileExtensions || [".conf"]).map(e => "*" + e);
}
function getPluginName(serviceType) {
if (!serviceType)
return "VPN";
const plugin = plugins.find(p => p.serviceType === serviceType);
if (plugin)
return plugin.name;
const svc = serviceType.toLowerCase();
if (svc.includes("openvpn"))
return "OpenVPN";
if (svc.includes("wireguard"))
return "WireGuard";
if (svc.includes("openconnect"))
return "OpenConnect";
if (svc.includes("fortissl") || svc.includes("forti"))
return "Fortinet";
if (svc.includes("strongswan"))
return "IPsec (strongSwan)";
if (svc.includes("libreswan"))
return "IPsec (Libreswan)";
if (svc.includes("l2tp"))
return "L2TP/IPsec";
if (svc.includes("pptp"))
return "PPTP";
if (svc.includes("vpnc"))
return "Cisco (vpnc)";
if (svc.includes("sstp"))
return "SSTP";
const parts = serviceType.split('.');
return parts[parts.length - 1] || "VPN";
}
function getVpnTypeFromProfile(profile) {
if (!profile)
return "VPN";
if (profile.type === "wireguard")
return "WireGuard";
return getPluginName(profile.serviceType);
}
}