Feature: Chat Image Upload
Branch: feat/chat-image-upload
Date: 2026-03-18
Impact: Users can now send photos in chat (previously silently dropped)
Root Cause
_pickImage() in chat_screen.dart selected an image and then discarded it — showing a “Upload foto in arrivo! 📸” snackbar but never uploading or sending anything.
Implementation
Upload Flow
User taps photo icon
→ _pickImage(source) picks XFile via image_picker
→ _sendImageMessage(XFile) called
→ Progress snackbar shown
→ XFile.readAsBytes() → Uint8List (works on web + native)
→ Supabase Storage upload to chat-attachments/{chatId}/{uuid}.{ext}
→ getPublicUrl() retrieves the public URL
→ MessageAttachment created with id, url, type=image, name, size, mimeType
→ chatNotifier.sendMessage(type: image, attachments: [attachment])
→ optimistic Message added to chat immediately (status: sending)
→ confirmed from server response
→ _scrollToBottom() called
Storage Path
chat-attachments/
{chatId}/
{uuid}.jpg
{uuid}.png
Key Technical Choices
XFile.readAsBytes()instead ofFile(path)— works on both web and native withoutkIsWebguardsuploadBinary()instead ofupload()— acceptsUint8List, bypasses file path issues on web- Progress feedback — shows a spinner snackbar during upload, hides it on completion or error
Required Infrastructure
Create the Supabase Storage bucket chat-attachments with public access policy:
-- Create bucket (via Supabase dashboard or SQL)
INSERT INTO storage.buckets (id, name, public)
VALUES ('chat-attachments', 'chat-attachments', true);
-- RLS: authenticated users can upload to their own chat paths
CREATE POLICY "Users can upload chat images"
ON storage.objects FOR INSERT
TO authenticated
WITH CHECK (bucket_id = 'chat-attachments');
-- RLS: anyone can read (public bucket)
CREATE POLICY "Public read chat images"
ON storage.objects FOR SELECT
USING (bucket_id = 'chat-attachments');Files Changed
| File | Change |
|---|---|
lib/features/messaging/screens/chat_screen.dart | _pickImage() fixed, _sendImageMessage() added |