mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-29 12:52:13 +02:00
fix(ui): allow landscape only in the full player
Keep application pages in portrait and let player sheets inherit rotation from the full player. Restore portrait on navigation, replacement, removal, and completed dismissal; discard stale minimization geometry when the screen rotates on close. Validated with 12 Flutter tests and targeted analysis. iOS simulator build confirms portrait startup from a landscape device. Platform orientation restrictions still apply on large Android displays and multitasking iPads.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
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<void> setAppOrientation({bool playerVisible = false}) =>
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
if (playerVisible) ...[
|
||||
DeviceOrientation.landscapeLeft,
|
||||
DeviceOrientation.landscapeRight,
|
||||
],
|
||||
]);
|
||||
|
||||
class AppOrientationObserver extends NavigatorObserver {
|
||||
final _routes = <Route<dynamic>>[];
|
||||
bool? _playerVisible;
|
||||
|
||||
void _sync() {
|
||||
final page = _routes.whereType<PageRoute<dynamic>>().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<dynamic> route, Route<dynamic>? previousRoute) {
|
||||
_routes.add(route);
|
||||
_sync();
|
||||
}
|
||||
|
||||
@override
|
||||
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
||||
_routes.remove(route);
|
||||
_sync();
|
||||
}
|
||||
|
||||
@override
|
||||
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
||||
_routes.remove(route);
|
||||
_sync();
|
||||
}
|
||||
|
||||
@override
|
||||
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user