From de87511d31e3f4b2ce76b595cd2fb196283cf1de Mon Sep 17 00:00:00 2001 From: James Leahy Date: Wed, 22 Feb 2023 17:14:01 +0100 Subject: [PATCH 1/7] feat: video_player web options --- .../lib/video_player_platform_interface.dart | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 32410660ce8e..d754b923d858 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -102,6 +102,11 @@ abstract class VideoPlayerPlatform extends PlatformInterface { Future setMixWithOthers(bool mixWithOthers) { throw UnimplementedError('setMixWithOthers() has not been implemented.'); } + + /// Sets additional options on web + Future setWebOptions(int textureId, VideoPlayerWebOptions options) { + throw UnimplementedError('setWebOptions() has not been implemented.'); + } } class _PlaceholderImplementation extends VideoPlayerPlatform {} @@ -373,6 +378,7 @@ class VideoPlayerOptions { VideoPlayerOptions({ this.mixWithOthers = false, this.allowBackgroundPlayback = false, + this.webOptions, }); /// Set this to true to keep playing video in background, when app goes in background. @@ -385,4 +391,57 @@ class VideoPlayerOptions { /// Note: This option will be silently ignored in the web platform (there is /// currently no way to implement this feature in this platform). final bool mixWithOthers; + + /// Additional web controls + final VideoPlayerWebOptions? webOptions; +} + +/// [VideoPlayerWebOptions] can be optionally used to set additional web settings +@immutable +class VideoPlayerWebOptions { + /// [VideoPlayerWebOptions] can be optionally used to set additional web settings + const VideoPlayerWebOptions({ + this.controlsEnabled = false, + this.allowDownload = true, + this.allowFullscreen = true, + this.allowPlaybackRate = true, + this.allowContextMenu = true, + }); + + /// Whether native controls are enabled + final bool controlsEnabled; + + /// Whether downloaded control is displayed + /// + /// Only applicable when [controlsEnabled] is true + final bool allowDownload; + + /// Whether fullscreen control is enabled + /// + /// Only applicable when [controlsEnabled] is true + final bool allowFullscreen; + + /// Whether playback rate control is displayed + /// + /// Only applicable when [controlsEnabled] is true + final bool allowPlaybackRate; + + /// Whether context menu (right click) is allowed + final bool allowContextMenu; + + /// A string representation of disallowed controls + String get controlsList { + final List controlsList = []; + if (!allowDownload) { + controlsList.add('nodownload'); + } + if (!allowFullscreen) { + controlsList.add('nofullscreen'); + } + if (!allowPlaybackRate) { + controlsList.add('noplaybackrate'); + } + + return controlsList.join(' '); + } } From d0d7b5e705c927184b21497a4f8a7b7576a01cc4 Mon Sep 17 00:00:00 2001 From: James Leahy Date: Wed, 17 May 2023 11:42:54 +0200 Subject: [PATCH 2/7] feat: split controls into VideoPlayerWebOptionsControls --- .../lib/video_player_platform_interface.dart | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index d754b923d858..9a8d9f76abc0 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -401,15 +401,36 @@ class VideoPlayerOptions { class VideoPlayerWebOptions { /// [VideoPlayerWebOptions] can be optionally used to set additional web settings const VideoPlayerWebOptions({ - this.controlsEnabled = false, + this.controls = const VideoPlayerWebOptionsControls.disabled(), + this.allowContextMenu = true, + }); + + /// Additional settings how control options are displayed + final VideoPlayerWebOptionsControls controls; + + /// Whether context menu (right click) is allowed + final bool allowContextMenu; +} + +/// [VideoPlayerWebOptions] can be used to set how control options are displayed +@immutable +class VideoPlayerWebOptionsControls { + /// Enables controls and sets how the options are displayed + const VideoPlayerWebOptionsControls.enabled({ this.allowDownload = true, this.allowFullscreen = true, this.allowPlaybackRate = true, - this.allowContextMenu = true, - }); + }) : enabled = true; + + /// Disables control options. Default behavior. + const VideoPlayerWebOptionsControls.disabled() + : enabled = false, + allowDownload = false, + allowFullscreen = false, + allowPlaybackRate = false; /// Whether native controls are enabled - final bool controlsEnabled; + final bool enabled; /// Whether downloaded control is displayed /// @@ -426,9 +447,6 @@ class VideoPlayerWebOptions { /// Only applicable when [controlsEnabled] is true final bool allowPlaybackRate; - /// Whether context menu (right click) is allowed - final bool allowContextMenu; - /// A string representation of disallowed controls String get controlsList { final List controlsList = []; From ada67144ca80d9a8698ebade301da93b716f8b6d Mon Sep 17 00:00:00 2001 From: James Leahy Date: Thu, 6 Jul 2023 17:00:29 +0200 Subject: [PATCH 3/7] feat: Add allowPictureInPicture (controls), allowRemotePlayback --- .../lib/video_player_platform_interface.dart | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 9a8d9f76abc0..69746f4ad1cb 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -403,6 +403,7 @@ class VideoPlayerWebOptions { const VideoPlayerWebOptions({ this.controls = const VideoPlayerWebOptionsControls.disabled(), this.allowContextMenu = true, + this.allowRemotePlayback = true, }); /// Additional settings how control options are displayed @@ -410,6 +411,9 @@ class VideoPlayerWebOptions { /// Whether context menu (right click) is allowed final bool allowContextMenu; + + /// Whether remote playback is allowed + final bool allowRemotePlayback; } /// [VideoPlayerWebOptions] can be used to set how control options are displayed @@ -420,6 +424,7 @@ class VideoPlayerWebOptionsControls { this.allowDownload = true, this.allowFullscreen = true, this.allowPlaybackRate = true, + this.allowPictureInPicture = true, }) : enabled = true; /// Disables control options. Default behavior. @@ -427,7 +432,8 @@ class VideoPlayerWebOptionsControls { : enabled = false, allowDownload = false, allowFullscreen = false, - allowPlaybackRate = false; + allowPlaybackRate = false, + allowPictureInPicture = false; /// Whether native controls are enabled final bool enabled; @@ -447,6 +453,11 @@ class VideoPlayerWebOptionsControls { /// Only applicable when [controlsEnabled] is true final bool allowPlaybackRate; + /// Whether picture in picture control is displayed + /// + /// Only applicable when [controlsEnabled] is true + final bool allowPictureInPicture; + /// A string representation of disallowed controls String get controlsList { final List controlsList = []; From a0a21c0ba5e12a07501a038dd7d5379a290f7593 Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sat, 8 Jul 2023 09:55:27 +0200 Subject: [PATCH 4/7] chore: Update version, CHANGELOG --- .../video_player/video_player_platform_interface/CHANGELOG.md | 3 ++- .../video_player/video_player_platform_interface/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index f75c5a10f94e..f39924a48eaf 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,6 +1,7 @@ -## NEXT +## 6.2.0 * Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. +* Adds web options to customize control's list and displaying context menu ## 6.1.0 diff --git a/packages/video_player/video_player_platform_interface/pubspec.yaml b/packages/video_player/video_player_platform_interface/pubspec.yaml index f266f6eaded3..b3ab22640f9c 100644 --- a/packages/video_player/video_player_platform_interface/pubspec.yaml +++ b/packages/video_player/video_player_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/video_player/ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 6.1.0 +version: 6.2.0 environment: sdk: ">=2.18.0 <4.0.0" From 4b74b470efcaf2b6815c91c811d5f07627dd1220 Mon Sep 17 00:00:00 2001 From: James Leahy Date: Thu, 13 Jul 2023 14:19:11 +0200 Subject: [PATCH 5/7] chore: Add tests --- .../video_player_platform_interface_test.dart | 12 ++- ...ideo_player_web_options_controls_test.dart | 82 +++++++++++++++++++ .../test/video_player_web_options_test.dart | 32 ++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 packages/video_player/video_player_platform_interface/test/video_player_web_options_controls_test.dart create mode 100644 packages/video_player/video_player_platform_interface/test/video_player_web_options_test.dart diff --git a/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart b/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart index 8aa7ad9bd3c1..7b643de83e3e 100644 --- a/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart +++ b/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart @@ -9,7 +9,17 @@ void main() { // Store the initial instance before any tests change it. final VideoPlayerPlatform initialInstance = VideoPlayerPlatform.instance; - test('default implementation throws uninimpletemented', () async { + test('default implementation init throws unimplemented', () async { await expectLater(() => initialInstance.init(), throwsUnimplementedError); }); + + test('default implementation setWebOptions throws unimplemented', () async { + await expectLater( + () => initialInstance.setWebOptions( + 1, + const VideoPlayerWebOptions(), + ), + throwsUnimplementedError, + ); + }); } diff --git a/packages/video_player/video_player_platform_interface/test/video_player_web_options_controls_test.dart b/packages/video_player/video_player_platform_interface/test/video_player_web_options_controls_test.dart new file mode 100644 index 000000000000..1d6ea15f0914 --- /dev/null +++ b/packages/video_player/video_player_platform_interface/test/video_player_web_options_controls_test.dart @@ -0,0 +1,82 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:video_player_platform_interface/video_player_platform_interface.dart'; + +void main() { + group('VideoPlayerWebOptionsControls', () { + late VideoPlayerWebOptionsControls controls; + + group('when disabled', () { + setUp(() { + controls = const VideoPlayerWebOptionsControls.disabled(); + }); + + test( + 'expect enabled isFalse', + () { + expect(controls.enabled, isFalse); + }, + ); + }); + + group('when enabled', () { + group('and all options are allowed', () { + setUp(() { + controls = const VideoPlayerWebOptionsControls.enabled(); + }); + + test( + 'expect enabled isTrue', + () { + expect(controls.enabled, isTrue); + expect(controls.allowDownload, isTrue); + expect(controls.allowFullscreen, isTrue); + expect(controls.allowPlaybackRate, isTrue); + expect(controls.allowPictureInPicture, isTrue); + }, + ); + + test( + 'expect controlsList isEmpty', + () { + expect(controls.controlsList, isEmpty); + }, + ); + }); + + group('and some options are disallowed', () { + setUp(() { + controls = const VideoPlayerWebOptionsControls.enabled( + allowDownload: false, + allowFullscreen: false, + allowPlaybackRate: false, + ); + }); + + test( + 'expect enabled isTrue', + () { + expect(controls.enabled, isTrue); + expect(controls.allowDownload, isFalse); + expect(controls.allowFullscreen, isFalse); + expect(controls.allowPlaybackRate, isFalse); + expect(controls.allowPictureInPicture, isTrue); + }, + ); + + test( + 'expect controlsList is correct', + () { + expect( + controls.controlsList, + 'nodownload nofullscreen noplaybackrate', + ); + }, + ); + }); + }); + }); +} diff --git a/packages/video_player/video_player_platform_interface/test/video_player_web_options_test.dart b/packages/video_player/video_player_platform_interface/test/video_player_web_options_test.dart new file mode 100644 index 000000000000..ae37fa399331 --- /dev/null +++ b/packages/video_player/video_player_platform_interface/test/video_player_web_options_test.dart @@ -0,0 +1,32 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:video_player_platform_interface/video_player_platform_interface.dart'; + +void main() { + test( + 'VideoPlayerOptions controls defaults to VideoPlayerWebOptionsControls.disabled()', + () { + const VideoPlayerWebOptions options = VideoPlayerWebOptions(); + expect(options.controls, const VideoPlayerWebOptionsControls.disabled()); + }, + ); + + test( + 'VideoPlayerOptions allowContextMenu defaults to true', + () { + const VideoPlayerWebOptions options = VideoPlayerWebOptions(); + expect(options.allowContextMenu, isTrue); + }, + ); + + test( + 'VideoPlayerOptions allowRemotePlayback defaults to true', + () { + const VideoPlayerWebOptions options = VideoPlayerWebOptions(); + expect(options.allowRemotePlayback, isTrue); + }, + ); +} From e74f0ee15b3d179b81566941da5b64c9ae79373f Mon Sep 17 00:00:00 2001 From: Tarrin Neal Date: Mon, 17 Jul 2023 15:24:08 -0700 Subject: [PATCH 6/7] Update CHANGELOG.md missed a period --- .../video_player/video_player_platform_interface/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index f39924a48eaf..e988a210f74d 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,7 +1,7 @@ ## 6.2.0 * Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. -* Adds web options to customize control's list and displaying context menu +* Adds web options to customize control's list and displaying context menu. ## 6.1.0 From ad8d0e98f99e812887740d908655a3055a7766d6 Mon Sep 17 00:00:00 2001 From: Tarrin Neal Date: Mon, 17 Jul 2023 15:31:50 -0700 Subject: [PATCH 7/7] Update video_player_platform_interface.dart more nits --- .../lib/video_player_platform_interface.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 69746f4ad1cb..46b992f58c61 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -370,7 +370,7 @@ class DurationRange { /// [VideoPlayerOptions] can be optionally used to set additional player settings @immutable class VideoPlayerOptions { - /// set additional optional player settings + /// Set additional optional player settings // TODO(stuartmorgan): Temporarily suppress warnings about not using const // in all of the other video player packages, fix this, and then update // the other packages to use const. @@ -406,7 +406,7 @@ class VideoPlayerWebOptions { this.allowRemotePlayback = true, }); - /// Additional settings how control options are displayed + /// Additional settings for how control options are displayed final VideoPlayerWebOptionsControls controls; /// Whether context menu (right click) is allowed