Files
AudiOhm/frontend/lib/presentation/providers/library_provider.dart
T
root a89c7894cf Initial commit: AudiOhm - Alternative Spotify avec streaming YouTube
Backend:
- FastAPI avec PostgreSQL et Redis
- Authentification JWT complète
- API REST pour musique, playlists, recherche
- Streaming audio via yt-dlp
- SQLAlchemy 2.0 async

Frontend:
- Flutter avec thème néon cyberpunk
- State management Riverpod
- Layout adaptatif desktop/mobile
- Lecteur audio avec mini-player

Infrastructure:
- Docker Compose (PostgreSQL + Redis)
- Scripts d'installation automatisés
- Scripts de build pour exécutables

Fichiers ajoutés:
- BUILD_CLIENT_*.bat/sh: Scripts de compilation
- BUILD_CLIENT_README.md: Documentation compilation
- CHECK_FLUTTER.sh: Vérificateur d'environnement
- requirements.txt mis à jour pour Python 3.13
- Modèles SQLAlchemy corrigés (metadata -> extra_metadata)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-18 20:08:36 +00:00

170 lines
5.3 KiB
Dart

/// Library Provider - Library state management
library;
import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../infrastructure/datasources/remote/playlist_api_service.dart';
import '../../../infrastructure/datasources/remote/music_api_service.dart';
import '../../../domain/entities/playlist.dart';
import '../../../domain/entities/track.dart';
import '../../../domain/entities/album.dart';
import '../../../domain/entities/artist.dart';
/// Library state
class LibraryState {
final List<Playlist> playlists;
final List<Track> likedSongs;
final List<Album> savedAlbums;
final List<Artist> followedArtists;
final bool isLoading;
final String? error;
const LibraryState({
this.playlists = const [],
this.likedSongs = const [],
this.savedAlbums = const [],
this.followedArtists = const [],
this.isLoading = false,
this.error,
});
LibraryState copyWith({
List<Playlist>? playlists,
List<Track>? likedSongs,
List<Album>? savedAlbums,
List<Artist>? followedArtists,
bool? isLoading,
String? error,
}) {
return LibraryState(
playlists: playlists ?? this.playlists,
likedSongs: likedSongs ?? this.likedSongs,
savedAlbums: savedAlbums ?? this.savedAlbums,
followedArtists: followedArtists ?? this.followedArtists,
isLoading: isLoading ?? this.isLoading,
error: error,
);
}
int get totalItems => playlists.length + likedSongs.length + savedAlbums.length + followedArtists.length;
}
/// Library notifier
class LibraryNotifier extends StateNotifier<LibraryState> {
LibraryNotifier(this._playlistApiService, this._musicApiService)
: super(const LibraryState());
final PlaylistApiService _playlistApiService;
final MusicApiService _musicApiService;
Future<void> loadLibrary() async {
state = state.copyWith(isLoading: true, error: null);
try {
// Load playlists in parallel
final results = await Future.wait([
_loadPlaylists(),
// TODO: Implement these endpoints when backend is ready
// _loadLikedSongs(),
// _loadSavedAlbums(),
// _loadFollowedArtists(),
]);
state = LibraryState(
playlists: results[0] as List<Playlist>,
likedSongs: [],
savedAlbums: [],
followedArtists: [],
);
} catch (e) {
state = LibraryState(
playlists: state.playlists,
likedSongs: state.likedSongs,
savedAlbums: state.savedAlbums,
followedArtists: state.followedArtists,
error: e.toString(),
);
} finally {
state = state.copyWith(isLoading: false);
}
}
Future<List<Playlist>> _loadPlaylists() async {
final playlistsJson = await _playlistApiService.getPlaylists();
return playlistsJson
.map((json) => Playlist.fromJson(json as Map<String, dynamic>))
.toList();
}
Future<void> addLikedSong(Track track) async {
// TODO: Implement when backend endpoint is ready
final updated = [...state.likedSongs, track];
state = state.copyWith(likedSongs: updated);
}
Future<void> removeLikedSong(String trackId) async {
// TODO: Implement when backend endpoint is ready
final updated = state.likedSongs.where((t) => t.id != trackId).toList();
state = state.copyWith(likedSongs: updated);
}
Future<void> addSavedAlbum(Album album) async {
// TODO: Implement when backend endpoint is ready
final updated = [...state.savedAlbums, album];
state = state.copyWith(savedAlbums: updated);
}
Future<void> removeSavedAlbum(String albumId) async {
// TODO: Implement when backend endpoint is ready
final updated = state.savedAlbums.where((a) => a.id != albumId).toList();
state = state.copyWith(savedAlbums: updated);
}
Future<void> followArtist(Artist artist) async {
// TODO: Implement when backend endpoint is ready
final updated = [...state.followedArtists, artist];
state = state.copyWith(followedArtists: updated);
}
Future<void> unfollowArtist(String artistId) async {
// TODO: Implement when backend endpoint is ready
final updated = state.followedArtists.where((a) => a.id != artistId).toList();
state = state.copyWith(followedArtists: updated);
}
Future<void> deletePlaylist(String playlistId) async {
await _playlistApiService.deletePlaylist(playlistId);
final updated = state.playlists.where((p) => p.id != playlistId).toList();
state = state.copyWith(playlists: updated);
}
Future<void> createPlaylist({
required String name,
String? description,
String? imageUrl,
bool isPublic = false,
}) async {
final playlistJson = await _playlistApiService.createPlaylist(
name: name,
description: description,
imageUrl: imageUrl,
isPublic: isPublic,
);
final playlist = Playlist.fromJson(playlistJson as Map<String, dynamic>);
final updated = [...state.playlists, playlist];
state = state.copyWith(playlists: updated);
}
Future<void> refresh() async {
await loadLibrary();
}
}
/// Library provider
final libraryProvider = StateNotifierProvider<LibraryNotifier, LibraryState>((ref) {
final playlistApiService = ref.watch(playlistApiServiceProvider);
final musicApiService = ref.watch(musicApiServiceProvider);
return LibraryNotifier(playlistApiService, musicApiService);
});