mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[web] ScreenOrientation singleton (flutter/engine#45304)
One more piece moving out of `FlutterViewEmbedder`. `ScreenOrientation` is a singleton class that can be used to control the screen orientation of the browser. Part of https://github.com/flutter/flutter/issues/134443
This commit is contained in:
parent
3ef852f5de
commit
b470cd2ab1
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
|
||||
import '../engine.dart';
|
||||
@ -59,3 +61,76 @@ class EngineFlutterDisplay extends ui.Display {
|
||||
|
||||
double? _debugDevicePixelRatioOverride;
|
||||
}
|
||||
|
||||
/// Controls the screen orientation using the browser's screen orientation API.
|
||||
class ScreenOrientation {
|
||||
const ScreenOrientation();
|
||||
|
||||
static ScreenOrientation get instance => _instance;
|
||||
static const ScreenOrientation _instance = ScreenOrientation();
|
||||
|
||||
static const String lockTypeAny = 'any';
|
||||
static const String lockTypeNatural = 'natural';
|
||||
static const String lockTypeLandscape = 'landscape';
|
||||
static const String lockTypePortrait = 'portrait';
|
||||
static const String lockTypePortraitPrimary = 'portrait-primary';
|
||||
static const String lockTypePortraitSecondary = 'portrait-secondary';
|
||||
static const String lockTypeLandscapePrimary = 'landscape-primary';
|
||||
static const String lockTypeLandscapeSecondary = 'landscape-secondary';
|
||||
|
||||
/// Sets preferred screen orientation.
|
||||
///
|
||||
/// Specifies the set of orientations the application interface can be
|
||||
/// displayed in.
|
||||
///
|
||||
/// The [orientations] argument is a list of DeviceOrientation values.
|
||||
/// The empty list uses Screen unlock api and causes the application to
|
||||
/// defer to the operating system default.
|
||||
///
|
||||
/// See w3c screen api: https://www.w3.org/TR/screen-orientation/
|
||||
Future<bool> setPreferredOrientation(List<dynamic> orientations) async {
|
||||
final DomScreen? screen = domWindow.screen;
|
||||
if (screen != null) {
|
||||
final DomScreenOrientation? screenOrientation = screen.orientation;
|
||||
if (screenOrientation != null) {
|
||||
if (orientations.isEmpty) {
|
||||
screenOrientation.unlock();
|
||||
return true;
|
||||
} else {
|
||||
final String? lockType =
|
||||
_deviceOrientationToLockType(orientations.first as String?);
|
||||
if (lockType != null) {
|
||||
try {
|
||||
await screenOrientation.lock(lockType);
|
||||
return true;
|
||||
} catch (_) {
|
||||
// On Chrome desktop an error with 'not supported on this device
|
||||
// error' is fired.
|
||||
return Future<bool>.value(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// API is not supported on this browser return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Converts device orientation to w3c OrientationLockType enum.
|
||||
//
|
||||
// See also: https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock
|
||||
static String? _deviceOrientationToLockType(String? deviceOrientation) {
|
||||
switch (deviceOrientation) {
|
||||
case 'DeviceOrientation.portraitUp':
|
||||
return lockTypePortraitPrimary;
|
||||
case 'DeviceOrientation.portraitDown':
|
||||
return lockTypePortraitSecondary;
|
||||
case 'DeviceOrientation.landscapeLeft':
|
||||
return lockTypeLandscapePrimary;
|
||||
case 'DeviceOrientation.landscapeRight':
|
||||
return lockTypeLandscapeSecondary;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:ui/src/engine/safe_browser_api.dart';
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
|
||||
@ -288,78 +286,6 @@ class FlutterViewEmbedder {
|
||||
}
|
||||
}
|
||||
|
||||
static const String orientationLockTypeAny = 'any';
|
||||
static const String orientationLockTypeNatural = 'natural';
|
||||
static const String orientationLockTypeLandscape = 'landscape';
|
||||
static const String orientationLockTypePortrait = 'portrait';
|
||||
static const String orientationLockTypePortraitPrimary = 'portrait-primary';
|
||||
static const String orientationLockTypePortraitSecondary =
|
||||
'portrait-secondary';
|
||||
static const String orientationLockTypeLandscapePrimary = 'landscape-primary';
|
||||
static const String orientationLockTypeLandscapeSecondary =
|
||||
'landscape-secondary';
|
||||
|
||||
/// Sets preferred screen orientation.
|
||||
///
|
||||
/// Specifies the set of orientations the application interface can be
|
||||
/// displayed in.
|
||||
///
|
||||
/// The [orientations] argument is a list of DeviceOrientation values.
|
||||
/// The empty list uses Screen unlock api and causes the application to
|
||||
/// defer to the operating system default.
|
||||
///
|
||||
/// See w3c screen api: https://www.w3.org/TR/screen-orientation/
|
||||
Future<bool> setPreferredOrientation(List<dynamic> orientations) {
|
||||
final DomScreen? screen = domWindow.screen;
|
||||
if (screen != null) {
|
||||
final DomScreenOrientation? screenOrientation = screen.orientation;
|
||||
if (screenOrientation != null) {
|
||||
if (orientations.isEmpty) {
|
||||
screenOrientation.unlock();
|
||||
return Future<bool>.value(true);
|
||||
} else {
|
||||
final String? lockType =
|
||||
_deviceOrientationToLockType(orientations.first as String?);
|
||||
if (lockType != null) {
|
||||
final Completer<bool> completer = Completer<bool>();
|
||||
try {
|
||||
screenOrientation.lock(lockType).then((dynamic _) {
|
||||
completer.complete(true);
|
||||
}).catchError((dynamic error) {
|
||||
// On Chrome desktop an error with 'not supported on this device
|
||||
// error' is fired.
|
||||
completer.complete(false);
|
||||
});
|
||||
} catch (_) {
|
||||
return Future<bool>.value(false);
|
||||
}
|
||||
return completer.future;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// API is not supported on this browser return false.
|
||||
return Future<bool>.value(false);
|
||||
}
|
||||
|
||||
// Converts device orientation to w3c OrientationLockType enum.
|
||||
//
|
||||
// See also: https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock
|
||||
static String? _deviceOrientationToLockType(String? deviceOrientation) {
|
||||
switch (deviceOrientation) {
|
||||
case 'DeviceOrientation.portraitUp':
|
||||
return orientationLockTypePortraitPrimary;
|
||||
case 'DeviceOrientation.portraitDown':
|
||||
return orientationLockTypePortraitSecondary;
|
||||
case 'DeviceOrientation.landscapeLeft':
|
||||
return orientationLockTypeLandscapePrimary;
|
||||
case 'DeviceOrientation.landscapeRight':
|
||||
return orientationLockTypeLandscapeSecondary;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Add an element as a global resource to be referenced by CSS.
|
||||
///
|
||||
/// This call create a global resource host element on demand and either
|
||||
|
||||
@ -532,7 +532,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
|
||||
return;
|
||||
case 'SystemChrome.setPreferredOrientations':
|
||||
final List<dynamic> arguments = decoded.arguments as List<dynamic>;
|
||||
flutterViewEmbedder.setPreferredOrientation(arguments).then((bool success) {
|
||||
ScreenOrientation.instance.setPreferredOrientation(arguments).then((bool success) {
|
||||
replyToPlatformMessage(
|
||||
callback, codec.encodeSuccessEnvelope(success));
|
||||
});
|
||||
|
||||
@ -358,25 +358,25 @@ Future<void> testMain() async {
|
||||
unlockCount = 0;
|
||||
|
||||
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.portraitUp']), isTrue);
|
||||
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypePortraitPrimary]);
|
||||
expect(lockCalls, <String>[ScreenOrientation.lockTypePortraitPrimary]);
|
||||
expect(unlockCount, 0);
|
||||
lockCalls.clear();
|
||||
unlockCount = 0;
|
||||
|
||||
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.portraitDown']), isTrue);
|
||||
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypePortraitSecondary]);
|
||||
expect(lockCalls, <String>[ScreenOrientation.lockTypePortraitSecondary]);
|
||||
expect(unlockCount, 0);
|
||||
lockCalls.clear();
|
||||
unlockCount = 0;
|
||||
|
||||
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.landscapeLeft']), isTrue);
|
||||
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypeLandscapePrimary]);
|
||||
expect(lockCalls, <String>[ScreenOrientation.lockTypeLandscapePrimary]);
|
||||
expect(unlockCount, 0);
|
||||
lockCalls.clear();
|
||||
unlockCount = 0;
|
||||
|
||||
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.landscapeRight']), isTrue);
|
||||
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypeLandscapeSecondary]);
|
||||
expect(lockCalls, <String>[ScreenOrientation.lockTypeLandscapeSecondary]);
|
||||
expect(unlockCount, 0);
|
||||
lockCalls.clear();
|
||||
unlockCount = 0;
|
||||
@ -389,7 +389,7 @@ Future<void> testMain() async {
|
||||
|
||||
simulateError = true;
|
||||
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.portraitDown']), isFalse);
|
||||
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypePortraitSecondary]);
|
||||
expect(lockCalls, <String>[ScreenOrientation.lockTypePortraitSecondary]);
|
||||
expect(unlockCount, 0);
|
||||
|
||||
js_util.setProperty(domWindow, 'screen', original);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user