From e25bdba29f49b1b55a8a8cccdc4583aea3c101ed Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Sun, 15 Mar 2026 13:41:09 +0100
Subject: [PATCH] feat: multi-image upload and catch_up message delivery

---
 components/chat/ImageCaptionModal.tsx |   51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/components/chat/ImageCaptionModal.tsx b/components/chat/ImageCaptionModal.tsx
index f408157..6c753e0 100644
--- a/components/chat/ImageCaptionModal.tsx
+++ b/components/chat/ImageCaptionModal.tsx
@@ -1,6 +1,7 @@
 import React, { useEffect, useRef, useState } from "react";
 import {
   Dimensions,
+  FlatList,
   Image,
   KeyboardAvoidingView,
   Modal,
@@ -12,22 +13,28 @@
 } from "react-native";
 import { useTheme } from "../../contexts/ThemeContext";
 
+interface ImageItem {
+  uri: string;
+}
+
 interface ImageCaptionModalProps {
   visible: boolean;
-  imageUri: string;
+  images: ImageItem[];
   onSend: (caption: string) => void;
   onCancel: () => void;
 }
 
-export function ImageCaptionModal({ visible, imageUri, onSend, onCancel }: ImageCaptionModalProps) {
+export function ImageCaptionModal({ visible, images, onSend, onCancel }: ImageCaptionModalProps) {
   const { colors } = useTheme();
   const [caption, setCaption] = useState("");
+  const [selectedIndex, setSelectedIndex] = useState(0);
   const inputRef = useRef<TextInput>(null);
   const { width, height } = Dimensions.get("window");
 
   useEffect(() => {
     if (visible) {
       setCaption("");
+      setSelectedIndex(0);
       setTimeout(() => inputRef.current?.focus(), 300);
     }
   }, [visible]);
@@ -37,6 +44,9 @@
     setCaption("");
   };
 
+  const currentImage = images[selectedIndex]?.uri ?? "";
+  const isMultiple = images.length > 1;
+
   return (
     <Modal visible={visible} animationType="slide" transparent={false} onRequestClose={onCancel}>
       <View style={{ flex: 1, backgroundColor: "#000" }}>
@@ -45,7 +55,7 @@
           behavior={Platform.OS === "ios" ? "padding" : undefined}
           keyboardVerticalOffset={0}
         >
-          {/* Top bar with cancel */}
+          {/* Top bar with cancel + count */}
           <View
             style={{
               paddingTop: 54,
@@ -68,17 +78,48 @@
             >
               <Text style={{ color: "#fff", fontSize: 16, fontWeight: "600" }}>Cancel</Text>
             </Pressable>
+            {isMultiple && (
+              <Text style={{ color: "rgba(255,255,255,0.6)", fontSize: 14 }}>
+                {selectedIndex + 1} / {images.length}
+              </Text>
+            )}
           </View>
 
           {/* Image preview */}
           <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
             <Image
-              source={{ uri: imageUri }}
-              style={{ width, height: height * 0.55 }}
+              source={{ uri: currentImage }}
+              style={{ width, height: isMultiple ? height * 0.45 : height * 0.55 }}
               resizeMode="contain"
             />
           </View>
 
+          {/* Thumbnail strip — only for multiple images */}
+          {isMultiple && (
+            <FlatList
+              data={images}
+              horizontal
+              showsHorizontalScrollIndicator={false}
+              keyExtractor={(_, i) => String(i)}
+              contentContainerStyle={{ paddingHorizontal: 12, paddingVertical: 8, gap: 8 }}
+              renderItem={({ item, index }) => (
+                <Pressable onPress={() => setSelectedIndex(index)}>
+                  <Image
+                    source={{ uri: item.uri }}
+                    style={{
+                      width: 56,
+                      height: 56,
+                      borderRadius: 8,
+                      borderWidth: index === selectedIndex ? 2 : 0,
+                      borderColor: colors.accent,
+                    }}
+                    resizeMode="cover"
+                  />
+                </Pressable>
+              )}
+            />
+          )}
+
           {/* Caption input + send */}
           <View
             style={{

--
Gitblit v1.3.1