@adminide-stack/yantra-mobile 12.0.105 → 12.0.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/features/messaging/BlockedContactsScreen.js +127 -0
- package/lib/features/messaging/BlockedContactsScreen.js.map +1 -0
- package/lib/features/messaging/ChatAttachments.js +4 -2
- package/lib/features/messaging/ChatAttachments.js.map +1 -1
- package/lib/features/messaging/ChatComponents.js +194 -10
- package/lib/features/messaging/ChatComponents.js.map +1 -1
- package/lib/features/messaging/ChatInfoScreen.js +173 -17
- package/lib/features/messaging/ChatInfoScreen.js.map +1 -1
- package/lib/features/messaging/ConversationListScreen.js +17 -1
- package/lib/features/messaging/ConversationListScreen.js.map +1 -1
- package/lib/features/messaging/MediaGalleryScreen.js +264 -0
- package/lib/features/messaging/MediaGalleryScreen.js.map +1 -0
- package/lib/features/messaging/NativeChatExperience.js +137 -18
- package/lib/features/messaging/NativeChatExperience.js.map +1 -1
- package/lib/features/messaging/NewGroupScreen.js +191 -0
- package/lib/features/messaging/NewGroupScreen.js.map +1 -0
- package/lib/features/messaging/PollComposer.js +137 -0
- package/lib/features/messaging/PollComposer.js.map +1 -0
- package/lib/features/messaging/PollVotesScreen.js +122 -0
- package/lib/features/messaging/PollVotesScreen.js.map +1 -0
- package/lib/features/messaging/ThreadScreen.js +180 -13
- package/lib/features/messaging/ThreadScreen.js.map +1 -1
- package/lib/features/messaging/chatLinks.js +39 -2
- package/lib/features/messaging/chatLinks.js.map +1 -1
- package/lib/features/messaging/chatModel.js +186 -19
- package/lib/features/messaging/chatModel.js.map +1 -1
- package/lib/features/messaging/chatOperations.js +111 -2
- package/lib/features/messaging/chatOperations.js.map +1 -1
- package/lib/features/messaging/nativeChatChannelQuery.js +7 -2
- package/lib/features/messaging/nativeChatChannelQuery.js.map +1 -1
- package/lib/features/messaging/useChatData.js +248 -10
- package/lib/features/messaging/useChatData.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationListScreen.js","sources":["../../../src/features/messaging/ConversationListScreen.tsx"],"sourcesContent":["/**\n * The conversation list, WhatsApp-style: a large \"Chats\" title, search, the\n * All / Unread / Groups filter chips, and rows with ticks, mute and a green\n * unread badge.\n */\nimport * as React from 'react';\nimport {\n ActivityIndicator,\n FlatList,\n Pressable,\n RefreshControl,\n StyleSheet,\n Text,\n TextInput,\n View,\n} from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { ConnectionBanner, ConversationRow, EmptyState, InlineBanner, type ChatTheme } from './ChatComponents';\nimport {\n conversationListKey,\n dedupeConversationList,\n emptyListCopy,\n filterConversations,\n type ChatConversation,\n type ChatListFilter,\n} from './chatModel';\nimport { usePressed } from './usePressed';\nimport { ActionSheet, type SheetAction } from './ActionSheet';\nimport type { ChatConnectionState, ChatPushSeam } from './chatHost';\n\nconst FILTERS: ReadonlyArray<{ key: ChatListFilter; label: string }> = [\n { key: 'all', label: 'All' },\n { key: 'unread', label: 'Unread' },\n { key: 'groups', label: 'Groups' },\n];\n\nfunction FilterChip({\n label,\n active,\n theme,\n onPress,\n}: {\n label: string;\n active: boolean;\n theme: ChatTheme;\n onPress: () => void;\n}) {\n const [pressed, pressHandlers] = usePressed();\n const activeBg = theme.isDark ? 'rgba(0, 168, 132, 0.25)' : '#d8fdd2';\n const activeText = theme.isDark ? '#d8fdd2' : '#0b5c44';\n return (\n <Pressable\n onPress={onPress}\n {...pressHandlers}\n accessibilityRole=\"tab\"\n accessibilityState={{ selected: active }}\n style={[styles.chip, { backgroundColor: active ? activeBg : theme.surface, opacity: pressed ? 0.7 : 1 }]}\n testID={`chat-filter-${label.toLowerCase()}`}\n >\n <Text style={[styles.chipText, { color: active ? activeText : theme.textMuted }]}>{label}</Text>\n </Pressable>\n );\n}\n\nexport function ConversationListScreen({\n conversations,\n loading,\n refreshing,\n error,\n theme,\n connectionState,\n canInvite,\n onRefresh,\n onRetry,\n onOpen,\n onNewChat,\n onOpenNotifications,\n pushStatus,\n onEnablePush,\n onDismissError,\n notice = null,\n onDismissNotice,\n loadingMore = false,\n onLoadMore,\n mode = 'chats',\n archivedCount = 0,\n onOpenArchived,\n onOpenStarred,\n onBack,\n onSetListState,\n}: {\n conversations: ChatConversation[];\n loading: boolean;\n refreshing: boolean;\n loadingMore?: boolean;\n onLoadMore?: () => void;\n error: string | null;\n theme: ChatTheme;\n connectionState: ChatConnectionState;\n canInvite: boolean;\n onRefresh: () => void;\n onRetry: () => void;\n onOpen: (id: string) => void;\n onNewChat: () => void;\n /** Opens the chat notification settings; absent hides the bell. */\n onOpenNotifications?: () => void;\n /** This phone's push permission; anything but granted shows the \"Turn on notifications\" row. */\n pushStatus?: ChatPushSeam['status'];\n onEnablePush?: () => void;\n onDismissError: () => void;\n /** A one-off message that is not a load failure (e.g. an invite that could not be opened). */\n notice?: string | null;\n onDismissNotice?: () => void;\n /** The main list, or the chats the viewer archived. */\n mode?: 'chats' | 'archived';\n /** Archived chats, for the \"Archived\" row at the top of the main list. */\n archivedCount?: number;\n onOpenArchived?: () => void;\n onOpenStarred?: () => void;\n /** Archived mode's back button. */\n onBack?: () => void;\n /** Pin / archive from a row's long-press options; absent disables them. */\n onSetListState?: (channelId: string, state: { pinned?: boolean; archived?: boolean }) => void;\n}) {\n const archived = mode === 'archived';\n const [rowTarget, setRowTarget] = React.useState<ChatConversation | null>(null);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const rowActions = React.useMemo<SheetAction[]>(() => {\n const target = rowTarget;\n if (!target || !onSetListState) return [];\n const list: SheetAction[] = [];\n if (!archived) {\n list.push({\n key: target.pinnedAt > 0 ? 'unpin' : 'pin',\n label: target.pinnedAt > 0 ? 'Unpin chat' : 'Pin chat',\n icon: target.pinnedAt > 0 ? 'pin-off-outline' : 'pin-outline',\n onPress: () => onSetListState(target.id, { pinned: !(target.pinnedAt > 0) }),\n });\n }\n list.push({\n key: archived ? 'unarchive' : 'archive',\n label: archived ? 'Unarchive chat' : 'Archive chat',\n icon: archived ? 'archive-arrow-up-outline' : 'archive-arrow-down-outline',\n onPress: () => onSetListState(target.id, { archived: !archived }),\n });\n return list;\n }, [rowTarget, onSetListState, archived]);\n const menuActions = React.useMemo<SheetAction[]>(() => {\n const list: SheetAction[] = [];\n if (onOpenStarred)\n list.push({ key: 'starred', label: 'Starred messages', icon: 'star-outline', onPress: onOpenStarred });\n if (onOpenArchived) {\n list.push({ key: 'archived', label: 'Archived chats', icon: 'archive-outline', onPress: onOpenArchived });\n }\n if (onOpenNotifications) {\n list.push({\n key: 'notifications',\n label: 'Notifications',\n icon: 'bell-outline',\n onPress: onOpenNotifications,\n });\n }\n return list;\n }, [onOpenStarred, onOpenArchived, onOpenNotifications]);\n const [now, setNow] = React.useState(() => Date.now());\n const [query, setQuery] = React.useState('');\n const [filter, setFilter] = React.useState<ChatListFilter>('all');\n React.useEffect(() => {\n const t = setInterval(() => setNow(Date.now()), 60_000);\n return () => clearInterval(t);\n }, []);\n\n const visible = React.useMemo(() => {\n const inMode = conversations.filter((c) => (archived ? c.archivedAt > 0 : !(c.archivedAt > 0)));\n const deduped = filterConversations(dedupeConversationList(inMode), filter);\n const q = query.trim().toLowerCase();\n if (!q) return deduped;\n return deduped.filter((c) => c.title.toLowerCase().includes(q) || c.subtitle.toLowerCase().includes(q));\n }, [conversations, query, filter, archived]);\n const narrowed = Boolean(query.trim()) || filter !== 'all';\n const empty = emptyListCopy({ searching: Boolean(query.trim()), filter, canInvite });\n let emptyAction: { label: string; onPress: () => void } | undefined;\n if (empty.action === 'all') emptyAction = { label: 'Show all chats', onPress: () => setFilter('all') };\n else if (empty.action === 'new') emptyAction = { label: 'New chat', onPress: onNewChat };\n\n const Separator = React.useCallback(\n () => <View style={[styles.separator, { backgroundColor: theme.border }]} />,\n [theme.border],\n );\n\n const listHeader = archived ? (\n // The host hides its header off the main list, so this one owns the top inset.\n <SafeAreaView edges={['top']} style={{ backgroundColor: theme.headerBg }}>\n <View style={[styles.archivedHeader, { borderBottomColor: theme.border, flexDirection: 'row' }]}>\n <Pressable\n onPress={onBack}\n hitSlop={10}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Back\"\n style={styles.headerCompose}\n testID=\"chat-archived-back\"\n >\n <MaterialCommunityIcons name=\"chevron-left\" size={32} color={theme.accent} />\n </Pressable>\n <Text style={[styles.archivedTitle, { color: theme.text }]}>Archived</Text>\n <View style={styles.headerComposeSpacer} />\n </View>\n </SafeAreaView>\n ) : (\n <View style={[styles.listHeader, { flexDirection: 'row', alignItems: 'center' }]}>\n <Text style={[styles.listTitle, { color: theme.text }]}>Chats</Text>\n <View style={{ flexDirection: 'row', alignItems: 'center' }}>\n {menuActions.length ? (\n <Pressable\n onPress={() => setMenuOpen(true)}\n accessibilityRole=\"button\"\n accessibilityLabel=\"More\"\n style={styles.headerCompose}\n testID=\"chat-list-menu\"\n >\n <MaterialCommunityIcons name=\"dots-horizontal-circle-outline\" size={26} color={theme.accent} />\n </Pressable>\n ) : null}\n {canInvite ? (\n <Pressable\n onPress={onNewChat}\n accessibilityRole=\"button\"\n accessibilityLabel=\"New chat\"\n style={styles.headerCompose}\n testID=\"chat-new\"\n >\n <View style={[styles.composeDot, { backgroundColor: theme.accent }]}>\n <MaterialCommunityIcons name=\"plus\" size={20} color={theme.onAccent} />\n </View>\n </Pressable>\n ) : (\n <View style={styles.headerComposeSpacer} />\n )}\n </View>\n </View>\n );\n\n return (\n <View style={[styles.fill, { backgroundColor: theme.bg }]}>\n {listHeader}\n <View style={[styles.searchWrap, { backgroundColor: theme.surface }]}>\n <MaterialCommunityIcons name=\"magnify\" size={20} color={theme.textMuted} />\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search\"\n placeholderTextColor={theme.textMuted}\n style={[styles.searchInput, { color: theme.text }]}\n testID=\"chat-search\"\n />\n </View>\n {archived ? (\n <Text style={[styles.archivedNote, { color: theme.textMuted }]}>\n Archived chats stay here when new messages arrive. Unarchive one to put it back in Chats.\n </Text>\n ) : null}\n <View style={[styles.chips, { flexDirection: 'row' }, archived && styles.hidden]}>\n {FILTERS.map((f) => (\n <FilterChip\n key={f.key}\n label={f.label}\n active={filter === f.key}\n theme={theme}\n onPress={() => setFilter(f.key)}\n />\n ))}\n </View>\n\n {!archived && onEnablePush && (pushStatus === 'undetermined' || pushStatus === 'denied') ? (\n <Pressable\n onPress={pushStatus === 'denied' && onOpenNotifications ? onOpenNotifications : onEnablePush}\n accessibilityRole=\"button\"\n style={[styles.pushRow, { backgroundColor: theme.isDark ? '#103629' : '#e7fce3' }]}\n testID=\"chat-push-banner\"\n >\n <View style={{ flexDirection: 'row', alignItems: 'center' }}>\n <MaterialCommunityIcons name=\"bell-ring-outline\" size={22} color={theme.accent} />\n <View style={{ flex: 1, marginLeft: 12 }}>\n <Text style={[styles.pushTitle, { color: theme.text }]}>Turn on notifications</Text>\n <Text style={[styles.pushDetail, { color: theme.textMuted }]}>\n Get notified about new messages.\n </Text>\n </View>\n <MaterialCommunityIcons name=\"chevron-right\" size={22} color={theme.textMuted} />\n </View>\n </Pressable>\n ) : null}\n <ConnectionBanner state={connectionState} theme={theme} />\n <InlineBanner message={error} theme={theme} onDismiss={onDismissError} />\n <InlineBanner message={notice} theme={theme} onDismiss={() => onDismissNotice?.()} />\n {error ? (\n <Pressable\n onPress={onRetry}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Retry loading chats\"\n style={[styles.retryBanner, { backgroundColor: theme.surface }]}\n >\n <Text style={[styles.retryBannerText, { color: theme.accent }]}>Retry loading chats</Text>\n </Pressable>\n ) : null}\n\n {loading && conversations.length === 0 ? (\n <View style={styles.center}>\n <ActivityIndicator color={theme.accent} />\n </View>\n ) : (\n <FlatList\n data={visible}\n keyExtractor={(c) => conversationListKey(c)}\n ItemSeparatorComponent={Separator}\n ListHeaderComponent={\n !archived && archivedCount > 0 && onOpenArchived ? (\n <Pressable\n onPress={onOpenArchived}\n accessibilityRole=\"button\"\n accessibilityLabel={`Archived, ${archivedCount} chats`}\n testID=\"chat-archived-row\"\n >\n <View style={[styles.archivedRow, { flexDirection: 'row' }]}>\n <View style={styles.archivedIcon}>\n <MaterialCommunityIcons\n name=\"archive-outline\"\n size={22}\n color={theme.textMuted}\n />\n </View>\n <Text style={[styles.archivedLabel, { color: theme.text }]}>Archived</Text>\n <Text style={{ color: theme.accent, fontSize: 14 }}>{archivedCount}</Text>\n </View>\n </Pressable>\n ) : null\n }\n renderItem={({ item }) => (\n <ConversationRow\n conversation={item}\n theme={theme}\n now={now}\n onPress={() => onOpen(item.id)}\n onLongPress={onSetListState ? () => setRowTarget(item) : undefined}\n />\n )}\n refreshControl={\n <RefreshControl refreshing={refreshing} onRefresh={onRefresh} tintColor={theme.textMuted} />\n }\n // Paging would skip rows while a search or a filter chip is hiding most of them.\n onEndReached={narrowed ? undefined : onLoadMore}\n onEndReachedThreshold={0.5}\n ListFooterComponent={\n loadingMore ? <ActivityIndicator style={styles.moreSpinner} color={theme.accent} /> : null\n }\n contentContainerStyle={visible.length === 0 ? styles.fill : undefined}\n ListEmptyComponent={\n <EmptyState\n icon=\"message-text-outline\"\n title={empty.title}\n detail={empty.detail}\n theme={theme}\n action={emptyAction}\n />\n }\n testID=\"chat-conversation-list\"\n />\n )}\n <ActionSheet\n visible={Boolean(rowTarget)}\n title={rowTarget?.title}\n actions={rowActions}\n theme={theme}\n onClose={() => setRowTarget(null)}\n testID=\"chat-row-sheet\"\n />\n <ActionSheet\n visible={menuOpen}\n actions={menuActions}\n theme={theme}\n onClose={() => setMenuOpen(false)}\n testID=\"chat-list-menu-sheet\"\n />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center' },\n moreSpinner: { paddingVertical: 16 },\n listHeader: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingTop: 4,\n paddingBottom: 4,\n },\n listTitle: { fontSize: 34, fontWeight: '700', letterSpacing: 0.35 },\n headerCompose: {\n width: 44,\n height: 44,\n alignItems: 'center',\n justifyContent: 'center',\n },\n headerComposeSpacer: { width: 44 },\n archivedHeader: {\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 4,\n minHeight: 52,\n borderBottomWidth: StyleSheet.hairlineWidth,\n marginBottom: 8,\n },\n archivedTitle: { fontSize: 17, fontWeight: '600' },\n archivedNote: { fontSize: 13, lineHeight: 18, textAlign: 'center', marginHorizontal: 32, marginBottom: 8 },\n hidden: { display: 'none' },\n archivedRow: { alignItems: 'center', paddingHorizontal: 16, minHeight: 48 },\n archivedIcon: { width: 52, alignItems: 'center' },\n archivedLabel: { flex: 1, fontSize: 16, fontWeight: '600', marginLeft: 14 },\n pushRow: { marginHorizontal: 16, marginBottom: 8, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12 },\n pushTitle: { fontSize: 15, fontWeight: '600' },\n pushDetail: { fontSize: 13, marginTop: 1 },\n composeDot: { width: 28, height: 28, borderRadius: 14, alignItems: 'center', justifyContent: 'center' },\n chips: { paddingHorizontal: 16, paddingBottom: 8, paddingTop: 2 },\n chip: { paddingHorizontal: 14, height: 32, borderRadius: 16, justifyContent: 'center', marginRight: 8 },\n chipText: { fontSize: 14, fontWeight: '500' },\n searchWrap: {\n flexDirection: 'row',\n alignItems: 'center',\n marginHorizontal: 16,\n marginBottom: 6,\n borderRadius: 10,\n paddingHorizontal: 10,\n height: 36,\n },\n searchInput: { flex: 1, marginLeft: 8, fontSize: 16, paddingVertical: 0 },\n separator: { height: StyleSheet.hairlineWidth, marginLeft: 82 },\n retryBanner: { alignItems: 'center', paddingVertical: 10 },\n retryBannerText: { fontSize: 14, fontWeight: '600' },\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAcA,MAAM,UAGD,CAAC;AAAA,EACJ,GAAK,EAAA,KAAA;AAAA,EACL,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,GAAK,EAAA,QAAA;AAAA,EACL,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,GAAK,EAAA,QAAA;AAAA,EACL,KAAO,EAAA;AACT,CAAC,CAAA;AACD,SAAS,UAAW,CAAA;AAAA,EAClB,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAKG,EAAA;AACD,EAAA,MAAM,CAAC,OAAA,EAAS,aAAa,CAAA,GAAI,UAAW,EAAA;AAC5C,EAAM,MAAA,QAAA,GAAW,KAAM,CAAA,MAAA,GAAS,yBAA4B,GAAA,SAAA;AAC5D,EAAM,MAAA,UAAA,GAAa,KAAM,CAAA,MAAA,GAAS,SAAY,GAAA,SAAA;AAC9C,EAAA,2BAAQ,SAAU,EAAA,aAAA,CAAA,cAAA,CAAA,EAAA,OAAA,EAAA,EAAsB,gBAAhC,EAA+C,iBAAA,EAAkB,OAAM,kBAAoB,EAAA;AAAA,IACjG,QAAU,EAAA;AAAA,GACT,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,IAAM,EAAA;AAAA,IACtB,eAAA,EAAiB,MAAS,GAAA,QAAA,GAAW,KAAM,CAAA,OAAA;AAAA,IAC3C,OAAA,EAAS,UAAU,GAAM,GAAA;AAAA,GAC1B,CAAA,EAAG,MAAQ,EAAA,CAAA,YAAA,EAAe,KAAM,CAAA,WAAA,EAAa,CAAA,CAAA,EACpC,QAAC,kBAAA,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,QAAU,EAAA;AAAA,IACrC,KAAA,EAAO,MAAS,GAAA,UAAA,GAAa,KAAM,CAAA;AAAA,GACpC,CAAI,EAAA,QAAA,EAAA,KAAA,EAAM,CACP,EAAA,CAAA,CAAA;AACR;AACO,SAAS,sBAAuB,CAAA;AAAA,EACrC,aAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,mBAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,MAAS,GAAA,IAAA;AAAA,EACT,eAAA;AAAA,EACA,WAAc,GAAA,KAAA;AAAA,EACd,UAAA;AAAA,EACA,IAAO,GAAA,OAAA;AAAA,EACP,aAAgB,GAAA,CAAA;AAAA,EAChB,cAAA;AAAA,EACA,aAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAoCG,EAAA;AACD,EAAA,MAAM,WAAW,IAAS,KAAA,UAAA;AAC1B,EAAA,MAAM,CAAC,SAAW,EAAA,YAAY,CAAI,GAAA,KAAA,CAAM,SAAkC,IAAI,CAAA;AAC9E,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,KAAA,CAAM,SAAS,KAAK,CAAA;AACpD,EAAM,MAAA,UAAA,GAAa,KAAM,CAAA,OAAA,CAAuB,MAAM;AACpD,IAAA,MAAM,MAAS,GAAA,SAAA;AACf,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,cAAA,SAAuB,EAAC;AACxC,IAAA,MAAM,OAAsB,EAAC;AAC7B,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAA,IAAA,CAAK,IAAK,CAAA;AAAA,QACR,GAAK,EAAA,MAAA,CAAO,QAAW,GAAA,CAAA,GAAI,OAAU,GAAA,KAAA;AAAA,QACrC,KAAO,EAAA,MAAA,CAAO,QAAW,GAAA,CAAA,GAAI,YAAe,GAAA,UAAA;AAAA,QAC5C,IAAM,EAAA,MAAA,CAAO,QAAW,GAAA,CAAA,GAAI,iBAAoB,GAAA,aAAA;AAAA,QAChD,OAAS,EAAA,MAAM,cAAe,CAAA,MAAA,CAAO,EAAI,EAAA;AAAA,UACvC,MAAA,EAAQ,EAAE,MAAA,CAAO,QAAW,GAAA,CAAA;AAAA,SAC7B;AAAA,OACF,CAAA;AAAA;AAEH,IAAA,IAAA,CAAK,IAAK,CAAA;AAAA,MACR,GAAA,EAAK,WAAW,WAAc,GAAA,SAAA;AAAA,MAC9B,KAAA,EAAO,WAAW,gBAAmB,GAAA,cAAA;AAAA,MACrC,IAAA,EAAM,WAAW,0BAA6B,GAAA,4BAAA;AAAA,MAC9C,OAAS,EAAA,MAAM,cAAe,CAAA,MAAA,CAAO,EAAI,EAAA;AAAA,QACvC,UAAU,CAAC;AAAA,OACZ;AAAA,KACF,CAAA;AACD,IAAO,OAAA,IAAA;AAAA,GACN,EAAA,CAAC,SAAW,EAAA,cAAA,EAAgB,QAAQ,CAAC,CAAA;AACxC,EAAM,MAAA,WAAA,GAAc,KAAM,CAAA,OAAA,CAAuB,MAAM;AACrD,IAAA,MAAM,OAAsB,EAAC;AAC7B,IAAI,IAAA,aAAA,OAAoB,IAAK,CAAA;AAAA,MAC3B,GAAK,EAAA,SAAA;AAAA,MACL,KAAO,EAAA,kBAAA;AAAA,MACP,IAAM,EAAA,cAAA;AAAA,MACN,OAAS,EAAA;AAAA,KACV,CAAA;AACD,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAA,IAAA,CAAK,IAAK,CAAA;AAAA,QACR,GAAK,EAAA,UAAA;AAAA,QACL,KAAO,EAAA,gBAAA;AAAA,QACP,IAAM,EAAA,iBAAA;AAAA,QACN,OAAS,EAAA;AAAA,OACV,CAAA;AAAA;AAEH,IAAA,IAAI,mBAAqB,EAAA;AACvB,MAAA,IAAA,CAAK,IAAK,CAAA;AAAA,QACR,GAAK,EAAA,eAAA;AAAA,QACL,KAAO,EAAA,eAAA;AAAA,QACP,IAAM,EAAA,cAAA;AAAA,QACN,OAAS,EAAA;AAAA,OACV,CAAA;AAAA;AAEH,IAAO,OAAA,IAAA;AAAA,GACN,EAAA,CAAC,aAAe,EAAA,cAAA,EAAgB,mBAAmB,CAAC,CAAA;AACvD,EAAM,MAAA,CAAC,KAAK,MAAM,CAAA,GAAI,MAAM,QAAS,CAAA,MAAM,IAAK,CAAA,GAAA,EAAK,CAAA;AACrD,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,CAAI,GAAA,KAAA,CAAM,SAAS,EAAE,CAAA;AAC3C,EAAA,MAAM,CAAC,MAAQ,EAAA,SAAS,CAAI,GAAA,KAAA,CAAM,SAAyB,KAAK,CAAA;AAChE,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAM,MAAA,CAAA,GAAI,YAAY,MAAM,MAAA,CAAO,KAAK,GAAI,EAAC,GAAG,GAAM,CAAA;AACtD,IAAO,OAAA,MAAM,cAAc,CAAC,CAAA;AAAA,GAC9B,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,OAAA,GAAU,KAAM,CAAA,OAAA,CAAQ,MAAM;AAClC,IAAM,MAAA,MAAA,GAAS,aAAc,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,QAAA,GAAW,CAAE,CAAA,UAAA,GAAa,CAAI,GAAA,EAAE,CAAE,CAAA,UAAA,GAAa,CAAE,CAAA,CAAA;AAC1F,IAAA,MAAM,OAAU,GAAA,mBAAA,CAAoB,sBAAuB,CAAA,MAAM,GAAG,MAAM,CAAA;AAC1E,IAAA,MAAM,CAAI,GAAA,KAAA,CAAM,IAAK,EAAA,CAAE,WAAY,EAAA;AACnC,IAAI,IAAA,CAAC,GAAU,OAAA,OAAA;AACf,IAAA,OAAO,QAAQ,MAAO,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,KAAA,CAAM,aAAc,CAAA,QAAA,CAAS,CAAC,CAAA,IAAK,EAAE,QAAS,CAAA,WAAA,EAAc,CAAA,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,KACnG,CAAC,aAAA,EAAe,KAAO,EAAA,MAAA,EAAQ,QAAQ,CAAC,CAAA;AAC3C,EAAA,MAAM,WAAW,OAAQ,CAAA,KAAA,CAAM,IAAK,EAAC,KAAK,MAAW,KAAA,KAAA;AACrD,EAAA,MAAM,QAAQ,aAAc,CAAA;AAAA,IAC1B,SAAW,EAAA,OAAA,CAAQ,KAAM,CAAA,IAAA,EAAM,CAAA;AAAA,IAC/B,MAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAI,IAAA,WAAA;AAIJ,EAAI,IAAA,KAAA,CAAM,MAAW,KAAA,KAAA,EAAqB,WAAA,GAAA;AAAA,IACxC,KAAO,EAAA,gBAAA;AAAA,IACP,OAAA,EAAS,MAAM,SAAA,CAAU,KAAK;AAAA,GAChC;AAAA,OAAW,IAAA,KAAA,CAAM,MAAW,KAAA,KAAA,EAAqB,WAAA,GAAA;AAAA,IAC/C,KAAO,EAAA,UAAA;AAAA,IACP,OAAS,EAAA;AAAA,GACX;AACA,EAAM,MAAA,SAAA,GAAY,MAAM,WAAY,CAAA,0BAAO,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,SAAW,EAAA;AAAA,IACxE,iBAAiB,KAAM,CAAA;AAAA,GACxB,CAAG,EAAA,CAAA,EAAI,CAAC,KAAA,CAAM,MAAM,CAAC,CAAA;AACtB,EAAA,MAAM,UAAa,GAAA,QAAA;AAAA;AAAA,wBAElB,YAAa,EAAA,EAAA,KAAA,EAAO,CAAC,KAAK,GAAG,KAAO,EAAA;AAAA,MACnC,iBAAiB,KAAM,CAAA;AAAA,OAEf,QAAC,kBAAA,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,cAAgB,EAAA;AAAA,MAC3C,mBAAmB,KAAM,CAAA,MAAA;AAAA,MACzB,aAAe,EAAA;AAAA,KAChB,CACW,EAAA,QAAA,EAAA;AAAA,sBAAC,GAAA,CAAA,SAAA,EAAA,EAAU,SAAS,MAAQ,EAAA,OAAA,EAAS,IAAI,iBAAkB,EAAA,QAAA,EAAS,kBAAmB,EAAA,MAAA,EAAO,KAAO,EAAA,MAAA,CAAO,eAAe,MAAO,EAAA,oBAAA,EAC9H,QAAC,kBAAA,GAAA,CAAA,sBAAA,EAAA,EAAuB,IAAK,EAAA,cAAA,EAAe,MAAM,EAAI,EAAA,KAAA,EAAO,KAAM,CAAA,MAAA,EAAQ,CAC/E,EAAA,CAAA;AAAA,sBACC,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,aAAe,EAAA;AAAA,QAC5C,OAAO,KAAM,CAAA;AAAA,OACd,GAAG,QAAQ,EAAA,UAAA,EAAA,CAAA;AAAA,sBACD,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,MAAA,CAAO,mBAAqB,EAAA;AAAA,KAAA,EAC7C,CACJ,EAAA;AAAA,sBAAmB,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,UAAY,EAAA;AAAA,IACvD,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA;AAAA,GACb,CACS,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,SAAW,EAAA;AAAA,MACtC,OAAO,KAAM,CAAA;AAAA,KACd,GAAG,QAAK,EAAA,OAAA,EAAA,CAAA;AAAA,oBACD,IAAA,CAAC,QAAK,KAAO,EAAA;AAAA,MACnB,aAAe,EAAA,KAAA;AAAA,MACf,UAAY,EAAA;AAAA,KAED,EAAA,QAAA,EAAA;AAAA,MAAY,WAAA,CAAA,MAAA,mBAAU,GAAA,CAAA,SAAA,EAAA,EAAU,OAAS,EAAA,MAAM,WAAY,CAAA,IAAI,CAAG,EAAA,iBAAA,EAAkB,QAAS,EAAA,kBAAA,EAAmB,MAAO,EAAA,KAAA,EAAO,MAAO,CAAA,aAAA,EAAe,MAAO,EAAA,gBAAA,EACpJ,QAAC,kBAAA,GAAA,CAAA,sBAAA,EAAA,EAAuB,IAAK,EAAA,gCAAA,EAAiC,IAAM,EAAA,EAAA,EAAI,KAAO,EAAA,KAAA,CAAM,MAAQ,EAAA,CAAA,EACjG,CAAe,GAAA,IAAA;AAAA,MAClB,4BAAa,GAAA,CAAA,SAAA,EAAA,EAAU,SAAS,SAAW,EAAA,iBAAA,EAAkB,UAAS,kBAAmB,EAAA,UAAA,EAAW,OAAO,MAAO,CAAA,aAAA,EAAe,QAAO,UACjI,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,UAAY,EAAA;AAAA,QAC/C,iBAAiB,KAAM,CAAA;AAAA,OACxB,CACmB,EAAA,QAAA,kBAAA,GAAA,CAAC,0BAAuB,IAAK,EAAA,MAAA,EAAO,MAAM,EAAI,EAAA,KAAA,EAAO,KAAM,CAAA,QAAA,EAAU,GACzE,CACJ,EAAA,CAAA,uBAAgB,IAAK,EAAA,EAAA,KAAA,EAAO,OAAO,mBAAqB,EAAA;AAAA,KAChE,EAAA;AAAA,GACJ,EAAA,CAAA;AACN,EAAA,uBAAQ,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA;AAAA,IAChC,iBAAiB,KAAM,CAAA;AAAA,GACxB,CACU,EAAA,QAAA,EAAA;AAAA,IAAA,UAAA;AAAA,oBACA,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,UAAY,EAAA;AAAA,MACvC,iBAAiB,KAAM,CAAA;AAAA,KACxB,CACW,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,0BAAuB,IAAK,EAAA,SAAA,EAAU,MAAM,EAAI,EAAA,KAAA,EAAO,MAAM,SAAW,EAAA,CAAA;AAAA,sBACxE,GAAA,CAAA,SAAA,EAAA,EAAU,KAAO,EAAA,KAAA,EAAO,cAAc,QAAU,EAAA,WAAA,EAAY,QAAS,EAAA,oBAAA,EAAsB,KAAM,CAAA,SAAA,EAAW,KAAO,EAAA,CAAC,OAAO,WAAa,EAAA;AAAA,QACjJ,OAAO,KAAM,CAAA;AAAA,OACd,CAAG,EAAA,MAAA,EAAO,aAAc,EAAA;AAAA,KACnB,EAAA,CAAA;AAAA,IACC,2BAAY,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,YAAc,EAAA;AAAA,MACrD,OAAO,KAAM,CAAA;AAAA,KACd,CAAG,EAAA,QAAA,EAAA,2FAAA,EAEQ,CAAU,GAAA,IAAA;AAAA,oBACb,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,KAAO,EAAA;AAAA,MAClC,aAAe,EAAA;AAAA,KACjB,EAAG,QAAY,IAAA,MAAA,CAAO,MAAM,CAAA,EACf,QAAQ,EAAA,OAAA,CAAA,GAAA,CAAI,CAAK,CAAA,qBAAA,GAAA,CAAC,UAAuB,EAAA,EAAA,KAAA,EAAO,CAAE,CAAA,KAAA,EAAO,MAAQ,EAAA,MAAA,KAAW,CAAE,CAAA,GAAA,EAAK,KAAc,EAAA,OAAA,EAAS,MAAM,SAAA,CAAU,CAAE,CAAA,GAAG,CAA7F,EAAA,EAAA,CAAA,CAAE,GAA8F,CAAE,CACzI,EAAA,CAAA;AAAA,IAEC,CAAC,YAAY,YAAiB,KAAA,UAAA,KAAe,kBAAkB,UAAe,KAAA,QAAA,CAAA,uBAAa,SAAU,EAAA,EAAA,OAAA,EAAS,eAAe,QAAY,IAAA,mBAAA,GAAsB,sBAAsB,YAAc,EAAA,iBAAA,EAAkB,UAAS,KAAO,EAAA,CAAC,OAAO,OAAS,EAAA;AAAA,MAC7P,eAAA,EAAiB,KAAM,CAAA,MAAA,GAAS,SAAY,GAAA;AAAA,KAC7C,CAAG,EAAA,MAAA,EAAO,kBACK,EAAA,QAAA,kBAAA,IAAA,CAAC,QAAK,KAAO,EAAA;AAAA,MACzB,aAAe,EAAA,KAAA;AAAA,MACf,UAAY,EAAA;AAAA,KAEI,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,0BAAuB,IAAK,EAAA,mBAAA,EAAoB,MAAM,EAAI,EAAA,KAAA,EAAO,MAAM,MAAQ,EAAA,CAAA;AAAA,sBAChF,IAAA,CAAC,QAAK,KAAO,EAAA;AAAA,QAC3B,IAAM,EAAA,CAAA;AAAA,QACN,UAAY,EAAA;AAAA,OAEM,EAAA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,SAAW,EAAA;AAAA,UAChD,OAAO,KAAM,CAAA;AAAA,SACd,GAAG,QAAqB,EAAA,uBAAA,EAAA,CAAA;AAAA,wBACN,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,UAAY,EAAA;AAAA,UACjD,OAAO,KAAM,CAAA;AAAA,SACd,GAAG,QAEc,EAAA,kCAAA,EAAA;AAAA,OACJ,EAAA,CAAA;AAAA,sBACA,GAAA,CAAC,0BAAuB,IAAK,EAAA,eAAA,EAAgB,MAAM,EAAI,EAAA,KAAA,EAAO,MAAM,SAAW,EAAA;AAAA,KAAA,EACnF,GACJ,CAAe,GAAA,IAAA;AAAA,oBAClB,GAAA,CAAA,gBAAA,EAAA,EAAiB,KAAO,EAAA,eAAA,EAAiB,KAAc,EAAA,CAAA;AAAA,wBACvD,YAAa,EAAA,EAAA,OAAA,EAAS,KAAO,EAAA,KAAA,EAAc,WAAW,cAAgB,EAAA,CAAA;AAAA,wBACtE,YAAa,EAAA,EAAA,OAAA,EAAS,QAAQ,KAAc,EAAA,SAAA,EAAW,MAAM,eAAqB,IAAA,IAAA,GAAA,MAAA,GAAA,eAAA,EAAA,EAAA,CAAA;AAAA,IAClF,KAAQ,mBAAA,GAAA,CAAC,SAAU,EAAA,EAAA,OAAA,EAAS,OAAS,EAAA,iBAAA,EAAkB,QAAS,EAAA,kBAAA,EAAmB,qBAAsB,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,WAAa,EAAA;AAAA,MAC5I,iBAAiB,KAAM,CAAA;AAAA,KACxB,CACe,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,eAAiB,EAAA;AAAA,MAClD,OAAO,KAAM,CAAA;AAAA,KACd,CAAA,EAAG,QAAmB,EAAA,qBAAA,EAAA,CAAA,EACb,CAAe,GAAA,IAAA;AAAA,IAElB,OAAW,IAAA,aAAA,CAAc,MAAW,KAAA,CAAA,uBAAK,IAAK,EAAA,EAAA,KAAA,EAAO,MAAO,CAAA,MAAA,EACrD,8BAAC,iBAAkB,EAAA,EAAA,KAAA,EAAO,KAAM,CAAA,MAAA,EAAQ,GAC5C,CAAU,mBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QAAS,IAAM,EAAA,OAAA;AAAA,QAAS,YAAA,EAAc,CAAK,CAAA,KAAA,mBAAA,CAAoB,CAAC,CAAA;AAAA,QAAG,sBAAwB,EAAA,SAAA;AAAA,QAAW,mBAAA,EAAqB,CAAC,QAAY,IAAA,aAAA,GAAgB,KAAK,cAAiB,mBAAA,GAAA,CAAC,SAAU,EAAA,EAAA,OAAA,EAAS,cAAgB,EAAA,iBAAA,EAAkB,UAAS,kBAAoB,EAAA,CAAA,UAAA,EAAa,aAAa,CAAA,MAAA,CAAA,EAAU,MAAO,EAAA,mBAAA,EACvS,+BAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,WAAa,EAAA;AAAA,UAC1D,aAAe,EAAA;AAAA,SAChB,CAC6B,EAAA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,MAAO,CAAA,YAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,sBAAA,EAAA,EAAuB,IAAK,EAAA,iBAAA,EAAkB,IAAM,EAAA,EAAA,EAAI,KAAO,EAAA,KAAA,CAAM,WAAW,CACrF,EAAA,CAAA;AAAA,0BACC,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,aAAe,EAAA;AAAA,YAC9D,OAAO,KAAM,CAAA;AAAA,WACd,GAAG,QAAQ,EAAA,UAAA,EAAA,CAAA;AAAA,0BACgB,GAAA,CAAC,QAAK,KAAO,EAAA;AAAA,YACvC,OAAO,KAAM,CAAA,MAAA;AAAA,YACb,QAAU,EAAA;AAAA,aACR,QAAc,EAAA,aAAA,EAAA;AAAA,SAAA,EACM,GACJ,CAAe,GAAA,IAAA;AAAA,QAAM,YAAY,CAAC;AAAA,UACxD;AAAA,8BACK,GAAA,CAAA,eAAA,EAAA,EAAgB,cAAc,IAAM,EAAA,KAAA,EAAc,KAAU,OAAS,EAAA,MAAM,OAAO,IAAK,CAAA,EAAE,GAAG,WAAa,EAAA,cAAA,GAAiB,MAAM,YAAa,CAAA,IAAI,IAAI,MAAW,EAAA,CAAA;AAAA,QAAI,gCAAiB,GAAA,CAAA,cAAA,EAAA,EAAe,YAAwB,SAAsB,EAAA,SAAA,EAAW,MAAM,SAAW,EAAA,CAAA;AAAA,QAErR,YAAA,EAAc,WAAW,MAAY,GAAA,UAAA;AAAA,QAAY,qBAAuB,EAAA,GAAA;AAAA,QAAK,mBAAA,EAAqB,WAAc,mBAAA,GAAA,CAAC,iBAAkB,EAAA,EAAA,KAAA,EAAO,OAAO,WAAa,EAAA,KAAA,EAAO,KAAM,CAAA,MAAA,EAAQ,CAAK,GAAA,IAAA;AAAA,QAAM,qBAAuB,EAAA,OAAA,CAAQ,MAAW,KAAA,CAAA,GAAI,OAAO,IAAO,GAAA,MAAA;AAAA,QAAW,kBAAoB,kBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,IAAA,EAAK,sBAAuB,EAAA,KAAA,EAAO,KAAM,CAAA,KAAA,EAAO,MAAQ,EAAA,KAAA,CAAM,MAAQ,EAAA,KAAA,EAAc,QAAQ,WAAa,EAAA,CAAA;AAAA,QAAI,MAAO,EAAA;AAAA;AAAA,KAAyB;AAAA,wBACza,WAAY,EAAA,EAAA,OAAA,EAAS,QAAQ,SAAS,CAAA,EAAG,OAAO,SAAW,IAAA,IAAA,GAAA,MAAA,GAAA,SAAA,CAAA,KAAA,EAAO,OAAS,EAAA,UAAA,EAAY,OAAc,OAAS,EAAA,MAAM,aAAa,IAAI,CAAA,EAAG,QAAO,gBAAiB,EAAA,CAAA;AAAA,oBAChK,GAAA,CAAA,WAAA,EAAA,EAAY,OAAS,EAAA,QAAA,EAAU,OAAS,EAAA,WAAA,EAAa,KAAc,EAAA,OAAA,EAAS,MAAM,WAAA,CAAY,KAAK,CAAA,EAAG,QAAO,sBAAuB,EAAA;AAAA,GACzI,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,IAAM,EAAA;AAAA,IACJ,IAAM,EAAA;AAAA,GACR;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,CAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,WAAa,EAAA;AAAA,IACX,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,UAAY,EAAA;AAAA,IACV,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,eAAA;AAAA,IAChB,iBAAmB,EAAA,EAAA;AAAA,IACnB,UAAY,EAAA,CAAA;AAAA,IACZ,aAAe,EAAA;AAAA,GACjB;AAAA,EACA,SAAW,EAAA;AAAA,IACT,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,aAAe,EAAA;AAAA,GACjB;AAAA,EACA,aAAe,EAAA;AAAA,IACb,KAAO,EAAA,EAAA;AAAA,IACP,MAAQ,EAAA,EAAA;AAAA,IACR,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,mBAAqB,EAAA;AAAA,IACnB,KAAO,EAAA;AAAA,GACT;AAAA,EACA,cAAgB,EAAA;AAAA,IACd,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,eAAA;AAAA,IAChB,iBAAmB,EAAA,CAAA;AAAA,IACnB,SAAW,EAAA,EAAA;AAAA,IACX,mBAAmB,UAAW,CAAA,aAAA;AAAA,IAC9B,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,aAAe,EAAA;AAAA,IACb,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,YAAc,EAAA;AAAA,IACZ,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,EAAA;AAAA,IACZ,SAAW,EAAA,QAAA;AAAA,IACX,gBAAkB,EAAA,EAAA;AAAA,IAClB,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,OAAS,EAAA;AAAA,GACX;AAAA,EACA,WAAa,EAAA;AAAA,IACX,UAAY,EAAA,QAAA;AAAA,IACZ,iBAAmB,EAAA,EAAA;AAAA,IACnB,SAAW,EAAA;AAAA,GACb;AAAA,EACA,YAAc,EAAA;AAAA,IACZ,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA;AAAA,GACd;AAAA,EACA,aAAe,EAAA;AAAA,IACb,IAAM,EAAA,CAAA;AAAA,IACN,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,UAAY,EAAA;AAAA,GACd;AAAA,EACA,OAAS,EAAA;AAAA,IACP,gBAAkB,EAAA,EAAA;AAAA,IAClB,YAAc,EAAA,CAAA;AAAA,IACd,YAAc,EAAA,EAAA;AAAA,IACd,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,SAAW,EAAA;AAAA,IACT,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,UAAY,EAAA;AAAA,IACV,QAAU,EAAA,EAAA;AAAA,IACV,SAAW,EAAA;AAAA,GACb;AAAA,EACA,UAAY,EAAA;AAAA,IACV,KAAO,EAAA,EAAA;AAAA,IACP,MAAQ,EAAA,EAAA;AAAA,IACR,YAAc,EAAA,EAAA;AAAA,IACd,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,KAAO,EAAA;AAAA,IACL,iBAAmB,EAAA,EAAA;AAAA,IACnB,aAAe,EAAA,CAAA;AAAA,IACf,UAAY,EAAA;AAAA,GACd;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,iBAAmB,EAAA,EAAA;AAAA,IACnB,MAAQ,EAAA,EAAA;AAAA,IACR,YAAc,EAAA,EAAA;AAAA,IACd,cAAgB,EAAA,QAAA;AAAA,IAChB,WAAa,EAAA;AAAA,GACf;AAAA,EACA,QAAU,EAAA;AAAA,IACR,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,UAAY,EAAA;AAAA,IACV,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,gBAAkB,EAAA,EAAA;AAAA,IAClB,YAAc,EAAA,CAAA;AAAA,IACd,YAAc,EAAA,EAAA;AAAA,IACd,iBAAmB,EAAA,EAAA;AAAA,IACnB,MAAQ,EAAA;AAAA,GACV;AAAA,EACA,WAAa,EAAA;AAAA,IACX,IAAM,EAAA,CAAA;AAAA,IACN,UAAY,EAAA,CAAA;AAAA,IACZ,QAAU,EAAA,EAAA;AAAA,IACV,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,SAAW,EAAA;AAAA,IACT,QAAQ,UAAW,CAAA,aAAA;AAAA,IACnB,UAAY,EAAA;AAAA,GACd;AAAA,EACA,WAAa,EAAA;AAAA,IACX,UAAY,EAAA,QAAA;AAAA,IACZ,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,eAAiB,EAAA;AAAA,IACf,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA;AAEhB,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"ConversationListScreen.js","sources":["../../../src/features/messaging/ConversationListScreen.tsx"],"sourcesContent":["/**\n * The conversation list, WhatsApp-style: a large \"Chats\" title, search, the\n * All / Unread / Groups filter chips, and rows with ticks, mute and a green\n * unread badge.\n */\nimport * as React from 'react';\nimport {\n ActivityIndicator,\n FlatList,\n Pressable,\n RefreshControl,\n StyleSheet,\n Text,\n TextInput,\n View,\n} from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { ConnectionBanner, ConversationRow, EmptyState, InlineBanner, type ChatTheme } from './ChatComponents';\nimport {\n conversationListKey,\n dedupeConversationList,\n emptyListCopy,\n filterConversations,\n type ChatConversation,\n type ChatListFilter,\n} from './chatModel';\nimport { usePressed } from './usePressed';\nimport { ActionSheet, type SheetAction } from './ActionSheet';\nimport type { ChatConnectionState, ChatPushSeam } from './chatHost';\n\nconst FILTERS: ReadonlyArray<{ key: ChatListFilter; label: string }> = [\n { key: 'all', label: 'All' },\n { key: 'unread', label: 'Unread' },\n { key: 'groups', label: 'Groups' },\n];\n\nfunction FilterChip({\n label,\n active,\n theme,\n onPress,\n}: {\n label: string;\n active: boolean;\n theme: ChatTheme;\n onPress: () => void;\n}) {\n const [pressed, pressHandlers] = usePressed();\n const activeBg = theme.isDark ? 'rgba(0, 168, 132, 0.25)' : '#d8fdd2';\n const activeText = theme.isDark ? '#d8fdd2' : '#0b5c44';\n return (\n <Pressable\n onPress={onPress}\n {...pressHandlers}\n accessibilityRole=\"tab\"\n accessibilityState={{ selected: active }}\n style={[styles.chip, { backgroundColor: active ? activeBg : theme.surface, opacity: pressed ? 0.7 : 1 }]}\n testID={`chat-filter-${label.toLowerCase()}`}\n >\n <Text style={[styles.chipText, { color: active ? activeText : theme.textMuted }]}>{label}</Text>\n </Pressable>\n );\n}\n\nexport function ConversationListScreen({\n conversations,\n loading,\n refreshing,\n error,\n theme,\n connectionState,\n canInvite,\n onRefresh,\n onRetry,\n onOpen,\n onNewChat,\n onNewGroup,\n onOpenNotifications,\n pushStatus,\n onEnablePush,\n onDismissError,\n notice = null,\n onDismissNotice,\n loadingMore = false,\n onLoadMore,\n mode = 'chats',\n archivedCount = 0,\n onOpenArchived,\n onOpenStarred,\n onOpenBlocked,\n onBack,\n onSetListState,\n}: {\n conversations: ChatConversation[];\n loading: boolean;\n refreshing: boolean;\n loadingMore?: boolean;\n onLoadMore?: () => void;\n error: string | null;\n theme: ChatTheme;\n connectionState: ChatConnectionState;\n canInvite: boolean;\n onRefresh: () => void;\n onRetry: () => void;\n onOpen: (id: string) => void;\n onNewChat: () => void;\n /** Open the New group flow (from the list menu). */\n onNewGroup?: () => void;\n /** Opens the chat notification settings; absent hides the bell. */\n onOpenNotifications?: () => void;\n /** This phone's push permission; anything but granted shows the \"Turn on notifications\" row. */\n pushStatus?: ChatPushSeam['status'];\n onEnablePush?: () => void;\n onDismissError: () => void;\n /** A one-off message that is not a load failure (e.g. an invite that could not be opened). */\n notice?: string | null;\n onDismissNotice?: () => void;\n /** The main list, or the chats the viewer archived. */\n mode?: 'chats' | 'archived';\n /** Archived chats, for the \"Archived\" row at the top of the main list. */\n archivedCount?: number;\n onOpenArchived?: () => void;\n onOpenStarred?: () => void;\n /** Open the blocked-contacts privacy list from the overflow menu. */\n onOpenBlocked?: () => void;\n /** Archived mode's back button. */\n onBack?: () => void;\n /** Pin / archive from a row's long-press options; absent disables them. */\n onSetListState?: (channelId: string, state: { pinned?: boolean; archived?: boolean }) => void;\n}) {\n const archived = mode === 'archived';\n const [rowTarget, setRowTarget] = React.useState<ChatConversation | null>(null);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const rowActions = React.useMemo<SheetAction[]>(() => {\n const target = rowTarget;\n if (!target || !onSetListState) return [];\n const list: SheetAction[] = [];\n if (!archived) {\n list.push({\n key: target.pinnedAt > 0 ? 'unpin' : 'pin',\n label: target.pinnedAt > 0 ? 'Unpin chat' : 'Pin chat',\n icon: target.pinnedAt > 0 ? 'pin-off-outline' : 'pin-outline',\n onPress: () => onSetListState(target.id, { pinned: !(target.pinnedAt > 0) }),\n });\n }\n list.push({\n key: archived ? 'unarchive' : 'archive',\n label: archived ? 'Unarchive chat' : 'Archive chat',\n icon: archived ? 'archive-arrow-up-outline' : 'archive-arrow-down-outline',\n onPress: () => onSetListState(target.id, { archived: !archived }),\n });\n return list;\n }, [rowTarget, onSetListState, archived]);\n const menuActions = React.useMemo<SheetAction[]>(() => {\n const list: SheetAction[] = [];\n if (onNewGroup)\n list.push({ key: 'new-group', label: 'New group', icon: 'account-group-outline', onPress: onNewGroup });\n if (onOpenStarred)\n list.push({ key: 'starred', label: 'Starred messages', icon: 'star-outline', onPress: onOpenStarred });\n if (onOpenArchived) {\n list.push({ key: 'archived', label: 'Archived chats', icon: 'archive-outline', onPress: onOpenArchived });\n }\n if (onOpenBlocked) {\n list.push({\n key: 'blocked',\n label: 'Blocked contacts',\n icon: 'account-cancel-outline',\n onPress: onOpenBlocked,\n });\n }\n if (onOpenNotifications) {\n list.push({\n key: 'notifications',\n label: 'Notifications',\n icon: 'bell-outline',\n onPress: onOpenNotifications,\n });\n }\n return list;\n }, [onNewGroup, onOpenStarred, onOpenArchived, onOpenBlocked, onOpenNotifications]);\n const [now, setNow] = React.useState(() => Date.now());\n const [query, setQuery] = React.useState('');\n const [filter, setFilter] = React.useState<ChatListFilter>('all');\n React.useEffect(() => {\n const t = setInterval(() => setNow(Date.now()), 60_000);\n return () => clearInterval(t);\n }, []);\n\n const visible = React.useMemo(() => {\n const inMode = conversations.filter((c) => (archived ? c.archivedAt > 0 : !(c.archivedAt > 0)));\n const deduped = filterConversations(dedupeConversationList(inMode), filter);\n const q = query.trim().toLowerCase();\n if (!q) return deduped;\n return deduped.filter((c) => c.title.toLowerCase().includes(q) || c.subtitle.toLowerCase().includes(q));\n }, [conversations, query, filter, archived]);\n const narrowed = Boolean(query.trim()) || filter !== 'all';\n const empty = emptyListCopy({ searching: Boolean(query.trim()), filter, canInvite });\n let emptyAction: { label: string; onPress: () => void } | undefined;\n if (empty.action === 'all') emptyAction = { label: 'Show all chats', onPress: () => setFilter('all') };\n else if (empty.action === 'new') emptyAction = { label: 'New chat', onPress: onNewChat };\n\n const Separator = React.useCallback(\n () => <View style={[styles.separator, { backgroundColor: theme.border }]} />,\n [theme.border],\n );\n\n const listHeader = archived ? (\n // The host hides its header off the main list, so this one owns the top inset.\n <SafeAreaView edges={['top']} style={{ backgroundColor: theme.headerBg }}>\n <View style={[styles.archivedHeader, { borderBottomColor: theme.border, flexDirection: 'row' }]}>\n <Pressable\n onPress={onBack}\n hitSlop={10}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Back\"\n style={styles.headerCompose}\n testID=\"chat-archived-back\"\n >\n <MaterialCommunityIcons name=\"chevron-left\" size={32} color={theme.accent} />\n </Pressable>\n <Text style={[styles.archivedTitle, { color: theme.text }]}>Archived</Text>\n <View style={styles.headerComposeSpacer} />\n </View>\n </SafeAreaView>\n ) : (\n <View style={[styles.listHeader, { flexDirection: 'row', alignItems: 'center' }]}>\n <Text style={[styles.listTitle, { color: theme.text }]}>Chats</Text>\n <View style={{ flexDirection: 'row', alignItems: 'center' }}>\n {menuActions.length ? (\n <Pressable\n onPress={() => setMenuOpen(true)}\n accessibilityRole=\"button\"\n accessibilityLabel=\"More\"\n style={styles.headerCompose}\n testID=\"chat-list-menu\"\n >\n <MaterialCommunityIcons name=\"dots-horizontal-circle-outline\" size={26} color={theme.accent} />\n </Pressable>\n ) : null}\n {canInvite ? (\n <Pressable\n onPress={onNewChat}\n accessibilityRole=\"button\"\n accessibilityLabel=\"New chat\"\n style={styles.headerCompose}\n testID=\"chat-new\"\n >\n <View style={[styles.composeDot, { backgroundColor: theme.accent }]}>\n <MaterialCommunityIcons name=\"plus\" size={20} color={theme.onAccent} />\n </View>\n </Pressable>\n ) : (\n <View style={styles.headerComposeSpacer} />\n )}\n </View>\n </View>\n );\n\n return (\n <View style={[styles.fill, { backgroundColor: theme.bg }]}>\n {listHeader}\n <View style={[styles.searchWrap, { backgroundColor: theme.surface }]}>\n <MaterialCommunityIcons name=\"magnify\" size={20} color={theme.textMuted} />\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search\"\n placeholderTextColor={theme.textMuted}\n style={[styles.searchInput, { color: theme.text }]}\n testID=\"chat-search\"\n />\n </View>\n {archived ? (\n <Text style={[styles.archivedNote, { color: theme.textMuted }]}>\n Archived chats stay here when new messages arrive. Unarchive one to put it back in Chats.\n </Text>\n ) : null}\n <View style={[styles.chips, { flexDirection: 'row' }, archived && styles.hidden]}>\n {FILTERS.map((f) => (\n <FilterChip\n key={f.key}\n label={f.label}\n active={filter === f.key}\n theme={theme}\n onPress={() => setFilter(f.key)}\n />\n ))}\n </View>\n\n {!archived && onEnablePush && (pushStatus === 'undetermined' || pushStatus === 'denied') ? (\n <Pressable\n onPress={pushStatus === 'denied' && onOpenNotifications ? onOpenNotifications : onEnablePush}\n accessibilityRole=\"button\"\n style={[styles.pushRow, { backgroundColor: theme.isDark ? '#103629' : '#e7fce3' }]}\n testID=\"chat-push-banner\"\n >\n <View style={{ flexDirection: 'row', alignItems: 'center' }}>\n <MaterialCommunityIcons name=\"bell-ring-outline\" size={22} color={theme.accent} />\n <View style={{ flex: 1, marginLeft: 12 }}>\n <Text style={[styles.pushTitle, { color: theme.text }]}>Turn on notifications</Text>\n <Text style={[styles.pushDetail, { color: theme.textMuted }]}>\n Get notified about new messages.\n </Text>\n </View>\n <MaterialCommunityIcons name=\"chevron-right\" size={22} color={theme.textMuted} />\n </View>\n </Pressable>\n ) : null}\n <ConnectionBanner state={connectionState} theme={theme} />\n <InlineBanner message={error} theme={theme} onDismiss={onDismissError} />\n <InlineBanner message={notice} theme={theme} onDismiss={() => onDismissNotice?.()} />\n {error ? (\n <Pressable\n onPress={onRetry}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Retry loading chats\"\n style={[styles.retryBanner, { backgroundColor: theme.surface }]}\n >\n <Text style={[styles.retryBannerText, { color: theme.accent }]}>Retry loading chats</Text>\n </Pressable>\n ) : null}\n\n {loading && conversations.length === 0 ? (\n <View style={styles.center}>\n <ActivityIndicator color={theme.accent} />\n </View>\n ) : (\n <FlatList\n data={visible}\n keyExtractor={(c) => conversationListKey(c)}\n ItemSeparatorComponent={Separator}\n ListHeaderComponent={\n !archived && archivedCount > 0 && onOpenArchived ? (\n <Pressable\n onPress={onOpenArchived}\n accessibilityRole=\"button\"\n accessibilityLabel={`Archived, ${archivedCount} chats`}\n testID=\"chat-archived-row\"\n >\n <View style={[styles.archivedRow, { flexDirection: 'row' }]}>\n <View style={styles.archivedIcon}>\n <MaterialCommunityIcons\n name=\"archive-outline\"\n size={22}\n color={theme.textMuted}\n />\n </View>\n <Text style={[styles.archivedLabel, { color: theme.text }]}>Archived</Text>\n <Text style={{ color: theme.accent, fontSize: 14 }}>{archivedCount}</Text>\n </View>\n </Pressable>\n ) : null\n }\n renderItem={({ item }) => (\n <ConversationRow\n conversation={item}\n theme={theme}\n now={now}\n onPress={() => onOpen(item.id)}\n onLongPress={onSetListState ? () => setRowTarget(item) : undefined}\n />\n )}\n refreshControl={\n <RefreshControl refreshing={refreshing} onRefresh={onRefresh} tintColor={theme.textMuted} />\n }\n // Paging would skip rows while a search or a filter chip is hiding most of them.\n onEndReached={narrowed ? undefined : onLoadMore}\n onEndReachedThreshold={0.5}\n ListFooterComponent={\n loadingMore ? <ActivityIndicator style={styles.moreSpinner} color={theme.accent} /> : null\n }\n contentContainerStyle={visible.length === 0 ? styles.fill : undefined}\n ListEmptyComponent={\n <EmptyState\n icon=\"message-text-outline\"\n title={empty.title}\n detail={empty.detail}\n theme={theme}\n action={emptyAction}\n />\n }\n testID=\"chat-conversation-list\"\n />\n )}\n <ActionSheet\n visible={Boolean(rowTarget)}\n title={rowTarget?.title}\n actions={rowActions}\n theme={theme}\n onClose={() => setRowTarget(null)}\n testID=\"chat-row-sheet\"\n />\n <ActionSheet\n visible={menuOpen}\n actions={menuActions}\n theme={theme}\n onClose={() => setMenuOpen(false)}\n testID=\"chat-list-menu-sheet\"\n />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center' },\n moreSpinner: { paddingVertical: 16 },\n listHeader: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingTop: 4,\n paddingBottom: 4,\n },\n listTitle: { fontSize: 34, fontWeight: '700', letterSpacing: 0.35 },\n headerCompose: {\n width: 44,\n height: 44,\n alignItems: 'center',\n justifyContent: 'center',\n },\n headerComposeSpacer: { width: 44 },\n archivedHeader: {\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 4,\n minHeight: 52,\n borderBottomWidth: StyleSheet.hairlineWidth,\n marginBottom: 8,\n },\n archivedTitle: { fontSize: 17, fontWeight: '600' },\n archivedNote: { fontSize: 13, lineHeight: 18, textAlign: 'center', marginHorizontal: 32, marginBottom: 8 },\n hidden: { display: 'none' },\n archivedRow: { alignItems: 'center', paddingHorizontal: 16, minHeight: 48 },\n archivedIcon: { width: 52, alignItems: 'center' },\n archivedLabel: { flex: 1, fontSize: 16, fontWeight: '600', marginLeft: 14 },\n pushRow: { marginHorizontal: 16, marginBottom: 8, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12 },\n pushTitle: { fontSize: 15, fontWeight: '600' },\n pushDetail: { fontSize: 13, marginTop: 1 },\n composeDot: { width: 28, height: 28, borderRadius: 14, alignItems: 'center', justifyContent: 'center' },\n chips: { paddingHorizontal: 16, paddingBottom: 8, paddingTop: 2 },\n chip: { paddingHorizontal: 14, height: 32, borderRadius: 16, justifyContent: 'center', marginRight: 8 },\n chipText: { fontSize: 14, fontWeight: '500' },\n searchWrap: {\n flexDirection: 'row',\n alignItems: 'center',\n marginHorizontal: 16,\n marginBottom: 6,\n borderRadius: 10,\n paddingHorizontal: 10,\n height: 36,\n },\n searchInput: { flex: 1, marginLeft: 8, fontSize: 16, paddingVertical: 0 },\n separator: { height: StyleSheet.hairlineWidth, marginLeft: 82 },\n retryBanner: { alignItems: 'center', paddingVertical: 10 },\n retryBannerText: { fontSize: 14, fontWeight: '600' },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import {jsxs,jsx}from'react/jsx-runtime';import*as React from'react';import {StyleSheet,Dimensions,View,Pressable,Text,ActivityIndicator,FlatList}from'react-native';import {SafeAreaView}from'react-native-safe-area-context';import {Image}from'expo-image';import {MaterialCommunityIcons}from'@expo/vector-icons';import {InlineBanner,EmptyState}from'./ChatComponents.js';import {useLinkPreview,LinkPreviewCard}from'./LinkPreviewCard.js';import {toChatMessage,toChatAttachments,attachmentUrl}from'./chatModel.js';import {firstLink}from'./chatLinks.js';import {MEDIA_MESSAGES_QUERY}from'./chatOperations.js';const TABS = [{
|
|
2
|
+
key: "media",
|
|
3
|
+
label: "Media"
|
|
4
|
+
}, {
|
|
5
|
+
key: "links",
|
|
6
|
+
label: "Links"
|
|
7
|
+
}, {
|
|
8
|
+
key: "docs",
|
|
9
|
+
label: "Docs"
|
|
10
|
+
}];
|
|
11
|
+
const GRID_COLS = 3;
|
|
12
|
+
const GRID_GAP = 2;
|
|
13
|
+
function LinkRow({
|
|
14
|
+
url,
|
|
15
|
+
theme,
|
|
16
|
+
loader,
|
|
17
|
+
onOpen
|
|
18
|
+
}) {
|
|
19
|
+
const preview = useLinkPreview(url, loader);
|
|
20
|
+
if (preview) {
|
|
21
|
+
return /* @__PURE__ */ jsx(View, { style: styles.linkRow, children: /* @__PURE__ */ jsx(LinkPreviewCard, { preview, theme, onOpen }) });
|
|
22
|
+
}
|
|
23
|
+
return /* @__PURE__ */ jsxs(Pressable, { onPress: onOpen ? () => onOpen(url) : void 0, style: [styles.linkFallback, {
|
|
24
|
+
borderColor: theme.border
|
|
25
|
+
}], accessibilityRole: "link", children: [
|
|
26
|
+
/* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "link-variant", size: 18, color: theme.accent }),
|
|
27
|
+
/* @__PURE__ */ jsx(Text, { numberOfLines: 1, style: [styles.linkFallbackText, {
|
|
28
|
+
color: theme.accent
|
|
29
|
+
}], children: url })
|
|
30
|
+
] });
|
|
31
|
+
}
|
|
32
|
+
function MediaGalleryScreen({
|
|
33
|
+
gql,
|
|
34
|
+
channelId,
|
|
35
|
+
viewerId,
|
|
36
|
+
theme,
|
|
37
|
+
fileBaseUrl,
|
|
38
|
+
linkPreviews,
|
|
39
|
+
onOpenLink,
|
|
40
|
+
onOpenImage,
|
|
41
|
+
onBack
|
|
42
|
+
}) {
|
|
43
|
+
const [tab, setTab] = React.useState("media");
|
|
44
|
+
const [error, setError] = React.useState(null);
|
|
45
|
+
const [media, setMedia] = React.useState(null);
|
|
46
|
+
const [links, setLinks] = React.useState(null);
|
|
47
|
+
const [docs, setDocs] = React.useState(null);
|
|
48
|
+
const cellSize = Math.floor((Dimensions.get("window").width - GRID_GAP * (GRID_COLS - 1)) / GRID_COLS);
|
|
49
|
+
const load = React.useCallback(async (which) => {
|
|
50
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
51
|
+
const res = await gql.query(MEDIA_MESSAGES_QUERY, {
|
|
52
|
+
channelId,
|
|
53
|
+
kind: which,
|
|
54
|
+
limit: 100,
|
|
55
|
+
skip: 0
|
|
56
|
+
}, {
|
|
57
|
+
fetchPolicy: "network-only"
|
|
58
|
+
}).catch(() => null);
|
|
59
|
+
if ((_a = res == null ? void 0 : res.errors) == null ? void 0 : _a.length) setError("Couldn\u2019t load this gallery.");
|
|
60
|
+
const posts = ((_d = (_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b.mediaMessages) == null ? void 0 : _c.data) != null ? _d : []).filter((p) => Boolean(p == null ? void 0 : p.id));
|
|
61
|
+
if (which === "links") {
|
|
62
|
+
setLinks(posts.map((p) => {
|
|
63
|
+
var _a2, _b2, _c2;
|
|
64
|
+
const message = toChatMessage(p, viewerId);
|
|
65
|
+
const url = firstLink(message.body);
|
|
66
|
+
return url ? {
|
|
67
|
+
messageId: message.id,
|
|
68
|
+
channelId: String((_c2 = (_b2 = (_a2 = p.channel) == null ? void 0 : _a2.id) != null ? _b2 : channelId) != null ? _c2 : ""),
|
|
69
|
+
url
|
|
70
|
+
} : null;
|
|
71
|
+
}).filter((x) => Boolean(x)));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const items = [];
|
|
75
|
+
for (const p of posts) {
|
|
76
|
+
const cid = String((_g = (_f = (_e = p.channel) == null ? void 0 : _e.id) != null ? _f : channelId) != null ? _g : "");
|
|
77
|
+
for (const attachment of toChatAttachments(p)) {
|
|
78
|
+
if (which === "media" && attachment.kind === "image") items.push({
|
|
79
|
+
messageId: p.id,
|
|
80
|
+
channelId: cid,
|
|
81
|
+
attachment
|
|
82
|
+
});
|
|
83
|
+
if (which === "docs" && attachment.kind === "file") items.push({
|
|
84
|
+
messageId: p.id,
|
|
85
|
+
channelId: cid,
|
|
86
|
+
attachment
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (which === "media") setMedia(items);
|
|
91
|
+
else setDocs(items);
|
|
92
|
+
}, [gql, channelId, viewerId]);
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
if (tab === "media" && media === null) void load("media");
|
|
95
|
+
if (tab === "links" && links === null) void load("links");
|
|
96
|
+
if (tab === "docs" && docs === null) void load("docs");
|
|
97
|
+
}, [tab, media, links, docs, load]);
|
|
98
|
+
const loaded = () => {
|
|
99
|
+
if (tab === "media") return media;
|
|
100
|
+
if (tab === "docs") return docs;
|
|
101
|
+
return links;
|
|
102
|
+
};
|
|
103
|
+
const renderMediaList = () => {
|
|
104
|
+
var _a;
|
|
105
|
+
return /* @__PURE__ */ jsx(FlatList, { data: media != null ? media : [], numColumns: GRID_COLS, keyExtractor: (m) => m.attachment.id, contentContainerStyle: ((_a = media == null ? void 0 : media.length) != null ? _a : 0) ? void 0 : styles.fill, ListEmptyComponent: /* @__PURE__ */ jsx(EmptyState, { icon: "image-off-outline", title: "No media", detail: "Photos and videos in this chat show here.", theme }), renderItem: ({
|
|
106
|
+
item,
|
|
107
|
+
index
|
|
108
|
+
}) => /* @__PURE__ */ jsx(Pressable, { onPress: () => onOpenImage == null ? void 0 : onOpenImage(attachmentUrl(item.attachment, fileBaseUrl)), style: {
|
|
109
|
+
width: cellSize,
|
|
110
|
+
height: cellSize,
|
|
111
|
+
marginRight: (index + 1) % GRID_COLS === 0 ? 0 : GRID_GAP,
|
|
112
|
+
marginBottom: GRID_GAP
|
|
113
|
+
}, accessibilityRole: "imagebutton", accessibilityLabel: "Open photo", children: /* @__PURE__ */ jsx(Image, { source: {
|
|
114
|
+
uri: item.attachment.url
|
|
115
|
+
}, style: {
|
|
116
|
+
width: cellSize,
|
|
117
|
+
height: cellSize,
|
|
118
|
+
backgroundColor: theme.surface
|
|
119
|
+
}, contentFit: "cover", transition: 120 }) }) }, "media");
|
|
120
|
+
};
|
|
121
|
+
const renderDocsList = () => {
|
|
122
|
+
var _a;
|
|
123
|
+
return /* @__PURE__ */ jsx(FlatList, { data: docs != null ? docs : [], keyExtractor: (m) => m.attachment.id, contentContainerStyle: ((_a = docs == null ? void 0 : docs.length) != null ? _a : 0) ? void 0 : styles.fill, ListEmptyComponent: /* @__PURE__ */ jsx(EmptyState, { icon: "file-outline", title: "No docs", detail: "Documents shared in this chat show here.", theme }), renderItem: ({
|
|
124
|
+
item
|
|
125
|
+
}) => /* @__PURE__ */ jsxs(Pressable, { onPress: () => onOpenLink == null ? void 0 : onOpenLink(attachmentUrl(item.attachment, fileBaseUrl)), style: [styles.docRow, {
|
|
126
|
+
borderBottomColor: theme.border,
|
|
127
|
+
flexDirection: "row"
|
|
128
|
+
}], accessibilityRole: "button", accessibilityLabel: `Open ${item.attachment.name}`, children: [
|
|
129
|
+
/* @__PURE__ */ jsx(View, { style: [styles.docIcon, {
|
|
130
|
+
backgroundColor: theme.surface
|
|
131
|
+
}], children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "file-document-outline", size: 22, color: theme.accent }) }),
|
|
132
|
+
/* @__PURE__ */ jsx(View, { style: {
|
|
133
|
+
flex: 1
|
|
134
|
+
}, children: /* @__PURE__ */ jsx(Text, { numberOfLines: 1, style: [styles.docName, {
|
|
135
|
+
color: theme.text
|
|
136
|
+
}], children: item.attachment.name }) })
|
|
137
|
+
] }) }, "docs");
|
|
138
|
+
};
|
|
139
|
+
const renderLinksList = () => {
|
|
140
|
+
var _a;
|
|
141
|
+
return /* @__PURE__ */ jsx(FlatList, { data: links != null ? links : [], keyExtractor: (l, i) => `${l.messageId}-${i}`, contentContainerStyle: ((_a = links == null ? void 0 : links.length) != null ? _a : 0) ? styles.linkList : styles.fill, ListEmptyComponent: /* @__PURE__ */ jsx(EmptyState, { icon: "link-off", title: "No links", detail: "Links shared in this chat show here.", theme }), renderItem: ({
|
|
142
|
+
item
|
|
143
|
+
}) => /* @__PURE__ */ jsx(LinkRow, { url: item.url, theme, loader: linkPreviews, onOpen: onOpenLink }) }, "links");
|
|
144
|
+
};
|
|
145
|
+
const renderBody = () => {
|
|
146
|
+
if (loaded() === null) {
|
|
147
|
+
return /* @__PURE__ */ jsx(View, { style: styles.center, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.accent }) });
|
|
148
|
+
}
|
|
149
|
+
if (tab === "media") return renderMediaList();
|
|
150
|
+
if (tab === "docs") return renderDocsList();
|
|
151
|
+
return renderLinksList();
|
|
152
|
+
};
|
|
153
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles.fill, {
|
|
154
|
+
backgroundColor: theme.bg
|
|
155
|
+
}], testID: "chat-media-gallery", children: [
|
|
156
|
+
/* @__PURE__ */ jsxs(SafeAreaView, { edges: ["top"], style: {
|
|
157
|
+
backgroundColor: theme.headerBg
|
|
158
|
+
}, children: [
|
|
159
|
+
/* @__PURE__ */ jsxs(View, { style: [styles.header, {
|
|
160
|
+
borderBottomColor: theme.border,
|
|
161
|
+
flexDirection: "row"
|
|
162
|
+
}], children: [
|
|
163
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: onBack, hitSlop: 10, accessibilityRole: "button", accessibilityLabel: "Back", style: styles.headerIcon, children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "chevron-left", size: 32, color: theme.accent }) }),
|
|
164
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.title, {
|
|
165
|
+
color: theme.text
|
|
166
|
+
}], children: "Media, links and docs" }),
|
|
167
|
+
/* @__PURE__ */ jsx(View, { style: styles.headerIcon })
|
|
168
|
+
] }),
|
|
169
|
+
/* @__PURE__ */ jsx(View, { style: [styles.tabs, {
|
|
170
|
+
flexDirection: "row"
|
|
171
|
+
}], children: TABS.map((t) => {
|
|
172
|
+
const active = t.key === tab;
|
|
173
|
+
return /* @__PURE__ */ jsx(Pressable, { onPress: () => setTab(t.key), style: [styles.tab, active && {
|
|
174
|
+
borderBottomColor: theme.accent
|
|
175
|
+
}], accessibilityRole: "tab", accessibilityState: {
|
|
176
|
+
selected: active
|
|
177
|
+
}, children: /* @__PURE__ */ jsx(Text, { style: [styles.tabText, {
|
|
178
|
+
color: active ? theme.accent : theme.textMuted
|
|
179
|
+
}], children: t.label }) }, t.key);
|
|
180
|
+
}) })
|
|
181
|
+
] }),
|
|
182
|
+
/* @__PURE__ */ jsx(InlineBanner, { message: error, theme, onDismiss: () => setError(null) }),
|
|
183
|
+
renderBody()
|
|
184
|
+
] });
|
|
185
|
+
}
|
|
186
|
+
const styles = StyleSheet.create({
|
|
187
|
+
fill: {
|
|
188
|
+
flex: 1
|
|
189
|
+
},
|
|
190
|
+
center: {
|
|
191
|
+
flex: 1,
|
|
192
|
+
alignItems: "center",
|
|
193
|
+
justifyContent: "center"
|
|
194
|
+
},
|
|
195
|
+
header: {
|
|
196
|
+
alignItems: "center",
|
|
197
|
+
justifyContent: "space-between",
|
|
198
|
+
paddingHorizontal: 4,
|
|
199
|
+
minHeight: 52,
|
|
200
|
+
borderBottomWidth: StyleSheet.hairlineWidth
|
|
201
|
+
},
|
|
202
|
+
headerIcon: {
|
|
203
|
+
width: 44,
|
|
204
|
+
height: 44,
|
|
205
|
+
alignItems: "center",
|
|
206
|
+
justifyContent: "center"
|
|
207
|
+
},
|
|
208
|
+
title: {
|
|
209
|
+
fontSize: 17,
|
|
210
|
+
fontWeight: "600"
|
|
211
|
+
},
|
|
212
|
+
tabs: {
|
|
213
|
+
alignItems: "stretch"
|
|
214
|
+
},
|
|
215
|
+
tab: {
|
|
216
|
+
flex: 1,
|
|
217
|
+
alignItems: "center",
|
|
218
|
+
paddingVertical: 12,
|
|
219
|
+
borderBottomWidth: 2,
|
|
220
|
+
borderBottomColor: "transparent"
|
|
221
|
+
},
|
|
222
|
+
tabText: {
|
|
223
|
+
fontSize: 14,
|
|
224
|
+
fontWeight: "600"
|
|
225
|
+
},
|
|
226
|
+
docRow: {
|
|
227
|
+
alignItems: "center",
|
|
228
|
+
paddingHorizontal: 16,
|
|
229
|
+
paddingVertical: 10,
|
|
230
|
+
borderBottomWidth: StyleSheet.hairlineWidth
|
|
231
|
+
},
|
|
232
|
+
docIcon: {
|
|
233
|
+
width: 40,
|
|
234
|
+
height: 40,
|
|
235
|
+
borderRadius: 8,
|
|
236
|
+
alignItems: "center",
|
|
237
|
+
justifyContent: "center",
|
|
238
|
+
marginRight: 12
|
|
239
|
+
},
|
|
240
|
+
docName: {
|
|
241
|
+
fontSize: 15,
|
|
242
|
+
fontWeight: "500"
|
|
243
|
+
},
|
|
244
|
+
linkList: {
|
|
245
|
+
padding: 12
|
|
246
|
+
},
|
|
247
|
+
linkRow: {
|
|
248
|
+
marginBottom: 10
|
|
249
|
+
},
|
|
250
|
+
linkFallback: {
|
|
251
|
+
flexDirection: "row",
|
|
252
|
+
alignItems: "center",
|
|
253
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
254
|
+
borderRadius: 10,
|
|
255
|
+
paddingHorizontal: 12,
|
|
256
|
+
paddingVertical: 12,
|
|
257
|
+
marginBottom: 10
|
|
258
|
+
},
|
|
259
|
+
linkFallbackText: {
|
|
260
|
+
fontSize: 14,
|
|
261
|
+
marginLeft: 8,
|
|
262
|
+
flex: 1
|
|
263
|
+
}
|
|
264
|
+
});export{MediaGalleryScreen};//# sourceMappingURL=MediaGalleryScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaGalleryScreen.js","sources":["../../../src/features/messaging/MediaGalleryScreen.tsx"],"sourcesContent":["/**\n * \"Media, links and docs\" - WhatsApp's per-chat gallery, with a cross-chat (\"all chats\") mode\n * when no channelId is given. Three tabs:\n * Media - a 3-column grid of photo/video thumbnails; tap opens the full image.\n * Links - each message carrying a URL, as a link-preview card.\n * Docs - document attachments as rows; tap opens the file.\n * Each tab loads lazily on first view via mediaMessages(kind).\n */\nimport * as React from 'react';\nimport { ActivityIndicator, Dimensions, FlatList, Pressable, StyleSheet, Text, View } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { Image } from 'expo-image';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { EmptyState, InlineBanner, type ChatTheme } from './ChatComponents';\nimport { LinkPreviewCard, useLinkPreview } from './LinkPreviewCard';\nimport { attachmentUrl, toChatAttachments, toChatMessage, type ChatAttachment, type WirePost } from './chatModel';\nimport { firstLink } from './chatLinks';\nimport type { ChatGraphQLSeam } from './chatHost';\nimport type { LinkPreviewLoader } from './linkPreview';\nimport { MEDIA_MESSAGES_QUERY } from './chatOperations';\n\ntype Tab = 'media' | 'links' | 'docs';\nconst TABS: { key: Tab; label: string }[] = [\n { key: 'media', label: 'Media' },\n { key: 'links', label: 'Links' },\n { key: 'docs', label: 'Docs' },\n];\n\ninterface MediaItem {\n messageId: string;\n channelId: string;\n attachment: ChatAttachment;\n}\ninterface LinkItem {\n messageId: string;\n channelId: string;\n url: string;\n}\n\nconst GRID_COLS = 3;\nconst GRID_GAP = 2;\n\n/** One Links row: resolves the preview itself (useLinkPreview is a hook, so it needs its own component). */\nfunction LinkRow({\n url,\n theme,\n loader,\n onOpen,\n}: {\n url: string;\n theme: ChatTheme;\n loader?: LinkPreviewLoader;\n onOpen?: (url: string) => void;\n}) {\n const preview = useLinkPreview(url, loader);\n if (preview) {\n return (\n <View style={styles.linkRow}>\n <LinkPreviewCard preview={preview} theme={theme} onOpen={onOpen} />\n </View>\n );\n }\n // No card yet (or none available): a plain tappable URL, so the row is never empty.\n return (\n <Pressable\n onPress={onOpen ? () => onOpen(url) : undefined}\n style={[styles.linkFallback, { borderColor: theme.border }]}\n accessibilityRole=\"link\"\n >\n <MaterialCommunityIcons name=\"link-variant\" size={18} color={theme.accent} />\n <Text numberOfLines={1} style={[styles.linkFallbackText, { color: theme.accent }]}>\n {url}\n </Text>\n </Pressable>\n );\n}\n\nexport function MediaGalleryScreen({\n gql,\n channelId,\n viewerId,\n theme,\n fileBaseUrl,\n linkPreviews,\n onOpenLink,\n onOpenImage,\n onBack,\n}: {\n gql: ChatGraphQLSeam;\n /** A single chat, or null for the cross-chat \"all chats\" gallery. */\n channelId: string | null;\n viewerId: string;\n theme: ChatTheme;\n fileBaseUrl?: string | null;\n linkPreviews?: LinkPreviewLoader;\n onOpenLink?: (url: string) => void;\n /** Open a full-size image in the shared viewer. */\n onOpenImage?: (url: string) => void;\n onBack: () => void;\n}) {\n const [tab, setTab] = React.useState<Tab>('media');\n const [error, setError] = React.useState<string | null>(null);\n // Per-tab cache so switching back is instant; null = not loaded yet.\n const [media, setMedia] = React.useState<MediaItem[] | null>(null);\n const [links, setLinks] = React.useState<LinkItem[] | null>(null);\n const [docs, setDocs] = React.useState<MediaItem[] | null>(null);\n\n const cellSize = Math.floor((Dimensions.get('window').width - GRID_GAP * (GRID_COLS - 1)) / GRID_COLS);\n\n const load = React.useCallback(\n async (which: Tab) => {\n const res = await gql\n .query<{\n mediaMessages?: { data?: (WirePost | null)[] | null } | null;\n }>(\n MEDIA_MESSAGES_QUERY,\n { channelId, kind: which, limit: 100, skip: 0 },\n { fetchPolicy: 'network-only' },\n )\n .catch(() => null);\n if (res?.errors?.length) setError('Couldn’t load this gallery.');\n const posts = (res?.data?.mediaMessages?.data ?? []).filter((p): p is WirePost => Boolean(p?.id));\n if (which === 'links') {\n setLinks(\n posts\n .map((p) => {\n const message = toChatMessage(p, viewerId);\n const url = firstLink(message.body);\n return url\n ? { messageId: message.id, channelId: String(p.channel?.id ?? channelId ?? ''), url }\n : null;\n })\n .filter((x): x is LinkItem => Boolean(x)),\n );\n return;\n }\n // media + docs both come from attachments; split by kind.\n const items: MediaItem[] = [];\n for (const p of posts) {\n const cid = String(p.channel?.id ?? channelId ?? '');\n for (const attachment of toChatAttachments(p)) {\n if (which === 'media' && attachment.kind === 'image')\n items.push({ messageId: p.id, channelId: cid, attachment });\n if (which === 'docs' && attachment.kind === 'file')\n items.push({ messageId: p.id, channelId: cid, attachment });\n }\n }\n if (which === 'media') setMedia(items);\n else setDocs(items);\n },\n [gql, channelId, viewerId],\n );\n\n // Load the active tab the first time it is shown.\n React.useEffect(() => {\n if (tab === 'media' && media === null) void load('media');\n if (tab === 'links' && links === null) void load('links');\n if (tab === 'docs' && docs === null) void load('docs');\n }, [tab, media, links, docs, load]);\n\n const loaded = (): unknown[] | null => {\n if (tab === 'media') return media;\n if (tab === 'docs') return docs;\n return links;\n };\n\n const renderMediaList = () => (\n <FlatList\n key=\"media\"\n data={media ?? []}\n numColumns={GRID_COLS}\n keyExtractor={(m) => m.attachment.id}\n contentContainerStyle={(media?.length ?? 0) ? undefined : styles.fill}\n ListEmptyComponent={\n <EmptyState\n icon=\"image-off-outline\"\n title=\"No media\"\n detail=\"Photos and videos in this chat show here.\"\n theme={theme}\n />\n }\n renderItem={({ item, index }) => (\n <Pressable\n onPress={() => onOpenImage?.(attachmentUrl(item.attachment, fileBaseUrl))}\n style={{\n width: cellSize,\n height: cellSize,\n marginRight: (index + 1) % GRID_COLS === 0 ? 0 : GRID_GAP,\n marginBottom: GRID_GAP,\n }}\n accessibilityRole=\"imagebutton\"\n accessibilityLabel=\"Open photo\"\n >\n <Image\n source={{ uri: item.attachment.url }}\n style={{ width: cellSize, height: cellSize, backgroundColor: theme.surface }}\n contentFit=\"cover\"\n transition={120}\n />\n </Pressable>\n )}\n />\n );\n\n const renderDocsList = () => (\n <FlatList\n key=\"docs\"\n data={docs ?? []}\n keyExtractor={(m) => m.attachment.id}\n contentContainerStyle={(docs?.length ?? 0) ? undefined : styles.fill}\n ListEmptyComponent={\n <EmptyState\n icon=\"file-outline\"\n title=\"No docs\"\n detail=\"Documents shared in this chat show here.\"\n theme={theme}\n />\n }\n renderItem={({ item }) => (\n <Pressable\n onPress={() => onOpenLink?.(attachmentUrl(item.attachment, fileBaseUrl))}\n style={[styles.docRow, { borderBottomColor: theme.border, flexDirection: 'row' }]}\n accessibilityRole=\"button\"\n accessibilityLabel={`Open ${item.attachment.name}`}\n >\n <View style={[styles.docIcon, { backgroundColor: theme.surface }]}>\n <MaterialCommunityIcons name=\"file-document-outline\" size={22} color={theme.accent} />\n </View>\n <View style={{ flex: 1 }}>\n <Text numberOfLines={1} style={[styles.docName, { color: theme.text }]}>\n {item.attachment.name}\n </Text>\n </View>\n </Pressable>\n )}\n />\n );\n\n const renderLinksList = () => (\n <FlatList\n key=\"links\"\n data={links ?? []}\n keyExtractor={(l, i) => `${l.messageId}-${i}`}\n contentContainerStyle={(links?.length ?? 0) ? styles.linkList : styles.fill}\n ListEmptyComponent={\n <EmptyState\n icon=\"link-off\"\n title=\"No links\"\n detail=\"Links shared in this chat show here.\"\n theme={theme}\n />\n }\n renderItem={({ item }) => (\n <LinkRow url={item.url} theme={theme} loader={linkPreviews} onOpen={onOpenLink} />\n )}\n />\n );\n\n const renderBody = () => {\n if (loaded() === null) {\n return (\n <View style={styles.center}>\n <ActivityIndicator color={theme.accent} />\n </View>\n );\n }\n if (tab === 'media') return renderMediaList();\n if (tab === 'docs') return renderDocsList();\n return renderLinksList();\n };\n\n return (\n <View style={[styles.fill, { backgroundColor: theme.bg }]} testID=\"chat-media-gallery\">\n <SafeAreaView edges={['top']} style={{ backgroundColor: theme.headerBg }}>\n <View style={[styles.header, { borderBottomColor: theme.border, flexDirection: 'row' }]}>\n <Pressable\n onPress={onBack}\n hitSlop={10}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Back\"\n style={styles.headerIcon}\n >\n <MaterialCommunityIcons name=\"chevron-left\" size={32} color={theme.accent} />\n </Pressable>\n <Text style={[styles.title, { color: theme.text }]}>Media, links and docs</Text>\n <View style={styles.headerIcon} />\n </View>\n <View style={[styles.tabs, { flexDirection: 'row' }]}>\n {TABS.map((t) => {\n const active = t.key === tab;\n return (\n <Pressable\n key={t.key}\n onPress={() => setTab(t.key)}\n style={[styles.tab, active && { borderBottomColor: theme.accent }]}\n accessibilityRole=\"tab\"\n accessibilityState={{ selected: active }}\n >\n <Text style={[styles.tabText, { color: active ? theme.accent : theme.textMuted }]}>\n {t.label}\n </Text>\n </Pressable>\n );\n })}\n </View>\n </SafeAreaView>\n <InlineBanner message={error} theme={theme} onDismiss={() => setError(null)} />\n\n {renderBody()}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center' },\n header: {\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 4,\n minHeight: 52,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n headerIcon: { width: 44, height: 44, alignItems: 'center', justifyContent: 'center' },\n title: { fontSize: 17, fontWeight: '600' },\n tabs: { alignItems: 'stretch' },\n tab: { flex: 1, alignItems: 'center', paddingVertical: 12, borderBottomWidth: 2, borderBottomColor: 'transparent' },\n tabText: { fontSize: 14, fontWeight: '600' },\n docRow: {\n alignItems: 'center',\n paddingHorizontal: 16,\n paddingVertical: 10,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n docIcon: {\n width: 40,\n height: 40,\n borderRadius: 8,\n alignItems: 'center',\n justifyContent: 'center',\n marginRight: 12,\n },\n docName: { fontSize: 15, fontWeight: '500' },\n linkList: { padding: 12 },\n linkRow: { marginBottom: 10 },\n linkFallback: {\n flexDirection: 'row',\n alignItems: 'center',\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: 10,\n paddingHorizontal: 12,\n paddingVertical: 12,\n marginBottom: 10,\n },\n linkFallbackText: { fontSize: 14, marginLeft: 8, flex: 1 },\n});\n"],"names":["_a","_b","_c"],"mappings":"2lBAqBA,MAAM,OAGA,CAAC;AAAA,EACL,GAAK,EAAA,OAAA;AAAA,EACL,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,GAAK,EAAA,OAAA;AAAA,EACL,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,GAAK,EAAA,MAAA;AAAA,EACL,KAAO,EAAA;AACT,CAAC,CAAA;AAWD,MAAM,SAAY,GAAA,CAAA;AAClB,MAAM,QAAW,GAAA,CAAA;AAGjB,SAAS,OAAQ,CAAA;AAAA,EACf,GAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAKG,EAAA;AACD,EAAM,MAAA,OAAA,GAAU,cAAe,CAAA,GAAA,EAAK,MAAM,CAAA;AAC1C,EAAA,IAAI,OAAS,EAAA;AACX,IAAO,uBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,MAAO,CAAA,OAAA,EACf,8BAAC,eAAgB,EAAA,EAAA,OAAA,EAAkB,KAAc,EAAA,MAAA,EAAgB,CACrE,EAAA,CAAA;AAAA;AAGV,EAAA,uBAAQ,IAAA,CAAA,SAAA,EAAA,EAAU,OAAS,EAAA,MAAA,GAAS,MAAM,MAAA,CAAO,GAAG,CAAA,GAAI,MAAW,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,YAAc,EAAA;AAAA,IAC9F,aAAa,KAAM,CAAA;AAAA,GACpB,CAAG,EAAA,iBAAA,EAAkB,MACZ,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,0BAAuB,IAAK,EAAA,cAAA,EAAe,MAAM,EAAI,EAAA,KAAA,EAAO,MAAM,MAAQ,EAAA,CAAA;AAAA,wBAC1E,IAAK,EAAA,EAAA,aAAA,EAAe,GAAG,KAAO,EAAA,CAAC,OAAO,gBAAkB,EAAA;AAAA,MAC/D,OAAO,KAAM,CAAA;AAAA,KACd,GACY,QACL,EAAA,GAAA,EAAA;AAAA,GACJ,EAAA,CAAA;AACR;AACO,SAAS,kBAAmB,CAAA;AAAA,EACjC,GAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAYG,EAAA;AACD,EAAA,MAAM,CAAC,GAAK,EAAA,MAAM,CAAI,GAAA,KAAA,CAAM,SAAc,OAAO,CAAA;AACjD,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,CAAI,GAAA,KAAA,CAAM,SAAwB,IAAI,CAAA;AAE5D,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,CAAI,GAAA,KAAA,CAAM,SAA6B,IAAI,CAAA;AACjE,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,CAAI,GAAA,KAAA,CAAM,SAA4B,IAAI,CAAA;AAChE,EAAA,MAAM,CAAC,IAAM,EAAA,OAAO,CAAI,GAAA,KAAA,CAAM,SAA6B,IAAI,CAAA;AAC/D,EAAM,MAAA,QAAA,GAAW,IAAK,CAAA,KAAA,CAAA,CAAO,UAAW,CAAA,GAAA,CAAI,QAAQ,CAAA,CAAE,KAAQ,GAAA,QAAA,IAAY,SAAY,GAAA,CAAA,CAAA,IAAM,SAAS,CAAA;AACrG,EAAA,MAAM,IAAO,GAAA,KAAA,CAAM,WAAY,CAAA,OAAO,KAAe,KAAA;AA3GvD,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AA4GI,IAAA,MAAM,GAAM,GAAA,MAAM,GAAI,CAAA,KAAA,CAInB,oBAAsB,EAAA;AAAA,MACvB,SAAA;AAAA,MACA,IAAM,EAAA,KAAA;AAAA,MACN,KAAO,EAAA,GAAA;AAAA,MACP,IAAM,EAAA;AAAA,KACL,EAAA;AAAA,MACD,WAAa,EAAA;AAAA,KACd,CAAA,CAAE,KAAM,CAAA,MAAM,IAAI,CAAA;AACnB,IAAA,IAAA,CAAI,EAAK,GAAA,GAAA,IAAA,IAAA,GAAA,MAAA,GAAA,GAAA,CAAA,MAAA,KAAL,IAAa,GAAA,MAAA,GAAA,EAAA,CAAA,MAAA,WAAiB,kCAA6B,CAAA;AAC/D,IAAA,MAAM,UAAS,EAAK,GAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,GAAA,IAAA,IAAA,GAAA,MAAA,GAAA,GAAA,CAAA,IAAA,KAAL,IAAW,GAAA,MAAA,GAAA,EAAA,CAAA,aAAA,KAAX,mBAA0B,IAA1B,KAAA,IAAA,GAAA,EAAA,GAAkC,EAAC,EAAG,OAAO,CAAC,CAAA,KAAqB,OAAQ,CAAA,CAAA,IAAA,IAAA,GAAA,MAAA,GAAA,CAAA,CAAG,EAAE,CAAC,CAAA;AAChG,IAAA,IAAI,UAAU,OAAS,EAAA;AACrB,MAAS,QAAA,CAAA,KAAA,CAAM,IAAI,CAAK,CAAA,KAAA;AA3H9B,QAAA,IAAAA,KAAAC,GAAAC,EAAAA,GAAAA;AA4HQ,QAAM,MAAA,OAAA,GAAU,aAAc,CAAA,CAAA,EAAG,QAAQ,CAAA;AACzC,QAAM,MAAA,GAAA,GAAM,SAAU,CAAA,OAAA,CAAQ,IAAI,CAAA;AAClC,QAAA,OAAO,GAAM,GAAA;AAAA,UACX,WAAW,OAAQ,CAAA,EAAA;AAAA,UACnB,SAAW,EAAA,MAAA,CAAA,CAAOA,GAAAD,GAAAA,CAAAA,GAAAA,GAAAA,CAAAD,MAAA,CAAE,CAAA,OAAA,KAAF,IAAAA,GAAAA,MAAAA,GAAAA,GAAAA,CAAW,OAAX,IAAAC,GAAAA,GAAAA,GAAiB,SAAjB,KAAA,IAAA,GAAAC,MAA8B,EAAE,CAAA;AAAA,UAClD;AAAA,SACE,GAAA,IAAA;AAAA,OACL,EAAE,MAAO,CAAA,CAAC,MAAqB,OAAQ,CAAA,CAAC,CAAC,CAAC,CAAA;AAC3C,MAAA;AAAA;AAGF,IAAA,MAAM,QAAqB,EAAC;AAC5B,IAAA,KAAA,MAAW,KAAK,KAAO,EAAA;AACrB,MAAM,MAAA,GAAA,GAAM,QAAO,EAAE,GAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,CAAA,CAAA,OAAA,KAAF,mBAAW,EAAX,KAAA,IAAA,GAAA,EAAA,GAAiB,SAAjB,KAAA,IAAA,GAAA,EAAA,GAA8B,EAAE,CAAA;AACnD,MAAW,KAAA,MAAA,UAAA,IAAc,iBAAkB,CAAA,CAAC,CAAG,EAAA;AAC7C,QAAA,IAAI,UAAU,OAAW,IAAA,UAAA,CAAW,IAAS,KAAA,OAAA,QAAe,IAAK,CAAA;AAAA,UAC/D,WAAW,CAAE,CAAA,EAAA;AAAA,UACb,SAAW,EAAA,GAAA;AAAA,UACX;AAAA,SACD,CAAA;AACD,QAAA,IAAI,UAAU,MAAU,IAAA,UAAA,CAAW,IAAS,KAAA,MAAA,QAAc,IAAK,CAAA;AAAA,UAC7D,WAAW,CAAE,CAAA,EAAA;AAAA,UACb,SAAW,EAAA,GAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA;AACH;AAEF,IAAI,IAAA,KAAA,KAAU,OAAS,EAAA,QAAA,CAAS,KAAK,CAAA;AAAA,iBAAe,KAAK,CAAA;AAAA,GACxD,EAAA,CAAC,GAAK,EAAA,SAAA,EAAW,QAAQ,CAAC,CAAA;AAG7B,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,QAAQ,OAAW,IAAA,KAAA,KAAU,IAAM,EAAA,KAAK,KAAK,OAAO,CAAA;AACxD,IAAA,IAAI,QAAQ,OAAW,IAAA,KAAA,KAAU,IAAM,EAAA,KAAK,KAAK,OAAO,CAAA;AACxD,IAAA,IAAI,QAAQ,MAAU,IAAA,IAAA,KAAS,IAAM,EAAA,KAAK,KAAK,MAAM,CAAA;AAAA,KACpD,CAAC,GAAA,EAAK,OAAO,KAAO,EAAA,IAAA,EAAM,IAAI,CAAC,CAAA;AAClC,EAAA,MAAM,SAAS,MAAwB;AACrC,IAAI,IAAA,GAAA,KAAQ,SAAgB,OAAA,KAAA;AAC5B,IAAI,IAAA,GAAA,KAAQ,QAAe,OAAA,IAAA;AAC3B,IAAO,OAAA,KAAA;AAAA,GACT;AACA,EAAA,MAAM,kBAAkB,MAAG;AArK7B,IAAA,IAAA,EAAA;AAqKgC,IAAA,uBAAA,GAAA,CAAC,QAAqB,EAAA,EAAA,IAAA,EAAM,KAAS,IAAA,IAAA,GAAA,KAAA,GAAA,IAAI,UAAY,EAAA,SAAA,EAAW,YAAc,EAAA,CAAA,CAAA,KAAK,CAAE,CAAA,UAAA,CAAW,EAAI,EAAA,qBAAA,EAAA,CAAA,CAAuB,oCAAO,MAAP,KAAA,IAAA,GAAA,EAAA,GAAiB,CAAI,IAAA,MAAA,GAAY,MAAO,CAAA,IAAA,EAAM,kBAAoB,kBAAA,GAAA,CAAC,cAAW,IAAK,EAAA,mBAAA,EAAoB,KAAM,EAAA,UAAA,EAAW,MAAO,EAAA,2CAAA,EAA4C,KAAc,EAAA,CAAA,EAAI,YAAY,CAAC;AAAA,MACjW,IAAA;AAAA,MACA;AAAA,KACF,qBAAO,GAAA,CAAA,SAAA,EAAA,EAAU,OAAS,EAAA,MAAM,WAAc,IAAA,IAAA,GAAA,MAAA,GAAA,WAAA,CAAA,aAAA,CAAc,IAAK,CAAA,UAAA,EAAY,WAAW,CAAA,CAAA,EAAI,KAAO,EAAA;AAAA,MACjG,KAAO,EAAA,QAAA;AAAA,MACP,MAAQ,EAAA,QAAA;AAAA,MACR,WAAc,EAAA,CAAA,KAAA,GAAQ,CAAK,IAAA,SAAA,KAAc,IAAI,CAAI,GAAA,QAAA;AAAA,MACjD,YAAc,EAAA;AAAA,OACb,iBAAkB,EAAA,aAAA,EAAc,oBAAmB,YACpC,EAAA,QAAA,kBAAA,GAAA,CAAC,SAAM,MAAQ,EAAA;AAAA,MAC7B,GAAA,EAAK,KAAK,UAAW,CAAA;AAAA,OACpB,KAAO,EAAA;AAAA,MACR,KAAO,EAAA,QAAA;AAAA,MACP,MAAQ,EAAA,QAAA;AAAA,MACR,iBAAiB,KAAM,CAAA;AAAA,OACtB,UAAW,EAAA,OAAA,EAAQ,YAAY,GAAK,EAAA,CAAA,EAC3B,KAhB8B,OAgBhB,CAAA;AAAA,GAAA;AAC5B,EAAA,MAAM,iBAAiB,MAAG;AAtL5B,IAAA,IAAA,EAAA;AAsL+B,IAAA,uBAAA,GAAA,CAAC,QAAoB,EAAA,EAAA,IAAA,EAAM,IAAQ,IAAA,IAAA,GAAA,IAAA,GAAA,EAAI,EAAA,YAAA,EAAc,CAAK,CAAA,KAAA,CAAA,CAAE,UAAW,CAAA,EAAA,EAAI,qBAAuB,EAAA,CAAA,CAAA,EAAA,GAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAM,WAAN,IAAgB,GAAA,EAAA,GAAA,CAAA,IAAI,MAAY,GAAA,MAAA,CAAO,IAAM,EAAA,kBAAA,kBAAqB,GAAA,CAAA,UAAA,EAAA,EAAW,IAAK,EAAA,cAAA,EAAe,KAAM,EAAA,SAAA,EAAU,MAAO,EAAA,0CAAA,EAA2C,KAAc,EAAA,CAAA,EAAI,YAAY,CAAC;AAAA,MAC/T;AAAA,KACI,qBAAA,IAAA,CAAC,SAAU,EAAA,EAAA,OAAA,EAAS,MAAM,UAAa,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAA,aAAA,CAAc,IAAK,CAAA,UAAA,EAAY,WAAW,CAAA,CAAA,EAAI,KAAO,EAAA,CAAC,OAAO,MAAQ,EAAA;AAAA,MAChH,mBAAmB,KAAM,CAAA,MAAA;AAAA,MACzB,aAAe,EAAA;AAAA,KAChB,GAAG,iBAAkB,EAAA,QAAA,EAAS,oBAAoB,CAAQ,KAAA,EAAA,IAAA,CAAK,UAAW,CAAA,IAAI,CAC7D,CAAA,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,OAAS,EAAA;AAAA,QAC5C,iBAAiB,KAAM,CAAA;AAAA,OACxB,CACmB,EAAA,QAAA,kBAAA,GAAA,CAAC,sBAAuB,EAAA,EAAA,IAAA,EAAK,uBAAwB,EAAA,IAAA,EAAM,EAAI,EAAA,KAAA,EAAO,KAAM,CAAA,MAAA,EAAQ,CACxF,EAAA,CAAA;AAAA,sBACA,GAAA,CAAC,QAAK,KAAO,EAAA;AAAA,QAC3B,IAAM,EAAA;AAAA,OACR,EACoB,8BAAC,IAAK,EAAA,EAAA,aAAA,EAAe,GAAG,KAAO,EAAA,CAAC,OAAO,OAAS,EAAA;AAAA,QAChE,OAAO,KAAM,CAAA;AAAA,OACd,CAAA,EACsB,QAAK,EAAA,IAAA,CAAA,UAAA,CAAW,MACrB,CACJ,EAAA;AAAA,KAAA,EACJ,KApB6B,MAoBf,CAAA;AAAA,GAAA;AAC5B,EAAA,MAAM,kBAAkB,MAAG;AA3M7B,IAAA,IAAA,EAAA;AA2MgC,IAAA,uBAAA,GAAA,CAAC,YAAqB,IAAM,EAAA,KAAA,IAAA,IAAA,GAAA,KAAA,GAAS,EAAC,EAAG,cAAc,CAAC,CAAA,EAAG,CAAM,KAAA,CAAA,EAAG,EAAE,SAAS,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,EAAI,yBAAuB,EAAO,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,MAAA,KAAP,IAAiB,GAAA,EAAA,GAAA,CAAA,IAAI,OAAO,QAAW,GAAA,MAAA,CAAO,IAAM,EAAA,kBAAA,sBAAqB,UAAW,EAAA,EAAA,IAAA,EAAK,UAAW,EAAA,KAAA,EAAM,YAAW,MAAO,EAAA,sCAAA,EAAuC,KAAc,EAAA,CAAA,EAAI,YAAY,CAAC;AAAA,MAC7U;AAAA,KACI,qBAAA,GAAA,CAAC,OAAQ,EAAA,EAAA,GAAA,EAAK,IAAK,CAAA,GAAA,EAAK,KAAc,EAAA,MAAA,EAAQ,YAAc,EAAA,MAAA,EAAQ,UAAY,EAAA,CAAA,EAAA,EAF1C,OAE8C,CAAA;AAAA,GAAA;AAC1F,EAAA,MAAM,aAAa,MAAM;AACvB,IAAI,IAAA,MAAA,OAAa,IAAM,EAAA;AACrB,MAAO,uBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,MAAO,CAAA,MAAA,EACb,8BAAC,iBAAkB,EAAA,EAAA,KAAA,EAAO,KAAM,CAAA,MAAA,EAAQ,CAC5C,EAAA,CAAA;AAAA;AAEZ,IAAI,IAAA,GAAA,KAAQ,OAAS,EAAA,OAAO,eAAgB,EAAA;AAC5C,IAAI,IAAA,GAAA,KAAQ,MAAQ,EAAA,OAAO,cAAe,EAAA;AAC1C,IAAA,OAAO,eAAgB,EAAA;AAAA,GACzB;AACA,EAAA,uBAAQ,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA;AAAA,IAChC,iBAAiB,KAAM,CAAA;AAAA,GACxB,CAAG,EAAA,MAAA,EAAO,oBACD,EAAA,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,YAAa,EAAA,EAAA,KAAA,EAAO,CAAC,KAAK,GAAG,KAAO,EAAA;AAAA,MAC3C,iBAAiB,KAAM,CAAA;AAAA,KAEb,EAAA,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,MAAQ,EAAA;AAAA,QACrC,mBAAmB,KAAM,CAAA,MAAA;AAAA,QACzB,aAAe,EAAA;AAAA,OAChB,CACa,EAAA,QAAA,EAAA;AAAA,wBAAC,GAAA,CAAA,SAAA,EAAA,EAAU,SAAS,MAAQ,EAAA,OAAA,EAAS,IAAI,iBAAkB,EAAA,QAAA,EAAS,oBAAmB,MAAO,EAAA,KAAA,EAAO,OAAO,UACxG,EAAA,QAAA,kBAAA,GAAA,CAAC,0BAAuB,IAAK,EAAA,cAAA,EAAe,MAAM,EAAI,EAAA,KAAA,EAAO,KAAM,CAAA,MAAA,EAAQ,CAC/E,EAAA,CAAA;AAAA,wBACC,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,KAAO,EAAA;AAAA,UACtC,OAAO,KAAM,CAAA;AAAA,SACd,GAAG,QAAqB,EAAA,uBAAA,EAAA,CAAA;AAAA,wBACZ,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,MAAA,CAAO,UAAY,EAAA;AAAA,OACpC,EAAA,CAAA;AAAA,sBACC,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA;AAAA,QACnC,aAAe,EAAA;AAAA,OAChB,CAAA,EACc,QAAK,EAAA,IAAA,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA;AACzB,QAAM,MAAA,MAAA,GAAS,EAAE,GAAQ,KAAA,GAAA;AACzB,QAAA,uBAAQ,GAAA,CAAA,SAAA,EAAA,EAAsB,OAAS,EAAA,MAAM,MAAO,CAAA,CAAA,CAAE,GAAG,CAAA,EAAG,KAAO,EAAA,CAAC,MAAO,CAAA,GAAA,EAAK,MAAU,IAAA;AAAA,UACxF,mBAAmB,KAAM,CAAA;AAAA,SAC1B,CAAA,EAAG,iBAAkB,EAAA,KAAA,EAAM,kBAAoB,EAAA;AAAA,UAC9C,QAAU,EAAA;AAAA,WAEU,QAAC,kBAAA,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,OAAS,EAAA;AAAA,UAChD,KAAO,EAAA,MAAA,GAAS,KAAM,CAAA,MAAA,GAAS,KAAM,CAAA;AAAA,SACtC,CACwB,EAAA,QAAA,EAAA,CAAA,CAAE,KACP,EAAA,CAAA,EAAA,EATC,EAAE,GAUP,CAAA;AAAA,OACnB,CACO,EAAA;AAAA,KACJ,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,gBAAa,OAAS,EAAA,KAAA,EAAO,OAAc,SAAW,EAAA,MAAM,QAAS,CAAA,IAAI,CAAG,EAAA,CAAA;AAAA,IAE5E,UAAW;AAAA,GAChB,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,IAAM,EAAA;AAAA,IACJ,IAAM,EAAA;AAAA,GACR;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,CAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,eAAA;AAAA,IAChB,iBAAmB,EAAA,CAAA;AAAA,IACnB,SAAW,EAAA,EAAA;AAAA,IACX,mBAAmB,UAAW,CAAA;AAAA,GAChC;AAAA,EACA,UAAY,EAAA;AAAA,IACV,KAAO,EAAA,EAAA;AAAA,IACP,MAAQ,EAAA,EAAA;AAAA,IACR,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,KAAO,EAAA;AAAA,IACL,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,UAAY,EAAA;AAAA,GACd;AAAA,EACA,GAAK,EAAA;AAAA,IACH,IAAM,EAAA,CAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,eAAiB,EAAA,EAAA;AAAA,IACjB,iBAAmB,EAAA,CAAA;AAAA,IACnB,iBAAmB,EAAA;AAAA,GACrB;AAAA,EACA,OAAS,EAAA;AAAA,IACP,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,EAAA;AAAA,IACjB,mBAAmB,UAAW,CAAA;AAAA,GAChC;AAAA,EACA,OAAS,EAAA;AAAA,IACP,KAAO,EAAA,EAAA;AAAA,IACP,MAAQ,EAAA,EAAA;AAAA,IACR,YAAc,EAAA,CAAA;AAAA,IACd,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,QAAA;AAAA,IAChB,WAAa,EAAA;AAAA,GACf;AAAA,EACA,OAAS,EAAA;AAAA,IACP,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,QAAU,EAAA;AAAA,IACR,OAAS,EAAA;AAAA,GACX;AAAA,EACA,OAAS,EAAA;AAAA,IACP,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,YAAc,EAAA;AAAA,IACZ,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,aAAa,UAAW,CAAA,aAAA;AAAA,IACxB,YAAc,EAAA,EAAA;AAAA,IACd,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,EAAA;AAAA,IACjB,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,gBAAkB,EAAA;AAAA,IAChB,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,CAAA;AAAA,IACZ,IAAM,EAAA;AAAA;AAEV,CAAC,CAAA"}
|