246 lines
7.7 KiB
Dart
246 lines
7.7 KiB
Dart
import 'package:aves/services/common/channel.dart';
|
|
import 'package:aves/services/common/services.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
abstract class WindowService {
|
|
Future<bool> isActivity();
|
|
|
|
Future<void> keepScreenOn(bool on);
|
|
|
|
Future<void> secureScreen(bool on);
|
|
|
|
Future<bool> isInMultiWindowMode();
|
|
|
|
Future<bool> isInPictureInPictureMode();
|
|
|
|
Future<bool> isRotationLocked();
|
|
|
|
Future<int> getOrientation();
|
|
|
|
Future<void> requestOrientation([Orientation? orientation]);
|
|
|
|
Future<bool> isCutoutAware();
|
|
|
|
Future<EdgeInsets> getCutoutInsets();
|
|
|
|
Future<bool> supportsWideGamut();
|
|
|
|
Future<bool> supportsHdr();
|
|
|
|
Future<void> setColorMode({required bool wideColorGamut, required bool hdr});
|
|
|
|
Future<bool> startGlobalDrag(String uri, String? label, Size shadowSize, Uint8List shadowBytes);
|
|
}
|
|
|
|
class PlatformWindowService implements WindowService {
|
|
static const _platform = AvesMethodChannel('deckers.thibault/aves/window');
|
|
|
|
bool? _isCutoutAware, _supportsHdr, _supportsWideGamut;
|
|
|
|
@override
|
|
Future<bool> isActivity() async {
|
|
try {
|
|
final result = await _platform.invokeMethod('isActivity');
|
|
if (result != null) return result as bool;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@override
|
|
Future<void> keepScreenOn(bool on) async {
|
|
try {
|
|
await _platform.invokeMethod('keepScreenOn', <String, dynamic>{
|
|
'on': on,
|
|
});
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> secureScreen(bool on) async {
|
|
try {
|
|
await _platform.invokeMethod('secureScreen', <String, dynamic>{
|
|
'on': on,
|
|
});
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<bool> isInMultiWindowMode() async {
|
|
try {
|
|
final result = await _platform.invokeMethod('isInMultiWindowMode');
|
|
if (result != null) return result as bool;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@override
|
|
Future<bool> isInPictureInPictureMode() async {
|
|
try {
|
|
final result = await _platform.invokeMethod('isInPictureInPictureMode');
|
|
if (result != null) return result as bool;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@override
|
|
Future<bool> isRotationLocked() async {
|
|
try {
|
|
final result = await _platform.invokeMethod('isRotationLocked');
|
|
if (result != null) return result as bool;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@override
|
|
Future<int> getOrientation() async {
|
|
try {
|
|
final result = await _platform.invokeMethod('getOrientation');
|
|
if (result != null) return result as int;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// cf https://developer.android.com/reference/android/R.attr#screenOrientation
|
|
// cf Android `ActivityInfo.ScreenOrientation`
|
|
static const screenOrientationUnspecified = -1; // SCREEN_ORIENTATION_UNSPECIFIED
|
|
static const screenOrientationLandscape = 0; // SCREEN_ORIENTATION_LANDSCAPE
|
|
static const screenOrientationPortrait = 1; // SCREEN_ORIENTATION_PORTRAIT
|
|
static const screenOrientationSensorLandscape = 6; // SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
|
static const screenOrientationSensorPortrait = 7; // SCREEN_ORIENTATION_SENSOR_PORTRAIT
|
|
static const screenOrientationReverseLandscape = 8; // SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
|
static const screenOrientationReversePortrait = 9; // SCREEN_ORIENTATION_REVERSE_PORTRAIT
|
|
static const screenOrientationUserLandscape = 11; // SCREEN_ORIENTATION_USER_LANDSCAPE
|
|
static const screenOrientationUserPortrait = 12; // SCREEN_ORIENTATION_USER_PORTRAIT
|
|
|
|
@override
|
|
Future<void> requestOrientation([Orientation? orientation]) async {
|
|
Future<void> apply(int orientationCode) async {
|
|
try {
|
|
await _platform.invokeMethod('requestOrientation', <String, dynamic>{
|
|
'orientation': orientationCode,
|
|
});
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
}
|
|
|
|
switch (orientation) {
|
|
case Orientation.landscape:
|
|
// first use the `sensor` variant to flip according to the sensor,
|
|
// then switch to a specific landscape orientation
|
|
// so that it no longer listens to the sensor
|
|
await apply(screenOrientationSensorLandscape);
|
|
switch (await getOrientation()) {
|
|
case 270:
|
|
await apply(screenOrientationReverseLandscape);
|
|
case 90:
|
|
default:
|
|
await apply(screenOrientationLandscape);
|
|
}
|
|
case Orientation.portrait:
|
|
await apply(screenOrientationUserPortrait);
|
|
default:
|
|
await apply(screenOrientationUnspecified);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<bool> isCutoutAware() async {
|
|
if (_isCutoutAware != null) return SynchronousFuture(_isCutoutAware!);
|
|
try {
|
|
final result = await _platform.invokeMethod('isCutoutAware');
|
|
_isCutoutAware = result as bool?;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return _isCutoutAware ?? false;
|
|
}
|
|
|
|
@override
|
|
Future<EdgeInsets> getCutoutInsets() async {
|
|
try {
|
|
final result = await _platform.invokeMethod('getCutoutInsets');
|
|
if (result != null) {
|
|
return EdgeInsets.only(
|
|
left: result['left']?.toDouble() ?? 0,
|
|
top: result['top']?.toDouble() ?? 0,
|
|
right: result['right']?.toDouble() ?? 0,
|
|
bottom: result['bottom']?.toDouble() ?? 0,
|
|
);
|
|
}
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return EdgeInsets.zero;
|
|
}
|
|
|
|
@override
|
|
Future<bool> supportsWideGamut() async {
|
|
if (_supportsWideGamut != null) return SynchronousFuture(_supportsWideGamut!);
|
|
try {
|
|
final result = await _platform.invokeMethod('supportsWideGamut');
|
|
_supportsWideGamut = result as bool?;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return _supportsWideGamut ?? false;
|
|
}
|
|
|
|
@override
|
|
Future<bool> supportsHdr() async {
|
|
if (_supportsHdr != null) return SynchronousFuture(_supportsHdr!);
|
|
try {
|
|
final result = await _platform.invokeMethod('supportsHdr');
|
|
_supportsHdr = result as bool?;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return _supportsHdr ?? false;
|
|
}
|
|
|
|
@override
|
|
Future<void> setColorMode({required bool wideColorGamut, required bool hdr}) async {
|
|
// TODO TLAD [hdr] enable when ready
|
|
// try {
|
|
// await _platform.invokeMethod('setColorMode', <String, dynamic>{
|
|
// 'wideColorGamut': wideColorGamut,
|
|
// 'hdr': hdr,
|
|
// });
|
|
// } on PlatformException catch (e, stack) {
|
|
// await reportService.recordError(e, stack);
|
|
// }
|
|
}
|
|
|
|
@override
|
|
Future<bool> startGlobalDrag(String uri, String? label, Size shadowSize, Uint8List shadowBytes) async {
|
|
try {
|
|
final result = await _platform.invokeMethod('startGlobalDrag', <String, dynamic>{
|
|
'uri': uri,
|
|
'label': label,
|
|
'shadowWidthDip': shadowSize.width,
|
|
'shadowHeightDip': shadowSize.height,
|
|
'shadowBytes': shadowBytes,
|
|
});
|
|
if (result != null) return result as bool;
|
|
} on PlatformException catch (e, stack) {
|
|
await reportService.recordError(e, stack);
|
|
}
|
|
return false;
|
|
}
|
|
}
|