left4me/l4d2web/l4d2web/static/js/files-overlay.js
mwiegand cb391ad456
feat(files): migrate uploads + drag-drop to uploads.js; legacy file is a stub
Step 4/12 of docs/superpowers/plans/2026-05-17-files-overlay-rewrite.md.

End of Phase A. files-overlay.js is now a 19-line tombstone comment;
all behavior lives in the 4 modules under files-overlay/. Step 10
deletes the stub and its <script> tag.

uploads.js owns:
  * The upload queue (concurrency 3, XHR-based progress, queued/active/
    done/cancelled/error/conflict states) and the progress panel
  * Drag-drop on treeRoot (5 events: dragstart, dragend, dragover,
    dragleave, drop). Internal drags (row → folder, via the custom
    application/x-files-overlay MIME) and external drags (OS files +
    folders via webkitGetAsEntry) flow through the same drop handler.
  * walkEntry for recursive folder walks during external drops
  * withCollisionSuffix (moves here from files-overlay.js — its biggest
    caller is the upload-conflict "keep both" path; exposed on
    __filesOverlay for editor.js's save-409 path too)
  * "zip" action handler (registered into __filesOverlay) — pure URL
    navigation; placed here as the closest thematic home

Pattern change: upload-row cancel buttons converted from direct-bound
per row (inside buildUploadRow, which captured `item` in a closure) to
a single document-level delegated click listener. Each row carries
data-upload-id; an uploads Map<uploadId, item> looks up the item at
click time. The Map entry is removed in the uploadsClearBtn handler
when a done/error/cancelled row is cleared, so the Map doesn't grow
unbounded.

Drag-drop stays direct-bound to treeRoot per the plan escape hatch —
the 5 events share coordinated highlight state (is-drag-source,
is-drop-target classes that are toggled across events), and treeRoot
is persistent (never swapped). Delegation would obscure the state
coordination logic without any real benefit.

Phase A end-state:
  * core.js (247 lines): helpers, manager guard, registry dispatch
  * editor.js (550 lines): editor flows (legacy + URL-addressable)
  * dialogs.js (212 lines): new-folder, delete-confirm, conflict
  * uploads.js (423 lines): upload queue + drag-drop + zip + collision
  * files-overlay.js (19 lines): tombstone comment, deleted in Step 10

Total: ~1432 lines across 4 modules + 19-line stub. The plan estimated
~780 lines across 4 modules; actual is ~1.8× larger, the difference
being module-header comments and the delegation-with-state scaffolding
(e.g., editor.js's dual-editor listener split, dialogs.js's per-dialog
state plus close-event resolvers).

Verified live on /overlays/2 in Chromium:
  * 5 script tags load in document order (core → editor → dialogs →
    uploads → legacy stub)
  * Registry has 10 keys; askConflict and withCollisionSuffix are both
    callable; withCollisionSuffix('foo.tar.gz') === 'foo.tar (1).gz'
    (legacy behavior preserved — lastIndexOf('.') splits before the
    final extension)
  * Uploads panel + list elements present in DOM, panel hidden by
    default
  * "zip" action button exists; registered handler would set
    window.location.href to /overlays/2/files/download_zip?path=...
  * No console errors
  * pytest still 573 passed, 1 skipped, 3 deselected

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 15:57:30 +02:00

19 lines
1,012 B
JavaScript

// files-overlay.js — empty stub pending deletion in Step 10 of
// docs/superpowers/plans/2026-05-17-files-overlay-rewrite.md.
//
// All behavior migrated in Phase A:
// * Helpers + manager-element detection + action-dispatch registry
// → static/js/files-overlay/core.js (Step 1)
// * Editor flows (legacy inline dialog + URL-addressable modal)
// → static/js/files-overlay/editor.js (Step 2)
// * Dialogs (new-folder, delete-confirm, conflict)
// → static/js/files-overlay/dialogs.js (Step 3)
// * Uploads (queue + progress) + drag-drop + withCollisionSuffix +
// "zip" action handler
// → static/js/files-overlay/uploads.js (Step 4)
//
// The four modules attach independently when .files-manager exists
// (each does its own document.querySelector check). This file is kept
// for the duration of Phase A so that <script src=".../files-overlay.js">
// in overlay_detail.html stays load-bearing during the transition; Step
// 10 deletes both the file and the script tag.