diff --git a/scripts/system/more-ng/more-ng.js b/scripts/system/more-ng/more-ng.js index 110e01337d9..ab78de99804 100644 --- a/scripts/system/more-ng/more-ng.js +++ b/scripts/system/more-ng/more-ng.js @@ -1,9 +1,11 @@ // // Copyright 2023 Overte e.V. +// "https://more.overte.org/applications/metadata.js", const html_url = Script.resolvePath("./ui/index.html"); let tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); let shown = false; +const logs = (info) => console.log("[NEW_MORE] " + JSON.stringify(info)); tablet.screenChanged.connect(onScreenChanged); Script.scriptEnding.connect(shutdownTabletApp); @@ -14,6 +16,13 @@ let tabletButton = tablet.addButton({ activeIcon: Script.resolvePath("./img/icon-a.png"), }); +let repo_list = [ + "https://raw.githubusercontent.com/Armored-Dragon/overte-app-examples/master/metadata.json", +]; +let app_info = { + installed_apps: [], + thirdparty_apps: [], +}; // REVIEW: How can we optimize this further? tabletButton.clicked.connect(clicked); @@ -57,16 +66,8 @@ function onWebEventReceived(message) { message = JSON.parse(message); if (message.action === "ready") { - // Get apps from repos - // Form custom Object and send to ui - - // Get installed apps - const installed_apps = ScriptDiscoveryService.getRunning(); - const repo_apps = _get(""); - - const app_list = _createAppList(installed_apps, repo_apps); - - _sendMessage({ action: "app_list", data: app_list }); + getInstalledApps(); + findThirdParty(); } if (message.action === "new_repo") { @@ -79,49 +80,112 @@ function onWebEventReceived(message) { } if (message.action === "install_script") { - // On installed, create "setting" to save app metadata + logs(`Installing script ${message.data}`); + ScriptDiscoveryService.loadScript(message.data); } if (message.action === "uninstall_script") { + logs(`Uninstalling script ${message.data}`); ScriptDiscoveryService.stopScript(message.data); - // TODO: Reload application window } } -function _get(url) { - // HTTPS Request here - return []; -} +function getInstalledApps() { + const running_apps = ScriptDiscoveryService.getRunning(); + const installed_apps = Settings.getValue("more_installed_list", []); -function _createAppList(installed_apps, repo_apps) { let return_array = []; - - installed_apps.forEach((app) => { + running_apps.forEach((app) => { // REVIEW: Multiplatform support functional? if (app.url.includes("file://")) return; + let found = false; - return_array.push({ - title: app.name, - url: app.url, - icon: app.icon || "", - installed: true, - }); - }); + logs(`Processing ${app.name || app.title}`); + logs(app.url); - // REVIEW: Is this legit? - repo_apps.forEach((app) => { for (let i = 0; installed_apps.length > i; i++) { - if (installed_apps[Object.keys(installed_apps)[i]].url === app.url) + if (installed_apps[i].url === app.url) { + return_array.push(installed_apps[i]); + found = true; + break; + } + + // Our installed app is not saved in settings, add it + if (installed_apps.length === i) { + logs("Not in settings"); + let template = { + title: app.name, + url: app.url, + icon: app.icon || "", + description: app.description, + directory: app.directory, + installed: true, + }; + return_array.push(template); + found = true; return; + } } + if (!found) { + logs("Settings was blank; just pushing it in."); + let template = { + title: app.name, + url: app.url, + icon: app.icon || "", + description: app.description, + directory: app.directory, + installed: true, + }; + return_array.push(template); + return; + } + }); + + Settings.setValue("more_installed_list", return_array); + _sendMessage({ action: "installed_apps", data: return_array }); +} - return_array.push({ - title: app.name, - url: app.url, - icon: app.icon || "", - installed: false, +function findThirdParty() { + repo_list.forEach((url) => { + var req = new XMLHttpRequest(); + + req.requestComplete.connect(() => { + if (req.status !== 200) { + _sendMessage({ + action: "repo_loaded", + data: { error: true, status: req.status }, + }); + } + + const response = JSON.parse(req.responseText); + let app_list_formatted = []; + + response.forEach((app) => { + const app_dir = + url.split("/metadata.json")[0] + "/" + app.directory + "/"; + + const icon_url = app_dir + app.icon; + const script_url = app_dir + app.script; + + app_list_formatted.push({ + title: app.name, + url: script_url, + icon: icon_url, + description: app.description, + directory: app.directory, + installed: false, + }); + }); + + return _sendMessage({ + action: "repo_loaded", + data: app_list_formatted, + }); }); - }); - return return_array; + req.open("GET", url); + req.send(); + }); } + +repo_list = Settings.getValue("more_repo_list", repo_list); diff --git a/scripts/system/more-ng/ui/index.css b/scripts/system/more-ng/ui/index.css index 86c168e370c..6d034730649 100644 --- a/scripts/system/more-ng/ui/index.css +++ b/scripts/system/more-ng/ui/index.css @@ -3,6 +3,10 @@ body { overflow-y: hidden; } +.container { + min-height: inherit; +} + .search-area { display: grid; grid-template-columns: auto 140px; diff --git a/scripts/system/more-ng/ui/index.html b/scripts/system/more-ng/ui/index.html index a9e8d948e5c..6dc4a463cb4 100644 --- a/scripts/system/more-ng/ui/index.html +++ b/scripts/system/more-ng/ui/index.html @@ -24,93 +24,17 @@ -
- -
-
-
- -
-
-
-
-
-
-
- - - -
-
-
-
-
- -
-
-
-
-
-
-
- - - -
-
-
-
-
- -
-
-
-
-
-
-
- - - -
-
-
-
-
- -
-
-
-
-
-
-
- - - -
-
-
-
-
- -
-
-
-
-
-
-
- - - -
-
-
+
@@ -170,7 +94,7 @@
- +
@@ -179,7 +103,9 @@
- +
diff --git a/scripts/system/more-ng/ui/index.js b/scripts/system/more-ng/ui/index.js index f08ad33c405..08e57db847d 100644 --- a/scripts/system/more-ng/ui/index.js +++ b/scripts/system/more-ng/ui/index.js @@ -2,13 +2,25 @@ const qs = (target) => document.querySelector(target); const qsa = (target) => document.querySelectorAll(target); +// Page selection qs("#open-settings").addEventListener("click", () => openPage("settings")); qs("#close-settings").addEventListener("click", () => openPage("app-listing")); qs("#open-filters").addEventListener("click", () => openFilter()); +const logs = (info) => console.log("[NEW_MORE] " + JSON.stringify(info)); EventBridge.scriptEventReceived.connect((message) => newMessage(JSON.parse(message)) ); + +let app_info = { + installed_apps: [], + thirdparty_apps: [], +}; + +let search_filters = { + only_installed: false, +}; + const _sendMessage = (message) => EventBridge.emitWebEvent(JSON.stringify(message)); @@ -28,39 +40,71 @@ function openFilter() { } function newMessage(message) { - if (message.action === "app_list") { + if (message.action === "installed_apps") { + buildAppList(message.data, true); + } + + if (message.action === "repo_loaded") { buildAppList(message.data); } } -function buildAppList(app_list) { +function buildAppList(app_list, clear) { // Remove existing listings - qsa(".app-list .listing").forEach((item) => item.remove()); + if (clear) qsa(".app-list .listing").forEach((item) => item.remove()); app_list.forEach((app) => { + let found = false; + + app_info.installed_apps.forEach((check_app) => { + if (check_app.url === app.url) found = true; + }); + if (found) return; + let template = qs("#app-listing-template").content.cloneNode(true); - if (app.local === true) return; - console.log(JSON.stringify(app)); + + template.querySelector(".icon img").src = app.icon; + template.querySelector(".app-info .body .title").innerText = app.title; + template.querySelector(".app-info .body .description").innerText = + app.description; if (app.installed) { - template.querySelector(".listing").classList.add("installed"); + // Hide "Install" button template .querySelector(".app-actions [data-intention='install']") .classList.add("hidden"); + + // Unhide "uninstall" button template .querySelector(".app-actions [data-intention='uninstall']") .classList.remove("hidden"); + + // Uninstall Script button template .querySelector(".app-actions .bad") .addEventListener("click", () => { uninstallApp(app.url); }); - } - if (app.icon) template.querySelector(".icon img").src = app.icon; - - template.querySelector(".app-info .body .title").innerText = app.title; + app_info.installed_apps.push(app); + } + if (!app.installed) { + // Unhide "Install" button + template + .querySelector(".app-actions [data-intention='install']") + .classList.remove("hidden"); + // Hide "uninstall" button + template + .querySelector(".app-actions [data-intention='uninstall']") + .classList.add("hidden"); + // Install script button + template + .querySelector(".app-actions [data-intention='install']") + .addEventListener("click", () => { + installApp(app.url); + }); + } qs(".app-list").appendChild(template); }); } @@ -69,4 +113,22 @@ function uninstallApp(url) { _sendMessage({ action: "uninstall_script", data: url }); } +function installApp(url) { + _sendMessage({ action: "install_script", data: url }); +} + +function toggleFilter(filter_name) { + if (search_filters[filter_name] === true) { + search_filters[filter_name] = false; + qs('#app-filters [data-filter_name="only_installed"').classList.remove( + "generic" + ); + } else { + search_filters[filter_name] = true; + qs('#app-filters [data-filter_name="only_installed"').classList.add( + "generic" + ); + } +} + _sendMessage({ action: "ready" }); diff --git a/scripts/system/more-ng/ui/index.scss b/scripts/system/more-ng/ui/index.scss index 3581d94871c..8cb6481a813 100644 --- a/scripts/system/more-ng/ui/index.scss +++ b/scripts/system/more-ng/ui/index.scss @@ -2,6 +2,9 @@ body { font-family: Verdana, Geneva, Tahoma, sans-serif; overflow-y: hidden; } +.container { + min-height: inherit; +} .search-area { display: grid;