fix(mobile): cache app list on cold boot and surface load failures (#1222) - #3499
Open
ptlnextdoor wants to merge 1 commit into
Open
fix(mobile): cache app list on cold boot and surface load failures (#1222)#3499ptlnextdoor wants to merge 1 commit into
ptlnextdoor wants to merge 1 commit into
Conversation
…entra-Community#1222) The home screen's app grid started from an empty apps=[] with no loading/error signal: on cold boot it rendered an empty grid for however long AppRegistry.getInstalledMiniapps() took, and a failed first refresh() left it empty forever with a full app reboot as the only recovery. - apps store: persist the last-known app list (JSON, stripped of the onStart/onStop closures) and hydrate from it on cold boot instead of []. Adds initialized/loading/refreshError state so the host can distinguish "still loading" from "confirmed empty". - Extracts the fetch -> project -> cache -> error-capture sequence into appsRefresh.ts as an injected-callback pure function, so it's unit testable without booting the store's full singleton graph (AppRegistry, MiniappLauncher, MiniappRunningRegistry, ...). - home.tsx: passes showPlaceholders to the skeleton while the first refresh is in flight, and shows a Retry button when a refresh fails with nothing to show. Test plan: - bun test src (mobile/modules/engine): 274 pass, 0 fail - npx tsc --noEmit: clean - Manually reasoned through the refresh() error path (getInstalledMiniapps currently never rejects, so the try/catch in appsRefresh.ts is defensive for future callers / a throwing projectApps())
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem (#1222)
On cold boot, the home screen's app grid starts from
apps: []in the engine'suseAppStatusStore, with no signal for "still loading" vs. "confirmed empty" —AppsGridon the home screen isn't passedshowPlaceholders, so it renders an empty grid for however longAppRegistry.getInstalledMiniapps()'s disk scan takes. And if that firstrefresh()throws, the store had no error state at all — the user is left staring at an empty grid, with a full app reboot as the only known recovery (per the issue).Changes
mobile/modules/engine/src/stores/apps.tsonStart/onStopclosures don't survive serialization, which is fine — a cached snapshot only shows briefly before the first liverefresh()replaces it) and hydratesappsfrom it at store creation instead of starting from[].initialized/loading/refreshErrorstate so hosts can distinguish "still loading" from "confirmed empty", and expose it via newuseAppsInitialized/useAppsLoading/useAppsRefreshErrorhooks.mobile/modules/engine/src/stores/appsRefresh.ts(new)create()callback intorunAppsRefresh, a pure function taking the two effects (getInstalledApps,project) and the cache-save callback as arguments. This makes the actual state-transition logic (success/failure, error-message extraction, never leavingloadingstuck) unit-testable without booting the store's full singleton graph (AppRegistry,MiniappLauncher,MiniappRunningRegistry,STTModelManager, ...) — see test plan below for why that matters.mobile/src/app/home.tsxshowPlaceholders={!appsInitialized}toAppsGridso the existing skeleton (already used elsewhere, e.g.AllAppsGridSheet) covers the "still loading" window instead of an empty grid.AppsLoadRetryview (reusing the existingButton/Textprimitives) shown when a refresh fails with nothing to show, calling the existingrefreshApps()— no reboot needed to recover.mobile/src/i18n/en.ts: two new strings (home:appsLoadFailed,home:appsLoadRetry).Test plan
bun test src(frommobile/modules/engine): 274 pass, 0 fail (270 pre-existing + 4 new forrunAppsRefresh)npx tsc --noEmit(frommobile): cleaneslint . --fix: no new errors/warnings introduced by these files (verified diff-scoped)useAppsRefreshErrorset +apps.length === 0rendersAppsLoadRetry, and itsonPresscalls the samerefreshApps()used by the existing focus-effect refreshNote on
runAppsRefresh's try/catch:AppRegistry.getInstalledMiniapps()currently catches its own errors internally and never rejects, so the catch path is defensive (a throwingprojectApps(), or future callers ofrunAppsRefreshthat do reject) rather than reachable today — the test suite covers both the fetch-throws and project-throws cases regardless.I didn't have a physical device to test the cold-boot skeleton/retry visually against — happy to iterate on it if the actual UI doesn't match expectations.
Summary by cubic
Fixes the empty home grid on cold boot and silent app-load failures. Caches the last app list, shows placeholders until the first refresh finishes, and surfaces a retry on error (addresses #1222).
Bug Fixes
useAppsInitialized,useAppsLoading,useAppsRefreshError(exported by@mentra/engine).showPlaceholders={!appsInitialized}toAppsGridand shows a retry UI when a refresh fails and there are no apps.home:appsLoadFailed,home:appsLoadRetry.Refactors
runAppsRefresh(getInstalledApps, project, saveCache)for clearer state handling and testability; errors are captured, not thrown.Written for commit 0835671. Summary will update on new commits.