C++ / fmt (pull_request) Successful in 5s
C++ / build (pull_request) Successful in 2m10s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 17s
Python / static (pull_request) Successful in 44s
C++ / clang-tidy (pull_request) Successful in 3m37s
Rust / build (pull_request) Successful in 1m3s
Rust / fmt (pull_request) Failing after 15m10s
Python / verify (pull_request) Failing after 16m16s
Rust / clippy (pull_request) Successful in 45s
346 lines
9.1 KiB
QML
346 lines
9.1 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import QtQuick.Layouts
|
|
import ZShell.Config
|
|
import qs.Components
|
|
import qs.Helpers.Network
|
|
import qs.Services
|
|
import qs.Modules.Settings.Common
|
|
|
|
PageBase {
|
|
id: root
|
|
|
|
flickable.bottomMargin: Tokens.padding.extraExtraLarge * 2 // Extra scrolling space at the bottom
|
|
|
|
isSubPage: true
|
|
title: Tr.tr("All networks")
|
|
|
|
ColumnLayout {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.top: parent.top
|
|
// spacing: Tokens.spacing.extraSmall / 2
|
|
width: root.cappedWidth
|
|
|
|
Timer {
|
|
interval: 300 // GlobalConfig.nexus.networkRescanInterval
|
|
repeat: true
|
|
running: root.visible && Nmcli.wifiEnabled
|
|
triggeredOnStart: true
|
|
|
|
onTriggered: Nmcli.rescanWifi()
|
|
}
|
|
|
|
ConnectedRect {
|
|
Layout.fillWidth: true
|
|
first: true
|
|
implicitHeight: headerLayout.implicitHeight + Tokens.padding.medium * 2
|
|
|
|
RowLayout {
|
|
id: headerLayout
|
|
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: Tokens.padding.largeIncreased
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: Tokens.padding.large
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.verticalCenterOffset: 1
|
|
|
|
// spacing: Tokens.spacing.extraSmall / 2
|
|
|
|
CustomText {
|
|
font: Tokens.font.title.small
|
|
text: Tr.trCtx("Filters", "network filter heading")
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
FilterButton {
|
|
id: savedFilter
|
|
|
|
function internalFilter(ap: Nmcli.AccessPoint): bool {
|
|
return Nmcli.hasSavedProfile(ap.ssid);
|
|
}
|
|
|
|
bottomLeftRadius: pressed ? pressedRadius : implicitHeight / 2
|
|
text: Tr.trCtx("Saved", "network filter")
|
|
topLeftRadius: pressed ? pressedRadius : implicitHeight / 2
|
|
|
|
Behavior on bottomLeftRadius {
|
|
Anim {
|
|
type: Anim.DefaultEffects
|
|
}
|
|
}
|
|
Behavior on topLeftRadius {
|
|
Anim {
|
|
type: Anim.DefaultEffects
|
|
}
|
|
}
|
|
}
|
|
|
|
FilterButton {
|
|
id: secureFilter
|
|
|
|
function internalFilter(ap: Nmcli.AccessPoint): bool {
|
|
return ap.security !== "none";
|
|
}
|
|
|
|
text: Tr.trCtx("Secured", "network filter")
|
|
}
|
|
|
|
FilterButton {
|
|
id: highFreqFilter
|
|
|
|
function internalFilter(ap: Nmcli.AccessPoint): bool {
|
|
return ap.frequency >= 4900 && ap.frequency <= 5900;
|
|
}
|
|
|
|
text: Tr.trCtx("5 GHz", "network filter")
|
|
}
|
|
|
|
FilterButton {
|
|
id: lowFreqFilter
|
|
|
|
function internalFilter(ap: Nmcli.AccessPoint): bool {
|
|
return ap.frequency >= 2400 && ap.frequency <= 2500;
|
|
}
|
|
|
|
bottomRightRadius: pressed ? pressedRadius : implicitHeight / 2
|
|
text: Tr.trCtx("2.4 GHz", "network filter")
|
|
topRightRadius: pressed ? pressedRadius : implicitHeight / 2
|
|
|
|
Behavior on bottomRightRadius {
|
|
Anim {
|
|
type: Anim.DefaultEffects
|
|
}
|
|
}
|
|
Behavior on topRightRadius {
|
|
Anim {
|
|
type: Anim.DefaultEffects
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NetworkList {
|
|
id: networkList
|
|
|
|
function networkFilter(ap: Nmcli.AccessPoint): bool {
|
|
return savedFilter.filter(ap) && secureFilter.filter(ap) && highFreqFilter.filter(ap) && lowFreqFilter.filter(ap);
|
|
}
|
|
|
|
enableFilter: true
|
|
last: true
|
|
// nState: root.nState
|
|
}
|
|
}
|
|
|
|
component FilterButton: IconTextButton {
|
|
id: filter
|
|
|
|
property int filterState // 0 = default, 1 = on, 2 = negate
|
|
|
|
function filter(ap: Nmcli.AccessPoint): bool {
|
|
if (filterState === 0)
|
|
return true;
|
|
if (filterState === 1)
|
|
return internalFilter(ap);
|
|
return !internalFilter(ap);
|
|
}
|
|
|
|
function internalFilter(ap: Nmcli.AccessPoint): bool {
|
|
return true;
|
|
}
|
|
|
|
defaultRadius: filterState > 0 ? implicitHeight / 2 : Tokens.rounding.small
|
|
icon: ["check_indeterminate_small", "check", "close"][filterState]
|
|
// inactiveColour: [Colours.palette.m3secondaryContainer, Colours.palette.m3secondary, Colours.palette.m3tertiary][filterState]
|
|
// inactiveOnColour: [Colours.palette.m3onSecondaryContainer, Colours.palette.m3onSecondary, Colours.palette.m3onTertiary][filterState]
|
|
pressedRadius: Tokens.rounding.extraSmall
|
|
|
|
// spacing: Tokens.spacing.extraSmall
|
|
|
|
onClicked: filterState = (filterState + 1) % 3
|
|
}
|
|
component NetworkList: ItemList {
|
|
id: netList
|
|
|
|
property bool enableFilter
|
|
property int limit: 0 // 0 = show all
|
|
|
|
// required property NexusState nState
|
|
|
|
signal networkSelected(ap: Nmcli.AccessPoint)
|
|
|
|
function networkFilter(ap: Nmcli.AccessPoint): bool {
|
|
return true;
|
|
}
|
|
|
|
extraHeight: Nmcli.scanning ? Tokens.rounding.extraSmall : 0 // Inline so it isn't affected by anim
|
|
list.anchors.top: scanningIndicator.bottom
|
|
placeholderIcon: Nmcli.wifiEnabled ? "wifi_find" : "signal_wifi_off"
|
|
placeholderText: Nmcli.wifiEnabled ? Tr.tr("No networks found") : Tr.tr("Wi-Fi disabled")
|
|
showList: Nmcli.wifiEnabled
|
|
|
|
delegate: StateLayer {
|
|
id: network
|
|
|
|
property bool currentSelected
|
|
required property int index
|
|
required property var modelData
|
|
property real textOpacity: disabled ? 0.5 : 1
|
|
|
|
anchors.fill: undefined
|
|
anchors.left: netList.list.contentItem.left
|
|
anchors.right: netList.list.contentItem.right
|
|
bottomLeftRadius: netList?.last && index === netList.list.count - 1 ? Tokens.rounding.extraLarge : radius
|
|
bottomRightRadius: netList?.last && index === netList.list.count - 1 ? Tokens.rounding.extraLarge : radius
|
|
// disabled: currentSelected || Nmcli.connectingSsid() === modelData.ssid
|
|
implicitHeight: networkLayout.implicitHeight + networkLayout.anchors.margins * 2
|
|
radius: Tokens.rounding.extraSmall
|
|
|
|
Behavior on textOpacity {
|
|
Anim {
|
|
type: Anim.DefaultEffects
|
|
}
|
|
}
|
|
|
|
onClicked: {
|
|
if (!modelData.active) {
|
|
NetworkConnection.handleConnect(modelData);
|
|
currentSelected = true;
|
|
netList.networkSelected(modelData);
|
|
} else {
|
|
// Active network: open its detail/settings sub-page.
|
|
netList.nState.selectedNetworkSsid = modelData.ssid;
|
|
netList.nState.networkDetailsFromSaved = false;
|
|
netList.nState.openSubPage(3);
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
function onActiveChanged(): void {
|
|
if (network.modelData.active)
|
|
network.currentSelected = false;
|
|
}
|
|
|
|
target: network.modelData
|
|
}
|
|
|
|
Connections {
|
|
function onNetworkSelected(ap: Nmcli.AccessPoint): void {
|
|
if (ap !== network.modelData)
|
|
network.currentSelected = false;
|
|
}
|
|
|
|
target: netList
|
|
}
|
|
|
|
RowLayout {
|
|
id: networkLayout
|
|
|
|
anchors.fill: parent
|
|
anchors.leftMargin: Tokens.padding.extraLarge
|
|
anchors.margins: Tokens.padding.large
|
|
anchors.rightMargin: Tokens.padding.extraLarge
|
|
|
|
// spacing: Tokens.spacing.extraSmall
|
|
|
|
MaterialIcon {
|
|
color: network.modelData.active ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
|
|
font.pointSize: Tokens.font.size.normal
|
|
opacity: network.textOpacity
|
|
text: Icons.getNetworkIcon(network.modelData.strength)
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
opacity: network.textOpacity
|
|
|
|
// spacing: 0
|
|
|
|
CustomText {
|
|
Layout.fillWidth: true
|
|
elide: Text.ElideRight
|
|
font: Tokens.font.body.small
|
|
text: network.modelData.ssid
|
|
}
|
|
|
|
CustomText {
|
|
Layout.fillWidth: true
|
|
color: Colours.palette.m3outline
|
|
elide: Text.ElideRight
|
|
font: Tokens.font.label.small
|
|
text: {
|
|
const net = network.modelData;
|
|
let status = "";
|
|
if (net.active)
|
|
status = Tr.trCtx("Connected", "network connected");
|
|
else if (Nmcli.hasSavedProfile(net.ssid))
|
|
status = Tr.trCtx("Saved", "network saved");
|
|
if (status)
|
|
// TRANSLATORS: %1 = security type, %2 = connection status
|
|
return Tr.trCtx("Security: %1 • %2", "network security and status").arg(net.security).arg(status);
|
|
return Tr.trCtx("Security: %1", "network security").arg(net.security);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Anim {
|
|
// // sourceComp: Nmcli.connectingSsid() === network.modelData.ssid ? loadingComp : iconComp
|
|
//
|
|
// Component {
|
|
// id: iconComp
|
|
//
|
|
// MaterialIcon {
|
|
// color: network.modelData.active ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
|
|
// fontStyle: Tokens.font.icon.medium
|
|
// opacity: network.textOpacity
|
|
// text: network.modelData.active ? "settings" : "lock"
|
|
// }
|
|
// }
|
|
//
|
|
// Component {
|
|
// id: loadingComp
|
|
//
|
|
// LoadingIndicator {
|
|
// implicitSize: Math.round(Tokens.font.icon.medium.pointSize * 1.3)
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
|
|
// model: ScriptModel {
|
|
// values: {
|
|
// const connecting = Nmcli.connectingSsid();
|
|
// // Lower rank sorts higher in the list
|
|
// const rank = n => n.active ? 0 : n.ssid === connecting ? 1 : Nmcli.hasSavedProfile(n.ssid) ? 2 : 3;
|
|
// const sorted = [...Nmcli.networks].sort((a, b) => rank(a) - rank(b) || b.strength - a.strength);
|
|
// if (netList.limit > 0 && sorted.length > netList.limit)
|
|
// sorted.length = netList.limit;
|
|
// return netList.enableFilter ? sorted.filter(netList.networkFilter) : sorted;
|
|
// }
|
|
// }
|
|
|
|
// StyledProgressBar {
|
|
// id: scanningIndicator
|
|
//
|
|
// anchors.left: parent.left
|
|
// anchors.margins: 1
|
|
// anchors.right: parent.right
|
|
// implicitHeight: Nmcli.scanning ? Tokens.rounding.extraSmall : 0
|
|
// indeterminate: true
|
|
//
|
|
// Behavior on implicitHeight {
|
|
// Anim {
|
|
// type: Anim.DefaultEffects
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
}
|