Migrate message forwarding to backend REST endpoint

Both real mobile clients (iOS, Android) forward messages via POST
/v1/im/messages/forward, never a client-side {pub} packet -- confirmed
by reading their source directly. Switches web's single-message and
bulk forward paths to the same endpoint, which copies message content
verbatim regardless of shape, eliminating the client-side flat-content
detection this used to require. Comment-sending stays on the existing
sendText() path, unchanged, to preserve current ordering.

Removes send.ts's now-unused forwardMessage/flatForwardPayload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-25 12:27:37 +08:00
co-authored by Claude Sonnet 5
parent e7cb4edf3a
commit 4cd2b33c53
6 changed files with 91 additions and 148 deletions
+38
View File
@@ -153,3 +153,41 @@ export function favoriteMessages(items: Array<{ topic: string; seq: number }>) {
messages: items.map((i) => ({ topic: i.topic, seq: String(i.seq) })),
});
}
export interface ForwardResultItem {
source?: { topic: string; seq: number };
target_topic: string;
client_mid: string;
seq: number;
status: 'sent' | 'pending' | 'uncertain';
reason?: string;
}
export interface ForwardFailureItem {
source?: { topic: string; seq: number };
target_topic?: string;
status: 'failed';
reason: string;
}
/**
* `POST /v1/im/messages/forward` (server/im_http.go's serveIMMessageForward, confirmed by reading
* the real Go source directly, not the protocol doc) -- the SAME backend-authoritative forward path
* both real mobile clients use (confirmed by reading their real source too: iOS's
* ChatDetailViewController+Forward.swift, Android's ImMessageActionApi.forward(), NEITHER ever builds
* a `{pub}` packet client-side). One call handles every (source, target) pair at once -- up to 100
* sources x 20 targets -- with per-pair success/failure reporting, and the server copies
* `msg.Content` verbatim regardless of shape (real Drafty or a mobile-sent flat object), so unlike
* the client-side approach this replaces, there is no content-shape detection to get wrong here.
* `comment` is deliberately NOT wired here even though the endpoint accepts one -- callers keep
* sending an optional forward comment as its own separate, ordinary text message afterward (matching
* this app's existing, unchanged UX: the comment appears AFTER the forwarded message(s), whereas the
* endpoint's own built-in `comment` would save it BEFORE -- a real behavioral difference that's the
* caller's choice to take on, not something to silently opt into here).
*/
export function forwardMessages(sources: Array<{ topic: string; seq: number }>, targetTopics: string[]) {
return imPost<{ items: ForwardResultItem[]; failed: ForwardFailureItem[] }>('/messages/forward', {
sources,
target_topics: targetTopics,
});
}