mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
feature: Swapping to use nmcli (#1015)
The reason is that we get better errors and that we get signal strength. Reworking all the commands to use nmcli instead. Feat: Wifi List Available Feat: strength sort for available fix: Backend to match the frontend asking feat: New get with all information chore: Make backend changing country not for NonWire Co-authored-by: Drew Ansbacher <drew.ansbacher@spiredigital.com> Co-authored-by: Drew Ansbacher <drew.ansbacher@spiredigital.com>
This commit is contained in:
270
ui/package-lock.json
generated
270
ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,12 @@
|
||||
<ion-back-button defaultHref="embassy"></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>WiFi Settings</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button (click)="getWifi()">
|
||||
Refresh
|
||||
<ion-icon slot="end" name="refresh"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
@@ -40,25 +46,43 @@
|
||||
<ion-skeleton-text animated style="width: 18%;"></ion-skeleton-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Available Networks</ion-item-divider>
|
||||
<ion-item *ngFor="let entry of ['', '']" class="skeleton-parts">
|
||||
<ion-button slot="start" fill="clear">
|
||||
<ion-skeleton-text animated style="width: 30px; height: 30px; border-radius: 0;"></ion-skeleton-text>
|
||||
</ion-button>
|
||||
<ion-label>
|
||||
<ion-skeleton-text animated style="width: 18%;"></ion-skeleton-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- not loading -->
|
||||
<ng-container *ngIf="!loading && wifi.country">
|
||||
<ion-item-divider>Saved Networks</ion-item-divider>
|
||||
<ion-item button detail="false" *ngFor="let ssid of wifi.ssids | keyvalue" (click)="presentAction(ssid.key)">
|
||||
<div *ngIf="ssid.key !== wifi.connected" slot="start" style="padding-right: 32px;"></div>
|
||||
<ion-icon *ngIf="ssid.key === wifi.connected" slot="start" size="large" name="checkmark" color="success"></ion-icon>
|
||||
<ion-label>{{ ssid.key }}</ion-label>
|
||||
<img *ngIf="ssid.value > 0 && ssid.value < 5" slot="end" src="assets/img/icons/wifi-1.png" style="max-width: 32px;" />
|
||||
<img *ngIf="ssid.value >= 5 && ssid.value < 50" slot="end" src="assets/img/icons/wifi-1.png" style="max-width: 32px;" />
|
||||
<img *ngIf="ssid.value >= 50 && ssid.value < 90" slot="end" src="assets/img/icons/wifi-2.png" style="max-width: 32px;" />
|
||||
<img *ngIf="ssid.value >= 90" slot="end" src="assets/img/icons/wifi-3.png" style="max-width: 32px;" />
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Available Networks</ion-item-divider>
|
||||
<ion-item button detail="false" *ngFor="let avWifi of wifi['available-wifi']" (click)="presentModalAdd(avWifi.ssid, !!avWifi.security.length)">
|
||||
<ion-icon slot="start" name="add" size="large"></ion-icon>
|
||||
<ion-label>{{ avWifi.ssid }}</ion-label>
|
||||
<img *ngIf="avWifi.strength < 5" slot="end" src="assets/img/icons/wifi-1.png" style="max-width: 32px;" />
|
||||
<img *ngIf="avWifi.strength >= 5 && avWifi.strength < 50" slot="end" src="assets/img/icons/wifi-1.png" style="max-width: 32px;" />
|
||||
<img *ngIf="avWifi.strength >= 50 && avWifi.strength < 90" slot="end" src="assets/img/icons/wifi-2.png" style="max-width: 32px;" />
|
||||
<img *ngIf="avWifi.strength >= 90" slot="end" src="assets/img/icons/wifi-3.png" style="max-width: 32px;" />
|
||||
</ion-item>
|
||||
<ion-item button detail="false" (click)="presentModalAdd()">
|
||||
<ion-icon slot="start" name="add" size="large"></ion-icon>
|
||||
<ion-label>Add new network</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button detail="false" *ngFor="let ssid of wifi.ssids; let i = index;" (click)="presentAction(ssid, i)">
|
||||
<div *ngIf="ssid !== wifi.connected" slot="start" style="padding-right: 32px;"></div>
|
||||
<ion-icon *ngIf="ssid === wifi.connected" slot="start" size="large" name="checkmark" color="success"></ion-icon>
|
||||
<ion-label>{{ ssid }}</ion-label>
|
||||
<ng-container *ngIf="ssid === wifi.connected && wifi['signal-strength'] as strength">
|
||||
<img *ngIf="strength < 5" slot="end" src="assets/img/icons/wifi-1.png" style="max-width: 32px;" />
|
||||
<img *ngIf="strength >= 5 && strength < 50" slot="end" src="assets/img/icons/wifi-1.png" style="max-width: 32px;" />
|
||||
<img *ngIf="strength >= 50 && strength < 90" slot="end" src="assets/img/icons/wifi-2.png" style="max-width: 32px;" />
|
||||
<img *ngIf="strength >= 90" slot="end" src="assets/img/icons/wifi-3.png" style="max-width: 32px;" />
|
||||
</ng-container>
|
||||
<ion-label>Other</ion-label>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
</ion-item-group>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ValueSpecObject } from 'src/app/pkg-config/config-types'
|
||||
import { RR } from 'src/app/services/api/api.types'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
|
||||
@Component({
|
||||
selector: 'wifi',
|
||||
@@ -27,6 +28,7 @@ export class WifiPage {
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly errToast: ErrorToastService,
|
||||
private readonly actionCtrl: ActionSheetController,
|
||||
private readonly config: ConfigService,
|
||||
) { }
|
||||
|
||||
async ngOnInit () {
|
||||
@@ -47,6 +49,23 @@ export class WifiPage {
|
||||
}
|
||||
|
||||
async presentAlertCountry (): Promise<void> {
|
||||
if (!this.config.isLan) {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Cannot Complete Action',
|
||||
message: 'You must be connected to your Emassy via LAN to change the country.',
|
||||
buttons: [
|
||||
{
|
||||
text: 'OK',
|
||||
role: 'cancel',
|
||||
},
|
||||
|
||||
],
|
||||
cssClass: 'wide-alert enter-click',
|
||||
})
|
||||
await alert.present()
|
||||
return
|
||||
}
|
||||
|
||||
const inputs: AlertInput[] = Object.entries(this.countries).map(([country, fullName]) => {
|
||||
return {
|
||||
name: fullName,
|
||||
@@ -59,6 +78,7 @@ export class WifiPage {
|
||||
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Select Country',
|
||||
message: 'Warning: Changing the country will delete all saved networks from the Embassy.',
|
||||
inputs,
|
||||
buttons: [
|
||||
{
|
||||
@@ -77,7 +97,8 @@ export class WifiPage {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentModalAdd () {
|
||||
async presentModalAdd (ssid?: string, needsPW: boolean = true) {
|
||||
const wifiSpec = getWifiValueSpec(ssid, needsPW)
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
@@ -104,14 +125,14 @@ export class WifiPage {
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
async presentAction (ssid: string, i: number) {
|
||||
async presentAction (ssid: string) {
|
||||
const buttons: ActionSheetButton[] = [
|
||||
{
|
||||
text: 'Forget',
|
||||
icon: 'trash',
|
||||
role: 'destructive',
|
||||
handler: () => {
|
||||
this.delete(ssid, i)
|
||||
this.delete(ssid)
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -147,6 +168,7 @@ export class WifiPage {
|
||||
|
||||
try {
|
||||
await this.api.setWifiCountry({ country })
|
||||
await this.getWifi(4000)
|
||||
this.wifi.country = country
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
@@ -164,7 +186,7 @@ export class WifiPage {
|
||||
if (attempts > maxAttempts) {
|
||||
this.presentToastFail()
|
||||
if (deleteOnFailure) {
|
||||
this.wifi.ssids = this.wifi.ssids.filter(s => s !== ssid)
|
||||
delete this.wifi.ssids[ssid]
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -243,7 +265,7 @@ export class WifiPage {
|
||||
}
|
||||
}
|
||||
|
||||
private async delete (ssid: string, i: number): Promise<void> {
|
||||
private async delete (ssid: string): Promise<void> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
spinner: 'lines',
|
||||
message: 'Deleting...',
|
||||
@@ -253,7 +275,8 @@ export class WifiPage {
|
||||
|
||||
try {
|
||||
await this.api.deleteWifi({ ssid })
|
||||
this.wifi.ssids = this.wifi.ssids.filter((w, index) => index !== i)
|
||||
await this.getWifi(4000)
|
||||
delete this.wifi.ssids[ssid]
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
@@ -276,7 +299,7 @@ export class WifiPage {
|
||||
priority: 0,
|
||||
connect: false,
|
||||
})
|
||||
await this.getWifi()
|
||||
await this.getWifi(4000)
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
@@ -310,25 +333,29 @@ export class WifiPage {
|
||||
}
|
||||
}
|
||||
|
||||
const wifiSpec: ValueSpecObject = {
|
||||
type: 'object',
|
||||
name: 'WiFi Credentials',
|
||||
description: 'Enter the network SSID and password. You can connect now or save the network for later.',
|
||||
'unique-by': null,
|
||||
spec: {
|
||||
ssid: {
|
||||
type: 'string',
|
||||
name: 'Network SSID',
|
||||
nullable: false,
|
||||
masked: false,
|
||||
copyable: false,
|
||||
function getWifiValueSpec (ssid?: string, needsPW: boolean = true): ValueSpecObject {
|
||||
return {
|
||||
type: 'object',
|
||||
name: 'WiFi Credentials',
|
||||
description: 'Enter the network SSID and password. You can connect now or save the network for later.',
|
||||
'unique-by': null,
|
||||
spec: {
|
||||
ssid: {
|
||||
type: 'string',
|
||||
name: 'Network SSID',
|
||||
nullable: false,
|
||||
masked: false,
|
||||
copyable: false,
|
||||
default: ssid,
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
name: 'Password',
|
||||
nullable: !needsPW,
|
||||
masked: true,
|
||||
copyable: false,
|
||||
},
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
name: 'Password',
|
||||
nullable: false,
|
||||
masked: true,
|
||||
copyable: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -983,10 +983,24 @@ export module Mock {
|
||||
|
||||
export const Wifi: RR.GetWifiRes = {
|
||||
ethernet: true,
|
||||
ssids: ['Goosers', 'Goosers5G'],
|
||||
ssids: {
|
||||
'Goosers': 50,
|
||||
'Goosers5G': 0,
|
||||
},
|
||||
connected: 'Goosers',
|
||||
country: 'US',
|
||||
'signal-strength': 50,
|
||||
'available-wifi': [
|
||||
{
|
||||
ssid: 'Goosers a billion',
|
||||
strength: 40,
|
||||
security: [],
|
||||
},
|
||||
{
|
||||
ssid: 'Bill nye the wifi guy',
|
||||
strength: 99,
|
||||
security: ['1', '2', '3'],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const BackupTargets: RR.GetBackupTargetsRes = {
|
||||
|
||||
@@ -83,13 +83,15 @@ export module RR {
|
||||
export type SetWifiCountryRes = null
|
||||
|
||||
export type GetWifiReq = { }
|
||||
export type GetWifiRes = { // wifi.get
|
||||
ethernet: boolean
|
||||
ssids: string[]
|
||||
connected: string | null
|
||||
country: string | null
|
||||
'signal-strength': number
|
||||
}
|
||||
export type GetWifiRes = {
|
||||
ssids: {
|
||||
[ssid: string]: number
|
||||
},
|
||||
connected?: string,
|
||||
country: string,
|
||||
ethernet: boolean,
|
||||
'available-wifi': AvailableWifi[]
|
||||
}
|
||||
|
||||
export type AddWifiReq = { // wifi.add
|
||||
ssid: string
|
||||
@@ -442,3 +444,9 @@ export interface BackupReport {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface AvailableWifi {
|
||||
ssid: string
|
||||
strength: number
|
||||
security: string []
|
||||
}
|
||||
Reference in New Issue
Block a user