🎉 Initial Commit

This commit is contained in:
2025-12-14 21:25:24 +08:00
commit 49854b44e1
151 changed files with 10034 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
import 'package:media_kit/media_kit.dart';
class AudioHandler {
final Player _player;
AudioHandler() : _player = Player() {
// Configure for audio
// _player.setPlaylistMode(PlaylistMode.loop); // Optional
}
Player get player => _player;
Future<void> play() => _player.play();
Future<void> pause() => _player.pause();
Future<void> stop() => _player.stop();
Future<void> seek(Duration position) => _player.seek(position);
Future<void> setSource(String path) async {
await _player.open(Media(path));
}
void dispose() {
_player.dispose();
}
}

View File

@@ -0,0 +1,49 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter_media_metadata/flutter_media_metadata.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'metadata_service.g.dart';
class TrackMetadata {
final String? title;
final String? artist;
final String? album;
final Uint8List? artBytes;
TrackMetadata({this.title, this.artist, this.album, this.artBytes});
}
class MetadataService {
Future<TrackMetadata> getMetadata(String path) async {
final file = File(path);
if (!await file.exists()) {
return TrackMetadata();
}
try {
final metadata = await MetadataRetriever.fromFile(file);
return TrackMetadata(
title: metadata.trackName,
artist: metadata.trackArtistNames?.join(
', ',
), // metadata often returns lists
album: metadata.albumName,
artBytes: metadata.albumArt,
);
} catch (e) {
// Fallback or ignore
return TrackMetadata();
}
}
}
@Riverpod(keepAlive: true)
MetadataService metadataService(Ref ref) {
return MetadataService();
}
@riverpod
Future<TrackMetadata> trackMetadata(Ref ref, String path) {
return ref.watch(metadataServiceProvider).getMetadata(path);
}

View File

@@ -0,0 +1,127 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'metadata_service.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
@ProviderFor(metadataService)
const metadataServiceProvider = MetadataServiceProvider._();
final class MetadataServiceProvider
extends
$FunctionalProvider<MetadataService, MetadataService, MetadataService>
with $Provider<MetadataService> {
const MetadataServiceProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'metadataServiceProvider',
isAutoDispose: false,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$metadataServiceHash();
@$internal
@override
$ProviderElement<MetadataService> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
MetadataService create(Ref ref) {
return metadataService(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(MetadataService value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<MetadataService>(value),
);
}
}
String _$metadataServiceHash() => r'62471f009f532ce97bab1ea7e87171ae385592b7';
@ProviderFor(trackMetadata)
const trackMetadataProvider = TrackMetadataFamily._();
final class TrackMetadataProvider
extends
$FunctionalProvider<
AsyncValue<TrackMetadata>,
TrackMetadata,
FutureOr<TrackMetadata>
>
with $FutureModifier<TrackMetadata>, $FutureProvider<TrackMetadata> {
const TrackMetadataProvider._({
required TrackMetadataFamily super.from,
required String super.argument,
}) : super(
retry: null,
name: r'trackMetadataProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$trackMetadataHash();
@override
String toString() {
return r'trackMetadataProvider'
''
'($argument)';
}
@$internal
@override
$FutureProviderElement<TrackMetadata> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<TrackMetadata> create(Ref ref) {
final argument = this.argument as String;
return trackMetadata(ref, argument);
}
@override
bool operator ==(Object other) {
return other is TrackMetadataProvider && other.argument == argument;
}
@override
int get hashCode {
return argument.hashCode;
}
}
String _$trackMetadataHash() => r'9833c87e90297f7c9aa952c31f78a73aae78422b';
final class TrackMetadataFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<TrackMetadata>, String> {
const TrackMetadataFamily._()
: super(
retry: null,
name: r'trackMetadataProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
TrackMetadataProvider call(String path) =>
TrackMetadataProvider._(argument: path, from: this);
@override
String toString() => r'trackMetadataProvider';
}