web: a reading walks past the recycle bin, not into it
The walk already turned its back on the folders a camera and an editor leave
behind: a name beginning with `.` or `@` is skipped, which is `.thumbnails`,
`.git`, `.Trash`, and the `@eaDir` a Synology writes beside every frame.
An external volume drags along a second set of names, and none of them begins
with a dot, so every one of them was walked. `$RECYCLE.BIN` and `RECYCLER` are
where Windows parks what the reader deleted — frames among them, at full size,
and every one of them decoded into a thumbnail on the way in. `System Volume
Information` is Windows' own bookkeeping. `#recycle` is the Synology share, and
`lost+found` is the directory a Linux volume keeps for repairs. A frame that
comes back out of a bin is a frame the reader threw away, and the pictures in a
share's recycle folder are pictures someone else deleted; neither belongs in
the catalogue, and both cost the reading the same seconds a real frame does.
The folder also stood in the column as a row of its own.
The rule is now one `SYSTEM_DIR` expression over both sets, matched
case-insensitively — the same volume spells the bin `$RECYCLE.BIN` on one drive
and `$Recycle.Bin` on the next — and the walk asks it before it looks at what
the entry is, so a refused folder is neither read nor named.
Verified:
roll-walk-check.mjs — all passed, with two new assertions: the stand-in roll
now carries `$RECYCLE.BIN`, `$Recycle.Bin`, `RECYCLER`, `System Volume
Information`, `#recycle` and `lost+found`, and every one of them holds a
file named like a frame, so nothing about the files can be what keeps them
out. No frame is read from them, and none of them reaches the column.
library-check.mjs — 43 steps, all passed. scan-nav-check.mjs — all passed.
frontend tsc --noEmit clean.
ponytail: the list is the names the volumes being read actually use, not a
guess at every spelling there is — a box that files its junk under something
else gets a line in that expression, which is the whole of the change. A folder
of the reader's own that happens to be called `#recycle` is skipped too; that
name is worth the trade.
Co-authored-by: PenguinHarness <noreply@penguin.local>
This commit is contained in:
@@ -19,7 +19,9 @@ const { DIRS_PER_PASS, jumpQueue, walkPass } = await import(`data:text/javascrip
|
||||
// A directory handle is only ever read for `values()` and `getDirectoryHandle()`,
|
||||
// so a stand-in tree needs nothing else: `{ name: { … } }` for folders and
|
||||
// `name: null` for a file. `@eaDir` and `.thumbnails` are the folders a real roll
|
||||
// drags along.
|
||||
// drags along, and the recycle bins below are the ones an external volume puts at
|
||||
// its root — each holds a frame-named file, so only the folder rule can be what
|
||||
// keeps them out.
|
||||
const dir = (name, children) => ({
|
||||
kind: 'directory',
|
||||
name,
|
||||
@@ -44,6 +46,12 @@ const roll = dir('CheckRoll', {
|
||||
'Empty': { 'notes.txt': null },
|
||||
'2026': { 'P2.JPG': null, '04': { 'P3.RW2': null, 'notes.txt': null } },
|
||||
'2025': { 'P4.JPG': null },
|
||||
'$RECYCLE.BIN': { 'deleted.JPG': null },
|
||||
'$Recycle.Bin': { 'also-deleted.JPG': null },
|
||||
'RECYCLER': { 'older.JPG': null },
|
||||
'System Volume Information': { 'W.JPG': null },
|
||||
'#recycle': { 'synology.JPG': null },
|
||||
'lost+found': { 'linux.JPG': null },
|
||||
});
|
||||
|
||||
// Walks to the end, one click per pass, which is what the browser does between
|
||||
@@ -77,6 +85,11 @@ assert.ok(
|
||||
'no deeper frame is read before a shallower one'
|
||||
);
|
||||
assert.ok(!rels.some((rel) => /\.thumbnails|@eaDir|notes\.txt/.test(rel)), 'hidden and unsupported names are skipped');
|
||||
// The frames inside the recycle bins are named like frames, so nothing about the
|
||||
// files keeps them out: the folders themselves are what the walk refuses.
|
||||
const SYSTEM = /\$Recycle\.Bin|RECYCLER|System Volume Information|#recycle|lost\+found/i;
|
||||
assert.ok(!rels.some((rel) => SYSTEM.test(rel)), 'a recycle bin or system folder yields no frame');
|
||||
assert.ok(!names.some((rel) => SYSTEM.test(rel)), 'and never becomes a row either');
|
||||
assert.deepEqual(
|
||||
names,
|
||||
['2025/', '2026/', 'Empty/', '2026/04/'],
|
||||
@@ -130,4 +143,4 @@ assert.equal(await walkPass(many, found, [], keep, () => null), false, 'the queu
|
||||
assert.equal(found.length, DIRS_PER_PASS - 1, `one pass read the picked folder and ${DIRS_PER_PASS - 1} below it`);
|
||||
assert.equal(many.pending.length, 6, 'the rest is left in the queue, for the next pass');
|
||||
|
||||
console.log(`ok roll walk — ${rels.length} frames layer by layer, names a pass ahead, click jumps the queue, ${DIRS_PER_PASS} folders a pass`);
|
||||
console.log(`ok roll walk — ${rels.length} frames layer by layer, recycle bins and system folders skipped, names a pass ahead, click jumps the queue, ${DIRS_PER_PASS} folders a pass`);
|
||||
|
||||
Reference in New Issue
Block a user