Esposter

Room Settings

A Discord-style fullscreen settings dialog for a room, opened from the room list. Opening settings for a room other than the one being viewed navigates to that room first — the Roles and Members panels load and key their data (roles, members, permissions, selection) by the current room, so the dialog always targets the room whose data is live. Its information architecture matches Discord Server Settings: a two-level sidebar of category groups (v-list-group) whose items are the panels, with the first category headed by the room name itself and Delete kept as a standalone destructive item below the categories.

Categories and panels

SettingsCategoryMap owns the grouping; every SettingsType except Delete belongs to exactly one category (enforced by the map's co-located test).

CategoryPanelsGated panels (permission)
(room name)Overview · Roles · Profile
IntegrationsWebhooks
ModerationWord Filter · Audit Log · BansWord Filter + Audit Log (ManageRoom), Bans (BanMembers)
User ManagementMembers · Invites
(below the categories)Deleteowner-only inside its confirm dialog

Gating lives in SettingsPermissionMap — a panel with an entry is hidden from members lacking that RoomPermission; a category with no visible panels disappears entirely. Room owners bypass all checks via hasPermission.

Roles (previously a combined "Permissions" panel) edits roles and their permission bitfields; Members (previously a tab inside it) assigns/revokes member roles; Invites manages your invite link — the same manager component (Invite/Manager.vue) the header's Add Friends dialog uses.

How it works

flowchart LR
  Dialog["Settings/Dialog.vue<br/>(singleton, settingsRoomId)"] --> LeftSideBar["LeftSideBar.vue<br/>v-list-group per SettingsCategory"]
  Dialog --> Content["Content.vue<br/>Suspense + skeleton"]
  LeftSideBar -- "select SettingsType (closes drawer on mobile)" --> Content
  Content -- "SettingsContentMap[settingsType]" --> Panel["Type/*/Index.vue<br/>lazy async panel"]
  Content -- "mobile hamburger — open v-model" --> LeftSideBar
  LeftSideBar -- "SettingsPermissionMap gate" --> RBAC["useRoleStore.getMyPermissions"]

The dialog mirrors the user settings dialog conventions: panels are lazy defineAsyncComponents rendered in <Suspense :timeout="0"> with the shared MessageModelSettingsSkeleton fallback, and the active panel item in the open category group is highlighted by the generic StyledSlideIndicator rail (items carry data-slide-indicator-key). Unlike the user dialog there is no in-panel section scrollspy — room panels are single-view tools (tables and two-pane editors), so the second nav level selects panels, not scroll sections.

Mobile

The shared MessageModelSettingsLeftSideBar drawer is permanent only on desktop; on smAndDown (useVDisplay) it becomes a temporary overlay drawer, closed by default and opened by a mdi-menu hamburger the content header renders on mobile. Selecting any panel closes the drawer so the content takes the full width — the room dialog threads this open-state through the Dialog (open v-model on the sidebar, open:drawer emit from the content), and the user settings dialog does the same via isDrawerOpen on its dialog store. The two-pane panels that would otherwise sit side by side — Roles and Members (list column + editor column) — stack to a single column under the sm breakpoint (cols="12" sm="4" on the list column) so neither pane is squeezed.

Key files

FileRole
packages/app/app/models/message/room/SettingsType.tspanel enum (values double as titles)
packages/app/app/models/message/room/SettingsCategory.tssidebar category enum
packages/app/app/services/message/settings/SettingsCategoryMap.tscategory → panels grouping
packages/app/app/services/message/settings/SettingsListItemMap.tspanel icons/colors
packages/app/app/services/message/settings/SettingsContentMap.tspanel → lazy component
packages/app/app/services/message/settings/SettingsPermissionMap.tspanel → required RoomPermission
packages/app/app/components/Message/Model/Room/Settings/dialog + sidebar + Type/* panels
packages/app/app/components/Message/Model/Room/Invite/Manager.vueinvite-link manager shared with the Add Friends dialog