import 'dart:async'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:spotiflac_android/utils/logger.dart'; const fullPlayerRouteName = '/full-player'; final _log = AppLogger('Orientation'); /// Only the full player opts into rotation. Sheets and dialogs inherit the /// underlying page's orientation, while another page restores portrait. Future setAppOrientation({bool playerVisible = false}) => SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, if (playerVisible) ...[ DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ], ]); class AppOrientationObserver extends NavigatorObserver { final _routes = >[]; bool? _playerVisible; void _sync() { final page = _routes.whereType>().lastOrNull; final playerVisible = page?.settings.name == fullPlayerRouteName; if (_playerVisible == playerVisible) return; _playerVisible = playerVisible; unawaited( setAppOrientation(playerVisible: playerVisible).catchError(( Object error, ) { _log.w('Could not update screen orientation: $error'); }), ); } @override void didPush(Route route, Route? previousRoute) { _routes.add(route); _sync(); } @override void didPop(Route route, Route? previousRoute) { _routes.remove(route); _sync(); } @override void didRemove(Route route, Route? previousRoute) { _routes.remove(route); _sync(); } @override void didReplace({Route? newRoute, Route? oldRoute}) { final index = oldRoute == null ? -1 : _routes.indexOf(oldRoute); if (index >= 0) { if (newRoute == null) { _routes.removeAt(index); } else { _routes[index] = newRoute; } } else if (newRoute != null) { _routes.add(newRoute); } _sync(); } }