From f466a25893663136a2435390dfb9d18fd56cf42b Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:16:55 +0200 Subject: [PATCH] [Client] Keep the message draft and notify when the recipient is offline (#7142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Client] Keep the message draft and notify when the recipient is offline * Don't blindly assume a user is online. --------- Co-authored-by: Lukas Brübach --- .../interface/widgets/tabs/tab_message.cpp | 31 ++++++++++++++++--- .../src/interface/widgets/tabs/tab_message.h | 7 +++-- .../interface/widgets/tabs/tab_supervisor.cpp | 4 ++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/cockatrice/src/interface/widgets/tabs/tab_message.cpp b/cockatrice/src/interface/widgets/tabs/tab_message.cpp index 9e9dbce1c..cee7da589 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_message.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_message.cpp @@ -23,9 +23,10 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User &_ownUserInfo, - const ServerInfo_User &_otherUserInfo) + const ServerInfo_User &_otherUserInfo, + bool _userOnline) : Tab(_tabSupervisor), client(_client), ownUserInfo(new ServerInfo_User(_ownUserInfo)), - otherUserInfo(new ServerInfo_User(_otherUserInfo)), userOnline(true) + otherUserInfo(new ServerInfo_User(_otherUserInfo)), userOnline(_userOnline) { chatView = new ChatView(tabSupervisor, 0, true); connect(chatView, &ChatView::showCardInfoPopup, this, &TabMessage::showCardInfoPopup); @@ -96,7 +97,14 @@ void TabMessage::closeEvent(QCloseEvent *event) void TabMessage::sendMessage() { - if (sayEdit->text().isEmpty() || !userOnline) { + if (sayEdit->text().isEmpty()) { + return; + } + + if (!userOnline) { + // Keep the draft: the user may be back momentarily, and the typed text + // should not be lost to a transient offline spell. + notifyUserOffline(); return; } @@ -105,17 +113,27 @@ void TabMessage::sendMessage() cmd.set_message(sayEdit->text().toStdString()); PendingCommand *pend = client->prepareSessionCommand(cmd); + pend->setExtraData(sayEdit->text()); connect(pend, &PendingCommand::finished, this, &TabMessage::messageSent); client->sendCommand(pend); sayEdit->clear(); } -void TabMessage::messageSent(const Response &response) +void TabMessage::messageSent(const Response &response, + const CommandContainer & /*commandContainer*/, + const QVariant &extraData) { if (response.response_code() == Response::RespInIgnoreList) { chatView->appendMessage(tr( "This user is ignoring you, they cannot see your messages in main chat and you cannot join their games.")); + } else if (response.response_code() == Response::RespNameNotFound) { + // The recipient went offline before the command reached the server: restore the draft. + userOnline = false; + if (sayEdit->text().isEmpty()) { + sayEdit->setText(extraData.toString()); + } + notifyUserOffline(); } } @@ -175,3 +193,8 @@ void TabMessage::processUserJoined(const ServerInfo_User &_userInfo) userOnline = true; *otherUserInfo = _userInfo; } + +void TabMessage::notifyUserOffline() +{ + chatView->appendMessage(tr("Message not sent — %1 is offline.").arg(QString::fromStdString(otherUserInfo->name()))); +} diff --git a/cockatrice/src/interface/widgets/tabs/tab_message.h b/cockatrice/src/interface/widgets/tabs/tab_message.h index 0472bb061..f7d15b4f6 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_message.h +++ b/cockatrice/src/interface/widgets/tabs/tab_message.h @@ -19,6 +19,7 @@ class LineEditUnfocusable; class Event_UserMessage; class Response; class ServerInfo_User; +class CommandContainer; class TabMessage : public Tab { @@ -39,7 +40,7 @@ signals: void maximizeClient(); private slots: void sendMessage(); - void messageSent(const Response &response); + void messageSent(const Response &response, const CommandContainer &commandContainer, const QVariant &extraData); void addMentionTag(QString mentionTag); void messageClicked(); @@ -50,7 +51,8 @@ public: TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User &_ownUserInfo, - const ServerInfo_User &_otherUserInfo); + const ServerInfo_User &_otherUserInfo, + bool _userOnline); ~TabMessage() override; void retranslateUi() override; void tabActivated() override; @@ -65,6 +67,7 @@ public: private: bool shouldShowSystemPopup(const Event_UserMessage &event); void showSystemPopup(const Event_UserMessage &event); + void notifyUserOffline(); }; #endif diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index 4100e124a..f72542832 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -904,8 +904,10 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus } ServerInfo_User otherUser; + bool userOnline = false; if (auto user = userListManager->getOnlineUser(receiverName)) { otherUser = ServerInfo_User(*user); + userOnline = true; } else { otherUser.set_name(receiverName.toStdString()); } @@ -919,7 +921,7 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus return tab; } - tab = new TabMessage(this, client, *userInfo, otherUser); + tab = new TabMessage(this, client, *userInfo, otherUser, userOnline); connect(tab, &TabMessage::talkClosing, this, &TabSupervisor::talkLeft); connect(tab, &TabMessage::maximizeClient, this, &TabSupervisor::maximizeMainWindow); myAddTab(tab);