| 1 |
// MNW frontend core — entry point. |
| 2 |
// |
| 3 |
// Loaded once, globally, as a `<script type="module">` in place of the retired |
| 4 |
// `static/mnw.js`. It installs every delegated listener the old god-file did |
| 5 |
// (toasts, HTMX glue, the data-action + hx-callback dispatchers, copy-link, |
| 6 |
// keyboard, tabs, restart banner) and bridges the shared primitives onto |
| 7 |
// `window` so the not-yet-migrated `static/*.js` files keep resolving them. |
| 8 |
// |
| 9 |
// As feature files migrate into frontend/src, drop their entries from the |
| 10 |
// bridge and register their handlers via `dispatch.register()` instead of a |
| 11 |
// global; the `frontend_globals` seal ratchets the legacy count down. |
| 12 |
|
| 13 |
import { escapeHtml, escapeAttr } from './dom.ts'; |
| 14 |
import { csrfHeaders, apiError } from './net.ts'; |
| 15 |
import { showToast, initToasts } from './toast.ts'; |
| 16 |
import { safeGet, safeSet } from './storage.ts'; |
| 17 |
import { copyWithFeedback, initCopyLink } from './clipboard.ts'; |
| 18 |
import { resolveHtmxLoadingButton, withLoadingState } from './loading.ts'; |
| 19 |
import { initActionDispatcher, initHxCallbackDispatcher } from './dispatch.ts'; |
| 20 |
import { setActiveTab, initTabs } from './tabs.ts'; |
| 21 |
import { toggleShortcutsHelp, initKeyboard } from './keyboard.ts'; |
| 22 |
import { initRestartBanner } from './restart-banner.ts'; |
| 23 |
import { initHtmxGlue } from './htmx-glue.ts'; |
| 24 |
|
| 25 |
// Common, lightweight islands are registered globally here (side-effect import |
| 26 |
// defines the custom element). Heavy or page-specific islands (media player, |
| 27 |
// uploader) load per-page instead. Custom elements auto-upgrade on connect, so |
| 28 |
// carousels in HTMX-swapped content wire themselves with no extra glue. |
| 29 |
import '../islands/carousel.ts'; |
| 30 |
// Image uploader appears in HTMX-swapped wizard steps, so it's registered |
| 31 |
// globally (auto-upgrades on swap). The heavier upload flows (item audio/version |
| 32 |
// queue, gallery, bundle) still use the legacy static/upload.js until migrated. |
| 33 |
import '../islands/uploader/image-uploader.ts'; |
| 34 |
|
| 35 |
/** |
| 36 |
* Legacy bridge — the not-yet-migrated `static/*.js` files call these by their |
| 37 |
* historical global names. `mnw.js` exposed them as classic-script globals |
| 38 |
* (function declarations / `window.*`); the module re-exposes them so the |
| 39 |
* cutover is behavior-preserving. Retire each entry as its consumers move into |
| 40 |
* frontend/src. |
| 41 |
*/ |
| 42 |
function installLegacyBridge(): void { |
| 43 |
const w = window as unknown as Record<string, unknown>; |
| 44 |
w.escapeHtml = escapeHtml; |
| 45 |
w.escapeAttr = escapeAttr; |
| 46 |
w.csrfHeaders = csrfHeaders; |
| 47 |
w.showToast = showToast; |
| 48 |
w.safeStorageGet = safeGet; |
| 49 |
w.safeStorageSet = safeSet; |
| 50 |
w.setActiveTab = setActiveTab; |
| 51 |
w.toggleShortcutsHelp = toggleShortcutsHelp; |
| 52 |
w.copyWithFeedback = copyWithFeedback; |
| 53 |
w.resolveHtmxLoadingButton = resolveHtmxLoadingButton; |
| 54 |
w.withLoadingState = withLoadingState; |
| 55 |
// Historical name; wraps apiError so the (response, fallback) signature and |
| 56 |
// the Promise<string> return match the old global exactly. |
| 57 |
w.apiErrorMessage = (response: Response | null | undefined, fallback?: string) => apiError(response, fallback); |
| 58 |
} |
| 59 |
|
| 60 |
function initCore(): void { |
| 61 |
installLegacyBridge(); |
| 62 |
initToasts(); |
| 63 |
initHtmxGlue(); |
| 64 |
initActionDispatcher(); |
| 65 |
initHxCallbackDispatcher(); |
| 66 |
initCopyLink(); |
| 67 |
initKeyboard(); |
| 68 |
initTabs(); |
| 69 |
initRestartBanner(); |
| 70 |
} |
| 71 |
|
| 72 |
// A module script is deferred, so the DOM is already parsed by the time this |
| 73 |
// runs; the readyState guard is belt-and-suspenders. |
| 74 |
if (document.readyState === 'loading') { |
| 75 |
document.addEventListener('DOMContentLoaded', initCore); |
| 76 |
} else { |
| 77 |
initCore(); |
| 78 |
} |
| 79 |
|