diff --git a/backend/src/backup/backup_bulk.rs b/backend/src/backup/backup_bulk.rs index e0e622ed5..04c85001c 100644 --- a/backend/src/backup/backup_bulk.rs +++ b/backend/src/backup/backup_bulk.rs @@ -358,11 +358,11 @@ async fn perform_backup( .await; let mut tx = db.begin().await?; - let lock_package = crate::db::DatabaseModel::new() + crate::db::DatabaseModel::new() .package_data() .idx(&package_id) .lock(&mut tx, LockType::Write) - .await; + .await?; installed_model.lock(&mut tx, LockType::Write).await?; diff --git a/backend/src/backup/restore.rs b/backend/src/backup/restore.rs index b806c9d1f..a69b86718 100644 --- a/backend/src/backup/restore.rs +++ b/backend/src/backup/restore.rs @@ -179,7 +179,7 @@ impl ProgressInfo { } SetupStatus { - total_bytes, + total_bytes: Some(total_bytes), bytes_transferred, complete: false, } diff --git a/backend/src/setup.rs b/backend/src/setup.rs index 7e791515e..e3c5c2538 100644 --- a/backend/src/setup.rs +++ b/backend/src/setup.rs @@ -114,7 +114,7 @@ pub async fn attach( } *status = Some(Ok(SetupStatus { bytes_transferred: 0, - total_bytes: 0, + total_bytes: None, complete: false, })); drop(status); @@ -165,7 +165,7 @@ pub async fn attach( })); *ctx.setup_status.write().await = Some(Ok(SetupStatus { bytes_transferred: 0, - total_bytes: 0, + total_bytes: None, complete: true, })); Ok(()) @@ -182,7 +182,7 @@ pub async fn attach( #[serde(rename_all = "kebab-case")] pub struct SetupStatus { pub bytes_transferred: u64, - pub total_bytes: u64, + pub total_bytes: Option, pub complete: bool, } @@ -277,7 +277,7 @@ pub async fn execute( } *status = Some(Ok(SetupStatus { bytes_transferred: 0, - total_bytes: 0, + total_bytes: None, complete: false, })); drop(status); @@ -306,7 +306,7 @@ pub async fn execute( )); *ctx.setup_status.write().await = Some(Ok(SetupStatus { bytes_transferred: 0, - total_bytes: 0, + total_bytes: None, complete: true, })); } @@ -440,10 +440,9 @@ async fn migrate( old_guid: &str, embassy_password: String, ) -> Result<(Arc, Hostname, OnionAddressV3, X509), Error> { - *ctx.setup_status.write().await = Some(Ok(SetupStatus { bytes_transferred: 0, - total_bytes: 110, + total_bytes: None, complete: false, })); @@ -465,15 +464,6 @@ async fn migrate( exclude: Vec::new(), }, )?; - while let Some(progress) = main_transfer.progress.next().await { - *ctx.setup_status.write().await = Some(Ok(SetupStatus { - bytes_transferred: (progress * 10.0) as u64, - total_bytes: 110, - complete: false, - })); - } - main_transfer.wait().await?; - let mut package_data_transfer = Rsync::new( "/media/embassy/migrate/package-data/", "/embassy-data/package-data/", @@ -484,14 +474,45 @@ async fn migrate( exclude: vec!["tmp".to_owned()], }, )?; - while let Some(progress) = package_data_transfer.progress.next().await { - *ctx.setup_status.write().await = Some(Ok(SetupStatus { - bytes_transferred: 10 + (progress * 100.0) as u64, - total_bytes: 110, - complete: false, - })); + + let mut main_prog = 0.0; + let mut main_complete = false; + let mut pkg_prog = 0.0; + let mut pkg_complete = false; + loop { + tokio::select! { + p = main_transfer.progress.next() => { + if let Some(p) = p { + main_prog = p; + } else { + main_prog = 1.0; + main_complete = true; + } + } + p = package_data_transfer.progress.next() => { + if let Some(p) = p { + pkg_prog = p; + } else { + pkg_prog = 1.0; + pkg_complete = true; + } + } + } + if main_prog > 0.0 && pkg_prog > 0.0 { + *ctx.setup_status.write().await = Some(Ok(SetupStatus { + bytes_transferred: ((main_prog * 50.0) + (pkg_prog * 950.0)) as u64, + total_bytes: Some(1000), + complete: false, + })); + } + if main_complete && pkg_complete { + break; + } } + + main_transfer.wait().await?; package_data_transfer.wait().await?; + let (hostname, tor_addr, root_ca) = setup_init(&ctx, Some(embassy_password)).await?; crate::disk::main::export(&old_guid, "/media/embassy/migrate").await?; diff --git a/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts index 56ebc01f0..b4d6eb9f9 100644 --- a/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts @@ -28,6 +28,7 @@ export class AttachPage { ) {} async ngOnInit() { + this.stateService.setupType = 'attach' await this.getDrives() } diff --git a/frontend/projects/setup-wizard/src/app/pages/home/home.page.html b/frontend/projects/setup-wizard/src/app/pages/home/home.page.html index f6c45c371..38c3594f2 100644 --- a/frontend/projects/setup-wizard/src/app/pages/home/home.page.html +++ b/frontend/projects/setup-wizard/src/app/pages/home/home.page.html @@ -1,5 +1,5 @@ - +
@@ -9,7 +9,7 @@ style="max-width: 220px" />
- + - + Initializing Embassy
- - Progress: {{ (stateService.dataProgress * 100).toFixed(0)}}% + + Progress: {{ (decimal * 100).toFixed(0)}}%
@@ -21,10 +24,10 @@ padding-bottom: 20px; margin-bottom: 40px; " - [type]="stateService.dataProgress ? 'determinate' : 'indeterminate'" - [value]="stateService.dataProgress" + [type]="progress.decimal ? 'determinate' : 'indeterminate'" + [value]="progress.decimal || 0" > -

Setting up your Embassy. This can take a while.

+

{{ progress.decimal | toMessage }}

diff --git a/frontend/projects/setup-wizard/src/app/pages/loading/loading.page.ts b/frontend/projects/setup-wizard/src/app/pages/loading/loading.page.ts index 658b9a55f..6e089c4e8 100644 --- a/frontend/projects/setup-wizard/src/app/pages/loading/loading.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/loading/loading.page.ts @@ -8,14 +8,16 @@ import { StateService } from 'src/app/services/state.service' styleUrls: ['loading.page.scss'], }) export class LoadingPage { + readonly progress$ = this.stateService.dataProgress$ + constructor( - public stateService: StateService, - private navCtrl: NavController, + private readonly stateService: StateService, + private readonly navCtrl: NavController, ) {} ngOnInit() { this.stateService.pollDataTransferProgress() - const progSub = this.stateService.dataCompletionSubject.subscribe( + const progSub = this.stateService.dataCompletionSubject$.subscribe( async complete => { if (complete) { progSub.unsubscribe() @@ -25,3 +27,30 @@ export class LoadingPage { ) } } + +import { Pipe, PipeTransform } from '@angular/core' + +@Pipe({ + name: 'toMessage', +}) +export class ToMessagePipe implements PipeTransform { + constructor(private readonly stateService: StateService) {} + + transform(progress: number | null): string { + switch (this.stateService.setupType) { + case 'fresh': + case 'attach': + return 'Setting up your Embassy' + case 'restore': + return 'Restoring data. This can take a while.' + case 'transfer': + if (!progress) { + return 'Preparing data. Depending on how much data you have, this could take up to 1 hour' + } else { + return 'Transferring data' + } + default: + return '' + } + } +} diff --git a/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts b/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts index 7ae376ef2..ea852d297 100644 --- a/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.ts @@ -25,6 +25,7 @@ export class RecoverPage { ) {} async ngOnInit() { + this.stateService.setupType = 'restore' await this.getDrives() } diff --git a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts index 571e7a377..c85e6c67d 100644 --- a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts @@ -22,6 +22,7 @@ export class TransferPage { ) {} async ngOnInit() { + this.stateService.setupType = 'transfer' await this.getDrives() } diff --git a/frontend/projects/setup-wizard/src/app/services/api/api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/api.service.ts index 54de528c1..93bf7f4cc 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/api.service.ts @@ -29,7 +29,7 @@ type Encrypted = { export type StatusRes = { 'bytes-transferred': number - 'total-bytes': number + 'total-bytes': number | null complete: boolean } | null diff --git a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts index 242ea0db8..e8c62d5fc 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts @@ -31,7 +31,7 @@ export class MockApiService extends ApiService { return { 'bytes-transferred': restoreOrMigrate ? progress : 0, - 'total-bytes': restoreOrMigrate ? total : 0, + 'total-bytes': restoreOrMigrate ? total : null, complete: progress === total, } } diff --git a/frontend/projects/setup-wizard/src/app/services/state.service.ts b/frontend/projects/setup-wizard/src/app/services/state.service.ts index c3971ceb0..9122318a0 100644 --- a/frontend/projects/setup-wizard/src/app/services/state.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/state.service.ts @@ -7,16 +7,18 @@ import { pauseFor, ErrorToastService } from '@start9labs/shared' providedIn: 'root', }) export class StateService { + setupType?: 'fresh' | 'restore' | 'attach' | 'transfer' + recoverySource?: RecoverySource recoveryPassword?: string dataTransferProgress?: { bytesTransferred: number - totalBytes: number + totalBytes: number | null complete: boolean } - dataProgress = 0 - dataCompletionSubject = new BehaviorSubject(false) + dataProgress$ = new BehaviorSubject(0) + dataCompletionSubject$ = new BehaviorSubject(false) constructor( private readonly api: ApiService, @@ -27,7 +29,7 @@ export class StateService { await pauseFor(500) if (this.dataTransferProgress?.complete) { - this.dataCompletionSubject.next(true) + this.dataCompletionSubject$.next(true) return } @@ -41,9 +43,10 @@ export class StateService { complete: progress.complete, } if (this.dataTransferProgress.totalBytes) { - this.dataProgress = + this.dataProgress$.next( this.dataTransferProgress.bytesTransferred / - this.dataTransferProgress.totalBytes + this.dataTransferProgress.totalBytes, + ) } } catch (e: any) { this.errorToastService.present({ diff --git a/frontend/projects/shared/styles/shared.scss b/frontend/projects/shared/styles/shared.scss index c9f2fd81c..59f8f5ca9 100644 --- a/frontend/projects/shared/styles/shared.scss +++ b/frontend/projects/shared/styles/shared.scss @@ -1,5 +1,4 @@ $wide-modal: 900px; -$medium-modal: 600px; body { -webkit-user-select: text; @@ -24,17 +23,16 @@ ion-alert { } } -ion-modal::part(content) { - position: absolute; - height: 90% !important; - top: 5%; - width: 90% !important; - left: 5%; - display: block; - - border-radius: 6px; - border: 2px solid rgba(255, 255, 255, 0.03); - box-shadow: 0 32px 64px rgba(0, 0, 0, 0.2); +ion-modal { + --max-height: 600px; + &::part(content) { + width: 90% !important; + left: 5%; + + border-radius: 6px; + border: 2px solid rgba(255, 255, 255, 0.03); + box-shadow: 0 32px 64px rgba(0, 0, 0, 0.2); + } } .alertlike-modal { @@ -47,33 +45,8 @@ ion-modal::part(content) { } } -.medium-modal { - &::part(content) { - position: absolute; - height: 80% !important; - top: 10%; - width: 90% !important; - left: 5% !important; - } -} - -@media (min-width: 1000px) { - .medium-modal { - &::part(content) { - position: absolute; - height: 80% !important; - top: 10%; - width: $medium-modal !important; - left: calc((100vw - $medium-modal) / 2) !important; - } - } -} - @media (min-width: 1000px) { ion-modal::part(content) { - position: absolute; - height: 80% !important; - top: 10%; width: $wide-modal !important; left: calc((100vw - $wide-modal) / 2) !important; }