| | |
| | | |
| | | Events.On('model:download-progress', (ev: any) => { |
| | | const data = ev?.data |
| | | if (data?.modelID && data.modelID === modelBusyID && typeof data.percent === 'number') { |
| | | if (data?.modelID && typeof data.percent === 'number') { |
| | | modelBusyID = data.modelID |
| | | modelBusyKind = 'download' |
| | | if (modelCancellingID !== data.modelID) { |
| | | modelCancellingID = '' |
| | | } |
| | | modelProgress = data.percent |
| | | } |
| | | }) |
| | | |
| | | Events.On('model:download-cancelled', (ev: any) => { |
| | | const data = ev?.data |
| | | if (data?.modelID) { |
| | | modelBusyID = data.modelID |
| | | modelBusyKind = 'download' |
| | | modelCancellingID = data.modelID |
| | | } |
| | | }) |
| | | |
| | | Events.On('model:download-finished', (ev: any) => { |
| | | const data = ev?.data |
| | | if (!data?.modelID || data.modelID === modelBusyID) { |
| | | clearModelBusy() |
| | | loadModelOptions() |
| | | } |
| | | }) |
| | | |
| | |
| | | applyLanguageSettings(lang) |
| | | } catch {} |
| | | await loadModelOptions() |
| | | await syncModelDownloadStatus() |
| | | settingsLoaded = true |
| | | } |
| | | loadSettings() |
| | |
| | | } catch { |
| | | modelOptions = [] |
| | | } |
| | | } |
| | | |
| | | async function syncModelDownloadStatus(): Promise<boolean> { |
| | | try { |
| | | const status: any = await Call.ByName('voicesnap/services.EngineService.GetModelDownloadStatus') |
| | | return applyModelDownloadStatus(status) |
| | | } catch { |
| | | return false |
| | | } |
| | | } |
| | | |
| | | function applyModelDownloadStatus(status: any): boolean { |
| | | if (status?.active && status?.modelID) { |
| | | modelBusyID = status.modelID |
| | | modelBusyKind = 'download' |
| | | modelCancellingID = status.cancelling ? status.modelID : '' |
| | | modelProgress = typeof status.percent === 'number' ? status.percent : 0 |
| | | modelError = '' |
| | | return true |
| | | } |
| | | if (modelBusyKind === 'download') { |
| | | clearModelBusy() |
| | | } |
| | | return false |
| | | } |
| | | |
| | | function clearModelBusy() { |
| | | modelBusyID = '' |
| | | modelBusyKind = '' |
| | | modelCancellingID = '' |
| | | modelProgress = 0 |
| | | } |
| | | |
| | | function modelDescription(option: ModelOption): string { |
| | |
| | | } |
| | | |
| | | function isCancelError(err: any): boolean { |
| | | const text = String(err?.message || err || '').toLowerCase() |
| | | const text = errorMessage(err).toLowerCase() |
| | | return text.includes('context canceled') || text.includes('cancelled') || text.includes('canceled') |
| | | } |
| | | |
| | | function isAlreadyDownloadingError(err: any): boolean { |
| | | return errorMessage(err).toLowerCase().includes('already downloading') |
| | | } |
| | | |
| | | function errorMessage(err: any): string { |
| | | const raw = String(err?.message || err || '') |
| | | if (!raw.startsWith('{')) return raw |
| | | try { |
| | | const parsed = JSON.parse(raw) |
| | | return String(parsed?.message || raw) |
| | | } catch { |
| | | return raw |
| | | } |
| | | } |
| | | |
| | | function canCancelModel(option: ModelOption): boolean { |
| | |
| | | try { |
| | | const cancelled: any = await Call.ByName('voicesnap/services.EngineService.CancelModelDownload', option.modelID) |
| | | if (!cancelled) { |
| | | modelBusyID = '' |
| | | modelBusyKind = '' |
| | | modelCancellingID = '' |
| | | modelProgress = 0 |
| | | clearModelBusy() |
| | | await loadModelOptions() |
| | | await syncModelDownloadStatus() |
| | | } |
| | | } catch (err: any) { |
| | | modelError = err?.message || String(err || t('settings.modelActionFailed')) |
| | | modelBusyID = '' |
| | | modelBusyKind = '' |
| | | modelCancellingID = '' |
| | | modelProgress = 0 |
| | | modelError = errorMessage(err) || t('settings.modelActionFailed') |
| | | clearModelBusy() |
| | | await loadModelOptions() |
| | | await syncModelDownloadStatus() |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | await loadModelOptions() |
| | | } catch (err: any) { |
| | | if (!isCancelError(err)) { |
| | | modelError = err?.message || String(err || t('settings.modelActionFailed')) |
| | | if (isAlreadyDownloadingError(err)) { |
| | | const active = await syncModelDownloadStatus() |
| | | if (!active) { |
| | | modelError = errorMessage(err) |
| | | } |
| | | } else if (!isCancelError(err)) { |
| | | modelError = errorMessage(err) || t('settings.modelActionFailed') |
| | | } |
| | | await loadModelOptions() |
| | | } finally { |
| | | if (modelBusyID === option.modelID) { |
| | | modelBusyID = '' |
| | | modelBusyKind = '' |
| | | modelCancellingID = '' |
| | | modelProgress = 0 |
| | | const active = await syncModelDownloadStatus() |
| | | if (!active || modelBusyID !== option.modelID) { |
| | | clearModelBusy() |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | applyLanguageSettings(settings) |
| | | await syncEngineForCurrentModel() |
| | | await loadModelOptions() |
| | | await syncModelDownloadStatus() |
| | | } catch { |
| | | languageModeVal = prevMode |
| | | languageIDVal = prevID |