a1331212cb
Self-hosted Minecraft modpack distribution + administration system.
- launcher/ Avalonia 12 desktop client; single-file win-x64 publish.
Microsoft auth via XboxAuthNet, manifest+SHA-1 mod sync,
portable install path, sidecar settings.
- server/ brass-sigil-server daemon (.NET 8, linux-x64). Wraps the
MC subprocess, embedded Kestrel admin panel with cookie
auth + rate limiting, RCON bridge, scheduled backups,
BlueMap CLI integration with player markers + skin proxy,
friend-side whitelist request flow, world wipe with seed
selection (keep current / random / custom).
- pack/ pack.lock.json (Modrinth + manual CurseForge entries),
data-only tweak source under tweaks/, build outputs in
overrides/ (gitignored).
- scripts/ Build-Pack / Build-Tweaks / Update-Pack / Check-Updates
plus Deploy-Brass.ps1 unified one-shot deploy with
version-bump pre-flight and daemon-state detection.
58 lines
1.8 KiB
JavaScript
58 lines
1.8 KiB
JavaScript
// Tiny modal helper. Registers a single document-level Esc + backdrop-click
|
|
// handler so individual modals don't have to. Public API: openModal(id) /
|
|
// closeModal(id) / closeAllModals().
|
|
"use strict";
|
|
|
|
let bound = false;
|
|
|
|
function bindGlobal() {
|
|
if (bound) return;
|
|
bound = true;
|
|
document.addEventListener("keydown", e => {
|
|
if (e.key === "Escape") closeAllModals();
|
|
});
|
|
document.addEventListener("click", e => {
|
|
// Backdrop click closes the topmost open modal.
|
|
const backdrop = e.target.closest(".modal-backdrop");
|
|
if (backdrop) closeModal(backdrop.parentElement.id);
|
|
const closeBtn = e.target.closest(".modal-close");
|
|
if (closeBtn) closeModal(closeBtn.closest(".modal").id);
|
|
});
|
|
}
|
|
|
|
export function openModal(id) {
|
|
bindGlobal();
|
|
const m = document.getElementById(id);
|
|
if (!m) return;
|
|
m.hidden = false;
|
|
document.body.classList.add("modal-open");
|
|
// Focus first input/button for keyboard users.
|
|
setTimeout(() => {
|
|
const focusable = m.querySelector("input, button:not(.modal-close), select, textarea");
|
|
focusable?.focus();
|
|
}, 50);
|
|
}
|
|
|
|
export function closeModal(id) {
|
|
const m = document.getElementById(id);
|
|
if (!m) return;
|
|
m.hidden = true;
|
|
if (!document.querySelector(".modal:not([hidden])")) {
|
|
document.body.classList.remove("modal-open");
|
|
}
|
|
}
|
|
|
|
export function closeAllModals() {
|
|
document.querySelectorAll(".modal:not([hidden])").forEach(m => m.hidden = true);
|
|
document.body.classList.remove("modal-open");
|
|
}
|
|
|
|
/// Wires `data-open-modal="someId"` on any element to opening the modal.
|
|
export function setupModalTriggers() {
|
|
bindGlobal();
|
|
document.addEventListener("click", e => {
|
|
const trigger = e.target.closest("[data-open-modal]");
|
|
if (trigger) openModal(trigger.getAttribute("data-open-modal"));
|
|
});
|
|
}
|