Refactor supported orientations logic to be more robust. Fixes bug where some Android Tablets could not rotate to landscape.
This commit is contained in:
parent
61e93029d7
commit
9a9ccff85c
@ -4,6 +4,7 @@ import 'package:desktop_window/desktop_window.dart';
|
|||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/logic/common/platform_info.dart';
|
import 'package:wonders/logic/common/platform_info.dart';
|
||||||
|
import 'package:wonders/ui/common/modals/fullscreen_video_viewer.dart';
|
||||||
import 'package:wonders/ui/common/utils/page_routes.dart';
|
import 'package:wonders/ui/common/utils/page_routes.dart';
|
||||||
|
|
||||||
class AppLogic {
|
class AppLogic {
|
||||||
@ -11,34 +12,31 @@ class AppLogic {
|
|||||||
/// The router will use this to prevent redirects while bootstrapping.
|
/// The router will use this to prevent redirects while bootstrapping.
|
||||||
bool isBootstrapComplete = false;
|
bool isBootstrapComplete = false;
|
||||||
|
|
||||||
bool get isLandscapeEnabled => PlatformInfo.isDesktopOrWeb || deviceSize.shortestSide > 500;
|
/// Indicates which orientations the app will allow be default. Affects Android/iOS devices only.
|
||||||
|
/// Defaults to both landscape (hz) and portrait (vt)
|
||||||
|
List<Axis> supportedOrientations = [Axis.vertical, Axis.horizontal];
|
||||||
|
|
||||||
/// Support portrait and landscape on desktop, web and tablets. Stick to portrait for phones.
|
/// Allow a view to override the currently supported orientations. For example, [FullscreenVideoViewer] always wants to enable both landscape and portrait.
|
||||||
/// A return value of null indicated both orientations are supported.
|
/// If a view sets this override, they are responsible for setting it back to null when finished.
|
||||||
Axis? get supportedOrientations => isLandscapeEnabled ? null : Axis.vertical;
|
List<Axis>? _supportedOrientationsOverride;
|
||||||
|
set supportedOrientationsOverride(List<Axis>? value) {
|
||||||
Size get deviceSize {
|
if (_supportedOrientationsOverride != value) {
|
||||||
final w = WidgetsBinding.instance.platformDispatcher.views.first;
|
_supportedOrientationsOverride = value;
|
||||||
return w.physicalSize / w.devicePixelRatio;
|
_updateSystemOrientation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the app and all main actors.
|
/// Initialize the app and all main actors.
|
||||||
/// Loads settings, sets up services etc.
|
/// Loads settings, sets up services etc.
|
||||||
Future<void> bootstrap() async {
|
Future<void> bootstrap() async {
|
||||||
// TODO: Switch to `debugPrint` here once landscape issues on android have been resolved
|
debugPrint('bootstrap start...');
|
||||||
print('bootstrap app, deviceSize: $deviceSize, isTablet: $isLandscapeEnabled');
|
|
||||||
print('supportedOrientations: ${supportedOrientations ?? 'All'}');
|
|
||||||
// Set min-sizes for desktop apps
|
// Set min-sizes for desktop apps
|
||||||
if (PlatformInfo.isDesktop) {
|
if (PlatformInfo.isDesktop) {
|
||||||
await DesktopWindow.setMinWindowSize($styles.sizes.minAppSize);
|
await DesktopWindow.setMinWindowSize($styles.sizes.minAppSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load any bitmaps the views might need
|
// Load any bitmaps the views might need
|
||||||
await AppBitmaps.init();
|
await AppBitmaps.init();
|
||||||
|
|
||||||
// Set the initial supported orientations
|
|
||||||
setDeviceOrientation(supportedOrientations);
|
|
||||||
|
|
||||||
// Set preferred refresh rate to the max possible (the OS may ignore this)
|
// Set preferred refresh rate to the max possible (the OS may ignore this)
|
||||||
if (PlatformInfo.isAndroid) {
|
if (PlatformInfo.isAndroid) {
|
||||||
await FlutterDisplayMode.setHighRefreshRate();
|
await FlutterDisplayMode.setHighRefreshRate();
|
||||||
@ -71,15 +69,34 @@ class AppLogic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDeviceOrientation(Axis? axis) {
|
Future<T?> showFullscreenDialogRoute<T>(BuildContext context, Widget child, {bool transparent = false}) async {
|
||||||
|
return await Navigator.of(context).push<T>(
|
||||||
|
PageRoutes.dialog<T>(child, duration: $styles.times.pageTransition),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Called from the UI layer once a MediaQuery has been obtained
|
||||||
|
void handleAppSizeChanged(Size size) {
|
||||||
|
/// Disable landscape layout on smaller form factors
|
||||||
|
bool isSmall = size.shortestSide < 500 && size != Size.zero;
|
||||||
|
supportedOrientations = isSmall ? [Axis.vertical] : [Axis.vertical, Axis.horizontal];
|
||||||
|
_updateSystemOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable landscape, portrait or both. Views can call this method to override the default settings.
|
||||||
|
/// For example, the [FullscreenVideoViewer] always wants to enable both landscape and portrait.
|
||||||
|
/// If a view overrides this, it is responsible for setting it back to [supportedOrientations] when disposed.
|
||||||
|
void _updateSystemOrientation() {
|
||||||
|
final axisList = _supportedOrientationsOverride ?? supportedOrientations;
|
||||||
|
debugPrint('updateDeviceOrientation, supportedAxis: $axisList');
|
||||||
final orientations = <DeviceOrientation>[];
|
final orientations = <DeviceOrientation>[];
|
||||||
if (axis == null || axis == Axis.vertical) {
|
if (axisList.contains(Axis.vertical)) {
|
||||||
orientations.addAll([
|
orientations.addAll([
|
||||||
DeviceOrientation.portraitUp,
|
DeviceOrientation.portraitUp,
|
||||||
DeviceOrientation.portraitDown,
|
DeviceOrientation.portraitDown,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if (axis == null || axis == Axis.horizontal) {
|
if (axisList.contains(Axis.horizontal)) {
|
||||||
orientations.addAll([
|
orientations.addAll([
|
||||||
DeviceOrientation.landscapeLeft,
|
DeviceOrientation.landscapeLeft,
|
||||||
DeviceOrientation.landscapeRight,
|
DeviceOrientation.landscapeRight,
|
||||||
@ -87,10 +104,4 @@ class AppLogic {
|
|||||||
}
|
}
|
||||||
SystemChrome.setPreferredOrientations(orientations);
|
SystemChrome.setPreferredOrientations(orientations);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<T?> showFullscreenDialogRoute<T>(BuildContext context, Widget child, {bool transparent = false}) async {
|
|
||||||
return await Navigator.of(context).push<T>(
|
|
||||||
PageRoutes.dialog<T>(child, duration: $styles.times.pageTransition),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ final appRouter = GoRouter(
|
|||||||
return TimelineScreen(type: _tryParseWonderType(s.queryParams['type']!));
|
return TimelineScreen(type: _tryParseWonderType(s.queryParams['type']!));
|
||||||
}),
|
}),
|
||||||
AppRoute('/video/:id', (s) {
|
AppRoute('/video/:id', (s) {
|
||||||
return FullscreenVideoPage(id: s.params['id']!);
|
return FullscreenVideoViewer(id: s.params['id']!);
|
||||||
}),
|
}),
|
||||||
AppRoute('/highlights/:type', (s) {
|
AppRoute('/highlights/:type', (s) {
|
||||||
return ArtifactCarouselScreen(type: _parseWonderType(s.params['type']));
|
return ArtifactCarouselScreen(type: _parseWonderType(s.params['type']));
|
||||||
|
@ -11,7 +11,8 @@ class WondersAppScaffold extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Listen to the device size, and update AppStyle when it changes
|
// Listen to the device size, and update AppStyle when it changes
|
||||||
_style = AppStyle(screenSize: context.sizePx);
|
_style = AppStyle(screenSize: context.sizePx);
|
||||||
Animate.defaultDuration = $styles.times.fast;
|
Animate.defaultDuration = _style.times.fast;
|
||||||
|
appLogic.handleAppSizeChanged(context.mq.size);
|
||||||
return Stack(
|
return Stack(
|
||||||
key: ValueKey($styles.scale),
|
key: ValueKey($styles.scale),
|
||||||
children: [
|
children: [
|
||||||
|
@ -2,15 +2,15 @@ import 'package:wonders/common_libs.dart';
|
|||||||
import 'package:wonders/ui/common/controls/app_loading_indicator.dart';
|
import 'package:wonders/ui/common/controls/app_loading_indicator.dart';
|
||||||
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
|
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
|
||||||
|
|
||||||
class FullscreenVideoPage extends StatefulWidget {
|
class FullscreenVideoViewer extends StatefulWidget {
|
||||||
const FullscreenVideoPage({Key? key, required this.id}) : super(key: key);
|
const FullscreenVideoViewer({Key? key, required this.id}) : super(key: key);
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FullscreenVideoPage> createState() => _FullscreenVideoPageState();
|
State<FullscreenVideoViewer> createState() => _FullscreenVideoViewerState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FullscreenVideoPageState extends State<FullscreenVideoPage> {
|
class _FullscreenVideoViewerState extends State<FullscreenVideoViewer> {
|
||||||
late final _controller = YoutubePlayerController(
|
late final _controller = YoutubePlayerController(
|
||||||
initialVideoId: widget.id,
|
initialVideoId: widget.id,
|
||||||
params: const YoutubePlayerParams(autoPlay: true, startAt: Duration(seconds: 1)),
|
params: const YoutubePlayerParams(autoPlay: true, startAt: Duration(seconds: 1)),
|
||||||
@ -19,13 +19,13 @@ class _FullscreenVideoPageState extends State<FullscreenVideoPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
appLogic.setDeviceOrientation(null);
|
appLogic.supportedOrientationsOverride = [Axis.horizontal, Axis.vertical];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
// when view closes, restore the supported orientations
|
// when view closes, remove the override
|
||||||
appLogic.setDeviceOrientation(appLogic.supportedOrientations);
|
appLogic.supportedOrientationsOverride = null;
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user