feat: add a setting to hide sub-pages in the sidebar - #8904
Conversation
Deeply nested page trees make the sidebar hard to scan, so offer an opt-in way to collapse the sidebar down to top-level pages only. The switch lives in Settings -> Workspace -> Sidebar and is persisted locally through AppearanceSettingsCubit, mirroring how the text scale factor is stored. Sub-pages remain reachable from their parent page, search and breadcrumbs. All three desktop sidebar entry points (folder sections, spaces and the shared section) read the setting and pass shouldRenderChildren down to ViewItem. When children are not rendered the expand/collapse chevron would be a no-op, so it falls back to a plain indent. Co-authored-by: Cursor <cursoragent@cursor.com>
Reviewer's GuideAdds an opt-in, locally persisted desktop setting that hides nested pages from the sidebar by propagating a shouldRenderChildren flag through folder, space, and shared page lists, while retaining access through other navigation paths and covering persistence and settings interactions with tests. Sequence diagram for toggling and applying the hidden sub-pages settingsequenceDiagram
actor User
participant Settings as SettingsWorkspaceView
participant Cubit as AppearanceSettingsCubit
participant Storage as KeyValueStorage
participant Sidebar as Sidebar views
participant Item as ViewItemDefaultLeftIcon
User->>Settings: Toggle HideSubPagesInSidebarSwitcher
Settings->>Cubit: setHideSubPagesInSidebar(value)
Cubit->>Storage: set(KVKeys.hideSubPagesInSidebar, value)
Cubit-->>Sidebar: state.hideSubPagesInSidebar
Sidebar->>Item: shouldRenderChildren = !hideSubPagesInSidebar
Item-->>Sidebar: Render children and chevron, or plain indent
State diagram for the locally persisted sidebar visibility preferencestateDiagram-v2
[*] --> DefaultOff: AppearanceSettingsCubit created
DefaultOff --> Loaded: readHideSubPagesInSidebar()
Loaded --> Hidden: stored value is true
Loaded --> Visible: stored value is false
Hidden --> Visible: setHideSubPagesInSidebar(false)
Visible --> Hidden: setHideSubPagesInSidebar(true)
Hidden --> Hidden: Persist KVKeys.hideSubPagesInSidebar
Visible --> Visible: Persist KVKeys.hideSubPagesInSidebar
File-Level Changes
Assessment against linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
🥷 Ninja i18n – 🛎️ Translations need to be updatedProject
|
| lint rule | new reports | level | link |
|---|---|---|---|
| Missing translation | 90 | warning | contribute (via Fink 🐦) |
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart" line_range="165-172" />
<code_context>
const SettingsCategorySpacer(),
+ SettingsCategory(
+ title: LocaleKeys.settings_workspacePage_sidebar_title.tr(),
+ children: const [HideSubPagesInSidebarSwitcher()],
+ ),
</code_context>
<issue_to_address>
**issue (bug_risk):** The new `LocaleKeys.settings_workspacePage_sidebar_title`, `LocaleKeys.settings_workspacePage_sidebar_hideSubPages`, and `LocaleKeys.settings_workspacePage_sidebar_hideSubPagesHint` references do not compile unless `generated/locale_keys.g.dart` is regenerated, but that generated file is absent from the diff. Dart reports undefined getters or identifiers for these constants.
**Suggested fix:** Regenerate and commit `lib/generated/locale_keys.g.dart`, or otherwise ensure the new translation keys are present before analysis and compilation.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| title: LocaleKeys.settings_workspacePage_sidebar_title.tr(), | ||
| children: const [HideSubPagesInSidebarSwitcher()], | ||
| ), | ||
| const SettingsCategorySpacer(), | ||
|
|
||
| SettingsCategory( | ||
| title: LocaleKeys.settings_workspacePage_dateTime_title.tr(), | ||
| children: [ |
There was a problem hiding this comment.
issue (bug_risk): The new LocaleKeys.settings_workspacePage_sidebar_title, LocaleKeys.settings_workspacePage_sidebar_hideSubPages, and LocaleKeys.settings_workspacePage_sidebar_hideSubPagesHint references do not compile unless generated/locale_keys.g.dart is regenerated, but that generated file is absent from the diff. Dart reports undefined getters or identifiers for these constants.
Suggested fix: Regenerate and commit lib/generated/locale_keys.g.dart, or otherwise ensure the new translation keys are present before analysis and compilation.
Feature Preview
No screen recording is attached: this was developed on a machine without a full Xcode install, so the macOS desktop app could not be built and run. The images below were rendered from the real
ViewItemandHideSubPagesInSidebarSwitcherwidgets through throwaway golden tests, which were removed again before committing.Sidebar, setting off (left, current behaviour) vs. on (right):
The new setting in Settings -> Workspace -> Sidebar:
fixes #8886
Summary
Deeply nested page trees make the sidebar hard to scan. This adds an opt-in switch that collapses the sidebar down to top-level pages only.
AppearanceSettingsCubit+KVKeys.hideSubPagesInSidebar, mirroring howtextScaleFactoris stored. No Rust or protobuf changes, and the value is deliberately not synced across devices.shouldRenderChildrendown toViewItem: folder sections (_section_folder.dart), spaces (sidebar_space.dart->SpacePages), and the shared section (shared_section.dart->SharedPageList).ViewItemDefaultLeftIconwould be a no-op, so it falls back to a plain indent.Sub-pages stay reachable from their parent page, from search, and from breadcrumbs.
Verification
Run on Flutter 3.27.4 against a locally built Rust backend:
flutter analyze- no issues foundflutter test --concurrency=1- 373 passed, 0 failedNew tests:
test/bloc_test/app_setting_test/appearance_test.dart- the setting defaults to off, is written to local storage, and is restored on relaunch.test/widget_test/hide_sub_pages_setting_test.dart- the switcher reflects the stored value and calls the cubit in both directions.Notes
SettingsWorkspaceViewis only reachable from the desktop settings dialog, and the toggle was not added to the mobile settings screens, soMobileViewItemand the mobile sidebar entry points are untouched and behave exactly as before. Happy to wire up mobile in a follow-up if you would like this on all platforms.shouldRenderChildren: false(favorites folder, favorite menu, move-page menu) all supply their ownleftIconBuilder, so theViewItemDefaultLeftIconchange does not reach them.SpacePagesin the move-page dialog keeps the defaultshouldRenderChildren: true, since that dialog needs the full tree to pick a destination.en-US.jsonis updated, following the usual translation workflow.PR Checklist
Made with Cursor
Summary by Sourcery
Add an opt-in desktop setting that limits the sidebar to top-level pages.
New Features:
Enhancements:
Tests: