#399 keep manually un/muted state for following autoplayed videos
This commit is contained in:
parent
ee6ee1b320
commit
f3bee6ec7e
7 changed files with 42 additions and 19 deletions
|
@ -13,8 +13,9 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- No default map style for `izzy` and `libre` flavors
|
- Map: no default map style for `izzy` and `libre` flavors
|
||||||
- allow setting default editor
|
- Viewer: allow setting default editor
|
||||||
|
- Viewer: keep manually un/muted state for following autoplayed videos
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:aves/app_mode.dart';
|
import 'package:aves/app_mode.dart';
|
||||||
|
import 'package:aves/model/actions/entry_actions.dart';
|
||||||
import 'package:aves/model/actions/move_type.dart';
|
import 'package:aves/model/actions/move_type.dart';
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
|
@ -255,7 +256,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
||||||
} else if (notification is VideoActionNotification) {
|
} else if (notification is VideoActionNotification) {
|
||||||
final controller = notification.controller;
|
final controller = notification.controller;
|
||||||
final action = notification.action;
|
final action = notification.action;
|
||||||
_videoActionDelegate.onActionSelected(context, controller, action);
|
_onVideoAction(context, controller, action);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -396,7 +397,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
||||||
scale: _overlayVideoControlScale,
|
scale: _overlayVideoControlScale,
|
||||||
onActionSelected: (action) {
|
onActionSelected: (action) {
|
||||||
if (videoController != null) {
|
if (videoController != null) {
|
||||||
_videoActionDelegate.onActionSelected(context, videoController, action);
|
_onVideoAction(context, videoController, action);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onActionMenuOpened: () {
|
onActionMenuOpened: () {
|
||||||
|
@ -482,6 +483,15 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _onVideoAction(BuildContext context, AvesVideoController controller, EntryAction action) async {
|
||||||
|
await _videoActionDelegate.onActionSelected(context, controller, action);
|
||||||
|
if (action == EntryAction.videoToggleMute) {
|
||||||
|
final override = controller.isMuted;
|
||||||
|
videoMutedOverride = override;
|
||||||
|
await context.read<VideoConductor>().muteAll(override);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _onVerticalPageControllerChange() {
|
void _onVerticalPageControllerChange() {
|
||||||
if (!_isEntryTracked && _verticalPager.hasClients && _verticalPager.page?.floor() == transitionPage) {
|
if (!_isEntryTracked && _verticalPager.hasClients && _verticalPager.page?.floor() == transitionPage) {
|
||||||
_trackEntry();
|
_trackEntry();
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/widgets/viewer/video/controller.dart';
|
import 'package:aves/widgets/viewer/video/controller.dart';
|
||||||
import 'package:aves/widgets/viewer/video/fijkplayer.dart';
|
import 'package:aves/widgets/viewer/video/fijkplayer.dart';
|
||||||
|
@ -34,5 +36,9 @@ class VideoConductor {
|
||||||
return _controllers.firstWhereOrNull((c) => c.entry.uri == entry.uri && c.entry.pageId == entry.pageId);
|
return _controllers.firstWhereOrNull((c) => c.entry.uri == entry.uri && c.entry.pageId == entry.pageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> pauseAll() => Future.forEach<AvesVideoController>(_controllers, (controller) => controller.pause());
|
Future<void> _applyToAll(FutureOr Function(AvesVideoController controller) action) => Future.forEach<AvesVideoController>(_controllers, action);
|
||||||
|
|
||||||
|
Future<void> pauseAll() => _applyToAll((controller) => controller.pause());
|
||||||
|
|
||||||
|
Future<void> muteAll(bool muted) => _applyToAll((controller) => controller.mute(muted));
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ abstract class AvesVideoController {
|
||||||
|
|
||||||
Future<Uint8List> captureFrame();
|
Future<Uint8List> captureFrame();
|
||||||
|
|
||||||
Future<void> toggleMute();
|
Future<void> mute(bool muted);
|
||||||
|
|
||||||
Widget buildPlayerWidget(BuildContext context);
|
Widget buildPlayerWidget(BuildContext context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,8 +363,8 @@ class IjkPlayerAvesVideoController extends AvesVideoController {
|
||||||
bool get isMuted => _volume == 0;
|
bool get isMuted => _volume == 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> toggleMute() async {
|
Future<void> mute(bool muted) async {
|
||||||
_volume = isMuted ? 1 : 0;
|
_volume = muted ? 0 : 1;
|
||||||
_volumeStreamController.add(_volume);
|
_volumeStreamController.add(_volume);
|
||||||
await _applyVolume();
|
await _applyVolume();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,39 +35,39 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
||||||
stopOverlayHidingTimer();
|
stopOverlayHidingTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onActionSelected(BuildContext context, AvesVideoController controller, EntryAction action) {
|
Future<void> onActionSelected(BuildContext context, AvesVideoController controller, EntryAction action) async {
|
||||||
// make sure overlay is not disappearing when selecting an action
|
// make sure overlay is not disappearing when selecting an action
|
||||||
stopOverlayHidingTimer();
|
stopOverlayHidingTimer();
|
||||||
const ToggleOverlayNotification(visible: true).dispatch(context);
|
const ToggleOverlayNotification(visible: true).dispatch(context);
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case EntryAction.videoCaptureFrame:
|
case EntryAction.videoCaptureFrame:
|
||||||
_captureFrame(context, controller);
|
await _captureFrame(context, controller);
|
||||||
break;
|
break;
|
||||||
case EntryAction.videoToggleMute:
|
case EntryAction.videoToggleMute:
|
||||||
controller.toggleMute();
|
await controller.mute(!controller.isMuted);
|
||||||
break;
|
break;
|
||||||
case EntryAction.videoSelectStreams:
|
case EntryAction.videoSelectStreams:
|
||||||
_showStreamSelectionDialog(context, controller);
|
await _showStreamSelectionDialog(context, controller);
|
||||||
break;
|
break;
|
||||||
case EntryAction.videoSetSpeed:
|
case EntryAction.videoSetSpeed:
|
||||||
_showSpeedDialog(context, controller);
|
await _showSpeedDialog(context, controller);
|
||||||
break;
|
break;
|
||||||
case EntryAction.videoSettings:
|
case EntryAction.videoSettings:
|
||||||
_showSettings(context, controller);
|
await _showSettings(context, controller);
|
||||||
break;
|
break;
|
||||||
case EntryAction.videoTogglePlay:
|
case EntryAction.videoTogglePlay:
|
||||||
_togglePlayPause(context, controller);
|
await _togglePlayPause(context, controller);
|
||||||
break;
|
break;
|
||||||
case EntryAction.videoReplay10:
|
case EntryAction.videoReplay10:
|
||||||
controller.seekTo(controller.currentPosition - 10000);
|
await controller.seekTo(controller.currentPosition - 10000);
|
||||||
break;
|
break;
|
||||||
case EntryAction.videoSkip10:
|
case EntryAction.videoSkip10:
|
||||||
controller.seekTo(controller.currentPosition + 10000);
|
await controller.seekTo(controller.currentPosition + 10000);
|
||||||
break;
|
break;
|
||||||
case EntryAction.open:
|
case EntryAction.open:
|
||||||
final entry = controller.entry;
|
final entry = controller.entry;
|
||||||
androidAppService.open(entry.uri, entry.mimeTypeAnySubtype).then((success) {
|
await androidAppService.open(entry.uri, entry.mimeTypeAnySubtype).then((success) {
|
||||||
if (!success) showNoMatchingAppDialog(context);
|
if (!success) showNoMatchingAppDialog(context);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,6 +17,8 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
final Map<AvesEntry, VoidCallback> _metadataChangeListeners = {};
|
final Map<AvesEntry, VoidCallback> _metadataChangeListeners = {};
|
||||||
final Map<MultiPageController, Future<void> Function()> _multiPageControllerPageListeners = {};
|
final Map<MultiPageController, Future<void> Function()> _multiPageControllerPageListeners = {};
|
||||||
|
|
||||||
|
bool? videoMutedOverride;
|
||||||
|
|
||||||
bool get isViewingImage;
|
bool get isViewingImage;
|
||||||
|
|
||||||
ValueNotifier<AvesEntry?> get entryNotifier;
|
ValueNotifier<AvesEntry?> get entryNotifier;
|
||||||
|
@ -89,6 +91,10 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get shouldAutoPlayVideoMuted {
|
bool get shouldAutoPlayVideoMuted {
|
||||||
|
if (videoMutedOverride != null) {
|
||||||
|
return videoMutedOverride!;
|
||||||
|
}
|
||||||
|
|
||||||
switch (videoPlaybackOverride) {
|
switch (videoPlaybackOverride) {
|
||||||
case SlideshowVideoPlayback.skip:
|
case SlideshowVideoPlayback.skip:
|
||||||
case SlideshowVideoPlayback.playWithSound:
|
case SlideshowVideoPlayback.playWithSound:
|
||||||
|
@ -189,7 +195,7 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
await Future.delayed(const Duration(milliseconds: 300) * timeDilation);
|
await Future.delayed(const Duration(milliseconds: 300) * timeDilation);
|
||||||
|
|
||||||
if (!videoController.isMuted && shouldAutoPlayVideoMuted) {
|
if (!videoController.isMuted && shouldAutoPlayVideoMuted) {
|
||||||
await videoController.toggleMute();
|
await videoController.mute(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resumeTimeMillis != null) {
|
if (resumeTimeMillis != null) {
|
||||||
|
|
Loading…
Reference in a new issue