aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app/browser.js4
-rw-r--r--src/app/icons/apply.pngbin0 -> 2555 bytes
-rw-r--r--src/app/icons/settings.pngbin0 -> 2496 bytes
-rw-r--r--src/app/index.html70
-rw-r--r--src/app/main.css141
-rw-r--r--src/app/main.js9
-rw-r--r--src/app/settings.js103
-rw-r--r--src/index.js2
-rw-r--r--src/utils.js14
9 files changed, 297 insertions, 46 deletions
diff --git a/src/app/browser.js b/src/app/browser.js
index ded12fa..275e16e 100644
--- a/src/app/browser.js
+++ b/src/app/browser.js
@@ -104,10 +104,6 @@ var Browser = {
}
}
-document.body.addEventListener("keyup", (e) => {
- if (e.key == "Escape") {Browser.toggle(false)}
-})
-
function BrowserElFromObj(obj) {
let pkg = {...obj, ...obj.versions[0]};
diff --git a/src/app/icons/apply.png b/src/app/icons/apply.png
new file mode 100644
index 0000000..915f809
--- /dev/null
+++ b/src/app/icons/apply.png
Binary files differ
diff --git a/src/app/icons/settings.png b/src/app/icons/settings.png
new file mode 100644
index 0000000..3f7715a
--- /dev/null
+++ b/src/app/icons/settings.png
Binary files differ
diff --git a/src/app/index.html b/src/app/index.html
index b5fc8cb..f605136 100644
--- a/src/app/index.html
+++ b/src/app/index.html
@@ -10,6 +10,7 @@
<div id="toasts"></div>
<div id="winbtns">
+ <div id="settings" onclick="Settings.toggle(true)"></div>
<div id="minimize" onclick="ipcRenderer.send('minimize')"></div>
<div id="close" onclick="ipcRenderer.send('exit')"></div>
</div>
@@ -21,9 +22,71 @@
</div>
</div>
- <div id="overlay" onclick="Browser.toggle(false)"></div>
- <div id="browser">
- <div id="misc">
+ <div id="overlay" onclick="Browser.toggle(false);Settings.toggle(false)"></div>
+ <div class="popup" id="options">
+ <div class="misc">
+ <div style="width:100%"></div>
+ <button id="apply" onclick="Settings.toggle(false);Settings.apply()">
+ <img src="icons/apply.png">
+ Save
+ </button>
+ <button id="close" onclick="Settings.toggle(false);Settings.load()">
+ <img src="icons/close.png">
+ Discard
+ </button>
+ </div>
+ <div class="options">
+ <h2>Northstar</h2>
+ <div class="option" name="nsargs">
+ <div class="text">
+ Launch options
+ <div class="desc">
+ Here you can add launch options for Northstar/Titanfall.
+ </div>
+ </div>
+ <div class="actions">
+ <input>
+ </div>
+ </div>
+ <h2>Updates</h2>
+ <div class="option" name="autoupdate">
+ <div class="text">
+ Viper Auto-Updates
+ <div class="desc">
+ Viper will automatically keep itself up-to-date.
+ </div>
+ </div>
+ <div class="actions">
+ <button class="switch on"></button>
+ </div>
+ </div>
+ <div class="option" name="nsupdate">
+ <div class="text">
+ Northstar Auto-Updates
+ <div class="desc">
+ Viper will automatically keep Northstar up-to-date, however it can still manually be updated through the Northstar page.
+ </div>
+ </div>
+ <div class="actions">
+ <button class="switch on"></button>
+ </div>
+ </div>
+ <div class="option" name="excludes" type="array">
+ <div class="text">
+ Retain files on update
+ <div class="desc">
+ When Northstar is updated, files specified here will not be overwritten by files from the new Northstar update, unless you know what you're changing, you should probably not change anything here.
+ </div>
+ </div>
+ <div class="actions">
+ <input>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="popup" id="browser">
+ <div class="misc">
<input id="search" placeholder="%%gui.browser.search%%">
<button id="close" onclick="Browser.toggle(false)">
<img src="icons/close.png">
@@ -126,6 +189,7 @@
<script src="main.js"></script>
<script src="toast.js"></script>
<script src="browser.js"></script>
+ <script src="settings.js"></script>
<script src="launcher.js"></script>
</body>
</html>
diff --git a/src/app/main.css b/src/app/main.css
index dcc4e8a..0d4b9ad 100644
--- a/src/app/main.css
+++ b/src/app/main.css
@@ -1,17 +1,17 @@
:root {
- --red: #C7777F;
- --blue: #81A1C1;
- --orange: #D59783;
+ --red: 199, 119, 127;
+ --blue: 129, 161, 193;
+ --orange: 213, 151, 131;
--padding: 25px;
--bg: rgba(0, 0, 0, 0.5);
--selbg: rgba(80, 80, 80, 0.5);
- --redbg: linear-gradient(45deg, var(--red), #FA4343);
- --bluebg: linear-gradient(45deg, var(--blue), #7380ED);
+ --redbg: linear-gradient(45deg, rgb(var(--red)), #FA4343);
+ --bluebg: linear-gradient(45deg, rgb(var(--blue)), #7380ED);
}
-#browser, #modsdiv {
+.popup, #modsdiv {
outline: 1px solid #444444;
border: 3px solid var(--bg);
}
@@ -27,12 +27,12 @@
::-webkit-scrollbar-thumb {
border-radius: 10px;
- background: var(--red);
+ background: rgb(var(--red));
}
::selection {
color: black;
- background: var(--red);
+ background: rgb(var(--red));
}
body {
@@ -66,7 +66,7 @@ button {
cursor: pointer;
}
-#browser {
+.popup {
--spacing: var(--padding);
z-index: 2;
@@ -85,7 +85,7 @@ button {
transition: opacity 0.15s ease-in-out, transform 0.15s ease-in-out;
}
-#browser.shown {
+.popup.shown {
opacity: 1.0;
pointer-events: all;
transform: scale(1.0);
@@ -114,7 +114,7 @@ button {
100% {opacity: 1.0}
}
-#browser .el, #browser #misc, #browser .loading {
+.popup .el, .popup .misc, .popup .loading {
--spacing: calc(var(--padding) / 2);
--height: calc(var(--padding) * 3);
--mischeight: calc(var(--padding) * 1.5);
@@ -129,7 +129,7 @@ button {
transition: 0.15s ease-in-out;
}
-#browser .el, #browser #search, #browser #close {
+.popup .el, .popup #search, .option .actions input, .popup #close, .popup .misc button {
color: white;
display: flex;
align-items: center;
@@ -141,41 +141,48 @@ button {
width: calc(100% - var(--spacing) * 4);
}
-#browser #misc, #browser #search {
+.popup .misc, .popup #search, .option .actions input {
--height: var(--mischeight);
}
-#browser #misc {
+.popup .misc {
display: flex;
}
-#browser #search {
+.popup #search, .option .actions input {
border: none;
outline: none;
transition: filter 0.15s ease-in-out;
width: calc(100% - var(--spacing) * 2);
}
-#browser #search:focus {
+.popup #search:focus, .option .actions input:focus, .option .actions button:active {
filter: brightness(1.5);
}
-#browser #close {
+.popup .misc button {
--height: calc(var(--padding) * 1.5);
padding: 0px;
margin-left: 0px;
- width: var(--height);
+ padding: 0px !important;
+ width: var(--height) !important;
}
-#browser #close img {
+.popup .misc button img {
opacity: 0.6;
width: var(--height);
- height: var(--height);
transform: scale(0.6);
+ height: var(--height) !important;
+}
+
+#options.popup .misc button {
+ margin-left: 0px;
+ width: auto !important;
+ padding-right: calc(var(--padding) / 2) !important;
}
-#browser .loading {
+.popup .loading {
width: 100%;
color: white;
display: flex;
@@ -185,38 +192,99 @@ button {
height: calc(100% - var(--mischeight) - var(--height));
}
-#browser .message {
+.popup .message {
color: white;
text-align: center;
margin: var(--padding);
width: calc(100% - var(--padding));
}
-#browser .el .image, #browser .el .image img {
+.popup .el .image, .popup .el .image img {
width: var(--height);
height: var(--height);
margin-right: var(--spacing);
border-radius: var(--spacing);
}
-#browser .el .text {
+.popup .el .text {
overflow: hidden;
}
-#browser .el .title, #browser .el .description {
+.popup .el .title, .popup .el .description {
height: 1.2em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
-#browser .el .title {font-size: 1.2em}
-#browser .el .description {font-size: 0.8em}
-#browser .el button {
- background: var(--blue);
+.popup .el .title {font-size: 1.2em}
+.popup .el .description {font-size: 0.8em}
+.popup .el button {
+ background: rgb(var(--blue));
margin-top: var(--spacing);
}
+.popup .options {
+ color: white;
+ margin: calc(var(--padding) / 2);
+}
+
+.popup .options .option {
+ width: 100%;
+ display: flex;
+ margin-bottom: var(--padding);
+ justify-content: space-between;
+}
+
+.option .text {font-weight: 600}
+.option .text .desc {
+ opacity: 0.8;
+ font-weight: 500;
+ font-size: 0.9em;
+ max-width: 400px;
+ margin-top: calc(var(--padding) / 3);
+}
+
+.option .actions input {
+ width: 100%;
+ margin: 0px;
+ --spacing: calc(var(--padding) / 3);
+}
+
+.option .actions button {
+ background: var(--selbg);
+}
+
+.switch {
+ width: 50px;
+ height: 25px;
+ border-radius: 50px;
+}
+
+.switch.on {
+ background: rgba(var(--red), 0.2) !important;
+}
+
+.switch::after {
+ left: -5px;
+ width: 15px;
+ height: 15px;
+ content: " ";
+ display: block;
+ background: red;
+ position: relative;
+ border-radius: 50px;
+ background: var(--bg);
+ transition: 0.2s ease-in-out;
+}
+
+.switch.on::after {
+ left: 15px;
+ width: 20px;
+ opacity: 0.5;
+ background: rgb(var(--red));
+}
+
#winbtns {
z-index: 2;
display: flex;
@@ -237,9 +305,10 @@ button {
#winbtns #close {background-image: url("icons/close.png")}
#winbtns #minimize {background-image: url("icons/minimize.png")}
+#winbtns #settings {background-image: url("icons/settings.png")}
#winbtns div:hover {opacity: 1.0}
-#winbtns div:active {transform: scale(0.98)}
+#winbtns div:active {transform: scale(0.95)}
button:hover {filter: brightness(110%)}
button:active {filter: brightness(90%)}
@@ -388,7 +457,7 @@ img {pointer-events: none}
text-align: center;
position: relative;
border-radius: 50px;
- background: var(--red);
+ background: rgb(var(--red));
left: calc(50% - 15px);
transition: 0.2s ease-in-out;
}
@@ -453,7 +522,7 @@ img {pointer-events: none}
}
a {
- color: var(--red);
+ color: rgb(var(--red));
text-decoration: none;
transition: filter 0.2s ease-in;
}
@@ -500,12 +569,12 @@ a:hover {
}
.simplebar-scrollbar:before {
- background: var(--red) !important;
+ background: rgb(var(--red)) !important;
}
-#installmod {background: var(--blue)}
-#togglemod, #toggleall {background: var(--orange)}
-#northstar, #removeall, #removemod {background: var(--red)}
+#installmod {background: rgb(var(--blue))}
+#togglemod, #toggleall {background: rgb(var(--orange))}
+#northstar, #removeall, #removemod {background: rgb(var(--red))}
button:disabled {
opacity: 0.5;
pointer-events: none;
diff --git a/src/app/main.js b/src/app/main.js
index 97937a9..a781ef1 100644
--- a/src/app/main.js
+++ b/src/app/main.js
@@ -8,7 +8,9 @@ let shouldInstallNorthstar = false;
// Base settings
var settings = {
+ nsargs: "",
gamepath: "",
+ nsupdate: true,
autoupdate: true,
zip: "/northstar.zip",
lang: navigator.language,
@@ -275,6 +277,13 @@ document.addEventListener("drop", (e) => {
installFromPath(event.dataTransfer.files[0].path)
});
+document.body.addEventListener("keyup", (e) => {
+ if (e.key == "Escape") {
+ Browser.toggle(false);
+ Settings.toggle(false);
+ }
+})
+
document.body.addEventListener("click", event => {
if (event.target.tagName.toLowerCase() === "a" && event.target.protocol != "file:") {
event.preventDefault();
diff --git a/src/app/settings.js b/src/app/settings.js
new file mode 100644
index 0000000..4921e07
--- /dev/null
+++ b/src/app/settings.js
@@ -0,0 +1,103 @@
+var Settings = {
+ toggle: (state) => {
+ if (state) {
+ Settings.load();
+ options.scrollTo(0, 0);
+ overlay.classList.add("shown")
+ options.classList.add("shown")
+
+ return
+ } else if (! state) {
+ if (state != undefined) {
+ overlay.classList.remove("shown")
+ options.classList.remove("shown")
+ return
+ }
+ }
+
+ Settings.load();
+ options.scrollTo(0, 0);
+ overlay.classList.toggle("shown")
+ options.classList.toggle("shown")
+ },
+ apply: () => {
+ settings = {...settings, ...Settings.get()};
+ ipcRenderer.send("savesettings", Settings.get());
+ },
+ reloadSwitches: () => {
+ let switches = document.querySelectorAll(".switch");
+
+ for (let i = 0; i < switches.length; i++) {
+ switches[i].setAttribute("onclick", `Settings.switch(${i})`);
+ }
+ },
+ switch: (element) => {
+ let switches = document.querySelectorAll(".switch");
+ element = switches[element];
+
+ if (element.classList.contains("on")) {
+ element.classList.add("off");
+ element.classList.remove("on");
+ } else {
+ element.classList.add("on");
+ element.classList.remove("off");
+ }
+
+ Settings.reloadSwitches();
+ },
+ get: () => {
+ let opts = {};
+ let options = document.querySelectorAll(".option");
+
+ for (let i = 0; i < options.length; i++) {
+ let optName = options[i].getAttribute("name");
+ if (options[i].querySelector(".actions input")) {
+ let input = options[i].querySelector(".actions input").value;
+ if (options[i].getAttribute("type")) {
+ opts[optName] = input.split(" ");
+ } else {
+ opts[optName] = input;
+ }
+ } else if (options[i].querySelector(".actions .switch")) {
+ if (options[i].querySelector(".actions .switch.on")) {
+ opts[optName] = true;
+ } else {
+ opts[optName] = false;
+ }
+ }
+ }
+
+ return opts;
+ },
+ load: () => {
+ let options = document.querySelectorAll(".option");
+
+ for (let i = 0; i < options.length; i++) {
+ let optName = options[i].getAttribute("name");
+ if (settings[optName] != undefined) {
+ switch(typeof settings[optName]) {
+ case "string":
+ options[i].querySelector(".actions input").value = settings[optName];
+ break
+ case "object":
+ options[i].querySelector(".actions input").value = settings[optName].join(" ");
+ break
+ case "boolean":
+ let switchDiv = options[i].querySelector(".actions .switch");
+ if (settings[optName]) {
+ switchDiv.classList.add("on");
+ switchDiv.classList.remove("off");
+ } else {
+ switchDiv.classList.add("off");
+ switchDiv.classList.remove("on");
+ }
+ break
+
+ }
+ }
+ }
+ }
+}
+
+Settings.reloadSwitches();
+Settings.load();
diff --git a/src/index.js b/src/index.js
index 95115b4..fa2a35f 100644
--- a/src/index.js
+++ b/src/index.js
@@ -53,6 +53,8 @@ function start() {
ipcMain.on("installedmod", (event, modname) => {win.webContents.send("installedmod", modname)});
ipcMain.on("guigetmods", (event, ...args) => {win.webContents.send("mods", utils.mods.list())});
+ ipcMain.on("savesettings", (event, obj) => {utils.saveSettings(obj)})
+
win.webContents.on("dom-ready", () => {
win.webContents.send("mods", utils.mods.list());
});
diff --git a/src/utils.js b/src/utils.js
index 336017f..2449a73 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -22,11 +22,13 @@ process.chdir(app.getPath("appData"));
var settings = {
gamepath: "",
lang: "en-US",
+ nsupdate: true,
autoupdate: true,
+ nsargs: "-multiple",
zip: "/northstar.zip",
// These files won't be overwritten when installing/updating
- // Northstar, useful for config file.
+ // Northstar, useful for config files
excludes: [
"ns_startup_args.txt",
"ns_startup_args_dedi.txt"
@@ -170,8 +172,13 @@ async function setpath(win, forcedialog) {
// As to not have to do the same one liner a million times, this
// function exists, as the name suggests, it simply writes the current
// settings to the disk.
-function saveSettings() {
- fs.writeFileSync(app.getPath("appData") + "/viper.json", JSON.stringify(settings));
+//
+// You can also pass a settings object to the function and it'll try and
+// merge it together with the already existing settings
+function saveSettings(obj = {}) {
+ settings = {...settings, ...obj};
+ fs.writeFileSync(path.join(settings.gamepath, "ns_startup_args.txt"), settings.nsargs);
+ fs.writeFileSync(app.getPath("appData") + "/viper.json", JSON.stringify({...settings, ...obj}));
}
// Returns the current Northstar version
@@ -756,6 +763,7 @@ module.exports = {
setpath,
updatevp,
settings,
+ saveSettings,
getNSVersion,
getTF2Version,
isGameRunning,