TF-2948 Apply new identity view for mobile
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -5,11 +5,12 @@ import 'package:core/presentation/constants/constants_ui.dart';
|
|||||||
import 'package:core/presentation/views/loading/cupertino_loading_widget.dart';
|
import 'package:core/presentation/views/loading/cupertino_loading_widget.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:core/utils/html/html_interaction.dart';
|
import 'package:core/utils/html/html_interaction.dart';
|
||||||
|
import 'package:core/utils/html/html_template.dart';
|
||||||
import 'package:core/utils/html/html_utils.dart';
|
import 'package:core/utils/html/html_utils.dart';
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart' as launcher;
|
import 'package:url_launcher/url_launcher.dart' as launcher;
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
@@ -30,10 +31,12 @@ class HtmlContentViewer extends StatefulWidget {
|
|||||||
final double? contentPadding;
|
final double? contentPadding;
|
||||||
final bool useDefaultFont;
|
final bool useDefaultFont;
|
||||||
final double? maxHtmlContentHeight;
|
final double? maxHtmlContentHeight;
|
||||||
final double minHtmlContentHeight;
|
final double htmlContentMinHeight;
|
||||||
final double offsetHtmlContentHeight;
|
final double offsetHtmlContentHeight;
|
||||||
final bool keepAlive;
|
final bool keepAlive;
|
||||||
final bool enableQuoteToggle;
|
final bool enableQuoteToggle;
|
||||||
|
final bool disableScrolling;
|
||||||
|
final double? maxViewHeight;
|
||||||
|
|
||||||
final OnLoadWidthHtmlViewerAction? onLoadWidthHtmlViewer;
|
final OnLoadWidthHtmlViewerAction? onLoadWidthHtmlViewer;
|
||||||
final OnMailtoDelegateAction? onMailtoDelegateAction;
|
final OnMailtoDelegateAction? onMailtoDelegateAction;
|
||||||
@@ -47,13 +50,15 @@ class HtmlContentViewer extends StatefulWidget {
|
|||||||
required this.contentHtml,
|
required this.contentHtml,
|
||||||
this.initialWidth,
|
this.initialWidth,
|
||||||
this.direction,
|
this.direction,
|
||||||
this.minHtmlContentHeight = ConstantsUI.htmlContentMinHeight,
|
this.htmlContentMinHeight = ConstantsUI.htmlContentMinHeight,
|
||||||
this.offsetHtmlContentHeight = ConstantsUI.htmlContentOffsetHeight,
|
this.offsetHtmlContentHeight = ConstantsUI.htmlContentOffsetHeight,
|
||||||
this.keepAlive = false,
|
this.keepAlive = false,
|
||||||
this.enableQuoteToggle = false,
|
this.enableQuoteToggle = false,
|
||||||
this.keepWidthWhileLoading = false,
|
this.keepWidthWhileLoading = false,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.useDefaultFont = false,
|
this.useDefaultFont = false,
|
||||||
|
this.disableScrolling = false,
|
||||||
|
this.maxViewHeight,
|
||||||
this.maxHtmlContentHeight,
|
this.maxHtmlContentHeight,
|
||||||
this.onLoadWidthHtmlViewer,
|
this.onLoadWidthHtmlViewer,
|
||||||
this.onMailtoDelegateAction,
|
this.onMailtoDelegateAction,
|
||||||
@@ -72,45 +77,39 @@ class HtmlContentViewState extends State<HtmlContentViewer> with AutomaticKeepAl
|
|||||||
late InAppWebViewController _webViewController;
|
late InAppWebViewController _webViewController;
|
||||||
late double _actualHeight;
|
late double _actualHeight;
|
||||||
late Set<Factory<OneSequenceGestureRecognizer>> _gestureRecognizers;
|
late Set<Factory<OneSequenceGestureRecognizer>> _gestureRecognizers;
|
||||||
late StringBuffer _customScriptsBuilder;
|
late InAppWebViewSettings _webViewSetting;
|
||||||
|
|
||||||
final _loadingBarNotifier = ValueNotifier(true);
|
final _loadingBarNotifier = ValueNotifier(true);
|
||||||
|
|
||||||
String? _htmlData;
|
String? _htmlData;
|
||||||
|
|
||||||
final _webViewSetting = InAppWebViewSettings(
|
|
||||||
transparentBackground: true,
|
|
||||||
verticalScrollBarEnabled: false,
|
|
||||||
supportZoom: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
InAppWebViewController get webViewController => _webViewController;
|
InAppWebViewController get webViewController => _webViewController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (PlatformInfo.isAndroid) {
|
_webViewSetting = InAppWebViewSettings(
|
||||||
_gestureRecognizers = {
|
transparentBackground: true,
|
||||||
Factory<LongPressGestureRecognizer>(() => LongPressGestureRecognizer()),
|
verticalScrollBarEnabled: false,
|
||||||
|
supportZoom: false,
|
||||||
|
disableHorizontalScroll: widget.disableScrolling,
|
||||||
|
disableVerticalScroll: widget.disableScrolling,
|
||||||
|
horizontalScrollBarEnabled: !widget.disableScrolling,
|
||||||
|
);
|
||||||
|
|
||||||
|
_gestureRecognizers = {
|
||||||
|
Factory<LongPressGestureRecognizer>(
|
||||||
|
() => LongPressGestureRecognizer(
|
||||||
|
duration: PlatformInfo.isAndroid
|
||||||
|
? null
|
||||||
|
: _longPressGestureDurationIOS,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (PlatformInfo.isAndroid && !widget.disableScrolling)
|
||||||
Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()),
|
Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()),
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
_gestureRecognizers = {
|
|
||||||
Factory<LongPressGestureRecognizer>(() => LongPressGestureRecognizer(duration: _longPressGestureDurationIOS)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_customScriptsBuilder = StringBuffer();
|
|
||||||
_customScriptsBuilder.write(HtmlInteraction.scriptsHandleLazyLoadingBackgroundImage);
|
|
||||||
if (widget.enableQuoteToggle) {
|
|
||||||
_customScriptsBuilder.write(HtmlUtils.quoteToggleScript);
|
|
||||||
}
|
|
||||||
if (widget.initialWidth != null) {
|
|
||||||
_customScriptsBuilder.write(HtmlInteraction.generateNormalizeImageScript(widget.initialWidth!));
|
|
||||||
}
|
|
||||||
if (PlatformInfo.isAndroid) {
|
|
||||||
_customScriptsBuilder.write(HtmlInteraction.scriptsHandleContentSizeChanged);
|
|
||||||
}
|
|
||||||
_initialData();
|
_initialData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,16 +124,33 @@ class HtmlContentViewState extends State<HtmlContentViewer> with AutomaticKeepAl
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _initialData() {
|
void _initialData() {
|
||||||
_actualHeight = widget.minHtmlContentHeight;
|
_actualHeight = widget.htmlContentMinHeight;
|
||||||
_htmlData = HtmlUtils.generateHtmlDocument(
|
|
||||||
content: widget.enableQuoteToggle
|
final processedContent = widget.enableQuoteToggle
|
||||||
? HtmlUtils.addQuoteToggle(widget.contentHtml)
|
? HtmlUtils.addQuoteToggle(widget.contentHtml)
|
||||||
: widget.contentHtml,
|
: widget.contentHtml;
|
||||||
|
|
||||||
|
final combinedCss = [
|
||||||
|
if (widget.enableQuoteToggle) HtmlUtils.quoteToggleStyle,
|
||||||
|
if (widget.disableScrolling) HtmlTemplate.disableScrollingStyleCSS,
|
||||||
|
].join();
|
||||||
|
|
||||||
|
final combinedScripts = [
|
||||||
|
HtmlInteraction.scriptsHandleLazyLoadingBackgroundImage,
|
||||||
|
if (widget.enableQuoteToggle) HtmlUtils.quoteToggleScript,
|
||||||
|
if (widget.initialWidth != null)
|
||||||
|
HtmlInteraction.generateNormalizeImageScript(widget.initialWidth!),
|
||||||
|
if (PlatformInfo.isAndroid)
|
||||||
|
HtmlInteraction.scriptsHandleContentSizeChanged,
|
||||||
|
].join();
|
||||||
|
|
||||||
|
_htmlData = HtmlUtils.generateHtmlDocument(
|
||||||
|
content: processedContent,
|
||||||
direction: widget.direction,
|
direction: widget.direction,
|
||||||
javaScripts: _customScriptsBuilder.toString(),
|
javaScripts: combinedScripts,
|
||||||
|
styleCSS: combinedCss,
|
||||||
contentPadding: widget.contentPadding,
|
contentPadding: widget.contentPadding,
|
||||||
useDefaultFont: widget.useDefaultFont,
|
useDefaultFont: widget.useDefaultFont,
|
||||||
styleCSS: widget.enableQuoteToggle ? HtmlUtils.quoteToggleStyle : null
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,23 +158,20 @@ class HtmlContentViewState extends State<HtmlContentViewer> with AutomaticKeepAl
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
final child = Stack(children: [
|
final child = Stack(children: [
|
||||||
if (_htmlData == null)
|
if (_htmlData?.trim().isNotEmpty == true)
|
||||||
const SizedBox.shrink()
|
if (widget.maxViewHeight != null)
|
||||||
else
|
Container(
|
||||||
SizedBox(
|
height: _actualHeight,
|
||||||
height: _actualHeight,
|
width: widget.initialWidth,
|
||||||
width: widget.initialWidth,
|
constraints: BoxConstraints(maxHeight: widget.maxViewHeight!),
|
||||||
child: InAppWebView(
|
child: _buildWebView(),
|
||||||
key: ValueKey(_htmlData),
|
|
||||||
initialSettings: _webViewSetting,
|
|
||||||
onWebViewCreated: _onWebViewCreated,
|
|
||||||
onLoadStop: _onLoadStop,
|
|
||||||
onContentSizeChanged: _onContentSizeChanged,
|
|
||||||
shouldOverrideUrlLoading: _shouldOverrideUrlLoading,
|
|
||||||
gestureRecognizers: _gestureRecognizers,
|
|
||||||
onScrollChanged: (controller, x, y) => controller.scrollTo(x: 0, y: 0)
|
|
||||||
)
|
)
|
||||||
),
|
else
|
||||||
|
SizedBox(
|
||||||
|
height: _actualHeight,
|
||||||
|
width: widget.initialWidth,
|
||||||
|
child: _buildWebView(),
|
||||||
|
),
|
||||||
ValueListenableBuilder(
|
ValueListenableBuilder(
|
||||||
valueListenable: _loadingBarNotifier,
|
valueListenable: _loadingBarNotifier,
|
||||||
builder: (context, loading, child) {
|
builder: (context, loading, child) {
|
||||||
@@ -171,23 +184,42 @@ class HtmlContentViewState extends State<HtmlContentViewer> with AutomaticKeepAl
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!widget.keepWidthWhileLoading) return child;
|
if (!widget.keepWidthWhileLoading) {
|
||||||
return SizedBox(
|
return child;
|
||||||
width: widget.initialWidth,
|
} else {
|
||||||
child: child,
|
return SizedBox(width: widget.initialWidth, child: child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildWebView() {
|
||||||
|
return InAppWebView(
|
||||||
|
key: ValueKey(_htmlData),
|
||||||
|
initialSettings: _webViewSetting,
|
||||||
|
onWebViewCreated: _onWebViewCreated,
|
||||||
|
onLoadStop: _onLoadStop,
|
||||||
|
onContentSizeChanged: _onContentSizeChanged,
|
||||||
|
shouldOverrideUrlLoading: _shouldOverrideUrlLoading,
|
||||||
|
gestureRecognizers: _gestureRecognizers,
|
||||||
|
onScrollChanged: widget.disableScrolling ? null : _onScrollChanged,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onScrollChanged(InAppWebViewController controller, int x, int y) {
|
||||||
|
controller.scrollTo(x: 0, y: 0);
|
||||||
|
}
|
||||||
|
|
||||||
void _onWebViewCreated(InAppWebViewController controller) async {
|
void _onWebViewCreated(InAppWebViewController controller) async {
|
||||||
log('_HtmlContentViewState::_onWebViewCreated:');
|
log('_HtmlContentViewState::_onWebViewCreated:');
|
||||||
_webViewController = controller;
|
_webViewController = controller;
|
||||||
|
|
||||||
await controller.loadData(data: _htmlData ?? '');
|
await controller.loadData(data: _htmlData ?? '');
|
||||||
|
|
||||||
controller.addJavaScriptHandler(
|
if (!widget.disableScrolling) {
|
||||||
handlerName: HtmlInteraction.scrollEventJSChannelName,
|
controller.addJavaScriptHandler(
|
||||||
callback: _onHandleScrollEvent
|
handlerName: HtmlInteraction.scrollEventJSChannelName,
|
||||||
);
|
callback: _onHandleScrollEvent,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (PlatformInfo.isAndroid) {
|
if (PlatformInfo.isAndroid) {
|
||||||
controller.addJavaScriptHandler(
|
controller.addJavaScriptHandler(
|
||||||
@@ -230,12 +262,8 @@ class HtmlContentViewState extends State<HtmlContentViewer> with AutomaticKeepAl
|
|||||||
double currentHeight = maxContentHeight + widget.offsetHtmlContentHeight;
|
double currentHeight = maxContentHeight + widget.offsetHtmlContentHeight;
|
||||||
|
|
||||||
if (PlatformInfo.isIOS && widget.maxHtmlContentHeight != null) {
|
if (PlatformInfo.isIOS && widget.maxHtmlContentHeight != null) {
|
||||||
final bool isClipped = currentHeight > widget.maxHtmlContentHeight!;
|
currentHeight = _reStandardizeHeight(
|
||||||
if (isClipped) {
|
currentHeight,
|
||||||
widget.onHtmlContentClippedAction?.call(true);
|
|
||||||
}
|
|
||||||
currentHeight = currentHeight.clamp(
|
|
||||||
widget.minHtmlContentHeight,
|
|
||||||
widget.maxHtmlContentHeight!,
|
widget.maxHtmlContentHeight!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -259,58 +287,74 @@ class HtmlContentViewState extends State<HtmlContentViewer> with AutomaticKeepAl
|
|||||||
|
|
||||||
log('_HtmlContentViewState::_getActualSizeHtmlViewer(): listSize: $listSize');
|
log('_HtmlContentViewState::_getActualSizeHtmlViewer(): listSize: $listSize');
|
||||||
|
|
||||||
bool isScrollActivated = false;
|
|
||||||
Set<Factory<OneSequenceGestureRecognizer>>? newGestureRecognizers;
|
|
||||||
|
|
||||||
final double? scrollWidth = listSize[0] is num ? (listSize[0] as num).toDouble() : null;
|
final double? scrollWidth = listSize[0] is num ? (listSize[0] as num).toDouble() : null;
|
||||||
final double? offsetWidth = listSize[1] is num ? (listSize[1] as num).toDouble() : null;
|
final double? offsetWidth = listSize[1] is num ? (listSize[1] as num).toDouble() : null;
|
||||||
final double? scrollHeight = listSize[2] is num ? (listSize[2] as num).toDouble() : null;
|
final double? scrollHeight = listSize[2] is num ? (listSize[2] as num).toDouble() : null;
|
||||||
|
|
||||||
if (scrollWidth != null && offsetWidth != null) {
|
bool isContentFullyVisible = scrollWidth != null &&
|
||||||
isScrollActivated = scrollWidth.round() == offsetWidth.round();
|
offsetWidth != null &&
|
||||||
if (!isScrollActivated && PlatformInfo.isIOS) {
|
scrollWidth.round() == offsetWidth.round();
|
||||||
newGestureRecognizers = {
|
|
||||||
Factory<LongPressGestureRecognizer>(() => LongPressGestureRecognizer(duration: _longPressGestureDurationIOS)),
|
final isIOSScrollingEnabled = !isContentFullyVisible && PlatformInfo.isIOS;
|
||||||
Factory<HorizontalDragGestureRecognizer>(() => HorizontalDragGestureRecognizer()),
|
log('_HtmlContentViewState::_getActualSizeHtmlViewer: isIOSScrollingEnabled = $isIOSScrollingEnabled | isContentFullyVisible = $isContentFullyVisible');
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrollHeight != null && scrollHeight > 0) {
|
if (scrollHeight != null && scrollHeight > 0) {
|
||||||
double currentHeight = scrollHeight + widget.offsetHtmlContentHeight;
|
double currentHeight = scrollHeight + widget.offsetHtmlContentHeight;
|
||||||
|
|
||||||
if (PlatformInfo.isIOS && widget.maxHtmlContentHeight != null) {
|
if (PlatformInfo.isIOS && widget.maxHtmlContentHeight != null) {
|
||||||
final bool isClipped = currentHeight > widget.maxHtmlContentHeight!;
|
currentHeight = _reStandardizeHeight(
|
||||||
if (isClipped) {
|
currentHeight,
|
||||||
widget.onHtmlContentClippedAction?.call(true);
|
|
||||||
}
|
|
||||||
currentHeight = currentHeight.clamp(
|
|
||||||
widget.minHtmlContentHeight,
|
|
||||||
widget.maxHtmlContentHeight!,
|
widget.maxHtmlContentHeight!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
log('_HtmlContentViewState::_getActualSizeHtmlViewer: currentHeight = $currentHeight');
|
||||||
|
|
||||||
if (_actualHeight != currentHeight || newGestureRecognizers != null) {
|
if (_actualHeight != currentHeight || isIOSScrollingEnabled) {
|
||||||
log('_HtmlContentViewState::_getActualSizeHtmlViewer: currentHeight = $currentHeight');
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_actualHeight = currentHeight;
|
_actualHeight = currentHeight;
|
||||||
if (newGestureRecognizers != null) {
|
if (isIOSScrollingEnabled && !widget.disableScrolling) {
|
||||||
_gestureRecognizers = newGestureRecognizers;
|
_gestureRecognizers = _iOSGestureRecognizersWithScrolling;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (newGestureRecognizers != null) {
|
} else if (isIOSScrollingEnabled && !widget.disableScrolling) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_gestureRecognizers = newGestureRecognizers!;
|
_gestureRecognizers = _iOSGestureRecognizersWithScrolling;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isScrollActivated) {
|
if (!isContentFullyVisible && !widget.disableScrolling) {
|
||||||
await _webViewController.evaluateJavascript(source: HtmlInteraction.runScriptsHandleScrollEvent);
|
await _webViewController.evaluateJavascript(
|
||||||
|
source: HtmlInteraction.runScriptsHandleScrollEvent,
|
||||||
|
);
|
||||||
|
|
||||||
|
widget.onLoadWidthHtmlViewer?.call(isContentFullyVisible);
|
||||||
}
|
}
|
||||||
widget.onLoadWidthHtmlViewer?.call(isScrollActivated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double _reStandardizeHeight(double currentHeight, double maxHtmlContentHeight) {
|
||||||
|
final bool isClipped = currentHeight > maxHtmlContentHeight;
|
||||||
|
if (isClipped) {
|
||||||
|
widget.onHtmlContentClippedAction?.call(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentHeight.clamp(
|
||||||
|
widget.htmlContentMinHeight,
|
||||||
|
maxHtmlContentHeight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Factory<OneSequenceGestureRecognizer>> get _iOSGestureRecognizersWithScrolling => {
|
||||||
|
Factory<LongPressGestureRecognizer>(
|
||||||
|
() => LongPressGestureRecognizer(
|
||||||
|
duration: _longPressGestureDurationIOS,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Factory<HorizontalDragGestureRecognizer>(
|
||||||
|
() => HorizontalDragGestureRecognizer(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
Future<NavigationActionPolicy?> _shouldOverrideUrlLoading(
|
Future<NavigationActionPolicy?> _shouldOverrideUrlLoading(
|
||||||
InAppWebViewController controller,
|
InAppWebViewController controller,
|
||||||
NavigationAction navigationAction
|
NavigationAction navigationAction
|
||||||
|
|||||||
+6
-1
@@ -1,6 +1,7 @@
|
|||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/views/checkbox/custom_icon_labeled_checkbox.dart';
|
import 'package:core/presentation/views/checkbox/custom_icon_labeled_checkbox.dart';
|
||||||
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
|
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
|
||||||
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_controller.dart';
|
import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_controller.dart';
|
||||||
@@ -82,7 +83,11 @@ class IdentityCreatorFormBottomView extends StatelessWidget {
|
|||||||
|
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 17),
|
padding: EdgeInsetsDirectional.only(
|
||||||
|
start: 17,
|
||||||
|
end: 17,
|
||||||
|
bottom: PlatformInfo.isMobile ? 24 : 0,
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
|||||||
Reference in New Issue
Block a user