Skip to content

feat: add a setting to hide sub-pages in the sidebar - #8904

Open
lurui1997 wants to merge 1 commit into
AppFlowy-IO:mainfrom
lurui1997:codex/issue-8886
Open

feat: add a setting to hide sub-pages in the sidebar#8904
lurui1997 wants to merge 1 commit into
AppFlowy-IO:mainfrom
lurui1997:codex/issue-8886

Conversation

@lurui1997

@lurui1997 lurui1997 commented Jul 30, 2026

Copy link
Copy Markdown

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 ViewItem and HideSubPagesInSidebarSwitcher widgets through throwaway golden tests, which were removed again before committing.

Sidebar, setting off (left, current behaviour) vs. on (right):

Sidebar with sub-pages shown versus hidden

The new setting in Settings -> Workspace -> Sidebar:

Hide sub-pages 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.

  • New toggle in Settings -> Workspace -> Sidebar, off by default, so nothing changes unless a user asks for it.
  • Persisted locally via AppearanceSettingsCubit + KVKeys.hideSubPagesInSidebar, mirroring how textScaleFactor is stored. No Rust or protobuf changes, and the value is deliberately not synced across devices.
  • All three desktop sidebar entry points read the setting and pass shouldRenderChildren down to ViewItem: folder sections (_section_folder.dart), spaces (sidebar_space.dart -> SpacePages), and the shared section (shared_section.dart -> SharedPageList).
  • When children are not rendered, the expand/collapse chevron in ViewItemDefaultLeftIcon would 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 found
  • flutter test --concurrency=1 - 373 passed, 0 failed

New 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

  • Mobile is out of scope. SettingsWorkspaceView is only reachable from the desktop settings dialog, and the toggle was not added to the mobile settings screens, so MobileViewItem and 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.
  • Manual QA not run: no desktop app run, for the reason given above. Behaviour was verified at the widget level instead.
  • Existing callers that already pass shouldRenderChildren: false (favorites folder, favorite menu, move-page menu) all supply their own leftIconBuilder, so the ViewItemDefaultLeftIcon change does not reach them.
  • SpacePages in the move-page dialog keeps the default shouldRenderChildren: true, since that dialog needs the full tree to pick a destination.
  • Only en-US.json is updated, following the usual translation workflow.
  • With the setting on, a newly created sub-page will not appear in the sidebar. That is inherent to the feature, but worth a maintainer's opinion on whether it deserves a hint in the UI.

PR Checklist

  • My code adheres to AppFlowy's Conventions
  • I've listed at least one issue that this PR fixes in the description above.
  • I've added a test(s) to validate changes in this PR, or this PR only contains semantic changes.
  • All existing tests are passing.

Made with Cursor

Summary by Sourcery

Add an opt-in desktop setting that limits the sidebar to top-level pages.

New Features:

  • Add a desktop workspace setting to hide nested pages from the sidebar while keeping them accessible through other navigation paths.

Enhancements:

  • Propagate the sidebar visibility preference across folder, space, and shared-page navigation components and suppress inactive expand/collapse indicators when children are hidden.
  • Persist the preference in local storage with an opt-in default and restore it when the application starts.

Tests:

  • Add coverage for the setting's default value, local persistence, restoration, and toggle interactions.

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>
@CLAassistant

CLAassistant commented Jul 30, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@sourcery-ai

sourcery-ai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds 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 setting

sequenceDiagram
    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
Loading

State diagram for the locally persisted sidebar visibility preference

stateDiagram-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
Loading

File-Level Changes

Change Details Files
Added a persisted desktop appearance preference and settings UI for hiding nested sidebar pages.
  • Introduced a local key and default-off appearance state field.
  • Loaded and saved the preference through local key-value storage without syncing it.
  • Added the Workspace > Sidebar toggle and localized its label and hint.
frontend/appflowy_flutter/lib/core/config/kv_keys.dart
frontend/appflowy_flutter/lib/workspace/application/settings/appearance/appearance_cubit.dart
frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart
frontend/resources/translations/en-US.json
Propagated the preference through all desktop sidebar page-list entry points to suppress nested page rendering.
  • Read the appearance setting in folder, space, and shared sidebar sections.
  • Added shouldRenderChildren parameters to shared and space page list widgets.
  • Passed the flag into ViewItem instances while preserving full-tree behavior for callers that omit it.
frontend/appflowy_flutter/lib/features/shared_section/presentation/shared_section.dart
frontend/appflowy_flutter/lib/features/shared_section/presentation/widgets/shared_page_list.dart
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/folder/_section_folder.dart
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space.dart
Updated view-item affordances so hidden children do not expose an ineffective expand/collapse control.
  • Forwarded shouldRenderChildren through the view-item widget hierarchy.
  • Replaced the default expand/collapse icon with indentation when child rendering is disabled.
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart
Added coverage for preference persistence and toggle behavior.
  • Verified the default value, local storage write, and restoration on cubit initialization.
  • Verified the settings switch reflects state and invokes the cubit in both directions.
frontend/appflowy_flutter/test/bloc_test/app_setting_test/appearance_test.dart
frontend/appflowy_flutter/test/widget_test/hide_sub_pages_setting_test.dart

Assessment against linked issues

Issue Objective Addressed Explanation
#8886 Provide a user-accessible setting to hide nested sub-pages from the desktop left sidebar while keeping the existing behavior as the default.
#8886 Persist the hide-sub-pages preference locally and restore it across application launches.
#8886 Apply the setting consistently to the desktop sidebar's page, folder, space, and shared-page navigation trees, removing ineffective expand/collapse controls when children are hidden.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

Copy link
Copy Markdown

🥷 Ninja i18n – 🛎️ Translations need to be updated

Project /project.inlang

lint rule new reports level link
Missing translation 90 warning contribute (via Fink 🐦)

@lurui1997
lurui1997 marked this pull request as ready for review August 31, 2026 03:50

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +165 to 172
title: LocaleKeys.settings_workspacePage_sidebar_title.tr(),
children: const [HideSubPagesInSidebarSwitcher()],
),
const SettingsCategorySpacer(),

SettingsCategory(
title: LocaleKeys.settings_workspacePage_dateTime_title.tr(),
children: [

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR] Option to hide sub-pages from left sidebar navigation tree

2 participants