| |
| |
| |
|
|
| import type { AnalysisData } from '../api/GLTR_API'; |
| import type { IDemoStorage, SaveOptions, SaveResult } from '../storage/demoStorage'; |
| import { showConfirmDialog, showAlertDialog } from '../ui/dialog'; |
| import { tr, trf } from '../lang/i18n-lite'; |
|
|
| export interface StorageCallbacks { |
| onStart?: () => void; |
| onSuccess?: (name?: string, result?: SaveResult) => void; |
| onError?: (error: Error) => void; |
| setLoading?: (loading: boolean) => void; |
| showToast?: (message: string, type: 'success' | 'error') => void; |
| |
| |
| |
| |
| |
| showSuccessToast?: boolean; |
| } |
|
|
| |
| |
| |
| export class DemoStorageController { |
| constructor( |
| private storage: IDemoStorage, |
| private callbacks: StorageCallbacks = {} |
| ) {} |
| |
| |
| |
| |
| async save(data: AnalysisData, options: SaveOptions): Promise<SaveResult | null> { |
| const { onStart, onSuccess, onError, setLoading, showToast, showSuccessToast = true } = this.callbacks; |
| |
| onStart?.(); |
| setLoading?.(true); |
| |
| try { |
| const result = await this._doSave(data, options, false); |
| setLoading?.(false); |
| |
| if (result) { |
| onSuccess?.(options.name, result); |
| |
| if (showSuccessToast) { |
| const hint = this.storage.type === 'local' ? tr('Downloaded to local') : tr('Upload successful'); |
| showToast?.(`Demo "${options.name}" ${hint}!`, 'success'); |
| } |
| } |
| |
| return result; |
| } catch (error) { |
| setLoading?.(false); |
| const err = error instanceof Error ? error : new Error(String(error)); |
| onError?.(err); |
| |
| |
| showAlertDialog(tr('Error'), trf('Save failed: {message}', { message: err.message })); |
| return null; |
| } |
| } |
| |
| |
| |
| |
| private async _doSave( |
| data: AnalysisData, |
| options: SaveOptions, |
| overwrite: boolean |
| ): Promise<SaveResult | null> { |
| const result = await this.storage.save(data, { ...options, overwrite }); |
| |
| |
| if (!result.success && result.exists && this.storage.type === 'server') { |
| return new Promise((resolve) => { |
| this.callbacks.setLoading?.(false); |
| showConfirmDialog( |
| tr('File already exists'), |
| trf('File "{name}.json" already exists, overwrite?', { name: options.name }), |
| async () => { |
| this.callbacks.setLoading?.(true); |
| const saved = await this._doSave(data, options, true); |
| resolve(saved); |
| }, |
| () => { |
| this.callbacks.onError?.(new Error(tr('User cancelled save'))); |
| resolve(null); |
| }, |
| tr('Overwrite'), |
| tr('Cancel') |
| ); |
| }); |
| } |
| |
| if (!result.success) { |
| throw new Error(result.message || 'Save failed'); |
| } |
| |
| return result; |
| } |
| |
| |
| |
| |
| async load(path?: string): Promise<AnalysisData | null> { |
| const { onStart, onSuccess, onError, setLoading } = this.callbacks; |
| |
| onStart?.(); |
| setLoading?.(true); |
| |
| try { |
| const result = await this.storage.load(path); |
| setLoading?.(false); |
| |
| if (result.success && result.data) { |
| onSuccess?.(); |
| return result.data; |
| } else { |
| |
| if (result.message) { |
| const err = new Error(result.message || 'Load failed'); |
| onError?.(err); |
| showAlertDialog(tr('Error'), tr(err.message)); |
| } |
| return null; |
| } |
| } catch (error) { |
| setLoading?.(false); |
| const err = error instanceof Error ? error : new Error(String(error)); |
| onError?.(err); |
| showAlertDialog(tr('Error'), trf('Load failed: {message}', { message: err.message })); |
| return null; |
| } |
| } |
| } |
|
|
|
|