import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'models/models.dart'; import '../widgets/mini_player.dart'; class AudioPlayerController extends StateNotifier { AudioPlayerController() : super(const PlayerStateModel()); Timer? _timer; void startAudio({ required String audioId, required String reportId, required String title, required int durationSec, }) { _timer?.cancel(); state = PlayerStateModel( audioId: audioId, reportId: reportId, title: title, durationSec: durationSec, playing: true, speed: state.speed, ); _timer = Timer.periodic(const Duration(seconds: 1), (_) => _tick()); } void startFromItem(AudioItem item) { startAudio( audioId: item.audioId, reportId: item.reportId, title: item.titleCn, durationSec: item.durationSec, ); } void startModuleAudio( String audioId, String reportId, String title, int durationSec, ) { startAudio( audioId: audioId, reportId: reportId, title: title, durationSec: durationSec, ); } void toggleAudio() { if (!state.hasAudio) return; state = state.copyWith(playing: !state.playing); if (state.playing && _timer == null) { _timer = Timer.periodic(const Duration(seconds: 1), (_) => _tick()); } } void seekAudio(int delta) { if (!state.hasAudio) return; state = state.copyWith( positionSec: (state.positionSec + delta).clamp(0, state.durationSec), ); } void cycleSpeed() { const speeds = [1.0, 1.25, 1.5, 2.0]; final current = speeds.indexOf(state.speed); state = state.copyWith(speed: speeds[(current + 1) % speeds.length]); } void _tick() { if (!state.playing) return; final step = state.speed.round().clamp(1, 2); final next = state.positionSec + step; if (next >= state.durationSec) { state = state.copyWith( positionSec: state.durationSec, playing: false, ); _timer?.cancel(); _timer = null; return; } state = state.copyWith(positionSec: next); } @override void dispose() { _timer?.cancel(); super.dispose(); } }