diff options
Diffstat (limited to 'src/app/main.js')
-rw-r--r-- | src/app/main.js | 576 |
1 files changed, 24 insertions, 552 deletions
diff --git a/src/app/main.js b/src/app/main.js index f4c1624..3adb96d 100644 --- a/src/app/main.js +++ b/src/app/main.js @@ -3,334 +3,16 @@ const path = require("path"); const Fuse = require("fuse.js"); const { app, ipcRenderer, shell } = require("electron"); -const json = require("../modules/json"); - const lang = require("../lang"); -var modsobj = { - all: [], - enabled: [], - disabled: [] -} - -let shouldInstallNorthstar = false; - -// Base settings -// -// TODO: dont duplicate this, instead just use the one in -// `src/modules/settings.js` automatically -var settings = { - nsargs: "", - gamepath: "", - nsupdate: true, - autolang: true, - forcedlang: "en", - autoupdate: true, - originkill: false, - zip: "/northstar.zip", - lang: navigator.language, - - linux_launch_cmd_ns: "", - linux_launch_cmd_vanilla: "", - linux_launch_method: "steam_auto", - - excludes: [ - "ns_startup_args.txt", - "ns_startup_args_dedi.txt" - ] -} - -// invokes `requests.get()` from `src/modules/requests.js` through the -// main process, and returns the output -async function request(...args) { - return await ipcRenderer.invoke("request", ...args); -} - -// Sets the lang to the system default -ipcRenderer.send("setlang", settings.lang); - -// Loads the settings -if (fs.existsSync("viper.json")) { - let iteration = 0; - - // loads the config file, it's loaded in an interval like this in - // case the config file is currently being written to, if we were to - // read from the file during that, then it'd be empty or similar. - // - // and because of that, we check if the file is empty when loading - // it, if so we wait 100ms, then check again, and we keep doing that - // hoping it'll become normal again. unless we've checked it 50 - // times, then we simply give up, and force the user to re-select - // the gamepath, as this'll make the config file readable again. - // - // ideally it'll never have to check those 50 times, it's only in - // case something terrible has gone awry, like if a write got - // interrupted, or a user messed with the file. - // - // were it to truly be broken, then it'd take up to 5 seconds to - // then reset, this is basically nothing, especially considering - // this should only happen in very rare cases... hopefully! - let config_interval = setInterval(() => { - iteration++; - - config = json("viper.json") || {}; - - // checks whether `settings.gamepath` is set, and if so, - // it'll attempt to load ns_startup_args.txt - let parse_settings = () => { - // if gamepath is not set, attempt to set it - if (settings.gamepath.length === 0) { - setpath(false); - } else { - // if the gamepath is set, we'll simply tell the main - // process about it, and it'll then show the main - // renderer BrowserWindow - setpath(true); - } - - // filepath to Northstar's startup args file - let args = path.join(settings.gamepath, "ns_startup_args.txt"); - - // check file exists, and that no `nsargs` setting was set - if (! settings.nsargs && fs.existsSync(args)) { - // load arguments from file into `settings` - settings.nsargs = fs.readFileSync(args, "utf8"); - } - } - - // make sure config isn't empty - if (Object.keys(config).length !== 0) { - // add `config` to `settings` - settings = { - ...settings, - ...config - }; parse_settings(); - - clearInterval(config_interval); - return; - } - - // we've attempted to load the config 50 times now, give up - if (iteration >= 50) { - // request a new gamepath be set - setpath(false); - clearInterval(config_interval); - } - }, 100) -} else { - setpath(); -} - -ipcRenderer.on("changed-settings", (e, new_settings) => { - // attempt to set `settings` to `new_settings` - try { - settings = { - ...settings, - ...new_settings - } - }catch(e) {} -}) - -// Show a toast message if no Internet connection has been detected. -if (! navigator.onLine) { - ipcRenderer.send("no-internet"); -} - -function exit() {ipcRenderer.send("exit")} - -let checked_for_ns_update = new Date().getTime(); - -function updateNorthstar() { - checked_for_ns_update = new Date().getTime(); - ipcRenderer.send("update-northstar") -} - -function force_update_ns() { - ipcRenderer.send("update-northstar", true); -} - -function reset_config() { - ipcRenderer.send("reset-config"); -} - -function open_gamepath() { - let open_path = require("electron").shell.openPath; - if (settings.gamepath) { - open_path(settings.gamepath); - } else { - alert(lang("gui.settings.miscbuttons.open_gamepath_alert")); - } -} - -function relaunch() { - ipcRenderer.send("relaunch"); -} - -// Reports to the main process about game path status. -// @param {boolean} value is game path loaded -function setpath(value = false) { - ipcRenderer.send("setpath", value); -} - -// Tells the main process to launch or install Northstar -function launch() { - if (shouldInstallNorthstar) { - updateNorthstar(); - shouldInstallNorthstar = false; - } else { - ipcRenderer.send("launch-ns"); - } -} - -// Tells the main process to launch the vanilla game -function launchVanilla() {ipcRenderer.send("launch-vanilla")} - -let log = console.log; - -// Disables or enables certain buttons when for example -// updating/installing Northstar. -function setButtons(state, enable_gamepath_btns) { - playNsBtn.disabled = !state; - - let disablearray = (array) => { - for (let i = 0; i < array.length; i++) { - array[i].disabled = ! state; - - if (state) { - array[i].classList.remove("disabled") - } else { - array[i].classList.add("disabled") - } - } - } - - disablearray(document.querySelectorAll("#modsdiv .el button")); - disablearray(document.querySelectorAll(".disable-when-installing")); - disablearray(document.querySelectorAll(".playBtnContainer .playBtn")); - disablearray(document.querySelectorAll("#nsMods .buttons.modbtns button")); - disablearray(document.querySelectorAll("#browser #browserEntries .text button")); - - if (enable_gamepath_btns) { - let gamepath_btns = - document.querySelectorAll('*[onclick="setpath()"]'); - - for (let i = 0; i < gamepath_btns.length; i++) { - gamepath_btns[i].disabled = false; - gamepath_btns[i].classList.remove("disabled"); - } - } -} - -// `percent` should be a number between 0 to 100, if it's `false` it'll -// reset it back to nothing instantly, with no animatino -function set_ns_progress(percent) { - // reset button progress - if (percent === false) { - document.querySelector(".contentContainer #nsMain .playBtn") - .style.setProperty("--progress", "unset"); - - return; - } - - percent = parseInt(percent); - - // make sure we're dealing with a number - if (isNaN(percent) || typeof percent !== "number") { - return false; - } - - // limit percent, while this barely has a difference, if you were to - // set a very high number, the CSS would then use a very high - // number, not great. - if (percent > 100) { - percent = 100; - } else if (percent < 0) { - percent = 0; - } - - // invert number to it works in the CSS - percent = 100 - percent; - - // set the CSS progress variable - document.querySelector(".contentContainer #nsMain .playBtn") - .style.setProperty("--progress", percent + "%"); -} - -ipcRenderer.on("set-buttons", (event, state) => { - setButtons(state); -}) - -ipcRenderer.on("gamepath-lost", (event, state) => { - page(0); - setButtons(false, true); - alert(lang("gui.gamepath.lost")); -}) - -// Frontend part of updating Northstar -ipcRenderer.on("ns-update-event", (event, options) => { - let key = options.key; - if (typeof options == "string") { - key = options; - } - - // updates text in update button to `lang(key)` - let update_btn = () => { - document.getElementById("update") - .innerText = `(${lang(key)})`; - } - - switch(key) { - case "cli.update.uptodate_short": - case "cli.update.no_internet": - // initial value - let delay = 0; - - // get current time - let now = new Date().getTime(); - - // check if `checked_for_ns_update` was less than 500ms - // since now, this variable is set when `updateNorthstar()` - // is called - if (now - checked_for_ns_update < 500) { - // if less than 500ms has passed, set `delay` to the - // amount of milliseconds missing until we've hit that - // 500ms threshold - delay = 500 - (now - checked_for_ns_update); - } - - // wait `delay`ms - setTimeout(() => { - // set buttons accordingly - update_btn(); - setButtons(true); - set_ns_progress(false); - playNsBtn.innerText = lang("gui.launch"); - }, delay) - - break; - default: - update_btn(); - - if (options.progress) { - set_ns_progress(options.progress); - } - - if (options.btn_text) { - playNsBtn.innerText = options.btn_text; - } - - setButtons(false); - break; - } -}); ipcRenderer.on("unknown-error", (event, err) => { - new Toast({ + toasts.show({ timeout: 10000, scheme: "error", title: lang("gui.toast.title.unknown_error"), description: lang("gui.toast.desc.unknown_error"), callback: () => { - new Toast({ + toasts.show({ timeout: 15000, scheme: "error", title: "", @@ -339,238 +21,28 @@ ipcRenderer.on("unknown-error", (event, err) => { } }) - console.error(err.stack) -}) - -let installqueue = []; - -// Tells the main process to install a mod through the file selector -function installmod() { - setButtons(false); - ipcRenderer.send("install-mod"); -} - -// Tells the main process to directly install a mod from this path -function installFromPath(path) { - setButtons(false); - ipcRenderer.send("install-from-path", path); -} - -// Tells the main process to install a mod from a URL -function installFromURL(url, dependencies, clearqueue, author, package_name, version) { - if (clearqueue) {installqueue = []}; - - let prettydepends = []; - - if (dependencies) { - let newdepends = []; - for (let i = 0; i < dependencies.length; i++) { - let depend = dependencies[i].toLowerCase(); - if (! depend.match(/northstar-northstar-.*/)) { - depend = dependencies[i].replaceAll("-", "/"); - let pkg = depend.split("/"); - if (! isModInstalled(pkg[1])) { - newdepends.push({ - pkg: depend, - author: pkg[0], - version: pkg[2], - package_name: pkg[1] - }); - - prettydepends.push(`${pkg[1]} v${pkg[2]} - ${lang("gui.browser.made_by")} ${pkg[0]}`); - } - } - } - - dependencies = newdepends; - } - - if (dependencies && dependencies.length != 0) { - let confirminstall = confirm(lang("gui.mods.confirm_dependencies") + prettydepends.join("\n")); - if (! confirminstall) { - return - } - } - - setButtons(false); - ipcRenderer.send("install-from-url", url, author, package_name, version); - - if (dependencies) { - installqueue = dependencies; - } -} - -function isModInstalled(modname) { - for (let i = 0; i < modsobj.all.length; i++) { - let mod = modsobj.all[i]; - if (mod.manifest_name) { - if (mod.manifest_name.match(modname)) { - return true; - } - } else if (mod.name.match(modname)) { - return true; - } - } - - return false; -} - -// Frontend part of settings a new game path -ipcRenderer.on("newpath", (event, newpath) => { - setButtons(true); - settings.gamepath = newpath; - ipcRenderer.send("gui-getmods"); - ipcRenderer.send("save-settings", settings); -}) - -// Continuation of log() -ipcRenderer.on("log", (event, msg) => {log(msg)}) -ipcRenderer.on("alert", (event, data) => { - alert(data.message); - ipcRenderer.send("alert-closed-" + data.id); -}) - -ipcRenderer.on("confirm", (event, data) => { - let confirmed = confirm(data.message); - ipcRenderer.send("confirm-closed-" + data.id, confirmed); -}) - -let is_running = false; -ipcRenderer.on("is-running", (event, running) => { - let set_playbtns = (text) => { - let playbtns = document.querySelectorAll(".playBtn"); - for (let i = 0; i < playbtns.length; i++) { - playbtns[i].innerHTML = text; - } - } - - if (running && is_running != running) { - setButtons(false); - set_playbtns(lang("general.running")); - - is_running = running; - - // show force quit button in Titanfall tab - tfquit.style.display = "inline-block"; - - update.setAttribute("onclick", "kill_game()"); - update.innerHTML = "(" + lang("ns.menu.force_quit") + ")"; - return; - } - - if (is_running != running) { - setButtons(true); - set_playbtns(lang("gui.launch")); - - is_running = running; - - // hide force quit button in Titanfall tab - tfquit.style.display = "none"; - - update.setAttribute("onclick", "updateNorthstar()"); - update.innerHTML = "(" + lang("gui.update.check") + ")"; - } -}) - -function kill_game() { - ipcRenderer.send("kill-game"); -} - -function kill_origin() { - ipcRenderer.send("kill-origin"); -} - -function delete_request_cache() { - ipcRenderer.send("delete-request-cache"); -} - -function delete_install_cache() { - ipcRenderer.send("delete-install-cache"); -} - -// Updates the installed mods -ipcRenderer.on("mods", (event, mods_obj) => { - modsobj = mods_obj; - if (! mods_obj) {return} - - mods.load(mods_obj); -}) - -// Updates version numbers -ipcRenderer.on("version", (event, versions) => { - vpversion.innerText = versions.vp; - nsversion.innerText = versions.ns; - tf2Version.innerText = versions.tf2; - - if (versions.ns == "unknown") { - let buttons = document.querySelectorAll(".modbtns button"); - - for (let i = 0; i < buttons.length; i++) { - buttons[i].disabled = true; - } - - // Since Northstar is not installed, we cannot launch it - shouldInstallNorthstar = true; - playNsBtn.innerText = lang("gui.install"); - } -}); ipcRenderer.send("get-version"); - -// When an update is available it'll ask the user about it -ipcRenderer.on("update-available", () => { - if (confirm(lang("gui.update.available"))) { - ipcRenderer.send("update-now"); - } + console.error(err.stack); }) -// Error out when no game path is set -ipcRenderer.on("no-path-selected", () => { - alert(lang("gui.gamepath.must")); - exit(); -}); - -// Error out when game path is wrong -ipcRenderer.on("wrong-path", () => { - alert(lang("gui.gamepath.wrong")); - setpath(false); -}); - -setlang(); - -let dragtimer; -document.addEventListener("dragover", (e) => { - e.preventDefault(); - e.stopPropagation(); - dragUI.classList.add("shown"); - - clearTimeout(dragtimer); - dragtimer = setTimeout(() => { - dragUI.classList.remove("shown"); - }, 5000) -}); - -document.addEventListener("mouseover", (e) => { - clearTimeout(dragtimer); - dragUI.classList.remove("shown"); -}); - -document.addEventListener("drop", (e) => { - event.preventDefault(); - event.stopPropagation(); - - dragUI.classList.remove("shown"); - installFromPath(event.dataTransfer.files[0].path); -}); - -document.body.addEventListener("keyup", (e) => { - if (e.key == "Escape") { - Browser.toggle(false); - Settings.toggle(false); - } -}) +const json = require("../modules/json"); -document.body.addEventListener("click", event => { - if (event.target.tagName.toLowerCase() === "a" && event.target.protocol != "file:") { - event.preventDefault(); - shell.openExternal(event.target.href); - } -}); +const kill = require("./js/kill"); +const mods = require("./js/mods"); +const toasts = require("./js/toasts"); +const update = require("./js/update"); +const events = require("./js/events"); +const launch = require("./js/launch"); +const popups = require("./js/popups"); +const browser = require("./js/browser"); +const tooltip = require("./js/tooltip"); +const version = require("./js/version"); +const request = require("./js/request"); +const process = require("./js/process"); +const settings = require("./js/settings"); +const gamepath = require("./js/gamepath"); +const launcher = require("./js/launcher"); +const is_running = require("./js/is_running"); +const set_buttons = require("./js/set_buttons"); + +require("./js/dom_events"); +require("./js/localize")(); |