Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
86c9bc4a60 | |||
3bd1fb9edb | |||
8a8856772e | |||
80343bd929 | |||
9da481b991 | |||
70643c4287 | |||
db03ed552f | |||
6ccc285c61 | |||
a72ae1df5f | |||
9fbab69206 | |||
ecf329dd69 | |||
4e79809c19 | |||
f06e63f7f8 | |||
638f1e852e | |||
8b30b7c1fa | |||
2bb4a86df3 | |||
f41ca92711 | |||
65a3e86261 | |||
c74bc57453 | |||
528af70446 | |||
6f2764a047 | |||
1c4a40c495 | |||
144d1bb86a | |||
a9de377456 |
@@ -12,6 +12,7 @@ The Launcher is a "plug and play thing", download it, place it on the desktop an
|
||||
|
||||
- Automatic osu! client updating before Launch
|
||||
- Custom osu! Logo in MainMenu
|
||||
- Relax misses and much more
|
||||
- Account saving
|
||||
|
||||
## Build from source
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const appName = "EZPPLauncher";
|
||||
const appVersion = "2.1.1";
|
||||
const appVersion = "2.1.6";
|
||||
|
||||
module.exports = { appName, appVersion };
|
||||
|
@@ -2,19 +2,19 @@ const childProcess = require("child_process");
|
||||
|
||||
const runFile = (folder, file, args, onExit) => {
|
||||
childProcess.execFile(file, args, {
|
||||
cwd: folder
|
||||
cwd: folder,
|
||||
}, (_err, _stdout, _stdin) => {
|
||||
if (onExit) onExit();
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const runFileDetached = (folder, file, args) => {
|
||||
const subProcess = childProcess.spawn(file + (args ? " " + args : ''), {
|
||||
const subProcess = childProcess.spawn(file + (args ? " " + args : ""), {
|
||||
cwd: folder,
|
||||
detached: true,
|
||||
stdio: 'ignore'
|
||||
stdio: "ignore",
|
||||
});
|
||||
subProcess.unref();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { runFile, runFileDetached };
|
15
electron/fileUtil.js
Normal file
15
electron/fileUtil.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const fs = require("fs");
|
||||
|
||||
function isWritable(filePath) {
|
||||
let fileAccess = false;
|
||||
try {
|
||||
fs.closeSync(fs.openSync(filePath, "r+"));
|
||||
fileAccess = true;
|
||||
} catch {
|
||||
}
|
||||
return fileAccess;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isWritable,
|
||||
};
|
@@ -1,13 +1,13 @@
|
||||
function formatBytes(bytes, decimals = 2) {
|
||||
if (!+bytes) return '0 Bytes'
|
||||
if (!+bytes) return "0 B";
|
||||
|
||||
const k = 1024
|
||||
const dm = decimals < 0 ? 0 : decimals
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))}${sizes[i]}`
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))}${sizes[i]}`;
|
||||
}
|
||||
|
||||
module.exports = { formatBytes };
|
44
electron/logging.js
Normal file
44
electron/logging.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
class Logger {
|
||||
constructor(directory) {
|
||||
this.directory = directory;
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
async init() {
|
||||
const filename = `${new Date().toISOString().replace(/:/g, "-")}.log`;
|
||||
this.logPath = path.join(this.directory, filename);
|
||||
}
|
||||
|
||||
async log(message) {
|
||||
if (this.logPath === undefined || this.enabled == false) {
|
||||
return;
|
||||
}
|
||||
if (!fs.existsSync(this.logPath)) {
|
||||
await fs.promises.mkdir(this.directory, { recursive: true });
|
||||
await fs.promises.writeFile(this.logPath, "");
|
||||
}
|
||||
const logMessage = `[${new Date().toISOString()}] LOG: ${message}`;
|
||||
await fs.promises.appendFile(this.logPath, `${logMessage}\n`);
|
||||
console.log(logMessage);
|
||||
}
|
||||
|
||||
async error(message, error) {
|
||||
if (this.logPath === undefined || this.enabled == false) {
|
||||
return;
|
||||
}
|
||||
if (!fs.existsSync(this.logPath)) {
|
||||
await fs.promises.mkdir(this.directory, { recursive: true });
|
||||
await fs.promises.writeFile(this.logPath, "");
|
||||
}
|
||||
const errorMessage = `[${
|
||||
new Date().toISOString()
|
||||
}] ERROR: ${message}\n${error.stack}`;
|
||||
await fs.promises.appendFile(this.logPath, `${errorMessage}\n`);
|
||||
console.error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Logger;
|
26
electron/netUtils.js
Normal file
26
electron/netUtils.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { exec } = require("child_process");
|
||||
|
||||
async function isNet8Installed() {
|
||||
return new Promise((resolve) => {
|
||||
exec("dotnet --list-runtimes", (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
if (stderr) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
const version = stdout.trim();
|
||||
for (const line of version.split('\n')) {
|
||||
if (line.startsWith("Microsoft.WindowsDesktop.App 8.")) {
|
||||
resolve(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
resolve(false);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { isNet8Installed };
|
@@ -10,6 +10,16 @@ const checkUpdateURL =
|
||||
const ignoredOsuEntities = [
|
||||
"osu!auth.dll",
|
||||
];
|
||||
const gamemodes = {
|
||||
0: "osu!",
|
||||
1: "taiko",
|
||||
2: "catch",
|
||||
3: "mania",
|
||||
4: "osu!(rx)",
|
||||
5: "taiko(rx)",
|
||||
6: "catch(rx)",
|
||||
8: "osu!(ap)",
|
||||
};
|
||||
const osuEntities = [
|
||||
"avcodec-51.dll",
|
||||
"avformat-52.dll",
|
||||
@@ -34,26 +44,7 @@ const osuEntities = [
|
||||
"scores.db",
|
||||
];
|
||||
|
||||
const patcherFiles = [
|
||||
{
|
||||
name: "patcher.exe",
|
||||
url_download: "https://ez-pp.farm/assets/patcher.exe",
|
||||
url_hash: "https://ez-pp.farm/assets/patcher.md5",
|
||||
},
|
||||
{
|
||||
name: "patch.hook.dll",
|
||||
url_download: "https://ez-pp.farm/assets/patch.hook.dll",
|
||||
url_hash: "https://ez-pp.farm/assets/patch.hook.md5",
|
||||
},
|
||||
];
|
||||
|
||||
const uiFiles = [
|
||||
{
|
||||
name: "ezpp!ui.dll",
|
||||
url_download: "https://ez-pp.farm/assets/ezpp!ui.dll",
|
||||
url_hash: "https://ez-pp.farm/assets/ezpp!ui.md5",
|
||||
},
|
||||
];
|
||||
const ezppLauncherUpdateList = "https://ez-pp.farm/ezpplauncher";
|
||||
|
||||
async function isValidOsuFolder(path) {
|
||||
const allFiles = await fs.promises.readdir(path);
|
||||
@@ -193,6 +184,7 @@ function downloadUpdateFiles(osuPath, updateFiles) {
|
||||
|
||||
const startDownload = async () => {
|
||||
for (const updatePatch of updateFiles) {
|
||||
try {
|
||||
const fileName = updatePatch.filename;
|
||||
const fileSize = updatePatch.filesize;
|
||||
const fileURL = updatePatch.url_full;
|
||||
@@ -209,15 +201,7 @@ function downloadUpdateFiles(osuPath, updateFiles) {
|
||||
});
|
||||
},
|
||||
});
|
||||
axiosDownloadWithProgress.data.on("end", () => {
|
||||
eventEmitter.emit("data", {
|
||||
fileName,
|
||||
loaded: fileSize,
|
||||
total: fileSize,
|
||||
progress: 100,
|
||||
});
|
||||
});
|
||||
try {
|
||||
|
||||
if (fs.existsSync(path.join(osuPath, fileName))) {
|
||||
await fs.promises.rm(path.join(osuPath, fileName), {
|
||||
force: true,
|
||||
@@ -231,6 +215,7 @@ function downloadUpdateFiles(osuPath, updateFiles) {
|
||||
console.log(err);
|
||||
eventEmitter.emit("error", {
|
||||
fileName,
|
||||
error: err,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -255,66 +240,91 @@ function runOsuWithDevServer(osuPath, serverDomain, onExit) {
|
||||
runFile(osuPath, osuExecuteable, ["-devserver", serverDomain], onExit);
|
||||
}
|
||||
|
||||
async function getPatcherUpdates(osuPath) {
|
||||
async function getEZPPLauncherUpdateFiles(osuPath) {
|
||||
const filesToDownload = [];
|
||||
|
||||
const patcherDir = path.join(osuPath, "EZPPLauncher");
|
||||
if (!fs.existsSync(patcherDir)) fs.mkdirSync(patcherDir);
|
||||
|
||||
for (const patcherFile of patcherFiles) {
|
||||
if (fs.existsSync(path.join(patcherDir, patcherFile.name))) {
|
||||
const latestPatchFileHash = await (await fetch(patcherFile.url_hash))
|
||||
.text();
|
||||
const localPatchFileHash = crypto.createHash("md5").update(
|
||||
fs.readFileSync(path.join(patcherDir, patcherFile.name)),
|
||||
).digest("hex");
|
||||
if (
|
||||
latestPatchFileHash.trim().toLowerCase() !=
|
||||
localPatchFileHash.trim().toLowerCase()
|
||||
) filesToDownload.push(patcherFile);
|
||||
} else filesToDownload.push(patcherFile);
|
||||
const updateFilesRequest = await fetch(ezppLauncherUpdateList, {
|
||||
method: "PATCH",
|
||||
});
|
||||
const updateFiles = await updateFilesRequest.json();
|
||||
for (const updateFile of updateFiles) {
|
||||
const filePath = path.join(
|
||||
osuPath,
|
||||
...updateFile.folder.split("/"),
|
||||
updateFile.name,
|
||||
);
|
||||
if (fs.existsSync(filePath)) {
|
||||
const fileHash = updateFile.md5.toLowerCase();
|
||||
const localFileHash = crypto.createHash("md5").update(
|
||||
fs.readFileSync(filePath),
|
||||
).digest("hex").toLowerCase();
|
||||
if (fileHash !== localFileHash) {
|
||||
filesToDownload.push(updateFile);
|
||||
}
|
||||
} else {
|
||||
filesToDownload.push(updateFile);
|
||||
}
|
||||
}
|
||||
|
||||
return filesToDownload;
|
||||
}
|
||||
|
||||
function downloadPatcherUpdates(osuPath, patcherUpdates) {
|
||||
async function downloadEZPPLauncherUpdateFiles(osuPath, updateFiles) {
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
const startDownload = async () => {
|
||||
const patcherDir = path.join(osuPath, "EZPPLauncher");
|
||||
if (!fs.existsSync(patcherDir)) fs.mkdirSync(patcherDir);
|
||||
//NOTE: delete files that are not in the updateFiles array
|
||||
const foldersToPrune = updateFiles.map(file => path.dirname(path.join(osuPath, ...file.folder.split("/"), file.name))).filter((folder, index, self) => self.indexOf(folder) === index);
|
||||
for (const pruneFolder of foldersToPrune) {
|
||||
//NOTE: check if the folder is not the osu root folder.
|
||||
if (path.basename(pruneFolder) == "osu!")
|
||||
continue;
|
||||
for (const files of await fs.promises.readdir(pruneFolder)) {
|
||||
const filePath = path.join(pruneFolder, files);
|
||||
if (!updateFiles.some(file => path.join(osuPath, ...file.folder.split("/"), file.name) === filePath)) {
|
||||
|
||||
for (const patcherFile of patcherUpdates) {
|
||||
const fileName = patcherFile.name;
|
||||
const fileURL = patcherFile.url_download;
|
||||
const axiosDownloadWithProgress = await axios.get(fileURL, {
|
||||
await fs.promises.rm(filePath, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const updateFile of updateFiles) {
|
||||
try {
|
||||
const filePath = path.join(
|
||||
osuPath,
|
||||
...updateFile.folder.split("/"),
|
||||
updateFile.name,
|
||||
);
|
||||
const folder = path.dirname(filePath);
|
||||
if (!fs.existsSync(folder)) {
|
||||
await fs.promises.mkdir(folder, { recursive: true });
|
||||
}
|
||||
const axiosDownloadWithProgress = await axios.get(updateFile.url, {
|
||||
responseType: "stream",
|
||||
onDownloadProgress: (progressEvent) => {
|
||||
const { loaded, total } = progressEvent;
|
||||
const fileSize = updateFile.size;
|
||||
const { loaded } = progressEvent;
|
||||
eventEmitter.emit("data", {
|
||||
fileName,
|
||||
fileName: path.basename(filePath),
|
||||
loaded,
|
||||
total,
|
||||
progress: Math.floor((loaded / total) * 100),
|
||||
total: fileSize,
|
||||
progress: Math.floor((loaded / fileSize) * 100),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
if (fs.existsSync(path.join(osuPath, "EZPPLauncher", fileName))) {
|
||||
await fs.promises.rm(path.join(osuPath, "EZPPLauncher", fileName), {
|
||||
if (fs.existsSync(filePath)) {
|
||||
await fs.promises.rm(filePath, {
|
||||
force: true,
|
||||
});
|
||||
}
|
||||
await fs.promises.writeFile(
|
||||
path.join(osuPath, "EZPPLauncher", fileName),
|
||||
filePath,
|
||||
axiosDownloadWithProgress.data,
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
eventEmitter.emit("error", {
|
||||
fileName,
|
||||
fileName: path.basename(filePath),
|
||||
error: err,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -326,93 +336,49 @@ function downloadPatcherUpdates(osuPath, patcherUpdates) {
|
||||
};
|
||||
}
|
||||
|
||||
async function getUIFiles(osuPath) {
|
||||
const filesToDownload = [];
|
||||
|
||||
const ezppLauncherDir = path.join(osuPath, "EZPPLauncher");
|
||||
if (!fs.existsSync(ezppLauncherDir)) fs.mkdirSync(ezppLauncherDir);
|
||||
|
||||
for (const uiFile of uiFiles) {
|
||||
if (fs.existsSync(path.join(ezppLauncherDir, uiFile.name))) {
|
||||
const latestPatchFileHash = await (await fetch(uiFile.url_hash)).text();
|
||||
const localPatchFileHash = crypto.createHash("md5").update(
|
||||
fs.readFileSync(path.join(ezppLauncherDir, uiFile.name)),
|
||||
).digest("hex");
|
||||
if (
|
||||
latestPatchFileHash.trim().toLowerCase() !=
|
||||
localPatchFileHash.trim().toLowerCase()
|
||||
) filesToDownload.push(uiFile);
|
||||
} else filesToDownload.push(uiFile);
|
||||
}
|
||||
|
||||
return filesToDownload;
|
||||
}
|
||||
|
||||
function downloadUIFiles(osuPath, uiFiles) {
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
const startDownload = async () => {
|
||||
const ezpplauncherDir = path.join(osuPath, "EZPPLauncher");
|
||||
if (!fs.existsSync(ezpplauncherDir)) fs.mkdirSync(ezpplauncherDir);
|
||||
|
||||
for (const uiFile of uiFiles) {
|
||||
const fileName = uiFile.name;
|
||||
const fileURL = uiFile.url_download;
|
||||
const axiosDownloadWithProgress = await axios.get(fileURL, {
|
||||
responseType: "stream",
|
||||
onDownloadProgress: (progressEvent) => {
|
||||
const { loaded, total } = progressEvent;
|
||||
eventEmitter.emit("data", {
|
||||
fileName,
|
||||
loaded,
|
||||
total,
|
||||
progress: Math.floor((loaded / total) * 100),
|
||||
});
|
||||
},
|
||||
});
|
||||
try {
|
||||
if (fs.existsSync(path.join(osuPath, "EZPPLauncher", fileName))) {
|
||||
await fs.promises.rm(path.join(osuPath, "EZPPLauncher", fileName), {
|
||||
force: true,
|
||||
});
|
||||
}
|
||||
|
||||
await fs.promises.writeFile(
|
||||
path.join(osuPath, "EZPPLauncher", fileName),
|
||||
axiosDownloadWithProgress.data,
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
eventEmitter.emit("error", {
|
||||
fileName,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
eventEmitter,
|
||||
startDownload,
|
||||
};
|
||||
}
|
||||
|
||||
async function replaceUIFile(osuPath, revert) {
|
||||
async function replaceUIFiles(osuPath, revert) {
|
||||
if (!revert) {
|
||||
const ezppUIFile = path.join(osuPath, "EZPPLauncher", "ezpp!ui.dll");
|
||||
const oldOsuUIFile = path.join(osuPath, "osu!ui.dll");
|
||||
const ezppGameplayFile = path.join(
|
||||
osuPath,
|
||||
"EZPPLauncher",
|
||||
"ezpp!gameplay.dll",
|
||||
);
|
||||
const oldOsuGameplayFile = path.join(osuPath, "osu!gameplay.dll");
|
||||
|
||||
await fs.promises.rename(
|
||||
oldOsuUIFile,
|
||||
path.join(osuPath, "osu!ui.dll.bak"),
|
||||
);
|
||||
await fs.promises.rename(ezppUIFile, oldOsuUIFile);
|
||||
|
||||
await fs.promises.rename(
|
||||
oldOsuGameplayFile,
|
||||
path.join(osuPath, "osu!gameplay.dll.bak"),
|
||||
);
|
||||
await fs.promises.rename(ezppGameplayFile, oldOsuGameplayFile);
|
||||
} else {
|
||||
const oldOsuUIFile = path.join(osuPath, "osu!ui.dll");
|
||||
const ezppUIFile = path.join(osuPath, "EZPPLauncher", "ezpp!ui.dll");
|
||||
const oldOsuGameplayFile = path.join(osuPath, "osu!gameplay.dll");
|
||||
const ezppGameplayFile = path.join(
|
||||
osuPath,
|
||||
"EZPPLauncher",
|
||||
"ezpp!gameplay.dll",
|
||||
);
|
||||
|
||||
await fs.promises.rename(oldOsuUIFile, ezppUIFile);
|
||||
await fs.promises.rename(
|
||||
path.join(osuPath, "osu!ui.dll.bak"),
|
||||
oldOsuUIFile,
|
||||
);
|
||||
|
||||
await fs.promises.rename(oldOsuGameplayFile, ezppGameplayFile);
|
||||
await fs.promises.rename(
|
||||
path.join(osuPath, "osu!gameplay.dll.bak"),
|
||||
oldOsuGameplayFile,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,12 +439,11 @@ module.exports = {
|
||||
getFilesThatNeedUpdate,
|
||||
downloadUpdateFiles,
|
||||
runOsuWithDevServer,
|
||||
getPatcherUpdates,
|
||||
downloadPatcherUpdates,
|
||||
downloadUIFiles,
|
||||
getUIFiles,
|
||||
replaceUIFile,
|
||||
replaceUIFiles,
|
||||
findOsuInstallation,
|
||||
updateOsuConfigHashes,
|
||||
runOsuUpdater,
|
||||
getEZPPLauncherUpdateFiles,
|
||||
downloadEZPPLauncherUpdateFiles,
|
||||
gamemodes,
|
||||
};
|
||||
|
@@ -35,7 +35,9 @@ module.exports = {
|
||||
richPresence = new DiscordRPC.AutoClient({ transport: "ipc" });
|
||||
richPresence.endlessLogin({ clientId });
|
||||
richPresence.once("ready", () => {
|
||||
console.log("connected presence with user " + richPresence.user.username);
|
||||
console.log(
|
||||
"connected presence with user " + richPresence.user.username,
|
||||
);
|
||||
richPresence.setActivity(currentStatus);
|
||||
intervalId = setInterval(() => {
|
||||
richPresence.setActivity(currentStatus);
|
||||
|
271
main.js
271
main.js
@@ -3,15 +3,6 @@ const { app, BrowserWindow, Menu, ipcMain, dialog, shell } = require(
|
||||
"electron",
|
||||
);
|
||||
|
||||
/* const unhandled = require("electron-unhandled");
|
||||
unhandled({
|
||||
logger: console.error,
|
||||
showDialog: true,
|
||||
reportButton: () => {
|
||||
shell.openExternal("https://ez-pp.farm/discord");
|
||||
},
|
||||
}); */
|
||||
|
||||
const path = require("path");
|
||||
const serve = require("electron-serve");
|
||||
const loadURL = serve({ directory: "public" });
|
||||
@@ -27,14 +18,12 @@ const {
|
||||
downloadUpdateFiles,
|
||||
getUserConfig,
|
||||
runOsuWithDevServer,
|
||||
getPatcherUpdates,
|
||||
downloadPatcherUpdates,
|
||||
getUIFiles,
|
||||
downloadUIFiles,
|
||||
replaceUIFile,
|
||||
replaceUIFiles,
|
||||
findOsuInstallation,
|
||||
updateOsuConfigHashes,
|
||||
runOsuUpdater,
|
||||
gamemodes,
|
||||
getEZPPLauncherUpdateFiles,
|
||||
downloadEZPPLauncherUpdateFiles,
|
||||
} = require("./electron/osuUtil");
|
||||
const { formatBytes } = require("./electron/formattingUtil");
|
||||
const windowName = require("get-window-by-name");
|
||||
@@ -47,6 +36,9 @@ const { appName, appVersion } = require("./electron/appInfo");
|
||||
const { updateAvailable, releasesUrl } = require("./electron/updateCheck");
|
||||
const fkill = require("fkill");
|
||||
const { checkImageExists } = require("./electron/imageUtil");
|
||||
const { isNet8Installed } = require("./electron/netUtils");
|
||||
const Logger = require("./electron/logging");
|
||||
const { isWritable } = require("./electron/fileUtil");
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
@@ -55,6 +47,13 @@ let osuCheckInterval;
|
||||
let userOsuPath;
|
||||
let osuLoaded = false;
|
||||
let patch = false;
|
||||
let logger = new Logger(path.join(
|
||||
process.platform == "win32"
|
||||
? process.env["LOCALAPPDATA"]
|
||||
: process.env["HOME"],
|
||||
"EZPPLauncher",
|
||||
"logs",
|
||||
));
|
||||
|
||||
let currentUser = undefined;
|
||||
|
||||
@@ -75,10 +74,18 @@ function startOsuStatus() {
|
||||
osuLoaded = true;
|
||||
|
||||
try {
|
||||
const currentUserInfo = await fetch(`https://api.ez-pp.farm/get_player_info?name=${currentUser.username}&scope=info`);
|
||||
const currentUserInfo = await fetch(
|
||||
`https://api.ez-pp.farm/get_player_info?name=${currentUser.username}&scope=info`,
|
||||
);
|
||||
const currentUserInfoJson = await currentUserInfo.json();
|
||||
if ("player" in currentUserInfoJson && currentUserInfoJson.player != null) {
|
||||
if ("info" in currentUserInfoJson.player && currentUserInfoJson.player.info != null) {
|
||||
if (
|
||||
"player" in currentUserInfoJson &&
|
||||
currentUserInfoJson.player != null
|
||||
) {
|
||||
if (
|
||||
"info" in currentUserInfoJson.player &&
|
||||
currentUserInfoJson.player.info != null
|
||||
) {
|
||||
const id = currentUserInfoJson.player.info.id;
|
||||
const username = currentUserInfoJson.player.info.name;
|
||||
richPresence.updateUser({
|
||||
@@ -89,7 +96,6 @@ function startOsuStatus() {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -97,7 +103,8 @@ function startOsuStatus() {
|
||||
const patcherExecuteable = path.join(
|
||||
userOsuPath,
|
||||
"EZPPLauncher",
|
||||
"patcher.exe",
|
||||
"patcher",
|
||||
"osu!.patcher.exe",
|
||||
);
|
||||
if (fs.existsSync(patcherExecuteable)) {
|
||||
runFileDetached(userOsuPath, patcherExecuteable);
|
||||
@@ -109,13 +116,26 @@ function startOsuStatus() {
|
||||
const windowTitle = firstInstance.processTitle;
|
||||
lastOsuStatus = windowTitle;
|
||||
const currentStatusRequest = await fetch(
|
||||
"https://api.ez-pp.farm/get_player_status?name=" + currentUser.username,
|
||||
"https://api.ez-pp.farm/v1/get_player_status?name=" + currentUser.username,
|
||||
);
|
||||
const currentStatus = await currentStatusRequest.json();
|
||||
|
||||
if (!("player_status" in currentStatus)) return;
|
||||
if (!("status" in currentStatus.player_status)) return;
|
||||
|
||||
const currentMode = currentStatus.player_status.status.mode;
|
||||
const currentModeString = gamemodes[currentMode];
|
||||
|
||||
const currentInfoRequest = await fetch(
|
||||
"https://api.ez-pp.farm/v1/get_player_info?name=" + currentUser.username + "&scope=all",
|
||||
);
|
||||
const currentInfo = await currentInfoRequest.json();
|
||||
let currentUsername = currentInfo.player.info.name;
|
||||
const currentId = currentInfo.player.info.id;
|
||||
const currentStats = currentInfo.player.stats[currentMode];
|
||||
|
||||
currentUsername += ` (#${currentStats.rank})`;
|
||||
|
||||
let largeImageKey = "ezppfarm";
|
||||
let details = "Idle...";
|
||||
let infoText = currentStatus.player_status.status.info_text.length > 0
|
||||
@@ -182,6 +202,13 @@ function startOsuStatus() {
|
||||
break;
|
||||
}
|
||||
|
||||
details = `[${currentModeString}] ${details}`;
|
||||
|
||||
richPresence.updateUser({
|
||||
username: currentUsername,
|
||||
id: currentId,
|
||||
});
|
||||
|
||||
richPresence.updateStatus({
|
||||
details,
|
||||
state: infoText,
|
||||
@@ -199,9 +226,19 @@ function stopOsuStatus() {
|
||||
|
||||
function registerIPCPipes() {
|
||||
ipcMain.handle("ezpplauncher:login", async (e, args) => {
|
||||
const hwid = getHwId();
|
||||
let hwid = "";
|
||||
try {
|
||||
hwid = getHwId();
|
||||
} catch (err) {
|
||||
logger.error(`Failed to get HWID.`, err);
|
||||
return {
|
||||
code: 500,
|
||||
message: "Failed to get HWID.",
|
||||
};
|
||||
}
|
||||
const timeout = new AbortController();
|
||||
const timeoutId = setTimeout(() => timeout.abort(), 8000);
|
||||
logger.log(`Logging in with user ${args.username}...`);
|
||||
try {
|
||||
const fetchResult = await fetch("https://ez-pp.farm/login/check", {
|
||||
signal: timeout.signal,
|
||||
@@ -226,14 +263,20 @@ function registerIPCPipes() {
|
||||
}
|
||||
currentUser = args;
|
||||
config.remove("guest");
|
||||
}
|
||||
logger.log(`Logged in as user ${args.username}!`);
|
||||
} else logger.log(`Login failed for user ${args.username}.`);
|
||||
return result;
|
||||
}
|
||||
logger.log(
|
||||
`Login failed for user ${username}.\nResponse:\n${await fetchResult
|
||||
.text()}`,
|
||||
);
|
||||
return {
|
||||
code: 500,
|
||||
message: "Something went wrong while logging you in.",
|
||||
};
|
||||
} catch (err) {
|
||||
logger.error("Error while logging in:", err);
|
||||
return {
|
||||
code: 500,
|
||||
message: "Something went wrong while logging you in.",
|
||||
@@ -263,6 +306,7 @@ function registerIPCPipes() {
|
||||
}
|
||||
const timeout = new AbortController();
|
||||
const timeoutId = setTimeout(() => timeout.abort(), 8000);
|
||||
logger.log(`Logging in with user ${username}...`);
|
||||
try {
|
||||
const fetchResult = await fetch("https://ez-pp.farm/login/check", {
|
||||
signal: timeout.signal,
|
||||
@@ -285,16 +329,23 @@ function registerIPCPipes() {
|
||||
username: username,
|
||||
password: password,
|
||||
};
|
||||
}
|
||||
logger.log(`Logged in as user ${username}!`);
|
||||
} else logger.log(`Login failed for user ${username}.`);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
config.remove("password");
|
||||
}
|
||||
logger.log(
|
||||
`Login failed for user ${username}.\nResponse:\n${await fetchResult
|
||||
.text()}`,
|
||||
);
|
||||
return {
|
||||
code: 500,
|
||||
message: "Something went wrong while logging you in.",
|
||||
};
|
||||
} catch (err) {
|
||||
logger.error("Error while logging in:", err);
|
||||
return {
|
||||
code: 500,
|
||||
message: "Something went wrong while logging you in.",
|
||||
@@ -307,6 +358,7 @@ function registerIPCPipes() {
|
||||
config.remove("password");
|
||||
config.set("guest", "1");
|
||||
currentUser = undefined;
|
||||
logger.log("Logged in as guest user.");
|
||||
});
|
||||
|
||||
ipcMain.handle("ezpplauncher:logout", (e) => {
|
||||
@@ -314,6 +366,7 @@ function registerIPCPipes() {
|
||||
config.remove("password");
|
||||
config.remove("guest");
|
||||
currentUser = undefined;
|
||||
logger.log("Loging out.");
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -330,6 +383,10 @@ function registerIPCPipes() {
|
||||
else richPresence.connect();
|
||||
}
|
||||
|
||||
if (key == "logging") {
|
||||
logger.enabled = logging;
|
||||
}
|
||||
|
||||
if (typeof value == "boolean") {
|
||||
config.set(key, value ? "true" : "false");
|
||||
} else {
|
||||
@@ -373,12 +430,30 @@ function registerIPCPipes() {
|
||||
return config.all();
|
||||
});
|
||||
|
||||
ipcMain.handle("ezpplauncher:checkUpdate", async (e) => {
|
||||
const updateInfo = await updateAvailable();
|
||||
if (updateInfo.update)
|
||||
mainWindow.webContents.send("ezpplauncher:update", updateInfo.release);
|
||||
});
|
||||
|
||||
ipcMain.handle("ezpplauncher:exitAndUpdate", async (e) => {
|
||||
await shell.openExternal(releasesUrl);
|
||||
app.exit();
|
||||
});
|
||||
|
||||
ipcMain.handle("ezpplauncher:launch", async (e) => {
|
||||
try {
|
||||
const osuWindowTitle = windowName.getWindowText("osu!.exe");
|
||||
if (osuWindowTitle.length > 0) {
|
||||
mainWindow.webContents.send("ezpplauncher:alert", {
|
||||
type: "error",
|
||||
message: "osu! is running, please exit.",
|
||||
});
|
||||
mainWindow.webContents.send("ezpplauncher:launchabort");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log("Preparing launch...");
|
||||
const configPatch = config.get("patch");
|
||||
patch = configPatch != undefined ? configPatch == "true" : true;
|
||||
mainWindow.webContents.send("ezpplauncher:launchstatus", {
|
||||
@@ -393,6 +468,8 @@ function registerIPCPipes() {
|
||||
type: "error",
|
||||
message: "osu! path not set!",
|
||||
});
|
||||
mainWindow.webContents.send("ezpplauncher:open-settings");
|
||||
logger.log("osu! path is not set.");
|
||||
return;
|
||||
}
|
||||
if (!(await isValidOsuFolder(osuPath))) {
|
||||
@@ -401,51 +478,42 @@ function registerIPCPipes() {
|
||||
type: "error",
|
||||
message: "invalid osu! path!",
|
||||
});
|
||||
logger.log("osu! path is invalid.");
|
||||
return;
|
||||
}
|
||||
if (patch) {
|
||||
if (!(await isNet8Installed())) {
|
||||
mainWindow.webContents.send("ezpplauncher:launchabort");
|
||||
mainWindow.webContents.send("ezpplauncher:alert", {
|
||||
type: "error",
|
||||
message: ".NET 8 is not installed.",
|
||||
});
|
||||
//open .net 8 download in browser
|
||||
shell.openExternal(
|
||||
"https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-8.0.4-windows-x64-installer",
|
||||
);
|
||||
logger.log(".NET 8 is not installed.");
|
||||
}
|
||||
}
|
||||
mainWindow.webContents.send("ezpplauncher:launchstatus", {
|
||||
status: "Checking for osu! updates...",
|
||||
});
|
||||
await new Promise((res) => setTimeout(res, 1000));
|
||||
const releaseStream = await getGlobalConfig(osuPath).get("_ReleaseStream");
|
||||
const releaseStream = await getGlobalConfig(osuPath).get(
|
||||
"_ReleaseStream",
|
||||
);
|
||||
const latestFiles = await getUpdateFiles(releaseStream);
|
||||
const uiFiles = await getUIFiles(osuPath);
|
||||
const updateFiles = await getFilesThatNeedUpdate(osuPath, latestFiles);
|
||||
if (uiFiles.length > 0) {
|
||||
const uiDownloader = downloadUIFiles(osuPath, uiFiles);
|
||||
let errored = false;
|
||||
uiDownloader.eventEmitter.on("error", (data) => {
|
||||
const filename = data.fileName;
|
||||
errored = true;
|
||||
mainWindow.webContents.send("ezpplauncher:alert", {
|
||||
type: "error",
|
||||
message:
|
||||
`Failed to download/replace ${filename}!\nMaybe try to restart EZPPLauncher.`,
|
||||
});
|
||||
});
|
||||
uiDownloader.eventEmitter.on("data", (data) => {
|
||||
mainWindow.webContents.send("ezpplauncher:launchprogress", {
|
||||
progress: Math.ceil(data.progress),
|
||||
});
|
||||
mainWindow.webContents.send("ezpplauncher:launchstatus", {
|
||||
status: `Downloading ${data.fileName}(${formatBytes(data.loaded)}/${formatBytes(data.total)
|
||||
})...`,
|
||||
});
|
||||
});
|
||||
await uiDownloader.startDownload();
|
||||
mainWindow.webContents.send("ezpplauncher:launchprogress", {
|
||||
progress: -1,
|
||||
});
|
||||
if (errored) {
|
||||
mainWindow.webContents.send("ezpplauncher:launchabort");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (updateFiles.length > 0) {
|
||||
logger.log("osu! updates found.");
|
||||
const updateDownloader = downloadUpdateFiles(osuPath, updateFiles);
|
||||
let errored = false;
|
||||
updateDownloader.eventEmitter.on("error", (data) => {
|
||||
const filename = data.fileName;
|
||||
logger.error(
|
||||
`Failed to download/replace ${filename}!`,
|
||||
data.error,
|
||||
);
|
||||
errored = true;
|
||||
mainWindow.webContents.send("ezpplauncher:alert", {
|
||||
type: "error",
|
||||
@@ -454,6 +522,9 @@ function registerIPCPipes() {
|
||||
});
|
||||
});
|
||||
updateDownloader.eventEmitter.on("data", (data) => {
|
||||
if (data.progress >= 100) {
|
||||
logger.log(`Downloaded ${data.fileName} successfully.`);
|
||||
}
|
||||
mainWindow.webContents.send("ezpplauncher:launchprogress", {
|
||||
progress: Math.ceil(data.progress),
|
||||
});
|
||||
@@ -486,12 +557,17 @@ function registerIPCPipes() {
|
||||
status: "Looking for patcher updates...",
|
||||
});
|
||||
await new Promise((res) => setTimeout(res, 1000));
|
||||
const patchFiles = await getPatcherUpdates(osuPath);
|
||||
const patchFiles = await getEZPPLauncherUpdateFiles(osuPath);
|
||||
if (patchFiles.length > 0) {
|
||||
const patcherDownloader = downloadPatcherUpdates(osuPath, patchFiles);
|
||||
logger.log("EZPPLauncher updates found.");
|
||||
const patcherDownloader = await downloadEZPPLauncherUpdateFiles(
|
||||
osuPath,
|
||||
patchFiles,
|
||||
);
|
||||
let errored = false;
|
||||
patcherDownloader.eventEmitter.on("error", (data) => {
|
||||
const filename = data.fileName;
|
||||
logger.error(`Failed to download/replace ${filename}!`, data.error);
|
||||
errored = true;
|
||||
mainWindow.webContents.send("ezpplauncher:alert", {
|
||||
type: "error",
|
||||
@@ -500,12 +576,15 @@ function registerIPCPipes() {
|
||||
});
|
||||
});
|
||||
patcherDownloader.eventEmitter.on("data", (data) => {
|
||||
if (data.progress >= 100) {
|
||||
logger.log(`Downloaded ${data.fileName} successfully.`);
|
||||
}
|
||||
mainWindow.webContents.send("ezpplauncher:launchprogress", {
|
||||
progress: Math.ceil(data.progress),
|
||||
});
|
||||
mainWindow.webContents.send("ezpplauncher:launchstatus", {
|
||||
status: `Downloading ${data.fileName}(${formatBytes(data.loaded)}/${formatBytes(data.total)
|
||||
})...`,
|
||||
status: `Downloading ${data.fileName}(${formatBytes(data.loaded)
|
||||
}/${formatBytes(data.total)})...`,
|
||||
});
|
||||
});
|
||||
await patcherDownloader.startDownload();
|
||||
@@ -558,15 +637,27 @@ function registerIPCPipes() {
|
||||
status: "Preparing launch...",
|
||||
});
|
||||
|
||||
await updateOsuConfigHashes(osuPath);
|
||||
await replaceUIFile(osuPath, false);
|
||||
/* await updateOsuConfigHashes(osuPath); */
|
||||
logger.log("Replacing UI files...");
|
||||
try {
|
||||
await replaceUIFiles(osuPath, false);
|
||||
logger.log("UI files replaced successfully.");
|
||||
} catch (err) {
|
||||
logger.error("Failed to replace UI files:", err);
|
||||
mainWindow.webContents.send("ezpplauncher:alert", {
|
||||
type: "error",
|
||||
message: "Failed to replace UI files. try restarting EZPPLauncher.",
|
||||
});
|
||||
mainWindow.webContents.send("ezpplauncher:launchabort");
|
||||
return;
|
||||
}
|
||||
|
||||
const forceUpdateFiles = [
|
||||
".require_update",
|
||||
"help.txt",
|
||||
"_pending",
|
||||
];
|
||||
//TODO: needs testing
|
||||
|
||||
try {
|
||||
for (const updateFileName of forceUpdateFiles) {
|
||||
const updateFile = path.join(osuPath, updateFileName);
|
||||
@@ -577,7 +668,9 @@ function registerIPCPipes() {
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch { }
|
||||
} catch (err) {
|
||||
logger.error("Failed to remove force update files:", err);
|
||||
}
|
||||
|
||||
const userConfig = getUserConfig(osuPath);
|
||||
if (richPresence.hasPresence) {
|
||||
@@ -596,13 +689,18 @@ function registerIPCPipes() {
|
||||
status: "Launching osu!...",
|
||||
});
|
||||
|
||||
await new Promise((res) => setTimeout(res, 1000));
|
||||
|
||||
logger.log("Launching osu!...");
|
||||
|
||||
const onExitHook = () => {
|
||||
logger.log("osu! has exited.");
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
stopOsuStatus();
|
||||
richPresence.updateUser({
|
||||
username: " ",
|
||||
id: undefined
|
||||
id: undefined,
|
||||
});
|
||||
richPresence.updateStatus({
|
||||
state: "Idle in Launcher...",
|
||||
@@ -612,24 +710,36 @@ function registerIPCPipes() {
|
||||
mainWindow.webContents.send("ezpplauncher:launchstatus", {
|
||||
status: "Waiting for cleanup...",
|
||||
});
|
||||
const timeStart = performance.now();
|
||||
logger.log("Waiting for cleanup...");
|
||||
|
||||
setTimeout(async () => {
|
||||
await replaceUIFile(osuPath, true);
|
||||
const cleanup = setInterval(async () => {
|
||||
const osuUIFile = path.join(osuPath, "osu!ui.dll");
|
||||
const osuGameplayFile = path.join(osuPath, "osu!gameplay.dll");
|
||||
if (isWritable(osuUIFile) && isWritable(osuGameplayFile)) {
|
||||
logger.log(
|
||||
`Cleanup complete, took ${((performance.now() - timeStart) / 1000).toFixed(3)
|
||||
} seconds.`,
|
||||
);
|
||||
clearInterval(cleanup);
|
||||
await replaceUIFiles(osuPath, true);
|
||||
mainWindow.webContents.send("ezpplauncher:launchabort");
|
||||
osuLoaded = false;
|
||||
}, 5000);
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
runOsuWithDevServer(osuPath, "ez-pp.farm", onExitHook);
|
||||
mainWindow.hide();
|
||||
startOsuStatus();
|
||||
|
||||
/* mainWindow.webContents.send("ezpplauncher:launchprogress", {
|
||||
progress: 0,
|
||||
});
|
||||
mainWindow.webContents.send("ezpplauncher:launchprogress", {
|
||||
progress: 100,
|
||||
}); */
|
||||
return true;
|
||||
} catch (err) {
|
||||
logger.error("Failed to launch", err);
|
||||
mainWindow.webContents.send("ezpplauncher:alert", {
|
||||
type: "error",
|
||||
message: "Failed to launch osu!. Please try again.",
|
||||
});
|
||||
mainWindow.webContents.send("ezpplauncher:launchabort");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -685,6 +795,13 @@ function createWindow() {
|
||||
richPresence.connect();
|
||||
}
|
||||
}
|
||||
|
||||
logger.init();
|
||||
|
||||
const loggingEnabled = config.get("logging");
|
||||
if (loggingEnabled && loggingEnabled == "true") {
|
||||
logger.enabled = true;
|
||||
}
|
||||
// Uncomment the following line of code when app is ready to be packaged.
|
||||
// loadURL(mainWindow);
|
||||
|
||||
@@ -705,10 +822,6 @@ function createWindow() {
|
||||
// Emitted when the window is ready to be shown
|
||||
// This helps in showing the window gracefully.
|
||||
mainWindow.once("ready-to-show", async () => {
|
||||
const updateInfo = await updateAvailable();
|
||||
if (updateInfo.update) {
|
||||
mainWindow.webContents.send("ezpplauncher:update", updateInfo.release);
|
||||
}
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
});
|
||||
|
1115
package-lock.json
generated
1115
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ezpplauncher-next",
|
||||
"version": "2.1.1",
|
||||
"version": "2.1.6",
|
||||
"description": "EZPPLauncher rewritten with Svelte.",
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
@@ -51,7 +51,7 @@
|
||||
"regedit-rs": "^1.0.2",
|
||||
"semver": "^7.5.4",
|
||||
"svelte-french-toast": "^1.2.0",
|
||||
"sweetalert2": "^11.10.3",
|
||||
"sweetalert2": "^11.10.8",
|
||||
"systeminformation": "^5.21.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -61,7 +61,6 @@
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@rollup/plugin-typescript": "^11.1.5",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.1",
|
||||
"@tsconfig/svelte": "^5.0.2",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"concurrently": "^8.2.2",
|
||||
|
10
preload.js
10
preload.js
@@ -82,6 +82,10 @@ window.addEventListener("settings-set", async (e) => {
|
||||
await ipcRenderer.invoke("ezpplauncher:settings-set", e.detail);
|
||||
});
|
||||
|
||||
window.addEventListener("updateCheck", async () => {
|
||||
await ipcRenderer.invoke("ezpplauncher:checkUpdate");
|
||||
})
|
||||
|
||||
window.addEventListener("updateExit", async () => {
|
||||
await ipcRenderer.invoke("ezpplauncher:exitAndUpdate");
|
||||
});
|
||||
@@ -115,3 +119,9 @@ ipcRenderer.addListener("ezpplauncher:update", (e, args) => {
|
||||
new CustomEvent("update", { detail: args }),
|
||||
);
|
||||
});
|
||||
|
||||
ipcRenderer.addListener("ezpplauncher:open-settings", (e, args) => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("open-settings"),
|
||||
);
|
||||
});
|
||||
|
@@ -66,6 +66,12 @@
|
||||
window.dispatchEvent(new CustomEvent("updateExit"));
|
||||
});
|
||||
|
||||
window.dispatchEvent(new CustomEvent("updateCheck"));
|
||||
|
||||
window.addEventListener("open-settings", (e) => {
|
||||
currentPage.set(Page.Settings);
|
||||
});
|
||||
|
||||
window.addEventListener("launchStatusUpdate", (e) => {
|
||||
const status = (e as CustomEvent).detail.status;
|
||||
launchStatus.set(status);
|
||||
|
@@ -26,12 +26,12 @@
|
||||
green: "bg-green-600 dark:bg-green-500",
|
||||
yellow: "bg-yellow-400",
|
||||
purple: "bg-purple-600 dark:bg-purple-500",
|
||||
indigo: "bg-indigo-600 dark:bg-indigo-500",
|
||||
indigo: "bg-indigo-600 dark:bg-indigo-500"
|
||||
};
|
||||
|
||||
let _progress = tweened(0, {
|
||||
duration: tweenDuration,
|
||||
easing,
|
||||
easing
|
||||
});
|
||||
|
||||
$: {
|
||||
@@ -50,7 +50,11 @@
|
||||
>
|
||||
<span class="text-sm font-medium text-blue-700 dark:text-white"
|
||||
>{animate
|
||||
? $_progress.toFixed(precision)
|
||||
? isNaN($_progress)
|
||||
? parseInt("100").toFixed(precision)
|
||||
: $_progress.toFixed(precision)
|
||||
: isNaN(progress)
|
||||
? parseInt("100").toFixed(precision)
|
||||
: progress.toFixed(precision)}%</span
|
||||
>
|
||||
</div>
|
||||
@@ -63,7 +67,13 @@
|
||||
class={twJoin(labelInsideClass, barColors[color])}
|
||||
style="width: {animate ? $_progress : progress}%"
|
||||
>
|
||||
{animate ? $_progress.toFixed(precision) : progress.toFixed(precision)}%
|
||||
{animate
|
||||
? isNaN($_progress)
|
||||
? parseInt("100").toFixed(precision)
|
||||
: $_progress.toFixed(precision)
|
||||
: isNaN(progress)
|
||||
? parseInt("100").toFixed(precision)
|
||||
: progress.toFixed(precision)}%
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
|
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { Button, Checkbox } from "flowbite-svelte";
|
||||
import { Button } from "flowbite-svelte";
|
||||
import Progressbar from "../lib/Progressbar.svelte";
|
||||
import {
|
||||
launching,
|
||||
patch,
|
||||
launchStatus,
|
||||
launchPercentage,
|
||||
launchPercentage
|
||||
} from "./../storage/localStore";
|
||||
let progressbarFix = true;
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input, Button, Spinner, Checkbox } from "flowbite-svelte";
|
||||
import type { User } from "../types/user";
|
||||
import type { Error } from "../types/error";
|
||||
import { type User } from "../types/user";
|
||||
import { currentPage, currentUser, startup } from "../storage/localStore";
|
||||
import toast from "svelte-french-toast";
|
||||
import { Page } from "../consts/pages";
|
||||
@@ -43,14 +42,14 @@
|
||||
position: "bottom-center",
|
||||
className:
|
||||
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
||||
duration: 3000,
|
||||
duration: 3000
|
||||
});
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("login-attempt", {
|
||||
detail: { username, password, saveCredentials },
|
||||
detail: { username, password, saveCredentials }
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -59,13 +58,13 @@
|
||||
{
|
||||
loading: "Logging in...",
|
||||
success: "Successfully logged in!",
|
||||
error: "Invalid Username or Password!",
|
||||
error: "Invalid Username or Password!"
|
||||
},
|
||||
{
|
||||
position: "bottom-center",
|
||||
className:
|
||||
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
||||
duration: 3000,
|
||||
duration: 3000
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -87,7 +86,7 @@
|
||||
position: "bottom-center",
|
||||
className:
|
||||
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
||||
duration: 3000,
|
||||
duration: 3000
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -104,7 +103,7 @@
|
||||
position: "bottom-center",
|
||||
className:
|
||||
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
||||
duration: 3000,
|
||||
duration: 3000
|
||||
});
|
||||
loading = false;
|
||||
},
|
||||
@@ -117,13 +116,13 @@
|
||||
{
|
||||
loading: "Logging in...",
|
||||
success: "Successfully logged in!",
|
||||
error: "Failed to login.",
|
||||
error: "Failed to login."
|
||||
},
|
||||
{
|
||||
position: "bottom-center",
|
||||
className:
|
||||
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
||||
duration: 3000,
|
||||
duration: 3000
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -135,7 +134,7 @@
|
||||
position: "bottom-center",
|
||||
className:
|
||||
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
||||
duration: 3000,
|
||||
duration: 3000
|
||||
});
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Button, ButtonGroup, Input, Toggle } from "flowbite-svelte";
|
||||
import { FileSearchSolid, FolderSolid } from "flowbite-svelte-icons";
|
||||
import { patch, presence } from "./../storage/localStore";
|
||||
import { patch, presence, logging } from "./../storage/localStore";
|
||||
|
||||
let folderPath: string = "";
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
const settingPresence = settings.find(
|
||||
(setting) => setting.key == "presence"
|
||||
);
|
||||
const settingLogging = settings.find((setting) => setting.key == "logging");
|
||||
patch.set(settingPatch ? settingPatch.val == "true" : true);
|
||||
presence.set(settingPresence ? settingPresence.val == "true" : true);
|
||||
logging.set(settingLogging ? settingLogging.val == "true" : false);
|
||||
folderPath = osuPath ? osuPath.val : "";
|
||||
});
|
||||
window.dispatchEvent(new CustomEvent("settings-get"));
|
||||
@@ -39,19 +41,18 @@
|
||||
new CustomEvent("setting-update", { detail: { presence: $presence } })
|
||||
);
|
||||
};
|
||||
|
||||
const toggleLogging = () => {
|
||||
logging.set(!$logging);
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("setting-update", { detail: { logging: $logging } })
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<main
|
||||
class="h-[265px] flex flex-col justify-start p-3 animate-fadeIn opacity-0"
|
||||
>
|
||||
<div class="flex flex-col gap-2 p-3">
|
||||
<Toggle class="w-fit" bind:checked={$presence} on:click={togglePresence}
|
||||
>Discord Presence</Toggle
|
||||
>
|
||||
<Toggle class="w-fit" bind:checked={$patch} on:click={togglePatching}
|
||||
>Patching</Toggle
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="container flex flex-col items-center justify-center gap-5 rounded-lg p-3"
|
||||
>
|
||||
@@ -77,4 +78,15 @@
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 p-3">
|
||||
<Toggle class="w-fit" bind:checked={$presence} on:click={togglePresence}
|
||||
>Discord Presence</Toggle
|
||||
>
|
||||
<Toggle class="w-fit" bind:checked={$patch} on:click={togglePatching}
|
||||
>Patching</Toggle
|
||||
>
|
||||
<Toggle class="w-fit" bind:checked={$logging} on:click={toggleLogging}
|
||||
>Debug Logging</Toggle
|
||||
>
|
||||
</div>
|
||||
</main>
|
||||
|
@@ -7,8 +7,11 @@ export const updateAvailable = writable(false);
|
||||
export const launching = writable(false);
|
||||
export const launchStatus = writable("Waiting...");
|
||||
export const launchPercentage = writable(-1);
|
||||
|
||||
export const currentUser: Writable<undefined | User> = writable(undefined);
|
||||
export const currentPage = writable(Page.Login);
|
||||
|
||||
export const osuPath: Writable<undefined | string> = writable(undefined);
|
||||
export const patch = writable(true);
|
||||
export const presence = writable(true);
|
||||
export const currentUser: Writable<undefined | User> = writable(undefined);
|
||||
export const currentPage = writable(Page.Login);
|
||||
export const logging = writable(false);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const { vitePreprocess } = require("@sveltejs/vite-plugin-svelte");
|
||||
const preprocess = require("svelte-preprocess");
|
||||
|
||||
const config = {
|
||||
preprocess: [vitePreprocess({})],
|
||||
preprocess: [preprocess()],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
Reference in New Issue
Block a user