diff --git a/static/crossroad.css b/static/crossroad.css index 92bcd3c..5569ae5 100644 --- a/static/crossroad.css +++ b/static/crossroad.css @@ -119,4 +119,13 @@ abbr[title] { top: 50%; left: 50%; translate: -50% -50%; +} + +.logo { + height: 4em; +} + +.inlineIcon { + height: var(--medium); + vertical-align: text-top; } \ No newline at end of file diff --git a/static/crossroad.html b/static/crossroad.html index 0ab8ba3..c5fb33d 100644 --- a/static/crossroad.html +++ b/static/crossroad.html @@ -20,15 +20,19 @@

FeDirect

  By Nekomata

- Nekomata Logo +
-
- - + +
+ + +

diff --git a/static/crossroad.mts b/static/crossroad.mts index 8d212c4..ad0bfe9 100644 --- a/static/crossroad.mts +++ b/static/crossroad.mts @@ -1,5 +1,7 @@ import { initializeAddInstanceFlow } from "./add_instance_flow.mjs"; -import { findDialogOrFail } from "./dom.mjs"; +import { findDialogOrFail, findFormOrFail } from "./dom.mjs"; +import knownSoftware from "./known_software.mjs"; +import storageManager from "./storage_manager.mjs"; export function getMainDialog(): HTMLDialogElement { return document.getElementById('mainDialog') as HTMLDialogElement; @@ -7,8 +9,43 @@ export function getMainDialog(): HTMLDialogElement { const detailsDialog = findDialogOrFail(document.body, "#instanceDetails"); const addDialog = findDialogOrFail(document.body, "#addInstance"); +const instanceSelectForm = findFormOrFail(document.body, "#instanceSelectForm"); export const { showAddInstanceDialog, hideAddInstanceDialog } = initializeAddInstanceFlow(detailsDialog, addDialog); + +function createInstanceSelectOptions() { + instanceSelectForm.replaceChildren(); // Erase all child nodes + for (const instance of storageManager.storage.instances) { + const div = document.createElement("div"); + div.setAttribute("x-option", instance.origin); + const radio = document.createElement("input"); + radio.id = instance.origin; + radio.type = "radio"; + radio.name = "instanceSelect"; + const label = document.createElement("label"); + label.htmlFor = instance.origin; + label.innerText = instance.name + " "; + if (instance.iconURL) { + const img = new Image(); + img.src = instance.iconURL; + img.alt = `${instance.name} icon`; + img.className = "inlineIcon"; + label.append(img, " "); + } + const small = document.createElement("small"); + const softwareName = knownSoftware.software[instance.software].name; + small.innerText = `(${softwareName})`; + label.appendChild(small); + div.appendChild(radio); + div.appendChild(label); + instanceSelectForm.appendChild(div); + } + const firstInput = instanceSelectForm.querySelector("input"); + if (firstInput) firstInput.checked = true; +} + +createInstanceSelectOptions(); +storageManager.addSaveCallback(createInstanceSelectOptions); diff --git a/static/storage_manager.mts b/static/storage_manager.mts index da88774..dc89b95 100644 --- a/static/storage_manager.mts +++ b/static/storage_manager.mts @@ -33,6 +33,7 @@ type LocalStorage = { export default new class StorageManager { storage: LocalStorage; + saveCallbacks: (() => void)[] = []; constructor() { this.load(); @@ -50,5 +51,10 @@ export default new class StorageManager { save() { window.localStorage.setItem("storage", JSON.stringify(this.storage)); + this.saveCallbacks.forEach(c => c()); + } + + addSaveCallback(callback: () => void) { + this.saveCallbacks.push(callback); } }(); \ No newline at end of file