/** * Un menù di scelte: quelle della foto (scatta, scegli, rimuovi) e quelle di * una sezione (aggiungi qui, rinomina, rimuovi). * * Sull'iPhone è il foglio di sistema, quello che tutti conoscono, col colore * dell'app e la voce che rimuove in rosso. Android un foglio così non ce l'ha, * e lì si usa il nostro Foglio, con le stesse voci in un riquadro. La scelta * fra i due la fa `menuDiSistema` in logica-modifica.ts. * * Su Android la voce scelta parte solo quando il foglio è sparito del tutto * (`onChiuso`): la fotocamera o un altro foglio aperti mentre questo sta * ancora scendendo non comparirebbero, due Modal non stanno uno sopra l'altro * mentre uno va via. Sull'iPhone il foglio di sistema chiama quando ha finito. * * I colori non si scrivono qui: vengono da tema.ts, come nelle altre schermate. */ import { useEffect, useMemo, useRef } from 'react'; import { ActionSheetIOS, Platform, Pressable, StyleSheet, Text, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useApp } from '../contesto.ts'; import { menuDiSistema } from '../logica-modifica.ts'; import type { ChiaveSegno } from '../segni.ts'; import type { Colori } from '../tema.ts'; import { RAGGIO, SPAZIO, TESTO, useColori, useSchema } from '../tema.ts'; import { Foglio } from './Foglio.tsx'; import Segno from './Segno.tsx'; export interface VoceMenu { etichetta: string; /** Una riga di spiegazione sotto l'etichetta, solo nel foglio nostro. */ spiega?: string; segno: ChiaveSegno; pericolo?: boolean; azione: () => void; } export interface PropsMenuAzioni { visibile: boolean; titolo?: string; voci: VoceMenu[]; onChiudi: () => void; } export function MenuAzioni({ visibile, titolo, voci, onChiudi }: PropsMenuAzioni) { const { testo } = useApp(); const colori = useColori(); const schema = useSchema(); const stili = useMemo(() => creaStili(colori), [colori]); const sotto = useSafeAreaInsets().bottom; const diSistema = menuDiSistema(Platform.OS); // La voce scelta nel foglio nostro, da eseguire quando il foglio è sparito. const scelta = useRef(null); // Le voci dell'ultima apertura: chi apre il menù spesso le azzera appena si // chiude, e il foglio che sta ancora scendendo resterebbe vuoto. const mostrate = useRef({ titolo, voci }); if (visibile) mostrate.current = { titolo, voci }; useEffect(() => { if (!visibile || !diSistema) return; const annulla = voci.length; const pericolo = voci.findIndex((v) => v.pericolo === true); ActionSheetIOS.showActionSheetWithOptions( { title: titolo, options: [...voci.map((v) => v.etichetta), testo('modifica.annulla')], cancelButtonIndex: annulla, destructiveButtonIndex: pericolo === -1 ? undefined : pericolo, tintColor: colori.accento, userInterfaceStyle: schema, }, (indice) => { onChiudi(); if (indice < annulla) voci[indice].azione(); }, ); // Si mostra una volta per ogni apertura: le voci e i colori che cambiano // mentre è aperto non lo devono riaprire. }, [visibile]); if (diSistema) return null; return ( { const v = scelta.current; scelta.current = null; v?.azione(); }} > {mostrate.current.titolo !== undefined ? {mostrate.current.titolo} : null} {mostrate.current.voci.map((v, i) => ( { scelta.current = v; onChiudi(); }} accessibilityRole="button" accessibilityLabel={v.etichetta} style={({ pressed }) => [stili.voce, i > 0 ? stili.separata : null, pressed ? stili.premuta : null]} > {v.etichetta} {v.spiega !== undefined ? {v.spiega} : null} ))} ); } const creaStili = (colori: Colori) => StyleSheet.create({ foglio: { backgroundColor: colori.fondo, borderTopLeftRadius: 22, borderTopRightRadius: 22, paddingHorizontal: SPAZIO.l, gap: SPAZIO.m, }, maniglia: { alignSelf: 'center', width: 38, height: 5, borderRadius: 3, backgroundColor: colori.bordo, marginTop: SPAZIO.s, }, titolo: { ...TESTO.piccolo, fontWeight: '600', color: colori.testoTenue, textAlign: 'center' }, riquadro: { backgroundColor: colori.superficie, borderRadius: RAGGIO.riga, overflow: 'hidden' }, voce: { flexDirection: 'row', alignItems: 'center', gap: SPAZIO.m, minHeight: 56, paddingHorizontal: SPAZIO.l, paddingVertical: SPAZIO.s }, separata: { borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: colori.bordo }, premuta: { backgroundColor: colori.bordo }, testi: { flex: 1, gap: 2 }, etichetta: { ...TESTO.corpo, color: colori.testo }, spiega: { ...TESTO.piccolo, color: colori.testoTenue }, });