🐛 fix version handling and improve IPC communication for downloads
This commit is contained in:
parent
8d56faeb80
commit
2edbbcb871
@ -11,7 +11,9 @@ class ServerController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveConfig(req: ControllerParam) {
|
saveConfig(req: ControllerParam) {
|
||||||
console.log("save", req.args);
|
this._serverService.saveServerConfig(req.args).then(() => {
|
||||||
|
req.event.reply(req.channel, success());
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getServerConfig(req: ControllerParam) {
|
getServerConfig(req: ControllerParam) {
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import BaseController from "./BaseController";
|
import BaseController from "./BaseController";
|
||||||
import VersionService from "../service/VersionService";
|
import VersionService from "../service/VersionService";
|
||||||
import { success } from "../utils/response";
|
import { fail, success } from "../utils/response";
|
||||||
|
import VersionDao from "../dao/VersionDao";
|
||||||
|
|
||||||
class VersionController extends BaseController {
|
class VersionController extends BaseController {
|
||||||
private readonly _versionService: VersionService;
|
private readonly _versionService: VersionService;
|
||||||
|
private readonly _versionDao: VersionDao;
|
||||||
|
|
||||||
constructor(versionService: VersionService) {
|
constructor(versionService: VersionService, versionDao: VersionDao) {
|
||||||
super();
|
super();
|
||||||
this._versionService = versionService;
|
this._versionService = versionService;
|
||||||
|
this._versionDao = versionDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
getVersions(req: ControllerParam) {
|
getVersions(req: ControllerParam) {
|
||||||
@ -22,6 +25,43 @@ class VersionController extends BaseController {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDownloadedVersions(req: ControllerParam) {
|
||||||
|
this._versionDao.findAll().then(data => {
|
||||||
|
req.event.reply(req.channel, success(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadFrpVersion(req: ControllerParam) {
|
||||||
|
this._versionService
|
||||||
|
.downloadFrpVersion(req.args.githubReleaseId, progress => {
|
||||||
|
req.event.reply(
|
||||||
|
req.channel,
|
||||||
|
success({
|
||||||
|
percent: progress.percent,
|
||||||
|
githubReleaseId: req.args.githubReleaseId,
|
||||||
|
completed: progress.percent >= 1
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.then(r => {
|
||||||
|
console.log(2);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteDownloadedVersion(req: ControllerParam) {
|
||||||
|
this._versionService
|
||||||
|
.deleteFrpVersion(req.args.githubReleaseId)
|
||||||
|
.then(() => {
|
||||||
|
req.event.reply(req.channel, success());
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
req.event.reply(req.channel, fail());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VersionController;
|
export default VersionController;
|
||||||
|
26
electron/core/BeanFactory.ts
Normal file
26
electron/core/BeanFactory.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* todo DI
|
||||||
|
*/
|
||||||
|
class BeanFactory {
|
||||||
|
private static _beans: Map<string, any> = new Map<string, any>();
|
||||||
|
|
||||||
|
private static registerBean(name: string, instance: any): void {
|
||||||
|
if (!this._beans.has(name)) {
|
||||||
|
this._beans.set(name, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getBean<T>(name: string): T {
|
||||||
|
return this._beans.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static hasBean(name: string): boolean {
|
||||||
|
return this._beans.has(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static clear(): void {
|
||||||
|
this._beans.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BeanFactory;
|
@ -1,13 +1,22 @@
|
|||||||
import path from "path";
|
|
||||||
import { app } from "electron";
|
|
||||||
import SecureUtils from "../utils/SecureUtils";
|
|
||||||
|
|
||||||
class GlobalConstant {
|
class GlobalConstant {
|
||||||
public static FRPC_STORAGE_FOLDER = "";
|
public static APP_NAME = "Frpc Desktop";
|
||||||
|
|
||||||
public static ZIP_EXT = ".zip";
|
public static ZIP_EXT = ".zip";
|
||||||
public static GZ_EXT = ".gz";
|
public static GZ_EXT = ".gz";
|
||||||
public static TAR_GZ_EXT = ".tar.gz";
|
public static TAR_GZ_EXT = ".tar.gz";
|
||||||
|
|
||||||
|
public static FRP_ARCH_VERSION_MAPPING = {
|
||||||
|
win32_x64: ["window", "amd64"],
|
||||||
|
win32_arm64: ["window", "arm64"],
|
||||||
|
win32_ia32: ["window", "386"],
|
||||||
|
darwin_arm64: ["darwin", "arm64"],
|
||||||
|
darwin_x64: ["darwin", "amd64"],
|
||||||
|
darwin_amd64: ["darwin", "amd64"],
|
||||||
|
linux_x64: ["linux", "amd64"],
|
||||||
|
linux_arm64: ["linux", "arm64"]
|
||||||
|
};
|
||||||
|
|
||||||
|
public static FRPC_PROCESS_STATUS_CHECK_INTERVAL = 3000;
|
||||||
// public static APP_DATA_PATH = app.getPath("userData");
|
// public static APP_DATA_PATH = app.getPath("userData");
|
||||||
|
|
||||||
// public static DOWNLOAD_STORAGE_PATH = path.join(
|
// public static DOWNLOAD_STORAGE_PATH = path.join(
|
||||||
|
@ -35,6 +35,18 @@ export const ipcRouters: IpcRouters = {
|
|||||||
getVersions: {
|
getVersions: {
|
||||||
path: "version/getVersions",
|
path: "version/getVersions",
|
||||||
controller: "versionController.getVersions"
|
controller: "versionController.getVersions"
|
||||||
|
},
|
||||||
|
downloadVersion: {
|
||||||
|
path: "version/downloadVersion",
|
||||||
|
controller: "versionController.downloadFrpVersion"
|
||||||
|
},
|
||||||
|
getDownloadedVersions: {
|
||||||
|
path: "version/getDownloadedVersions",
|
||||||
|
controller: "versionController.getDownloadedVersions"
|
||||||
|
},
|
||||||
|
deleteDownloadedVersion: {
|
||||||
|
path: "version/deleteDownloadedVersion",
|
||||||
|
controller: "versionController.deleteDownloadedVersion"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -68,7 +80,7 @@ class IpcRouterConfigurate {
|
|||||||
);
|
);
|
||||||
const logService = new LogService(fileService);
|
const logService = new LogService(fileService);
|
||||||
const serverController = new ServerController(serverService);
|
const serverController = new ServerController(serverService);
|
||||||
const versionController = new VersionController(versionService);
|
const versionController = new VersionController(versionService, versionDao);
|
||||||
const logController = new LogController(logService);
|
const logController = new LogController(logService);
|
||||||
|
|
||||||
this._beans.set("serverDao", serverDao);
|
this._beans.set("serverDao", serverDao);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import Datastore from "nedb";
|
import Datastore from "nedb";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import Snowflakify from "snowflakify";
|
|
||||||
import GlobalConstant from "../core/GlobalConstant";
|
|
||||||
import PathUtils from "../utils/PathUtils";
|
import PathUtils from "../utils/PathUtils";
|
||||||
|
import IdUtils from "../utils/IdUtils";
|
||||||
|
|
||||||
// interface BaseDaoInterface<T> {
|
// interface BaseDaoInterface<T> {
|
||||||
// db: Datastore;
|
// db: Datastore;
|
||||||
@ -25,10 +24,7 @@ class BaseDao<T> {
|
|||||||
protected readonly db: Datastore;
|
protected readonly db: Datastore;
|
||||||
|
|
||||||
constructor(dbName: string) {
|
constructor(dbName: string) {
|
||||||
const dbFilename = path.join(
|
const dbFilename = path.join(PathUtils.getAppData(), `${dbName}-v2.db`);
|
||||||
PathUtils.getAppData(),
|
|
||||||
`${dbName}-v2.db`
|
|
||||||
);
|
|
||||||
this.db = new Datastore({
|
this.db = new Datastore({
|
||||||
autoload: true,
|
autoload: true,
|
||||||
filename: dbFilename
|
filename: dbFilename
|
||||||
@ -83,10 +79,17 @@ class BaseDao<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
deleteById(id: string): Promise<void> {
|
||||||
// deleteById(id: string): void {
|
return new Promise<void>((resolve, reject) => {
|
||||||
// return null;
|
this.db.remove({ _id: id }, err => {
|
||||||
// }
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// findAll(): T[] {
|
// findAll(): T[] {
|
||||||
// return null;
|
// return null;
|
||||||
@ -103,6 +106,18 @@ class BaseDao<T> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findAll(): Promise<Array<T>> {
|
||||||
|
return new Promise<Array<T>>((resolve, reject) => {
|
||||||
|
this.db.find({}, (err, document) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(document);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BaseDao;
|
export default BaseDao;
|
||||||
|
@ -18,7 +18,7 @@ class VersionDao extends BaseDao<FrpcVersion> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exists(githubReleaseId: number): Promise<boolean> {
|
exists(githubReleaseId: number): Promise<boolean> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise(( resolve, reject) => {
|
||||||
this.db.count({ githubReleaseId: githubReleaseId }, (err, count) => {
|
this.db.count({ githubReleaseId: githubReleaseId }, (err, count) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
|
@ -4,8 +4,9 @@ import fs from "fs";
|
|||||||
import zlib from "zlib";
|
import zlib from "zlib";
|
||||||
import admZip from "adm-zip";
|
import admZip from "adm-zip";
|
||||||
import GlobalConstant from "../core/GlobalConstant";
|
import GlobalConstant from "../core/GlobalConstant";
|
||||||
import { logError, logInfo, LogModule } from "../utils/log";
|
|
||||||
// import tar from "tar";
|
// import tar from "tar";
|
||||||
|
const tar = require("tar");
|
||||||
|
|
||||||
class FileService {
|
class FileService {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
@ -49,37 +50,40 @@ class FileService {
|
|||||||
// const frpcPath = path.join("frp", path.basename(zipFilePath, zipExt));
|
// const frpcPath = path.join("frp", path.basename(zipFilePath, zipExt));
|
||||||
}
|
}
|
||||||
|
|
||||||
decompressTarGzFile(tarGzPath: string, targetPath: string) {
|
decompressTarGzFile(tarGzPath: string, targetPath: string, finish: Function) {
|
||||||
// const targetFolder = path.join(targetPath, targetPath);
|
// const targetFolder = path.join(targetPath, targetPath);
|
||||||
const unzip = zlib.createGunzip();
|
const unzip = zlib.createGunzip();
|
||||||
const readStream = fs.createReadStream(tarGzPath);
|
const readStream = fs.createReadStream(tarGzPath);
|
||||||
// if (!fs.existsSync(unzip)) {
|
if (!fs.existsSync(targetPath)) {
|
||||||
// fs.mkdirSync(targetPath, { recursive: true, mode: 0o777 });
|
fs.mkdirSync(targetPath, { recursive: true, mode: 0o777 });
|
||||||
// }
|
}
|
||||||
|
|
||||||
readStream
|
readStream
|
||||||
.pipe(unzip)
|
.pipe(unzip)
|
||||||
.on("error", err => {
|
.on("error", err => {
|
||||||
logError(LogModule.APP, `Error during gunzip: ${err.message}`);
|
// logError(LogModule.APP, `Error during gunzip: ${err.message}`);
|
||||||
})
|
})
|
||||||
// .pipe(
|
.pipe(
|
||||||
// tar
|
tar
|
||||||
// .extract({
|
.extract({
|
||||||
// cwd: targetPath,
|
cwd: targetPath,
|
||||||
// filter: filePath => path.basename(filePath) === "frpc"
|
strip: 1,
|
||||||
// })
|
filter: filePath => path.basename(filePath) === "frpc"
|
||||||
// .on("error", err => {
|
})
|
||||||
// logError(
|
.on("error", err => {
|
||||||
// LogModule.APP,
|
// logError(
|
||||||
// `Error extracting tar file: ${err.message}`
|
// LogModule.APP,
|
||||||
// );
|
// `Error extracting tar file: ${err.message}`
|
||||||
// })
|
// );
|
||||||
// )
|
})
|
||||||
|
)
|
||||||
.on("finish", () => {
|
.on("finish", () => {
|
||||||
const frpcPath = path.join("frp", path.basename(tarGzPath, ".tar.gz"));
|
finish();
|
||||||
logInfo(
|
// const frpcPath = path.join("frp", path.basename(tarGzPath, ".tar.gz"));
|
||||||
LogModule.APP,
|
// logInfo(
|
||||||
`Extraction completed. Extracted directory: ${frpcPath}`
|
// LogModule.APP,
|
||||||
);
|
// `Extraction completed. Extracted directory: ${frpcPath}`
|
||||||
|
// );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
74
electron/service/FrpProcessService.ts
Normal file
74
electron/service/FrpProcessService.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import ServerService from "./ServerService";
|
||||||
|
import VersionDao from "../dao/VersionDao";
|
||||||
|
import PathUtils from "../utils/PathUtils";
|
||||||
|
import { frpcProcess } from "../api/frpc";
|
||||||
|
import GlobalConstant from "../core/GlobalConstant";
|
||||||
|
import { Notification } from "electron";
|
||||||
|
|
||||||
|
const { exec, spawn } = require("child_process");
|
||||||
|
|
||||||
|
class FrpProcessService {
|
||||||
|
private readonly _serverService: ServerService;
|
||||||
|
private readonly _versionDao: VersionDao;
|
||||||
|
private _frpcProcess: any;
|
||||||
|
private _FrpcProcessListener: any;
|
||||||
|
|
||||||
|
constructor(serverService: ServerService, versionDao: VersionDao) {
|
||||||
|
this._serverService = serverService;
|
||||||
|
this._versionDao = versionDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunning(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async startFrpcProcess() {
|
||||||
|
const config = await this._serverService.getServerConfig();
|
||||||
|
const version = await this._versionDao.findByGithubReleaseId(
|
||||||
|
config.frpcVersion
|
||||||
|
);
|
||||||
|
// todo genConfigfile.
|
||||||
|
const configPath = "";
|
||||||
|
const command = `${PathUtils.getFrpcFilename()} -c ${configPath}`;
|
||||||
|
this._frpcProcess = spawn(command, {
|
||||||
|
cwd: version.localPath,
|
||||||
|
shell: true
|
||||||
|
});
|
||||||
|
|
||||||
|
frpcProcess.stdout.on("data", data => {
|
||||||
|
// logDebug(LogModule.FRP_CLIENT, `Frpc process output: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
frpcProcess.stdout.on("error", data => {
|
||||||
|
// logError(LogModule.FRP_CLIENT, `Frpc process error: ${data}`);
|
||||||
|
// stopFrpcProcess(() => {});
|
||||||
|
this.stopFrpcProcess();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
stopFrpcProcess() {}
|
||||||
|
|
||||||
|
watchFrpcProcess(listenerParam: ListenerParam) {
|
||||||
|
this._FrpcProcessListener = setInterval(() => {
|
||||||
|
const running = this.isRunning();
|
||||||
|
// todo return status to view.
|
||||||
|
// logDebug(
|
||||||
|
// LogModule.FRP_CLIENT,
|
||||||
|
// `Monitoring frpc process status: ${status}, Listener ID: ${frpcStatusListener}`
|
||||||
|
// );
|
||||||
|
if (!running) {
|
||||||
|
new Notification({
|
||||||
|
title: GlobalConstant.APP_NAME,
|
||||||
|
body: "Connection lost, please check the logs for details."
|
||||||
|
}).show();
|
||||||
|
// logError(
|
||||||
|
// LogModule.FRP_CLIENT,
|
||||||
|
// "Frpc process status check failed. Connection lost."
|
||||||
|
// );
|
||||||
|
clearInterval(this._FrpcProcessListener);
|
||||||
|
}
|
||||||
|
}, GlobalConstant.FRPC_PROCESS_STATUS_CHECK_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FrpProcessService;
|
@ -8,26 +8,14 @@ class ServerService extends BaseService<FrpcDesktopServer> {
|
|||||||
this._serverDao = serverDao;
|
this._serverDao = serverDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveServerConfig(frpcServer: FrpcDesktopServer): Promise<void> {
|
async saveServerConfig(
|
||||||
return new Promise((resolve, reject) => {
|
frpcServer: FrpcDesktopServer
|
||||||
this._serverDao
|
): Promise<FrpcDesktopServer> {
|
||||||
.updateById("1", frpcServer)
|
return await this._serverDao.updateById("1", frpcServer);
|
||||||
.then(() => {
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch(err => reject(err));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getServerConfig(): Promise<FrpcDesktopServer> {
|
async getServerConfig(): Promise<FrpcDesktopServer> {
|
||||||
return new Promise((resolve, reject) => {
|
return await this._serverDao.findById("1");
|
||||||
this._serverDao
|
|
||||||
.findById("1")
|
|
||||||
.then((frpcServer: FrpcDesktopServer) => {
|
|
||||||
resolve(frpcServer);
|
|
||||||
})
|
|
||||||
.catch(err => reject(err));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasServerConfig(): Promise<boolean> {
|
hasServerConfig(): Promise<boolean> {
|
||||||
|
@ -8,23 +8,9 @@ import { BrowserWindow } from "electron";
|
|||||||
import GlobalConstant from "../core/GlobalConstant";
|
import GlobalConstant from "../core/GlobalConstant";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import FileUtils from "../utils/FileUtils";
|
|
||||||
import SecureUtils from "../utils/SecureUtils";
|
import SecureUtils from "../utils/SecureUtils";
|
||||||
import PathUtils from "../utils/PathUtils";
|
import PathUtils from "../utils/PathUtils";
|
||||||
|
import FileUtils from "../utils/FileUtils";
|
||||||
/**
|
|
||||||
* arch mapping
|
|
||||||
*/
|
|
||||||
const versionMapping = {
|
|
||||||
win32_x64: ["window", "amd64"],
|
|
||||||
win32_arm64: ["window", "arm64"],
|
|
||||||
win32_ia32: ["window", "386"],
|
|
||||||
darwin_arm64: ["darwin", "arm64"],
|
|
||||||
darwin_x64: ["darwin", "amd64"],
|
|
||||||
darwin_amd64: ["darwin", "amd64"],
|
|
||||||
linux_x64: ["linux", "amd64"],
|
|
||||||
linux_arm64: ["linux", "arm64"]
|
|
||||||
};
|
|
||||||
|
|
||||||
class VersionService extends BaseService<FrpcVersion> {
|
class VersionService extends BaseService<FrpcVersion> {
|
||||||
private readonly _versionDao: VersionDao;
|
private readonly _versionDao: VersionDao;
|
||||||
@ -43,7 +29,7 @@ class VersionService extends BaseService<FrpcVersion> {
|
|||||||
this._gitHubService = gitHubService;
|
this._gitHubService = gitHubService;
|
||||||
this._fileService = fileService;
|
this._fileService = fileService;
|
||||||
const nodeVersion = `${process.platform}_${process.arch}`;
|
const nodeVersion = `${process.platform}_${process.arch}`;
|
||||||
this._currFrpArch = versionMapping[nodeVersion];
|
this._currFrpArch = GlobalConstant.FRP_ARCH_VERSION_MAPPING[nodeVersion];
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadFrpVersion(githubReleaseId: number, onProgress: Function) {
|
downloadFrpVersion(githubReleaseId: number, onProgress: Function) {
|
||||||
@ -65,6 +51,9 @@ class VersionService extends BaseService<FrpcVersion> {
|
|||||||
SecureUtils.calculateMD5(version.name)
|
SecureUtils.calculateMD5(version.name)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (fs.existsSync(versionFilePath)) {
|
||||||
|
fs.rmSync(versionFilePath, { recursive: true, force: true });
|
||||||
|
}
|
||||||
// const targetPath = path.resolve();
|
// const targetPath = path.resolve();
|
||||||
download(BrowserWindow.getFocusedWindow(), url, {
|
download(BrowserWindow.getFocusedWindow(), url, {
|
||||||
filename: `${version.assetName}`,
|
filename: `${version.assetName}`,
|
||||||
@ -73,42 +62,78 @@ class VersionService extends BaseService<FrpcVersion> {
|
|||||||
onProgress(progress);
|
onProgress(progress);
|
||||||
},
|
},
|
||||||
onCompleted: () => {
|
onCompleted: () => {
|
||||||
if (fs.existsSync(versionFilePath)) {
|
|
||||||
fs.rmSync(versionFilePath, { recursive: true, force: true });
|
|
||||||
}
|
|
||||||
const ext = path.extname(version.assetName);
|
const ext = path.extname(version.assetName);
|
||||||
if (ext === GlobalConstant.ZIP_EXT) {
|
if (ext === GlobalConstant.ZIP_EXT) {
|
||||||
this._fileService.decompressZipFile(
|
this._fileService.decompressZipFile(
|
||||||
downloadedFilePath,
|
downloadedFilePath,
|
||||||
versionFilePath
|
versionFilePath
|
||||||
);
|
);
|
||||||
|
// todo delete frps and other file.
|
||||||
} else if (
|
} else if (
|
||||||
ext === GlobalConstant.GZ_EXT &&
|
ext === GlobalConstant.GZ_EXT &&
|
||||||
version.assetName.includes(GlobalConstant.TAR_GZ_EXT)
|
version.assetName.includes(GlobalConstant.TAR_GZ_EXT)
|
||||||
) {
|
) {
|
||||||
this._fileService.decompressTarGzFile(
|
this._fileService.decompressTarGzFile(
|
||||||
downloadedFilePath,
|
downloadedFilePath,
|
||||||
versionFilePath
|
versionFilePath,
|
||||||
|
() => {
|
||||||
|
// rename frpc.
|
||||||
|
const frpcFilePath = path.join(versionFilePath, "frpc");
|
||||||
|
if (fs.existsSync(frpcFilePath)) {
|
||||||
|
const newFrpcFilePath = path.join(
|
||||||
|
versionFilePath,
|
||||||
|
PathUtils.getFrpcFilename()
|
||||||
|
);
|
||||||
|
fs.renameSync(frpcFilePath, newFrpcFilePath);
|
||||||
|
}
|
||||||
|
// delete downloaded file.
|
||||||
|
// todo has bug.
|
||||||
|
const downloadedFile = path.join(
|
||||||
|
PathUtils.getDownloadStoragePath(),
|
||||||
|
version.assetName
|
||||||
|
);
|
||||||
|
if (fs.existsSync(downloadedFile)) {
|
||||||
|
fs.rmSync(downloadedFile, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo 2025-02-23 delete downloaded file.
|
||||||
version.localPath = versionFilePath;
|
version.localPath = versionFilePath;
|
||||||
this._versionDao.insert(version).then(data => {
|
version.downloaded = true;
|
||||||
resolve(data);
|
this._versionDao
|
||||||
});
|
.insert(version)
|
||||||
|
.then(data => {
|
||||||
|
resolve(data);
|
||||||
|
})
|
||||||
|
.catch(err => reject(err));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteFrpVersion() {}
|
async deleteFrpVersion(githubReleaseId: number) {
|
||||||
|
if (!githubReleaseId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const version = await this._versionDao.findByGithubReleaseId(
|
||||||
|
githubReleaseId
|
||||||
|
);
|
||||||
|
if (this.frpcVersionExists(version)) {
|
||||||
|
fs.rmSync(version.localPath, { recursive: true, force: true });
|
||||||
|
await this._versionDao.deleteById(version._id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getFrpVersionsByGitHub(): Promise<Array<FrpcVersion>> {
|
async getFrpVersionsByGitHub(): Promise<Array<FrpcVersion>> {
|
||||||
return new Promise<Array<FrpcVersion>>((resolve, reject) => {
|
return new Promise<Array<FrpcVersion>>((resolve, reject) => {
|
||||||
this._gitHubService
|
this._gitHubService
|
||||||
.getGithubRepoAllReleases("fatedier/frp")
|
.getGithubRepoAllReleases("fatedier/frp")
|
||||||
.then((releases: Array<GithubRelease>) => {
|
.then(async (releases: Array<GithubRelease>) => {
|
||||||
const versions: Array<FrpcVersion> =
|
const versions: Array<FrpcVersion> =
|
||||||
this.githubRelease2FrpcVersion(releases);
|
await this.githubRelease2FrpcVersion(releases);
|
||||||
|
// const versions: Array<FrpcVersion> = (this.versions = versions);
|
||||||
this.versions = versions;
|
this.versions = versions;
|
||||||
resolve(versions);
|
resolve(versions);
|
||||||
})
|
})
|
||||||
@ -116,11 +141,8 @@ class VersionService extends BaseService<FrpcVersion> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getFrpVersionByLocalJson(): Promise<Array<FrpcVersion>> {
|
async getFrpVersionByLocalJson(): Promise<Array<FrpcVersion>> {
|
||||||
return new Promise<Array<FrpcVersion>>(resolve => {
|
return this.githubRelease2FrpcVersion(frpReleasesJson);
|
||||||
const versions = this.githubRelease2FrpcVersion(frpReleasesJson);
|
|
||||||
resolve(versions);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFrpVersion() {}
|
getFrpVersion() {}
|
||||||
@ -131,34 +153,24 @@ class VersionService extends BaseService<FrpcVersion> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private githubRelease2FrpcVersion(
|
private async githubRelease2FrpcVersion(
|
||||||
releases: Array<GithubRelease>
|
releases: Array<GithubRelease>
|
||||||
): Array<FrpcVersion> {
|
): Promise<Array<FrpcVersion>> {
|
||||||
|
const allVersions = await this._versionDao.findAll();
|
||||||
return releases
|
return releases
|
||||||
.filter(release => {
|
.filter(release => {
|
||||||
return this.findCurrentArchitectureAsset(release.assets);
|
return this.findCurrentArchitectureAsset(release.assets);
|
||||||
})
|
})
|
||||||
.map(m => {
|
.map(m => {
|
||||||
const asset = this.findCurrentArchitectureAsset(m.assets);
|
const asset = this.findCurrentArchitectureAsset(m.assets);
|
||||||
// m.assets.forEach((ma: GithubAsset) => {
|
|
||||||
// // if (asset) {
|
|
||||||
// // const absPath = path.join(
|
|
||||||
// // frpPath,
|
|
||||||
// // asset.name.replace(/(\.tar\.gz|\.zip)$/, "")
|
|
||||||
// // );
|
|
||||||
// // m.absPath = absPath;
|
|
||||||
// // m.download_completed = fs.existsSync(absPath);
|
|
||||||
// m.download_count = download_count;
|
|
||||||
// m.size = formatBytes(ma.size);
|
|
||||||
// // }
|
|
||||||
// });
|
|
||||||
// const asset = getAdaptiveAsset(m.id);
|
|
||||||
const download_count = m.assets.reduce(
|
const download_count = m.assets.reduce(
|
||||||
(sum, item) => sum + item.download_count,
|
(sum, item) => sum + item.download_count,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const currVersion = allVersions.find(ff => ff.githubReleaseId === m.id);
|
||||||
const v: FrpcVersion = {
|
const v: FrpcVersion = {
|
||||||
|
_id: "",
|
||||||
githubReleaseId: m.id,
|
githubReleaseId: m.id,
|
||||||
githubAssetId: asset.id,
|
githubAssetId: asset.id,
|
||||||
githubCreatedAt: asset.created_at,
|
githubCreatedAt: asset.created_at,
|
||||||
@ -167,25 +179,24 @@ class VersionService extends BaseService<FrpcVersion> {
|
|||||||
versionDownloadCount: download_count,
|
versionDownloadCount: download_count,
|
||||||
assetDownloadCount: asset.download_count,
|
assetDownloadCount: asset.download_count,
|
||||||
browserDownloadUrl: asset.browser_download_url,
|
browserDownloadUrl: asset.browser_download_url,
|
||||||
downloaded: false,
|
downloaded: this.frpcVersionExists(currVersion),
|
||||||
localPath: "",
|
localPath: currVersion && currVersion.localPath,
|
||||||
size: FileUtils.formatBytes(asset.size)
|
size: FileUtils.formatBytes(asset.size)
|
||||||
};
|
};
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// private async frpcVersionExists(githubReleaseId: number): boolean {
|
private frpcVersionExists(version: FrpcVersion): boolean {
|
||||||
// const version = await this._versionDao.findByGithubReleaseId(
|
// const version = await this._versionDao.findByGithubReleaseId(
|
||||||
// githubReleaseId
|
// githubReleaseId
|
||||||
// );
|
// );
|
||||||
//
|
|
||||||
// if (version) {
|
if (version) {
|
||||||
// return fs.existsSync(version.localPath);
|
return fs.existsSync(version.localPath);
|
||||||
// }
|
}
|
||||||
// return false;
|
return false;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VersionService;
|
export default VersionService;
|
||||||
|
@ -1,39 +1,21 @@
|
|||||||
class IdUtils {
|
class IdUtils {
|
||||||
public static genUUID() {
|
public static genUUID() {
|
||||||
if (typeof crypto === "object") {
|
let uuidValue = "",
|
||||||
if (typeof crypto.randomUUID === "function") {
|
k,
|
||||||
return crypto.randomUUID();
|
randomValue;
|
||||||
}
|
for (k = 0; k < 32; k++) {
|
||||||
if (
|
randomValue = (Math.random() * 16) | 0;
|
||||||
typeof crypto.getRandomValues === "function" &&
|
|
||||||
typeof Uint8Array === "function"
|
if (k == 8 || k == 12 || k == 16 || k == 20) {
|
||||||
) {
|
uuidValue += "-";
|
||||||
const callback = c => {
|
|
||||||
const num = Number(c);
|
|
||||||
return (
|
|
||||||
num ^
|
|
||||||
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))
|
|
||||||
).toString(16);
|
|
||||||
};
|
|
||||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, callback);
|
|
||||||
}
|
}
|
||||||
|
uuidValue += (
|
||||||
|
k == 12 ? 4 : k == 16 ? (randomValue & 3) | 8 : randomValue
|
||||||
|
).toString(16);
|
||||||
}
|
}
|
||||||
let timestamp = new Date().getTime();
|
return uuidValue;
|
||||||
let perforNow =
|
|
||||||
(typeof performance !== "undefined" &&
|
|
||||||
performance.now &&
|
|
||||||
performance.now() * 1000) ||
|
|
||||||
0;
|
|
||||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
|
|
||||||
let random = Math.random() * 16;
|
|
||||||
if (timestamp > 0) {
|
|
||||||
random = (timestamp + random) % 16 | 0;
|
|
||||||
timestamp = Math.floor(timestamp / 16);
|
|
||||||
} else {
|
|
||||||
random = (perforNow + random) % 16 | 0;
|
|
||||||
perforNow = Math.floor(perforNow / 16);
|
|
||||||
}
|
|
||||||
return (c === "x" ? random : (random & 0x3) | 0x8).toString(16);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default IdUtils;
|
||||||
|
@ -18,6 +18,10 @@ class PathUtils {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static getFrpcFilename() {
|
||||||
|
return SecureUtils.calculateMD5("frpc")
|
||||||
|
}
|
||||||
|
|
||||||
public static getAppData() {
|
public static getAppData() {
|
||||||
return app.getPath("userData");
|
return app.getPath("userData");
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export function success<T>(data: any, message?: string) {
|
export function success<T>(data?: any, message?: string) {
|
||||||
const resp: ApiResponse<T> = {
|
const resp: ApiResponse<T> = {
|
||||||
success: true,
|
success: true,
|
||||||
data: data,
|
data: data,
|
||||||
@ -7,6 +7,15 @@ export function success<T>(data: any, message?: string) {
|
|||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export function success(message?: string) {
|
||||||
|
// const resp: ApiResponse<void> = {
|
||||||
|
// success: true,
|
||||||
|
// data: null,
|
||||||
|
// message: message || "successful."
|
||||||
|
// };
|
||||||
|
// return resp;
|
||||||
|
// }
|
||||||
|
|
||||||
export function fail(message?: string) {
|
export function fail(message?: string) {
|
||||||
const resp: ApiResponse<any> = {
|
const resp: ApiResponse<any> = {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { ipcRenderer } from "electron";
|
import { ipcRenderer } from "electron";
|
||||||
|
|
||||||
export const send = (router: IpcRouter) => {
|
export const send = (router: IpcRouter, params?: any) => {
|
||||||
console.log(router, "send.router");
|
console.log(router, "send.router");
|
||||||
ipcRenderer.send(router.path);
|
ipcRenderer.send(router.path, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const on = (router: IpcRouter, listerHandler: (data: any) => void) => {
|
export const on = (router: IpcRouter, listerHandler: (data: any) => void) => {
|
||||||
|
@ -179,7 +179,7 @@ const rules = reactive<FormRules>({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
const versions = ref<Array<FrpVersion>>([]);
|
const versions = ref<Array<FrpcVersion>>([]);
|
||||||
const copyServerConfigBase64 = ref();
|
const copyServerConfigBase64 = ref();
|
||||||
const pasteServerConfigBase64 = ref();
|
const pasteServerConfigBase64 = ref();
|
||||||
|
|
||||||
@ -234,13 +234,28 @@ const checkAndResetVersion = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
const handleLoadDownloadedVersion = () => {
|
||||||
|
send(ipcRouters.VERSION.getDownloadedVersions);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoadSavedConfig = () => {
|
||||||
send(ipcRouters.SERVER.getServerConfig);
|
send(ipcRouters.SERVER.getServerConfig);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
handleLoadDownloadedVersion();
|
||||||
|
handleLoadSavedConfig();
|
||||||
|
|
||||||
on(ipcRouters.SERVER.getServerConfig, data => {
|
on(ipcRouters.SERVER.getServerConfig, data => {
|
||||||
console.log("data", data);
|
console.log("data", data);
|
||||||
loading.value--;
|
loading.value--;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
on(ipcRouters.VERSION.getDownloadedVersions, data => {
|
||||||
|
console.log("versions", data);
|
||||||
|
versions.value = data;
|
||||||
|
// checkAndResetVersion();
|
||||||
|
});
|
||||||
// ipcRenderer.send("config.getConfig");
|
// ipcRenderer.send("config.getConfig");
|
||||||
// handleLoadVersions();
|
// handleLoadVersions();
|
||||||
// ipcRenderer.on("Config.getConfig.hook", (event, args) => {
|
// ipcRenderer.on("Config.getConfig.hook", (event, args) => {
|
||||||
@ -541,13 +556,13 @@ onUnmounted(() => {
|
|||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="v in versions"
|
v-for="v in versions"
|
||||||
:key="v.id"
|
:key="v.githubReleaseId"
|
||||||
:label="v.name"
|
:label="v.name"
|
||||||
:value="v.id"
|
:value="v.githubReleaseId"
|
||||||
></el-option>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<div class="w-full flex justify-end">
|
<div class="w-full flex justify-end">
|
||||||
<el-link type="primary" @click="handleLoadVersions">
|
<el-link type="primary" @click="handleLoadDownloadedVersion">
|
||||||
<iconify-icon-offline class="mr-1" icon="refresh-rounded" />
|
<iconify-icon-offline class="mr-1" icon="refresh-rounded" />
|
||||||
手动刷新
|
手动刷新
|
||||||
</el-link>
|
</el-link>
|
||||||
|
@ -7,13 +7,13 @@ import { ElMessage, ElMessageBox } from "element-plus";
|
|||||||
import { useDebounceFn } from "@vueuse/core";
|
import { useDebounceFn } from "@vueuse/core";
|
||||||
import IconifyIconOffline from "@/components/IconifyIcon/src/iconifyIconOffline";
|
import IconifyIconOffline from "@/components/IconifyIcon/src/iconifyIconOffline";
|
||||||
import { on, send } from "@/utils/ipcUtils";
|
import { on, send } from "@/utils/ipcUtils";
|
||||||
import ipcRouter, { ipcRouters } from "../../../electron/core/IpcRouter";
|
import { ipcRouters } from "../../../electron/core/IpcRouter";
|
||||||
|
|
||||||
defineComponent({
|
defineComponent({
|
||||||
name: "Download"
|
name: "Download"
|
||||||
});
|
});
|
||||||
|
|
||||||
const versions = ref<Array<FrpVersion>>([]);
|
const versions = ref<Array<FrpcVersion>>([]);
|
||||||
const loading = ref(1);
|
const loading = ref(1);
|
||||||
const downloadPercentage = ref(0);
|
const downloadPercentage = ref(0);
|
||||||
const downloading = ref<Map<number, number>>(new Map<number, number>());
|
const downloading = ref<Map<number, number>>(new Map<number, number>());
|
||||||
@ -28,28 +28,25 @@ const mirrors = ref<Array<GitHubMirror>>([
|
|||||||
/**
|
/**
|
||||||
* 获取版本
|
* 获取版本
|
||||||
*/
|
*/
|
||||||
const handleLoadVersions = () => {
|
const handleLoadAllVersions = () => {
|
||||||
ipcRenderer.send("github.getFrpVersions", currMirror.value);
|
send(ipcRouters.VERSION.getVersions);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载
|
* 下载
|
||||||
* @param version
|
* @param version
|
||||||
*/
|
*/
|
||||||
const handleDownload = useDebounceFn((version: FrpVersion) => {
|
const handleDownload = useDebounceFn((version: FrpcVersion) => {
|
||||||
// console.log(version, currMirror.value);
|
send(ipcRouters.VERSION.downloadVersion, {
|
||||||
ipcRenderer.send("github.download", {
|
githubReleaseId: version.githubReleaseId
|
||||||
versionId: version.id,
|
|
||||||
mirror: currMirror.value
|
|
||||||
});
|
});
|
||||||
downloading.value.set(version.id, 0);
|
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除下载
|
* 删除下载
|
||||||
* @param version
|
* @param version
|
||||||
*/
|
*/
|
||||||
const handleDeleteVersion = useDebounceFn((version: FrpVersion) => {
|
const handleDeleteVersion = useDebounceFn((version: FrpcVersion) => {
|
||||||
ElMessageBox.alert(
|
ElMessageBox.alert(
|
||||||
`确认要删除 <span class="text-primary font-bold">${version.name} </span> 吗?`,
|
`确认要删除 <span class="text-primary font-bold">${version.name} </span> 吗?`,
|
||||||
"提示",
|
"提示",
|
||||||
@ -60,85 +57,86 @@ const handleDeleteVersion = useDebounceFn((version: FrpVersion) => {
|
|||||||
confirmButtonText: "删除"
|
confirmButtonText: "删除"
|
||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
ipcRenderer.send("github.deleteVersion", {
|
send(ipcRouters.VERSION.deleteDownloadedVersion, {
|
||||||
id: version.id,
|
githubReleaseId: version.githubReleaseId
|
||||||
absPath: version.absPath
|
|
||||||
});
|
});
|
||||||
|
// ipcRenderer.send("github.deleteVersion", {
|
||||||
|
// id: version.id,
|
||||||
|
// absPath: version.absPath
|
||||||
|
// });
|
||||||
});
|
});
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
const handleInitDownloadHook = () => {
|
// const handleInitDownloadHook = () => {
|
||||||
ipcRenderer.on("Download.frpVersionHook", (event, args) => {
|
// ipcRenderer.on("Download.deleteVersion.hook", (event, args) => {
|
||||||
loading.value--;
|
// const { err, data } = args;
|
||||||
versions.value = args.map(m => {
|
// if (!err) {
|
||||||
m.published_at = moment(m.published_at).format("YYYY-MM-DD");
|
// loading.value++;
|
||||||
return m as FrpVersion;
|
// ElMessage({
|
||||||
}) as Array<FrpVersion>;
|
// type: "success",
|
||||||
console.log(versions, "versions");
|
// message: "删除成功"
|
||||||
});
|
// });
|
||||||
// 进度监听
|
// handleLoadVersions();
|
||||||
ipcRenderer.on("Download.frpVersionDownloadOnProgress", (event, args) => {
|
// }
|
||||||
const { id, progress } = args;
|
// });
|
||||||
downloading.value.set(
|
// ipcRenderer.on("Download.importFrpFile.hook", (event, args) => {
|
||||||
id,
|
// const { success, data } = args;
|
||||||
Number(Number(progress.percent * 100).toFixed(2))
|
// console.log(args);
|
||||||
);
|
//
|
||||||
});
|
// // if (err) {
|
||||||
ipcRenderer.on("Download.frpVersionDownloadOnCompleted", (event, args) => {
|
// loading.value++;
|
||||||
downloading.value.delete(args);
|
// ElMessage({
|
||||||
const version: FrpVersion | undefined = versions.value.find(
|
// type: success ? "success" : "error",
|
||||||
f => f.id === args
|
// message: data
|
||||||
);
|
// });
|
||||||
if (version) {
|
// handleLoadVersions();
|
||||||
version.download_completed = true;
|
// // }
|
||||||
}
|
// });
|
||||||
});
|
// };
|
||||||
ipcRenderer.on("Download.deleteVersion.hook", (event, args) => {
|
|
||||||
const { err, data } = args;
|
|
||||||
if (!err) {
|
|
||||||
loading.value++;
|
|
||||||
ElMessage({
|
|
||||||
type: "success",
|
|
||||||
message: "删除成功"
|
|
||||||
});
|
|
||||||
handleLoadVersions();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ipcRenderer.on("Download.importFrpFile.hook", (event, args) => {
|
|
||||||
const { success, data } = args;
|
|
||||||
console.log(args);
|
|
||||||
|
|
||||||
// if (err) {
|
|
||||||
loading.value++;
|
|
||||||
ElMessage({
|
|
||||||
type: success ? "success" : "error",
|
|
||||||
message: data
|
|
||||||
});
|
|
||||||
handleLoadVersions();
|
|
||||||
// }
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMirrorChange = () => {
|
const handleMirrorChange = () => {
|
||||||
handleLoadVersions();
|
handleLoadAllVersions();
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
handleLoadAllVersions();
|
||||||
|
|
||||||
send(ipcRouters.VERSION.getVersions);
|
on(ipcRouters.VERSION.getVersions, data => {
|
||||||
|
console.log("versionData", data);
|
||||||
on(ipcRouters.VERSION.getVersions, (data) => {
|
versions.value = data.map(m => {
|
||||||
console.log('versionData', data);
|
m.githubCreatedAt = moment(m.githubCreatedAt).format("YYYY-MM-DD");
|
||||||
// versions.value = args.map(m => {
|
return m as FrpcVersion;
|
||||||
// m.published_at = moment(m.published_at).format("YYYY-MM-DD");
|
}) as Array<FrpcVersion>;
|
||||||
// return m as FrpVersion;
|
loading.value--;
|
||||||
// }) as Array<FrpVersion>;
|
});
|
||||||
|
|
||||||
|
on(ipcRouters.VERSION.downloadVersion, data => {
|
||||||
|
console.log("downloadData", data);
|
||||||
|
const { githubReleaseId, completed, percent } = data;
|
||||||
|
if (completed) {
|
||||||
|
downloading.value.delete(githubReleaseId);
|
||||||
|
const version: FrpcVersion | undefined = versions.value.find(
|
||||||
|
f => f.githubReleaseId === githubReleaseId
|
||||||
|
);
|
||||||
|
if (version) {
|
||||||
|
version.downloaded = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
downloading.value.set(
|
||||||
|
githubReleaseId,
|
||||||
|
Number(Number(percent * 100).toFixed(2))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
on(ipcRouters.VERSION.deleteDownloadedVersion, () => {
|
||||||
|
loading.value++;
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: "删除成功"
|
||||||
|
});
|
||||||
|
handleLoadAllVersions();
|
||||||
});
|
});
|
||||||
// handleLoadVersions();
|
|
||||||
// handleInitDownloadHook();
|
|
||||||
// ipcRenderer.invoke("process").then((r: any) => {
|
|
||||||
// console.log(r, "rrr");
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleImportFrp = () => {
|
const handleImportFrp = () => {
|
||||||
@ -211,7 +209,7 @@ onUnmounted(() => {
|
|||||||
<!-- </el-col>-->
|
<!-- </el-col>-->
|
||||||
<el-col
|
<el-col
|
||||||
v-for="version in versions"
|
v-for="version in versions"
|
||||||
:key="version.id"
|
:key="version.githubAssetId"
|
||||||
:lg="6"
|
:lg="6"
|
||||||
:md="8"
|
:md="8"
|
||||||
:sm="12"
|
:sm="12"
|
||||||
@ -235,19 +233,19 @@ onUnmounted(() => {
|
|||||||
<span class="text-primary font-bold"
|
<span class="text-primary font-bold"
|
||||||
>{{
|
>{{
|
||||||
// moment(version.published_at).format("YYYY-MM-DD HH:mm:ss")
|
// moment(version.published_at).format("YYYY-MM-DD HH:mm:ss")
|
||||||
version.download_count
|
version.versionDownloadCount
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[12px]">
|
<div class="text-[12px]">
|
||||||
发布时间:<span class="text-primary font-bold">{{
|
发布时间:<span class="text-primary font-bold">{{
|
||||||
// moment(version.published_at).format("YYYY-MM-DD HH:mm:ss")
|
// moment(version.published_at).format("YYYY-MM-DD HH:mm:ss")
|
||||||
version.published_at
|
version.githubCreatedAt
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div v-if="version.download_completed">
|
<div v-if="version.downloaded">
|
||||||
<!-- <span class="text-[12px] text-primary font-bold mr-2"-->
|
<!-- <span class="text-[12px] text-primary font-bold mr-2"-->
|
||||||
<!-- >已下载</span-->
|
<!-- >已下载</span-->
|
||||||
<!-- >-->
|
<!-- >-->
|
||||||
@ -276,9 +274,12 @@ onUnmounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="w-32" v-if="downloading.has(version.id)">
|
<div
|
||||||
|
class="w-32"
|
||||||
|
v-if="downloading.has(version.githubReleaseId)"
|
||||||
|
>
|
||||||
<el-progress
|
<el-progress
|
||||||
:percentage="downloading.get(version.id)"
|
:percentage="downloading.get(version.githubReleaseId)"
|
||||||
:text-inside="false"
|
:text-inside="false"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
2
types/core.d.ts
vendored
2
types/core.d.ts
vendored
@ -8,7 +8,7 @@ interface ControllerParam {
|
|||||||
win: BrowserWindow;
|
win: BrowserWindow;
|
||||||
channel: string;
|
channel: string;
|
||||||
event: Electron.IpcMainEvent;
|
event: Electron.IpcMainEvent;
|
||||||
args: any[];
|
args: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ListenerParam {
|
interface ListenerParam {
|
||||||
|
6
types/frpc-desktop.d.ts
vendored
6
types/frpc-desktop.d.ts
vendored
@ -1,5 +1,9 @@
|
|||||||
type FrpcDesktopProxy = FrpcProxyConfig & {};
|
type FrpcDesktopProxy = FrpcProxyConfig & {};
|
||||||
|
|
||||||
|
interface BaseEntity {
|
||||||
|
_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
interface FrpcSystemConfiguration {
|
interface FrpcSystemConfiguration {
|
||||||
launchAtStartup: boolean;
|
launchAtStartup: boolean;
|
||||||
silentStartup: boolean;
|
silentStartup: boolean;
|
||||||
@ -10,7 +14,7 @@ type FrpcDesktopServer = FrpcCommonConfig & {
|
|||||||
frpcVersion: number;
|
frpcVersion: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FrpcVersion = {
|
type FrpcVersion = BaseEntity & {
|
||||||
githubReleaseId: number;
|
githubReleaseId: number;
|
||||||
githubAssetId: number;
|
githubAssetId: number;
|
||||||
githubCreatedAt: string;
|
githubCreatedAt: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user