Files
Mykhailo ShevchukandClaude Opus 5 b710cdcb17 GUI: a folder the file browser cannot read says so, instead of <Empty> with Up, Down and OK dead (#1212)
When file_browser could not open the directory it was pointed at, it said `<Empty>`,
three of its four keys stopped working for ever, and nothing was logged. Two bool returns
were discarded in the worker: browser_folder_init failed at storage_dir_open but folder_cb
ran anyway, so the view set list_loading and asked for a load; browser_folder_load_full
then failed the same way and sent neither list_load_cb nor the is_last item callback, so
list_loading was never cleared and file_browser_view_input_callback returned false for Up,
Down and OK on every press. Back was not consumed, so the screen could at least be left.
The user was told the folder was empty when the truth was that the card was gone.

Every load now ends with a last item, on every early exit of both load paths, so the view
always stops waiting. That also fixes the identical freeze in the Archive app, which gates
input on the same flag and clears it only on is_last, with no change in Archive and no new
ABI - it goes through callbacks Archive already implements. The chunked path had a third
dead exit nobody had noticed: the items_cnt != offset break when a folder loses entries
mid-load.

A new optional callback, file_browser_worker_set_folder_error_callback, lets the view draw
"Cannot read folder" instead of lying with `<Empty>`, and discard a row count that a failed
listing can never fill - without it the message was unreachable from the load paths, where
item_cnt came from a count that had succeeded, leaving rows of `---` that OK did nothing
on. The existing callback signatures are untouched, so third-party .faps are unaffected.
API 88.25 -> 88.26 for the new export.

Three more things in the same code:

- A read that died part way through a folder was indistinguishable from the end of one:
  storage_dir_read stops the same way for both, so a truncated listing was reported as a
  complete folder with nothing logged at any level. A 30-file folder failing at file 12
  looked like a clean 12-file folder, and the user would conclude files had been deleted.
  FSE_NOT_EXIST is the end of a folder; any other error after the loop means the rest was
  never seen.
- The failures are logged now, with the path and the FS error, at a level a release build
  shows, and the count pass is distinguished from the load pass. browser_folder_check_and_switch
  still falls back to the nearest readable ancestor for a missing folder, but it no longer
  does it silently.
- `<Empty>` was also drawn before the first scan landed, and input was live against that
  zero-item model, where an Up press left item_idx at -1 and fired a redundant re-read.
  file_browser_start raises the loading flag before the worker exists, since the worker
  queues its own first scan.

An unopenable folder no longer costs two storage_dir_open round trips either; the second
attempt was guaranteed to fail.

Not verified on hardware. Host build, lint and format are clean, SDKCHK reports API 88.26
up to date, a FAP builds against it, and the storage semantics the fix relies on were
traced through storage_ext.c, but none of the failure paths have been exercised on a
device. To check: open Apps, pull the SD card, navigate - expect "Cannot read folder" with
Up, Down and OK still alive, and `Cannot open <path>` in the log.

Left for a follow-up: the in-loop storage_file_get_error checks in the enumeration loops
are dead code, browser_folder_load_chunked and _full have return values no caller reads,
and the new FSE_NOT_EXIST predicate is the third hand-rolled copy in the tree
(desktop_settings_app.c has it character-for-character, plugin_manager.c a looser version),
so it probably belongs in storage.h.

Closes #1197

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-11-10 15:49:00 +02:00
..
2026-11-07 06:10:24 +03:00
2026-11-07 06:10:24 +03:00
2026-11-07 06:10:24 +03:00
2024-10-14 14:39:09 +01:00
fmt
2025-07-30 04:30:01 +03:00
2025-04-08 17:50:30 +03:00
fmt
2026-02-10 00:05:21 +03:00
2026-10-08 18:33:34 +03:00
2026-11-07 06:10:24 +03:00