guid and new alert flow

This commit is contained in:
Drew Ansbacher
2021-11-01 15:07:43 -06:00
committed by Aiden McClelland
parent a5266c2e41
commit 7576b30a6b
15 changed files with 157 additions and 81 deletions

View File

@@ -15,7 +15,7 @@
<ion-card-content class="ion-margin">
<ng-container *ngIf="!loading && !recoveryPartitions.length">
<ng-container *ngIf="!loading && !drives.length">
<h2>No recovery drives found</h2>
<p>Please connect a recovery drive to your Embassy and refresh the page.</p>
<ion-button
@@ -29,43 +29,43 @@
<ion-item-group>
<ng-container *ngIf="loading">
<ion-item button color="light" lines="none">
<ion-avatar slot="start">
<ion-skeleton-text animated></ion-skeleton-text>
<ion-item-divider color="light">
<ion-skeleton-text animated style="width: 120px; height: 16px;"></ion-skeleton-text>
</ion-item-divider>
<ion-item color="light">
<ion-avatar slot="start" style="margin-right: 24px;">
<ion-skeleton-text animated style="width: 30px; height: 30px; border-radius: 0;"></ion-skeleton-text>
</ion-avatar>
<ion-label class="ion-text-wrap">
<ion-skeleton-text style="width: 80%; margin: 13px 0;" animated></ion-skeleton-text>
<ion-skeleton-text style="width: 60%; margin: 10px 0;" animated></ion-skeleton-text>
<ion-skeleton-text style="width: 30%; margin: 8px 0;" animated></ion-skeleton-text>
<ion-label>
<ion-skeleton-text animated style="width: 100px; height: 20px; margin-bottom: 12px;"></ion-skeleton-text>
<ion-skeleton-text animated style="width: 50px; height: 16px; margin-bottom: 16px;"></ion-skeleton-text>
<ion-skeleton-text animated style="width: 100px;"></ion-skeleton-text>
</ion-label>
</ion-item>
</ng-container>
<ng-container *ngIf="recoveryPartitions.length">
<ion-item (click)="choosePartition(p.partition)" class="ion-margin-bottom" button color="light" lines="none" *ngFor="let p of recoveryPartitions" [ngClass]="p.partition.logicalname === selectedPartition?.logicalname ? 'selected' : null">
<ion-icon slot="start" name="save-outline"></ion-icon>
<ion-label class="ion-text-wrap">
<h1>{{ p.partition.logicalname }} <span *ngIf="!!p.partition.label">-</span> {{ p.partition.label }}</h1>
<h2 *ngIf="p.vendor || p.model">
{{ p.vendor }}
<span *ngIf="p.vendor && p.model"> - </span>
{{ p.model }}
</h2>
<h2> Embassy version: {{p.partition['embassy-os'].version}}</h2>
</ion-label>
<ion-icon *ngIf="(p.partition['embassy-os'].version.startsWith('0.2') && stateService.hasProductKey) || passwords[p.partition.logicalname] || prodKeys[p.partition.logicalname]" color="success" slot="end" name="lock-open-outline"></ion-icon>
<ion-icon *ngIf="(p.partition['embassy-os'].version.startsWith('0.2') && !stateService.hasProductKey && !prodKeys[p.partition.logicalname]) || (!p.partition['embassy-os'].version.startsWith('0.2') && !passwords[p.partition.logicalname])" color="danger" slot="end" name="lock-closed-outline"></ion-icon>
<!-- loaded -->
<div *ngFor="let drive of drives">
<ion-item-divider color="light">
{{ drive.vendor || 'Unknown Vendor' }} - {{ drive.model || 'Unknown Model' }} - {{ drive.capacity | convertBytes }}
</ion-item-divider>
<ion-item color="light" button *ngFor="let partition of drive.partitions" [disabled]="!partitionClickable(partition)" (click)="choosePartition(partition)">
<ion-icon slot="start" name="save-outline"></ion-icon>
<ion-label>
<h1>{{ partition.label || partition.logicalname }}</h1>
<h2>{{ drive.capacity | convertBytes }}</h2>
<p *ngIf="partition['embassy-os'] && partition['embassy-os'].full">
<ion-text color="success">
Embassy backups detected
</ion-text>
</p>
</ion-label>
<div *ngIf="partition['embassy-os'] && partition['embassy-os'].full">
<ion-icon *ngIf="partition['embassy-os'].version.startsWith('0.2')" color="success" slot="end" name="lock-open-outline" size="large"></ion-icon>
<ion-icon *ngIf="!partition['embassy-os'].version.startsWith('0.2')" color="danger" slot="end" name="lock-closed-outline" size="large"></ion-icon>
</div>
</ion-item>
</ng-container>
<ion-button
(click)="selectRecoveryPartition()"
color="light"
[disabled]="!selectedPartition || (!passwords[selectedPartition.logicalname] && !selectedPartition['embassy-os'].version.startsWith('0.2'))"
class="claim-button"
*ngIf="recoveryPartitions.length"
>
Next
</ion-button>
</div>
</ion-item-group>
</ion-card-content>
</ion-card>

View File

@@ -1,6 +1,6 @@
import { Component } from '@angular/core'
import { ModalController, NavController } from '@ionic/angular'
import { ApiService, PartitionInfo } from 'src/app/services/api/api.service'
import { AlertController, LoadingController, ModalController, NavController } from '@ionic/angular'
import { ApiService, DiskInfo, PartitionInfo } from 'src/app/services/api/api.service'
import { ErrorToastService } from 'src/app/services/error-toast.service'
import { StateService } from 'src/app/services/state.service'
import { PasswordPage } from '../password/password.page'
@@ -12,39 +12,60 @@ import { ProdKeyModal } from '../prod-key-modal/prod-key-modal.page'
styleUrls: ['recover.page.scss'],
})
export class RecoverPage {
passwords = { }
prodKeys = { }
recoveryPartitions: { partition: PartitionInfo, model: string, vendor: string }[] = []
selectedPartition: PartitionInfo = null
loading = true
drives: DiskInfo[] = []
hasShownGuidAlert = false
constructor (
private readonly apiService: ApiService,
private readonly navCtrl: NavController,
private readonly modalController: ModalController,
private readonly alertCtrl: AlertController,
private readonly loadingCtrl: LoadingController,
readonly stateService: StateService,
private readonly errorToastService: ErrorToastService,
) { }
async ngOnInit () {
await this.getPartitions()
await this.getDrives()
}
async refresh () {
this.recoveryPartitions = []
this.selectedPartition = null
this.loading = true
await this.getPartitions()
await this.getDrives()
}
async getPartitions () {
try {
let drives = await this.apiService.getDrives()
partitionClickable (partition: PartitionInfo) {
return partition['embassy-os']?.full && ((!this.stateService.hasProductKey && partition['embassy-os']?.version.startsWith('0.2') ) || this.stateService.hasProductKey)
}
this.recoveryPartitions = drives.map(d => d.partitions.map(p => ({ partition: p, vendor: d.vendor, model: d.model})).filter(p => p.partition['embassy-os']?.full)).flat()
// if theres no product key, only show 0.2s
if (!this.stateService.hasProductKey) {
this.recoveryPartitions = this.recoveryPartitions.filter(p => p.partition['embassy-os']?.version.startsWith('0.2'))
async getDrives () {
try {
this.drives = await this.apiService.getDrives()
const importableDrive = this.drives.filter(d => !!d.guid)[0]
if (!!importableDrive && !this.hasShownGuidAlert) {
const alert = await this.alertCtrl.create({
header: 'Warning',
subHeader: 'Drive contains data!',
message: 'All data stored on this drive will be permanently deleted.',
buttons: [
{
role: 'cancel',
text: 'Dismiss',
},
{
text: 'Use',
handler: async () => {
await this.importDrive(importableDrive.guid)
},
},
],
})
await alert.present()
this.hasShownGuidAlert = true
}
} catch (e) {
this.errorToastService.present(`${e.message}: ${e.data}`)
@@ -53,15 +74,27 @@ export class RecoverPage {
}
}
async choosePartition (partition: PartitionInfo) {
if (this.selectedPartition?.logicalname === partition.logicalname) {
this.selectedPartition = null
return
} else {
this.selectedPartition = partition
async importDrive (guid: string) {
const loader = await this.loadingCtrl.create({
message: 'Importing Drive',
})
await loader.present()
try {
await this.stateService.importDrive(guid)
await this.navCtrl.navigateForward(`/success`)
} catch (e) {
this.errorToastService.present(`${e.message}: ${e.data}`)
} finally {
loader.dismiss()
}
}
if ((partition['embassy-os'].version.startsWith('0.2') && this.stateService.hasProductKey) || this.passwords[partition.logicalname] || this.prodKeys[partition.logicalname]) return
async choosePartition (partition: PartitionInfo) {
this.selectedPartition = partition
if (partition['embassy-os'].version.startsWith('0.2')) {
return this.selectRecoveryPartition()
}
if (this.stateService.hasProductKey) {
const modal = await this.modalController.create({
@@ -75,7 +108,7 @@ export class RecoverPage {
if (!ret.data) {
this.selectedPartition = null
} else if (ret.data.password) {
this.passwords[partition.logicalname] = ret.data.password
this.selectRecoveryPartition(ret.data.password)
}
})
@@ -92,7 +125,7 @@ export class RecoverPage {
if (!ret.data) {
this.selectedPartition = null
} else if (ret.data.productKey) {
this.prodKeys[partition.logicalname] = ret.data.productKey
this.selectRecoveryPartition()
}
})
@@ -100,11 +133,10 @@ export class RecoverPage {
}
}
async selectRecoveryPartition () {
async selectRecoveryPartition (password?: string) {
this.stateService.recoveryPartition = this.selectedPartition
const pw = this.passwords[this.selectedPartition.logicalname]
if (pw) {
this.stateService.recoveryPassword = pw
if (password) {
this.stateService.recoveryPassword = password
}
await this.navCtrl.navigateForward(`/embassy`)
}