TF-3479 Allow open multiple composer on screen
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M7.65081 7.24076C7.23148 6.88134 6.60018 6.9299 6.24076 7.34923C5.88134 7.76855 5.9299 8.39985 6.34923 8.75927L13.3492 14.7593C13.7237 15.0803 14.2763 15.0803 14.6508 14.7593L21.6508 8.75928C22.0701 8.39985 22.1187 7.76855 21.7593 7.34923C21.3999 6.9299 20.7686 6.88134 20.3492 7.24076L14 12.6829L7.65081 7.24076Z"
|
||||
fill="black" />
|
||||
<path
|
||||
d="M7.65081 14.2408C7.23148 13.8813 6.60018 13.9299 6.24076 14.3492C5.88134 14.7686 5.9299 15.3999 6.34923 15.7593L13.3492 21.7593C13.7237 22.0803 14.2763 22.0803 14.6508 21.7593L21.6508 15.7593C22.0701 15.3999 22.1187 14.7686 21.7593 14.3492C21.3999 13.9299 20.7686 13.8813 20.3492 14.2408L14 19.6829L7.65081 14.2408Z"
|
||||
fill="black" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 825 B |
@@ -0,0 +1,8 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M20.3492 21.7593C20.7686 22.1187 21.3999 22.0701 21.7593 21.6508C22.1187 21.2315 22.0701 20.6002 21.6508 20.2407L14.6508 14.2407C14.2763 13.9198 13.7237 13.9198 13.3492 14.2407L6.34923 20.2407C5.9299 20.6002 5.88134 21.2315 6.24076 21.6508C6.60018 22.0701 7.23148 22.1187 7.65081 21.7593L14 16.3171L20.3492 21.7593Z"
|
||||
fill="black" />
|
||||
<path
|
||||
d="M20.3492 14.7593C20.7686 15.1187 21.3999 15.0701 21.7593 14.6508C22.1187 14.2315 22.0701 13.6002 21.6508 13.2407L14.6508 7.24074C14.2763 6.91975 13.7237 6.91975 13.3492 7.24074L6.34923 13.2407C5.9299 13.6002 5.88134 14.2315 6.24076 14.6508C6.60018 15.0701 7.23148 15.1187 7.65081 14.7593L14 9.31708L20.3492 14.7593Z"
|
||||
fill="black" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 827 B |
@@ -227,6 +227,8 @@ class ImagePaths {
|
||||
String get icSubaddressingDisallow => _getImagePath('ic_subaddressing_disallow.svg');
|
||||
String get icMarkAsImportant => _getImagePath('ic_mark_as_important.svg');
|
||||
String get icCloseDialog => _getImagePath('ic_close_dialog.svg');
|
||||
String get icDoubleArrowUp => _getImagePath('ic_double_arrow_up.svg');
|
||||
String get icDoubleArrowDown => _getImagePath('ic_double_arrow_down.svg');
|
||||
|
||||
String _getImagePath(String imageName) {
|
||||
return AssetsPaths.images + imageName;
|
||||
|
||||
@@ -262,7 +262,6 @@ class ComposerController extends BaseController
|
||||
if (PlatformInfo.isWeb) {
|
||||
responsiveContainerKey = GlobalKey();
|
||||
richTextWebController = getBinding<RichTextWebController>(tag: composerId);
|
||||
responsiveContainerKey = GlobalKey();
|
||||
menuMoreOptionController = CustomPopupMenuController();
|
||||
} else {
|
||||
richTextMobileTabletController = getBinding<RichTextMobileTabletController>(tag: composerId);
|
||||
@@ -310,7 +309,6 @@ class ComposerController extends BaseController
|
||||
richTextMobileTabletController = null;
|
||||
}
|
||||
_identityContentOnOpenPolicy = SignatureStatus.editedAvailable;
|
||||
responsiveContainerKey = null;
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/manager/composer_manager.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/utils/composer_utils.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/expand_composer_button.dart';
|
||||
|
||||
class ComposerOverlayView extends StatefulWidget {
|
||||
const ComposerOverlayView({super.key});
|
||||
@@ -14,13 +20,94 @@ class ComposerOverlayView extends StatefulWidget {
|
||||
class _ComposerOverlayViewState extends State<ComposerOverlayView> {
|
||||
|
||||
final ComposerManager _composerManager = Get.find<ComposerManager>();
|
||||
final ImagePaths _imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() {
|
||||
if (!_composerManager.hasComposer) return const SizedBox.shrink();
|
||||
final composers = _composerManager.composers;
|
||||
if (composers.isEmpty) return const SizedBox.shrink();
|
||||
|
||||
return ComposerView(composerId: _composerManager.singleComposerId);
|
||||
if (composers.length == 1) {
|
||||
return _composerManager.getComposerView(_composerManager.singleComposerId);
|
||||
}
|
||||
|
||||
return Align(
|
||||
alignment: AlignmentDirectional.bottomEnd,
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.symmetric(
|
||||
horizontal: 24,
|
||||
vertical: 16,
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
final availableWidth = constraints.maxWidth - ComposerUtils.composerExpandMoreButtonMaxWidth;
|
||||
|
||||
final composerIds = _composerManager.composerIdsQueue.toList();
|
||||
final composerViews = composerIds
|
||||
.map((id) => _composerManager.getComposerView(id))
|
||||
.toList();
|
||||
|
||||
final countNormalComposer = composerViews.where(
|
||||
(view) => view.controller.screenDisplayMode.value == ScreenDisplayMode.normal,
|
||||
).length;
|
||||
|
||||
final maxNormalComposer = ComposerUtils.calculateNormalWidgets(availableWidth);
|
||||
final countDisplayNormalComposer = min(
|
||||
countNormalComposer,
|
||||
maxNormalComposer,
|
||||
);
|
||||
|
||||
final countDisplayComposer = countDisplayNormalComposer > 0
|
||||
? ComposerUtils.calculateNormalAndMinimizeWidgets(availableWidth, countDisplayNormalComposer)
|
||||
: ComposerUtils.calculateMinimizeWidgets(availableWidth);
|
||||
|
||||
if (countDisplayComposer < 1) return const SizedBox.shrink();
|
||||
|
||||
Iterable<String> composerIdsDisplayed = [];
|
||||
if (composerIds.length > countDisplayComposer) {
|
||||
composerIdsDisplayed = composerIds
|
||||
.reversed
|
||||
.take(countDisplayComposer)
|
||||
.toList()
|
||||
.reversed;
|
||||
} else {
|
||||
composerIdsDisplayed = composerIds;
|
||||
}
|
||||
|
||||
final countMinimizeComposer =
|
||||
composerIdsDisplayed.length - countDisplayNormalComposer;
|
||||
|
||||
int countComposerHidden = composerIds.length - countDisplayComposer;
|
||||
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (countComposerHidden > 0)
|
||||
ExpandComposerButton(
|
||||
imagePaths: _imagePaths,
|
||||
countComposerHidden: countComposerHidden,
|
||||
onToggleDisplayComposerAction: () {},
|
||||
),
|
||||
...composerIdsDisplayed.mapIndexed((index, id) {
|
||||
final composerView = _composerManager.getComposerView(id);
|
||||
final isMinimized = countDisplayNormalComposer < 1 ||
|
||||
(countMinimizeComposer > 0 && index < countMinimizeComposer);
|
||||
|
||||
composerView.controller.screenDisplayMode.value = isMinimized
|
||||
? ScreenDisplayMode.minimize
|
||||
: ScreenDisplayMode.normal;
|
||||
|
||||
return composerView;
|
||||
}).toList(),
|
||||
],
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,6 +639,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
]),
|
||||
);
|
||||
},
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
displayMode: controller.screenDisplayMode.value,
|
||||
emailSubject: controller.subjectEmail.value ?? '',
|
||||
onCloseViewAction: () => controller.handleClickCloseComposer(context),
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/utils/composer_utils.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
|
||||
class ComposerManager extends GetxController {
|
||||
final RxMap<String, ComposerController> composers = <String, ComposerController>{}.obs;
|
||||
final RxMap<String, ComposerView> composers = <String, ComposerView>{}.obs;
|
||||
final Queue<String> composerIdsQueue = Queue<String>();
|
||||
|
||||
void addComposer(ComposerArguments composerArguments) {
|
||||
final String id = DateTime.now().millisecondsSinceEpoch.toString();
|
||||
@@ -14,22 +19,36 @@ class ComposerManager extends GetxController {
|
||||
composerId: id,
|
||||
composerArguments: composerArguments,
|
||||
).dependencies();
|
||||
composers[id] = Get.find<ComposerController>(tag: id);
|
||||
composerIdsQueue.add(id);
|
||||
composers[id] = ComposerView(
|
||||
key: Key(id),
|
||||
composerId: id,
|
||||
);
|
||||
log('ComposerManager::addComposer:Success');
|
||||
}
|
||||
|
||||
void removeComposer(String id) {
|
||||
log('ComposerManager::removeComposer:ID = $id');
|
||||
if (composers.containsKey(id)) {
|
||||
ComposerBindings(composerId: id).dispose();
|
||||
composerIdsQueue.remove(id);
|
||||
composers.remove(id);
|
||||
ComposerBindings(composerId: id).dispose();
|
||||
log('ComposerManager::removeComposer:Success');
|
||||
}
|
||||
}
|
||||
|
||||
bool get hasComposer => composers.isNotEmpty;
|
||||
({
|
||||
String? previousTargetId,
|
||||
String? targetId,
|
||||
String? nextTargetId,
|
||||
}) findSurroundingComposerIds(String targetId) =>
|
||||
ComposerUtils.findSurroundingElements(composerIdsQueue, targetId);
|
||||
|
||||
List<String> get composerIds => composers.keys.toList();
|
||||
bool get hasComposer => composerIdsQueue.isNotEmpty;
|
||||
|
||||
String get singleComposerId => composerIds.first;
|
||||
List<String> get composerIds => composerIdsQueue.toList();
|
||||
|
||||
String get singleComposerId => composerIdsQueue.first;
|
||||
|
||||
ComposerView getComposerView(String id) => composers[id]!;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/utils/composer_utils.dart';
|
||||
|
||||
class MinimizeComposerWidgetStyle {
|
||||
static const double radius = 24;
|
||||
static const double elevation = 16;
|
||||
static const double width = 500;
|
||||
static const double height = 50;
|
||||
static const double width = ComposerUtils.minimizeWidth;
|
||||
static const double height = ComposerUtils.minimizeHeight;
|
||||
static const double space = 8;
|
||||
static const double iconSize = 20;
|
||||
|
||||
|
||||
+3
@@ -1,10 +1,13 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/utils/composer_utils.dart';
|
||||
|
||||
class DesktopResponsiveContainerViewStyle {
|
||||
static const double radius = 28;
|
||||
static const double margin = 20;
|
||||
static const double elevation = 16;
|
||||
static const double normalScreenMaxWidth = ComposerUtils.normalWidth;
|
||||
static const double normalScreenMaxHeight = ComposerUtils.normalHeight;
|
||||
|
||||
static const Color backgroundColor = Colors.white;
|
||||
static const Color outSideBackgroundColor = Colors.black38;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
class ComposerUtils {
|
||||
static const double normalWidth = 725;
|
||||
static const double normalHeight = 525;
|
||||
static const double minimizeWidth = 400;
|
||||
static const double minimizeHeight = 52;
|
||||
static const double composerExpandMoreButtonMaxWidth = 130;
|
||||
|
||||
static int calculateNormalAndMinimizeWidgets(double width, int countNormalWidgets) {
|
||||
double remainingWidth = width - (countNormalWidgets * normalWidth);
|
||||
if (remainingWidth < 0) return countNormalWidgets;
|
||||
int countWidgets = countNormalWidgets + (remainingWidth / minimizeWidth).floor();
|
||||
return countWidgets;
|
||||
}
|
||||
|
||||
static int calculateNormalWidgets(double width) => (width / normalWidth).floor();
|
||||
|
||||
static int calculateMinimizeWidgets(double width) => (width / minimizeWidth).floor();
|
||||
|
||||
static ({
|
||||
String? previousTargetId,
|
||||
String? targetId,
|
||||
String? nextTargetId,
|
||||
}) findSurroundingElements(Queue<String> queue, String targetId) {
|
||||
var ids = queue.toList(),
|
||||
index = ids.indexOf(targetId);
|
||||
|
||||
return index == -1
|
||||
? (previousTargetId: null, targetId: null, nextTargetId: null)
|
||||
: (
|
||||
previousTargetId: index > 0 ? ids[index - 1] : null,
|
||||
targetId: ids[index],
|
||||
nextTargetId: index < ids.length - 1 ? ids[index + 1] : null
|
||||
);
|
||||
}
|
||||
}
|
||||
+58
-26
@@ -2,23 +2,26 @@ import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/manager/composer_manager.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/web/desktop_responsive_container_view_style.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/minimize_composer_widget.dart';
|
||||
|
||||
class DesktopResponsiveContainerView extends StatelessWidget {
|
||||
|
||||
final ResponsiveUtils responsiveUtils;
|
||||
final ScreenDisplayMode displayMode;
|
||||
final String emailSubject;
|
||||
final VoidCallback onCloseViewAction;
|
||||
final OnChangeDisplayModeAction onChangeDisplayModeAction;
|
||||
final Widget Function(BuildContext context, BoxConstraints constraints) childBuilder;
|
||||
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final ComposerManager _composerManager = Get.find<ComposerManager>();
|
||||
|
||||
DesktopResponsiveContainerView({
|
||||
super.key,
|
||||
required this.childBuilder,
|
||||
required this.responsiveUtils,
|
||||
required this.displayMode,
|
||||
required this.emailSubject,
|
||||
required this.onCloseViewAction,
|
||||
@@ -28,45 +31,74 @@ class DesktopResponsiveContainerView extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (displayMode == ScreenDisplayMode.minimize) {
|
||||
return PositionedDirectional(
|
||||
end: DesktopResponsiveContainerViewStyle.margin,
|
||||
bottom: DesktopResponsiveContainerViewStyle.margin,
|
||||
child: PointerInterceptor(
|
||||
if (_composerManager.composerIds.length == 1) {
|
||||
return PositionedDirectional(
|
||||
end: DesktopResponsiveContainerViewStyle.margin,
|
||||
bottom: DesktopResponsiveContainerViewStyle.margin,
|
||||
child: PointerInterceptor(
|
||||
child: MinimizeComposerWidget(
|
||||
emailSubject: emailSubject,
|
||||
onCloseViewAction: onCloseViewAction,
|
||||
onChangeDisplayModeAction: onChangeDisplayModeAction,
|
||||
),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return PointerInterceptor(
|
||||
child: MinimizeComposerWidget(
|
||||
emailSubject: emailSubject,
|
||||
onCloseViewAction: onCloseViewAction,
|
||||
onChangeDisplayModeAction: onChangeDisplayModeAction,
|
||||
),
|
||||
)
|
||||
);
|
||||
} else if (displayMode == ScreenDisplayMode.normal) {
|
||||
final maxWidth = _responsiveUtils.getSizeScreenWidth(context) * 0.5;
|
||||
final maxHeight = _responsiveUtils.getSizeScreenHeight(context) * 0.75;
|
||||
);
|
||||
}
|
||||
|
||||
return PositionedDirectional(
|
||||
end: DesktopResponsiveContainerViewStyle.margin,
|
||||
bottom: DesktopResponsiveContainerViewStyle.margin,
|
||||
child: Card(
|
||||
} else if (displayMode == ScreenDisplayMode.normal) {
|
||||
if (_composerManager.composerIds.length == 1) {
|
||||
return PositionedDirectional(
|
||||
end: DesktopResponsiveContainerViewStyle.margin,
|
||||
bottom: DesktopResponsiveContainerViewStyle.margin,
|
||||
child: Card(
|
||||
elevation: DesktopResponsiveContainerViewStyle.elevation,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(DesktopResponsiveContainerViewStyle.radius))
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Container(
|
||||
color: DesktopResponsiveContainerViewStyle.backgroundColor,
|
||||
width: DesktopResponsiveContainerViewStyle.normalScreenMaxWidth,
|
||||
height: DesktopResponsiveContainerViewStyle.normalScreenMaxHeight,
|
||||
child: LayoutBuilder(builder: (context, constraints) =>
|
||||
PointerInterceptor(
|
||||
child: childBuilder.call(context, constraints)
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return Card(
|
||||
elevation: DesktopResponsiveContainerViewStyle.elevation,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(DesktopResponsiveContainerViewStyle.radius))
|
||||
borderRadius: BorderRadius.all(Radius.circular(DesktopResponsiveContainerViewStyle.radius))
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Container(
|
||||
color: DesktopResponsiveContainerViewStyle.backgroundColor,
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
child: LayoutBuilder(builder: (context, constraints) =>
|
||||
PointerInterceptor(
|
||||
child: childBuilder.call(context, constraints)
|
||||
color: DesktopResponsiveContainerViewStyle.backgroundColor,
|
||||
width: DesktopResponsiveContainerViewStyle.normalScreenMaxWidth,
|
||||
height: DesktopResponsiveContainerViewStyle.normalScreenMaxHeight,
|
||||
child: LayoutBuilder(builder: (context, constraints) =>
|
||||
PointerInterceptor(
|
||||
child: childBuilder.call(context, constraints)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
} else if (displayMode == ScreenDisplayMode.fullScreen) {
|
||||
final maxWidth = _responsiveUtils.getSizeScreenWidth(context) * 0.85;
|
||||
final maxHeight = _responsiveUtils.getSizeScreenHeight(context) * 0.9;
|
||||
final maxWidth = responsiveUtils.getSizeScreenWidth(context) * 0.85;
|
||||
final maxHeight = responsiveUtils.getSizeScreenHeight(context) * 0.9;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: DesktopResponsiveContainerViewStyle.outSideBackgroundColor,
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/utils/composer_utils.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class ExpandComposerButton extends StatelessWidget {
|
||||
|
||||
final ImagePaths imagePaths;
|
||||
final int countComposerHidden;
|
||||
final VoidCallback onToggleDisplayComposerAction;
|
||||
|
||||
const ExpandComposerButton({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
required this.countComposerHidden,
|
||||
required this.onToggleDisplayComposerAction,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
elevation: 16,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12))
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
onTap: () => {},
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
width: ComposerUtils.composerExpandMoreButtonMaxWidth,
|
||||
height: ComposerUtils.minimizeHeight,
|
||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(imagePaths.icDoubleArrowUp),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'+$countComposerHidden ${AppLocalizations.of(context).more.toLowerCase()}',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user