0.3.0 refactor

ui: adds overlay layer to patch-db-client

ui: getting towards mocks

ui: cleans up factory init

ui: nice type hack

ui: live api for patch

ui: api service source + http

starts up

ui: api source + http

ui: rework patchdb config, pass stashTimeout into patchDbModel

wires in temp patching into api service

ui: example of wiring patchdbmodel into page

begin integration

remove unnecessary method

linting

first data rendering

rework app initialization

http source working for ssh delete call

temp patches working

entire Embassy tab complete

not in kansas anymore

ripping, saving progress

progress for API request response types and endoint defs

Update data-model.ts

shambles, but in a good way

progress

big progress

progress

installed list working

big progress

progress

progress

begin marketplace redesign

Update api-types.ts

Update api-types.ts

marketplace improvements

cosmetic

dependencies and recommendations

begin nym auth approach

install wizard

restore flow and donations
This commit is contained in:
Aaron Greenspan
2021-02-16 13:45:09 -07:00
committed by Aiden McClelland
parent fd685ae32c
commit 594d93eb3b
238 changed files with 15137 additions and 21331 deletions

View File

@@ -34,13 +34,13 @@
<ion-grid style="margin-top: 40px;">
<ion-row>
<ion-col size="6">
<ion-button [disabled]="!ssid" expand="block" fill="outline" color="primary" (click)="add()">
Save for Later
<ion-button class="ion-text-wrap" [disabled]="!ssid" expand="block" fill="outline" color="primary" (click)="save()">
<p>Save</p>
</ion-button>
</ion-col>
<ion-col size="6">
<ion-button [disabled]="!ssid" expand="block" fill="outline" color="primary" (click)="addAndConnect()">
Save and Connect Now
<ion-button class="ion-text-wrap" [disabled]="!ssid" expand="block" fill="outline" color="primary" (click)="saveAndConnect()">
<p>Save & Connect</p>
</ion-button>
</ion-col>
</ion-row>

View File

@@ -3,7 +3,6 @@ import { NavController } from '@ionic/angular'
import { ApiService } from 'src/app/services/api/api.service'
import { WifiService } from '../wifi.service'
import { LoaderService } from 'src/app/services/loader.service'
import { ServerModel } from 'src/app/models/server-model'
@Component({
selector: 'wifi-add',
@@ -22,18 +21,22 @@ export class WifiAddPage {
private readonly apiService: ApiService,
private readonly loader: LoaderService,
private readonly wifiService: WifiService,
private readonly serverModel: ServerModel,
) { }
async add (): Promise<void> {
async save (): Promise<void> {
this.error = ''
this.loader.of({
message: 'Saving...',
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync( async () => {
await this.apiService.addWifi(this.ssid, this.password, this.countryCode, false)
this.wifiService.addWifi(this.ssid)
}).displayDuringAsync(async () => {
await this.apiService.addWifi({
ssid: this.ssid,
password: this.password,
country: this.countryCode,
priority: 0,
connect: false,
})
this.navCtrl.back()
}).catch(e => {
console.error(e)
@@ -41,23 +44,25 @@ export class WifiAddPage {
})
}
async addAndConnect (): Promise<void> {
async saveAndConnect (): Promise<void> {
this.error = ''
this.loader.of({
message: 'Connecting. This could take while...',
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync( async () => {
const current = this.serverModel.peek().wifi.current
await this.apiService.addWifi(this.ssid, this.password, this.countryCode, true)
const success = await this.wifiService.confirmWifi(this.ssid)
if (success) {
this.navCtrl.back()
this.wifiService.presentAlertSuccess(this.ssid, current)
} else {
this.wifiService.presentToastFail()
}
}).catch (e => {
}).displayDuringAsync(async () => {
await this.apiService.addWifi({
ssid: this.ssid,
password: this.password,
country: this.countryCode,
priority: 0,
connect: true,
})
const success = this.wifiService.confirmWifi(this.ssid)
if (success) {
this.navCtrl.back()
}
}).catch (e => {
console.error(e)
this.error = e.message
})

View File

@@ -4,6 +4,7 @@ import { IonicModule } from '@ionic/angular'
import { RouterModule, Routes } from '@angular/router'
import { WifiListPage } from './wifi.page'
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
import { SharingModule } from 'src/app/modules/sharing.module'
const routes: Routes = [
{
@@ -22,6 +23,7 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
PwaBackComponentModule,
SharingModule,
],
declarations: [WifiListPage],
})

View File

@@ -8,11 +8,6 @@
</ion-header>
<ion-content class="ion-padding-top">
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingIcon="lines" refreshingSpinner="lines"></ion-refresher-content>
</ion-refresher>
<ion-item *ngIf="error">
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
</ion-item>
@@ -20,21 +15,20 @@
<ion-item-group>
<ion-item>
<ion-label class="ion-text-wrap">
<ion-text color="dark">By providing your Embassy with WiFi credentials for one or more networks, you can remove the Ethernet cable and place your Embassy anywhere.</ion-text>
<p style="padding-bottom: 6px;">About</p>
<h2>Embassy will automatically connect to available networks, allowing you to remove the Ethernet cable.</h2>
<br />
<br />
<ion-text color="warning">Warning!</ion-text>
<br />
<br />
<ion-text color="dark">Connecting, disconnecting, or changing WiFi networks can cause your Embassy and its services to become unreachable for up to an hour. Please be patient.</ion-text>
<h2>Connecting, disconnecting, or changing WiFi networks can cause your Embassy and its services to become unreachable for up to an hour. Please be patient.</h2>
</ion-label>
</ion-item>
<ion-item-divider>Saved Networks</ion-item-divider>
<ion-item button detail="false" *ngFor="let ssid of (server.wifi | async)?.ssids" (click)="presentAction(ssid)">
<ion-label>{{ ssid }}</ion-label>
<ion-icon *ngIf="ssid === (server.wifi | async).current" name="wifi" color="success"></ion-icon>
</ion-item>
<ng-container *ngIf="patch.watch$('server-info', 'wifi') | ngrxPush as wifi">
<ion-item button detail="false" *ngFor="let ssid of wifi.ssids" (click)="presentAction(ssid, wifi)">
<ion-label>{{ ssid }}</ion-label>
<ion-icon *ngIf="ssid === wifi.connected" name="wifi" color="success"></ion-icon>
</ion-item>
</ng-container>
</ion-item-group>
<ion-fab vertical="bottom" horizontal="end" slot="fixed">

View File

@@ -2,12 +2,10 @@ import { Component } from '@angular/core'
import { ActionSheetController } from '@ionic/angular'
import { ApiService } from 'src/app/services/api/api.service'
import { ActionSheetButton } from '@ionic/core'
import { pauseFor } from 'src/app/util/misc.util'
import { WifiService } from './wifi.service'
import { PropertySubject } from 'src/app/util/property-subject.util'
import { S9Server } from 'src/app/models/server-model'
import { LoaderService } from 'src/app/services/loader.service'
import { ModelPreload } from 'src/app/models/model-preload'
import { WiFiInfo } from 'src/app/models/patch-db/data-model'
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
@Component({
selector: 'wifi',
@@ -15,32 +13,17 @@ import { ModelPreload } from 'src/app/models/model-preload'
styleUrls: ['wifi.page.scss'],
})
export class WifiListPage {
server: PropertySubject<S9Server> = { } as any
error: string
error = ''
constructor (
private readonly apiService: ApiService,
private readonly loader: LoaderService,
private readonly actionCtrl: ActionSheetController,
private readonly wifiService: WifiService,
private readonly preload: ModelPreload,
public readonly patch: PatchDbModel,
) { }
async ngOnInit () {
this.loader.displayDuring$(
this.preload.server(),
).subscribe(s => this.server = s)
}
async doRefresh (event: any) {
await Promise.all([
this.apiService.getServer(),
pauseFor(600),
])
event.target.complete()
}
async presentAction (ssid: string) {
async presentAction (ssid: string, wifi: WiFiInfo) {
const buttons: ActionSheetButton[] = [
{
text: 'Forget',
@@ -51,7 +34,7 @@ export class WifiListPage {
},
]
if (ssid !== this.server.wifi.getValue().current) {
if (ssid !== wifi.connected) {
buttons.unshift(
{
text: 'Connect',
@@ -69,7 +52,7 @@ export class WifiListPage {
await action.present()
}
// Let's add country code here.
// Let's add country code here
async connect (ssid: string): Promise<void> {
this.error = ''
this.loader.of({
@@ -77,17 +60,11 @@ export class WifiListPage {
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync(async () => {
const current = this.server.wifi.getValue().current
await this.apiService.connectWifi(ssid)
const success = await this.wifiService.confirmWifi(ssid)
if (success) {
this.wifiService.presentAlertSuccess(ssid, current)
} else {
this.wifiService.presentToastFail()
}
await this.apiService.connectWifi({ ssid })
this.wifiService.confirmWifi(ssid)
}).catch(e => {
console.error(e)
this.error = e.message
this.error = ''
})
}
@@ -97,13 +74,12 @@ export class WifiListPage {
message: 'Deleting...',
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync( async () => {
await this.apiService.deleteWifi(ssid)
this.wifiService.removeWifi(ssid)
}).displayDuringAsync(async () => {
await this.apiService.deleteWifi({ ssid })
this.error = ''
}).catch(e => {
console.error(e)
this.error = e.message
this.error = ''
})
}
}

View File

@@ -1,8 +1,8 @@
import { Injectable } from '@angular/core'
import { AlertController, ToastController } from '@ionic/angular'
import { ApiService } from 'src/app/services/api/api.service'
import { pauseFor } from 'src/app/util/misc.util'
import { ServerModel } from 'src/app/models/server-model'
import { merge, Observable, timer } from 'rxjs'
import { filter, map, take, tap } from 'rxjs/operators'
import { PatchDbModel } from 'src/app/models/patch-db/patch-db-model'
@Injectable({
providedIn: 'root',
@@ -10,53 +10,39 @@ import { ServerModel } from 'src/app/models/server-model'
export class WifiService {
constructor (
private readonly apiService: ApiService,
private readonly toastCtrl: ToastController,
private readonly alertCtrl: AlertController,
private readonly serverModel: ServerModel,
private readonly patch: PatchDbModel,
) { }
addWifi (ssid: string): void {
const wifi = this.serverModel.peek().wifi
this.serverModel.update({ wifi: { ...wifi, ssids: [...new Set([ssid, ...wifi.ssids])] } })
confirmWifi (ssid: string): Observable<boolean> {
const success$ = this.patch.watch$('server-info', 'wifi', 'connected')
.pipe(
filter(connected => connected === ssid),
tap(connected => this.presentAlertSuccess(connected)),
map(_ => true),
)
const timer$ = timer(20000)
.pipe(
map(_ => false),
tap(_ => this.presentToastFail()),
)
return merge(success$, timer$).pipe(take(1))
}
removeWifi (ssid: string): void {
const wifi = this.serverModel.peek().wifi
this.serverModel.update({ wifi: { ...wifi, ssids: wifi.ssids.filter(s => s !== ssid) } })
private async presentAlertSuccess (ssid: string): Promise<void> {
const alert = await this.alertCtrl.create({
header: `Connected to "${ssid}"`,
message: 'Note. It may take several minutes to an hour for your Embassy to reconnect over Tor.',
buttons: ['OK'],
})
await alert.present()
}
async confirmWifi (ssid: string): Promise<boolean> {
const timeout = 4000
const maxAttempts = 5
let attempts = 0
while (attempts < maxAttempts) {
try {
const start = new Date().valueOf()
const { current, ssids } = (await this.apiService.getServer(timeout)).wifi
const end = new Date().valueOf()
if (current === ssid) {
this.serverModel.update({ wifi: { current, ssids } })
break
} else {
attempts++
const diff = end - start
await pauseFor(Math.max(2000, timeout - diff))
if (attempts === maxAttempts) {
this.serverModel.update({ wifi: { current, ssids } })
}
}
} catch (e) {
attempts++
console.error(e)
}
}
return this.serverModel.peek().wifi.current === ssid
}
async presentToastFail (): Promise<void> {
private async presentToastFail (): Promise<void> {
const toast = await this.toastCtrl.create({
header: 'Failed to connect:',
message: `Check credentials and try again`,
@@ -71,20 +57,9 @@ export class WifiService {
},
},
],
cssClass: 'notification-toast',
cssClass: 'notification-toast-error',
})
await toast.present()
}
async presentAlertSuccess (current: string, old?: string): Promise<void> {
let message = 'Note. It may take a while for your Embassy to reconnect over Tor, upward of a few hours. Unplugging the device and plugging it back in may help, but it may also just need time. You may also need to hard refresh your browser cache.'
const alert = await this.alertCtrl.create({
header: `Connected to "${current}"`,
message: old ? message : 'You may now unplug your Embassy from Ethernet.<br /></br />' + message,
buttons: ['OK'],
})
await alert.present()
}
}