ZDDC/transmittal/js/app.js
ZDDC ea385b5366 Initial commit
ZDDC — Zero Day Document Control. A file-naming convention plus five
single-file HTML tools (archive, transmittal, classifier, mdedit,
landing) and an optional Go HTTP server (zddc-server) with ACL and a
virtual archive index. Self-contained, offline-capable, dependency-free.

See README.md for an overview, AGENTS.md and ARCHITECTURE.md for the
build/release/architecture detail, bootstrap/README.md for the
two-level deployment install pattern, and zddc/README.md for the
HTTP server.
2026-04-27 11:05:47 -05:00

73 lines
2 KiB
JavaScript

(function (global) {
'use strict';
if (global.transmittalApp) {
return;
}
const app = {
state: {
mode: 'edit',
published: false,
dirty: false
},
data: {
files: [],
selectedDirHandle: null,
selectedDirName: ''
},
constants: {
viewableExts: ['pdf', 'png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'txt', 'html', 'htm', 'md'],
digestAlgorithm: 'SHA-256',
signatureAlgorithm: 'ECDSA-P256-SHA256',
SELF_HASH: 'self:payload-digest'
},
modules: {},
initCallbacks: [],
registerInit(fn) {
if (typeof fn === 'function') {
app.initCallbacks.push(fn);
}
},
dirtyListeners: [],
onDirty(fn) {
if (typeof fn === 'function') {
app.dirtyListeners.push(fn);
}
},
markDirty() {
app.state.dirty = true;
app.dirtyListeners.forEach(function (fn) {
try { fn(); } catch (err) { console.error('[transmittal] dirtyListener error', err); }
});
},
ready(fn) {
if (typeof fn !== 'function') {
return;
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn, { once: true });
} else {
fn();
}
},
start() {
if (app._started) {
return;
}
app._started = true;
const run = function () {
app.initCallbacks.forEach(function (fn) {
try {
fn();
} catch (err) {
console.error('[transmittal] init error', err);
}
});
};
app.ready(run);
}
};
global.transmittalApp = app;
})(window);