|
@@ -30,8 +30,7 @@ import '../widgets/camera_progress_button.dart';
|
|
|
const Color _lockedColor = Colors.orangeAccent;
|
|
|
const Duration _kDuration = Duration(milliseconds: 300);
|
|
|
|
|
|
-class CameraPickerState extends State<CameraPicker>
|
|
|
- with WidgetsBindingObserver {
|
|
|
+class CameraPickerState extends State<CameraPicker> with WidgetsBindingObserver {
|
|
|
/// The controller for the current camera.
|
|
|
/// 当前相机实例的控制器
|
|
|
CameraController get controller => innerController!;
|
|
@@ -72,8 +71,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
/// Current exposure offset.
|
|
|
/// 当前曝光值
|
|
|
final ValueNotifier<double> currentExposureOffset = ValueNotifier<double>(0);
|
|
|
- final ValueNotifier<double> currentExposureSliderOffset =
|
|
|
- ValueNotifier<double>(0);
|
|
|
+ final ValueNotifier<double> currentExposureSliderOffset = ValueNotifier<double>(0);
|
|
|
double maxAvailableExposureOffset = 0;
|
|
|
double minAvailableExposureOffset = 0;
|
|
|
double exposureStep = 0;
|
|
@@ -141,8 +139,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
/// not valid, it is removed from the list.
|
|
|
/// 使用每个相机的所有闪光灯模式进行初始化。
|
|
|
/// 如果闪光灯模式无效,则将其从列表中删除。
|
|
|
- final Map<CameraDescription, List<FlashMode>> validFlashModes =
|
|
|
- <CameraDescription, List<FlashMode>>{};
|
|
|
+ final Map<CameraDescription, List<FlashMode>> validFlashModes = <CameraDescription, List<FlashMode>>{};
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
////////////////////////////// Global Getters //////////////////////////////
|
|
@@ -159,13 +156,11 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
|
|
|
/// Whether the picker only enables video recording.
|
|
|
/// 选择器是否只可以录像
|
|
|
- bool get onlyEnableRecording =>
|
|
|
- enableRecording && pickerConfig.onlyEnableRecording;
|
|
|
+ bool get onlyEnableRecording => enableRecording && pickerConfig.onlyEnableRecording;
|
|
|
|
|
|
/// Whether allow the record can start with single tap.
|
|
|
/// 选择器是否可以单击录像
|
|
|
- bool get enableTapRecording =>
|
|
|
- onlyEnableRecording && pickerConfig.enableTapRecording;
|
|
|
+ bool get enableTapRecording => onlyEnableRecording && pickerConfig.enableTapRecording;
|
|
|
|
|
|
/// No audio integration required when it's only for camera.
|
|
|
/// 在仅允许拍照时不需要启用音频
|
|
@@ -173,16 +168,13 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
|
|
|
/// Whether the picker needs to prepare for video recording on iOS.
|
|
|
/// 是否需要为 iOS 的录制视频执行准备操作
|
|
|
- bool get shouldPrepareForVideoRecording =>
|
|
|
- enableRecording && enableAudio && Platform.isIOS;
|
|
|
+ bool get shouldPrepareForVideoRecording => enableRecording && enableAudio && Platform.isIOS;
|
|
|
|
|
|
- bool get enablePullToZoomInRecord =>
|
|
|
- enableRecording && pickerConfig.enablePullToZoomInRecord;
|
|
|
+ bool get enablePullToZoomInRecord => enableRecording && pickerConfig.enablePullToZoomInRecord;
|
|
|
|
|
|
/// Whether the recording restricted to a specific duration.
|
|
|
/// 录像是否有限制的时长
|
|
|
- bool get isRecordingRestricted =>
|
|
|
- pickerConfig.maximumRecordingDuration != null;
|
|
|
+ bool get isRecordingRestricted => pickerConfig.maximumRecordingDuration != null;
|
|
|
|
|
|
/// The minimum recording duration limit.
|
|
|
/// 录制视频的最短时长限制。
|
|
@@ -190,9 +182,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
/// If the maximum duration is less than the minimum, use the maximum instead.
|
|
|
/// 如果最大时长大于最小时长,则使用最大时长。
|
|
|
Duration get minimumRecordingDuration {
|
|
|
- if (pickerConfig.maximumRecordingDuration != null &&
|
|
|
- pickerConfig.maximumRecordingDuration! <
|
|
|
- pickerConfig.minimumRecordingDuration) {
|
|
|
+ if (pickerConfig.maximumRecordingDuration != null && pickerConfig.maximumRecordingDuration! < pickerConfig.minimumRecordingDuration) {
|
|
|
return pickerConfig.maximumRecordingDuration!;
|
|
|
}
|
|
|
return pickerConfig.minimumRecordingDuration;
|
|
@@ -202,9 +192,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
bool get isRecordingVideo => innerController?.value.isRecordingVideo ?? false;
|
|
|
|
|
|
/// Whether the capture button is displaying.
|
|
|
- bool get shouldCaptureButtonDisplay =>
|
|
|
- (isCaptureButtonTapDown || MediaQuery.accessibleNavigationOf(context)) &&
|
|
|
- isRecordingVideo;
|
|
|
+ bool get shouldCaptureButtonDisplay => (isCaptureButtonTapDown || MediaQuery.accessibleNavigationOf(context)) && isRecordingVideo;
|
|
|
|
|
|
/// Whether the camera preview should be rotated.
|
|
|
bool get isCameraRotated => pickerConfig.cameraQuarterTurns % 4 != 0;
|
|
@@ -217,8 +205,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
|
|
|
/// If there's no theme provided from the user, use [CameraPicker.themeData] .
|
|
|
/// 如果用户未提供主题,通过 [CameraPicker.themeData] 创建。
|
|
|
- late final ThemeData theme =
|
|
|
- pickerConfig.theme ?? CameraPicker.themeData(defaultThemeColorWeChat);
|
|
|
+ late final ThemeData theme = pickerConfig.theme ?? CameraPicker.themeData(defaultThemeColorWeChat);
|
|
|
|
|
|
CameraPickerTextDelegate get textDelegate => Singleton.textDelegate;
|
|
|
|
|
@@ -260,6 +247,12 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
@override
|
|
|
void initState() {
|
|
|
super.initState();
|
|
|
+
|
|
|
+ SystemChrome.setPreferredOrientations([
|
|
|
+ DeviceOrientation.portraitUp,
|
|
|
+ // DeviceOrientation.landscapeLeft,
|
|
|
+ // DeviceOrientation.landscapeRight,
|
|
|
+ ]);
|
|
|
ambiguate(WidgetsBinding.instance)?.addObserver(this);
|
|
|
Singleton.textDelegate = widget.pickerConfig.textDelegate ?? cameraPickerTextDelegateFromLocale(widget.locale);
|
|
|
initCameras();
|
|
@@ -313,12 +306,11 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
return 1;
|
|
|
}
|
|
|
final int turns = cameraQuarterTurns;
|
|
|
- final String orientation = controller.value.deviceOrientation.toString();
|
|
|
+ final String orientation = controller.value.lockedCaptureOrientation.toString();
|
|
|
// Fetch the biggest size from the constraints.
|
|
|
Size size = constraints.biggest;
|
|
|
// Flip the size when the preview needs to turn with an odd count of quarters.
|
|
|
- if ((turns.isOdd && orientation.contains('portrait')) ||
|
|
|
- (turns.isEven && orientation.contains('landscape'))) {
|
|
|
+ if ((turns.isOdd && orientation.contains('portrait')) || (turns.isEven && orientation.contains('landscape'))) {
|
|
|
size = size.flipped;
|
|
|
}
|
|
|
// Calculate scale depending on the size and camera ratios.
|
|
@@ -416,8 +408,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
|
|
|
initFlashModesForCameras();
|
|
|
final int preferredIndex = cameras.indexWhere(
|
|
|
- (CameraDescription e) =>
|
|
|
- e.lensDirection == pickerConfig.preferredLensDirection,
|
|
|
+ (CameraDescription e) => e.lensDirection == pickerConfig.preferredLensDirection,
|
|
|
);
|
|
|
final int index;
|
|
|
if (preferredIndex != -1 && c == null) {
|
|
@@ -505,8 +496,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
if (camera.lensDirection != CameraLensDirection.front)
|
|
|
Future(() async {
|
|
|
final flashMode = pickerConfig.preferredFlashMode;
|
|
|
- if (flashMode != FlashMode.auto &&
|
|
|
- validFlashModes[camera]?.contains(flashMode) != false) {
|
|
|
+ if (flashMode != FlashMode.auto && validFlashModes[camera]?.contains(flashMode) != false) {
|
|
|
return wrapControllerMethod<void>(
|
|
|
'setFlashMode',
|
|
|
() => newController.setFlashMode(flashMode),
|
|
@@ -596,11 +586,12 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
newOrientation = null;
|
|
|
}
|
|
|
// Throttle.
|
|
|
- if (newOrientation != null && lockedCaptureOrientation != newOrientation) {
|
|
|
- lockedCaptureOrientation = newOrientation;
|
|
|
- realDebugPrint('Locking new capture orientation: $newOrientation');
|
|
|
- controller.lockCaptureOrientation(newOrientation);
|
|
|
- }
|
|
|
+ // if (newOrientation != null && lockedCaptureOrientation != newOrientation) {
|
|
|
+ // lockedCaptureOrientation = newOrientation;
|
|
|
+ // realDebugPrint('Locking new capture orientation: $newOrientation');
|
|
|
+ // controller.lockCaptureOrientation(newOrientation);
|
|
|
+ // }
|
|
|
+ controller.lockCaptureOrientation(lockedCaptureOrientation);
|
|
|
}
|
|
|
|
|
|
/// Initializes the flash modes in [validFlashModes] for each
|
|
@@ -782,8 +773,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
if (enableScaledPreview) {
|
|
|
// Ignore point update when the new point is less than 8% and higher than
|
|
|
// 92% of the screen's height.
|
|
|
- if (position.dy < constraints.maxHeight / 12 ||
|
|
|
- position.dy > constraints.maxHeight / 12 * 11) {
|
|
|
+ if (position.dy < constraints.maxHeight / 12 || position.dy > constraints.maxHeight / 12 * 11) {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -814,10 +804,8 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
1 / constraints.maxHeight,
|
|
|
);
|
|
|
await Future.wait(<Future<void>>[
|
|
|
- if (controller.value.exposurePointSupported)
|
|
|
- controller.setExposurePoint(newPoint),
|
|
|
- if (controller.value.focusPointSupported)
|
|
|
- controller.setFocusPoint(newPoint),
|
|
|
+ if (controller.value.exposurePointSupported) controller.setExposurePoint(newPoint),
|
|
|
+ if (controller.value.focusPointSupported) controller.setFocusPoint(newPoint),
|
|
|
]);
|
|
|
} catch (e, s) {
|
|
|
handleErrorWithHandler(e, s, pickerConfig.onError);
|
|
@@ -840,9 +828,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
}
|
|
|
value = roundedOffset;
|
|
|
}
|
|
|
- if (value == currentExposureOffset.value ||
|
|
|
- value < minAvailableExposureOffset ||
|
|
|
- value > maxAvailableExposureOffset) {
|
|
|
+ if (value == currentExposureOffset.value || value < minAvailableExposureOffset || value > maxAvailableExposureOffset) {
|
|
|
return;
|
|
|
}
|
|
|
final previousOffsetValue = currentExposureOffset.value;
|
|
@@ -1154,9 +1140,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
}
|
|
|
|
|
|
PointerMoveEventListener? onPointerMove(BoxConstraints c) {
|
|
|
- if (innerController != null &&
|
|
|
- enablePullToZoomInRecord &&
|
|
|
- controller.value.isRecordingVideo) {
|
|
|
+ if (innerController != null && enablePullToZoomInRecord && controller.value.isRecordingVideo) {
|
|
|
return (PointerMoveEvent e) => onShootingButtonMove(e, c);
|
|
|
}
|
|
|
return null;
|
|
@@ -1255,7 +1239,8 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
child: flashModeSwitch,
|
|
|
);
|
|
|
}
|
|
|
- final isPortrait = v.deviceOrientation.toString().contains('portrait');
|
|
|
+ //todo 改为 lockedCaptureOrientation 替换 deviceOrientation 判断
|
|
|
+ final isPortrait = v.lockedCaptureOrientation.toString().contains('portrait');
|
|
|
return Padding(
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
|
child: Flex(
|
|
@@ -1282,9 +1267,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
onPressed: () => switchCameras(),
|
|
|
icon: Icon(
|
|
|
switch (defaultTargetPlatform) {
|
|
|
- TargetPlatform.iOS ||
|
|
|
- TargetPlatform.macOS =>
|
|
|
- Icons.flip_camera_ios_outlined,
|
|
|
+ TargetPlatform.iOS || TargetPlatform.macOS => Icons.flip_camera_ios_outlined,
|
|
|
_ => Icons.flip_camera_android_outlined,
|
|
|
},
|
|
|
size: 24,
|
|
@@ -1348,7 +1331,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
}) {
|
|
|
const fallbackSize = 150.0;
|
|
|
final previewSize = controller?.value.previewSize;
|
|
|
- final orientation = controller?.value.deviceOrientation ??
|
|
|
+ final orientation = controller?.value.lockedCaptureOrientation ??
|
|
|
MediaQuery.orientationOf(context);
|
|
|
final isPortrait = orientation.toString().contains('portrait');
|
|
|
double effectiveSize;
|
|
@@ -1672,13 +1655,10 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
duration: _kDuration,
|
|
|
opacity: isFadeOut ? .5 : 1,
|
|
|
child: Row(
|
|
|
- textDirection: shouldReverseLayout
|
|
|
- ? TextDirection.rtl
|
|
|
- : TextDirection.ltr,
|
|
|
+ textDirection: shouldReverseLayout ? TextDirection.rtl : TextDirection.ltr,
|
|
|
children: <Widget>[
|
|
|
child!,
|
|
|
- if (pickerConfig.enableExposureControlOnPoint)
|
|
|
- const SizedBox(width: 2),
|
|
|
+ if (pickerConfig.enableExposureControlOnPoint) const SizedBox(width: 2),
|
|
|
if (pickerConfig.enableExposureControlOnPoint)
|
|
|
SizedBox.fromSize(
|
|
|
size: Size(exposureControlWidth, lineHeight),
|
|
@@ -1695,9 +1675,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
child: CameraFocusPoint(
|
|
|
key: ValueKey<Offset>(point),
|
|
|
size: pointWidth,
|
|
|
- color: cameraValue.exposureMode == ExposureMode.locked
|
|
|
- ? _lockedColor
|
|
|
- : theme.iconTheme.color!,
|
|
|
+ color: cameraValue.exposureMode == ExposureMode.locked ? _lockedColor : theme.iconTheme.color!,
|
|
|
),
|
|
|
),
|
|
|
),
|
|
@@ -1770,6 +1748,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
preview = ValueListenableBuilder<CameraValue>(
|
|
|
valueListenable: controller,
|
|
|
builder: (_, CameraValue value, Widget? child) {
|
|
|
+ print("buildCameraPreview - ValueListenableBuilder - rebuild - lockedOrientation:${value.lockedCaptureOrientation} deviceOrientation:${value.deviceOrientation}");
|
|
|
final lockedOrientation = value.lockedCaptureOrientation;
|
|
|
int? quarterTurns = lockedOrientation?.index;
|
|
|
if (quarterTurns == null) {
|
|
@@ -1777,11 +1756,11 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
}
|
|
|
if (value.deviceOrientation == DeviceOrientation.landscapeLeft) {
|
|
|
quarterTurns--;
|
|
|
- } else if (value.deviceOrientation ==
|
|
|
- DeviceOrientation.landscapeRight) {
|
|
|
+ } else if (value.deviceOrientation == DeviceOrientation.landscapeRight) {
|
|
|
quarterTurns++;
|
|
|
}
|
|
|
- return RotatedBox(quarterTurns: quarterTurns, child: child);
|
|
|
+ //todo 强制不旋转
|
|
|
+ return RotatedBox(quarterTurns: 0, child: child);
|
|
|
},
|
|
|
child: preview,
|
|
|
);
|
|
@@ -1791,8 +1770,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
onPointerUp: (_) => pointers--,
|
|
|
child: GestureDetector(
|
|
|
onScaleStart: pickerConfig.enablePinchToZoom ? handleScaleStart : null,
|
|
|
- onScaleUpdate:
|
|
|
- pickerConfig.enablePinchToZoom ? handleScaleUpdate : null,
|
|
|
+ onScaleUpdate: pickerConfig.enablePinchToZoom ? handleScaleUpdate : null,
|
|
|
// Enabled cameras switching by default if we have multiple cameras.
|
|
|
onDoubleTap: cameras.length > 1 ? switchCameras : null,
|
|
|
child: preview,
|
|
@@ -1800,8 +1778,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
);
|
|
|
|
|
|
// Make a transformed widget if it's defined.
|
|
|
- final Widget? transformedWidget =
|
|
|
- pickerConfig.previewTransformBuilder?.call(
|
|
|
+ final Widget? transformedWidget = pickerConfig.previewTransformBuilder?.call(
|
|
|
context,
|
|
|
controller,
|
|
|
preview,
|
|
@@ -1810,8 +1787,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
preview = Stack(
|
|
|
children: <Widget>[
|
|
|
preview,
|
|
|
- if (pickerConfig.enableSetExposure)
|
|
|
- buildExposureDetector(context, constraints),
|
|
|
+ if (pickerConfig.enableSetExposure) buildExposureDetector(context, constraints),
|
|
|
buildFocusingPoint(
|
|
|
cameraValue: cameraValue,
|
|
|
constraints: constraints,
|
|
@@ -1856,6 +1832,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
valueListenable: controller,
|
|
|
builder: (_, CameraValue value, Widget? w) {
|
|
|
if (isInitialized?.call() ?? value.isInitialized) {
|
|
|
+ print("buildInitializeWrapper - ValueListenableBuilder - rebuild - lockedOrientation:${value.lockedCaptureOrientation} deviceOrientation:${value.deviceOrientation}");
|
|
|
return builder(value, w);
|
|
|
}
|
|
|
return const SizedBox.shrink();
|
|
@@ -1875,12 +1852,8 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
bottom: false,
|
|
|
child: Flex(
|
|
|
direction: isPortrait ? Axis.vertical : Axis.horizontal,
|
|
|
- textDirection: orientation == DeviceOrientation.landscapeRight
|
|
|
- ? TextDirection.rtl
|
|
|
- : TextDirection.ltr,
|
|
|
- verticalDirection: orientation == DeviceOrientation.portraitDown
|
|
|
- ? VerticalDirection.up
|
|
|
- : VerticalDirection.down,
|
|
|
+ textDirection: orientation == DeviceOrientation.landscapeRight ? TextDirection.rtl : TextDirection.ltr,
|
|
|
+ verticalDirection: orientation == DeviceOrientation.portraitDown ? VerticalDirection.up : VerticalDirection.down,
|
|
|
children: <Widget>[
|
|
|
Semantics(
|
|
|
sortKey: const OrdinalSortKey(0),
|
|
@@ -1902,13 +1875,14 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ //todo 改为 lockedCaptureOrientation 替换 deviceOrientation 判断
|
|
|
Widget buildBody(BuildContext context) {
|
|
|
return LayoutBuilder(
|
|
|
builder: (BuildContext context, BoxConstraints constraints) {
|
|
|
Widget previewWidget = ExcludeSemantics(
|
|
|
child: buildInitializeWrapper(
|
|
|
builder: (CameraValue v, Widget? w) {
|
|
|
- //为什么相机旋转了,这了会触发回调,此时v.deviceOrientation变为left横屏了
|
|
|
+ //为什么相机旋转了,这了会触发回调,此时v.deviceOrientation变为left横屏了
|
|
|
if (enableScaledPreview) {
|
|
|
return buildCameraPreview(
|
|
|
context: context,
|
|
@@ -1922,10 +1896,10 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
DeviceOrientation.portraitDown: Alignment.bottomCenter,
|
|
|
DeviceOrientation.landscapeLeft: Alignment.centerLeft,
|
|
|
DeviceOrientation.landscapeRight: Alignment.centerRight,
|
|
|
- }[v.deviceOrientation]!,
|
|
|
+ }[v.lockedCaptureOrientation]!,
|
|
|
child: AspectRatio(
|
|
|
aspectRatio:
|
|
|
- v.deviceOrientation.toString().contains('portrait')
|
|
|
+ v.lockedCaptureOrientation.toString().contains('portrait')
|
|
|
? 1 / v.aspectRatio
|
|
|
: v.aspectRatio,
|
|
|
child: LayoutBuilder(
|
|
@@ -1973,8 +1947,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
children: <Widget>[
|
|
|
previewWidget,
|
|
|
if (enableScaledPreview) ...<Widget>[
|
|
|
- if (pickerConfig.enableSetExposure)
|
|
|
- buildExposureDetector(context, constraints),
|
|
|
+ if (pickerConfig.enableSetExposure) buildExposureDetector(context, constraints),
|
|
|
buildInitializeWrapper(
|
|
|
builder: (CameraValue v, _) => buildFocusingPoint(
|
|
|
cameraValue: v,
|
|
@@ -1983,8 +1956,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
),
|
|
|
if (pickerConfig.foregroundBuilder != null)
|
|
|
Positioned.fill(
|
|
|
- child:
|
|
|
- pickerConfig.foregroundBuilder!(context, innerController),
|
|
|
+ child: pickerConfig.foregroundBuilder!(context, innerController),
|
|
|
),
|
|
|
],
|
|
|
if (innerController == null)
|
|
@@ -1994,7 +1966,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
builder: (CameraValue v, _) => buildForegroundBody(
|
|
|
context,
|
|
|
constraints,
|
|
|
- v.deviceOrientation,
|
|
|
+ v.lockedCaptureOrientation,
|
|
|
),
|
|
|
),
|
|
|
],
|
|
@@ -2012,9 +1984,7 @@ class CameraPickerState extends State<CameraPicker>
|
|
|
quarterTurns: pickerConfig.cameraQuarterTurns,
|
|
|
child: MediaQuery(
|
|
|
data: mq.copyWith(
|
|
|
- size: pickerConfig.cameraQuarterTurns.isOdd
|
|
|
- ? mq.size.flipped
|
|
|
- : mq.size,
|
|
|
+ size: pickerConfig.cameraQuarterTurns.isOdd ? mq.size.flipped : mq.size,
|
|
|
),
|
|
|
child: body,
|
|
|
),
|