aboutsummaryrefslogtreecommitdiff
path: root/src/app/browser.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/browser.js')
-rw-r--r--src/app/browser.js259
1 files changed, 220 insertions, 39 deletions
diff --git a/src/app/browser.js b/src/app/browser.js
index 40670bc..db68d31 100644
--- a/src/app/browser.js
+++ b/src/app/browser.js
@@ -2,9 +2,24 @@ const Fuse = require("fuse.js");
var fuse;
var packages = [];
+var packagecount = 0;
+
var Browser = {
maxentries: 50,
filters: {
+ getpkgs: () => {
+ let pkgs = [];
+ let other = [];
+ for (let i in packages) {
+ if (! Browser.filters.isfiltered(packages[i].categories)) {
+ pkgs.push(packages[i]);
+ } else {
+ other.push(packages[i]);
+ }
+ }
+
+ return pkgs;
+ },
get: () => {
let filtered = [];
let unfiltered = [];
@@ -27,6 +42,19 @@ var Browser = {
let filtered = Browser.filters.get().filtered;
let unfiltered = Browser.filters.get().unfiltered;
let state = false;
+
+ let filters = [
+ "Mods", "Skins",
+ "Client-side", "Server-side",
+ ];
+
+ let newcategories = [];
+ for (let i = 0; i < categories.length; i++) {
+ if (filters.includes(categories[i])) {
+ newcategories.push(categories[i]);
+ }
+ }; categories = newcategories;
+
if (categories.length == 0) {return true}
for (let i = 0; i < categories.length; i++) {
if (filtered.includes(categories[i])) {
@@ -53,14 +81,14 @@ var Browser = {
let spacing = parseInt(getComputedStyle(filters).getPropertyValue("--spacing"));
filters.style.top = filterRect.bottom - spacing;
- filters.style.right = filterRect.right - filterRect.left + filterRect.width;
+ filters.style.right = filterRect.right - filterRect.left + filterRect.width - (spacing / 2);
},
},
toggle: (state) => {
if (state) {
browser.scrollTo(0, 0);
- overlay.classList.add("shown")
- browser.classList.add("shown")
+ overlay.classList.add("shown");
+ browser.classList.add("shown");
if (browserEntries.querySelectorAll(".el").length == 0) {
Browser.loadfront();
@@ -69,18 +97,21 @@ var Browser = {
} else if (! state) {
if (state != undefined) {
Browser.filters.toggle(false);
- overlay.classList.remove("shown")
- browser.classList.remove("shown")
+ overlay.classList.remove("shown");
+ browser.classList.remove("shown");
+ preview.classList.remove("shown");
return
}
}
browser.scrollTo(0, 0);
- overlay.classList.toggle("shown")
- browser.classList.toggle("shown")
+ overlay.classList.toggle("shown");
+ browser.classList.toggle("shown");
},
loadfront: async () => {
Browser.loading();
+
+ packagecount = 0;
if (packages.length < 1) {
packages = await (await fetch("https://northstar.thunderstore.io/api/v1/package/")).json();
@@ -90,8 +121,15 @@ var Browser = {
})
}
- for (let i in packages) {
- new BrowserElFromObj(packages[i]);
+ let pkgs = Browser.filters.getpkgs();
+ for (let i in pkgs) {
+ if (packagecount >= Browser.maxentries) {
+ Browser.endoflist();
+ break
+ }
+
+ new BrowserElFromObj(pkgs[i]);
+ packagecount++;
}
},
loading: (string) => {
@@ -107,21 +145,53 @@ var Browser = {
browserEntries.innerHTML = `<div class="loading">${lang('gui.browser.loading')}</div>`;
}
},
- endoflist: () => {
- if (browserEntries.querySelector(".message")) {return}
- browserEntries.innerHTML += `<div class="message">${lang('gui.browser.endoflist')}</div>`
+ endoflist: (isEnd) => {
+ let pkgs = [];
+ let filtered = Browser.filters.getpkgs();
+ for (let i = 0; i < filtered.length; i++) {
+ if ([packagecount + i]) {
+ pkgs.push(filtered[packagecount + i]);
+ } else {
+ break
+ }
+ }
+
+ if (browserEntries.querySelector(".message")) {
+ browserEntries.querySelector(".message").remove();
+ }
+
+ if (pkgs.length == 0 || isEnd) {
+ Browser.msg(`${lang('gui.browser.endoflist')}`);
+ return
+ }
+
+ Browser.msg(`<button id="loadmore">${lang("gui.browser.loadmore")}</button>`);
+ loadmore.addEventListener("click", () => {
+ Browser.loadpkgs(pkgs);
+ Browser.endoflist(pkgs);
+ })
},
search: (string) => {
Browser.loading();
let res = fuse.search(string);
if (res.length < 1) {
- Browser.loading(lang("gui.browser.noresults"))
+ Browser.loading(lang("gui.browser.noresults"));
return
}
+ packagecount = 0;
+
+ let count = 0;
for (let i = 0; i < res.length; i++) {
+ if (count >= Browser.maxentries) {break}
+ if (Browser.filters.isfiltered(res[i].item.categories)) {continue}
new BrowserElFromObj(res[i].item);
+ count++;
+ }
+
+ if (count < 1) {
+ Browser.loading(lang("gui.browser.noresults"));
}
},
setbutton: (mod, string) => {
@@ -157,6 +227,58 @@ var Browser = {
}
}, 1501)
}
+ },
+ loadpkgs: (pkgs, clear) => {
+ if (clear) {packagecount = 0}
+
+ if (browserEntries.querySelector(".message")) {
+ browserEntries.querySelector(".message").remove();
+ }
+
+ let count = 0;
+ for (let i in pkgs) {
+ if (count >= Browser.maxentries) {
+ if (pkgs[i] === undefined) {
+ Browser.endoflist(true);
+ }
+
+ Browser.endoflist();
+ break
+ }
+
+ try {
+ new BrowserElFromObj(pkgs[i]);
+ }catch(e) {}
+
+ count++;
+ packagecount++;
+ }
+ },
+ msg: (html) => {
+ let msg = document.createElement("div");
+ msg.classList.add("message");
+ msg.innerHTML = html;
+
+ browserEntries.appendChild(msg);
+ }
+}
+
+function openExternal(url) {
+ require("electron").shell.openExternal(url);
+}
+
+var view = document.querySelector(".popup#preview webview");
+var Preview = {
+ show: () => {
+ preview.classList.add("shown");
+ },
+ hide: () => {
+ preview.classList.remove("shown");
+ },
+ set: (url, autoshow) => {
+ if (autoshow != false) {Preview.show()}
+ view.src = url;
+ document.querySelector("#preview #external").setAttribute("onclick", `openExternal("${url}")`);
}
}
@@ -171,16 +293,14 @@ function BrowserElFromObj(obj) {
download: pkg.download_url,
version: pkg.version_number,
categories: pkg.categories,
- description: pkg.description
+ description: pkg.description,
+ dependencies: pkg.dependencies,
})
}
function BrowserEl(properties) {
if (Browser.filters.isfiltered(properties.categories)) {return}
- let entries = browser.querySelectorAll(".el").length;
- if (entries == Browser.maxentries) {Browser.endoflist();return}
-
properties = {
title: "No name",
version: "1.0.0",
@@ -230,25 +350,30 @@ function BrowserEl(properties) {
}
}
}
-
- browserEntries.innerHTML += `
- <div class="el" id="mod-${normalize(properties.title)}">
- <div class="image">
- <img src="${properties.image}">
- </div>
- <div class="text">
- <div class="title">${properties.title}</div>
- <div class="description">${properties.description}</div>
- <button onclick="installFromURL('${properties.download}')">${installstr}</button>
- <button onclick="require('electron').shell.openExternal('${properties.url}')">${lang('gui.browser.info')}</button>
- <button class="visual">${properties.version}</button>
- <button class="visual">${lang("gui.browser.madeby")} ${properties.author}</button>
- </div>
+
+ let entry = document.createElement("div");
+ entry.classList.add("el");
+ entry.id = `mod-${normalize(properties.title)}`;
+
+ entry.innerHTML = `
+ <div class="image">
+ <img src="${properties.image}">
+ <img class="blur" src="${properties.image}">
+ </div>
+ <div class="text">
+ <div class="title">${properties.title}</div>
+ <div class="description">${properties.description}</div>
+ <button class="install" onclick='installFromURL("${properties.download}", ${JSON.stringify(properties.dependencies)}, true)'>${installstr}</button>
+ <button class="info" onclick="Preview.set('${properties.url}')">${lang('gui.browser.view')}</button>
+ <button class="visual">${properties.version}</button>
+ <button class="visual">${lang("gui.browser.madeby")} ${properties.author}</button>
</div>
`
+
+ browserEntries.appendChild(entry);
}
-ipcRenderer.on("removedmod", (event, mod) => {
+ipcRenderer.on("removed-mod", (event, mod) => {
setButtons(true);
Browser.setbutton(mod.name, lang("gui.browser.install"));
if (mod.manifestname) {
@@ -256,7 +381,7 @@ ipcRenderer.on("removedmod", (event, mod) => {
}
})
-ipcRenderer.on("failedmod", (event, modname) => {
+ipcRenderer.on("failed-mod", (event, modname) => {
setButtons(true);
new Toast({
timeout: 10000,
@@ -266,7 +391,17 @@ ipcRenderer.on("failedmod", (event, modname) => {
})
})
-ipcRenderer.on("installedmod", (event, mod) => {
+ipcRenderer.on("no-internet", (event, modname) => {
+ setButtons(true);
+ new Toast({
+ timeout: 10000,
+ scheme: "error",
+ title: lang("gui.toast.noInternet.title"),
+ description: lang("gui.toast.noInternet.desc")
+ })
+})
+
+ipcRenderer.on("installed-mod", (event, mod) => {
setButtons(true);
Browser.setbutton(mod.name, lang("gui.browser.reinstall"));
@@ -284,14 +419,21 @@ ipcRenderer.on("installedmod", (event, mod) => {
title: lang("gui.toast.title.installed"),
description: mod.name + " " + lang("gui.toast.desc.installed")
})
+
+ if (installqueue.length != 0) {
+ installFromURL("https://thunderstore.io/package/download/" + installqueue[0]);
+ installqueue.shift();
+ }
})
function normalize(items) {
let main = (string) => {
- return string.replaceAll(" ", "").replaceAll(".", "").replaceAll("-", "").replaceAll("_", "").toLowerCase()
+ return string.replaceAll(" ", "")
+ .replaceAll(".", "").replaceAll("-", "")
+ .replaceAll("_", "").toLowerCase();
}
if (typeof items == "string") {
- return main(items)
+ return main(items);
} else {
let newArray = [];
for (let i = 0; i < items.length; i++) {
@@ -322,11 +464,50 @@ search.addEventListener("keyup", () => {
}
})
-browser.addEventListener("scroll", () => {
- Browser.filters.toggle(false);
+let events = ["scroll", "mousedown", "touchdown"];
+events.forEach((event) => {
+ browser.addEventListener(event, () => {
+ Preview.hide();
+
+ let mouseAt = document.elementsFromPoint(mouseX, mouseY);
+ if (! mouseAt.includes(document.querySelector("#filter"))
+ && ! mouseAt.includes(document.querySelector(".overlay"))) {
+ Browser.filters.toggle(false);
+ }
+ })
+});
+
+view.addEventListener("dom-ready", () => {
+ let css = [
+ fs.readFileSync(__dirname + "/css/theming.css", "utf8"),
+ fs.readFileSync(__dirname + "/css/webview.css", "utf8")
+ ]
+
+ view.insertCSS(css.join(" "));
+})
+
+view.addEventListener("did-stop-loading", () => {
+ view.style.display = "flex";
+ setTimeout(() => {
+ view.classList.remove("loading");
+ }, 200)
+})
+
+view.addEventListener("did-start-loading", () => {
+ view.style.display = "none";
+ view.classList.add("loading");
+})
+
+let mouseY = 0;
+let mouseX = 0;
+browser.addEventListener("mousemove", (event) => {
+ mouseY = event.clientY;
+ mouseX = event.clientX;
})
let checks = document.querySelectorAll(".check");
for (let i = 0; i < checks.length; i++) {
- checks[i].setAttribute("onclick", "this.classList.toggle('checked');Browser.loadfront();search.value = ''")
+ checks[i].setAttribute("onclick",
+ "this.classList.toggle('checked');Browser.loadfront();search.value = ''"
+ )
}