-
Notifications
You must be signed in to change notification settings - Fork 19
Add Wifi Settings #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
646345f
cc71d99
9951258
bc739c9
13f6828
512b10a
d6f838c
859dd99
2e1dcbf
64ed598
8c970e1
5af1c7a
5940966
7069f16
3deca50
b80e363
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,208 @@ | ||
| /* | ||
| * Copyright (C) 2023 - Arseniy Movshev <[email protected]> | ||
| * 2022 - Ed Beroset <github.com/beroset> | ||
| * 2017-2022 - Chupligin Sergey <[email protected]> | ||
| * 2021 - Darrel Griët <[email protected]> | ||
| * 2016 - Sylvia van Os <[email protected]> | ||
| * 2015 - Florent Revest <[email protected]> | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * 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. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| /* A large proportion of this code has been referenced from Nemomobile-UX Glacier-Settings, published at https://github.com/nemomobile-ux/glacier-settings/blob/master/src/plugins/wifi/WifiSettings.qml | ||
| */ | ||
|
|
||
| import QtQuick 2.9 | ||
| import org.asteroid.controls 1.0 | ||
| import org.asteroid.utils 1.0 | ||
| import Connman 0.2 | ||
| import QtQuick.VirtualKeyboard 2.4 | ||
|
|
||
| Item { | ||
| id: dialogItem | ||
| property var modelData | ||
|
|
||
| property real rowHeight: Dims.h(25) | ||
| property real rowMargin: Dims.w(15) | ||
|
|
||
| InputPanel { | ||
| id: inputPanel | ||
| z: 99 | ||
| visible: active | ||
| anchors.left: parent.left | ||
| anchors.top: parent.top | ||
| anchors.topMargin: -Dims.h(25) | ||
| height: Dims.h(100) | ||
|
|
||
| width: Dims.w(100) | ||
| externalLanguageSwitchEnabled: false | ||
| } | ||
|
|
||
| UserAgent { | ||
| id: userAgent | ||
| onUserInputRequested: { | ||
| var view = { | ||
| "fields": [] | ||
| } | ||
| for (var key in fields) { | ||
| view.fields.push({ | ||
| "name": key, | ||
| "id": key.toLowerCase(), | ||
| "type": fields[key]["Type"], | ||
| "requirement": fields[key]["Requirement"] | ||
| }) | ||
| console.log(key + ":") | ||
| for (var inkey in fields[key]) { | ||
| console.log(" " + inkey + ": " + fields[key][inkey]) | ||
| } | ||
| } | ||
| userAgent.sendUserReply({"Passphrase": passphraseField.text}) | ||
| } | ||
|
|
||
| onErrorReported: { | ||
| console.log("Got error from model: " + error) | ||
| failDialog.subLabelText = error | ||
| failDialog.open() | ||
| } | ||
| } | ||
| Connections { | ||
| target: modelData | ||
| function onConnectRequestFailed(error) { | ||
| console.log(error) | ||
| } | ||
|
|
||
| function onConnectedChanged(connected) { | ||
| if(connected) { | ||
| layerStack.pop(layerStack.currentLayer) | ||
| } | ||
| } | ||
| } | ||
| Flickable { | ||
| anchors.fill: parent | ||
| contentHeight: contentColumn.implicitHeight | ||
| Column { | ||
| id: contentColumn | ||
| width: parent.width | ||
| Item {height: Dims.h(15); width: parent.width} | ||
| Marquee { | ||
| anchors { | ||
| left: parent.left | ||
| right: parent.right | ||
| leftMargin: dialogItem.rowMargin | ||
| rightMargin: dialogItem.rowMargin | ||
| } | ||
| text: modelData.name | ||
| font.pixelSize: Dims.l(6) | ||
| height: Dims.l(8) | ||
| } | ||
| Column { | ||
| id: loginFieldsColumn | ||
| visible: !(modelData.connected || modelData.favorite) | ||
| anchors { | ||
| left: parent.left | ||
| right: parent.right | ||
| leftMargin: dialogItem.rowMargin | ||
| rightMargin: dialogItem.rowMargin | ||
| } | ||
| Label { | ||
| id: identityLabel | ||
| text: qsTrId("id-wifi-login")+":" | ||
| font.pixelSize: Dims.l(6) | ||
| visible: modelData.securityType === NetworkService.SecurityIEEE802 | ||
| } | ||
|
|
||
| TextField { | ||
| id: identityField | ||
| text: modelData.identity | ||
| width: parent.width | ||
| visible: modelData.securityType === NetworkService.SecurityIEEE802 | ||
| } | ||
|
|
||
| Label { | ||
| id: passphraseLabel | ||
| text: qsTrId("id-wifi-password")+":" | ||
| font.pixelSize: Dims.l(6) | ||
| visible: !(modelData.securityType == NetworkService.SecurityNone) | ||
| } | ||
|
|
||
| TextField { | ||
| id: passphraseField | ||
| text: modelData.passphrase | ||
| echoMode: TextInput.Password //smartwatches are hard to type on. it is worth adding a 'show password' button for this field | ||
| width: parent.width | ||
| height: dialogItem.rowHeight | ||
| visible: !(modelData.securityType == NetworkService.SecurityNone) | ||
| } | ||
| } | ||
| Column { | ||
| visible: modelData.connected | ||
| width: parent.width | ||
| Label { | ||
| anchors { | ||
| left: parent.left | ||
| right: parent.right | ||
| leftMargin: dialogItem.rowMargin | ||
| rightMargin: dialogItem.rowMargin | ||
| } | ||
| text: "IP: " + modelData.ipv4["Address"] | ||
| horizontalAlignment: Text.AlignHCenter | ||
| font.pixelSize: Dims.l(6) | ||
| } | ||
| LabeledActionButton { | ||
| width: parent.width | ||
| height: dialogItem.rowHeight | ||
| text: qsTrId("id-wifi-disconnect") | ||
| icon: "ios-close-circle-outline" | ||
| onClicked: { | ||
| modelData.requestDisconnect() | ||
| layerStack.pop(layerStack.currentLayer) | ||
| } | ||
| } | ||
| } | ||
| LabeledSwitch { | ||
| id: autoConnectCheckBox | ||
| width: parent.width | ||
| height: dialogItem.rowHeight | ||
| text: qsTrId("id-wifi-autoconnect") | ||
| checked: modelData.autoConnect | ||
| } | ||
| LabeledActionButton { | ||
| visible: modelData.connected || modelData.favorite | ||
| width: parent.width | ||
| height: dialogItem.rowHeight | ||
| text: qsTrId("id-wifi-removenetwork") | ||
| icon: "ios-remove-circle-outline" | ||
| onClicked: { | ||
| modelData.remove() | ||
| layerStack.pop(layerStack.currentLayer) | ||
| } | ||
| } | ||
|
|
||
| IconButton { | ||
| iconName: "ios-checkmark-circle-outline" | ||
| height: width | ||
| width: Dims.w(20) | ||
| anchors.horizontalCenter: parent.horizontalCenter | ||
| onClicked: { | ||
| if(!modelData.connected) { | ||
| modelData.passphrase = passphraseField.text | ||
| modelData.identity = identityField.text | ||
| } | ||
| modelData.autoConnect = autoConnectCheckBox.checked | ||
| modelData.requestConnect() | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| /* | ||
| * Copyright (C) 2023 - Arseniy Movshev <[email protected]> | ||
| * 2017-2022 - Chupligin Sergey <[email protected]> | ||
| * 2021 - Darrel Griët <[email protected]> | ||
| * 2016 - Sylvia van Os <[email protected]> | ||
| * 2015 - Florent Revest <[email protected]> | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * 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. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| /* A large proportion of this code has been referenced from Nemomobile-UX Glacier-Settings, published at https://github.com/nemomobile-ux/glacier-settings/blob/master/src/plugins/wifi/WifiSettings.qml | ||
| */ | ||
|
|
||
| import QtQuick 2.9 | ||
| import org.asteroid.controls 1.0 | ||
| import org.asteroid.utils 1.0 | ||
| import Connman 0.2 | ||
| import QtQuick.VirtualKeyboard 2.4 | ||
|
|
||
| Item { | ||
| id: root | ||
| TechnologyModel { | ||
| id: wifiModel | ||
| name: "wifi" | ||
| onCountChanged: { | ||
| console.log("COUNT CHANGE " + count) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this is a draft but since I'm at it, let me think out loud. I believe we should try to keep the console.logs that make it to production ~minimal and "to the point". There's a sweet spot between not providing any debug info in our logs (basically the current situation) and drowning useful information in tons of logs (what would happen if we start to do this sort of things) |
||
| } | ||
| onScanRequestFinished: { | ||
| console.log("SCAN FINISH") | ||
| } | ||
| } | ||
|
|
||
| NetworkTechnology { | ||
| id: wifiStatus | ||
| path: "/net/connman/technology/wifi" | ||
| onPoweredChanged: { | ||
| console.log("POWER CHANGE ") + powered | ||
| if (powered) | ||
| wifiModel.requestScan() | ||
| } | ||
| } | ||
|
|
||
| ListView { | ||
| id: wifiList | ||
| model: wifiModel | ||
| width: parent.width*0.7 | ||
| anchors.horizontalCenter: parent.horizontalCenter | ||
| height: parent.height | ||
| header: Item { | ||
| //this is literally a statuspage | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't looked at the exact diff but any reason why you're not re-using/extending the existing statuspage instead ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, the comment here is old and misleading. Basically, this is/was the visual components of a statuspage, but they're then moved and resized to make way for the rest of the menu items when wifi is enabled. I'll add this to my cleanup todo list. |
||
| width: root.width | ||
| height: wifiStatus.powered ? width*0.6 : root.height | ||
| Behavior on height { NumberAnimation { duration: 100 } } | ||
| anchors.horizontalCenter: parent.horizontalCenter | ||
| Rectangle { | ||
| id: statusIconBackground | ||
| anchors.centerIn: parent | ||
| anchors.verticalCenterOffset: -parent.width*0.13 | ||
| color: "black" | ||
| radius: width/2 | ||
| opacity: wifiStatus.powered ? 0.4 : 0.2 | ||
| width: parent.width*0.25 | ||
| height: width | ||
| Icon { | ||
| id: statusIcon | ||
| anchors.fill: statusIconBackground | ||
| anchors.margins: parent.width*0.12 | ||
| name: wifiStatus.powered ? "ios-wifi" : "ios-wifi-outline" | ||
| } | ||
| MouseArea { | ||
| id: statusMA | ||
| enabled: true | ||
| anchors.fill: parent | ||
| onClicked: wifiStatus.powered = !wifiStatus.powered | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spacing between components isn't consistent with sometimes 2 spaces, sometimes 1, sometimes 0. The QML convention seems to be to leave 1 empty line between two consecutive blocks at the same depth. I believe that @eLtMosen uses a QML linter. Whatever canonical coding style is outputted by a sane QML linter should be our project-wide default. |
||
| Label { | ||
| id: statusLabel | ||
| font.pixelSize: parent.width*0.07 | ||
| horizontalAlignment: Text.AlignHCenter | ||
| verticalAlignment: Text.AlignVCenter | ||
| wrapMode: Text.Wrap | ||
| anchors.left: parent.left; anchors.right: parent.right | ||
| anchors.leftMargin: parent.width*0.04; anchors.rightMargin: anchors.leftMargin | ||
| anchors.verticalCenter: parent.verticalCenter | ||
| anchors.verticalCenterOffset: parent.width*0.15 | ||
| text: "<h3>" + (wifiStatus.powered ? qsTrId("id-wifi-on"): qsTrId("id-wifi-off")) + "</h3>\n" + (wifiStatus.connected ? qsTrId("id-wifi-connected") : qsTrId("id-wifi-disconnected")) | ||
| } | ||
| } | ||
|
|
||
| footer: Item {height: wifiStatus.powered ? root.height*0.15 : 0; width: parent.width} | ||
|
|
||
| delegate: MouseArea { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should use a https://github.com/AsteroidOS/qml-asteroid/blob/master/src/controls/qml/ListItem.qml here instead of re-inventing that wheel. We can also have the ListItem use a Marquee, I think it's a sane default anyway. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this does show two bits of text instead of one, and doesn't make use of an icon, so ListItem isn't relevant here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. qml-asteroid is not set in stone. We can expand ListItem to handle a primary and a secondary text and no icon. The reason why I think this is relevant is that this sort of code factorization also keeps the design consistent across the OS. For example, ListItem has a HighlightBar that isn't used here. The more we factorize code the better it is to keep the UI sharp and to conduct refactorings/redesigns in the future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The highlightbar is something I wanted to add, but I wanted to push the code to prompt the security conversation before I invested too much time.
|
||
| property var wifiName: modelData.name | ||
| visible: wifiStatus.powered | ||
| width: wifiList.width | ||
| height: wifiStatus.powered ? width*0.23 : 0 | ||
| Marquee { | ||
| id: wifiNameLabel | ||
| text: wifiName | ||
| height: parent.height*0.6 | ||
| width: parent.width | ||
| } | ||
| Label { | ||
| anchors.top: wifiNameLabel.bottom | ||
| anchors.horizontalCenter: parent.horizontalCenter | ||
| opacity: 0.8 | ||
| font.pixelSize: parent.width*0.07 | ||
| font.weight: Font.Thin | ||
| text: { | ||
| if (modelData.connected) { | ||
| qsTrId("id-wifi-connected") | ||
| } else if (modelData.favorite){ | ||
| qsTrId("id-wifi-saved") | ||
| } else { | ||
| qsTrId("id-wifi-notsetup") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe you'd need to provide the string in a specially formatted comment just above these qsTrId There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also a final PR would need to update the translation files, but you can keep this for when that's undrafted |
||
| } | ||
| } | ||
| } | ||
| onClicked: { | ||
| if (modelData.favorite && !modelData.connected) { | ||
| modelData.requestConnect() | ||
| } else { | ||
| layerStack.push(connectionDialog, {modelData: modelData}) | ||
| } | ||
| } | ||
| onPressAndHold: layerStack.push(connectionDialog, {modelData: modelData}) | ||
| } | ||
| } | ||
|
|
||
| Component { | ||
| id: connectionDialog | ||
| WiFiConnectionDialog {} | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delegating all UX decisions to @eLtMosen but I don't think we gain very much from hiding the password here. Imho these password placeholders are for situation where the user is sitting in a crowded space and types a password that they don't want anyone around to see. I don't really see this happening with a user typing their Wi-Fi passphrase once on their watch. I don't feel particularly strongly either way but this echoMode feels a bit overkill to me.