Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7a5ed32

Browse files
mdebbarharryterkelsen
authored andcommitted
[web] ScreenOrientation singleton (#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 flutter/flutter#134443
1 parent 01e7ba1 commit 7a5ed32

File tree

4 files changed

+81
-80
lines changed

4 files changed

+81
-80
lines changed

lib/web_ui/lib/src/engine/display.dart

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:async';
6+
57
import 'package:ui/ui.dart' as ui;
68

79
import '../engine.dart';
@@ -59,3 +61,76 @@ class EngineFlutterDisplay extends ui.Display {
5961

6062
double? _debugDevicePixelRatioOverride;
6163
}
64+
65+
/// Controls the screen orientation using the browser's screen orientation API.
66+
class ScreenOrientation {
67+
const ScreenOrientation();
68+
69+
static ScreenOrientation get instance => _instance;
70+
static const ScreenOrientation _instance = ScreenOrientation();
71+
72+
static const String lockTypeAny = 'any';
73+
static const String lockTypeNatural = 'natural';
74+
static const String lockTypeLandscape = 'landscape';
75+
static const String lockTypePortrait = 'portrait';
76+
static const String lockTypePortraitPrimary = 'portrait-primary';
77+
static const String lockTypePortraitSecondary = 'portrait-secondary';
78+
static const String lockTypeLandscapePrimary = 'landscape-primary';
79+
static const String lockTypeLandscapeSecondary = 'landscape-secondary';
80+
81+
/// Sets preferred screen orientation.
82+
///
83+
/// Specifies the set of orientations the application interface can be
84+
/// displayed in.
85+
///
86+
/// The [orientations] argument is a list of DeviceOrientation values.
87+
/// The empty list uses Screen unlock api and causes the application to
88+
/// defer to the operating system default.
89+
///
90+
/// See w3c screen api: https://www.w3.org/TR/screen-orientation/
91+
Future<bool> setPreferredOrientation(List<dynamic> orientations) async {
92+
final DomScreen? screen = domWindow.screen;
93+
if (screen != null) {
94+
final DomScreenOrientation? screenOrientation = screen.orientation;
95+
if (screenOrientation != null) {
96+
if (orientations.isEmpty) {
97+
screenOrientation.unlock();
98+
return true;
99+
} else {
100+
final String? lockType =
101+
_deviceOrientationToLockType(orientations.first as String?);
102+
if (lockType != null) {
103+
try {
104+
await screenOrientation.lock(lockType);
105+
return true;
106+
} catch (_) {
107+
// On Chrome desktop an error with 'not supported on this device
108+
// error' is fired.
109+
return Future<bool>.value(false);
110+
}
111+
}
112+
}
113+
}
114+
}
115+
// API is not supported on this browser return false.
116+
return false;
117+
}
118+
119+
// Converts device orientation to w3c OrientationLockType enum.
120+
//
121+
// See also: https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock
122+
static String? _deviceOrientationToLockType(String? deviceOrientation) {
123+
switch (deviceOrientation) {
124+
case 'DeviceOrientation.portraitUp':
125+
return lockTypePortraitPrimary;
126+
case 'DeviceOrientation.portraitDown':
127+
return lockTypePortraitSecondary;
128+
case 'DeviceOrientation.landscapeLeft':
129+
return lockTypeLandscapePrimary;
130+
case 'DeviceOrientation.landscapeRight':
131+
return lockTypeLandscapeSecondary;
132+
default:
133+
return null;
134+
}
135+
}
136+
}

lib/web_ui/lib/src/engine/embedder.dart

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
import 'dart:async';
6-
75
import 'package:ui/src/engine/safe_browser_api.dart';
86
import 'package:ui/ui.dart' as ui;
97

@@ -288,78 +286,6 @@ class FlutterViewEmbedder {
288286
}
289287
}
290288

291-
static const String orientationLockTypeAny = 'any';
292-
static const String orientationLockTypeNatural = 'natural';
293-
static const String orientationLockTypeLandscape = 'landscape';
294-
static const String orientationLockTypePortrait = 'portrait';
295-
static const String orientationLockTypePortraitPrimary = 'portrait-primary';
296-
static const String orientationLockTypePortraitSecondary =
297-
'portrait-secondary';
298-
static const String orientationLockTypeLandscapePrimary = 'landscape-primary';
299-
static const String orientationLockTypeLandscapeSecondary =
300-
'landscape-secondary';
301-
302-
/// Sets preferred screen orientation.
303-
///
304-
/// Specifies the set of orientations the application interface can be
305-
/// displayed in.
306-
///
307-
/// The [orientations] argument is a list of DeviceOrientation values.
308-
/// The empty list uses Screen unlock api and causes the application to
309-
/// defer to the operating system default.
310-
///
311-
/// See w3c screen api: https://www.w3.org/TR/screen-orientation/
312-
Future<bool> setPreferredOrientation(List<dynamic> orientations) {
313-
final DomScreen? screen = domWindow.screen;
314-
if (screen != null) {
315-
final DomScreenOrientation? screenOrientation = screen.orientation;
316-
if (screenOrientation != null) {
317-
if (orientations.isEmpty) {
318-
screenOrientation.unlock();
319-
return Future<bool>.value(true);
320-
} else {
321-
final String? lockType =
322-
_deviceOrientationToLockType(orientations.first as String?);
323-
if (lockType != null) {
324-
final Completer<bool> completer = Completer<bool>();
325-
try {
326-
screenOrientation.lock(lockType).then((dynamic _) {
327-
completer.complete(true);
328-
}).catchError((dynamic error) {
329-
// On Chrome desktop an error with 'not supported on this device
330-
// error' is fired.
331-
completer.complete(false);
332-
});
333-
} catch (_) {
334-
return Future<bool>.value(false);
335-
}
336-
return completer.future;
337-
}
338-
}
339-
}
340-
}
341-
// API is not supported on this browser return false.
342-
return Future<bool>.value(false);
343-
}
344-
345-
// Converts device orientation to w3c OrientationLockType enum.
346-
//
347-
// See also: https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock
348-
static String? _deviceOrientationToLockType(String? deviceOrientation) {
349-
switch (deviceOrientation) {
350-
case 'DeviceOrientation.portraitUp':
351-
return orientationLockTypePortraitPrimary;
352-
case 'DeviceOrientation.portraitDown':
353-
return orientationLockTypePortraitSecondary;
354-
case 'DeviceOrientation.landscapeLeft':
355-
return orientationLockTypeLandscapePrimary;
356-
case 'DeviceOrientation.landscapeRight':
357-
return orientationLockTypeLandscapeSecondary;
358-
default:
359-
return null;
360-
}
361-
}
362-
363289
/// Add an element as a global resource to be referenced by CSS.
364290
///
365291
/// This call create a global resource host element on demand and either

lib/web_ui/lib/src/engine/platform_dispatcher.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
532532
return;
533533
case 'SystemChrome.setPreferredOrientations':
534534
final List<dynamic> arguments = decoded.arguments as List<dynamic>;
535-
flutterViewEmbedder.setPreferredOrientation(arguments).then((bool success) {
535+
ScreenOrientation.instance.setPreferredOrientation(arguments).then((bool success) {
536536
replyToPlatformMessage(
537537
callback, codec.encodeSuccessEnvelope(success));
538538
});

lib/web_ui/test/engine/window_test.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -358,25 +358,25 @@ Future<void> testMain() async {
358358
unlockCount = 0;
359359

360360
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.portraitUp']), isTrue);
361-
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypePortraitPrimary]);
361+
expect(lockCalls, <String>[ScreenOrientation.lockTypePortraitPrimary]);
362362
expect(unlockCount, 0);
363363
lockCalls.clear();
364364
unlockCount = 0;
365365

366366
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.portraitDown']), isTrue);
367-
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypePortraitSecondary]);
367+
expect(lockCalls, <String>[ScreenOrientation.lockTypePortraitSecondary]);
368368
expect(unlockCount, 0);
369369
lockCalls.clear();
370370
unlockCount = 0;
371371

372372
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.landscapeLeft']), isTrue);
373-
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypeLandscapePrimary]);
373+
expect(lockCalls, <String>[ScreenOrientation.lockTypeLandscapePrimary]);
374374
expect(unlockCount, 0);
375375
lockCalls.clear();
376376
unlockCount = 0;
377377

378378
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.landscapeRight']), isTrue);
379-
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypeLandscapeSecondary]);
379+
expect(lockCalls, <String>[ScreenOrientation.lockTypeLandscapeSecondary]);
380380
expect(unlockCount, 0);
381381
lockCalls.clear();
382382
unlockCount = 0;
@@ -389,7 +389,7 @@ Future<void> testMain() async {
389389

390390
simulateError = true;
391391
expect(await sendSetPreferredOrientations(<dynamic>['DeviceOrientation.portraitDown']), isFalse);
392-
expect(lockCalls, <String>[FlutterViewEmbedder.orientationLockTypePortraitSecondary]);
392+
expect(lockCalls, <String>[ScreenOrientation.lockTypePortraitSecondary]);
393393
expect(unlockCount, 0);
394394

395395
js_util.setProperty(domWindow, 'screen', original);

0 commit comments

Comments
 (0)