# Memoro Menü-System Dieses Dokument beschreibt die Verwendung von Menüs in der Memoro-App. Wir verwenden zwei verschiedene Menü-Typen für unterschiedliche Anwendungsfälle. ## Übersicht | Menü-Typ | Verwendung | Bibliothek | Plattformunterstützung | |----------|------------|------------|------------------------| | Action Sheet | Bestätigungsdialoge, Aktionsauswahl | `@expo/react-native-action-sheet` | iOS, Android, Web, macOS | | Context Menu | Kontext-/Dropdown-Menüs | `react-native-context-menu-view` | iOS (nativ), Android (adaptiert), **NICHT macOS** | ## ⚠️ Wichtiger Hinweis: macOS (Mac Catalyst) Kompatibilität Die `react-native-context-menu-view` Bibliothek ist **nicht kompatibel mit Mac Catalyst** und verursacht Abstürze beim Rendern auf macOS. Alle Menü-Komponenten müssen ein spezielles Import-Pattern verwenden, um macOS-Kompatibilität sicherzustellen. ### Implementierungs-Pattern für Context Menus ```javascript // Nur ContextMenu für unterstützte native Plattformen importieren let ContextMenu: any = null; // Erst Platform.OS statisch prüfen, dann Runtime-Check if (Platform.OS !== 'web') { try { // Nur importieren wenn nicht auf macOS - Runtime-Check im require-Block const contextMenuModule = require('react-native-context-menu-view'); // Doppelcheck zur Laufzeit nach Import if (!shouldDisableContextMenu()) { ContextMenu = contextMenuModule.default; } } catch (error) { console.warn('ContextMenu not available on', getPlatformString()); } } ``` ### Schlüsselpunkte für macOS-Kompatibilität 1. **Zweistufige Prüfung**: Erst `Platform.OS !== 'web'` statisch prüfen, dann `shouldDisableContextMenu()` zur Laufzeit 2. **Runtime-Validierung**: Die `shouldDisableContextMenu()` Funktion erkennt Mac Catalyst und gibt `true` zurück 3. **Fallback-Mechanismus**: Wenn `ContextMenu` `null` ist, fallen Komponenten auf Web-Style Implementierungen zurück ### Platform Detection Die Platform-Detection-Logik befindet sich in `/features/utils/platformDetection.ts`: - `isMacOS()`: Erkennt ob die App auf Mac Catalyst läuft - `shouldDisableContextMenu()`: Gibt `true` für Plattformen zurück, auf denen Context Menus deaktiviert werden sollen - `getPlatformString()`: Gibt einen Plattform-Identifier für Logging zurück ## 1. Action Sheet für Bestätigungsdialoge Wir verwenden Action Sheets anstelle von modalen Dialogen für alle Bestätigungsabfragen und Aktionsauswahlen. ### Installation ```bash npm install @expo/react-native-action-sheet ``` ### Einrichtung Das Action Sheet Provider ist bereits im Root Layout (`app/_layout.tsx`) eingerichtet: ```tsx import { ActionSheetProvider } from '@expo/react-native-action-sheet'; export default function RootLayout() { return ( ); } ``` ### Verwendung ```tsx import { useActionSheet } from '@expo/react-native-action-sheet'; import { useTheme } from '~/features/theme/ThemeProvider'; function YourComponent() { const { showActionSheetWithOptions } = useActionSheet(); const { isDark } = useTheme(); const handleShowActionSheet = () => { const options = ['Option 1', 'Löschen', 'Abbrechen']; const destructiveButtonIndex = 1; const cancelButtonIndex = 2; showActionSheetWithOptions({ options, cancelButtonIndex, destructiveButtonIndex, title: 'Titel', message: 'Beschreibung der verfügbaren Optionen', // iOS: Native Dark Mode Unterstützung userInterfaceStyle: isDark ? 'dark' : 'light', // Android/Web: Benutzerdefiniertes Styling für Dark Mode containerStyle: isDark ? { backgroundColor: '#1e1e1e', } : undefined, textStyle: { color: isDark ? '#FFFFFF' : '#000000', }, titleTextStyle: { color: isDark ? '#FFFFFF' : '#000000', }, messageTextStyle: { color: isDark ? 'rgba(255, 255, 255, 0.7)' : 'rgba(0, 0, 0, 0.7)', }, }, (selectedIndex?: number) => { if (selectedIndex === undefined) return; // Abgebrochen switch (selectedIndex) { case 0: // Option 1 ausgewählt break; case destructiveButtonIndex: // Löschen ausgewählt break; } }); }; return ( Action Sheet anzeigen ); } ``` ### Anwendungsfälle - Bestätigung von Löschaktionen - Bestätigung von Abbruch-Aktionen - Auswahl aus einer Liste von Optionen - Jede Art von Bestätigungsdialog ## 2. Context Menu für Kontext- und Dropdown-Menüs Wir verwenden Context Menus für Kontext- und Dropdown-Menüs, die an bestimmte UI-Elemente gebunden sind. ### Installation ```bash npm install react-native-context-menu-view ``` ### Verwendung ```tsx import ContextMenu from 'react-native-context-menu-view'; import { useTheme } from '~/features/theme/ThemeProvider'; function YourComponent() { const { isDark, themeVariant } = useTheme(); const handleMenuPress = (e) => { const { index, name } = e.nativeEvent; switch (name) { case 'edit': // Bearbeiten-Aktion break; case 'delete': // Löschen-Aktion break; } }; return ( Rechtsklick oder lange drücken für Optionen ); } ``` ### Anwendungsfälle - Kontextmenüs für Listenelemente - Dropdown-Menüs für Schaltflächen - Zusätzliche Aktionen für UI-Elemente - Alle Menüs, die an ein bestimmtes Element gebunden sind ## Richtlinien für die Menüauswahl 1. **Action Sheet verwenden wenn:** - Eine Bestätigung vom Benutzer benötigt wird - Eine Auswahl aus einer Liste von Optionen angeboten wird - Die Aktion nicht an ein bestimmtes UI-Element gebunden ist - Modale Dialoge ersetzt werden sollen 2. **Context Menu verwenden wenn:** - Das Menü an ein bestimmtes UI-Element gebunden ist - Rechtsklick- oder Long-Press-Funktionalität benötigt wird - Mehrere Aktionen für ein Element angeboten werden - Eine native Menüerfahrung gewünscht ist ## Dark Mode Unterstützung Beide Menütypen unterstützen den Dark Mode: - **Action Sheet:** Verwendet `userInterfaceStyle` auf iOS und benutzerdefinierte Styling-Props auf Android/Web - **Context Menu:** Verwendet `previewBackgroundColor` und native Darstellung ## Beispiele Beispiele für die Verwendung beider Menütypen findest du in: - `components/organisms/AudioPlayer.tsx` - Action Sheet für Löschbestätigung - `components/atoms/RecordingButton.tsx` - Action Sheet für Aufnahmebestätigung ## Ressourcen - [Action Sheet Dokumentation](https://github.com/expo/react-native-action-sheet) - [Context Menu Dokumentation](https://github.com/mpiannucci/react-native-context-menu-view)