feat: smart auto-rotation & orientation controls in fullscreen video (v2.3.5)

This commit is contained in:
2026-09-04 13:42:07 +03:00
parent fe4777c4b3
commit 10b02b2d6f
3 changed files with 55 additions and 13 deletions
+9
View File
@@ -1,4 +1,13 @@
const lunarisChangelog = [ const lunarisChangelog = [
LunarisChange(
version: '2.3.5',
title: 'Fullscreen Video Auto-Rotation & Orientation Controls',
bullets: [
'Smart Fullscreen Auto-Rotation: entering fullscreen mode on horizontal/landscape videos automatically snaps the device into landscape orientation for maximum viewing area, while vertical/portrait videos stay in portrait mode.',
'Manual Orientation Toggle: added a quick-access rotation button (Icons.screen_lock_portrait / landscape) directly in the fullscreen top bar next to the close button, allowing 1-tap switching between landscape and portrait.',
'Clean Orientation Recovery: exiting fullscreen seamlessly restores system navigation bars (Edge-to-Edge) and restores unrestricted device sensor orientations.',
],
),
LunarisChange( LunarisChange(
version: '2.3.4', version: '2.3.4',
title: 'OverlayPortal Architecture & Search UI Unblocking', title: 'OverlayPortal Architecture & Search UI Unblocking',
@@ -701,6 +701,7 @@ class _FullscreenVideoPageState extends State<_FullscreenVideoPage> {
late bool _muted; late bool _muted;
late bool _loopVideo; late bool _loopVideo;
late bool _halfVolume; late bool _halfVolume;
late bool _isLandscape;
Timer? _hideTimer; Timer? _hideTimer;
@override @override
@@ -710,13 +711,30 @@ class _FullscreenVideoPageState extends State<_FullscreenVideoPage> {
_muted = widget.muted; _muted = widget.muted;
_loopVideo = widget.loopVideo; _loopVideo = widget.loopVideo;
_halfVolume = widget.halfVolume; _halfVolume = widget.halfVolume;
_isLandscape = widget.aspectRatio > 1.05;
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
_applyOrientation();
_scheduleControlsHide();
}
void _applyOrientation() {
if (_isLandscape) {
SystemChrome.setPreferredOrientations([ SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight, DeviceOrientation.landscapeRight,
DeviceOrientation.portraitUp,
]); ]);
_scheduleControlsHide(); } else {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
}
void _toggleOrientation() {
setState(() => _isLandscape = !_isLandscape);
_applyOrientation();
_showControls();
} }
@override @override
@@ -814,7 +832,20 @@ class _FullscreenVideoPageState extends State<_FullscreenVideoPage> {
top: 12, top: 12,
right: 12, right: 12,
child: SafeArea( child: SafeArea(
child: IconButton.filledTonal( child: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton.filledTonal(
tooltip: _isLandscape
? 'Портретная ориентация'
: 'Альбомная ориентация',
onPressed: _toggleOrientation,
icon: Icon(_isLandscape
? Icons.screen_lock_portrait_rounded
: Icons.screen_lock_landscape_rounded),
),
const SizedBox(width: 8),
IconButton.filledTonal(
tooltip: 'Close fullscreen', tooltip: 'Close fullscreen',
onPressed: () => Navigator.of( onPressed: () => Navigator.of(
context, context,
@@ -822,6 +853,8 @@ class _FullscreenVideoPageState extends State<_FullscreenVideoPage> {
).pop(_snapshot()), ).pop(_snapshot()),
icon: const Icon(Icons.close_rounded), icon: const Icon(Icons.close_rounded),
), ),
],
),
), ),
), ),
], ],
+1 -1
View File
@@ -1,7 +1,7 @@
name: gel_rule_app name: gel_rule_app
description: Local backend/core layer for a Flutter booru browser app. description: Local backend/core layer for a Flutter booru browser app.
publish_to: "none" publish_to: "none"
version: 2.3.4+44 version: 2.3.5+45
environment: environment:
sdk: ">=3.3.0 <4.0.0" sdk: ">=3.3.0 <4.0.0"