Skip to content

Commit

Permalink
improved error handling
Browse files Browse the repository at this point in the history
improved install process
  • Loading branch information
mariotaku committed Feb 6, 2024
1 parent a0d4eb5 commit 4fb94d5
Show file tree
Hide file tree
Showing 16 changed files with 565 additions and 511 deletions.
1 change: 1 addition & 0 deletions src-tauri/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub enum Error {
Disconnected,
ExitStatus {
message: String,
command: String,
exit_code: i32,
stderr: Vec<u8>,
},
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/plugins/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ async fn exec<R: Runtime>(
if exit_code != 0 {
return Err(Error::ExitStatus {
message: format!(""),
command: command.clone(),
exit_code,
stderr,
});
Expand Down
36 changes: 34 additions & 2 deletions src-tauri/src/plugins/local_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::env::temp_dir;
use tauri::plugin::{Builder, TauriPlugin};
use tauri::Runtime;
use tokio::fs::File;
use tokio::io::AsyncReadExt;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use uuid::Uuid;

use crate::error::Error;
Expand All @@ -18,6 +18,36 @@ async fn checksum(path: String, algorithm: String) -> Result<String, Error> {
};
}

#[tauri::command]
async fn download(url: String, target: String) -> Result<(), Error> {
let mut response = reqwest::get(&url)
.await
.map_err(|e| Error::new(format!("Failed to request {}: {}", url, e)))?;
let mut file = File::create(&target)
.await
.map_err(|e| Error::new(format!("Failed to open {} for download: {}", target, e)))?;
while let Some(chunk) = response
.chunk()
.await
.map_err(|e| Error::new(format!("Failed to fetch {}: {}", url, e)))?
{
file.write(&chunk)
.await
.map_err(|e| Error::new(format!("Failed to save downloaded file to {}: {}", url, e)))?;
}
return Ok(());
}

#[tauri::command]
async fn remove(path: String, recursive: bool) -> Result<(), Error> {
if recursive {
tokio::fs::remove_dir_all(&path).await?;
} else {
tokio::fs::remove_file(&path).await?;
}
return Ok(());
}

#[tauri::command]
async fn temp_path(extension: String) -> Result<String, Error> {
let temp_path = temp_dir().join(format!("webos-dev-tmp-{}{}", Uuid::new_v4(), extension));
Expand All @@ -29,6 +59,8 @@ async fn temp_path(extension: String) -> Result<String, Error> {

pub fn plugin<R: Runtime>(name: &'static str) -> TauriPlugin<R> {
Builder::new(name)
.invoke_handler(tauri::generate_handler![checksum, temp_path])
.invoke_handler(tauri::generate_handler![
checksum, download, remove, temp_path
])
.build()
}
2 changes: 1 addition & 1 deletion src/app/apps/apps.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
<div class="p-3 flex-fill overflow-auto" (drop)="dropFiles($event)" (dragover)="onDragOver($event)"
(dragenter)="onDragEnter($event)" (dragleave)="onDragLeave($event)" [ngbNavOutlet]="nav"></div>
<div class="stat-bar border-top bottom-0 mt-auto d-flex flex-row flex-shrink-0 align-items-center">
<app-stat-storage-info class="ms-auto me-3 storage-info-bar" [device]="device"></app-stat-storage-info>
<app-stat-storage-info class="ms-auto me-3 storage-info-bar" [device]="device" #storageInfo></app-stat-storage-info>
</div>
</div>
46 changes: 19 additions & 27 deletions src/app/apps/apps.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
import {noop, Observable, Subscription} from 'rxjs';
import {Device, PackageInfo, RawPackageInfo} from '../types';
import {AppManagerService, DeviceManagerService, RepositoryItem} from '../core/services';
import {MessageDialogComponent} from '../shared/components/message-dialog/message-dialog.component';
import {ProgressDialogComponent} from '../shared/components/progress-dialog/progress-dialog.component';
import {has, keyBy} from 'lodash';
import {keyBy} from 'lodash';
import {open as showOpenDialog} from '@tauri-apps/api/dialog';
import {basename, downloadDir} from "@tauri-apps/api/path";
import {APP_ID_HBCHANNEL} from "../shared/constants";
import {HbchannelRemoveComponent} from "./hbchannel-remove/hbchannel-remove.component";
import {BaseDirectory, writeBinaryFile} from "@tauri-apps/api/fs";
import {LocalFileService} from "../core/services/local-file.service";
import {StatStorageInfoComponent} from "../shared/components/stat-storage-info/stat-storage-info.component";

@Component({
selector: 'app-apps',
Expand All @@ -25,14 +25,15 @@ export class AppsComponent implements OnInit, OnDestroy {
device: Device | null = null;
tabId: string = 'installed';

@ViewChild('storageInfo') storageInfo?: StatStorageInfoComponent;

private deviceSubscription?: Subscription;
private packagesSubscription?: Subscription;

constructor(
private modalService: NgbModal,
private deviceManager: DeviceManagerService,
private appManager: AppManagerService,
private localFiles: LocalFileService,
) {
}

Expand Down Expand Up @@ -107,7 +108,7 @@ export class AppsComponent implements OnInit, OnDestroy {
const progress = ProgressDialogComponent.open(this.modalService);
const component = progress.componentInstance as ProgressDialogComponent;
try {
await this.appManager.installByPath(this.device, file.webkitRelativePath, this.hasHbChannel, (progress, statusText) => {
await this.appManager.installByPath(this.device, file.webkitRelativePath, (progress, statusText) => {
component.progress = progress;
component.message = statusText;
});
Expand All @@ -130,7 +131,7 @@ export class AppsComponent implements OnInit, OnDestroy {
const progress = ProgressDialogComponent.open(this.modalService);
const component = progress.componentInstance as ProgressDialogComponent;
try {
await this.appManager.installByPath(this.device, path, this.hasHbChannel, (progress, statusText) => {
await this.appManager.installByPath(this.device, path, (progress, statusText) => {
component.progress = progress;
component.message = statusText;
});
Expand Down Expand Up @@ -171,6 +172,7 @@ export class AppsComponent implements OnInit, OnDestroy {
const progress = ProgressDialogComponent.open(this.modalService);
try {
await this.appManager.remove(this.device, pkg.id);
this.storageInfo?.refresh();
} catch (e) {
MessageDialogComponent.open(this.modalService, {
message: `Failed to remove ${pkg.title}`,
Expand All @@ -182,42 +184,32 @@ export class AppsComponent implements OnInit, OnDestroy {
}
}

async installPackage(item: RepositoryItem): Promise<void> {
async installPackage(item: RepositoryItem, channel: 'stable' | 'beta' = 'stable'): Promise<void> {
if (!this.device) return;
const progress = ProgressDialogComponent.open(this.modalService);
const component = progress.componentInstance as ProgressDialogComponent;
try {
await this.appManager.installByManifest(this.device, item.manifest!, this.hasHbChannel, (progress, statusText) => {
component.progress = progress;
component.message = statusText;
const manifest = channel === 'stable' ? item.manifest : item.manifestBeta;
if (!manifest) {
MessageDialogComponent.open(this.modalService, {
title: `Failed to install ${item.title}`,
message: `No manifest found for ${item.title} in channel ${channel}`,
positive: 'Close',
});
} catch (e: any) {
this.handleInstallationError(item.title, e as Error);
} finally {
progress.close(true);
return;
}
}

async installBetaPackage(item: RepositoryItem): Promise<void> {
if (!this.device) return;
const progress = ProgressDialogComponent.open(this.modalService);
const component = progress.componentInstance as ProgressDialogComponent;
try {
await this.appManager.installByManifest(this.device, item.manifestBeta!, this.hasHbChannel, (progress, statusText) => {
await this.appManager.installByManifest(this.device, manifest, (progress, statusText) => {
component.progress = progress;
component.message = statusText;
});
} catch (e) {
this.storageInfo?.refresh();
} catch (e: any) {
this.handleInstallationError(item.title, e as Error);
} finally {
progress.close(true);
}
}

private get hasHbChannel(): boolean {
return has(this.instPackages, APP_ID_HBCHANNEL);
}

private handleInstallationError(name: string, e: Error) {
MessageDialogComponent.open(this.modalService, {
title: `Failed to install ${name}`,
Expand Down
2 changes: 1 addition & 1 deletion src/app/apps/channel/channel.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<span class="caret"></span>
</button>
<ul class="dropdown-menu" ngbDropdownMenu>
<li ngbDropdownItem *ngIf="item.manifestBeta" (click)="parent.installBetaPackage(item)">
<li ngbDropdownItem *ngIf="item.manifestBeta" (click)="parent.installPackage(item, 'beta')">
<i class="bi bi-download me-3"></i>Install Beta
</li>
<a ngbDropdownItem *ngIf="manifest?.sourceUrl as url" [href]="url" appExternalLink>
Expand Down
2 changes: 1 addition & 1 deletion src/app/apps/installed/installed.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</button>
<ul class="dropdown-menu" ngbDropdownMenu>
<ng-container *ngIf="rpkg">
<li ngbDropdownItem *ngIf="rpkg.manifestBeta" (click)="parent.installBetaPackage(rpkg)">
<li ngbDropdownItem *ngIf="rpkg.manifestBeta" (click)="parent.installPackage(rpkg, 'beta')">
<i class="bi bi-download me-3"></i>Install Beta
</li>
<li ngbDropdownItem *ngIf="rpkg.manifest?.sourceUrl as url">
Expand Down
Loading

0 comments on commit 4fb94d5

Please sign in to comment.