Files
simplexmq/xftp-web/web/main.ts

55 lines
1.6 KiB
TypeScript

import sodium from 'libsodium-wrappers-sumo'
import {initUpload} from './upload.js'
import {initDownload} from './download.js'
import {t} from './i18n.js'
function getAppElement(): HTMLElement | null {
return (document.querySelector('[data-xftp-app]') as HTMLElement | null) ?? document.getElementById('app')
}
const wasmReady = sodium.ready
async function main() {
// Render UI immediately — no WASM needed for HTML + event listeners.
// WASM is only used later when user triggers upload/download.
const app = getAppElement()
if (!app?.hasAttribute('data-defer-init')) {
initApp()
}
if (!app?.hasAttribute('data-no-hashchange')) {
window.addEventListener('hashchange', () => {
const hash = window.location.hash.slice(1)
if (!hash || looksLikeXFTPHash(hash)) initApp()
})
}
await wasmReady
app?.dispatchEvent(new CustomEvent('xftp:ready', {bubbles: true}))
}
// XFTP hashes are base64url-encoded DEFLATE data, always long.
// Matches the index.html inline script heuristic (length > 50).
function looksLikeXFTPHash(hash: string): boolean {
return hash.length > 50 && /^[A-Za-z0-9_=-]+$/.test(hash)
}
function initApp() {
const app = getAppElement()!
const hash = window.location.hash.slice(1)
if (hash && looksLikeXFTPHash(hash)) {
initDownload(app, hash)
} else {
initUpload(app)
}
}
;(window as any).__xftp_initApp = async () => { await wasmReady; initApp() }
main().catch(err => {
const app = getAppElement()
if (app) {
app.innerHTML = `<div class="error"><p>${t('initError', 'Failed to initialize: %error%').replace('%error%', err.message)}</p></div>`
}
console.error(err)
})