[Client] Tabbed room channels with unread states and collapsible chat (#7478)

* [Client] Add room channel selector with per-channel chat views

* [Client] Tabbed room channels with unread states, collapse, read-only, banners

Reworks the room chat channel display: channels move out of the combobox
into a tab bar below the message input showing every channel available
to the user.

- Each tab shows its unread message count and is tinted when it holds
  unreads or a mention; both colors are user-configurable chat settings
  (channelUnreadColor, channelMentionColor) with a settings-page section.
- Clicking the active tab collapses the chat: message view and input
  hide and the splitter section minimizes to the tab strip; expanding
  restores the previous splitter sizes. Viewing a channel clears its
  unread state.
- Channels the user may read but not write (per write_access_level)
  show with the message input disabled and a read-only placeholder;
  sends are guarded locally, the server still enforces.
- Channel banner_message strings render at the top of their channel
  view on join, like the room join message on Main.
- Replayed channel history no longer inflates unread counts; moderation
  redaction now applies across all channel views.

* Fixup: keep chat tab bar visible when chat is collapsed

QSplitter children are collapsible by default, so setSizes({1, 0})
hid the whole chat group box including the channel tab bar.
Mark the chat widget non-collapsible so collapsing clamps to its
minimum size (title + tab bar) instead.

* [Room] Explicitly initialize MAIN_CHANNEL per review

* [Room] Address channel tab review follow-ups

- gate @all mentions on moderator/admin sender to match ChatView,
  whole-word matching for own name and highlight words
- hide single-channel tab bar so old servers do not show a lone Main
  tab that collapses chat on misclick
- capture target ChatView in sendMessage so errors land in the
  channel the message was sent from
- share ignore/unregistered filtering between RoomSay and
  RoomChannelSay via isRoomMessageIgnored

* [Client] Fix tab_room.cpp formatting per clang-format-18

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: BruebachL <bruebachl@cockatrice.example>
This commit is contained in:
BruebachL 2026-10-16 22:46:39 +02:00 • committed by GitHub
parent 05dcde69db
commit c99113ab0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 543 additions and 38 deletions

View file

@ -31,6 +31,16 @@ QString ChatSettings::getChatHighlightColor() const
return getValue("highlightColor", QString(), QString(), "A6120D").toString();
}
QString ChatSettings::getChannelUnreadColor() const
{
return getValue("channelUnreadColor", QString(), QString(), "1A7B00").toString();
}
QString ChatSettings::getChannelMentionColor() const
{
return getValue("channelMentionColor", QString(), QString(), "A6120D").toString();
}
bool ChatSettings::getChatMentionForeground() const
{
return getValue("mentionForeground", QString(), QString(), true).toBool();
@ -107,6 +117,16 @@ void ChatSettings::setChatHighlightColor(const QString &_chatHighlightColor)
setValue(_chatHighlightColor, "highlightColor");
}
void ChatSettings::setChannelUnreadColor(const QString &_channelUnreadColor)
{
setValue(_channelUnreadColor, "channelUnreadColor");
}
void ChatSettings::setChannelMentionColor(const QString &_channelMentionColor)
{
setValue(_channelMentionColor, "channelMentionColor");
}
void ChatSettings::setChatMentionForeground(bool _chatMentionForeground)
{
setValue(_chatMentionForeground, "mentionForeground");

View file

@ -19,6 +19,8 @@ public:
[[nodiscard]] bool getChatMentionCompleter() const override;
[[nodiscard]] QString getChatMentionColor() const override;
[[nodiscard]] QString getChatHighlightColor() const override;
[[nodiscard]] QString getChannelUnreadColor() const override;
[[nodiscard]] QString getChannelMentionColor() const override;
[[nodiscard]] bool getChatMentionForeground() const override;
[[nodiscard]] bool getChatHighlightForeground() const override;
[[nodiscard]] bool getIgnoreUnregisteredUsers() const override;
@ -35,6 +37,8 @@ public:
void setChatMentionCompleter(bool _chatMentionCompleter);
void setChatMentionColor(const QString &_chatMentionColor);
void setChatHighlightColor(const QString &_chatHighlightColor);
void setChannelUnreadColor(const QString &_channelUnreadColor);
void setChannelMentionColor(const QString &_channelMentionColor);
void setChatMentionForeground(bool _chatMentionForeground);
void setChatHighlightForeground(bool _chatHighlightForeground);
void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers);