Merge branch 'rebuild' of github.com:Ly-sec/Noctalia into rebuild

This commit is contained in:
quadbyte 2025-08-15 10:23:18 -04:00
commit 13df665f94
2 changed files with 405 additions and 204 deletions

View file

@ -41,7 +41,9 @@ NLoader {
// Also handle visibility changes from external sources // Also handle visibility changes from external sources
onVisibleChanged: { onVisibleChanged: {
if (!visible && wifiMenuRect.opacityValue > 0) { if (visible && Settings.data.network.wifiEnabled) {
network.refreshNetworks()
} else if (wifiMenuRect.opacityValue > 0) {
// Start hide animation // Start hide animation
wifiMenuRect.scaleValue = 0.8 wifiMenuRect.scaleValue = 0.8
wifiMenuRect.opacityValue = 0.0 wifiMenuRect.opacityValue = 0.0
@ -65,6 +67,22 @@ NLoader {
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
Network {
id: network
}
// Timer to refresh networks when WiFi is enabled while menu is open
Timer {
id: wifiEnableRefreshTimer
interval: 3000 // Wait 3 seconds for WiFi to be fully ready
repeat: false
onTriggered: {
if (Settings.data.network.wifiEnabled && wifiPanel.visible) {
network.refreshNetworks()
}
}
}
Rectangle { Rectangle {
id: wifiMenuRect id: wifiMenuRect
color: Colors.mSurface color: Colors.mSurface
@ -135,14 +153,19 @@ NLoader {
value: Settings.data.network.wifiEnabled value: Settings.data.network.wifiEnabled
onToggled: function (value) { onToggled: function (value) {
Settings.data.network.wifiEnabled = value Settings.data.network.wifiEnabled = value
// TBC: This should be done in a service network.setWifiEnabled(value)
Quickshell.execDetached(["nmcli", "radio", "wifi", Settings.data.network.wifiEnabled ? "on" : "off"])
// If enabling WiFi while menu is open, refresh after a delay
if (value) {
wifiEnableRefreshTimer.start()
}
} }
} }
NIconButton { NIconButton {
icon: "refresh" icon: "refresh"
sizeMultiplier: 0.8 sizeMultiplier: 0.8
enabled: Settings.data.network.wifiEnabled && !network.isLoading
onClicked: { onClicked: {
network.refreshNetworks() network.refreshNetworks()
} }
@ -159,10 +182,65 @@ NLoader {
NDivider {} NDivider {}
ListView { Item {
id: networkList
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
// Loading indicator
ColumnLayout {
anchors.centerIn: parent
visible: Settings.data.network.wifiEnabled && network.isLoading
spacing: Style.marginMedium * scaling
NBusyIndicator {
running: network.isLoading
color: Colors.mPrimary
size: Style.baseWidgetSize * scaling
Layout.alignment: Qt.AlignHCenter
}
NText {
text: "Scanning for networks..."
font.pointSize: Style.fontSizeNormal * scaling
color: Colors.mOnSurfaceVariant
Layout.alignment: Qt.AlignHCenter
}
}
// WiFi disabled message
ColumnLayout {
anchors.centerIn: parent
visible: !Settings.data.network.wifiEnabled
spacing: Style.marginMedium * scaling
NText {
text: "wifi_off"
font.family: "Material Symbols Outlined"
font.pointSize: Style.fontSizeXXL * scaling
color: Colors.mOnSurfaceVariant
Layout.alignment: Qt.AlignHCenter
}
NText {
text: "WiFi is disabled"
font.pointSize: Style.fontSizeLarge * scaling
color: Colors.mOnSurfaceVariant
Layout.alignment: Qt.AlignHCenter
}
NText {
text: "Enable WiFi to see available networks"
font.pointSize: Style.fontSizeNormal * scaling
color: Colors.mOnSurfaceVariant
Layout.alignment: Qt.AlignHCenter
}
}
// Network list
ListView {
id: networkList
anchors.fill: parent
visible: Settings.data.network.wifiEnabled && !network.isLoading
model: Object.values(network.networks) model: Object.values(network.networks)
spacing: Style.marginMedium * scaling spacing: Style.marginMedium * scaling
clip: true clip: true
@ -388,4 +466,5 @@ NLoader {
} }
} }
} }
}
} }

View file

@ -1,4 +1,5 @@
import QtQuick import QtQuick
import Quickshell
import Quickshell.Io import Quickshell.Io
QtObject { QtObject {
@ -10,6 +11,8 @@ QtObject {
property string connectStatusSsid: "" property string connectStatusSsid: ""
property string connectError: "" property string connectError: ""
property string detectedInterface: "" property string detectedInterface: ""
property string lastConnectedNetwork: ""
property bool isLoading: false
function signalIcon(signal) { function signalIcon(signal) {
if (signal >= 80) if (signal >= 80)
@ -28,9 +31,29 @@ QtObject {
} }
function refreshNetworks() { function refreshNetworks() {
isLoading = true
existingNetwork.running = true existingNetwork.running = true
} }
function setWifiEnabled(enabled) {
if (enabled) {
// Enable WiFi radio
isLoading = true
enableWifiProcess.running = true
} else {
// Store the currently connected network before disabling
for (const ssid in networks) {
if (networks[ssid].connected) {
lastConnectedNetwork = ssid
break
}
}
// Disable WiFi radio
disableWifiProcess.running = true
}
}
function connectNetwork(ssid, security) { function connectNetwork(ssid, security) {
pendingConnect = { pendingConnect = {
"ssid": ssid, "ssid": ssid,
@ -87,7 +110,7 @@ QtObject {
property int refreshInterval: 25000 property int refreshInterval: 25000
// Only refresh when we have an active connection // Only refresh when we have an active connection and WiFi is enabled
property bool hasActiveConnection: { property bool hasActiveConnection: {
for (const net in networks) { for (const net in networks) {
if (networks[net].connected) { if (networks[net].connected) {
@ -99,18 +122,111 @@ QtObject {
property Timer refreshTimer: Timer { property Timer refreshTimer: Timer {
interval: root.refreshInterval interval: root.refreshInterval
// Only run timer when we're connected to a network // Only run timer when we're connected to a network and WiFi is enabled
running: root.hasActiveConnection running: root.hasActiveConnection && Settings.data.network.wifiEnabled
repeat: true repeat: true
onTriggered: root.refreshNetworks() onTriggered: root.refreshNetworks()
} }
// Force a refresh when menu is opened // Force a refresh when menu is opened
function onMenuOpened() { function onMenuOpened() {
if (Settings.data.network.wifiEnabled) {
refreshNetworks() refreshNetworks()
} }
}
function onMenuClosed() {// No need to do anything special on close function onMenuClosed() {
// No need to do anything special on close
}
// Process to enable WiFi radio
property Process enableWifiProcess: Process {
id: enableWifiProcess
running: false
command: ["nmcli", "radio", "wifi", "on"]
onRunningChanged: {
if (!running) {
// Wait a moment for the radio to be enabled, then refresh networks
enableWifiDelayTimer.start()
}
}
stderr: StdioCollector {
onStreamFinished: {
if (text.trim() !== "") {
console.warn("Error enabling WiFi:", text)
}
}
}
}
// Timer to delay network refresh after enabling WiFi
property Timer enableWifiDelayTimer: Timer {
id: enableWifiDelayTimer
interval: 2000 // Wait 2 seconds for radio to be ready
repeat: false
onTriggered: {
// Force refresh networks multiple times to ensure UI updates
root.refreshNetworks()
// Try to auto-reconnect to the last connected network if it exists
if (lastConnectedNetwork) {
autoReconnectTimer.start()
}
// Set up additional refresh to ensure UI is populated
postEnableRefreshTimer.start()
}
}
// Additional timer to ensure networks are populated after enabling
property Timer postEnableRefreshTimer: Timer {
id: postEnableRefreshTimer
interval: 1000
repeat: false
onTriggered: {
root.refreshNetworks()
}
}
// Timer to attempt auto-reconnection to the last connected network
property Timer autoReconnectTimer: Timer {
id: autoReconnectTimer
interval: 3000 // Wait 3 seconds after scan for networks to be available
repeat: false
onTriggered: {
if (lastConnectedNetwork && networks[lastConnectedNetwork]) {
const network = networks[lastConnectedNetwork]
if (network.existing && !network.connected) {
upConnectionProcess.profileName = lastConnectedNetwork
upConnectionProcess.running = true
}
}
}
}
// Process to disable WiFi radio
property Process disableWifiProcess: Process {
id: disableWifiProcess
running: false
command: ["nmcli", "radio", "wifi", "off"]
onRunningChanged: {
if (!running) {
// Clear networks when WiFi is disabled
root.networks = ({})
root.connectingSsid = ""
root.connectStatus = ""
root.connectStatusSsid = ""
root.connectError = ""
root.isLoading = false
}
}
stderr: StdioCollector {
onStreamFinished: {
if (text.trim() !== "") {
console.warn("Error disabling WiFi:", text)
}
}
}
} }
property Process disconnectProfileProcess: Process { property Process disconnectProfileProcess: Process {
@ -211,6 +327,7 @@ QtObject {
} }
root.networks = networksMap root.networks = networksMap
root.isLoading = false
scanProcess.existingNetwork = {} scanProcess.existingNetwork = {}
} }
} }
@ -235,6 +352,7 @@ QtObject {
root.connectStatus = "success" root.connectStatus = "success"
root.connectStatusSsid = connectProcess.ssid root.connectStatusSsid = connectProcess.ssid
root.connectError = "" root.connectError = ""
root.lastConnectedNetwork = connectProcess.ssid
root.refreshNetworks() root.refreshNetworks()
} }
} }
@ -322,8 +440,9 @@ QtObject {
onStreamFinished: { onStreamFinished: {
root.connectingSsid = "" root.connectingSsid = ""
root.connectStatus = "success" root.connectStatus = "success"
root.connectStatusSsid = root.pendingConnect ? root.pendingConnect.ssid : "" root.connectStatusSsid = root.pendingConnect ? root.pendingConnect.ssid : profileName
root.connectError = "" root.connectError = ""
root.lastConnectedNetwork = profileName
root.pendingConnect = null root.pendingConnect = null
root.refreshNetworks() root.refreshNetworks()
} }
@ -332,7 +451,7 @@ QtObject {
onStreamFinished: { onStreamFinished: {
root.connectingSsid = "" root.connectingSsid = ""
root.connectStatus = "error" root.connectStatus = "error"
root.connectStatusSsid = root.pendingConnect ? root.pendingConnect.ssid : "" root.connectStatusSsid = root.pendingConnect ? root.pendingConnect.ssid : profileName
root.connectError = text root.connectError = text
root.pendingConnect = null root.pendingConnect = null
} }
@ -340,6 +459,9 @@ QtObject {
} }
Component.onCompleted: { Component.onCompleted: {
// Only refresh networks if WiFi is enabled
if (Settings.data.network.wifiEnabled) {
refreshNetworks() refreshNetworks()
} }
}
} }