172 lines
5.2 KiB
Markdown
172 lines
5.2 KiB
Markdown
# Melo App – Server-Sync & Widgets Implementation Plan
|
||
|
||
> **Für Hermes:** Schritt-für-Schritt abarbeiten, keine Tasks springen.
|
||
|
||
**Goal:** Melo App um Widgets + Hidden Message "Seit 2008" erweitern, dann Server-Sync auf Aingrad aufsetzen (Musik zentral lagern, von jedem Gerät abrufbar).
|
||
|
||
**Architektur:**
|
||
- Phase 1+2: Reine App-Erweiterungen (Widgets + Easter Egg)
|
||
- Phase 3: Server als Caddy-File-Server + JSON-API, App holt Song-Liste und lädt runter
|
||
|
||
**Tech Stack:** Flutter/Dart, Caddy (läuft auf Aingrad), SQLite (bereits vorhanden)
|
||
|
||
---
|
||
|
||
## Phase 1: Widgets
|
||
|
||
### Task 1: Home-Widget (Recent Songs)
|
||
|
||
**Objective:** Widget zeigt die letzten 5 abgespielten Songs auf dem Home-Screen
|
||
|
||
**Files:**
|
||
- Create: `lib/widgets/recent_widget.dart`
|
||
- Modify: `lib/screens/home_screen.dart` (Widget einbauen)
|
||
- Modify: `lib/viewmodels/melo_home_viewmodel.dart` (letzte Songs laden)
|
||
|
||
**Schritte:**
|
||
|
||
1. `recent_widget.dart` erstellen – kleiner Container mit den letzten 5 Songs, ähnlich wie StatistikCard aufgebaut (schwarz/rot Design)
|
||
2. ViewModel: `letzteSongs` laden aus `wiedergabe_verlauf`-Tabelle via `db.positionAktualisieren` – die Tabelle existiert bereits
|
||
3. `home_screen.dart`: Widget unter StatistikCard einbauen
|
||
4. Nur sichtbar wenn `letzteSongs.isNotEmpty`
|
||
|
||
**Code-Skizze recent_widget.dart (~40 Zeilen):**
|
||
```dart
|
||
class RecentWidget extends StatelessWidget {
|
||
final List<Song> songs;
|
||
final void Function(Song) onPlay;
|
||
|
||
// UI: kleiner Container, 5 horizontale Einträge mit Cover + Titel
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Task 2: Tag-Statistik-Widget
|
||
|
||
**Objective:** Widget zeigt wie viele Songs pro Tag existieren (kleine Übersicht)
|
||
|
||
**Files:**
|
||
- Create: `lib/widgets/tag_stats_widget.dart`
|
||
- Modify: `lib/viewmodels/melo_home_viewmodel.dart` (Tag-Counts berechnen)
|
||
- Modify: `lib/screens/home_screen.dart`
|
||
|
||
**Schritte:**
|
||
|
||
1. ViewModel: `Map<String, int> tagCounts` – zählt Songs pro Tag-Namen
|
||
2. `tag_stats_widget.dart` – horizontale Chips mit Tag-Name + Count
|
||
3. In home_screen unter Tags-Leiste einbauen
|
||
|
||
---
|
||
|
||
## Phase 2: Hidden Message "Seit 2008"
|
||
|
||
### Task 3: Easter Egg auf dem Home-Screen
|
||
|
||
**Objective:** Versteckte Nachricht "Seit 2008" die nach 10 Song-Playbacks erscheint
|
||
|
||
**Files:**
|
||
- Modify: `lib/viewmodels/melo_home_viewmodel.dart` (Counter + Logik)
|
||
- Modify: `lib/screens/home_screen.dart` (Anzeige)
|
||
|
||
**Schritte:**
|
||
|
||
1. ViewModel: `int _playCount = 0; bool get zeigeBotschaft => _playCount >= 10;`
|
||
2. Bei jedem `spieleSong()` → `_playCount++`, bei 10 → `zeigeBotschaft = true`
|
||
3. UI: Wenn `zeigeBotschaft`, zeige ein rotes Herz mit "💌 Seit 2008" zwischen Header und StatistikCard
|
||
4. Nach einmaligem Anzeigen → `_playCount` zurücksetzen oder ausblendbar
|
||
|
||
**Code (~15 Zeilen ViewModel + ~10 Zeilen UI)**
|
||
|
||
---
|
||
|
||
## Phase 3: Server-Sync
|
||
|
||
### Task 4: Caddy-Subdomain einrichten
|
||
|
||
**Objective:** `musik.baka-net.de` served Musik-Ordner + JSON-Liste
|
||
|
||
**Files:**
|
||
- Modify: `/etc/caddy/Caddyfile` (auf Aingrad)
|
||
|
||
**Schritte:**
|
||
|
||
1. Ordner erstellen: `mkdir -p /home/dustin/musik/songs`
|
||
2. Caddyfile-Eintrag:
|
||
```
|
||
musik.baka-net.de {
|
||
root * /home/dustin/musik
|
||
file_server browse
|
||
@auth {
|
||
path /upload*
|
||
}
|
||
basicauth @auth {
|
||
melo HASH_PASSWORT
|
||
}
|
||
}
|
||
```
|
||
3. JSON-API Script: `/home/dustin/musik/api/songs.json` – generiert Liste aller `.mp3`/`.m4a`/`.flac` Dateien mit Metadaten
|
||
4. `caddy reload`
|
||
|
||
---
|
||
|
||
### Task 5: ServerSyncService in der App
|
||
|
||
**Objective:** Neuer Service ruft Server-Liste ab und managed Downloads
|
||
|
||
**Files:**
|
||
- Create: `lib/services/server_sync_service.dart`
|
||
- Create: `lib/models/server_status.dart`
|
||
- Modify: `lib/screens/home_screen.dart` (neuer Tab)
|
||
|
||
**Schritte:**
|
||
|
||
1. `ServerSyncService` mit Methoden:
|
||
- `Future<List<ServerSong>> fetchServerList()` – ruft `musik.baka-net.de/api/songs.json` ab
|
||
- `Future<Song?> downloadSong(ServerSong s)` – lädt runter, speichert lokal + in DB
|
||
- `Future<bool> istBereitsLokal(ServerSong s)` – checkt ob Datei existiert
|
||
|
||
2. Neuer Screen/Sheet: "📡 Server"-Button im Header öffnet Server-Browser
|
||
- Zeigt alle Songs auf dem Server
|
||
- Status: "Downloaded ✓" / "Download ⬇"
|
||
- Fortschrittsbalken wie beim YouTube-Download
|
||
|
||
---
|
||
|
||
### Task 6: Auto-Scan von Server-Songs
|
||
|
||
**Objective:** Einmal pro Session prüfen ob Server neue Songs hat
|
||
|
||
**Files:**
|
||
- Modify: `lib/viewmodels/melo_home_viewmodel.dart`
|
||
- Modify: `lib/services/server_sync_service.dart`
|
||
|
||
**Schritte:**
|
||
|
||
1. `ladeSongs()` → zusätzlich Server-Scan starten (im Hintergrund)
|
||
2. Neue Songs automatisch in DB eintragen (ohne Download – nur Metadaten)
|
||
3. Badge im Server-Button: "3 neue Songs"
|
||
|
||
---
|
||
|
||
## Abhängigkeiten
|
||
|
||
```
|
||
Phase 1 (Widgets) → Phase 2 (Hidden Message) → Phase 3 (Server-Sync)
|
||
↓
|
||
Alles unabhängig von Server
|
||
```
|
||
|
||
## Validation
|
||
|
||
- Widgets: Nach App-Neustart sichtbar, reagieren auf Song-Änderungen
|
||
- Hidden Message: Nach 10 Playbacks erscheint "Seit 2008"
|
||
- Server-Sync: `curl https://musik.baka-net.de/api/songs.json` liefert JSON
|
||
- App: Server-Tab zeigt Songs, Download funktioniert, Musik spielt ab
|
||
|
||
## Offene Fragen
|
||
|
||
- Soll Hidden Message persistiert werden (einmalig, nie wieder)?
|
||
- Auth für Download nötig oder öffentlich? (Server intern → öffentlich okay)
|
||
- Auto-Upload von lokal gescannten Songs zum Server? (Nur Download, kein Upload)
|