Updates galore. Improved folder structure, componentized, and notifications upon completion.
This commit is contained in:
parent
b48784e2ad
commit
7e0502ca40
33 changed files with 3565 additions and 728 deletions
119
static/js/modules/state.js
Normal file
119
static/js/modules/state.js
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* state.js
|
||||
* --------
|
||||
* Single shared application state object and all DOM element references.
|
||||
*
|
||||
* Centralising these here means every module imports the same live object —
|
||||
* mutations made in one module are immediately visible to all others without
|
||||
* any event bus or pub/sub layer.
|
||||
*
|
||||
* Also exports announce(), which every module uses to push messages to the
|
||||
* ARIA live region for screen-reader users.
|
||||
*/
|
||||
|
||||
// ─── Shared mutable state ────────────────────────────────────────────────────
|
||||
export const state = {
|
||||
/** Files returned by the last /api/scan call. */
|
||||
scannedFiles: [],
|
||||
|
||||
/** Set of file paths the user has checked for compression. */
|
||||
selectedPaths: new Set(),
|
||||
|
||||
/** job_id of the currently active or most-recently-seen compression job. */
|
||||
currentJobId: null,
|
||||
|
||||
/** Active EventSource for the SSE progress stream. */
|
||||
eventSource: null,
|
||||
|
||||
/** Per-file result objects accumulated during a compression run. */
|
||||
compressionResults: [],
|
||||
|
||||
/** Current path shown in the server-side directory browser modal. */
|
||||
browserPath: '/',
|
||||
|
||||
/**
|
||||
* Index of the last SSE event we have processed.
|
||||
* Passed as ?from=N when reconnecting so the server skips events
|
||||
* we already applied to the UI.
|
||||
*/
|
||||
seenEventCount: 0,
|
||||
|
||||
/** Handle returned by setTimeout for the auto-reconnect retry. */
|
||||
reconnectTimer: null,
|
||||
};
|
||||
|
||||
// ─── DOM element references ───────────────────────────────────────────────────
|
||||
const $ = id => document.getElementById(id);
|
||||
|
||||
export const els = {
|
||||
// Step 1 — Configure source
|
||||
dirInput: $('dir-input'),
|
||||
browseBtn: $('browse-btn'),
|
||||
minSizeInput: $('min-size-input'),
|
||||
suffixInput: $('suffix-input'),
|
||||
scanBtn: $('scan-btn'),
|
||||
scanStatus: $('scan-status'),
|
||||
|
||||
// Directory browser modal
|
||||
browserModal: $('browser-modal'),
|
||||
browserList: $('browser-list'),
|
||||
browserPath: $('browser-current-path'),
|
||||
closeBrowser: $('close-browser'),
|
||||
browserCancel: $('browser-cancel'),
|
||||
browserSelect: $('browser-select'),
|
||||
|
||||
// Step 2 — File selection
|
||||
sectionFiles: $('section-files'),
|
||||
selectAllBtn: $('select-all-btn'),
|
||||
deselectAllBtn: $('deselect-all-btn'),
|
||||
selectionSummary: $('selection-summary'),
|
||||
fileTbody: $('file-tbody'),
|
||||
compressBtn: $('compress-btn'),
|
||||
|
||||
// Email notification opt-in
|
||||
notifyChk: $('notify-chk'),
|
||||
notifyEmailRow: $('notify-email-row'),
|
||||
notifyEmail: $('notify-email'),
|
||||
|
||||
// Step 3 — Compression progress
|
||||
sectionProgress: $('section-progress'),
|
||||
progTotal: $('prog-total'),
|
||||
progDone: $('prog-done'),
|
||||
progStatus: $('prog-status'),
|
||||
overallBar: $('overall-bar'),
|
||||
overallBarFill: $('overall-bar-fill'),
|
||||
overallPct: $('overall-pct'),
|
||||
fileProgressList: $('file-progress-list'),
|
||||
cancelBtn: $('cancel-btn'),
|
||||
notifyStatus: $('notify-status'),
|
||||
reconnectBtn: $('reconnect-btn'),
|
||||
reconnectBtnBanner: $('reconnect-btn-banner'),
|
||||
streamLostBanner: $('stream-lost-banner'),
|
||||
|
||||
// Step 4 — Results
|
||||
sectionResults: $('section-results'),
|
||||
resultsContent: $('results-content'),
|
||||
restartBtn: $('restart-btn'),
|
||||
|
||||
// Header
|
||||
themeToggle: $('theme-toggle'),
|
||||
themeIcon: $('theme-icon'),
|
||||
settingsBtn: $('settings-btn'),
|
||||
|
||||
// Accessibility live region
|
||||
srAnnounce: $('sr-announce'),
|
||||
};
|
||||
|
||||
// ─── Screen-reader announcements ─────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Push a message to the ARIA assertive live region.
|
||||
* Clears first so repeated identical messages are still announced.
|
||||
* @param {string} msg
|
||||
*/
|
||||
export function announce(msg) {
|
||||
els.srAnnounce.textContent = '';
|
||||
requestAnimationFrame(() => {
|
||||
els.srAnnounce.textContent = msg;
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue