#476 fixed saving video playback state when leaving viewer

This commit is contained in:
Thibault Deckers 2023-01-04 19:13:57 +01:00
parent 822b2c859a
commit 4c6a4e3568
4 changed files with 17 additions and 12 deletions

View file

@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file.
### Fixed ### Fixed
- transition between collection and viewer when cutout area is not used - transition between collection and viewer when cutout area is not used
- saving video playback state when leaving viewer
## <a id="v1.7.8"></a>[v1.7.8] - 2022-12-20 ## <a id="v1.7.8"></a>[v1.7.8] - 2022-12-20

View file

@ -1,4 +1,3 @@
import 'package:aves/app_mode.dart';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/widgets/viewer/controller.dart'; import 'package:aves/widgets/viewer/controller.dart';
@ -96,9 +95,7 @@ class VideoConductorProvider extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Provider<VideoConductor>( return Provider<VideoConductor>(
create: (context) => VideoConductor( create: (context) => VideoConductor(),
persistPlayback: context.read<ValueNotifier<AppMode>>().value == AppMode.main,
),
dispose: (context, value) => value.dispose(), dispose: (context, value) => value.dispose(),
child: child, child: child,
); );

View file

@ -604,8 +604,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
if (Navigator.canPop(context)) { if (Navigator.canPop(context)) {
Navigator.pop(context); Navigator.pop(context);
} else { } else {
// leave viewer _leaveViewer();
SystemNavigator.pop();
} }
} }
@ -654,11 +653,18 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
pop(); pop();
} }
} else { } else {
// exit app when trying to pop a viewer page for a single entry // exit app when trying to pop a viewer page
SystemNavigator.pop(); _leaveViewer();
} }
} }
Future<void> _leaveViewer() async {
// widgets do not get disposed normally when popping the `SystemNavigator`
// so we manually clean video controllers and save playback state
await context.read<VideoConductor>().dispose();
await SystemNavigator.pop();
}
// track item when returning to collection, // track item when returning to collection,
// if they are not fully visible already // if they are not fully visible already
void _trackEntry() { void _trackEntry() {

View file

@ -11,14 +11,13 @@ import 'package:collection/collection.dart';
class VideoConductor { class VideoConductor {
final List<AvesVideoController> _controllers = []; final List<AvesVideoController> _controllers = [];
final List<StreamSubscription> _subscriptions = []; final List<StreamSubscription> _subscriptions = [];
final bool persistPlayback;
static const _defaultMaxControllerCount = 3; static const _defaultMaxControllerCount = 3;
VideoConductor({required this.persistPlayback}); VideoConductor();
Future<void> dispose() async { Future<void> dispose() async {
await Future.forEach<AvesVideoController>(_controllers, (controller) => controller.dispose()); await disposeAll();
_subscriptions _subscriptions
..forEach((sub) => sub.cancel()) ..forEach((sub) => sub.cancel())
..clear(); ..clear();
@ -33,7 +32,7 @@ class VideoConductor {
if (controller != null) { if (controller != null) {
_controllers.remove(controller); _controllers.remove(controller);
} else { } else {
controller = IjkPlayerAvesVideoController(entry, persistPlayback: persistPlayback); controller = IjkPlayerAvesVideoController(entry, persistPlayback: true);
_subscriptions.add(controller.statusStream.listen(_onControllerStatusChanged)); _subscriptions.add(controller.statusStream.listen(_onControllerStatusChanged));
} }
_controllers.insert(0, controller); _controllers.insert(0, controller);
@ -55,6 +54,8 @@ class VideoConductor {
Future<void> _applyToAll(FutureOr Function(AvesVideoController controller) action) => Future.forEach<AvesVideoController>(_controllers, action); Future<void> _applyToAll(FutureOr Function(AvesVideoController controller) action) => Future.forEach<AvesVideoController>(_controllers, action);
Future<void> disposeAll() => _applyToAll((controller) => controller.dispose());
Future<void> pauseAll() => _applyToAll((controller) => controller.pause()); Future<void> pauseAll() => _applyToAll((controller) => controller.pause());
Future<void> muteAll(bool muted) => _applyToAll((controller) => controller.mute(muted)); Future<void> muteAll(bool muted) => _applyToAll((controller) => controller.mute(muted));