add client upgrade progress

This commit is contained in:
josc146 2023-11-09 21:38:02 +08:00
parent f03c9cf25f
commit 4f0558ae34
2 changed files with 79 additions and 20 deletions

View File

@ -4,12 +4,14 @@ import (
"bufio" "bufio"
"context" "context"
"errors" "errors"
"io"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"syscall" "syscall"
"time"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/minio/selfupdate" "github.com/minio/selfupdate"
@ -118,13 +120,50 @@ func (a *App) monitorHardware() {
monitor.Start() monitor.Start()
} }
type ProgressReader struct {
reader io.Reader
total int64
err error
}
func (pr *ProgressReader) Read(p []byte) (n int, err error) {
n, err = pr.reader.Read(p)
pr.err = err
pr.total += int64(n)
return
}
func (a *App) UpdateApp(url string) (broken bool, err error) { func (a *App) UpdateApp(url string) (broken bool, err error) {
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
return false, err return false, err
} }
defer resp.Body.Close() defer resp.Body.Close()
err = selfupdate.Apply(resp.Body, selfupdate.Options{}) pr := &ProgressReader{reader: resp.Body}
ticker := time.NewTicker(250 * time.Millisecond)
defer ticker.Stop()
go func() {
for {
<-ticker.C
wruntime.EventsEmit(a.ctx, "updateApp", &DownloadStatus{
Name: filepath.Base(url),
Path: "",
Url: url,
Transferred: pr.total,
Size: resp.ContentLength,
Speed: 0,
Progress: 100 * (float64(pr.total) / float64(resp.ContentLength)),
Downloading: pr.err == nil && pr.total < resp.ContentLength,
Done: pr.total == resp.ContentLength,
})
if pr.err != nil || pr.total == resp.ContentLength {
break
}
}
}()
err = selfupdate.Apply(pr, selfupdate.Options{})
if err != nil { if err != nil {
if rerr := selfupdate.RollbackError(err); rerr != nil { if rerr := selfupdate.RollbackError(err); rerr != nil {
return true, rerr return true, rerr

View File

@ -15,7 +15,7 @@ import { toast } from 'react-toastify';
import { t } from 'i18next'; import { t } from 'i18next';
import { ToastOptions } from 'react-toastify/dist/types'; import { ToastOptions } from 'react-toastify/dist/types';
import { Button } from '@fluentui/react-components'; import { Button } from '@fluentui/react-components';
import { BrowserOpenURL, WindowShow } from '../../wailsjs/runtime'; import { BrowserOpenURL, EventsOff, EventsOn, WindowShow } from '../../wailsjs/runtime';
import { NavigateFunction } from 'react-router'; import { NavigateFunction } from 'react-router';
import { ModelConfig, ModelParameters } from '../types/configs'; import { ModelConfig, ModelParameters } from '../types/configs';
import { DownloadStatus } from '../types/downloads'; import { DownloadStatus } from '../types/downloads';
@ -333,27 +333,47 @@ export async function checkUpdate(notifyEvenLatest: boolean = false) {
`https://gitee.com/josc146/RWKV-Runner/releases/download/${versionTag}/${asset.name}`; `https://gitee.com/josc146/RWKV-Runner/releases/download/${versionTag}/${asset.name}`;
toastWithButton(t('New Version Available') + ': ' + versionTag, t('Update'), () => { toastWithButton(t('New Version Available') + ': ' + versionTag, t('Update'), () => {
DeleteFile('cache.json'); DeleteFile('cache.json');
toast(t('Downloading update, please wait. If it is not completed, please manually download the program from GitHub and replace the original program.'), { const progressId = 'update_app';
type: 'info', const progressEvent = 'updateApp';
position: 'bottom-left', const updateProgress = (ds: DownloadStatus | null) => {
autoClose: false const content =
}); t('Downloading update, please wait. If it is not completed, please manually download the program from GitHub and replace the original program.')
setTimeout(() => { + (ds ? ` (${ds.progress.toFixed(2)}% ${bytesToReadable(ds.transferred)}/${bytesToReadable(ds.size)})` : '');
UpdateApp(updateUrl).then(() => { const options: ToastOptions = {
toast(t('Update completed, please restart the program.'), { type: 'info',
type: 'success', position: 'bottom-left',
position: 'bottom-left', autoClose: false,
autoClose: false toastId: progressId,
} hideProgressBar: false,
); progress: ds ? ds.progress / 100 : 0
}).catch((e) => { };
toast(t('Update Error') + ' - ' + (e.message || e), { if (toast.isActive(progressId))
type: 'error', toast.update(progressId, {
render: content,
...options
});
else
toast(content, options);
};
updateProgress(null);
EventsOn(progressEvent, updateProgress);
UpdateApp(updateUrl).then(() => {
toast(t('Update completed, please restart the program.'), {
type: 'success',
position: 'bottom-left', position: 'bottom-left',
autoClose: false autoClose: false
}); }
);
}).catch((e) => {
toast(t('Update Error') + ' - ' + (e.message || e), {
type: 'error',
position: 'bottom-left',
autoClose: false
}); });
}, 500); }).finally(() => {
toast.dismiss(progressId);
EventsOff(progressEvent);
});
}, { }, {
autoClose: false, autoClose: false,
position: 'bottom-left' position: 'bottom-left'