diff options
-rw-r--r-- | src/app/css/grid.css | 8 | ||||
-rw-r--r-- | src/app/index.html | 4 | ||||
-rw-r--r-- | src/app/js/browser.js | 8 | ||||
-rw-r--r-- | src/app/js/settings.js | 210 | ||||
-rw-r--r-- | src/app/main.js | 1 | ||||
-rw-r--r-- | src/lang/de.json | 2 | ||||
-rw-r--r-- | src/lang/en.json | 2 | ||||
-rw-r--r-- | src/lang/es.json | 2 | ||||
-rw-r--r-- | src/lang/fr.json | 2 | ||||
-rw-r--r-- | src/lang/zh.json | 2 |
10 files changed, 225 insertions, 16 deletions
diff --git a/src/app/css/grid.css b/src/app/css/grid.css index 2533fea..6cd2232 100644 --- a/src/app/css/grid.css +++ b/src/app/css/grid.css @@ -22,7 +22,7 @@ animation-name: none; } -.grid .el, .popup #search, +.grid .el, .popup .search, .popup #close, .popup .misc button, .option .actions select, .option .actions input { color: white; @@ -36,7 +36,7 @@ width: calc(50% - var(--spacing) * 4); } -.popup .misc, .popup #search, .option .actions input { +.popup .misc, .popup .search, .option .actions input { --height: var(--mischeight); } @@ -53,7 +53,7 @@ position: fixed; } -.popup #search, +.popup .search, .option .actions input, .option .actions select { border: none; @@ -62,7 +62,7 @@ width: calc(100% - var(--spacing) * 2); } -.popup #search:focus, +.popup .search:focus, .option .actions input:focus, .option .actions button:active { filter: brightness(1.5); diff --git a/src/app/index.html b/src/app/index.html index d3de578..cb2d63b 100644 --- a/src/app/index.html +++ b/src/app/index.html @@ -33,7 +33,7 @@ <div id="overlay" onclick="popups.set_all(false)"></div> <div class="popup" id="options"> <div class="misc"> - <div style="width:100%"></div> + <input class="search" placeholder="%%gui.search%%"> <button id="apply" onclick="Settings.toggle(false);Settings.apply()"> <img src="icons/apply.png"> %%gui.settings.save%% @@ -204,7 +204,7 @@ </div> <div class="misc"> - <input id="search" placeholder="%%gui.browser.search%%"> + <input class="search" placeholder="%%gui.search%%"> <button id="filter" onclick="Browser.filters.toggle()"> <img src="icons/filter.png"> </button> diff --git a/src/app/js/browser.js b/src/app/js/browser.js index d6034eb..80d3f04 100644 --- a/src/app/js/browser.js +++ b/src/app/js/browser.js @@ -1,5 +1,4 @@ -const Fuse = require("fuse.js"); -var fuse; +var browser_fuse; var packages = []; var packagecount = 0; @@ -184,7 +183,7 @@ var Browser = { Browser.add_pkg_properties(); - fuse = new Fuse(packages, { + browser_fuse = new Fuse(packages, { keys: ["full_name"] }) } @@ -241,7 +240,7 @@ var Browser = { }, search: (string) => { Browser.loading(); - let res = fuse.search(string); + let res = browser_fuse.search(string); if (res.length < 1) { Browser.loading(lang("gui.browser.no_results")); @@ -551,6 +550,7 @@ function normalize(items) { let searchtimeout; let searchstr = ""; +let search = document.querySelector("#browser .search"); search.addEventListener("keyup", () => { Browser.filters.toggle(false); clearTimeout(searchtimeout); diff --git a/src/app/js/settings.js b/src/app/js/settings.js index 57d542a..2d68c13 100644 --- a/src/app/js/settings.js +++ b/src/app/js/settings.js @@ -1,3 +1,5 @@ +var settings_fuse; + var Settings = { toggle: (state) => { Settings.load(); @@ -95,9 +97,24 @@ var Settings = { } } + // create Fuse based on options from `get_search_arr()` + settings_fuse = new Fuse(get_search_arr(), { + keys: ["text"], + threshold: 0.4, + ignoreLocation: true + }) + + // reset search + Settings.search(); + search_el.value = ""; + ipcRenderer.send("can-autoupdate"); ipcRenderer.on("cant-autoupdate", () => { - document.querySelector(".option[name=autoupdate]").style.display = "none"; + document.querySelector(".option[name=autoupdate]") + .style.display = "none"; + + document.querySelector(".option[name=autoupdate]") + .setAttribute("perma-hidden", true); }) }, switch: (el, state) => { @@ -110,7 +127,198 @@ var Settings = { if (el.classList.contains("switch") && el.tagName == "BUTTON") { el.classList.toggle("on"); } + }, + + // searches for `query` in the list of options, hides the options + // that dont match, and shows the one that do, if `query` is falsy, + // it'll simply reset everything back to being visible + search: (query = "") => { + // get list of elements that can be hidden + let search_els = [ + ...document.querySelectorAll(".options .title"), + ...document.querySelectorAll(".options .option"), + ...document.querySelectorAll(".options .buttons"), + ...document.querySelectorAll(".options .details"), + ] + + // this sets the visibility of all elements found in + // `search_els` unless the element has the `perma-hidden` + // attribute set + let set_all = (state) => { + // set `state` to the CSS equivalent + if (state) { + state = null; + } else { + state = "none"; + } + + // run through elements + for (let i = 0; i < search_els.length; i++) { + // check that the element shouldn't be perma hidden, and + // if so, hide it correctly. + if (search_els[i].hasAttribute("perma-hidden")) { + search_els[i].style.display = "none"; + continue; + } + + // set the visibility + search_els[i].style.display = state; + } + } + + // check if `query` is empty, and reset search if so + if (! query || ! query.trim()) { + set_all(true); + } else { + // hide everything + set_all(false); + } + + // unhides `el` and relevant elements related to it + let unhide = (el) => { + // list of elements that could be relevant through `el`'s + // `.closest()` function + let closest = [ + ".option", + "details", + ".buttons", + ] + + // run through `closest` + for (let i = 0; i < closest.length; i++) { + // shorthand + let closest_el = el.closest(closest[i]); + + // was a relevant element found? + if (closest_el) { + // is it supposed to always be hidden? do nothing + if (el.hasAttribute("perma-hidden") + || closest_el.hasAttribute("perma-hidden")) { + + break; + } + + // reset visibility + closest_el.style.display = null; + + // are we at a `<details>`? + if (closest[i] == "details") { + // attempt to get a `.title` inside that + // `<details>` element + let title = closest_el.querySelector(".title"); + + // did we find a title? + if (title) { + // reset visibility of title and also reset + // open state of `<details>` + title.style.display = null; + closest_el.setAttribute("open", false); + } + } + } + } + } + + // do a Fuse.js search with `query` + let res = settings_fuse.search(query); + + // if nothing was found, reset all + if (res.length == 0) { + return set_all(true); + } + + // run through results and unhide all of them + for (let i = 0; i < res.length; i++) { + unhide(res[i].item.el); + } + } +} + +// search on key events in search input +let search_el = document.body.querySelector("#options .search"); +search_el.addEventListener("keyup", () => { + Settings.search(search_el.value); +}) + +// returns a Fuse.js compatible Array for searching through the settings +function get_search_arr() { + // list of elements that should be taken into consideration when + // trying to do a search + let searchables_queries = [ + ".option .text", + ".buttons .text", + ".option .actions input", + ".option .actions select", + ".buttons .actions button:not(.switch)", + ] + + let searchables_els = []; + + // run through queries + for (let i = 0; i < searchables_queries.length; i++) { + // attempt to get element(s) with that query + let query = document.querySelectorAll( + ".options " + searchables_queries[i] + ) + + // if something was found add it + searchables_els = [ + ...query, + ...searchables_els + ] } + + let searchables = []; + + // run through the found elements + for (let i = 0; i < searchables_els.length; i++) { + let el = searchables_els[i]; + switch(el.tagName.toLowerCase()) { + // is this an `<input>`? + case "input": + // if no value is in the input, do nothing + if (! el.value) { + continue; + } + + // add to list of searchable elements, using the value + // of the input as the text + searchables.push({ + el: el, + text: el.value + }) + break; + + // is this a `<select>`? + case "select": + // get options in `<select>` + let options = el.children; + + // run through options + for (let ii = 0; ii < options.length; ii++) { + // add to list of searchable elements, using the + // insides of the option as the text, and the + // element being the `<select>` and not the + // `<option>`! + searchables.push({ + el: el, + text: options[ii].innerText + }) + } + break; + + default: + // add to list of searchable elements using the insides + // of the element as the text + searchables.push({ + el: el, + text: el.innerText + }) + } + } + + // return the actual searchable elements and text + return searchables; } events.on("popup-changed", () => { diff --git a/src/app/main.js b/src/app/main.js index 98a5fda..ad06fcf 100644 --- a/src/app/main.js +++ b/src/app/main.js @@ -1,5 +1,6 @@ const fs = require("fs"); const path = require("path"); +const Fuse = require("fuse.js"); const { app, ipcRenderer, shell } = require("electron"); const json = require("../modules/json"); diff --git a/src/lang/de.json b/src/lang/de.json index d677de3..21292dd 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -62,6 +62,7 @@ "gui": { "exit": "Schließen", + "search": "Suchen...", "welcome": "Willkommen zu Viper!", "setpath": "Installationspfad aktualisieren.", @@ -111,7 +112,6 @@ "info": "Info", "view": "Anschauen", "made_by": "von", - "search": "Suchen...", "update": "Aktualisieren", "install": "Installieren", "reinstall": "Neuinstallieren", diff --git a/src/lang/en.json b/src/lang/en.json index bcfb372..2bf2b0e 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -61,6 +61,7 @@ }, "gui": { "exit": "Exit", + "search": "Search...", "welcome": "Welcome to Viper!", "setpath": "Change Game Path", @@ -111,7 +112,6 @@ "info": "Info", "view": "View", "made_by": "by", - "search": "Search...", "update": "Update", "install": "Install", "reinstall": "Re-Install", diff --git a/src/lang/es.json b/src/lang/es.json index 9db77b3..c453926 100644 --- a/src/lang/es.json +++ b/src/lang/es.json @@ -62,6 +62,7 @@ "gui": { "exit": "Salir", + "search": "Buscar...", "welcome": "Bienvenido a Viper!", "setpath": "Cambiar la ruta del juego", @@ -111,7 +112,6 @@ "info": "Información", "view": "Ver", "made_by": "hecho por", - "search": "Buscar...", "update": "Actualizar", "install": "Instalar", "reinstall": "Re-Instalar", diff --git a/src/lang/fr.json b/src/lang/fr.json index fe5a715..caa785f 100644 --- a/src/lang/fr.json +++ b/src/lang/fr.json @@ -62,6 +62,7 @@ "gui": { "exit": "Fermer", + "search": "Rechercher", "welcome": "Bienvenue sur Viper !", "setpath": "Mettre à jour le chemin du jeu", @@ -111,7 +112,6 @@ "info": "Info", "view": "Voir", "made_by": "par", - "search": "Rechercher", "update": "Mise à jour", "install": "Installer", "reinstall": "Réinstaller", diff --git a/src/lang/zh.json b/src/lang/zh.json index 2eda09b..7d53b44 100644 --- a/src/lang/zh.json +++ b/src/lang/zh.json @@ -61,6 +61,7 @@ }, "gui": { "exit": "退出", + "search": "搜索...", "welcome": "欢迎来到Viper!", "setpath": "更换游戏目录", @@ -110,7 +111,6 @@ "info": "详情", "view": "查看", "made_by": "来自", - "search": "搜索...", "update": "更新", "install": "安装", "reinstall": "重新安装", |