✨ lrc fetcher
This commit is contained in:
96
lib/providers/lrc_fetcher_provider.dart
Normal file
96
lib/providers/lrc_fetcher_provider.dart
Normal file
@@ -0,0 +1,96 @@
|
||||
import 'package:groovybox/data/db.dart' as db;
|
||||
import 'package:drift/drift.dart' as drift;
|
||||
import 'package:groovybox/logic/lrc_providers.dart';
|
||||
import 'package:groovybox/logic/lyrics_parser.dart';
|
||||
import 'package:groovybox/providers/db_provider.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'lrc_fetcher_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
class LyricsFetcher extends _$LyricsFetcher {
|
||||
@override
|
||||
LyricsFetcherState build() {
|
||||
return LyricsFetcherState();
|
||||
}
|
||||
|
||||
Future<void> fetchLyricsForTrack({
|
||||
required int trackId,
|
||||
required String searchTerm,
|
||||
required LRCProvider provider,
|
||||
required String trackPath,
|
||||
}) async {
|
||||
state = state.copyWith(isLoading: true, error: null);
|
||||
|
||||
try {
|
||||
final lyrics = await provider.getLrc(searchTerm);
|
||||
if (lyrics == null) {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
error: 'No lyrics found from ${provider.name}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the lyrics into LyricsData format
|
||||
String? lyricsJson;
|
||||
if (lyrics.synced != null) {
|
||||
// It's LRC format
|
||||
final lyricsData = LyricsParser.parseLrc(lyrics.synced!);
|
||||
lyricsJson = lyricsData.toJsonString();
|
||||
} else if (lyrics.plain != null) {
|
||||
// Plain text
|
||||
final lyricsData = LyricsParser.parsePlaintext(lyrics.plain!);
|
||||
lyricsJson = lyricsData.toJsonString();
|
||||
}
|
||||
|
||||
if (lyricsJson != null) {
|
||||
// Update the track in the database
|
||||
final database = ref.read(databaseProvider);
|
||||
await (database.update(database.tracks)
|
||||
..where((t) => t.id.equals(trackId)))
|
||||
.write(db.TracksCompanion(lyrics: drift.Value(lyricsJson)));
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
successMessage: 'Lyrics fetched from ${provider.name}',
|
||||
);
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
error: 'Failed to parse lyrics',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
error: 'Error fetching lyrics: $e',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LyricsFetcherState {
|
||||
final bool isLoading;
|
||||
final String? error;
|
||||
final String? successMessage;
|
||||
|
||||
LyricsFetcherState({this.isLoading = false, this.error, this.successMessage});
|
||||
|
||||
LyricsFetcherState copyWith({
|
||||
bool? isLoading,
|
||||
String? error,
|
||||
String? successMessage,
|
||||
}) {
|
||||
return LyricsFetcherState(
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
error: error ?? this.error,
|
||||
successMessage: successMessage ?? this.successMessage,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Providers for each LRC provider
|
||||
final musixmatchProvider = Provider((ref) => MusixmatchProvider());
|
||||
final neteaseProvider = Provider((ref) => NetEaseProvider());
|
||||
63
lib/providers/lrc_fetcher_provider.g.dart
Normal file
63
lib/providers/lrc_fetcher_provider.g.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'lrc_fetcher_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(LyricsFetcher)
|
||||
const lyricsFetcherProvider = LyricsFetcherProvider._();
|
||||
|
||||
final class LyricsFetcherProvider
|
||||
extends $NotifierProvider<LyricsFetcher, LyricsFetcherState> {
|
||||
const LyricsFetcherProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'lyricsFetcherProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$lyricsFetcherHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
LyricsFetcher create() => LyricsFetcher();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(LyricsFetcherState value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<LyricsFetcherState>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$lyricsFetcherHash() => r'49468a75e00ab1533368acb52328b059831836d3';
|
||||
|
||||
abstract class _$LyricsFetcher extends $Notifier<LyricsFetcherState> {
|
||||
LyricsFetcherState build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<LyricsFetcherState, LyricsFetcherState>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<LyricsFetcherState, LyricsFetcherState>,
|
||||
LyricsFetcherState,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user