mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2026-09-02 11:23:50 +00:00
* Loader: show the loading animation while an app's .fap is read Launching an app drew nothing while the loader read and relocated its ELF off the SD card, so the screen sat on the previous view looking like the press had been ignored. NFC is the worst case - at 327 KB it is 2.5x the next largest main-menu app - and a cold or fragmented card stretches it to seconds, which is why it seems intermittent. The animation was never missing, only unused here. loader_applications.c already raises it around a launch from the Apps browser, and loader_do_deferred_launch() around a chained one; what had none was loader_do_start_by_name(), which every other entry point funnels through - main menu, archive browser, desktop favourites and hold-buttons, RPC and autorun - while loader_start_external_app() blocked the loader thread in flipper_application_preload() and _map_to_memory(). Scoped to the .fap branch rather than the whole function: that storage_file_exists test is the first point that knows the launch will touch the SD card at all. Internal apps resolve above it and start in microseconds, so covering them would only flash the hourglass for a frame. It also brackets the API-mismatch retry as a single span, which bracketing inside loader_start_external_app() would have split into two. Launches nest - loader_do_deferred_launch() calls loader_do_start_by_name(), and re-enters itself once per queued app on failure, up to LOADER_QUEUE_MAX_SIZE deep - so show/hide is refcounted. Without it the inner hide would tear the backdrop down mid-chain, which is the gap the deferred site exists to cover. Both callers now go through the same pair, which also drops the stop/start the old code inflicted on the animation at every link of a retry chain. The counter follows furi_hal_power_insomnia_enter/exit: guarded at both ends, bare furi_check so it survives release builds, where an unbalanced hide would otherwise wrap to 255 and strand a fullscreen view that swallows all input. send_to_front is load-bearing and runs on every show, not once at attach: launched apps and the Apps browser add their viewports above ours, and gui_view_port_find_enabled() takes the last one added. Error dialogs raised from inside the load still render on top - dialogs allocate a fresh ViewHolder per message and gui_add_view_port() pushes to front - so the API-mismatch prompt is not covered by the view we sent to front first. Two things left uncovered on purpose. The desktop's DesktopGlobalBeforeAppStarted handshake runs above the internal/external split and is budgeted at 3 s (desktop.c), so reaching it would mean showing the hourglass for internal apps too. And the hide fires when the app thread starts, not when it paints; closing that needs a GUI "viewport drawn" signal that does not exist, and the deferred path has always had the same shape. Closes #1100 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * CHANGELOG: loader loading animation Closes #1100 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>