📊 Feature: History-Sync vom Navidrome-Server (Phase 2, Part 5/X)
- Neue NavidromeService APIs: scrobble() + getBookmark() - Lädt Wiedergabe-Position vom Server beim Song-Start (Subsonic-API) - Sendet Position alle 5s zum Server wenn verbunden - Priorisiert Server-Position über lokale Position - Full Sync: lokal speichern + Server synchen parallel Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJzQjUtnvYUtHdnTs3iCru
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
5202b130c5
commit
f93b2d35da
@@ -298,6 +298,49 @@ class NavidromeService {
|
||||
return streamUrl(songId);
|
||||
}
|
||||
}
|
||||
|
||||
/// Speichert die aktuelle Wiedergabe-Position für einen Song zum Server.
|
||||
/// Subsonic-API: scrobble.view mit `submission=true` und Position in Sekunden.
|
||||
Future<void> scrobble(String songId, int positionSeconds) async {
|
||||
if (!istVerbunden) return;
|
||||
try {
|
||||
final uri = _uri('scrobble.view', {
|
||||
'id': songId,
|
||||
'submission': 'true',
|
||||
'position': positionSeconds.toString(),
|
||||
});
|
||||
await http.get(uri).timeout(const Duration(seconds: 10));
|
||||
debugPrint('Scrobble erfolgreich: Song=$songId, Position=${positionSeconds}s');
|
||||
} catch (e) {
|
||||
debugPrint('Scrobble Fehler: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Lädt die gespeicherte Wiedergabe-Position für einen Song vom Server.
|
||||
/// Gibt Position in Millisekunden zurück oder null wenn nicht gespeichert.
|
||||
Future<int?> getBookmark(String songId) async {
|
||||
if (!istVerbunden) return null;
|
||||
try {
|
||||
final uri = _uri('getBookmarks.view', {'id': songId});
|
||||
final response = await http.get(uri).timeout(const Duration(seconds: 10));
|
||||
if (response.statusCode != 200) return null;
|
||||
|
||||
final json = jsonDecode(response.body) as Map<String, dynamic>;
|
||||
final subsonicResponse = json['subsonic-response'] as Map<String, dynamic>?;
|
||||
if (subsonicResponse == null) return null;
|
||||
|
||||
final bookmarks = subsonicResponse['bookmark'] as List<dynamic>?;
|
||||
if (bookmarks == null || bookmarks.isEmpty) return null;
|
||||
|
||||
final position = (bookmarks[0] as Map<String, dynamic>)['position'] as int?;
|
||||
if (position == null) return null;
|
||||
debugPrint('Bookmark geladen: Song=$songId, Position=${position}ms');
|
||||
return position;
|
||||
} catch (e) {
|
||||
debugPrint('Bookmark Fehler: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SubsonicArtist {
|
||||
|
||||
Reference in New Issue
Block a user