From b18f22ea06dd98017107ebec16fad14577b0dbed Mon Sep 17 00:00:00 2001 From: Tommy Chow Date: Sun, 5 Jun 2022 17:24:51 -0400 Subject: [PATCH] Fix rotate button behavior on iOS (#138) --- lib/screens/channel/stores/video_store.dart | 18 +++++++++- lib/screens/channel/stores/video_store.g.dart | 26 ++++++++++++++ lib/screens/channel/video_chat.dart | 35 ++++++++++++++----- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/lib/screens/channel/stores/video_store.dart b/lib/screens/channel/stores/video_store.dart index 44e2f2c2..ea769af6 100644 --- a/lib/screens/channel/stores/video_store.dart +++ b/lib/screens/channel/stores/video_store.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:frosty/api/twitch_api.dart'; @@ -37,6 +38,9 @@ abstract class VideoStoreBase with Store { @readonly var _overlayVisible = true; + @readonly + var _isIPad = false; + @readonly StreamTwitch? _streamInfo; @@ -152,13 +156,25 @@ abstract class VideoStoreBase with Store { return NavigationDecision.prevent; } - void initVideo() { + @action + Future initVideo() async { try { controller?.runJavascript('document.getElementsByTagName("video")[0].addEventListener("pause", () => Pause.postMessage("video paused"));'); controller?.runJavascript('document.getElementsByTagName("video")[0].addEventListener("play", () => Play.postMessage("video playing"));'); } catch (e) { debugPrint(e.toString()); } + + // Determine whether the device is an iPad or not. + // Used to show or hide the rotate button on the overlay. + // Flutter doesn't allow programmatic rotation on iPad unless multitasking is disabled. + final deviceInfo = DeviceInfoPlugin(); + final info = await deviceInfo.iosInfo; + if (info.model?.toLowerCase().contains('ipad') == true) { + _isIPad = true; + } else { + _isIPad = false; + } } void requestPictureInPicture() { diff --git a/lib/screens/channel/stores/video_store.g.dart b/lib/screens/channel/stores/video_store.g.dart index 28710c74..914038ce 100644 --- a/lib/screens/channel/stores/video_store.g.dart +++ b/lib/screens/channel/stores/video_store.g.dart @@ -101,6 +101,24 @@ mixin _$VideoStore on VideoStoreBase, Store { }); } + late final _$_isIPadAtom = + Atom(name: 'VideoStoreBase._isIPad', context: context); + + bool get isIPad { + _$_isIPadAtom.reportRead(); + return super._isIPad; + } + + @override + bool get _isIPad => isIPad; + + @override + set _isIPad(bool value) { + _$_isIPadAtom.reportWrite(value, super._isIPad, () { + super._isIPad = value; + }); + } + late final _$_streamInfoAtom = Atom(name: 'VideoStoreBase._streamInfo', context: context); @@ -136,6 +154,14 @@ mixin _$VideoStore on VideoStoreBase, Store { .run(() => super.handleToggleOverlay()); } + late final _$initVideoAsyncAction = + AsyncAction('VideoStoreBase.initVideo', context: context); + + @override + Future initVideo() { + return _$initVideoAsyncAction.run(() => super.initVideo()); + } + late final _$VideoStoreBaseActionController = ActionController(name: 'VideoStoreBase', context: context); diff --git a/lib/screens/channel/video_chat.dart b/lib/screens/channel/video_chat.dart index 68a37ae7..d14e37de 100644 --- a/lib/screens/channel/video_chat.dart +++ b/lib/screens/channel/video_chat.dart @@ -433,18 +433,35 @@ class _VideoOverlay extends StatelessWidget { ); final rotateButton = IconButton( - tooltip: orientation == Orientation.portrait ? 'Enter Landscape Mode (Lock)' : 'Exit Landscape Mode', + tooltip: orientation == Orientation.portrait ? 'Enter Landscape Mode' : 'Exit Landscape Mode', + icon: const Icon( + Icons.screen_rotation, + color: Colors.white, + ), onPressed: () { - if (orientation == Orientation.portrait) { - SystemChrome.setPreferredOrientations([ - DeviceOrientation.landscapeRight, - DeviceOrientation.landscapeLeft, - ]); + if (Platform.isIOS) { + if (orientation == Orientation.portrait) { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeRight, + ]); + SystemChrome.setPreferredOrientations([]); + } else { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + ]); + SystemChrome.setPreferredOrientations([]); + } } else { - SystemChrome.setPreferredOrientations([]); + if (orientation == Orientation.portrait) { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeRight, + DeviceOrientation.landscapeLeft, + ]); + } else { + SystemChrome.setPreferredOrientations([]); + } } }, - icon: orientation == Orientation.portrait ? const Icon(Icons.screen_lock_rotation) : const Icon(Icons.screen_rotation), ); final streamInfo = videoStore.streamInfo; @@ -600,7 +617,7 @@ class _VideoOverlay extends StatelessWidget { ), if (videoStore.settingsStore.fullScreen && orientation == Orientation.landscape) chatOverlayButton, refreshButton, - rotateButton, + if (!videoStore.isIPad) rotateButton, if (orientation == Orientation.landscape) fullScreenButton, ], ),