aboutsummaryrefslogtreecommitdiff
path: root/src/app
diff options
context:
space:
mode:
author0neGal <mail@0negal.com>2024-01-24 19:17:10 +0100
committer0neGal <mail@0negal.com>2024-01-24 19:43:07 +0100
commit6de175f28f3cc818333db10fe164ec9a8b24e8d5 (patch)
tree428c82955832c6cc9586289535593b1c0c456e21 /src/app
parent7c2e3977a45a372ce4ebd08faf2a8c6a82cebec0 (diff)
downloadViper-6de175f28f3cc818333db10fe164ec9a8b24e8d5.tar.gz
Viper-6de175f28f3cc818333db10fe164ec9a8b24e8d5.zip
added search in settings popup
Diffstat (limited to 'src/app')
-rw-r--r--src/app/css/grid.css8
-rw-r--r--src/app/index.html4
-rw-r--r--src/app/js/browser.js8
-rw-r--r--src/app/js/settings.js210
-rw-r--r--src/app/main.js1
5 files changed, 220 insertions, 11 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");