diff options
author | 0neGal <mail@0negal.com> | 2024-02-04 15:40:23 +0100 |
---|---|---|
committer | 0neGal <mail@0negal.com> | 2024-02-04 15:46:55 +0100 |
commit | e8e502cc574fdd6eaa54a3a25c2d975596c13026 (patch) | |
tree | d193b02d9f37afe109a497b99b6bffc54a5cab64 | |
parent | ceda605611c9ec2fbe858f3ae29942d56a06ac66 (diff) | |
download | Viper-e8e502cc574fdd6eaa54a3a25c2d975596c13026.tar.gz Viper-e8e502cc574fdd6eaa54a3a25c2d975596c13026.zip |
move IPC events into their respective modules
I've not been able to find anything that breaks from this, as I've gone
through every IPC event that got moved, to ensure it still functions,
and all the breakage I found has since been fixed.
IPC events that dont fit in any particular module is also now in the new
file named `src/app/modules/ipc.js`
There's also another module `src/win.js`, which lets you get the
`BrowserWindow` outside of `src/index.js`
I also took the oppertunity to clean up some of the code when moving it
around, and adding a couple comments, as some of it was quite horrid.
-rw-r--r-- | src/cli.js | 11 | ||||
-rw-r--r-- | src/index.js | 336 | ||||
-rw-r--r-- | src/modules/gamepath.js | 61 | ||||
-rw-r--r-- | src/modules/ipc.js | 32 | ||||
-rw-r--r-- | src/modules/is_running.js | 5 | ||||
-rw-r--r-- | src/modules/kill.js | 15 | ||||
-rw-r--r-- | src/modules/launch.js | 6 | ||||
-rw-r--r-- | src/modules/mods.js | 86 | ||||
-rw-r--r-- | src/modules/packages.js | 12 | ||||
-rw-r--r-- | src/modules/releases.js | 12 | ||||
-rw-r--r-- | src/modules/requests.js | 19 | ||||
-rw-r--r-- | src/modules/settings.js | 28 | ||||
-rw-r--r-- | src/modules/update.js | 76 | ||||
-rw-r--r-- | src/modules/version.js | 17 | ||||
-rw-r--r-- | src/modules/window.js | 15 | ||||
-rw-r--r-- | src/win.js | 13 |
16 files changed, 400 insertions, 344 deletions
@@ -80,7 +80,16 @@ async function init() { // --update if (cli.hasSwitch("update") && gamepathExists()) {ipcMain.emit("update")} // --version - if (cli.hasSwitch("version") && gamepathExists()) {ipcMain.emit("version-cli")} + if (cli.hasSwitch("version") && gamepathExists()) { + let version = require("./modules/version"); + + console.log("Viper: v" + require("../package.json").version); + console.log("Titanfall 2: " + version.titanfall()); + console.log("Northstar: " + version.northstar()); + console.log("Node: " + process.version); + console.log("Electron: v" + process.versions.electron); + exit(); + } // --setpath if (cli.hasSwitch("setpath")) { diff --git a/src/index.js b/src/index.js index 82805d1..ef6703a 100644 --- a/src/index.js +++ b/src/index.js @@ -1,30 +1,24 @@ -const fs = require("fs"); const path = require("path"); -const { autoUpdater } = require("electron-updater"); -const { app, ipcMain, BrowserWindow, dialog } = require("electron"); +const { app, BrowserWindow } = require("electron"); // ensures PWD/CWD is the config folder where viper.json is located process.chdir(app.getPath("appData")); const cli = require("./cli"); -const lang = require("./lang"); +const main_win = require("./win"); -const json = require("./modules/json"); -const kill = require("./modules/kill"); const mods = require("./modules/mods"); const update = require("./modules/update"); -const launch = require("./modules/launch"); -const win_show = require("./modules/window"); const version = require("./modules/version"); -const gamepath = require("./modules/gamepath"); const settings = require("./modules/settings"); -const requests = require("./modules/requests"); -const releases = require("./modules/releases"); -const packages = require("./modules/packages"); -const is_running = require("./modules/is_running"); + +// loads `ipcMain` events that dont fit in any of the modules directly +require("./modules/ipc"); + +// required to load launch IPC events +require("./modules/launch"); console = require("./modules/console"); -var log = console.log; // Starts the actual BrowserWindow, which is only run when using the // GUI, for the CLI this function is never called. @@ -50,7 +44,16 @@ function start() { nodeIntegration: true, contextIsolation: false, }, - }); + }) + + // makes sending things to the renderer a little more readable + win.send = (channel, data) => { + win.webContents.send(channel, data); + }; send = win.send; + + // give `main_win` the main window, `main_win()` will then be equal + // to `win`, but its accessible anywhere + main_win.set(win); // when --devtools is added it'll open the dev tools if (cli.hasParam("devtools")) { @@ -63,159 +66,24 @@ function start() { }, 1) } - // general setup + // we dont need this! win.removeMenu(); + + // load `src/app/index.html` (the app) win.loadURL("file://" + __dirname + "/app/index.html", { userAgent: "viper/" + version.viper(), - }); - - win.send = (channel, data) => { - win.webContents.send(channel, data); - }; send = win.send; - - ipcMain.on("exit", () => { - if (settings().originkill) { - is_running.origin().then((running) => { - if (running) { - kill.origin().then(process.exit(0)) - } else { - process.exit(0) - } - }) - } else { - process.exit(0) - } - }); - - ipcMain.on("minimize", () => {win.minimize()}); - ipcMain.on("relaunch", () => { - app.relaunch({ - args: process.argv.slice(1) - }); - - app.exit(0); - }); - - ipcMain.on("kill-game", () => { - kill.game(); - }); - - ipcMain.on("kill-origin", () => { - kill.origin(); - }); - - ipcMain.on("delete-request-cache", () => { - requests.cache.delete.all(); - }); - - ipcMain.on("delete-install-cache", () => { - let delete_dirs = [ - path.join(app.getPath("cache"), "vipertmp"), - path.join(settings().gamepath, "northstar.zip") - ] - - for (let i = 0; i < delete_dirs.length; i++) { - if (fs.existsSync(delete_dirs[i])) { - fs.rmSync(delete_dirs[i], {recursive: true}); - } - } - }); - - ipcMain.on("reset-config", async () => { - let confirmation = await win_show.confirm( - lang("gui.settings.miscbuttons.reset_config_alert") - ) - - if (confirmation) { - fs.rmSync("viper.json"); - - app.relaunch({ - args: process.argv.slice(1) - }); - - app.exit(0); - } - }); - - // passthrough to renderer from main - ipcMain.on("win-log", (event, ...args) => {send("log", ...args)}); - ipcMain.on("win-alert", (event, msg, id) => { - send("alert", { - id: id, - message: msg, - }) - }); - - ipcMain.on("win-confirm", (event, msg, id) => { - send("confirm", { - id: id, - message: msg, - }) - }); - - // mod states - ipcMain.on("duped-mod", (event, modname) => {send("duped-mod", modname)}); - ipcMain.on("failed-mod", (event, modname) => {send("failed-mod", modname)}); - ipcMain.on("removed-mod", (event, modname) => {send("removed-mod", modname)}); - ipcMain.on("gui-getmods", (event, ...args) => {send("mods", mods.list())}); - ipcMain.on("installed-mod", (event, modname) => {send("installed-mod", modname)}); - ipcMain.on("no-internet", () => {send("no-internet")}); + }) + // print exceptions to terminal, and forward the exception to the + // renderer, it'll then show a more user friendly error message process.on("uncaughtException", (err) => { send("unknown-error", err); console.error(err); - }); - - // install calls - ipcMain.on("install-from-path", (event, path) => {mods.install(path)}); - ipcMain.on("install-from-url", (event, url, author, package_name, version) => { - packages.install(url, author, package_name, version); - }); - - // lets renderer use `requests.get()` - ipcMain.handle("request", async (e, ...args) => { - let res = false; - - try { - res = await requests.get(...args); - }catch(err) {} - - return res; }) + // load list of mods on initial load win.webContents.on("dom-ready", () => { send("mods", mods.list()); - }); - - // ensures gamepath still exists and is valid on startup - let gamepathlost = false; - ipcMain.on("gamepath-lost", (event, ...args) => { - if (! gamepathlost) { - gamepathlost = true; - send("gamepath-lost"); - } - }); - - ipcMain.on("save-settings", (event, obj) => { - settings().save(obj, false); - }); - - ipcMain.on("saved-settings", (event, obj) => { - send("changed-settings", obj); - }); - - // allows renderer to check for updates - ipcMain.on("ns-update-event", (event) => {send("ns-update-event", event)}); - - let update_active; - ipcMain.on("can-autoupdate", () => { - if (typeof update_active == "undefined") { - update_active = autoUpdater.isUpdaterActive(); - } - - if (! update_active || cli.hasParam("no-vp-updates")) { - send("cant-autoupdate"); - } }) // start auto-update process @@ -223,171 +91,29 @@ function start() { if (cli.hasParam("no-vp-updates")) { update.northstar_autoupdate(); } else { - update.viper(false) + update.viper(false); } } else { update.northstar_autoupdate(); } - - autoUpdater.on("update-downloaded", () => { - send("update-available"); - }); - - // updates and restarts Viper, if user says yes to do so. - // otherwise it'll do it on the next start up. - ipcMain.on("update-now", () => { - autoUpdater.quitAndInstall(); - }) - - setInterval(async () => { - send("is-running", await is_running.game()); - }, 1000) } -ipcMain.on("install-mod", () => { - if (cli.hasArgs()) { - mods.install(cli.param("installmod")); - } else { - dialog.showOpenDialog({properties: ["openFile"]}).then(res => { - if (res.filePaths.length != 0) { - mods.install(res.filePaths[0]); - } else { - send("set-buttons", true); - } - }).catch(err => {error(err)}); - } -}) - -ipcMain.on("remove-mod", (event, mod) => {mods.remove(mod)}); -ipcMain.on("toggle-mod", (event, mod) => {mods.toggle(mod)}); - -ipcMain.on("launch-ns", () => {launch()}); -ipcMain.on("launch-vanilla", () => {launch("vanilla")}); - -ipcMain.on("setlang", (event, lang) => { - settings().set("lang", lang); - settings().save(); -}); - -ipcMain.on("update-northstar", async (e, force_install) => { - if (await is_running.game()) { - return win_show.alert(lang("general.auto_updates.game_running")); - } - - update.northstar(force_install); -}) - -ipcMain.on("setpath-cli", () => {gamepath.set()}); -ipcMain.on("setpath", (event, value, force_dialog) => { - if (! value) { - if (! win.isVisible()) { - gamepath.set(win, force_dialog); - } else { - gamepath.set(win, force_dialog || true); - } - } else if (! win.isVisible()) { - win.show(); - } -}); - -// retrieves various local version numbers -function sendVersionsInfo() { - send("version", { - ns: version.northstar(), - tf2: version.titanfall(), - vp: "v" + version.viper() - }); -} - -// sends the version info back to the renderer -ipcMain.on("get-version", () => {sendVersionsInfo()}); - -// prints out version info for the CLI -ipcMain.on("version-cli", () => { - log("Viper: v" + require("../package.json").version); - log("Titanfall 2: " + version.titanfall()); - log("Northstar: " + version.northstar()); - log("Node: " + process.version); - log("Electron: v" + process.versions.electron); - cli.exit(); -}) - -// sends installed mods info to renderer -ipcMain.on("getmods", () => { - let mods = mods.list(); - if (mods.all.length > 0) { - log(`${lang("general.mods.installed")} ${mods.all.length}`); - log(`${lang("general.mods.enabled")} ${mods.enabled.length}`); - for (let i = 0; i < mods.enabled.length; i++) { - log(` ${mods.enabled[i].name} ${mods.enabled[i].version}`); - } - - if (mods.disabled.length > 0) { - log(`${lang("general.mods.disabled")} ${mods.disabled.length}`); - for (let i = 0; i < mods.disabled.length; i++) { - log(` ${mods.disabled[i].name} ${mods.disabled[i].version}`); - } - } - cli.exit(0); - } else { - log("No mods installed"); - cli.exit(0); - } -}) -// } - -// allows renderer to set a new renderer -ipcMain.on("newpath", (event, newpath) => { - if (newpath === false && ! win.isVisible()) { - win.send("no-path-selected"); - } else { - sendVersionsInfo(); - if (!win.isVisible()) { - win.show(); - } - } -}); ipcMain.on("wrong-path", () => { - win.send("wrong-path"); -}); - -ipcMain.on("found-missing-perms", async (e, selected_gamepath) => { - await win_show.alert(lang("gui.gamepath.found_missing_perms") + selected_gamepath); - ipcMain.emit("setpath", null, false, true); -}) - -ipcMain.on("missing-perms", async (e, selected_gamepath) => { - await win_show.alert(lang("gui.gamepath.missing_perms") + selected_gamepath); - ipcMain.emit("setpath"); -}) - -ipcMain.on("gamepath-lost-perms", async (e, selected_gamepath) => { - if (! gamepath.setting) { - gamepath.setting = true; - await win_show.alert(lang("gui.gamepath.lost_perms") + selected_gamepath); - ipcMain.emit("setpath"); - } -}) - // starts the GUI or CLI if (cli.hasArgs()) { if (cli.hasParam("update-viper")) { update.viper(true); } else { + // start the CLI cli.init(); } } else { app.on("ready", () => { + // makes it so Electron cache doesn't get stored in your system + // config folder, changing it over to actually using the system + // cache folder instead app.setPath("userData", path.join(app.getPath("cache"), app.name)); + // start the window/GUI start(); }) } - -// returns cached requests -ipcMain.on("get-ns-notes", async () => { - win.send("ns-notes", await releases.notes.northstar()); -}); - -ipcMain.on("get-vp-notes", async () => { - win.send("vp-notes", await releases.notes.viper()); -}); diff --git a/src/modules/gamepath.js b/src/modules/gamepath.js index 8d28c29..9d12854 100644 --- a/src/modules/gamepath.js +++ b/src/modules/gamepath.js @@ -1,18 +1,77 @@ const path = require("path"); const fs = require("fs-extra"); +const win = require("../win"); const { dialog, ipcMain } = require("electron"); const cli = require("../cli"); const lang = require("../lang"); +const version = require("./version"); const win_show = require("./window"); const settings = require("./settings"); const findgame = require("./findgame"); - let gamepath = {}; +ipcMain.on("setpath-cli", () => {gamepath.set()}); +ipcMain.on("setpath", (event, value, force_dialog) => { + if (! value) { + if (! win().isVisible()) { + gamepath.set(win(), force_dialog); + } else { + gamepath.set(win(), force_dialog || true); + } + } else if (! win().isVisible()) { + win().show(); + } +}) + + +// allows renderer to set a new renderer +ipcMain.on("newpath", (event, newpath) => { + if (newpath === false && ! win().isVisible()) { + win().send("no-path-selected"); + } else { + version.send_info(); + + if (! win().isVisible()) { + win().show(); + } + } +}) + +ipcMain.on("wrong-path", () => { + win().send("wrong-path"); +}) + +ipcMain.on("found-missing-perms", async (e, selected_gamepath) => { + await win_show.alert(lang("gui.gamepath.found_missing_perms") + selected_gamepath); + ipcMain.emit("setpath", null, false, true); +}) + +ipcMain.on("missing-perms", async (e, selected_gamepath) => { + await win_show.alert(lang("gui.gamepath.missing_perms") + selected_gamepath); + ipcMain.emit("setpath"); +}) + +ipcMain.on("gamepath-lost-perms", async (e, selected_gamepath) => { + if (! gamepath.setting) { + gamepath.setting = true; + await win_show.alert(lang("gui.gamepath.lost_perms") + selected_gamepath); + ipcMain.emit("setpath"); + } +}) + +// ensures gamepath still exists and is valid on startup +let gamepathlost = false; +ipcMain.on("gamepath-lost", (event, ...args) => { + if (! gamepathlost) { + gamepathlost = true; + win().send("gamepath-lost"); + } +}) + // returns true/false depending on if the gamepath currently exists/is // mounted, used to avoid issues... gamepath.exists = (folder) => { diff --git a/src/modules/ipc.js b/src/modules/ipc.js new file mode 100644 index 0000000..55737b7 --- /dev/null +++ b/src/modules/ipc.js @@ -0,0 +1,32 @@ +const win = require("../win"); +const { app, ipcMain } = require("electron"); + +const kill = require("./kill"); +const settings = require("./settings"); +const is_running = require("./is_running"); + +ipcMain.on("exit", () => { + if (settings().originkill) { + is_running.origin().then((running) => { + if (running) { + kill.origin().then(process.exit(0)); + } else { + process.exit(0) ; + } + }) + } else { + process.exit(0); + } +}) + +ipcMain.on("minimize", () => { + win().minimize(); +}) + +ipcMain.on("relaunch", () => { + app.relaunch({ + args: process.argv.slice(1) + }) + + app.exit(0); +}) diff --git a/src/modules/is_running.js b/src/modules/is_running.js index 1cfdc1d..b9fbde1 100644 --- a/src/modules/is_running.js +++ b/src/modules/is_running.js @@ -1,7 +1,12 @@ +const win = require("../win"); const exec = require("child_process").exec; let is_running = {}; +setInterval(async () => { + win().send("is-running", await is_running.game()); +}, 1000) + // a simple function that checks whether any of a given set of process // names are running, you can either input a string or an Array of // strings diff --git a/src/modules/kill.js b/src/modules/kill.js index 3c93f7b..43eda23 100644 --- a/src/modules/kill.js +++ b/src/modules/kill.js @@ -1,4 +1,13 @@ const exec = require("child_process").exec; +const ipcMain = require("electron").ipcMain; + +ipcMain.on("kill-game", () => { + kill.game(); +}) + +ipcMain.on("kill-origin", () => { + kill.origin(); +}) // a simple function to kill processes with a certain name async function kill(process_name) { @@ -9,13 +18,13 @@ async function kill(process_name) { case "linux": return "killall -9 " + proc; case "win32": return "taskkill /IM " + proc + " /F"; } - })(); + })() exec(cmd, (err, stdout) => { // just try and fail silently if we don't find it w/e resolve(true); - }); - }); + }) + }) } kill.process = kill; diff --git a/src/modules/launch.js b/src/modules/launch.js index bb094e9..e9ad1a3 100644 --- a/src/modules/launch.js +++ b/src/modules/launch.js @@ -1,4 +1,5 @@ const exec = require("child_process").exec; +const ipcMain = require("electron").ipcMain; const cli = require("../cli"); const lang = require("../lang"); @@ -8,6 +9,11 @@ const settings = require("./settings"); console = require("./console"); +ipcMain.on("launch-ns", launch); +ipcMain.on("launch-vanilla", () => { + launch("vanilla"); +}) + // launches the game // // either Northstar or Vanilla. Linux support is not currently a thing, diff --git a/src/modules/mods.js b/src/modules/mods.js index 122ff7f..2e9288b 100644 --- a/src/modules/mods.js +++ b/src/modules/mods.js @@ -2,8 +2,8 @@ const path = require("path"); const fs = require("fs-extra"); const unzip = require("unzipper"); const copy = require("recursive-copy"); -const { app, ipcMain } = require("electron"); const { https } = require("follow-redirects"); +const { app, ipcMain, dialog } = require("electron"); const json = require("./json"); const win = require("./window"); @@ -14,12 +14,72 @@ console = require("./console"); const cli = require("../cli"); const lang = require("../lang"); +const main_win = require("../win"); var mods = { installing: [], dupe_msg_sent: false, } +ipcMain.on("remove-mod", (event, mod) => { + mods.remove(mod); +}) + +ipcMain.on("toggle-mod", (event, mod) => { + mods.toggle(mod); +}) + +// lets renderer install mods from a path +ipcMain.on("install-from-path", (event, path) => { + mods.install(path); +}) + +ipcMain.on("no-internet", () => { + main_win().send("no-internet"); +}) + +ipcMain.on("install-mod", () => { + if (cli.hasArgs()) { + mods.install(cli.param("installmod")); + } else { + dialog.showOpenDialog({properties: ["openFile"]}).then(res => { + if (res.filePaths.length != 0) { + mods.install(res.filePaths[0]); + } else { + main_win().send("set-buttons", true); + } + }).catch(err => {error(err)}); + } +}) + +// sends installed mods info to renderer +ipcMain.on("gui-getmods", (event, ...args) => { + main_win().send("mods", mods.list()); +}) + +ipcMain.on("getmods", () => { + let mods = mods.list(); + + if (mods.all.length > 0) { + log(`${lang("general.mods.installed")} ${mods.all.length}`); + log(`${lang("general.mods.enabled")} ${mods.enabled.length}`); + for (let i = 0; i < mods.enabled.length; i++) { + log(` ${mods.enabled[i].name} ${mods.enabled[i].version}`); + } + + if (mods.disabled.length > 0) { + log(`${lang("general.mods.disabled")} ${mods.disabled.length}`); + for (let i = 0; i < mods.disabled.length; i++) { + log(` ${mods.disabled[i].name} ${mods.disabled[i].version}`); + } + } + cli.exit(0); + } else { + log("No mods installed"); + cli.exit(0); + } +}) + function update_path() { mods.path = path.join(settings().gamepath, "R2Northstar/mods"); }; update_path(); @@ -341,12 +401,12 @@ mods.install = (mod, opts) => { } } - ipcMain.emit("installed-mod", "", { + main_win().send("installed-mod", { name: modname, malformed: opts.malformed, - }); + }) - ipcMain.emit("gui-getmods"); + main_win().send("mods", mods.list()); return true; } @@ -360,7 +420,7 @@ mods.install = (mod, opts) => { if (! json(path.join(mod, "mod.json"))) { - ipcMain.emit("failed-mod"); + main_win().send("failed-mod"); return notamod(); } @@ -375,13 +435,13 @@ mods.install = (mod, opts) => { copy(mod, copydest, (err) => { if (err) { - ipcMain.emit("failed-mod"); + main_win().send("failed-mod"); return; } copy(opts.manifest_file, path.join(copydest, "manifest.json"), (err) => { if (err) { - ipcMain.emit("failed-mod"); + main_win().send("failed-mod"); return; } @@ -411,7 +471,7 @@ mods.install = (mod, opts) => { while (mods.installing.includes(mod_name)) { if (! mods.dupe_msg_sent) { mods.dupe_msg_sent = true; - ipcMain.emit("duped-mod", "", mod_name); + main_win().send("duped-mod", mod_name); } use_mod_name = true; @@ -490,7 +550,7 @@ mods.install = (mod, opts) => { } if (files.length == 0) { - ipcMain.emit("failed-mod"); + main_win().send("failed-mod"); return notamod(); } } @@ -612,14 +672,14 @@ mods.remove = (mod) => { console.ok(lang("cli.mods.removed")); cli.exit(); - ipcMain.emit("gui-getmods"); // send updated list to renderer + main_win().send("mods", mods.list()); // send updated list to renderer // tell the renderer that the mod has been removed, along with // relevant info for it to properly update everything graphically - ipcMain.emit("removed-mod", "", { + main_win().send("removed-mod", { name: mod.replace(/^.*(\\|\/|\:)/, ""), manifest_name: manifest_name - }); + }) } // toggles mods @@ -660,7 +720,7 @@ mods.toggle = (mod, fork) => { } // send updated modlist to renderer - ipcMain.emit("gui-getmods"); + main_win().send("mods", mods.list()); } module.exports = mods; diff --git a/src/modules/packages.js b/src/modules/packages.js index 392c550..88e389a 100644 --- a/src/modules/packages.js +++ b/src/modules/packages.js @@ -5,6 +5,7 @@ const { app, ipcMain } = require("electron"); const https = require("follow-redirects").https; const lang = require("../lang"); +const main_win = require("../win"); const json = require("./json"); const win = require("./window"); @@ -14,6 +15,11 @@ console = require("./console"); var packages = {}; +// lets renderer install packages +ipcMain.on("install-from-url", (event, url, author, package_name, version) => { + packages.install(url, author, package_name, version); +}) + function update_path() { packages.path = path.join(settings().gamepath, "R2Northstar/packages"); @@ -238,7 +244,7 @@ packages.install = async (url, author, package_name, version) => { } break; default: - ipcMain.emit("failed-mod", name); + main_win().send("failed-mod", name); // other unhandled error console.error( @@ -303,7 +309,7 @@ packages.install = async (url, author, package_name, version) => { let moved = packages.move(package_path); if (! moved) { - ipcMain.emit("failed-mod", name); + main_win().send("failed-mod", name); console.error("Moving package failed:", name); cleanup(); @@ -311,7 +317,7 @@ packages.install = async (url, author, package_name, version) => { return false; } - ipcMain.emit("installed-mod", "", { + main_win().send("installed-mod", { name: name, fancy_name: package_name }) diff --git a/src/modules/releases.js b/src/modules/releases.js index c071970..b041d38 100644 --- a/src/modules/releases.js +++ b/src/modules/releases.js @@ -1,3 +1,6 @@ +const win = require("../win"); +const ipcMain = require("electron").ipcMain; + const requests = require("./requests"); let releases = { @@ -5,6 +8,15 @@ let releases = { latest: {} } +// returns release notes to renderer +ipcMain.on("get-ns-notes", async () => { + win().send("ns-notes", await releases.notes.northstar()); +}) + +ipcMain.on("get-vp-notes", async () => { + win().send("vp-notes", await releases.notes.viper()); +}) + // gets and returns the release notes of a GitHub repo async function github_releases(repo) { let request = false; diff --git a/src/modules/requests.js b/src/modules/requests.js index d4ee678..60e0760 100644 --- a/src/modules/requests.js +++ b/src/modules/requests.js @@ -1,6 +1,6 @@ const fs = require("fs"); const path = require("path"); -const app = require("electron").app; +const { app, ipcMain } = require("electron"); const https = require("follow-redirects").https; const json = require("./json"); @@ -9,6 +9,23 @@ const version = require("./version"); var cache_dir = app.getPath("userData"); var cache_file = path.join(cache_dir, "cached-requests.json"); +// lets renderer delete request cache +ipcMain.on("delete-request-cache", () => { + requests.cache.delete.all(); +}) + +// lets renderer use `requests.get()` +ipcMain.handle("request", async (e, ...args) => { + let res = false; + + try { + res = await requests.get(...args); + }catch(err) {} + + return res; +}) + + // updates `cache_dir` and `cache_file` function set_paths() { cache_dir = app.getPath("userData"); diff --git a/src/modules/settings.js b/src/modules/settings.js index db6c68c..ae02c79 100644 --- a/src/modules/settings.js +++ b/src/modules/settings.js @@ -4,11 +4,37 @@ const { app, ipcMain } = require("electron"); const json = require("./json"); const lang = require("../lang"); +const win = require("./window"); console = require("./console"); var invalid_settings = false; +ipcMain.on("save-settings", (event, obj) => { + save(obj, false); +}) + +ipcMain.on("reset-config", async () => { + let confirmation = await win.confirm( + lang("gui.settings.miscbuttons.reset_config_alert") + ) + + if (confirmation) { + fs.rmSync("viper.json"); + + app.relaunch({ + args: process.argv.slice(1) + }) + + app.exit(0); + } +}) + +ipcMain.on("setlang", (event, lang) => { + set("lang", lang); + save(); +}) + // base settings var settings = { gamepath: "", @@ -81,7 +107,7 @@ let save = (obj = {}, notify_renderer = true) => { settings = settings_content; if (notify_renderer) { - ipcMain.emit("saved-settings", settings_content); + send("changed-settings", obj); } } diff --git a/src/modules/update.js b/src/modules/update.js index 6b31da7..1165622 100644 --- a/src/modules/update.js +++ b/src/modules/update.js @@ -1,9 +1,11 @@ const path = require("path"); const fs = require("fs-extra"); -const { ipcMain, Notification } = require("electron"); +const { autoUpdater } = require("electron-updater"); +const { app, ipcMain, Notification } = require("electron"); const cli = require("../cli"); const lang = require("../lang"); +const main_win = require("../win"); const win = require("./window"); const version = require("./version"); @@ -15,10 +17,60 @@ const is_running = require("./is_running"); console = require("./console"); const unzip = require("unzipper"); -const { https } = require("follow-redirects"); +const https = require("follow-redirects").https; let update = {}; +ipcMain.on("delete-install-cache", () => { + let delete_dirs = [ + path.join(app.getPath("cache"), "vipertmp"), + path.join(settings().gamepath, "northstar.zip") + ] + + for (let i = 0; i < delete_dirs.length; i++) { + if (fs.existsSync(delete_dirs[i])) { + fs.rmSync(delete_dirs[i], {recursive: true}); + } + } +}) + +ipcMain.on("update-northstar", async (e, force_install) => { + if (await is_running.game()) { + return win.alert(lang("general.auto_updates.game_running")); + } + + update.northstar(force_install); +}) + +// inform renderer that an update has been downloaded +autoUpdater.on("update-downloaded", () => { + main_win().send("update-available"); +}) + +// updates and restarts Viper, if user says yes to do so. +// otherwise it'll do it on the next start up. +ipcMain.on("update-now", () => { + autoUpdater.quitAndInstall(); +}) + +let update_active; + +// renderer requested a check for whether we can auto updates +ipcMain.on("can-autoupdate", () => { + // is this the first time we're checking? + if (typeof update_active == "undefined") { + // save auto updater status + update_active = autoUpdater.isUpdaterActive(); + } + + // if `update_active` is falsy or `--no-vp-updates` is set, + // inform the renderer that auto updates aren't possible + if (! update_active || cli.hasParam("no-vp-updates")) { + main_win().send("cant-autoupdate"); + } +}) + + // renames excluded files to their original name function restore_excluded_files() { if (! gamepath.exists()) {return} @@ -219,7 +271,7 @@ update.northstar = async (force_install) => { return; } - ipcMain.emit("ns-update-event", "cli.update.checking"); + main_win().send("ns-update-event", "cli.update.checking"); console.info(lang("cli.update.checking")); let ns_version = version.northstar(); @@ -227,13 +279,13 @@ update.northstar = async (force_install) => { if (latest && latest.version == false) { update.northstar.updating = false; - ipcMain.emit("ns-update-event", "cli.update.noInternet"); + main_win().send("ns-update-event", "cli.update.noInternet"); return; } // Makes sure it is not already the latest version if (! force_install && ! await northstar_update_available()) { - ipcMain.emit("ns-update-event", "cli.update.uptodate_short"); + main_win().send("ns-update-event", "cli.update.uptodate_short"); console.ok(lang("cli.update.uptodate").replace("%s", ns_version)); win.log(lang("gui.update.uptodate")); @@ -254,7 +306,7 @@ update.northstar = async (force_install) => { https.get(latest.download_link, (res) => { // cancel out if zip can't be retrieved and or found if (res.statusCode !== 200) { - ipcMain.emit("ns-update-event", "cli.update.uptodate_short"); + main_win().send("ns-update-event", "cli.update.uptodate_short"); console.ok(lang("cli.update.uptodate"), ns_version); update.northstar.updating = false; return false; @@ -279,11 +331,11 @@ update.northstar = async (force_install) => { } console.info(lang("cli.update.downloading") + ":", latest.version); - ipcMain.emit("ns-update-event", { + main_win().send("ns-update-event", { progress: 0, btn_text: "1/2", key: "cli.update.downloading", - }); + }) let tmp = path.dirname(settings().zip); @@ -317,7 +369,7 @@ update.northstar = async (force_install) => { percentage_str = " - " + current_percentage + "%"; } - ipcMain.emit("ns-update-event", { + main_win().send("ns-update-event", { key: key, progress: current_percentage, btn_text: "1/2" + percentage_str @@ -331,7 +383,7 @@ update.northstar = async (force_install) => { let extract = fs.createReadStream(settings().zip); win.log(lang("gui.update.extracting")); - ipcMain.emit("ns-update-event", { + main_win().send("ns-update-event", { progress: 0, btn_text: "2/2 - 0%", key: lang("gui.update.extracting") @@ -352,7 +404,7 @@ update.northstar = async (force_install) => { let percent = Math.floor(extracted / size * 100); let extracted_mb = (extracted / 1024 / 1024).toFixed(1); - ipcMain.emit("ns-update-event", { + main_win().send("ns-update-event", { progress: percent, btn_text: "2/2 - " + percent + "%", key: lang("gui.update.extracting") + @@ -368,7 +420,7 @@ update.northstar = async (force_install) => { ipcMain.emit("gui-getmods"); ipcMain.emit("get-version"); - ipcMain.emit("ns-update-event", "cli.update.uptodate_short"); + main_win().send("ns-update-event", "cli.update.uptodate_short"); win.log(lang("gui.update.finished")); console.ok(lang("cli.update.finished")); diff --git a/src/modules/version.js b/src/modules/version.js index da0a730..e337fc4 100644 --- a/src/modules/version.js +++ b/src/modules/version.js @@ -1,11 +1,28 @@ const path = require("path"); const fs = require("fs-extra"); +const ipcMain = require("electron").ipcMain; + +const win = require("../win"); const json = require("./json"); const settings = require("./settings"); let version = {}; +// sends the version info back to the renderer +ipcMain.on("get-version", () => { + version.send_info(); +}) + +// retrieves various local version numbers and sends them to the renderer +version.send_info = () => { + win().send("version", { + ns: version.northstar(), + tf2: version.titanfall(), + vp: "v" + version.viper() + }) +} + // returns the current Northstar version // if not installed it'll return "unknown" version.northstar = () => { diff --git a/src/modules/window.js b/src/modules/window.js index 6cc573c..ebb0165 100644 --- a/src/modules/window.js +++ b/src/modules/window.js @@ -1,10 +1,11 @@ +const main_win = require("../win"); const ipcMain = require("electron").ipcMain; let win = {}; // logs into the dev tools of the renderer -win.log = (msg) => { - ipcMain.emit("win-log", msg, msg); +win.log = (...args) => { + main_win().send("log", ...args); } // this increments for every alert that's created, the ID is used to @@ -20,7 +21,10 @@ win.alert = (msg) => { resolve(); }) - ipcMain.emit("win-alert", msg, msg, alert_id); + main_win().send("alert", { + id: alert_id, + message: msg + }) }) } @@ -37,7 +41,10 @@ win.confirm = (msg) => { resolve(confirmed); }) - ipcMain.emit("win-confirm", msg, msg, confirm_id); + main_win().send("confirm", { + message: msg, + id: confirm_id + }) }) } diff --git a/src/win.js b/src/win.js new file mode 100644 index 0000000..056dee8 --- /dev/null +++ b/src/win.js @@ -0,0 +1,13 @@ +let win = { + send: () => {} +} + +let func = () => { + return win; +} + +func.set = (main_window) => { + win = main_window; +} + +module.exports = func; |