diff --git a/Modules/ControlCenter/ControlCenterPopout.qml b/Modules/ControlCenter/ControlCenterPopout.qml index 5928dec3..c23271f4 100644 --- a/Modules/ControlCenter/ControlCenterPopout.qml +++ b/Modules/ControlCenter/ControlCenterPopout.qml @@ -651,15 +651,32 @@ DankPopout { width: (parent.width - Theme.spacingM) / 2 expanded: root.expandedSection === "network" onClicked: { + if (NetworkService.wifiToggling) { + return + } if (NetworkService.networkStatus === "ethernet") { - if (NetworkService.ethernetConnected && NetworkService.wifiConnected) { - NetworkService.setNetworkPreference("wifi") + if (NetworkService.ethernetConnected && !NetworkService.wifiEnabled) { + NetworkService.toggleWifiRadio() return } root.toggleSection("network") return } - NetworkService.disconnectWifi() + if (NetworkService.networkStatus === "wifi") { + if (NetworkService.ethernetConnected) { + NetworkService.toggleWifiRadio() + return + } + NetworkService.disconnectWifi() + return + } + if (!NetworkService.wifiEnabled) { + NetworkService.toggleWifiRadio() + return + } + if (NetworkService.wifiEnabled && NetworkService.networkStatus === "disconnected") { + root.toggleSection("network") + } } onExpandClicked: root.toggleSection("network") } diff --git a/Modules/ControlCenter/Details/NetworkDetail.qml b/Modules/ControlCenter/Details/NetworkDetail.qml index 59701864..32070202 100644 --- a/Modules/ControlCenter/Details/NetworkDetail.qml +++ b/Modules/ControlCenter/Details/NetworkDetail.qml @@ -7,7 +7,15 @@ import qs.Widgets import qs.Modals Rectangle { - implicitHeight: NetworkService.wifiEnabled ? headerRow.height + wifiContent.height + Theme.spacingM : headerRow.height + implicitHeight: { + if (NetworkService.wifiToggling) { + return headerRow.height + wifiToggleContent.height + Theme.spacingM + } + if (NetworkService.wifiEnabled) { + return headerRow.height + wifiContent.height + Theme.spacingM + } + return headerRow.height + wifiOffContent.height + Theme.spacingM + } radius: Theme.cornerRadius color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) @@ -129,6 +137,111 @@ Rectangle { } } + Item { + id: wifiToggleContent + anchors.top: headerRow.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: Theme.spacingM + anchors.topMargin: Theme.spacingM + visible: NetworkService.wifiToggling + height: visible ? 80 : 0 + + Column { + anchors.centerIn: parent + spacing: Theme.spacingM + + DankIcon { + anchors.horizontalCenter: parent.horizontalCenter + name: "sync" + size: 32 + color: Theme.primary + + RotationAnimation on rotation { + running: NetworkService.wifiToggling + loops: Animation.Infinite + from: 0 + to: 360 + duration: 1000 + } + } + + StyledText { + anchors.horizontalCenter: parent.horizontalCenter + text: NetworkService.wifiEnabled ? "Disabling WiFi..." : "Enabling WiFi..." + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceText + horizontalAlignment: Text.AlignHCenter + } + } + } + + Item { + id: wifiOffContent + anchors.top: headerRow.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: Theme.spacingM + anchors.topMargin: Theme.spacingM + visible: !NetworkService.wifiEnabled && !NetworkService.wifiToggling + height: visible ? 120 : 0 + + Column { + anchors.centerIn: parent + spacing: Theme.spacingL + width: parent.width + + DankIcon { + anchors.horizontalCenter: parent.horizontalCenter + name: "wifi_off" + size: 48 + color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) + } + + StyledText { + anchors.horizontalCenter: parent.horizontalCenter + text: "WiFi is off" + font.pixelSize: Theme.fontSizeLarge + color: Theme.surfaceText + font.weight: Font.Medium + horizontalAlignment: Text.AlignHCenter + } + + Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + width: 120 + height: 36 + radius: 18 + color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) + border.width: 1 + border.color: Theme.primary + + StyledText { + anchors.centerIn: parent + text: "Enable WiFi" + color: Theme.primary + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.Medium + } + + MouseArea { + id: enableWifiButton + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: NetworkService.toggleWifiRadio() + } + + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + } + } + } + DankFlickable { id: wifiContent anchors.top: headerRow.bottom @@ -137,7 +250,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.margins: Theme.spacingM anchors.topMargin: Theme.spacingM - visible: NetworkService.wifiInterface + visible: NetworkService.wifiInterface && NetworkService.wifiEnabled && !NetworkService.wifiToggling contentHeight: wifiColumn.height clip: true @@ -149,7 +262,7 @@ Rectangle { Item { width: parent.width height: 200 - visible: NetworkService.wifiInterface && NetworkService.wifiNetworks?.length < 1 + visible: NetworkService.wifiInterface && NetworkService.wifiNetworks?.length < 1 && !NetworkService.wifiToggling DankIcon { anchors.centerIn: parent diff --git a/Modules/ControlCenter/Widgets/NetworkPill.qml b/Modules/ControlCenter/Widgets/NetworkPill.qml index 98d97aa6..51a673eb 100644 --- a/Modules/ControlCenter/Widgets/NetworkPill.qml +++ b/Modules/ControlCenter/Widgets/NetworkPill.qml @@ -9,9 +9,23 @@ import qs.Modules.ControlCenter.Widgets BasePill { id: root - isActive: NetworkService.networkStatus !== "disconnected" + isActive: { + if (NetworkService.wifiToggling) { + return false + } + if (NetworkService.networkStatus === "ethernet") { + return true + } + if (NetworkService.networkStatus === "wifi") { + return true + } + return NetworkService.wifiEnabled + } iconName: { + if (NetworkService.wifiToggling) { + return "sync" + } if (NetworkService.networkStatus === "ethernet") { return "settings_ethernet" } @@ -25,6 +39,9 @@ BasePill { } primaryText: { + if (NetworkService.wifiToggling) { + return NetworkService.wifiEnabled ? "Disabling WiFi..." : "Enabling WiFi..." + } if (NetworkService.networkStatus === "ethernet") { return "Ethernet" } @@ -38,6 +55,9 @@ BasePill { } secondaryText: { + if (NetworkService.wifiToggling) { + return "Please wait..." + } if (NetworkService.networkStatus === "ethernet") { return "Connected" } diff --git a/Modules/TopBar/ControlCenterButton.qml b/Modules/TopBar/ControlCenterButton.qml index 25e99912..00dff339 100644 --- a/Modules/TopBar/ControlCenterButton.qml +++ b/Modules/TopBar/ControlCenterButton.qml @@ -41,15 +41,27 @@ Rectangle { DankIcon { id: networkIcon name: { + if (NetworkService.wifiToggling) + return "sync" if (NetworkService.networkStatus === "ethernet") return "lan" return NetworkService.wifiSignalIcon } size: Theme.iconSize - 8 - color: NetworkService.networkStatus - !== "disconnected" ? Theme.primary : Theme.outlineButton + color: { + if (NetworkService.wifiToggling) return Theme.primary + return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton + } anchors.verticalCenter: parent.verticalCenter visible: root.showNetworkIcon + + RotationAnimation on rotation { + running: NetworkService.wifiToggling + loops: Animation.Infinite + from: 0 + to: 360 + duration: 1000 + } } DankIcon { diff --git a/Services/NightModeAutomationService.qml b/Services/NightModeAutomationService.qml index bb71bb34..ffeb075d 100644 --- a/Services/NightModeAutomationService.qml +++ b/Services/NightModeAutomationService.qml @@ -94,13 +94,12 @@ Singleton { gammaStepProcess.processType = "automation" if (latitude !== 0.0 && longitude !== 0.0) { - gammaStepProcess.command = [ - "gammastep", + gammaStepProcess.command = buildGammastepCommand([ "-m", "wayland", "-l", `${latitude.toFixed(6)}:${longitude.toFixed(6)}`, "-t", `${dayTemp}:${temperature}`, "-v" - ] + ]) gammaStepProcess.running = true return } @@ -114,9 +113,17 @@ Singleton { } if (currentProvider === "geoclue2") { - // Kill existing processes and start new one in the onExited callback - pkillProcess.pendingLocationBasedStart = true - pkillProcess.running = true + const temperature = SessionData.nightModeTemperature || 4500 + const dayTemp = 6500 + + gammaStepProcess.processType = "automation" + gammaStepProcess.command = buildGammastepCommand([ + "-m", "wayland", + "-l", "geoclue2", + "-t", `${dayTemp}:${temperature}`, + "-v" + ]) + gammaStepProcess.running = true return } else { console.warn("NightModeAutomationService: No working location provider, falling back to time-based mode") @@ -170,11 +177,10 @@ Singleton { gammaStepProcess.running = false gammaStepProcess.processType = "activate" - gammaStepProcess.command = [ - "gammastep", + gammaStepProcess.command = buildGammastepCommand([ "-m", "wayland", "-O", String(temperature) - ] + ]) gammaStepProcess.running = true if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode !== "manual") { @@ -186,11 +192,10 @@ Singleton { gammaStepProcess.running = false gammaStepProcess.processType = "reset" - gammaStepProcess.command = [ - "gammastep", + gammaStepProcess.command = buildGammastepCommand([ "-m", "wayland", "-O", "6500" - ] + ]) gammaStepProcess.running = true if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode !== "manual") { @@ -222,6 +227,11 @@ Singleton { } } + function buildGammastepCommand(gammastepArgs) { + const commandStr = "pkill gammastep; " + ["gammastep"].concat(gammastepArgs).join(" ") + return ["sh", "-c", commandStr] + } + function updateFromSessionData() { if (SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) { @@ -243,11 +253,10 @@ Singleton { gammaStepProcess.running = false gammaStepProcess.processType = "test" - gammaStepProcess.command = [ - "gammastep", + gammaStepProcess.command = buildGammastepCommand([ "-m", "wayland", "-O", String(temperature) - ] + ]) gammaStepProcess.running = true testFeedbackTimer.interval = 2000 @@ -258,11 +267,10 @@ Singleton { function manualResetTest() { gammaStepProcess.running = false gammaStepProcess.processType = "test" - gammaStepProcess.command = [ - "gammastep", + gammaStepProcess.command = buildGammastepCommand([ "-m", "wayland", "-O", "6500" - ] + ]) gammaStepProcess.running = true testFeedbackTimer.interval = 2000 @@ -280,34 +288,6 @@ Singleton { } } - - Process { - id: pkillProcess - command: ["killall", "-w", "gammastep"] - running: false - - property bool pendingLocationBasedStart: false - - onExited: function(exitCode) { - if (pendingLocationBasedStart) { - pendingLocationBasedStart = false - - const temperature = SessionData.nightModeTemperature || 4500 - const dayTemp = 6500 - - gammaStepProcess.processType = "automation" - gammaStepProcess.command = [ - "gammastep", - "-m", "wayland", - "-l", "geoclue2", - "-t", `${dayTemp}:${temperature}`, - "-v" - ] - gammaStepProcess.running = true - } - } - } - Process { id: gammaStepTestProcess command: ["which", "gammastep"] @@ -374,13 +354,12 @@ Singleton { const dayTemp = 6500 gammaStepProcess.processType = "automation" - gammaStepProcess.command = [ - "gammastep", + gammaStepProcess.command = buildGammastepCommand([ "-m", "wayland", "-l", "geoclue2", "-t", `${dayTemp}:${temperature}`, "-v" - ] + ]) gammaStepProcess.running = true } else { SessionData.setNightModeAutoMode("time")