managarten/memoro/apps/mobile/features/menus
Till-JS e7f5f942f3 chore: initial commit - consolidate 4 projects into monorepo
Projects included:
- maerchenzauber (NestJS backend + Expo mobile + SvelteKit web + Astro landing)
- manacore (Expo mobile + SvelteKit web + Astro landing)
- manadeck (NestJS backend + Expo mobile + SvelteKit web)
- memoro (Expo mobile + SvelteKit web + Astro landing)

This commit preserves the current state before monorepo restructuring.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 23:38:24 +01:00
..
ReadMes chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00
AndroidContextMenu.tsx chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00
Header.tsx chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00
HeaderContext.tsx chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00
HeaderMenu.tsx chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00
MemoHeaderMenu.tsx chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00
MemoMenu.tsx chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00
README.md chore: initial commit - consolidate 4 projects into monorepo 2025-11-22 23:38:24 +01:00

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

// 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

npm install @expo/react-native-action-sheet

Einrichtung

Das Action Sheet Provider ist bereits im Root Layout (app/_layout.tsx) eingerichtet:

import { ActionSheetProvider } from '@expo/react-native-action-sheet';

export default function RootLayout() {
  return (
    <SafeAreaProvider>
      <ThemeProvider>
        <ActionSheetProvider>
          <AuthProvider>
            <RootLayoutNav />
          </AuthProvider>
        </ActionSheetProvider>
      </ThemeProvider>
    </SafeAreaProvider>
  );
}

Verwendung

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 (
    <Pressable onPress={handleShowActionSheet}>
      <Text>Action Sheet anzeigen</Text>
    </Pressable>
  );
}

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

npm install react-native-context-menu-view

Verwendung

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 (
    <ContextMenu
      title="Optionen"
      actions={[
        { 
          title: 'Bearbeiten',
          subtitle: 'Element bearbeiten',
          systemIcon: 'square.and.pencil', // iOS SF Symbol
          id: 'edit',
        },
        { 
          title: 'Löschen',
          systemIcon: 'trash',
          destructive: true,
          id: 'delete',
        },
      ]}
      onPress={handleMenuPress}
      previewBackgroundColor={isDark ? '#1e1e1e' : '#ffffff'}
    >
      <View style={styles.yourElement}>
        <Text>Rechtsklick oder lange drücken für Optionen</Text>
      </View>
    </ContextMenu>
  );
}

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