chore & auto dep
This commit is contained in:
@@ -90,5 +90,8 @@
|
||||
"Continue": "继续",
|
||||
"Check": "查看",
|
||||
"Model file not found": "模型文件不存在",
|
||||
"Can not find download url": "找不到下载地址"
|
||||
"Can not find download url": "找不到下载地址",
|
||||
"Python target not found, would you like to download it?": "没有找到目标Python, 是否下载?",
|
||||
"Python dependencies are incomplete, would you like to install them?": "Python依赖缺失, 是否安装?",
|
||||
"Install": "安装"
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, {FC, MouseEventHandler, ReactElement} from 'react';
|
||||
import commonStore, {ModelStatus} from '../stores/commonStore';
|
||||
import {AddToDownloadList, FileExists, StartServer} from '../../wailsjs/go/backend_golang/App';
|
||||
import {AddToDownloadList, DepCheck, FileExists, InstallPyDep, StartServer} from '../../wailsjs/go/backend_golang/App';
|
||||
import {Button} from '@fluentui/react-components';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
import {exit, readRoot, switchModel, updateConfig} from '../apis';
|
||||
import {toast} from 'react-toastify';
|
||||
import manifest from '../../../manifest.json';
|
||||
import {getStrategy, toastWithButton} from '../utils';
|
||||
import {getStrategy, saveCache, toastWithButton} from '../utils';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {ToolTipButton} from './ToolTipButton';
|
||||
import {Play16Regular, Stop16Regular} from '@fluentui/react-icons';
|
||||
@@ -39,6 +39,32 @@ export const RunButton: FC<{ onClickRun?: MouseEventHandler, iconMode?: boolean
|
||||
const modelName = modelConfig.modelParameters.modelName;
|
||||
const modelPath = `./${manifest.localModelDir}/${modelName}`;
|
||||
|
||||
if (!commonStore.depComplete) {
|
||||
let depErrorMsg = '';
|
||||
await DepCheck().catch((e) => {
|
||||
depErrorMsg = e.message || e;
|
||||
if (depErrorMsg === 'python zip not found') {
|
||||
toastWithButton(t('Python target not found, would you like to download it?'), t('Download'), () => {
|
||||
toastWithButton(`${t('Downloading')} Python`, t('Check'), () => {
|
||||
navigate({pathname: '/downloads'});
|
||||
}, {autoClose: 3000});
|
||||
AddToDownloadList('python-3.10.11-embed-amd64.zip', 'https://www.python.org/ftp/python/3.10.11/python-3.10.11-embed-amd64.zip');
|
||||
});
|
||||
} else if (depErrorMsg.includes('DepCheck Error')) {
|
||||
toastWithButton(t('Python dependencies are incomplete, would you like to install them?'), t('Install'), () => {
|
||||
InstallPyDep();
|
||||
});
|
||||
} else {
|
||||
toast(depErrorMsg, {type: 'error'});
|
||||
}
|
||||
});
|
||||
if (depErrorMsg) {
|
||||
return;
|
||||
}
|
||||
commonStore.setDepComplete(true);
|
||||
saveCache();
|
||||
}
|
||||
|
||||
if (!await FileExists(modelPath)) {
|
||||
toastWithButton(t('Model file not found'), t('Download'), () => {
|
||||
const downloadUrl = commonStore.modelSourceList.find(item => item.name === modelName)?.downloadUrl;
|
||||
|
||||
@@ -256,7 +256,7 @@ export const Configs: FC = observer(() => {
|
||||
toast(`${t('Convert Success')} - ${newModelPath}`, {type: 'success'});
|
||||
refreshLocalModels({models: commonStore.modelSourceList}, false);
|
||||
}).catch(e => {
|
||||
toast(`${t('Convert Failed')} - ${e}`, {type: 'error'});
|
||||
toast(`${t('Convert Failed')} - ${e.message || e}`, {type: 'error'});
|
||||
});
|
||||
} else {
|
||||
toast(`${t('Model Not Found')} - ${modelPath}`, {type: 'error'});
|
||||
|
||||
@@ -4,7 +4,7 @@ import {Page} from '../components/Page';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
import commonStore from '../stores/commonStore';
|
||||
import {Divider, Field, ProgressBar} from '@fluentui/react-components';
|
||||
import {bytesToGb, bytesToMb, refreshLocalModels} from '../utils';
|
||||
import {bytesToGb, bytesToKb, bytesToMb, refreshLocalModels} from '../utils';
|
||||
import {ToolTipButton} from '../components/ToolTipButton';
|
||||
import {Folder20Regular, Pause20Regular, Play20Regular} from '@fluentui/react-icons';
|
||||
import {ContinueDownload, OpenFileFolder, PauseDownload} from '../../wailsjs/go/backend_golang/App';
|
||||
@@ -23,21 +23,31 @@ export type DownloadStatus = {
|
||||
|
||||
export const Downloads: FC = observer(() => {
|
||||
const {t} = useTranslation();
|
||||
const finishedDownloads = commonStore.downloadList.filter((status) => status.done).length;
|
||||
const finishedModelsLen = commonStore.downloadList.filter((status) => status.done && status.name.endsWith('.pth')).length;
|
||||
useEffect(() => {
|
||||
if (finishedDownloads > 0)
|
||||
if (finishedModelsLen > 0)
|
||||
refreshLocalModels({models: commonStore.modelSourceList}, false);
|
||||
console.log('finishedDownloads:', finishedDownloads);
|
||||
}, [finishedDownloads]);
|
||||
console.log('finishedModelsLen:', finishedModelsLen);
|
||||
}, [finishedModelsLen]);
|
||||
|
||||
return (
|
||||
<Page title={t('Downloads')} content={
|
||||
<div className="flex flex-col gap-2 overflow-y-auto overflow-x-hidden p-1">
|
||||
{commonStore.downloadList.map((status, index) => (
|
||||
<div className="flex flex-col gap-1" key={index}>
|
||||
{commonStore.downloadList.slice().reverse().map((status, index) => {
|
||||
const downloadProgress = `${status.progress.toFixed(2)}%`;
|
||||
const downloadSpeed = `${status.downloading ? bytesToMb(status.speed) : '0'}MB/s`;
|
||||
let downloadDetails: string;
|
||||
if (status.size < 1024 * 1024)
|
||||
downloadDetails = `${bytesToKb(status.transferred) + 'KB'}/${bytesToKb(status.size) + 'KB'}`;
|
||||
else if (status.size < 1024 * 1024 * 1024)
|
||||
downloadDetails = `${bytesToMb(status.transferred) + 'MB'}/${bytesToMb(status.size) + 'MB'}`;
|
||||
else
|
||||
downloadDetails = `${bytesToGb(status.transferred) + 'GB'}/${bytesToGb(status.size) + 'GB'}`;
|
||||
|
||||
return <div className="flex flex-col gap-1" key={index}>
|
||||
<Field
|
||||
label={`${status.downloading ? (t('Downloading') + ': ') : ''}${status.name}`}
|
||||
validationMessage={`${status.progress.toFixed(2)}% - ${bytesToGb(status.transferred) + 'GB'}/${bytesToGb(status.size) + 'GB'} - ${status.downloading ? bytesToMb(status.speed) : 0}MB/s - ${status.url}`}
|
||||
validationMessage={`${downloadProgress} - ${downloadDetails} - ${downloadSpeed} - ${status.url}`}
|
||||
validationState={status.done ? 'success' : 'none'}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -57,8 +67,8 @@ export const Downloads: FC = observer(() => {
|
||||
</div>
|
||||
</Field>
|
||||
<Divider style={{flexGrow: 0}}/>
|
||||
</div>
|
||||
))
|
||||
</div>;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
}/>
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
import commonStore from './stores/commonStore';
|
||||
import {ReadJson} from '../wailsjs/go/backend_golang/App';
|
||||
import {Cache, checkUpdate, downloadProgramFiles, LocalConfig, refreshModels} from './utils';
|
||||
import {Cache, checkUpdate, downloadProgramFiles, LocalConfig, refreshModels, saveCache} from './utils';
|
||||
import {getStatus} from './apis';
|
||||
import {EventsOn} from '../wailsjs/runtime';
|
||||
import {defaultModelConfigs} from './pages/Configs';
|
||||
|
||||
export async function startup() {
|
||||
downloadProgramFiles();
|
||||
|
||||
initRemoteText();
|
||||
initCache();
|
||||
await initConfig();
|
||||
|
||||
if (commonStore.settings.autoUpdatesCheck)
|
||||
checkUpdate();
|
||||
|
||||
getStatus(500).then(status => {
|
||||
if (status)
|
||||
commonStore.setModelStatus(status);
|
||||
});
|
||||
|
||||
EventsOn('downloadList', (data) => {
|
||||
if (data)
|
||||
commonStore.setDownloadList(data);
|
||||
});
|
||||
|
||||
initCache().then(initRemoteText);
|
||||
|
||||
await initConfig();
|
||||
|
||||
if (commonStore.settings.autoUpdatesCheck) // depends on config settings
|
||||
checkUpdate();
|
||||
|
||||
getStatus(500).then(status => { // depends on config api port
|
||||
if (status)
|
||||
commonStore.setModelStatus(status);
|
||||
});
|
||||
}
|
||||
|
||||
async function initRemoteText() {
|
||||
@@ -33,7 +32,7 @@ async function initRemoteText() {
|
||||
commonStore.setIntroduction(data.introduction);
|
||||
if (data.about)
|
||||
commonStore.setAbout(data.about);
|
||||
});
|
||||
}).then(saveCache);
|
||||
}
|
||||
|
||||
async function initConfig() {
|
||||
@@ -61,6 +60,8 @@ async function initCache() {
|
||||
commonStore.setIntroduction(cacheData.introduction);
|
||||
if (cacheData.about)
|
||||
commonStore.setAbout(cacheData.about);
|
||||
if (cacheData.depComplete)
|
||||
commonStore.setDepComplete(cacheData.depComplete);
|
||||
}).catch(() => {
|
||||
});
|
||||
await refreshModels(false);
|
||||
|
||||
@@ -24,6 +24,7 @@ class CommonStore {
|
||||
|
||||
// global
|
||||
modelStatus: ModelStatus = ModelStatus.Offline;
|
||||
depComplete: boolean = false;
|
||||
|
||||
// home
|
||||
introduction: IntroductionContent = manifest.introduction;
|
||||
@@ -130,6 +131,10 @@ class CommonStore {
|
||||
this.about = value;
|
||||
};
|
||||
|
||||
setDepComplete = (value: boolean) => {
|
||||
this.depComplete = value;
|
||||
};
|
||||
|
||||
setDownloadList = (value: DownloadStatus[]) => {
|
||||
this.downloadList = value;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
AddToDownloadList,
|
||||
DeleteFile,
|
||||
DownloadFile,
|
||||
FileExists,
|
||||
@@ -23,6 +24,7 @@ export type Cache = {
|
||||
models: ModelSourceItem[]
|
||||
introduction: IntroductionContent,
|
||||
about: AboutContent
|
||||
depComplete: boolean
|
||||
}
|
||||
|
||||
export type LocalConfig = {
|
||||
@@ -153,7 +155,8 @@ export const saveCache = async () => {
|
||||
const data: Cache = {
|
||||
models: commonStore.modelSourceList,
|
||||
introduction: commonStore.introduction,
|
||||
about: commonStore.about
|
||||
about: commonStore.about,
|
||||
depComplete: commonStore.depComplete
|
||||
};
|
||||
return SaveJson('cache.json', data);
|
||||
};
|
||||
@@ -175,7 +178,7 @@ export function downloadProgramFiles() {
|
||||
manifest.programFiles.forEach(({url, path}) => {
|
||||
FileExists(path).then(exists => {
|
||||
if (!exists)
|
||||
DownloadFile(path, url);
|
||||
AddToDownloadList(path, url);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -188,7 +191,7 @@ export function forceDownloadProgramFiles() {
|
||||
|
||||
export function deletePythonProgramFiles() {
|
||||
manifest.programFiles.forEach(({path}) => {
|
||||
if (path.endsWith('.py'))
|
||||
if (path.endsWith('.py') && !path.includes('get-pip.py'))
|
||||
DeleteFile(path);
|
||||
});
|
||||
}
|
||||
@@ -201,6 +204,10 @@ export function bytesToMb(size: number) {
|
||||
return (size / 1024 / 1024).toFixed(2);
|
||||
}
|
||||
|
||||
export function bytesToKb(size: number) {
|
||||
return (size / 1024).toFixed(2);
|
||||
}
|
||||
|
||||
export async function checkUpdate() {
|
||||
let updateUrl = '';
|
||||
await fetch('https://api.github.com/repos/josstorer/RWKV-Runner/releases/latest').then((r) => {
|
||||
@@ -214,7 +221,7 @@ export async function checkUpdate() {
|
||||
deletePythonProgramFiles();
|
||||
setTimeout(() => {
|
||||
UpdateApp(updateUrl).catch((e) => {
|
||||
toast(t('Update Error, Please restart this program') + ' - ' + e.message, {
|
||||
toast(t('Update Error, Please restart this program') + ' - ' + e.message || e, {
|
||||
type: 'error',
|
||||
position: 'bottom-left',
|
||||
autoClose: false
|
||||
@@ -235,7 +242,7 @@ export async function checkUpdate() {
|
||||
}
|
||||
}
|
||||
).catch((e) => {
|
||||
toast(t('Updates Check Error') + ' - ' + e.message, {type: 'error', position: 'bottom-left'});
|
||||
toast(t('Updates Check Error') + ' - ' + e.message || e, {type: 'error', position: 'bottom-left'});
|
||||
});
|
||||
return updateUrl;
|
||||
}
|
||||
|
||||
6
frontend/wailsjs/go/backend_golang/App.d.ts
vendored
6
frontend/wailsjs/go/backend_golang/App.d.ts
vendored
@@ -10,10 +10,16 @@ export function ConvertModel(arg1:string,arg2:string,arg3:string):Promise<string
|
||||
|
||||
export function DeleteFile(arg1:string):Promise<void>;
|
||||
|
||||
export function DepCheck():Promise<void>;
|
||||
|
||||
export function DownloadFile(arg1:string,arg2:string):Promise<void>;
|
||||
|
||||
export function FileExists(arg1:string):Promise<boolean>;
|
||||
|
||||
export function GetPlatform():Promise<string>;
|
||||
|
||||
export function InstallPyDep():Promise<string>;
|
||||
|
||||
export function ListDirFiles(arg1:string):Promise<Array<backend_golang.FileInfo>>;
|
||||
|
||||
export function OpenFileFolder(arg1:string):Promise<void>;
|
||||
|
||||
@@ -18,6 +18,10 @@ export function DeleteFile(arg1) {
|
||||
return window['go']['backend_golang']['App']['DeleteFile'](arg1);
|
||||
}
|
||||
|
||||
export function DepCheck() {
|
||||
return window['go']['backend_golang']['App']['DepCheck']();
|
||||
}
|
||||
|
||||
export function DownloadFile(arg1, arg2) {
|
||||
return window['go']['backend_golang']['App']['DownloadFile'](arg1, arg2);
|
||||
}
|
||||
@@ -26,6 +30,14 @@ export function FileExists(arg1) {
|
||||
return window['go']['backend_golang']['App']['FileExists'](arg1);
|
||||
}
|
||||
|
||||
export function GetPlatform() {
|
||||
return window['go']['backend_golang']['App']['GetPlatform']();
|
||||
}
|
||||
|
||||
export function InstallPyDep() {
|
||||
return window['go']['backend_golang']['App']['InstallPyDep']();
|
||||
}
|
||||
|
||||
export function ListDirFiles(arg1) {
|
||||
return window['go']['backend_golang']['App']['ListDirFiles'](arg1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user