# Sub-rooms — handoff ## Summary Sub-rooms let a parent room own an ordered list of child rooms, displayed nested in the home channel list and manageable in room settings. Hierarchy is stored in Matrix room state (`im.paarrot.sub_rooms`), not only `m.space.child`, so channels can nest under a room without full space semantics. ## User-facing behavior - Nested channels under a room in **Home** sidebar (indented tree) - **Add Sub-Room** from room nav context menu (requires power level on `im.paarrot.sub_rooms`) - **Room settings → Sub-rooms** to reorder/remove children - Creating a sub-room from parent updates parent's `children` array - Unjoined sub-rooms show as `UnjoinedSubRoomItem` with join affordance ## Architecture ``` Room state: im.paarrot.sub_rooms { children: string[] } → useRoomSubRooms hook → Home.tsx flatten tree (addRoomAndSubRooms) → RoomNavItem "Add Sub-Room" → CreateRoomModal → SubRooms.tsx settings editor → SpaceHierarchy.tsx (lobby) reads same state ``` ## Key files | Path | Role | |------|------| | `cinny/src/app/hooks/useRoomSubRooms.ts` | Hook + `PaarrotSubRoomsContent` type | | `cinny/src/types/matrix/room.ts` | `StateEvent.PaarrotSubRooms` | | `cinny/src/app/pages/client/home/Home.tsx` | Renders nested list | | `cinny/src/app/features/room-nav/RoomNavItem.tsx` | Add sub-room action | | `cinny/src/app/features/room-nav/UnjoinedSubRoomItem.tsx` | Unjoined child UI | | `cinny/src/app/features/room-settings/sub-rooms/SubRooms.tsx` | Settings page | | `cinny/src/app/features/create-room/CreateRoomModal.tsx` | Appends new room to parent state | | `cinny/src/app/features/lobby/SpaceHierarchy.tsx` | Lobby hierarchy integration | ## Data model | Event | State key | Content | |-------|-----------|---------| | `im.paarrot.sub_rooms` | `""` (empty) | `{ children: string[] }` — room IDs in display order | Power levels: treat like other state events; editors need `state_default` or explicit level for `im.paarrot.sub_rooms`. ## Dependencies - `matrix-js-sdk` state events - Parent room must exist and user must have permission to send state ## Integration points - **Home navigation**: primary consumer of tree flattening - **Lobby/forums**: `SpaceHierarchy` reads sub-rooms for display - **Create room flow**: auto-updates parent on sub-room create - Distinct from **m.space.child** space hierarchy (may coexist) ## Testing ### Manual 1. In a room where you have admin, add sub-room from nav menu. 2. Verify child appears indented under parent in Home. 3. Reorder in Room settings → Sub-rooms. 4. Leave child room; verify unjoined state UI. 5. Check lobby view shows hierarchy when applicable. ### Automated - None ## Known issues & gotchas - Only **joined** sub-rooms appear in home tree; unjoined listed separately - Top-level filter: rooms that appear in any parent's `children` are excluded from root list - Creating sub-room sends state event on **parent** — failure leaves orphan room - `StateEvent.PaarrotSubRooms as any` casts in sendStateEvent — typing debt ## Future work - Sync with `m.space.child` for federation-friendly hierarchy - Drag-and-drop reorder in nav (DnD exists in lobby, not necessarily sub-rooms settings) - Depth limits / circular reference guards ## Related docs - [lobby-forums HANDOFF](../lobby-forums/HANDOFF.md) ## Add your extra things here - Interface: `PaarrotSubRoomsContent { children: string[] }` in `useRoomSubRooms.ts` - Permission check pattern: `permissions.stateEvent(StateEvent.PaarrotSubRooms, userId)`