From e1a1e4953d90d2c92ae9d6a6fece0fb333639fe7 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Mon, 14 Sep 2026 13:48:04 +0200 Subject: feat(desktop): network wifi page Radio switch, scan, and a list ordered connected, known, strongest. A secured unknown network reveals an inline password field rather than opening a popup, since a QtQuick.Controls popup is a separate window that positions badly on this layer surface, the same reason the sound page expands in place. Connection failures come through the Network.connectionFailed signal and show inline; the same failure also notifies, for the case where the drawer has closed by the time it lands. --- desktop/modules/network/NetworkRow.qml | 144 +++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 desktop/modules/network/NetworkRow.qml (limited to 'desktop/modules/network/NetworkRow.qml') diff --git a/desktop/modules/network/NetworkRow.qml b/desktop/modules/network/NetworkRow.qml new file mode 100644 index 0000000..34c134b --- /dev/null +++ b/desktop/modules/network/NetworkRow.qml @@ -0,0 +1,144 @@ +// Copyright (C) 2026 Danilo M. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +import Quickshell.Networking +import QtQuick +import "../.." + +// One wifi network. A row click connects; a secured unknown network reveals +// an inline password field instead. The click area is declared first so the +// buttons and the field, declared later, sit above it. +Rectangle { + id: row + + required property var net + required property var entry + property bool prompting: false + property string psk: "" + + implicitHeight: col.implicitHeight + 16 + radius: 8 + color: entry.connected ? Qt.alpha(Theme.accent, 0.10) : Qt.alpha(Theme.surface, 0.35) + + MouseArea { + anchors.fill: parent + enabled: !row.prompting + cursorShape: Qt.PointingHandCursor + onClicked: row.activate() + } + + Column { + id: col + anchors { left: parent.left; right: parent.right; top: parent.top; margins: 10 } + spacing: 8 + + Item { + width: parent.width + implicitHeight: Math.max(nameText.implicitHeight, actions.implicitHeight) + + Text { + id: nameText + anchors { left: parent.left; right: actions.left; rightMargin: 8; verticalCenter: parent.verticalCenter } + elide: Text.ElideRight + text: row.entry.name + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: row.entry.connected } + color: row.entry.connected ? Theme.accent : Theme.text + } + + Row { + id: actions + anchors { right: parent.right; verticalCenter: parent.verticalCenter } + spacing: 6 + + Text { + anchors.verticalCenter: parent.verticalCenter + visible: row.secured() + text: "\uf023" + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } + color: Theme.overlay + } + + Text { + anchors.verticalCenter: parent.verticalCenter + text: Math.round((row.entry.signalStrength ?? 0) * 100) + "%" + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } + color: Theme.overlay + } + + Button { + visible: row.entry.connected + text: "Disconnect" + onClicked: row.net.disconnectNetwork(row.entry) + } + + Button { + visible: !row.entry.connected && row.entry.known + text: "Forget" + danger: true + onClicked: row.net.forget(row.entry) + } + } + } + + Row { + width: parent.width + spacing: 8 + visible: row.prompting + + TextInput { + id: pskField + width: parent.width - connectBtn.width - parent.spacing + echoMode: TextInput.Password + text: row.psk + onTextChanged: row.psk = text + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + color: Theme.text + Component.onCompleted: forceActiveFocus() + Keys.onReturnPressed: row.submit() + Keys.onEscapePressed: { row.prompting = false; row.psk = ""; } + + Rectangle { + anchors.fill: parent + anchors.margins: -5 + z: -1 + radius: 6 + color: Qt.alpha(Theme.surface, 0.9) + border.width: 1 + border.color: Qt.alpha(Theme.text, 0.15) + } + } + + Button { + id: connectBtn + text: "Connect" + onClicked: row.submit() + } + } + } + + function secured() { + return entry.security !== WifiSecurityType.Open && entry.security !== WifiSecurityType.Owe; + } + + function activate() { + if (entry.connected) { net.disconnectNetwork(entry); return; } + if (entry.known || !secured()) { net.connect(entry); return; } + row.prompting = true; + pskField.forceActiveFocus(); + } + + function submit() { + if (row.psk === "") return; + net.connectWithPsk(entry, row.psk); + row.psk = ""; + row.prompting = false; + } +} -- cgit v1.2.3