Files
yanting/lib/data/audio_player_controller.dart
T
2026-06-03 16:29:53 +08:00

97 lines
2.2 KiB
Dart

import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'models/models.dart';
import '../widgets/mini_player.dart';
class AudioPlayerController extends StateNotifier<PlayerStateModel> {
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();
}
}