fix(companion): reply to the right author in rooms (and keep nicks UTF-8)

A room is viewed through DM history, where each post is stored "Author:
text" and shown attributed to that author. The reply path, though, built
the @[nick] prefix from _sel_contact.name — the room server's own name —
so replying to someone's post in a room addressed the room, not the person.

New buildDmReplyPrefix() derives the addressee from the same author the
history shows (via dmDisplayParts): the post's author in a room, the
contact name in a 1:1 DM. It also stores the nick raw (UTF-8), like the
channel reply path, instead of running it through the lossy display
transliterator — the prefix is sent over the air verbatim, so a non-ASCII
nick was previously corrupted on the wire.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MarekZegare4
2026-06-28 12:27:16 +02:00
parent 7a5247d5d4
commit 31d602c88a

View File

@@ -258,6 +258,19 @@ class QuickMsgScreen : public UIScreen {
return true;
}
// Build "@[nick] " into _reply_prefix for a reply to a DM/room post, raw
// (UTF-8) so it goes out over the air intact — like buildChannelReplyPrefix,
// and unlike the old per-site code which ran the name through the lossy
// display transliterator. Addresses the same author the history shows
// (dmDisplayParts): in a room every post is stored "Author: text", so the
// addressee is that author, not the room server's own name (_sel_contact.name);
// a plain 1:1 DM uses the contact name. Caller ensures the post is incoming.
void buildDmReplyPrefix(const DmHistEntry& e) {
char nick[32];
dmDisplayParts(e, _sel_contact.type == ADV_TYPE_ROOM, _sel_contact.name, nick, sizeof(nick));
snprintf(_reply_prefix, sizeof(_reply_prefix), "@[%.31s] ", nick);
}
void startReply(bool to_channel) {
_sending_to_channel = to_channel;
_reply_mode = true;
@@ -1788,10 +1801,7 @@ public:
int ring_pos = dmHistEntryForContact(_sel_contact.id.pub_key, _dm_hist_sel);
if (ring_pos >= 0) {
bool reply_ok = !_dm_hist[ring_pos].outgoing;
if (reply_ok) {
char _tname[32]; DisplayDriver::translateUTF8Static(_tname, _sel_contact.name, sizeof(_tname));
snprintf(_reply_prefix, sizeof(_reply_prefix), "@[%.31s] ", _tname);
}
if (reply_ok) buildDmReplyPrefix(_dm_hist[ring_pos]);
buildFsMenu(_dm_hist[ring_pos].text, reply_ok);
}
}
@@ -1847,10 +1857,7 @@ public:
int ring_pos = dmHistEntryForContact(_sel_contact.id.pub_key, _dm_hist_sel);
if (ring_pos >= 0) {
bool reply_ok = !_dm_hist[ring_pos].outgoing;
if (reply_ok) {
char _tname[32]; DisplayDriver::translateUTF8Static(_tname, _sel_contact.name, sizeof(_tname));
snprintf(_reply_prefix, sizeof(_reply_prefix), "@[%.31s] ", _tname);
}
if (reply_ok) buildDmReplyPrefix(_dm_hist[ring_pos]);
buildFsMenu(_dm_hist[ring_pos].text, reply_ok);
}
return true;