diff options
author | Rémy Raes <contact@remyraes.com> | 2022-01-12 16:49:02 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-12 16:49:02 +0100 |
commit | ab71fa02bc751da44dee7d4118feaa13f28dee67 (patch) | |
tree | 35f5c15ea502cc3c7de01011f1b9a61b5286d339 | |
parent | 9a135bfc554ccfddf64e71725b98bc4317d14732 (diff) | |
download | Viper-ab71fa02bc751da44dee7d4118feaa13f28dee67.tar.gz Viper-ab71fa02bc751da44dee7d4118feaa13f28dee67.zip |
feat: New UI (#26)
* [chore] removing setsize mechanism
* [feat] adding new html skeleton
* [feat] adding games icon buttons
* [feat] all icon buttons have same size
* [fix] games container width varies between 95 and 120px
* [feat] displaying bg image
* [feat] each game has its own background image
* [feat] adding content skeleton
* [feat] window has no frame anymore
* [feat] buttons show related content only
* [feat] displaying viper release notes
* [feat] game icons are vertically centered
* [feat] background is a bit grayed out
* [feat] adding some items to games menus
* [feat] displaying games logos
* [feat] adding content menu active item indicator
* [fix] centering active item indicator
* [feat] not displaying viper credits by default
* [feat] viper categories can be browsed through via menu
* [feat] adjusting hovering style of menu items
* [feat] adding play button styles
* [feat] adding missing vp sections
* [feat] adding link styles
* [fix] scaling down northstar logo
* [feat] adding ns sections
* [feat] fetching northstar release notes
* [fix] release notes containers are scrollable
* [feat] removing space between menu and some sections
* [feat] loading vp+ns versions into interface
* [chore] pushing version to 0.10.0
* [feat] play buttons launch games
* [refactor] renaming vp releases fetching method
* [feat] displaying an option to update northstar
* [feat] message is displayed if ns is up-to-date
* [feat] displaying ns download progress
* [refactor] removing ns-updating and ns-updated events
* [feat] adding UI translations
* [fix] correctly displaying vp release notes
* [refactor] removing useless code
* [feat] adding Imply to credits for viper logo
* [feat] loading titanfall version from gameversion.txt file
* [feat] centering viper main section
* [feat] adding custom scrollbars to release notes sections
* [feat] disabling images drag
* [feat] all external links are opened in default browser
* [feat] formatting release notes with markdown converter
* [feat] translating UI items
* fixed backgrounds not being same size
This would cause weird transitions.
* new.css is now main.css, fixed colors and fonts
* page indicator is now prettier
We no longer use a character to render a circle, and it's no longer a
circle, instead it's a line, we also now have a nice transition on it,
both for fading in and out.
* removed simplebar in favor of ::-webkit-scrollbar
Almost everything we did with simplerbar could be done with native
WebKit scollbar CSS, hence why we switched to it.
* fixed uneven nav button margin
* fixed formatting
Single quotes to double quotes, spaces to tabs, etc etc... I also
removed simplerbar properly...
* removed unneeded consts
Elements set with ID's can by default be referred to with their ID, aka:
const element = document.getElementById("element");
Is useless as "element" will automatically refer to that element if
theres no variable that overwrites it.
* use release name over tag_name
"Release vX.X.X" frankly looks better than "vX.X.X"
* playBtn's now look nicer
Slight transition on hover and click.
* added pointer cursors to nav buttons and playBtn's
Along with transitions to the nav buttons, because they look very good.
* [fix] viper main section appears correctly on viper logo clicked
* different opacity for inactive pages
* removed "Roboto Mono", added normal "Roboto"
* removed old HTML
* fixed formatting in launcher.js
* redesigned contentContainer's, and a lot more
I also swapped around the Vanilla logo and Northstar logo to have the
same size and the "Titanfall 2" text is in the same place on both
images, allowing seamless transition when changing pages.
I also completely redesigned displayContent(), it's now page() and
doesn't revolve around a switch case. I'll likely do a similar thing
with showVpSection() and showNsSection(), uniting them into one function
that doesn't use switch cases.
* added close button
* fix game icons not being found
* removed excess icons from assets folder
* [feat] adding a br to french releases key
* [feat] centering menu items
* [feat] implementing requests cache for NS release notes
* [feat] implementing cache for VP release notes
* changed ttf2 to tf2
Along with that, I also renamed the northstar2.jpeg bg to just
northstar.jpg, as all other background are .jpg
* [fix] adjusting containers
* [fix] adding some space between menu and content
Since we have lots of space to use now, let's use it!
This extra-space does not apply to release notes sections, which
already takes all available screen space.
* [feat] adding code style
* [fix] window is draggable thanks to a drag bar on its top
* [fix] drag bar height
* [fix] all window is draggable
* [fix] not disabling game buttons on ns update
* [fix] disabled buttons cannot be clicked
* [fix] displaying ns update downloading state on UI
* [fix] typos
* general improvements to the UI
Launch buttons now have a nice gradient, a shadow and a better hover
animation. The Titanfall logos are now also centered no matter the
window size, so if in the future we decide to allow resizing the window
that won't be a problem, or if you force the window to do it through
some trickery, it'll also still show correctly.
I also changed the default font weight to 500, some pieces of text
looked very thin.
* unified information and credits section
* mods section should more or less look good now
Still not complete done, I still wanna implement a drag and drop
install, along with selecting whether you're installing a zip or folder.
And also a warning when toggling or removing required mods...
But generally this is the design I will go with.
* added warnings for toggling/removing core mods
* [feat] adding missing translations
* [fix] typo in gui.mods.disabledtag french translation
* re-added download progress
* added section transitions
* switched to npm module for markdown parsing
* correcting some formatting, nothing special
* active page button is now more obvious
Co-authored-by: 0neGal <mail@0negal.com>
34 files changed, 891 insertions, 170 deletions
diff --git a/package-lock.json b/package-lock.json index d02e4c7..5e3168f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { "name": "viper", - "version": "0.9.1", + "version": "0.9.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "viper", - "version": "0.9.1", + "version": "0.9.2", "license": "GPL-3.0-or-later", "dependencies": { "copy-dir": "^1.3.0", "electron-updater": "^4.6.1", "follow-redirects": "^1.14.6", + "markdown": "^0.5.0", "marked-man": "^0.7.0", "unzipper": "^0.10.11" }, @@ -297,6 +298,11 @@ "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", "dev": true }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2371,6 +2377,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/markdown/-/markdown-0.5.0.tgz", + "integrity": "sha1-KCBbVlqK51kt4gdGPWY33BgnIrI=", + "dependencies": { + "nopt": "~2.1.1" + }, + "bin": { + "md2html": "bin/md2html.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/marked": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", @@ -2488,6 +2508,17 @@ "dev": true, "optional": true }, + "node_modules/nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, "node_modules/normalize-url": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", @@ -3687,6 +3718,11 @@ "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5294,6 +5330,14 @@ "semver": "^6.0.0" } }, + "markdown": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/markdown/-/markdown-0.5.0.tgz", + "integrity": "sha1-KCBbVlqK51kt4gdGPWY33BgnIrI=", + "requires": { + "nopt": "~2.1.1" + } + }, "marked": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", @@ -5376,6 +5420,14 @@ "dev": true, "optional": true }, + "nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", + "requires": { + "abbrev": "1" + } + }, "normalize-url": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", diff --git a/package.json b/package.json index 942efd6..78dcb36 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "copy-dir": "^1.3.0", "electron-updater": "^4.6.1", "follow-redirects": "^1.14.6", + "markdown": "^0.5.0", "marked-man": "^0.7.0", "unzipper": "^0.10.11" }, diff --git a/src/app/fonts/Roboto-Black.ttf b/src/app/fonts/Roboto-Black.ttf Binary files differnew file mode 100644 index 0000000..43a00e0 --- /dev/null +++ b/src/app/fonts/Roboto-Black.ttf diff --git a/src/app/fonts/Roboto-BlackItalic.ttf b/src/app/fonts/Roboto-BlackItalic.ttf Binary files differnew file mode 100644 index 0000000..5082cdc --- /dev/null +++ b/src/app/fonts/Roboto-BlackItalic.ttf diff --git a/src/app/fonts/Roboto-Bold.ttf b/src/app/fonts/Roboto-Bold.ttf Binary files differnew file mode 100644 index 0000000..3742457 --- /dev/null +++ b/src/app/fonts/Roboto-Bold.ttf diff --git a/src/app/fonts/Roboto-BoldItalic.ttf b/src/app/fonts/Roboto-BoldItalic.ttf Binary files differnew file mode 100644 index 0000000..e85e7fb --- /dev/null +++ b/src/app/fonts/Roboto-BoldItalic.ttf diff --git a/src/app/fonts/Roboto-Italic.ttf b/src/app/fonts/Roboto-Italic.ttf Binary files differnew file mode 100644 index 0000000..c9df607 --- /dev/null +++ b/src/app/fonts/Roboto-Italic.ttf diff --git a/src/app/fonts/Roboto-Light.ttf b/src/app/fonts/Roboto-Light.ttf Binary files differnew file mode 100644 index 0000000..0e97751 --- /dev/null +++ b/src/app/fonts/Roboto-Light.ttf diff --git a/src/app/fonts/Roboto-LightItalic.ttf b/src/app/fonts/Roboto-LightItalic.ttf Binary files differnew file mode 100644 index 0000000..3ad14fa --- /dev/null +++ b/src/app/fonts/Roboto-LightItalic.ttf diff --git a/src/app/fonts/Roboto-Medium.ttf b/src/app/fonts/Roboto-Medium.ttf Binary files differnew file mode 100644 index 0000000..e89b0b7 --- /dev/null +++ b/src/app/fonts/Roboto-Medium.ttf diff --git a/src/app/fonts/Roboto-MediumItalic.ttf b/src/app/fonts/Roboto-MediumItalic.ttf Binary files differnew file mode 100644 index 0000000..a5a41d3 --- /dev/null +++ b/src/app/fonts/Roboto-MediumItalic.ttf diff --git a/src/app/fonts/Roboto-Regular.ttf b/src/app/fonts/Roboto-Regular.ttf Binary files differnew file mode 100644 index 0000000..3d6861b --- /dev/null +++ b/src/app/fonts/Roboto-Regular.ttf diff --git a/src/app/fonts/Roboto-Thin.ttf b/src/app/fonts/Roboto-Thin.ttf Binary files differnew file mode 100644 index 0000000..7d084ae --- /dev/null +++ b/src/app/fonts/Roboto-Thin.ttf diff --git a/src/app/fonts/Roboto-ThinItalic.ttf b/src/app/fonts/Roboto-ThinItalic.ttf Binary files differnew file mode 100644 index 0000000..c173389 --- /dev/null +++ b/src/app/fonts/Roboto-ThinItalic.ttf diff --git a/src/app/fonts/import.css b/src/app/fonts/import.css new file mode 100644 index 0000000..c6b677a --- /dev/null +++ b/src/app/fonts/import.css @@ -0,0 +1,83 @@ +@font-face { + font-weight: 100; + font-style: italic; + font-family: "Roboto"; + src: url("Roboto-ThinItalic.ttf"); +} + +@font-face { + font-weight: 300; + font-style: italic; + font-family: "Roboto"; + src: url("Roboto-Italic.ttf"); +} + +@font-face { + font-weight: 400; + font-style: italic; + font-family: "Roboto"; + src: url("Roboto-Italic.ttf"); +} + +@font-face { + font-weight: 500; + font-style: italic; + font-family: "Roboto"; + src: url("Roboto-MediumItalic.ttf"); +} + +@font-face { + font-weight: 700; + font-style: italic; + font-family: "Roboto"; + src: url("Roboto-BoldItalic.ttf"); +} + +@font-face { + font-weight: 900; + font-style: italic; + font-family: "Roboto"; + src: url("Roboto-BlackItalic.ttf"); +} + +@font-face { + font-weight: 100; + font-style: normal; + font-family: "Roboto"; + src: url("Roboto-Thin.ttf"); +} + +@font-face { + font-weight: 300; + font-style: normal; + font-family: "Roboto"; + src: url("Roboto-Light.ttf"); +} + +@font-face { + font-weight: 400; + font-style: normal; + font-family: "Roboto"; + src: url("Roboto-Regular.ttf"); +} + +@font-face { + font-weight: 500; + font-style: normal; + font-family: "Roboto"; + src: url("Roboto-Medium.ttf"); +} + +@font-face { + font-weight: 700; + font-style: normal; + font-family: "Roboto"; + src: url("Roboto-Bold.ttf"); +} + +@font-face { + font-weight: 900; + font-style: normal; + font-family: "Roboto"; + src: url("Roboto-Black.ttf"); +} diff --git a/src/app/icons/close.png b/src/app/icons/close.png Binary files differnew file mode 100644 index 0000000..d6c162f --- /dev/null +++ b/src/app/icons/close.png diff --git a/src/app/icons/northstar.png b/src/app/icons/northstar.png Binary files differnew file mode 100644 index 0000000..f13ae27 --- /dev/null +++ b/src/app/icons/northstar.png diff --git a/src/app/icons/titanfall2.png b/src/app/icons/titanfall2.png Binary files differnew file mode 100644 index 0000000..f1caa0e --- /dev/null +++ b/src/app/icons/titanfall2.png diff --git a/src/app/icons/viper.png b/src/app/icons/viper.png Binary files differnew file mode 100644 index 0000000..281f3dd --- /dev/null +++ b/src/app/icons/viper.png diff --git a/src/app/index.html b/src/app/index.html index d9db79b..8ebffff 100644 --- a/src/app/index.html +++ b/src/app/index.html @@ -1,46 +1,103 @@ <html> <head> <meta name="viewport" content="width=device-width,initial-scale=1.0"> + <link rel="stylesheet" href="fonts/import.css"> <link rel="stylesheet" href="main.css"> + <meta charset="utf-8"> </head> <body> - <div class="lines"> - <div class="line"> - <div class="text"> - <div class="text" id="welcome">%%gui.welcome%%</div> - <div class="versions"> - <div id="vpversion"></div> - <div id="nsversion"></div> + <div id="bgHolder"></div> + + <div id="close" onclick="ipcRenderer.send('exit')"></div> + + <nav class="gamesContainer"> + <button id="vpBtn" onclick="page(0)"></button> + <button id="nsBtn" onclick="page(1)"></button> + <button id="tfBtn" onclick="page(2)"></button> + </nav> + + <div class="mainContainer"> + <div id="vpContent" class="contentContainer"> + <ul class="contentMenu"> + <li id="vpMainBtn" active onclick="showVpSection('main')">%%viper.menu.main%%</li> + <li id="vpReleaseBtn" onclick="showVpSection('release')">%%viper.menu.release%%</li> + <li id="vpInfoBtn" onclick="showVpSection('info')">%%viper.menu.info%%</li> + </ul> + <div class="contentBody"> + <div id="vpMain" class="section"> + <img src="icons/viper.png"/> + <div class="inline" style="margin-top: 20px;"> + <div id="vpversion"></div> | + <a id="setpath" href="#" onclick="setpath()">%%gui.setpath%%</a> + </div> + </div> + <div id="vpReleaseNotes" class="hidden section"></div> + <div id="vpInfo" class="hidden section"> + <h2>%%viper.menu.info.links%%</h2> + <ul> + <li>%%viper.info.discord%% <a href="https://northstar.tf/discord">northstar.tf/discord</a></li> + <li>%%viper.info.issues%% <a href="https://github.com/0neGal/viper/issues">github.com/0neGal/viper/issues</a></li> + </ul> + <h2>%%viper.menu.info.credits%%</h2> + <ul> + <li>"Titanfall|2 + Northstar" logo: <a href="https://www.steamgriddb.com/logo/47851">Aftonstjarma</a></li> + <li>Viper logo: Imply#9781</li> + </ul> </div> - </div> - <div class="buttons"> - <button id="exit" onclick="exit()">%%gui.exit%%</button> - <button id="updateBtn" onclick="update()">%%gui.update%%</button> - <button id="setpath" onclick="setpath()">%%gui.setpath%%</button> </div> </div> - <div class="line"> - <div class="text">%%gui.launch%%:</div> - <div class="buttons"> - <button id="vanilla" onclick="launchVanilla()">%%gui.launchvanilla%%</button> - <button id="northstar" onclick="launch()">%%gui.launchnorthstar%%</button> + + <div id="nsContent" class="contentContainer"> + <ul class="contentMenu"> + <li id="nsMainBtn" active onclick="showNsSection('main')">%%ns.menu.main%%</li> + <li id="nsModsBtn" onclick="showNsSection('mods')">%%ns.menu.mods%%</li> + <li id="nsReleaseBtn" onclick="showNsSection('release')">%%ns.menu.release%%</li> + </ul> + <div class="contentBody"> + <div id="nsMain" class="section"> + <div class="img"><img src="../assets/ns.png"></div> + <div class="playBtnContainer"> + <button id="playNsBtn" class="playBtn" onclick="launch()">%%gui.launch%%</button> + <div class="inline"> + <div id="nsversion"></div> + <a id="update" href="#" onclick="update()">(%%gui.update.check%%)</a> + </div> + </div> + </div> + <div id="nsMods" class="hidden section"> + <div id="modsdiv"> + </div> + <div class="line"> + <div class="text" id="modcount">%%gui.mods%%</div> + <div class="buttons modbtns"> + <button id="removemod" onclick="selected().remove()">%%gui.mods.remove%%</button> + <button id="removeall" onclick="selected(true).remove()">%%gui.mods.removeall%%</button> + <button id="togglemod" onclick="selected().toggle()">%%gui.mods.toggle%%</button> + <button id="toggleall" onclick="selected(true).toggle(true)">%%gui.mods.toggleall%%</button> + <button id="installmod" onclick="installmod()">%%gui.mods.install%%</button> + </div> + </div> + </div> + <div id="nsRelease" class="hidden section"></div> </div> </div> - <div id="modsdiv"> - </div> - <div class="line"> - <div class="text" id="modcount">%%gui.mods%%</div> - <div class="buttons modbtns"> - <button id="removemod" onclick="selected().remove()">%%gui.mods.remove%%</button> - <button id="removeall" onclick="selected(true).remove()">%%gui.mods.removeall%%</button> - <button id="togglemod" onclick="selected().toggle()">%%gui.mods.toggle%%</button> - <button id="toggleall" onclick="selected(true).toggle(true)">%%gui.mods.toggleall%%</button> - <button id="installmod" onclick="installmod()">%%gui.mods.install%%</button> + + <div id="tfContent" class="contentContainer"> + <ul class="contentMenu"><li style="opacity:0.0">filler</li></ul> + <div class="contentBody"> + <div class="section"> + <div class="img"><img src="../assets/vanilla.png"></div> + <div class="playBtnContainer"> + <button class="playBtn" onclick="launchVanilla()">%%gui.launch%%</button> + <div id="tf2Version"></div> + </div> + </div> </div> </div> </div> <script src="lang.js"></script> <script src="main.js"></script> + <script src="launcher.js"></script> </body> </html> diff --git a/src/app/launcher.js b/src/app/launcher.js new file mode 100644 index 0000000..9e09938 --- /dev/null +++ b/src/app/launcher.js @@ -0,0 +1,105 @@ +const markdown = require("markdown").markdown.toHTML; + +function page(page) { + let pages = document.querySelectorAll(".mainContainer .contentContainer") + let btns = document.querySelectorAll(".gamesContainer button") + + for (let i = 0; i < pages.length; i++) { + pages[i].classList.add("hidden"); + } + + for (let i = 0; i < btns.length; i++) { + btns[i].classList.add("inactive"); + } + + pages[page].classList.remove("hidden"); + btns[page].classList.remove("inactive"); + bgHolder.setAttribute("bg", page); +}; page(0) + + +ipcRenderer.on("vp-notes", (event, response) => { + let content = ""; + + for (const release of response) { + content += "# " + release.name + "\n\n" + + release.body.replaceAll("\r\n", "\n") + "\n\n\n"; + } + + vpReleaseNotes.innerHTML = markdown(content); +}); +async function loadVpReleases() { + ipcRenderer.send("get-vp-notes"); +}; loadVpReleases(); + + +ipcRenderer.on("ns-notes", (event, response) => { + let content = ""; + + for (let release of response) { + content += "# " + release.name + "\n\n" + + release.body.replaceAll("\r\n", "\nhtmlbreak") + "\n\n\n"; + } + + nsRelease.innerHTML = markdown(content).replaceAll("htmlbreak", "<br>"); +}); + +async function loadNsReleases() { + ipcRenderer.send("get-ns-notes"); +}; loadNsReleases(); + +// TODO: We gotta make this more automatic instead of switch statements +// it's both not pretty, but adding more sections requires way too much +// effort, compared to how it should be. +function showVpSection(section) { + if (!["main", "release", "info", "credits"].includes(section)) throw new Error("unknown vp section"); + vpMainBtn.removeAttribute("active"); + vpReleaseBtn.removeAttribute("active"); + vpInfoBtn.removeAttribute("active"); + + vpMain.classList.add("hidden"); + vpReleaseNotes.classList.add("hidden"); + vpInfo.classList.add("hidden"); + + switch(section) { + case "main": + vpMainBtn.setAttribute("active", ""); + vpMain.classList.remove("hidden"); + break; + case "release": + vpReleaseBtn.setAttribute("active", ""); + vpReleaseNotes.classList.remove("hidden"); + break; + case "info": + vpInfoBtn.setAttribute("active", ""); + vpInfo.classList.remove("hidden"); + break; + } +} + +function showNsSection(section) { + if (!["main", "release", "mods"].includes(section)) throw new Error("unknown ns section"); + nsMainBtn.removeAttribute("active"); + nsModsBtn.removeAttribute("active"); + nsReleaseBtn.removeAttribute("active"); + + nsMain.classList.add("hidden"); + nsMods.classList.add("hidden"); + nsRelease.classList.add("hidden"); + + switch(section) { + case "main": + nsMainBtn.setAttribute("active", ""); + nsMain.classList.remove("hidden"); + break; + case "mods": + nsModsBtn.setAttribute("active", ""); + nsMods.style.display = "block"; + nsMods.classList.remove("hidden"); + break; + case "release": + nsReleaseBtn.setAttribute("active", ""); + nsRelease.classList.remove("hidden"); + break; + } +} diff --git a/src/app/main.css b/src/app/main.css index 69b10ad..30f462e 100644 --- a/src/app/main.css +++ b/src/app/main.css @@ -1,116 +1,391 @@ :root { - --padding: 15px; - --disabled: #656E7F; - --foreground: #DDE2EB; - --background: #4C515B; - --boxbackground: #666E7F; - --subforeground: #AFAFAF; - --btnforeground: var(--foreground); - --red: #C7777F; --blue: #81A1C1; - --yellow: #ECD19A; + --orange: #D59783; + + --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); + } -@media (prefers-color-scheme: light) { - :root { - --background: #FFFFFF; - --foreground: #4C566A; - --boxbackground: #EEF0F4; - --btnforeground: var(--background); - } +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + border-radius: 10px; + background: transparent; +} + +::-webkit-scrollbar-thumb { + border-radius: 10px; + background: var(--red); } -@font-face { - font-family: "Roboto Mono"; - src: url("roboto.ttf"); +.playBtn, .gamesContainer button, #close { + cursor: pointer; } -::-webkit-scrollbar {display: none} +#close { + z-index: 1; + width: 25px; + opacity: 0.6; + height: 25px; + position: fixed; + top: var(--padding); + right: var(--padding); + background-size: contain; + transition: 0.25s ease-in-out; + background-image: url("icons/close.png"); +} -body, button, input { - font-size: 18px; - font-weight: 700; +#close:hover {opacity: 1.0} +#close:active {transform: scale(0.98)} + +body { + margin: 0; overflow: hidden; - -webkit-app-region: drag; - color: var(--foreground); - text-transform: uppercase; - background: var(--background); - font-family: "Roboto Mono", monospace; + user-select: none; + font-family: "Roboto", sans-serif; } -nobr {white-space: nowrap} +button {outline: none} +b, strong {font-weight: 700} +body, input, button {font-weight: 500} -.versions { - height: 15px; - font-size: 12px; - color: var(--subforeground); +button { + border: none; + color: white; + outline: none; + font-weight: 700; + padding: 5px 10px; + border-radius: 5px; + transition: 0.2s ease-in-out; } -.line { +button:hover {filter: brightness(110%)} +button:active {filter: brightness(90%)} + +img {pointer-events: none} + +#bgHolder { + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: none; + position: fixed; + transform: scale(1.1); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + transition: background-image 0.5s ease-in-out; + filter: brightness(0.4) blur(2px) grayscale(0.6); +} + +#bgHolder[bg="0"] {background-image: url("../assets/bg/viper.jpg")} +#bgHolder[bg="1"] {background-image: url("../assets/bg/northstar.jpg")} +#bgHolder[bg="2"] {background-image: url("../assets/bg/tf2.jpg")} + +.gamesContainer { + width: 10%; + height: 100%; + min-width: 95px; + max-width: 120px; + + float: left; display: flex; - margin-top: var(--padding); + flex-wrap: wrap; + align-content: center; } -#modsdiv { - padding: 1px; - height: 125px; - overflow-y: scroll; - border-radius: var(--padding); - background: var(--boxbackground); - margin: calc(var(--padding) / 3) var(--padding); +.mainContainer { + height: 100%; + flex-grow: 1; + display: flex; + position: relative; } -.mod { - margin: calc(var(--padding) / 3); - border-radius: calc(var(--padding) / 2) !important; + +/* nav bar buttons */ +.gamesContainer button { + background-size: 90%; + background-position: center; + background-repeat: no-repeat; + + border: none; + transition: 0.3s ease-in-out; + background-color: transparent; + + + margin: 20px; + position: relative; + box-sizing: border-box; + flex-basis: calc(100% - 10px); } -.mod.selected {background: var(--background)} +.gamesContainer button.inactive { + opacity: 0.5; + transform: scale(0.9); +} -.mod .disabled { - color: var(--red); - position: relative; - left: var(--padding); +.gamesContainer button::before { + content: ""; + display: block; + padding-top: 100%; } -.buttons { - text-align: right; - margin-left: auto; - user-select: none; - margin-right: calc(var(--padding) / 1.9); +.gamesContainer button .content { + width: 100%; + height: 100%; + top: 0; left: 0; + position: absolute; } -.text {max-width: 38vw} -.buttons {max-width: 55vw} +#vpBtn {background-image: url("icons/viper.png")} +#nsBtn {background-image: url("icons/northstar.png")} +#tfBtn { + background-image: url("icons/titanfall2.png"); + background-size: 69%; /* nice */ +} -button, .text, .mod { - border: none; - outline: none; - user-select: none; +.contentContainer { + width: 90%; + color: white; + flex-grow: 1; + opacity: 1.0; + margin-left: 5%; + position: absolute; + transition: 0.15s ease-in-out; +} + +.contentContainer.hidden { + opacity: 0.0; + pointer-events: none; +} + +.contentMenu { + padding: 0; + flex-grow: 1; + display: flex; + font-size: 20px; + list-style: none; + margin-bottom: 0; + align-items: center; + justify-content: center; + margin-top: var(--padding); +} + +/* some sections do not need space between them and menu */ +#nsMain, #nsRelease, #vpReleaseNotes, .playBtnContainer { + margin-top: 0 !important; +} + +.contentMenu li { + opacity: 0.6; + margin: 0 26px; + cursor: pointer; + font-weight: 700; + text-align: center; + height: fit-content; + transition: opacity 0.3s ease-in-out; +} + +.contentMenu li:last-child {margin-right: 0px} +.contentMenu li:first-child {margin-left: 0px} + +.contentMenu li:hover {opacity: 0.7} + +.contentMenu li[active] { + opacity: 1.0; + pointer-events: none; +} + +.contentMenu li::after { + top: 10px; + width: 30px; + height: 5px; + opacity: 0.0; + content: " "; + display: block; + text-align: center; + position: relative; border-radius: 50px; + background: var(--red); + left: calc(50% - 15px); transition: 0.2s ease-in-out; - padding: calc(var(--padding) / 3) var(--padding); } -#welcome {padding: 0px} +.contentMenu li[active]::after { + top: 5px; + opacity: 1.0; +} -button { - color: var(--btnforeground); - -webkit-app-region: no-drag; - margin-bottom: calc(var(--padding) / 1.5); +.section { + opacity: 1.0; + position: fixed; + right: calc(var(--padding) * 2); + left: calc(100px + var(--padding)); + transition: opacity 0.15s ease-in-out; } -button:hover {opacity: 0.9} -button:active { - opacity: 0.7; - transform: scale(0.95); +.section.hidden { + opacity: 0.0; + pointer-events: none; } +.contentBody img {max-width: 100%} +.contentBody .img {text-align: center} -#setpath {background: #5E81AC} -#vanilla, #exit {background: #656E7F} -#updateBtn, #installmod {background: var(--blue)} -#togglemod, #toggleall {background: var(--yellow)} +.contentBody .section > :first-child:not(.img) { + margin-top: 35px; +} + +.contentContainer .playBtnContainer { + text-align: center; +} + +.contentContainer .playBtn { + width: 27%; + height: 11%; + border: none; + color: white; + padding: 20px; + font-size: 24px; + font-weight: bold; + margin-top: 100px; + margin-bottom: 10px; + border-radius: 10px; + background: var(--redbg); + transition: 0.3s ease-in-out; + filter: drop-shadow(0px 8px 5px rgba(0, 0, 0, 0.1)); +} + +.contentContainer .playBtn:hover { + transform: scale(1.05); + filter: drop-shadow(0px 5px 15px rgba(0, 0, 0, 0.3)) brightness(110%); +} + +.contentContainer .playBtn:active { + opacity: 0.7;transform: scale(0.98); + filter: drop-shadow(0px 5px 10px rgba(0, 0, 0, 0.4)); +} + +.contentContainer #nsMain .playBtn { + background: var(--bluebg); +} + +a { + color: var(--red); + text-decoration: none; + transition: filter 0.2s ease-in; +} + +a:hover { + filter: brightness(80%); +} + +#nsContent .contentMenu { + margin-bottom: 0; +} + +.contentBody .img img { + transform: scale(0.85); +} + +.contentBody .img { + width: 100%; + text-align: center; +} + +#nsRelease, #vpReleaseNotes { + height: 80vh; + overflow-y: scroll; + flex-direction: column; + margin-top: 10px !important; +} + +.inline * { + display: inline-block; +} + +#vpMain { + margin-top: 140px; + text-align: center; +} + +#vpMain img { + width: 20%; +} + +#vpVersion { + font-size: 16px; +} + +.simplebar-scrollbar:before { + background: var(--red) !important; +} + +#installmod {background: var(--blue)} +#togglemod, #toggleall {background: var(--orange)} #northstar, #removeall, #removemod {background: var(--red)} -button:disabled {background: var(--disabled) !important; opacity: 0.5} +button:disabled { + opacity: 0.5; + pointer-events: none; +} + +code { + font-size: 16px; + padding: 2px 5px; + border-radius: 3px; + background-color: #00000070; +} + +#nsMods .line { + display: flex; + align-items: center; + margin-top: calc(var(--padding) / 2); +} + +#modsdiv { + height: 50vh; + border-radius: 5px; + background: var(--bg); + backdrop-filter: blur(15px); + padding: calc(var(--padding) / 4); +} + +#modsdiv .mod { + display: flex; + border-radius: 5px; + transition: 0.1s ease-in-out; + margin: calc(var(--padding) / 3); + padding: calc(var(--padding) / 3); +} + +#modsdiv .mod.selected { + background: var(--selbg); +} + +#modsdiv .mod .disabled, .modbtns { + margin-left: auto; +} + +.modbtns button { + margin-left: calc(var(--padding) / 3); +} + +/* drag control */ + +#bgHolder { + user-select: none; + -webkit-app-region: drag; +} + +a, button, .contentMenu, #close, #nsRelease, #vpReleaseNotes, .mod { + -webkit-app-region: no-drag; +} diff --git a/src/app/main.js b/src/app/main.js index c365cf4..893572a 100644 --- a/src/app/main.js +++ b/src/app/main.js @@ -1,6 +1,6 @@ const fs = require("fs"); const path = require("path"); -const { ipcRenderer } = require("electron"); +const { ipcRenderer, shell } = require("electron"); const lang = require("../lang"); let shouldInstallNorthstar = false; @@ -36,10 +36,9 @@ if (fs.existsSync("viper.json")) { function exit() {ipcRenderer.send("exit")} function update() {ipcRenderer.send("update")} -/** - * Reports to the main thread about game path status. - * @param {boolean} value is game path loaded - */ +// Reports to the main process about game path status. +// @param {boolean} value is game path loaded + function setpath(value = false) { ipcRenderer.send("setpath", value); } @@ -56,16 +55,26 @@ function launchVanilla() {ipcRenderer.send("launchVanilla")} function log(msg) { console.log(msg); - welcome.innerHTML = msg; + // welcome.innerHTML = msg; } function setButtons(state) { - let buttons = document.querySelectorAll("button"); + playNsBtn.disabled = !state; +} - for (let i = 0; i < buttons.length; i++) { - buttons[i].disabled = !state; +ipcRenderer.on("ns-update-event", (event, key) => { + document.getElementById("update").innerText = `(${lang(key)})`; + console.log(key); + switch(key) { + case "cli.update.uptodate.short": + setButtons(true); + playNsBtn.innerText = lang("gui.launch"); + break; + default: + setButtons(false); + break; } -} +}); let lastselected = ""; function select(entry) { @@ -100,7 +109,12 @@ function selected(all) { return { remove: () => { - if (selected == "allmods") { + + if (selected.match(/^Northstar\./)) { + if (! confirm(lang("gui.mods.required.confirm"))) { + return; + } + } else if (selected == "allmods") { if (! confirm(lang("gui.mods.removeall.confirm"))) { return; } @@ -109,6 +123,16 @@ function selected(all) { ipcRenderer.send("removemod", selected) }, toggle: () => { + if (selected.match(/^Northstar\./)) { + if (! confirm(lang("gui.mods.required.confirm"))) { + return; + } + } else if (selected == "allmods") { + if (! confirm(lang("gui.mods.toggleall.confirm"))) { + return; + } + } + ipcRenderer.send("togglemod", selected) } } @@ -118,13 +142,6 @@ function installmod() { ipcRenderer.send("installmod") } -ipcRenderer.on("ns-updated", () => { - setButtons(true); - northstar.disabled = false; - updateBtn.innerText = lang("gui.update"); -}) -ipcRenderer.on("ns-updating", () => {setButtons(false)}) - ipcRenderer.on("newpath", (event, newpath) => { settings.gamepath = newpath; }) @@ -153,8 +170,9 @@ ipcRenderer.on("mods", (event, mods) => { }) ipcRenderer.on("version", (event, versions) => { - vpversion.innerText = lang("gui.versions.viper") + ": " + versions.vp; - nsversion.innerText = lang("gui.versions.northstar") + ": " + versions.ns; + vpversion.innerText = versions.vp; + nsversion.innerText = versions.ns; + tf2Version.innerText = versions.tf2; if (versions.ns == "unknown") { let buttons = document.querySelectorAll(".modbtns button"); @@ -164,9 +182,8 @@ ipcRenderer.on("version", (event, versions) => { } // Since Northstar is not installed, we cannot launch it - northstar.disabled = true; shouldInstallNorthstar = true; - updateBtn.innerText = lang("gui.installnorthstar"); + playNsBtn.innerText = lang("gui.installnorthstar"); } }); ipcRenderer.send("getversion"); @@ -187,6 +204,10 @@ ipcRenderer.on("wrongpath", () => { }); setlang(); -setInterval(() => { - ipcRenderer.send("setsize", document.querySelector(".lines").offsetHeight + 20); -}, 150); + +document.body.addEventListener("click", event => { + if (event.target.tagName.toLowerCase() === "a" && event.target.protocol != "file:") { + event.preventDefault(); + shell.openExternal(event.target.href); + } +}); diff --git a/src/app/roboto.ttf b/src/app/roboto.ttf Binary files differdeleted file mode 100644 index 900fce6..0000000 --- a/src/app/roboto.ttf +++ /dev/null diff --git a/src/assets/bg/northstar.jpg b/src/assets/bg/northstar.jpg Binary files differnew file mode 100644 index 0000000..01e7e55 --- /dev/null +++ b/src/assets/bg/northstar.jpg diff --git a/src/assets/bg/tf2.jpg b/src/assets/bg/tf2.jpg Binary files differnew file mode 100644 index 0000000..b6e8f2f --- /dev/null +++ b/src/assets/bg/tf2.jpg diff --git a/src/assets/bg/viper.jpg b/src/assets/bg/viper.jpg Binary files differnew file mode 100644 index 0000000..8b1d5ad --- /dev/null +++ b/src/assets/bg/viper.jpg diff --git a/src/assets/ns.png b/src/assets/ns.png Binary files differnew file mode 100644 index 0000000..a3bbf94 --- /dev/null +++ b/src/assets/ns.png diff --git a/src/assets/vanilla.png b/src/assets/vanilla.png Binary files differnew file mode 100644 index 0000000..a6ed688 --- /dev/null +++ b/src/assets/vanilla.png diff --git a/src/index.js b/src/index.js index 1b594ad..333b1c9 100644 --- a/src/index.js +++ b/src/index.js @@ -1,23 +1,24 @@ const fs = require("fs"); const path = require("path"); const { autoUpdater } = require("electron-updater"); -const { app, ipcMain, BrowserWindow } = require("electron"); +const { app, ipcMain, BrowserWindow, dialog } = require("electron"); const Emitter = require("events"); const events = new Emitter(); const utils = require("./utils"); const cli = require("./cli"); +const requests = require("./requests"); function start() { - let width = 600; win = new BrowserWindow({ - width: width, - height: 115, + width: 1000, + height: 600, show: false, title: "Viper", resizable: false, titleBarStyle: "hidden", + frame: false, icon: path.join(__dirname, "assets/icons/512x512.png"), webPreferences: { nodeIntegration: true, @@ -31,17 +32,12 @@ function start() { win.loadFile(__dirname + "/app/index.html"); ipcMain.on("exit", () => {process.exit(0)}) - ipcMain.on("setsize", (event, height) => { - win.setSize(width, height); - }) - - ipcMain.on("ns-updated", () => {win.webContents.send("ns-updated")}) - ipcMain.on("ns-updating", () => {win.webContents.send("ns-updating")}) - ipcMain.on("winLog", (event, ...args) => {win.webContents.send("log", ...args)}) - ipcMain.on("winAlert", (event, ...args) => {win.webContents.send("alert", ...args)}) - ipcMain.on("guigetmods", (event, ...args) => {win.webContents.send("mods", utils.mods.list())}) + ipcMain.on("winLog", (event, ...args) => {win.webContents.send("log", ...args)}); + ipcMain.on("winAlert", (event, ...args) => {win.webContents.send("alert", ...args)}); + ipcMain.on("ns-update-event", (event) => win.webContents.send("ns-update-event", event)); + ipcMain.on("guigetmods", (event, ...args) => {win.webContents.send("mods", utils.mods.list())}); - win.webContents.once("dom-ready", () => { + win.webContents.on("dom-ready", () => { win.webContents.send("mods", utils.mods.list()); }); @@ -99,6 +95,7 @@ ipcMain.on("newpath", (event, newpath) => { function _sendVersionsInfo() { win.webContents.send("version", { ns: utils.getNSVersion(), + tf2: utils.getTF2Version(), vp: "v" + require("../package.json").version }); } @@ -149,3 +146,10 @@ if (cli.hasArgs()) { start(); }) } + +ipcMain.on("get-ns-notes", async () => { + win.webContents.send("ns-notes", await requests.getNsReleaseNotes()); +}); +ipcMain.on("get-vp-notes", async () => { + win.webContents.send("vp-notes", await requests.getVpReleaseNotes()); +}); diff --git a/src/lang/en.json b/src/lang/en.json index bb5cf09..c2b6f98 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -13,11 +13,12 @@ "cli.setpath.noarg": "No argument provided for --setpath", "cli.update.current": "Current version:", - "cli.update.downloading": "Downloading", + "cli.update.downloading": "Downloading...", "cli.update.checking": "Checking for updates...", "cli.update.downloaddone": "Download done! Extracting...", "cli.update.finished": "Installation/Update finished!", "cli.update.uptodate": "Latest version (%s) is already installed, skipping update.", + "cli.update.uptodate.short": "Up-to-date", "cli.autoupdates.checking": "Checking for Northstar updates...", "cli.autoupdates.available": "Northstar update available!", @@ -43,6 +44,7 @@ "gui.update": "Update", "gui.setpath": "Game Path", + "gui.update.check": "Check for updates", "gui.mods": "Mods", "gui.mods.count": "Mods Installed:", "gui.mods.disabledtag": "Disabled", @@ -52,7 +54,9 @@ "gui.mods.remove": "Remove Mod", "gui.mods.removeall": "Remove All", "gui.mods.nothingselected": "You've not selected a mod.", - "gui.mods.removeall.confirm": "Removing all mods will usually require you to reinstall Northstar, are you sure?", + "gui.mods.toggleall.confirm": "Toggling all mods could disable mods required for Northstar to function. Are you sure?", + "gui.mods.removeall.confirm": "Removing all mods will usually require you to reinstall Northstar. Are you sure?", + "gui.mods.required.confirm": "You've selected a core mod, Northstar may not function without it. Are you sure?", "gui.mods.notamod": "Not a mod!", "gui.mods.extracting": "Extracting mod...", "gui.mods.installing": "Installing mod...", @@ -74,13 +78,25 @@ "gui.selectpath": "Please select the path!", "gui.gamepath.must": "The game path must be set to start Viper.", - "gui.gamepath.wrong": "This folder is not a valid game path.", + "gui.gamepath.wrong": "This folder is not a valid game path.", + "viper.menu.main": "Viper", + "viper.menu.release": "Release Notes", + "viper.menu.info": "Extras", + "viper.menu.info.links": "Links", + "viper.menu.info.credits": "Credits", + + "viper.info.discord": "Join Discord:", + "viper.info.issues": "Report issues with Viper:", + + "ns.menu.main": "Northstar Launcher", + "ns.menu.mods": "Mods", + "ns.menu.release": "Release Notes", - "general.launching": "Launching", "general.mods.enabled": "Enabled mods:", "general.mods.disabled": "Disabled mods:", "general.mods.installed": "Installed mods:", "general.missingpath": "Game path is not set!", - "general.notinstalled": "Northstar is not installed!" + "general.notinstalled": "Northstar is not installed!", + "general.launching": "Launching" } diff --git a/src/lang/fr.json b/src/lang/fr.json index 0eb083c..59a3090 100644 --- a/src/lang/fr.json +++ b/src/lang/fr.json @@ -13,11 +13,12 @@ "cli.setpath.noarg": "Aucun argument donné à --setpath", "cli.update.current": "Version actuelle :", - "cli.update.downloading": "Téléchargement en cours ", - "cli.update.checking": "Vérification des mises à jour ...", + "cli.update.downloading": "Téléchargement en cours...", + "cli.update.checking": "Vérification des mises à jour...", "cli.update.downloaddone": "Téléchargement terminé ! Extraction des fichiers...", "cli.update.finished": "Mise à jour terminée !", "cli.update.uptodate": "La dernière version (%s) est déjà installée.", + "cli.update.uptodate.short": "Votre client est à jour", "cli.autoupdates.checking": "Vérifications des mises à jour de Northstar...", "cli.autoupdates.available": "Une mise à jour de Northstar est disponible !", @@ -43,16 +44,19 @@ "gui.update": "Mise à jour", "gui.setpath": "Chemin du jeu", + "gui.update.check": "Vérifier les mises à jour", "gui.mods": "Mods", "gui.mods.count": "Mods installés :", - "gui.mods.disabledtag": "Désactivés", + "gui.mods.disabledtag": "Désactivé", "gui.mods.install": "Installer le mod", "gui.mods.toggle": "Activer/désactiver le mod", "gui.mods.toggleall": "Activer/désactiver tous les mods", "gui.mods.remove": "Supprimer le mod", "gui.mods.removeall": "Tout supprimer", "gui.mods.nothingselected": "Aucun mod n'est sélectionné.", + "gui.mods.toggleall.confirm": "Cette action pourrait désactiver des mods nécessaires au bon fonctionnement de Northstar. Souhaitez-vous faire cela ?", "gui.mods.removeall.confirm": "Supprimer tous les mods vous forcera à réinstaller Northstar, souhaitez-vous faire cela ?", + "gui.mods.required.confirm": "Vous avez sélectionné un mod de base, Northstar peut ne pas fonctionner sans celui-ci. Souhaitez-vous faire cela ?", "gui.mods.notamod": "Ceci n'est pas un mod !", "gui.mods.extracting": "Extraction du mod...", "gui.mods.installing": "Installation du mod...", @@ -74,13 +78,25 @@ "gui.selectpath": "Veuillez sélectionner le dossier où se trouve le client Titanfall 2.", "gui.gamepath.must": "Vous devez sélectionner le chemin du dossier du jeu Titanfall 2 pour pouvoir lancer Viper.", - "gui.gamepath.wrong": "Ce dossier ne contient pas le jeu Titanfall 2, et n'est donc pas valide.", + "gui.gamepath.wrong": "Ce dossier ne contient pas le jeu Titanfall 2, et n'est donc pas valide.", + "viper.menu.main": "Viper", + "viper.menu.release": "Notes de mises à jour", + "viper.menu.info": "Informations", + "viper.menu.info.links": "Liens utiles", + "viper.menu.info.credits": "Remerciements", + + "viper.info.discord": "Rejoingnez le serveur Discord :", + "viper.info.issues": "Un problème avec Viper ? Créez un ticket ici :", + + "ns.menu.main": "Lanceur Northstar", + "ns.menu.mods": "Mods", + "ns.menu.release": "Notes de mises à jour", - "general.launching": "Lancement", "general.mods.enabled": "Mods activés :", "general.mods.disabled": "Mods désactivés :", "general.mods.installed": "Mods installés :", "general.missingpath": "Le chemin du client n'est pas défini !", - "general.notinstalled": "Northstar n'est pas installé !" + "general.notinstalled": "Northstar n'est pas installé !", + "general.launching": "Lancement" } diff --git a/src/requests.js b/src/requests.js index 06c5577..5452b0d 100644 --- a/src/requests.js +++ b/src/requests.js @@ -7,6 +7,8 @@ const { https } = require("follow-redirects"); // all requests results are stored in this file const cachePath = path.join(app.getPath("cache"), "requests.json"); const NORTHSTAR_LATEST_RELEASE_KEY = "nsLatestRelease"; +const NORTHSTAR_RELEASE_NOTES_KEY = "nsReleaseNotes"; +const VIPER_RELEASE_NOTES_KEY = "vpReleaseNotes"; function _saveCache(data) { @@ -30,7 +32,6 @@ async function getLatestNsVersion() { let cache = _getRequestsCache(); if (cache[NORTHSTAR_LATEST_RELEASE_KEY] && (Date.now() - cache[NORTHSTAR_LATEST_RELEASE_KEY]["time"]) < 5 * 60 * 1000) { - console.log(`returning ${NORTHSTAR_LATEST_RELEASE_KEY} data from cache`); resolve( cache[NORTHSTAR_LATEST_RELEASE_KEY]["body"]["tag_name"] ); } else { https.get({ @@ -70,8 +71,81 @@ function getLatestNsVersionLink() { return cache[NORTHSTAR_LATEST_RELEASE_KEY]["body"].assets[0].browser_download_url; } +async function getNsReleaseNotes() { + return new Promise(resolve => { + let cache = _getRequestsCache(); + + if (cache[NORTHSTAR_RELEASE_NOTES_KEY] && (Date.now() - cache[NORTHSTAR_RELEASE_NOTES_KEY]["time"]) < 5 * 60 * 1000) { + resolve( cache[NORTHSTAR_RELEASE_NOTES_KEY]["body"] ); + } else { + https.get({ + host: "api.github.com", + port: 443, + path: "/repos/R2Northstar/Northstar/releases", + method: "GET", + headers: { "User-Agent": "viper" } + }, + + response => { + response.setEncoding("utf8"); + let responseData = ""; + + response.on("data", data => { + responseData += data; + }); + + response.on("end", _ => { + cache[NORTHSTAR_RELEASE_NOTES_KEY] = { + "time": Date.now(), + "body": JSON.parse(responseData) + }; + _saveCache(cache); + resolve( cache[NORTHSTAR_RELEASE_NOTES_KEY]["body"] ); + }); + }); + } + }); +} + +async function getVpReleaseNotes() { + return new Promise(resolve => { + let cache = _getRequestsCache(); + + if (cache[VIPER_RELEASE_NOTES_KEY] && (Date.now() - cache[VIPER_RELEASE_NOTES_KEY]["time"]) < 5 * 60 * 1000) { + resolve( cache[VIPER_RELEASE_NOTES_KEY]["body"] ); + } else { + https.get({ + host: "api.github.com", + port: 443, + path: "/repos/0negal/viper/releases", + method: "GET", + headers: { "User-Agent": "viper" } + }, + + response => { + response.setEncoding("utf8"); + let responseData = ""; + + response.on("data", data => { + responseData += data; + }); + + response.on("end", _ => { + cache[VIPER_RELEASE_NOTES_KEY] = { + "time": Date.now(), + "body": JSON.parse(responseData) + }; + _saveCache(cache); + resolve( cache[VIPER_RELEASE_NOTES_KEY]["body"] ); + }); + }); + } + }); +} module.exports = { getLatestNsVersion, - getLatestNsVersionLink + getLatestNsVersionLink, + getNsReleaseNotes, + getVpReleaseNotes }; diff --git a/src/utils.js b/src/utils.js index 87499ae..17091b4 100644 --- a/src/utils.js +++ b/src/utils.js @@ -136,6 +136,21 @@ function getNSVersion() { } } + +/** + * Loads up Titanfall|2 version from gameversion.txt file. + * TODO This file is present on Origin install, should check if it's present with + * Steam install as well. + */ +function getTF2Version() { + var versionFilePath = path.join(settings.gamepath, "gameversion.txt"); + if (fs.existsSync(versionFilePath)) { + return fs.readFileSync(versionFilePath, "utf8"); + } else { + return "unknown"; + } +} + async function update() { for (let i = 0; i < settings.excludes.length; i++) { let exclude = path.join(settings.gamepath + "/" + settings.excludes[i]); @@ -144,14 +159,14 @@ async function update() { } } - ipcMain.emit("ns-updating"); + ipcMain.emit("ns-update-event", "cli.update.checking"); console.log(lang("cli.update.checking")); var version = getNSVersion(); const latestAvailableVersion = await requests.getLatestNsVersion(); if (version === latestAvailableVersion) { - ipcMain.emit("ns-updated"); + ipcMain.emit("ns-update-event", "cli.update.uptodate.short"); console.log(lang("cli.update.uptodate"), version); winLog(lang("gui.update.uptodate")); @@ -159,9 +174,9 @@ async function update() { } else { if (version != "unknown") { console.log(lang("cli.update.current"), version); - }; console.log(lang("cli.update.downloading") + ":", latestAvailableVersion); - - winLog(lang("gui.update.downloading")); + }; + console.log(lang("cli.update.downloading") + ":", latestAvailableVersion); + ipcMain.emit("ns-update-event", "cli.update.downloading"); } https.get(requests.getLatestNsVersionLink(), (res) => { @@ -171,17 +186,18 @@ async function update() { let received = 0; res.on("data", (chunk) => { received += chunk.length; - winLog(lang("gui.update.downloading") + " " + (received / 1024 / 1024).toFixed(1) + "mb"); + ipcMain.emit("ns-update-event", lang("gui.update.downloading") + " " + (received / 1024 / 1024).toFixed(1) + "mb"); }) stream.on("finish", () => { stream.close(); winLog(lang("gui.update.extracting")); + ipcMain.emit("ns-update-event", "gui.update.extracting"); console.log(lang("cli.update.downloaddone")); fs.createReadStream(settings.zip).pipe(unzip.Extract({path: settings.gamepath})) .on("finish", () => { - fs.writeFileSync(path.join(settings.gamepath, "ns_version.txt"), latestAvailableVersion); - ipcMain.emit("getversion"); + fs.writeFileSync(path.join(settings.gamepath, "ns_version.txt"), latestAvailableVersion); + ipcMain.emit("getversion"); for (let i = 0; i < settings.excludes.length; i++) { let exclude = path.join(settings.gamepath + "/" + settings.excludes[i]); @@ -190,11 +206,11 @@ async function update() { } } - ipcMain.emit("guigetmods"); - ipcMain.emit("ns-updated"); - winLog(lang("gui.update.finished")); - console.log(lang("cli.update.finished")); - cli.exit(); + ipcMain.emit("guigetmods"); + ipcMain.emit("ns-update-event", "cli.update.uptodate.short"); + winLog(lang("gui.update.finished")); + console.log(lang("cli.update.finished")); + cli.exit(); }) }) }) @@ -487,6 +503,7 @@ module.exports = { updatevp, settings, getNSVersion, + getTF2Version, isGameRunning, setlang: (lang) => { settings.lang = lang; |