Implementation of Message Forwarding in Mobile App
Forward is simpler than reply — no recursion, no binding to position in feed. But details consume time: selecting multiple chats at once, media preview before sending, attribution ("forwarded from Ivan"), and the mandatory question — do we copy the attachment or forward a link to the original.
Data Model
On the server, a forwarded message is a new object with field forwarded_from: { message_id, sender_name, sender_id }. Attachments either copy (new object in storage) or point to the same S3 key. The second variant is cheaper on storage but creates dependency: deleting the original message breaks the attachment for all forwarded copies. Copying is more reliable.
If forwarding media between chats of different types (personal → group) — backend must check permissions for the original attachment. Otherwise private photos from a closed chat leak into a public one.
UI: Chat Selection and Sending
Pattern is uniform: long-tap on message opens context menu, "Forward" option → bottom sheet or modal screen with chat list. Interface is similar to iOS share sheet (UIActivityViewController), but with its own list inside the app.
On iOS above standard UITableView with chat list add multiselect via tableView(_:didSelectRowAt:) with selected IndexPath stored in Set<IndexPath>. Button "Send (N)" in navbar updates via navigationItem.rightBarButtonItem.title. On confirmation — sequential POST requests or one batch-endpoint.
On Compose — LazyColumn with selectedChats: Set<String> in ViewModel. Each element ChatItem checks item.id in selectedChats and draws Checkbox or colored overlay. Button "Send" in FloatingActionButton active when selectedChats.isNotEmpty().
Attribution in Feed
In the bubble of a forwarded message display signature "Forwarded from [name]". If the original sender prohibited forwarding (privacy setting) — hide the name, show just "Forwarded message". Check on server when creating forward: if the original user has allow_forwarding = false, return null in forwarded_from.
Flutter
ForwardCubit holds chat list and selectedIds. UI — showModalBottomSheet with StatefulBuilder or separate route. After selection — cubit.forwardMessage(messageId, toChats: selectedIds). Animation of closing sheet and returning to chat — standard via Navigator.pop.
Timeline
1-3 business days. If forwarding between different chat types with permission separation needed — closer to 3. Cost calculated individually.







