import { useState } from "react"; import { Modal, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from "react-native"; import type { MobileBot, MobileBotSection } from "../lib/api"; import { native } from "../lib/native"; import { NativeSymbol } from "./native-symbol"; export type BotOrganizationUpdate = { pinned?: boolean; sectionId?: string | null; notifyOnFinish?: boolean; }; export function BotOrganizeModal({ bot, sections, onClose, onUpdate, onCreateSection, }: { bot: Pick & Partial>; sections: MobileBotSection[]; onClose: () => void; onUpdate: (update: BotOrganizationUpdate) => Promise; onCreateSection: (name: string) => Promise; }) { const [creating, setCreating] = useState(false); const [name, setName] = useState(""); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); async function save(request: () => Promise) { if (saving) return; setSaving(true); setError(null); try { await request(); onClose(); } catch (err) { setError(err instanceof Error ? err.message : "Could not update chat"); setSaving(false); } } return ( {bot.name} void save(() => onUpdate({ pinned: !bot.pinned }))} style={({ pressed }) => [styles.action, pressed && styles.pressed]} > {bot.pinned ? "Unpin" : "Pin"} {typeof bot.notifyOnFinish === "boolean" ? ( void save(() => onUpdate({ notifyOnFinish: !bot.notifyOnFinish }))} style={({ pressed }) => [styles.action, pressed && styles.pressed]} > {bot.notifyOnFinish ? "Silence notifications" : "Resume notifications"} ) : null} Move to {sections.map((section) => ( void save(() => onUpdate({ sectionId: section.id }))} /> ))} void save(() => onUpdate({ sectionId: null }))} /> {creating ? ( void save(() => onCreateSection(name.trim()))} style={styles.newSectionSubmit} > Create ) : ( setCreating(true)} style={({ pressed }) => [styles.action, pressed && styles.pressed]} > New section )} {error ? {error} : null} Cancel ); } function SectionOption({ label, selected, disabled, onPress, }: { label: string; selected: boolean; disabled: boolean; onPress: () => void; }) { return ( [styles.sectionOption, pressed && styles.pressed]} > {label} {selected ? : null} ); } const styles = StyleSheet.create({ overlay: { flex: 1, justifyContent: "flex-end", backgroundColor: "rgba(0, 0, 0, 0.62)", }, sheet: { maxHeight: "82%", borderTopLeftRadius: 22, borderTopRightRadius: 22, backgroundColor: "#1C1C1E", paddingHorizontal: 16, paddingTop: 18, paddingBottom: 28, }, title: { color: native.label, fontSize: 18, fontWeight: "600", paddingHorizontal: 8, paddingBottom: 10, }, action: { minHeight: 46, flexDirection: "row", alignItems: "center", gap: 12, borderRadius: 11, paddingHorizontal: 10, }, pressed: { backgroundColor: native.fill, }, actionLabel: { flex: 1, color: native.label, fontSize: 16, }, sectionLabel: { color: native.secondaryLabel, fontSize: 13, fontWeight: "600", paddingHorizontal: 10, paddingTop: 12, paddingBottom: 6, }, sectionOptions: { maxHeight: 230, }, sectionOption: { minHeight: 44, flexDirection: "row", alignItems: "center", gap: 12, borderRadius: 11, paddingHorizontal: 10, }, newSectionRow: { flexDirection: "row", alignItems: "center", gap: 8, paddingHorizontal: 8, paddingVertical: 6, }, newSectionInput: { flex: 1, height: 40, borderRadius: 10, backgroundColor: native.fill, color: native.label, paddingHorizontal: 12, fontSize: 16, }, newSectionSubmit: { minHeight: 40, justifyContent: "center", borderRadius: 10, backgroundColor: native.label, paddingHorizontal: 14, }, newSectionSubmitLabel: { color: native.page, fontSize: 14, fontWeight: "600", }, error: { color: "#FF5364", fontSize: 13, paddingHorizontal: 10, paddingTop: 8, }, cancel: { alignItems: "center", paddingTop: 14, paddingBottom: 2, }, cancelLabel: { color: native.secondaryLabel, fontSize: 16, fontWeight: "600", }, });