AppFlowy-IO / AppFlowy-IO/AppFlowy-Web

[Bug] Sidebar spaces appear empty after switching workspace (expand state is global and pruned per workspace; reload fixes it)

Ouverte
#526 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
TypeScript
Étoiles
326
Forks
167
Merge moyen
17 h 6 min
PR mergées (30 j)
72

Description

**Describe the bug**

After switching to another workspace via the workspace switcher, the sidebar shows the spaces (e.g. "General", "Shared") but **no pages underneath**. The space looks empty. A browser reload (F5) makes the pages appear. Clicking on the space name after the switch also shows them.

So the pages are there – the space is simply **collapsed**, and a collapsed space is visually indistinguishable from an empty one. Users who work on the mobile app and then open the web app to continue editing conclude that their pages did not sync (that is what happened to me for weeks).

Two things combine to cause this:

1. **The sidebar expand state is one global localStorage entry for all workspaces and gets wiped on every workspace switch.**
`src/components/_shared/outline/utils.ts:181` stores expanded view ids in a single key `outline_expanded`, not scoped by workspace.
`src/components/app/outline/Outline.tsx:351-400` (the "validate restored expanded IDs" effect) then checks every restored id against the *current* workspace via `GET /api/workspace//views?depth=1&view_ids=…`. Ids that belong to another workspace obviously come back empty and are treated as stale → `setOutlineExpands(id, false)` deletes them from localStorage.
Net effect: visiting workspace A erases the expand state of workspaces B, C, D… With several workspaces, the target workspace's spaces are therefore practically always collapsed after a switch.

2. **After a switch, nothing auto-expands the space that contains the selected page.**
The switch navigates to the workspace's last-opened page. That page is already contained in the deep outline (`/view/?depth=6`), so the navigation-hydration effect in `Outline.tsx:155` (`if (findView(outline, selectedViewId)) return;`) does not run and the ancestors are never expanded.
On a full reload the same effect fires while the outline is still `[]` (truthy), calls `/view//navigation?depth=0`, receives the ancestor ids and expands the space – which is why F5 "fixes" it.

**To Reproduce**

1. Self-hosted AppFlowy Cloud (docker compose, all images `:latest`, `appflowy_web` build 0.17.1 / image created 2026-08-31; behaviour identical to current `main`), account with several workspaces, each with pages under "General"
2. Open workspace A in the browser, expand "General" (pages visible)
3. Switch to workspace B via the switcher → "General" shows without any pages
4. Press F5 → pages appear (or click on "General" → pages appear)
5. Switch back to A → "General" is collapsed again, although it was expanded in step 2

Server-side evidence from the nginx access log for step 3 (workspace ids shortened):

```
PUT /api/workspace/B/open
GET /api/workspace/B/view/B?depth=6 200 6088 <- full outline incl. pages
GET /api/workspace/B/views?depth=1&view_ids= 200 76 <- validating A's expanded space in B → empty → pruned
(no /navigation request)
```
and for the reload in step 4:
```
GET /api/workspace/B/view//navigation?depth=0 200 4849 <- ancestors → space expanded
GET /api/workspace/B/view/?depth=1 200 4868
```

**Expected behavior**

- Expand state should be scoped per workspace (e.g. `outline_expanded_`), or the pruning should only remove ids that belonged to the current workspace.
- After switching workspaces the space containing the selected page should be expanded (same behaviour as after a reload).
- A collapsed space with children should be distinguishable from an empty one (chevron / count / placeholder).

**Environment**

- Self-hosted, Docker Compose, `:latest` tags (appflowy_cloud, appflowy_web, gotrue, admin_frontend, appflowy_worker, ai, appflowy_search), Raspberry Pi ARM64, accessed via Tailscale (HTTPS)
- Browsers: Firefox and Vivaldi (both affected)
- Related: #444 (workspace switcher hides workspaces beyond the 4th) – together these two make the web app look like it is not syncing when it actually is.

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.