feat(library): give a folder its missing thumbnails, and the wall its stars

Four asks, one screen: a folder can be given the tiles it is short of, by hand
or on the way in; the rescan row says RESCAN...; and the wall of thumbnails
scores a frame without the trip to the stage.

- Library.tsx + i18n: "RESCAN FROM THE TOP" is "RESCAN..." in both languages.
  The reading is unchanged — a row's roll is still read from the top, its
  subfolders included.
- engine/library.ts + Library.tsx: the tile of one frame is one function now
  (`makeThumb`: the store, the backup behind it, then the file's own preview
  for a RAW or a HEIC and a decode for anything else). The wall's lazy path
  calls it instead of keeping its own copy of the same branches.
- engine/library.ts: `missingThumbs` asks which of a folder's rows no tile was
  ever drawn for, in one transaction, and `makeThumbs` makes those — a few
  frames at a time, and giving up when the caller has moved on.
- Library.tsx: the folder menu carries MAKE THUMBS, which reads the row's
  folder and what lies under it; and opening a folder asks for its own frames'
  tiles by itself, silently, in the background — the branch too when the
  screen is drawing the branch. A frame that lands after the ask is asked for
  again, which is why the frame count is a dependency of the effect.
- Library.tsx: a wall card carries the same five stars the stage does, under
  the picture, and rates the frame on the click. The click stops at the star,
  so scoring a frame is not picking it.

Verified in Chrome at 1440x900 against OPFS standing in for the disk, three
frames with one of them in a subfolder: opening the folder leaves two tiles
(the node's own frames) and MAKE THUMBS takes the roll to three, the frame in
the subfolder included; clearing the store and reloading brings the two back
on the open; the menu reads RESCAN... and MAKE THUMBS; and the wall's fourth
star lights four, writes star 4 to the catalogue row, and takes it back on the
second click. The same checks pass on the built bundle at :8090.
This commit is contained in:
2026-10-09 20:04:24 +07:00
parent 9ac197a595
commit 936414a3b6
4 changed files with 236 additions and 58 deletions
+4 -2
View File
@@ -248,12 +248,14 @@ export const en: Dict = {
'lib.rename': 'RENAME FOLDER',
'lib.renameAsk': 'Name shown for this folder (the folder on the disk is not renamed):',
'lib.update': 'UPDATE...',
'lib.rescan': 'RESCAN FROM THE TOP',
'lib.rescan': 'RESCAN...',
'lib.makeThumbs': 'MAKE THUMBS',
'lib.thumbsMade': 'Made {n} thumbnails for {folder}.',
'lib.resume': 'KEEP READING {folder}',
'lib.resumeHint': 'The last reading of this folder was cut off. Press to read it on from where it stopped.',
'lib.remove': 'REMOVE',
'lib.reconnect': 'GRANT ACCESS AGAIN',
'lib.nodeHint': 'Right-click to rename, update, rescan, collapse or remove the folder.',
'lib.nodeHint': 'Right-click to rename, update, rescan, make the missing thumbnails, collapse or remove the folder.',
'lib.collapseAll': 'COLLAPSE ALL',
'lib.collapse': 'COLLAPSE',
'lib.colHint': 'Right-click the empty part of this column to add a folder.',
+4 -2
View File
@@ -260,12 +260,14 @@ export const vi = {
'lib.rename': 'ĐỔI TÊN THƯ MỤC',
'lib.renameAsk': 'Tên hiển thị cho thư mục này (thư mục trên máy không bị đổi tên):',
'lib.update': 'CẬP NHẬT...',
'lib.rescan': 'QUÉT LẠI TỪ ĐẦU',
'lib.rescan': 'QUÉT LẠI...',
'lib.makeThumbs': 'TẠO ẢNH THU NHỎ',
'lib.thumbsMade': 'Đã tạo {n} ảnh thu nhỏ cho {folder}.',
'lib.resume': 'ĐỌC TIẾP {folder}',
'lib.resumeHint': 'Lượt đọc thư mục này bị cắt ngang. Bấm để đọc tiếp từ chỗ đã dừng.',
'lib.remove': 'BỎ',
'lib.reconnect': 'CẤP LẠI QUYỀN',
'lib.nodeHint': 'Chuột phải để đổi tên, cập nhật, quét lại, thu gọn hay bỏ thư mục.',
'lib.nodeHint': 'Chuột phải để đổi tên, cập nhật, quét lại, tạo ảnh thu nhỏ còn thiếu, thu gọn hay bỏ thư mục.',
'lib.collapseAll': 'THU GỌN TẤT CẢ',
'lib.collapse': 'THU GỌN',
'lib.colHint': 'Chuột phải vào vùng trống của cột này để thêm thư mục.',