diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml new file mode 100644 index 000000000..f2f350abf --- /dev/null +++ b/.github/workflows/dart.yml @@ -0,0 +1,18 @@ +name: Dart CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + container: + image: google/dart:latest + + steps: + - uses: actions/checkout@v1 + - name: Install dependencies + run: pub get + - name: Run tests + run: pub run test diff --git a/example/flutter_01.log b/example/flutter_01.log new file mode 100644 index 000000000..ff5effb7c --- /dev/null +++ b/example/flutter_01.log @@ -0,0 +1,95 @@ +Flutter crash report; please file at https://github.com/flutter/flutter/issues. + +## command + +flutter --no-color run --machine --track-widget-creation --device-id=emulator-5554 lib/main.dart + +## exception + +NoSuchMethodError: NoSuchMethodError: The method 'matchAsPrefix' was called on null. +Receiver: null +Tried calling: matchAsPrefix(" ^", 0) + +``` +#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5) +#1 _StringBase.startsWith (dart:core-patch/string_patch.dart:331:20) +#2 StdoutHandler.handler (package:flutter_tools/src/compile.dart:109:17) +#3 _rootRunUnary (dart:async/zone.dart:1132:38) +#4 _CustomZone.runUnary (dart:async/zone.dart:1029:19) +#5 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7) +#6 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11) +#7 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7) +#8 _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:68:11) +#9 _EventSinkWrapper.add (dart:async/stream_transformers.dart:15:11) +#10 _StringAdapterSink.add (dart:convert/string_conversion.dart:236:11) +#11 _LineSplitterSink._addLines (dart:convert/line_splitter.dart:150:13) +#12 _LineSplitterSink.addSlice (dart:convert/line_splitter.dart:125:5) +#13 StringConversionSinkMixin.add (dart:convert/string_conversion.dart:163:5) +#14 _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:120:24) +#15 _rootRunUnary (dart:async/zone.dart:1132:38) +#16 _CustomZone.runUnary (dart:async/zone.dart:1029:19) +#17 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7) +#18 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11) +#19 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7) +#20 _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:68:11) +#21 _EventSinkWrapper.add (dart:async/stream_transformers.dart:15:11) +#22 _StringAdapterSink.add (dart:convert/string_conversion.dart:236:11) +#23 _StringAdapterSink.addSlice (dart:convert/string_conversion.dart:241:7) +#24 _Utf8ConversionSink.addSlice (dart:convert/string_conversion.dart:312:20) +#25 _Utf8ConversionSink.add (dart:convert/string_conversion.dart:305:5) +#26 _ConverterStreamEventSink.add (dart:convert/chunked_conversion.dart:72:18) +#27 _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:120:24) +#28 _rootRunUnary (dart:async/zone.dart:1132:38) +#29 _CustomZone.runUnary (dart:async/zone.dart:1029:19) +#30 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7) +#31 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11) +#32 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7) +#33 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:764:19) +#34 _StreamController._add (dart:async/stream_controller.dart:640:7) +#35 _StreamController.add (dart:async/stream_controller.dart:586:5) +#36 _Socket._onData (dart:io-patch/socket_patch.dart:1791:41) +#37 _rootRunUnary (dart:async/zone.dart:1136:13) +#38 _CustomZone.runUnary (dart:async/zone.dart:1029:19) +#39 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7) +#40 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11) +#41 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7) +#42 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:764:19) +#43 _StreamController._add (dart:async/stream_controller.dart:640:7) +#44 _StreamController.add (dart:async/stream_controller.dart:586:5) +#45 new _RawSocket. (dart:io-patch/socket_patch.dart:1339:33) +#46 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:860:14) +#47 _microtaskLoop (dart:async/schedule_microtask.dart:41:21) +#48 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5) +#49 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:116:13) +#50 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:173:5) +``` + +## flutter doctor + +``` +[✓] Flutter (Channel stable, v1.9.1+hotfix.6, on Linux, locale en_US.utf8) + • Flutter version 1.9.1+hotfix.6 at /home/kasbokar/flutter/flutter + • Framework revision 68587a0916 (3 months ago), 2019-09-13 19:46:58 -0700 + • Engine revision b863200c37 + • Dart version 2.5.0 + +[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3) + • Android SDK at /home/kasbokar/app/sdk + • Android NDK location not configured (optional; useful for native profiling support) + • Platform android-29, build-tools 28.0.3 + • ANDROID_HOME = /home/kasbokar/app/sdk + • Java binary at: /home/kasbokar/app/android-studio/jre/bin/java + • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405) + • All Android licenses accepted. + +[✓] Android Studio (version 3.5) + • Android Studio at /home/kasbokar/app/android-studio + • Flutter plugin version 42.1.1 + • Dart plugin version 191.8593 + • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405) + +[✓] Connected device (1 available) + • Android SDK built for x86 • emulator-5554 • android-x86 • Android 9 (API 28) (emulator) + +• No issues found! +``` diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh new file mode 100755 index 000000000..acb3ce81d --- /dev/null +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/home/kasbokar/flutter/flutter" +export "FLUTTER_APPLICATION_PATH=/home/kasbokar/AndroidStudioProjects/chewie_local/chewie/example" +export "FLUTTER_TARGET=lib/main.dart" +export "FLUTTER_BUILD_DIR=build" +export "SYMROOT=${SOURCE_ROOT}/../build/ios" +export "FLUTTER_FRAMEWORK_DIR=/home/kasbokar/flutter/flutter/bin/cache/artifacts/engine/ios" diff --git a/example/lib/auto_rotate.dart b/example/lib/auto_rotate.dart index 67774e1c3..7a4aeedfc 100644 --- a/example/lib/auto_rotate.dart +++ b/example/lib/auto_rotate.dart @@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:video_player/video_player.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; void main() { runApp( @@ -90,10 +91,20 @@ class _ChewieDemoState extends State { theme: ThemeData.light().copyWith( platform: _platform ?? Theme.of(context).platform, ), + locale:Locale('fa', 'IR'), + supportedLocales: [ + const Locale('fa', 'IR'), + const Locale('en', 'US'), + ], + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], home: Scaffold( appBar: AppBar( title: Text(widget.title), ), + body: Column( children: [ Expanded( diff --git a/example/lib/main.dart b/example/lib/main.dart index 828ed2c66..5222b485a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -3,6 +3,7 @@ import 'package:chewie/src/chewie_player.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; void main() { runApp( @@ -26,7 +27,7 @@ class _ChewieDemoState extends State { VideoPlayerController _videoPlayerController1; VideoPlayerController _videoPlayerController2; ChewieController _chewieController; - + Locale locale; @override void initState() { super.initState(); @@ -66,10 +67,19 @@ class _ChewieDemoState extends State { @override Widget build(BuildContext context) { return MaterialApp( + supportedLocales: [ + const Locale('fa', 'IR'), + const Locale('en', 'US'), + ], + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], title: widget.title, theme: ThemeData.light().copyWith( platform: _platform ?? Theme.of(context).platform, ), + locale:Locale('fa', 'IR'), home: Scaffold( appBar: AppBar( title: Text(widget.title), diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 51a24767f..fe7a05aec 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -8,12 +8,14 @@ dependencies: auto_orientation: ^0.0.2 flutter: sdk: flutter - + flutter_localizations: + sdk: flutter + flutter_cupertino_localizations: ^1.0.1 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - - cupertino_icons: ^0.1.0 - + intl: + intl_translation: + cupertino_icons: ^0.1.2 dev_dependencies: flutter_test: sdk: flutter diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index dec4ba740..e32f3dcf7 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -185,6 +185,7 @@ class ChewieController extends ChangeNotifier { this.isLive = false, this.allowFullScreen = true, this.allowMuting = true, + this.rtl=false, this.systemOverlaysAfterFullScreen = SystemUiOverlay.values, this.deviceOrientationsAfterFullScreen = const [ DeviceOrientation.portraitUp, @@ -271,6 +272,8 @@ class ChewieController extends ChangeNotifier { /// Defines a custom RoutePageBuilder for the fullscreen final ChewieRoutePageBuilder routePageBuilder; + /// Defines a rtl Direction + final bool rtl; static ChewieController of(BuildContext context) { final chewieControllerProvider = diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart index c85c39433..06bf0214e 100644 --- a/lib/src/material_controls.dart +++ b/lib/src/material_controls.dart @@ -6,7 +6,6 @@ import 'package:chewie/src/material_progress_bar.dart'; import 'package:chewie/src/utils.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; - class MaterialControls extends StatefulWidget { const MaterialControls({Key key}) : super(key: key); @@ -108,7 +107,6 @@ class _MaterialControlsState extends State { BuildContext context, ) { final iconColor = Theme.of(context).textTheme.button.color; - return AnimatedOpacity( opacity: _hideStuff ? 0.0 : 1.0, duration: Duration(milliseconds: 300), @@ -116,24 +114,32 @@ class _MaterialControlsState extends State { height: barHeight, color: Theme.of(context).dialogBackgroundColor, child: Row( - children: [ - _buildPlayPause(controller), - chewieController.isLive - ? Expanded(child: const Text('LIVE')) - : _buildPosition(iconColor), - chewieController.isLive ? const SizedBox() : _buildProgressBar(), - chewieController.allowMuting - ? _buildMuteButton(controller) - : Container(), - chewieController.allowFullScreen - ? _buildExpandButton() - : Container(), - ], + children: createWidget(iconColor) ), ), ); } + List createWidget(Color iconColor){ + Locale myLocale = Localizations.localeOf(context); + isRtlLanguage( myLocale.languageCode); + List showTabBar=[ _buildPlayPause(controller), + chewieController.isLive + ? Expanded(child: const Text('LIVE')) + : _buildPosition(iconColor), + chewieController.isLive ? const SizedBox() : _buildProgressBar(), + chewieController.allowMuting + ? _buildMuteButton(controller) + : Container(), + chewieController.allowFullScreen + ? _buildExpandButton() + : Container(),]; + if(chewieController.rtl||isRtlLanguage( myLocale.languageCode)){ + showTabBar =showTabBar.reversed.toList(); + } + return showTabBar; + } + GestureDetector _buildExpandButton() { return GestureDetector( onTap: _onExpandCollapse, diff --git a/lib/src/utils.dart b/lib/src/utils.dart index f1b216fa8..3fe165fda 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -20,3 +20,16 @@ String formatDuration(Duration position) { return formattedTime; } +///isRtlLanguage return bool rtl +///RegExp is taken from intl dart package +bool isRtlLanguage(String language) { + final _rtlLocaleRegex = RegExp( + r'^(ar|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|.*[-_]' + r'(Arab|Hebr|Thaa|Nkoo|Tfng))(?!.*[-_](Latn|Cyrl)($|-|_))' + r'($|-|_)', + caseSensitive: false); + + final bool _rtlCheck = _rtlLocaleRegex.hasMatch(language); + +return _rtlCheck; +} \ No newline at end of file