feat(chat): raise the composer cap to the tier-2 larger-message capacity

The composer byte cap was 236 (one memo). With larger-messages tier 2 a body
can span up to 16 memo outputs in one tx, so kChatBodyMaxBytes rises to 4000
(a touch under the ~4063 protocol max so the composer never produces a body
compose would reject). The compose buffer grows to match, guarded by a
static_assert, and the emoji picker / byte gauge follow the single constant.
sendChatMessage now shows a specific "message too long" toast on a TooLong
compose instead of the generic compose-failed one (English string added; the
8 locales fall back until translated).

Broadcast is unchanged — both chatSendOutputs call sites already iterate the
N outputs. (Lite backend acceptance of >2 duplicate-address 0-value outputs is
the one bit needing a live smoke test, like the other lite broadcast paths.)

Larger-messages tiers 1-2 are now usable end to end on the full node.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 11:19:45 -05:00
co-authored by Claude Opus 4.8
parent 6b93a8ab60
commit 743e7f8b65
3 changed files with 13 additions and 7 deletions
+5 -3
View File
@@ -4660,9 +4660,11 @@ void App::sendChatMessage(const std::string& conversationId, const std::string&
}
chat::OutgoingChatMemos memos;
if (chat_service_.composeMessage(myReply, peerPubKey, peerZaddr, conversationId, text, memos)
!= chat::ChatComposeStatus::Ok) {
ui::Notifications::instance().error(TR("chat_toast_compose_failed"));
const auto composeStatus =
chat_service_.composeMessage(myReply, peerPubKey, peerZaddr, conversationId, text, memos);
if (composeStatus != chat::ChatComposeStatus::Ok) {
ui::Notifications::instance().error(TR(composeStatus == chat::ChatComposeStatus::TooLong
? "chat_toast_too_long" : "chat_toast_compose_failed"));
return;
}
chat::ChatMessage echo;
+7 -4
View File
@@ -63,15 +63,18 @@ int s_msgsel_head = 0; // drag-current byte offset
bool s_msgsel_dragging = false;
// Composer + new-conversation UI state.
char s_compose[512] = "";
char s_compose[4100] = ""; // must be >= kChatBodyMaxBytes + 1 (static_assert'd below)
std::string s_compose_cid; // the conversation s_compose is a draft for; draft is wiped when it changes
// Live byte offset of the composer's text caret, kept in sync by composeInputCallback while the composer
// is active (the callback only fires then). The emoji picker uses it to splice a glyph at the cursor
// instead of always appending. -1 = unknown/never-focused => append at the end.
int s_composeCursor = -1;
// On-chain chat body cap in bytes = (512 − len("utf8:"))/2 − secretstream ABYTES (see chat_outgoing.cpp).
// The composer hard-caps input to this; the emoji picker respects it too.
constexpr int kChatBodyMaxBytes = (512 - 5) / 2 - 17; // = 236
// On-chain chat body cap in bytes. Larger-messages tier 2 splits the ciphertext across up to
// kHushChatMaxMessageParts (16) memo outputs in one tx, so the body can be a few KB (protocol max ~4063:
// 16 × 255 cipher bytes − 17 secretstream tag). Kept a touch under that so the composer never produces a
// body that compose would reject as TooLong. The composer hard-caps input here; the emoji picker too.
constexpr int kChatBodyMaxBytes = 4000;
static_assert(sizeof(s_compose) >= kChatBodyMaxBytes + 1, "compose buffer too small for the body cap");
float s_composerAnimH = 0.0f; // animated composer-box height — grows with newlines, pushing the thread up
float s_composerTargetH = 0.0f; // target height measured in the composer block (wrapped content), consumed next frame
+1
View File
@@ -265,6 +265,7 @@ void I18n::loadBuiltinEnglish()
strings_["chat_toast_lite_busy"] = "A send is already in progress, or no wallet is open.";
strings_["chat_toast_waiting_reply"] = "Waiting for the contact to reply before you can message them.";
strings_["chat_toast_compose_failed"] = "Could not compose the message (too long?).";
strings_["chat_toast_too_long"] = "Message too long — shorten it and send again.";
strings_["chat_toast_request_compose_failed"] = "Could not compose the contact request (invalid address / text?).";
strings_["chat_toast_request_queued"] = "Contact request queued.";
strings_["chat_toast_need_funds"] = "Need a small shielded balance to send chat (to cover the fee).";