Skip to content

feat(desktop): nest channel sections one level deep - #8356

Draft
s-kikeriki wants to merge 1 commit into
block:mainfrom
s-kikeriki:feat/desktop-nested-channel-sections
Draft

s-kikeriki wants to merge 1 commit into
block:mainfrom
s-kikeriki:feat/desktop-nested-channel-sections

Conversation

@s-kikeriki

Copy link
Copy Markdown

What this adds

Sidebar sections are a flat list today. This lets a section hold other sections one
level down, each with their own channels, order and icon.

Closest existing issue: #5738 (the original custom sections request). No open issue or
PR asks for nesting specifically — I searched issues and PRs for "subsection", "nested
section" and sidebar section titles before starting. Happy to convert this to an issue
first if you would rather agree the direction before reviewing code.

How it works

  • A section carries a parent register in the existing kind 30078 lane, so nesting
    syncs across devices and survives a reinstall like the rest of the sidebar state.
    No new event kind.
  • The projection caps the tree at two levels and treats a parent that is missing,
    deleted, self-referential or already nested as "no parent". A corrupt document, or
    one written by a newer client, degrades to a flat list rather than hiding channels.
  • The legacy payload older clients read gains a parentId field. Clients that ignore
    it keep rendering every section flat, so this is additive on the wire.

UI

  • "New subsection..." on a top-level section, "Move out of subsection" on a nested
    one, both in the ⋮ menu and the header context menu.
  • Subsections indent under their parent, collapse with it, and roll their unread count
    and "Mark all as read" up into it.
  • "Move to section" lists subsections indented, with the parent spelled out in the
    accessible name.
  • Only top-level sections take part in drag reordering; a subsection reorders within
    its siblings.

Trade-offs

  • One level only. Two levels covers the grouping people ask for and keeps the
    projection rules small enough to reason about; arbitrary depth would need cycle
    handling on every read path.
  • Mobile renders the subsections flat for now. The payload carries the parent, so
    mobile can pick it up separately.

How to test manually

  1. Right-click a section header, "New subsection...", name it.
  2. Right-click a channel, "Move to section", pick the subsection.
  3. Collapse the parent and confirm the subsection and its channels collapse with it.
  4. Reload. The nesting is still there.
  5. "Move out of subsection" on the nested section returns it to the top level.

Tests

  • Projection rules: depth cap, cycles, orphan promotion, channel assignment.
  • Hook guards.
  • A Playwright spec that creates a subsection, moves a channel into it and reloads.

Deferred

Screenshot

"Clients" holds #random, with "Kalte Herberge" and "Schweizerhof" nested under it,
each with their own channels.

subsections-screenshot

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is b77ba862627c7362a4b863a0a077677d811a7558...97351870a66850fcc352f335600aea3cf7b27ce6.
A new review must complete for this exact range. When manual authorization
is required, a user with write access must comment exactly
@buzz-security-review 97351870a66850fcc352f335600aea3cf7b27ce6 to authorize a new review.
Any previous review applies only to its recorded range.

Sections in the sidebar were a flat list. This adds subsections: a section
can hold other sections one level down, with their own channels, order and
icons.

A section carries a `parent` register in the existing kind 30078 lane, so
nesting syncs across devices and survives a reinstall like the rest of the
sidebar state. The projection caps the tree at two levels and treats a
parent that is missing, deleted, self-referential or already nested as "no
parent", so a corrupt or newer-client document degrades to a flat list
instead of hiding channels. The legacy payload older clients read gains a
`parentId` field; clients that ignore it keep rendering the sections flat.

UI: "New subsection..." on a top-level section, "Move out of subsection" on
a nested one, both in the ⋮ menu and the header context menu. Subsections
indent under their parent, collapse with it, and roll their unread and
"Mark all as read" up into it. "Move to section" lists them indented, with
the parent spelled out in the accessible name. Only top-level sections take
part in drag reordering; a subsection reorders within its siblings.

Tests: projection rules (depth cap, cycles, orphan promotion, assignments),
hook guards, and a Playwright spec that creates a subsection, moves a
channel into it and reloads.

Signed-off-by: Support Kikeriki <support@kikeriki.net>
@s-kikeriki
s-kikeriki force-pushed the feat/desktop-nested-channel-sections branch from b5f254e to 9735187 Compare October 15, 2026 10:27

This branch has not been deployed

No deployments
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.

1 participant