78 lines
4.6 KiB
Markdown
78 lines
4.6 KiB
Markdown
# MarianumMobile Client
|
||
|
||
Flutter-App für die Schul-Community: Webuntis-Stundenplan, Nextcloud Talk + Files, Custom MHSL-Backend (Breaker, Custom Events, Push).
|
||
|
||
## Stack
|
||
|
||
- **Flutter** (Dart >= 3.8)
|
||
- **State:** `flutter_bloc` + `hydrated_bloc` (persistente BLoCs pro Modul)
|
||
- **Navigation:** `persistent_bottom_nav_bar_v2` mit zentraler `AppRoutes`-Klasse als Single Entry Point
|
||
- **HTTP:** `dio`, lokales Caching via `localstore` (Generic `RequestCache<T>`)
|
||
- **Calendar:** `syncfusion_flutter_calendar`
|
||
- **Datum/Zeit:** `jiffy` – wird **nur** über die Extensions in `lib/extensions/date_time.dart` verwendet
|
||
- **Code-Gen:** `freezed`, `json_serializable`
|
||
|
||
## Ordnerstruktur
|
||
|
||
```
|
||
lib/
|
||
├── api/ HTTP-Layer pro Backend (mhsl/, marianumcloud/, webuntis/, holidays/)
|
||
├── state/app/modules/ BLoC pro Feature-Modul (timetable, chat, chat_list, files, ...)
|
||
├── state/app/infrastructure LoadableState<T>, DataLoader, geteilte BLoC-Bausteine
|
||
├── view/ Screens
|
||
│ ├── login/ Login-Flow
|
||
│ └── pages/ ein Verzeichnis pro Modul (timetable, files, talk, ...)
|
||
├── widget/ Geteilte UI-Komponenten (Dialoge, Buttons, Sheets)
|
||
├── extensions/ DateTime-, Text-, TimeOfDay-Extensions
|
||
├── routing/ AppRoutes (Single Navigation Entry)
|
||
├── theming/ Light/Dark Theme
|
||
├── storage/ Freezed Settings-Modelle (HydratedBloc-persistent)
|
||
├── notification/ Firebase + flutter_local_notifications
|
||
└── utils/ Helper (clipboard_helper, debouncer, download_manager, ...)
|
||
```
|
||
|
||
## Konventionen
|
||
|
||
**Navigation:** Ausschließlich über `AppRoutes.openX(context, ...)`. Direkte `Navigator.push(...)` für volle Pages sind nicht erlaubt – `Navigator.pop` für Sheets/Dialogs bleibt am Call-Site.
|
||
|
||
**Dialoge:**
|
||
- Info/Fehler: `InfoDialog.show(context, body, copyable: true, title: '...')` aus `lib/widget/info_dialog.dart`.
|
||
- Bestätigung: `ConfirmDialog(...).asDialog(context)` aus `lib/widget/confirm_dialog.dart`. Async-Bestätigung nutzt `onConfirmAsync` (zeigt Spinner und Inline-Fehler über `AsyncDialogAction`).
|
||
- **Kein** inline `AlertDialog`/`SimpleDialog` mehr.
|
||
|
||
**Bottom-Sheets:** Detail-Sheets gehen über `showDetailsBottomSheet(context, header: ..., children: (ctx) => [...])` aus `lib/widget/details_bottom_sheet.dart`. Header ist optional.
|
||
|
||
**Async-Actions:** Statt manuelles Spinner+Try/Catch die `AsyncActionButton`-Familie aus `lib/widget/async_action_button.dart` (`AsyncActionButton`, `AsyncTextButton`, `AsyncIconButton`, `AsyncFab`, `AsyncListTile`, `AsyncDialogAction`, `runWithErrorDialog`). Fehler-Mapping läuft über `errorBuilder` oder zentral über `errorToUserMessage` aus `lib/api/errors/error_mapper.dart`.
|
||
|
||
**Clipboard:** Über `copyToClipboard(context, text)` aus `lib/utils/clipboard_helper.dart`. Zeigt automatisch SnackBar.
|
||
|
||
**Datum/Zeit-Formatierung:** Über die Extensions in `lib/extensions/date_time.dart`:
|
||
`dt.formatHm()`, `dt.formatDate()`, `dt.formatDateTime()`, `dt.formatDateShort()`, `dt.formatRelative()`, `start.timeRangeTo(end)`. **Kein** direktes `Jiffy.parseFromDateTime(...).format(pattern: '...')` im View-Code.
|
||
|
||
**Settings:** Pro Feature ein Freezed-Modell unter `lib/storage/`, persistiert via HydratedBloc.
|
||
|
||
## Build / Run
|
||
|
||
```bash
|
||
flutter pub get
|
||
dart run build_runner build --delete-conflicting-outputs # nach Änderungen an Freezed/JSON-Modellen
|
||
flutter run # Debug auf angeschlossenem Device
|
||
flutter analyze # statische Analyse, muss 0 Issues melden
|
||
flutter test # Tests (siehe test/)
|
||
```
|
||
|
||
## Backend-Integrationen
|
||
|
||
| Backend | Pfad | Zweck |
|
||
|---------------------------|-----------------------|----------------------------------------|
|
||
| Webuntis | `lib/api/webuntis/` | Stundenplan, Klassen, Räume, Lehrer |
|
||
| Nextcloud (Talk + WebDAV) | `lib/api/marianumcloud/` | Chats, Datei-Verwaltung |
|
||
| Custom MHSL-Server | `lib/api/mhsl/` | Breaker, Custom Events, Notify, Noten |
|
||
| Holiday-Calendar | `lib/api/holidays/` | Ferien |
|
||
|
||
`nextcloud`-Paket ist auf einen Custom-Fork gepinnt (siehe `pubspec.yaml` `dependency_overrides`).
|
||
|
||
## Tests
|
||
|
||
`test/` deckt aktuell nur Kern-Funktionen ab (DateTime-Extensions, AsyncActionController, LessonResolver). Beim Hinzufügen neuer pure-function-Helper bitte Test mit dazu.
|