diff --git a/modules/nexus/pages/NetworkPage.qml b/modules/nexus/pages/NetworkPage.qml index 8c7b0b5a..9b74ffbc 100644 --- a/modules/nexus/pages/NetworkPage.qml +++ b/modules/nexus/pages/NetworkPage.qml @@ -2,7 +2,7 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts -import Caelestia.Components +import Quickshell import Caelestia.Config import qs.components import qs.components.controls @@ -21,85 +21,155 @@ PageBase { width: root.cappedWidth spacing: Tokens.spacing.extraSmall / 2 + Timer { + running: root.visible + repeat: true + triggeredOnStart: true + interval: GlobalConfig.nexus.networkRescanInterval + onTriggered: Nmcli.rescanWifi() + } + ToggleRow { Layout.fillWidth: true first: true text: qsTr("Wi-Fi") font: Tokens.font.title.medium - checked: Network.wifiEnabled - onToggled: Network.enableWifi(checked) + checked: Nmcli.wifiEnabled + onToggled: Nmcli.enableWifi(checked) horizontalPadding: Tokens.padding.largeIncreased - verticalPadding: Tokens.padding.medium + verticalPadding: Tokens.padding.large } StyledRect { Layout.fillWidth: true - implicitHeight: networkList.implicitHeight + networkList.anchors.margins * 2 + implicitHeight: networkList.contentHeight + (Nmcli.scanning ? Tokens.rounding.extraSmall : 0) // Inline so it isn't affected by anim radius: Tokens.rounding.extraSmall color: Colours.tPalette.m3surfaceContainer + clip: true - ColumnLayout { + Behavior on implicitHeight { + Anim {} + } + + ListView { id: networkList - anchors.fill: parent + anchors.left: parent.left + anchors.right: parent.right + anchors.top: scanningIndicator.bottom + anchors.bottom: parent.bottom + spacing: 0 + interactive: false - Repeater { - model: Network.networks + model: ScriptModel { + values: [...Nmcli.networks].sort((a, b) => { + if (a.active) + return -1; + if (b.active) + return 1; + return b.strength - a.strength; + }) + } - StateLayer { - id: network + add: Transition { + Anim { + property: "opacity" + from: 0 + to: 1 + type: Anim.DefaultEffects + } + } - required property Network.AccessPoint modelData + remove: Transition { + Anim { + property: "opacity" + to: 0 + type: Anim.DefaultEffects + } + } - Layout.fillWidth: true - implicitHeight: networkLayout.implicitHeight + networkLayout.anchors.margins * 2 - radius: Tokens.rounding.extraSmall - anchors.fill: undefined + move: Transition { + Anim { + property: "y" + } + } - RowLayout { - id: networkLayout + displaced: Transition { + Anim { + property: "y" + } + } - anchors.fill: parent - anchors.margins: Tokens.padding.medium - anchors.leftMargin: Tokens.padding.largeIncreased - anchors.rightMargin: Tokens.padding.largeIncreased - spacing: Tokens.spacing.medium + delegate: StateLayer { + id: network - MaterialIcon { - text: Icons.getNetworkIcon(network.modelData.strength) - color: network.modelData.active ? Colours.palette.m3primary : Colours.tPalette.m3onSurfaceVariant - font: Tokens.font.icon.medium - } + required property Nmcli.AccessPoint modelData - ColumnLayout { + anchors.left: networkList.contentItem.left + anchors.right: networkList.contentItem.right + implicitHeight: networkLayout.implicitHeight + networkLayout.anchors.margins * 2 + radius: Tokens.rounding.extraSmall + anchors.fill: undefined + + RowLayout { + id: networkLayout + + anchors.fill: parent + anchors.margins: Tokens.padding.medium + anchors.leftMargin: Tokens.padding.largeIncreased + anchors.rightMargin: Tokens.padding.largeIncreased + spacing: Tokens.spacing.medium + + MaterialIcon { + text: Icons.getNetworkIcon(network.modelData.strength) + color: network.modelData.active ? Colours.palette.m3primary : Colours.tPalette.m3onSurfaceVariant + font: Tokens.font.icon.medium + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 0 + + StyledText { Layout.fillWidth: true - spacing: 0 - - StyledText { - Layout.fillWidth: true - text: network.modelData.ssid - font: Tokens.font.body.small - elide: Text.ElideRight - } - - StyledText { - Layout.fillWidth: true - text: qsTr("Security: %1").arg(network.modelData.security) - color: Colours.tPalette.m3outline - font: Tokens.font.label.small - elide: Text.ElideRight - } + text: network.modelData.ssid + font: Tokens.font.body.small + elide: Text.ElideRight } - MaterialIcon { - visible: network.modelData.isSecure - text: network.modelData.active ? "settings" : "lock" - color: network.modelData.active ? Colours.palette.m3primary : Colours.tPalette.m3onSurfaceVariant - font: Tokens.font.icon.medium + StyledText { + Layout.fillWidth: true + text: qsTr("Security: %1").arg(network.modelData.security) + color: Colours.tPalette.m3outline + font: Tokens.font.label.small + elide: Text.ElideRight } } + + MaterialIcon { + visible: network.modelData.isSecure + text: network.modelData.active ? "settings" : "lock" + color: network.modelData.active ? Colours.palette.m3primary : Colours.tPalette.m3onSurfaceVariant + font: Tokens.font.icon.medium + } + } + } + } + + StyledProgressBar { + id: scanningIndicator + + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 1 + implicitHeight: Nmcli.scanning ? Tokens.rounding.extraSmall : 0 + indeterminate: true + + Behavior on implicitHeight { + Anim { + type: Anim.DefaultEffects } } } diff --git a/plugin/src/Caelestia/Config/nexusconfig.hpp b/plugin/src/Caelestia/Config/nexusconfig.hpp index 7d43220f..2389acb3 100644 --- a/plugin/src/Caelestia/Config/nexusconfig.hpp +++ b/plugin/src/Caelestia/Config/nexusconfig.hpp @@ -9,6 +9,7 @@ class NexusConfig : public ConfigObject { QML_ANONYMOUS CONFIG_PROPERTY(int, wallpapersPerRow, 4) + CONFIG_GLOBAL_PROPERTY(int, networkRescanInterval, 15000) public: explicit NexusConfig(QObject* parent = nullptr)