import React, { useRef, useState } from "react"; import { Animated, LayoutAnimation, Linking, Platform, Text, TouchableOpacity, UIManager, View, useColorScheme, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { Entry } from "../services/api"; if (Platform.OS === "android") { UIManager.setLayoutAnimationEnabledExperimental?.(true); } function formatDate(iso: string): string { try { return new Date(iso).toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric", }); } catch { return iso; } } function fileName(path: string): string { return path.split(/[\\/]/).pop() ?? path; } export default function ExpandableItem({ item }: { item: Entry }) { const [expanded, setExpanded] = useState(false); const rotateAnim = useRef(new Animated.Value(0)).current; const dark = useColorScheme() === "dark"; const toggle = () => { LayoutAnimation.configureNext({ duration: 280, create: { type: "easeInEaseOut", property: "opacity" }, update: { type: "spring", springDamping: 0.8 }, }); Animated.timing(rotateAnim, { toValue: expanded ? 0 : 1, duration: 250, useNativeDriver: true, }).start(); setExpanded((v) => !v); }; const chevronRotation = rotateAnim.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "180deg"], }); return ( {/* ── Collapsed header ── */} {/* Subject tag + date */} {item.subject?.name ?? item.groupName} {item.groupName} {formatDate(item.timePublished)} {/* Title */} {item.title} {/* info_entry — always visible as subtitle */} {item.infoEntry ? ( {item.infoEntry} ) : null} {/* ── Expanded body ── */} {expanded && ( {/* paragraph */} {item.paragraph ? ( Content {item.paragraph} ) : null} {/* Meta row: subject + group + date */} {/* filepath — clickable attachment */} {item.filepath ? ( Linking.openURL(item.filepath!)} activeOpacity={0.75} className={`mx-4 mb-4 flex-row items-center gap-3 px-4 py-3 rounded-xl border ${ dark ? "bg-obsidian-50 border-border-dark" : "bg-parchment-100 border-border-light" }`} // stop the expand/collapse toggle firing onStartShouldSetResponder={() => true} > {fileName(item.filepath)} Tap to open attachment ) : null} )} ); } function Row({ label, value, dark, last = false }: { label: string; value?: string; dark: boolean; last?: boolean; }) { if (!value) return null; return ( {label} {value} ); }