Commit f1e7834
Fix startup project projection initialization (#1962)
* Fix startup project projection initialization
* Add default startup projection setting
* style: auto-format (ruff + oxfmt) [pre-commit.ci]
* Offer the startup projection setting in the browser build
- Ungate the Settings → Startup section for non-Tauri builds and add a
Startup Settings entry to the settings dropdown. Only the three project
restoration modes are desktop-only (the browser has no persistent local
file to reopen); the empty-workspace projection preference applies
everywhere, so hide the mode radios rather than the whole section.
- `useStartupProject` no longer bails out early on the web: it resolves a
startup path only under Tauri, but still applies the configured
empty-workspace projection before mounting the shell.
- Persist a GlobeControl toggle from a click on the control itself instead
of MapLibre's `projectiontransition` event. Style initialization and
project reconciliation emit that event too, so a stale one could
overwrite the projection of a project that had just loaded.
- Update the Startup docs to match.
* Address review feedback
- Bound the startup restore gate. `openRecentProjectFile` and the XYZ
probes have no deadline of their own, so a startup project whose tile
host black-holes the connection left the window blank forever with no
way to reach Settings. A 10s watchdog now mounts the shell over the
default workspace; the restore keeps running and can still land, guarded
by the existing `projectGeneration`/`isDirty` check.
- Render a spinner and "Opening your startup project…" while the gate is
up, instead of nothing at all, so a slow restore does not read as a hang.
- Extract `hasExplicitLaunchPayload()` so the deep-link/`?data=`
precedence check has one definition instead of a verbatim copy in both
the `restoring` initializer and the effect, which could silently drift.
- Preserve `globeByDefault` when a pinned startup project turns out to be
missing. Resetting the whole block to `DEFAULT_STARTUP_SETTINGS` flipped
a saved Mercator preference back to globe on the next launch; only the
project selection should be cleared.
- Refresh the stale "the shell is interactive throughout" comment: the
shell is now unmounted until the gate expires.
- Backfill the required `globeByDefault` field on every `StartupSettings`
literal in tests/startup-project-settings.test.ts and the shared
fixture in tests/startup-project-snapshot.test.ts.
* Address CodeRabbit review feedback
- Guard the failure path's `openDefaultWorkspace()` with the same
`projectGeneration`/`isDirty` ownership test the success path already
uses. Once the restore gate added in 3b7a26d expires the shell is live,
so a restore that fails after that could reset the projection of a
workspace the user had since opened or edited, and show a banner
claiming the default workspace was opened for them. The
`forgetRecentProject` and stale-preference cleanups stay unconditional:
a project file that is gone stays gone whoever owns the workspace now.
* Address Claude review feedback
- Extract the GlobeControl class-name mirror into
`packages/map/src/globe-control-toggle.ts` and pin it with
`tests/globe-control-toggle.test.ts`, which builds a real
`maplibre-gl` `GlobeControl` and asserts the selector still matches its
button in both projections. These classes are internal and unexported,
so a rename would otherwise have stopped persisting the user's
projection with no build error. Added to CLAUDE.md's recheck-on-bump
list next to the other internal-class mirrors, and noted in the handler
why reading `getProjection()` on the bubbled click is not stale (the
control's own listener runs first and `setProjection` is synchronous).
- Stop showing the restore spinner on launches with nothing to restore.
`restoring` started `true` for every build, so the browser and the
Jupyter embed unmounted the shell and flashed "Opening your startup
project…" on every load even though they never restore a project. The
decision now lives in one pure `planStartup()` in `lib/startup-project.ts`
(payload / restore / default), which the render-time gate and the
restore effect both call, so they cannot drift. The empty-workspace
projection is seeded during the first render rather than from an effect,
because MapCanvas creates the map in its own mount effect, which runs
before this component's — so the shell no longer has to be unmounted to
avoid the globe flash. Desktop launches in default mode also mount
immediately now.
- `planStartup` is covered in `tests/startup-project-settings.test.ts`:
payload precedence, desktop restore, the non-desktop case honoring the
projection but never restoring, and the empty-workspace fallback.
- Note explicitly why the gate-timeout callback omits the
`projectGeneration`/`isDirty` ownership check the other two paths have:
the shell is unmounted while the gate is up, so there is nothing to
overwrite. Rendering anything interactive behind the spinner would break
that invariant.
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>1 parent 1a35006 commit f1e7834
14 files changed
Lines changed: 519 additions & 64 deletions
File tree
- apps/geolibre-desktop/src
- components/layout
- hooks
- i18n/locales
- lib
- docs
- user-guide
- packages/map/src
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| 134 | + | |
134 | 135 | | |
135 | 136 | | |
136 | 137 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
29 | 30 | | |
30 | 31 | | |
31 | 32 | | |
32 | | - | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
51 | | - | |
| 52 | + | |
| 53 | + | |
52 | 54 | | |
53 | 55 | | |
54 | 56 | | |
| |||
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
71 | 89 | | |
72 | 90 | | |
73 | 91 | | |
| |||
Lines changed: 28 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
456 | 456 | | |
457 | 457 | | |
458 | 458 | | |
459 | | - | |
460 | 459 | | |
461 | 460 | | |
462 | 461 | | |
| |||
1504 | 1503 | | |
1505 | 1504 | | |
1506 | 1505 | | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
| 1513 | + | |
| 1514 | + | |
| 1515 | + | |
| 1516 | + | |
1507 | 1517 | | |
1508 | 1518 | | |
1509 | 1519 | | |
| |||
2542 | 2552 | | |
2543 | 2553 | | |
2544 | 2554 | | |
2545 | | - | |
| 2555 | + | |
2546 | 2556 | | |
2547 | 2557 | | |
2548 | 2558 | | |
| |||
2590 | 2600 | | |
2591 | 2601 | | |
2592 | 2602 | | |
| 2603 | + | |
| 2604 | + | |
| 2605 | + | |
| 2606 | + | |
| 2607 | + | |
| 2608 | + | |
| 2609 | + | |
| 2610 | + | |
| 2611 | + | |
| 2612 | + | |
| 2613 | + | |
| 2614 | + | |
| 2615 | + | |
| 2616 | + | |
| 2617 | + | |
| 2618 | + | |
2593 | 2619 | | |
2594 | 2620 | | |
2595 | 2621 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
| 97 | + | |
96 | 98 | | |
97 | 99 | | |
98 | 100 | | |
| |||
200 | 202 | | |
201 | 203 | | |
202 | 204 | | |
| 205 | + | |
203 | 206 | | |
204 | 207 | | |
205 | 208 | | |
| |||
279 | 282 | | |
280 | 283 | | |
281 | 284 | | |
| 285 | + | |
282 | 286 | | |
283 | 287 | | |
284 | 288 | | |
| |||
0 commit comments