TF-381 Apply new UI for list emails
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.21917 5.37534C2.56418 4.94408 3.19347 4.87416 3.62473 5.21917L8.00004 8.71941L12.3753 5.21917C12.8066 4.87416 13.4359 4.94408 13.7809 5.37534C14.1259 5.8066 14.056 6.4359 13.6247 6.78091L8.62473 10.7809C8.25951 11.0731 7.74056 11.0731 7.37534 10.7809L2.37534 6.78091C1.94408 6.4359 1.87416 5.8066 2.21917 5.37534Z" fill="#007AFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 487 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.8246 5.21346C3.16498 6.25709 4.14611 7.01121 5.30337 7.01121C6.46063 7.01121 7.44176 6.25709 7.78214 5.21346C10.2518 5.21346 12.7214 5.21346 15.191 5.21346C15.6378 5.21346 16 4.85126 16 4.40447C16 3.95768 15.6378 3.59548 15.191 3.59548C12.7214 3.59548 10.2518 3.59548 7.78214 3.59548C7.77341 3.56819 7.7851 3.60456 7.78214 3.59548C7.44176 2.55185 6.46063 1.79773 5.30337 1.79773C4.14611 1.79773 3.16498 2.55185 2.8246 3.59548C2.15273 3.59548 1.48086 3.59548 0.808989 3.59548C0.362197 3.59548 0 3.95768 0 4.40447C0 4.85126 0.362197 5.21346 0.808989 5.21346C1.48086 5.21346 2.15273 5.21346 2.8246 5.21346ZM5.30337 3.41571C4.75729 3.41571 4.31461 3.85839 4.31461 4.40447C4.31461 4.95055 4.75729 5.39324 5.30337 5.39324C5.84945 5.39324 6.29214 4.95055 6.29214 4.40447C6.29214 3.85839 5.84945 3.41571 5.30337 3.41571Z" fill="#007AFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 11.5955C0 11.1487 0.362197 10.7865 0.808989 10.7865C3.27861 10.7865 5.74824 10.7865 8.21786 10.7865C8.55824 9.74286 9.53937 8.98874 10.6966 8.98874C11.8539 8.98874 12.835 9.74286 13.1754 10.7865C13.1754 10.7865 14.7223 10.7865 15.191 10.7865C15.6378 10.7865 16 11.1487 16 11.5955C16 12.0423 15.6378 12.4045 15.191 12.4045C14.9912 12.4045 13.1754 12.4045 13.1754 12.4045C12.835 13.4481 11.8539 14.2022 10.6966 14.2022C9.53937 14.2022 8.55824 13.4481 8.21786 12.4045C5.74824 12.4045 3.27861 12.4045 0.808989 12.4045C0.362197 12.4045 0 12.0423 0 11.5955ZM9.70787 11.5955C9.70787 11.0494 10.1506 10.6067 10.6966 10.6067C11.2427 10.6067 11.6854 11.0494 11.6854 11.5955C11.6854 12.1416 11.2427 12.5842 10.6966 12.5842C10.1506 12.5842 9.70787 12.1416 9.70787 11.5955Z" fill="#007AFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.37282 16H13.6273C14.9008 16 15.9365 14.9643 15.9365 13.6913V6.74368C15.9365 6.11726 15.6785 5.51248 15.2294 5.08412C15.1915 5.06481 9.43134 0.498567 9.43134 0.498567C8.58869 -0.166692 7.41144 -0.165686 6.56882 0.498567L0.864436 5.00095C0.378424 5.44784 0.0586148 6.0667 0.0636574 6.74368V13.6913C0.0636574 14.9643 1.09929 16 2.37282 16ZM7.52837 1.7141C7.80556 1.49437 8.1946 1.49437 8.47179 1.7141L13.4066 5.60824L8.47179 9.50237C8.1946 9.72209 7.80556 9.72209 7.52837 9.50237L2.59355 5.60825L7.52837 1.7141ZM1.61182 6.80586L6.56882 10.7179C7.41137 11.3829 8.58869 11.3822 9.43134 10.7179L14.3883 6.80586V13.6913C14.3883 14.1106 14.0471 14.4518 13.6273 14.4518H2.37282C1.95299 14.4518 1.61182 14.1106 1.61182 13.6913V6.80586Z" fill="#007AFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 859 B |
@@ -0,0 +1,6 @@
|
||||
<svg width="26" height="24" viewBox="0 0 26 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.90002 12C3.90002 14.5129 4.91858 16.7879 6.56535 18.4347C8.21213 20.0815 10.4871 21.1 13 21.1C14.6344 21.1 16.1681 20.6185 17.4938 19.8642M22.1 12C22.1 9.48713 21.0815 7.21213 19.4347 5.56535C17.7879 3.91858 15.5129 2.90002 13 2.90002C11.3656 2.90002 9.83189 3.38148 8.50617 4.13582" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M19.4948 11C19.0879 11 18.8514 11.4603 19.0884 11.7911L21.5916 15.2861C21.791 15.5645 22.2051 15.5645 22.4045 15.2861L24.9078 11.7911C25.1447 11.4603 24.9082 11 24.5013 11H19.4948Z" fill="white"/>
|
||||
<path d="M6.50516 13C6.91214 13 7.14863 12.5397 6.91165 12.2089L4.40844 8.71393C4.20898 8.43546 3.79491 8.43546 3.59546 8.71393L1.09225 12.2089C0.855264 12.5397 1.09175 13 1.49874 13H6.50516Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.01163 3.26667C9.46463 2.43991 11.1671 1.90002 13 1.90002C15.7888 1.90002 18.3152 3.0316 20.1418 4.85825C21.7474 6.46387 22.816 8.61014 23.0511 11H24.5013C24.9083 11 25.1447 11.4603 24.9078 11.7912L22.4046 15.2861C22.2051 15.5646 21.791 15.5646 21.5916 15.2861L19.0884 11.7912C18.8514 11.4603 19.0879 11 19.4949 11H21.039C20.813 9.16312 19.9725 7.51732 18.7276 6.27246C17.2607 4.80555 15.2371 3.90002 13 3.90002C11.5642 3.90002 10.1992 4.32304 9.00073 5.00497C8.52071 5.2781 7.91016 5.11038 7.63703 4.63037C7.3639 4.15035 7.53161 3.5398 8.01163 3.26667ZM4.96109 13H6.50511C6.91209 13 7.14858 12.5398 6.9116 12.2089L4.40839 8.71396C4.20893 8.43549 3.79486 8.43549 3.59541 8.71396L1.0922 12.2089C0.855213 12.5398 1.0917 13 1.49869 13H2.94896C3.18405 15.3899 4.25263 17.5362 5.85826 19.1418C7.6849 20.9685 10.2113 22.1 13 22.1C14.8329 22.1 16.5354 21.5601 17.9884 20.7334C18.4684 20.4602 18.6361 19.8497 18.363 19.3697C18.0899 18.8896 17.4793 18.7219 16.9993 18.9951C15.8008 19.677 14.4359 20.1 13 20.1C10.763 20.1 8.73938 19.1945 7.27247 17.7276C6.02761 16.4827 5.18704 14.8369 4.96109 13Z" fill="#007AFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.8538 0C12.278 0.01504 13.0027 0.168509 13.7542 0.570407C14.4735 0.955113 15.0424 1.52399 15.4271 2.24333C15.829 2.99481 15.9825 3.71955 15.9975 5.14371V10.8538C15.9825 12.278 15.829 13.0027 15.4271 13.7542C15.0424 14.4735 14.4735 15.0424 13.7542 15.4271C13.0027 15.829 12.278 15.9825 10.8538 15.9975H5.14371C3.71955 15.9825 2.99481 15.829 2.24333 15.4271C1.52399 15.0424 0.955113 14.4735 0.570407 13.7542C0.168509 13.0027 0.01504 12.278 0 10.8538V5.14371C0.01504 3.71955 0.168509 2.99481 0.570407 2.24333C0.955113 1.52399 1.52399 0.955113 2.24333 0.570407C2.99481 0.168509 3.71955 0.01504 5.14371 0H10.8538ZM10.6099 1.4533H5.38764L4.98227 1.45685C3.90643 1.47725 3.42471 1.58809 2.92929 1.85304C2.46344 2.10218 2.10218 2.46344 1.85304 2.92929C1.58809 3.42471 1.47725 3.90643 1.45685 4.98227L1.4533 5.38764V10.6099L1.45685 11.0153C1.47725 12.0911 1.58809 12.5728 1.85304 13.0682C2.10218 13.5341 2.46344 13.8953 2.92929 14.1444C3.42471 14.4095 3.90643 14.5203 4.98227 14.5407L5.38764 14.5442H10.6099L11.0153 14.5407C12.0911 14.5203 12.5728 14.4095 13.0682 14.1444C13.5341 13.8953 13.8953 13.5341 14.1444 13.0682C14.4095 12.5728 14.5203 12.0911 14.5407 11.0153L14.5442 10.6099V5.38764L14.5407 4.98227C14.5203 3.90643 14.4095 3.42471 14.1444 2.92929C13.8953 2.46344 13.5341 2.10218 13.0682 1.85304C12.5728 1.58809 12.0911 1.47725 11.0153 1.45685L10.6099 1.4533Z" fill="#007AFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -54,6 +54,7 @@ export 'presentation/views/bottom_popup/cupertino_action_sheet_action_builder.da
|
||||
export 'presentation/views/bottom_popup/cupertino_action_sheet_builder.dart';
|
||||
export 'presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart';
|
||||
export 'presentation/views/modal_sheets/edit_text_modal_sheet_builder.dart';
|
||||
export 'presentation/views/search/search_bar_view.dart';
|
||||
|
||||
// Resources
|
||||
export 'presentation/resources/assets_paths.dart';
|
||||
|
||||
@@ -98,6 +98,10 @@ extension AppColor on Color {
|
||||
static const colorBottomBarComposer = Color(0x5CEBEDF0);
|
||||
static const colorShadowComposerFullScreen = Color(0x33000000);
|
||||
static const colorCancelButton = Color(0xFFF2F2F2);
|
||||
static const colorTextButtonHeaderThread = Color(0xFF686E76);
|
||||
static const colorButtonHeaderThread = Color(0x99EBEDF0);
|
||||
static const colorBorderBodyThread = Color(0x5CB8C1CC);
|
||||
static const colorBgDesktop = Color(0xFFF6F6F6);
|
||||
|
||||
static const mapGradientColor = [
|
||||
[Color(0xFF21D4FD), Color(0xFFB721FF)],
|
||||
|
||||
@@ -75,6 +75,11 @@ class ImagePaths {
|
||||
String get icDeleteAttachment => _getImagePath('ic_delete_attachment.svg');
|
||||
String get icSendMobile => _getImagePath('ic_send_mobile.svg');
|
||||
String get icSendMobileDisable => _getImagePath('ic_send_mobile_disable.svg');
|
||||
String get icArrowDown => _getImagePath('ic_arrow_down.svg');
|
||||
String get icFilterWeb => _getImagePath('ic_filter_web.svg');
|
||||
String get icMarkAllAsRead => _getImagePath('ic_mark_all_as_read.svg');
|
||||
String get icRefresh => _getImagePath('ic_refresh.svg');
|
||||
String get icSelectAll => _getImagePath('ic_select_all.svg');
|
||||
|
||||
String _getImagePath(String imageName) {
|
||||
return AssetsPaths.images + imageName;
|
||||
|
||||
@@ -4,10 +4,13 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
typedef OnPressActionClick = void Function();
|
||||
typedef OnPressActionWithPositionClick = void Function(RelativeRect? position);
|
||||
|
||||
class ButtonBuilder {
|
||||
OnPressActionClick? _onPressActionClick;
|
||||
OnPressActionWithPositionClick? _onPressActionWithPositionClick;
|
||||
|
||||
BuildContext? _context;
|
||||
String? _icon;
|
||||
String? _text;
|
||||
double? _size;
|
||||
@@ -15,12 +18,21 @@ class ButtonBuilder {
|
||||
bool? _isVertical;
|
||||
Key? _key;
|
||||
Color? _iconColor;
|
||||
Color? _colorButton;
|
||||
TextStyle? _textStyle;
|
||||
BoxDecoration? _decoration;
|
||||
Widget? _iconAction;
|
||||
double? _radiusSplash;
|
||||
EdgeInsets? _padding;
|
||||
|
||||
void key(Key key) {
|
||||
_key = key;
|
||||
}
|
||||
|
||||
void context(BuildContext context) {
|
||||
_context = context;
|
||||
}
|
||||
|
||||
void size(double size) {
|
||||
_size = size;
|
||||
}
|
||||
@@ -29,6 +41,26 @@ class ButtonBuilder {
|
||||
_iconColor = color;
|
||||
}
|
||||
|
||||
void colorButton(Color color) {
|
||||
_colorButton = color;
|
||||
}
|
||||
|
||||
void decoration(BoxDecoration decoration) {
|
||||
_decoration = decoration;
|
||||
}
|
||||
|
||||
void addIconAction(Widget icon) {
|
||||
_iconAction = icon;
|
||||
}
|
||||
|
||||
void radiusSplash(double? radius) {
|
||||
_radiusSplash = radius;
|
||||
}
|
||||
|
||||
void padding(EdgeInsets? padding) {
|
||||
_padding = padding;
|
||||
}
|
||||
|
||||
void textStyle(TextStyle style) {
|
||||
_textStyle = style;
|
||||
}
|
||||
@@ -48,13 +80,33 @@ class ButtonBuilder {
|
||||
_onPressActionClick = onPressActionClick;
|
||||
}
|
||||
|
||||
void addOnPressActionWithPositionClick(OnPressActionWithPositionClick onPressActionClick) {
|
||||
_onPressActionWithPositionClick = onPressActionClick;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return InkWell(
|
||||
onTap: () => _onPressActionClick?.call(),
|
||||
onTap: () => _onPressActionClick != null ? _onPressActionClick?.call() : null,
|
||||
onTapDown: (detail) {
|
||||
if (_onPressActionWithPositionClick != null && _context != null) {
|
||||
final screenSize = MediaQuery.of(_context!).size;
|
||||
final offset = detail.globalPosition;
|
||||
final position = RelativeRect.fromLTRB(
|
||||
offset.dx,
|
||||
offset.dy,
|
||||
screenSize.width - offset.dx,
|
||||
screenSize.height - offset.dy,
|
||||
);
|
||||
_onPressActionWithPositionClick?.call(position);
|
||||
}
|
||||
},
|
||||
borderRadius: BorderRadius.all(Radius.circular(_radiusSplash ?? 0)),
|
||||
child: Container(
|
||||
key: _key,
|
||||
alignment: Alignment.center,
|
||||
color: Colors.white,
|
||||
color: _decoration == null ? _colorButton ?? Colors.white : null,
|
||||
decoration: _decoration,
|
||||
padding: _padding ?? EdgeInsets.zero,
|
||||
child: _buildBody()
|
||||
)
|
||||
);
|
||||
@@ -64,18 +116,18 @@ class ButtonBuilder {
|
||||
if (_text != null) {
|
||||
return _isVertical!
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildIcon(),
|
||||
_buildText(),
|
||||
if (_iconAction != null) _iconAction!
|
||||
])
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildIcon(),
|
||||
_buildText(),
|
||||
if (_iconAction != null) _iconAction!
|
||||
]);
|
||||
} else {
|
||||
return _buildIcon();
|
||||
|
||||
@@ -12,9 +12,15 @@ Widget buildIconWeb({
|
||||
double? iconSize,
|
||||
}) {
|
||||
return Material(
|
||||
type: MaterialType.circle,
|
||||
color: Colors.transparent,
|
||||
child: IconButton(icon: icon, iconSize: iconSize, padding: iconPadding ?? EdgeInsets.all(8.0), tooltip: tooltip, onPressed: onTap)
|
||||
shape: CircleBorder(),
|
||||
child: IconButton(
|
||||
icon: icon,
|
||||
iconSize: iconSize,
|
||||
padding: iconPadding ?? EdgeInsets.all(8.0),
|
||||
splashRadius: 20,
|
||||
tooltip: tooltip,
|
||||
onPressed: onTap)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,40 +57,26 @@ class AvatarBuilder {
|
||||
_onTapAvatarActionClick!();
|
||||
}},
|
||||
child: Container(
|
||||
key: _key,
|
||||
width: _size ?? 40,
|
||||
height: _size ?? 40,
|
||||
padding: EdgeInsets.zero,
|
||||
margin: EdgeInsets.zero,
|
||||
alignment: Alignment.center,
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: _size ?? 40,
|
||||
height: _size ?? 40,
|
||||
padding: EdgeInsets.zero,
|
||||
margin: EdgeInsets.zero,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular((_size ?? 40) * 0.5),
|
||||
border: Border.all(color: Colors.transparent),
|
||||
boxShadow: _boxShadows ?? [],
|
||||
gradient: _avatarColors?.isNotEmpty == true
|
||||
? LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
tileMode: TileMode.decal,
|
||||
colors: _avatarColors ?? [])
|
||||
key: _key,
|
||||
width: _size ?? 40,
|
||||
height: _size ?? 40,
|
||||
padding: EdgeInsets.zero,
|
||||
margin: EdgeInsets.zero,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular((_size ?? 40) * 0.5),
|
||||
border: Border.all(color: Colors.transparent),
|
||||
boxShadow: _boxShadows ?? [],
|
||||
gradient: _avatarColors?.isNotEmpty == true
|
||||
? LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, tileMode: TileMode.decal, colors: _avatarColors ?? [])
|
||||
: null,
|
||||
color: _bgColor ?? AppColor.avatarColor
|
||||
),
|
||||
child: Text(
|
||||
'${_text ?? ''}',
|
||||
style: _textStyle ?? TextStyle(fontSize: 20, color: _textColor ?? AppColor.avatarTextColor, fontWeight: FontWeight.w500)
|
||||
)
|
||||
),
|
||||
],
|
||||
)),
|
||||
color: _bgColor ?? AppColor.avatarColor
|
||||
),
|
||||
child: Text(
|
||||
'${_text ?? ''}',
|
||||
style: _textStyle ?? TextStyle(fontSize: 20, color: _textColor ?? AppColor.avatarTextColor, fontWeight: FontWeight.w500)
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -5,7 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
typedef OnOpenSearchViewAction = Function();
|
||||
|
||||
class SearchBarThreadViewWidget {
|
||||
class SearchBarView {
|
||||
OnOpenSearchViewAction? _onOpenSearchViewAction;
|
||||
|
||||
final ImagePaths _imagePaths;
|
||||
@@ -14,8 +14,9 @@ class SearchBarThreadViewWidget {
|
||||
EdgeInsets? _padding;
|
||||
EdgeInsets? _margin;
|
||||
String? _hintTextSearch;
|
||||
double? _maxSizeWidth;
|
||||
|
||||
SearchBarThreadViewWidget(this._imagePaths);
|
||||
SearchBarView(this._imagePaths);
|
||||
|
||||
void addOnOpenSearchViewAction(OnOpenSearchViewAction onOpenSearchViewAction) {
|
||||
_onOpenSearchViewAction = onOpenSearchViewAction;
|
||||
@@ -37,18 +38,24 @@ class SearchBarThreadViewWidget {
|
||||
_hintTextSearch = text;
|
||||
}
|
||||
|
||||
void maxSizeWidth(double? size) {
|
||||
_maxSizeWidth = size;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return GestureDetector(
|
||||
return InkWell(
|
||||
onTap: () => _onOpenSearchViewAction?.call(),
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
child: Container(
|
||||
key: Key('search_bar_widget'),
|
||||
alignment: Alignment.topCenter,
|
||||
height: _heightSearchBar ?? 40,
|
||||
width: _maxSizeWidth ?? double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: AppColor.colorBgSearchBar),
|
||||
padding: _padding ?? EdgeInsets.zero,
|
||||
margin: _margin ?? EdgeInsets.only(left: 16, right: 16, bottom: 10),
|
||||
margin: _margin ?? EdgeInsets.zero,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: Row(
|
||||
@@ -3,67 +3,78 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
/// A builder which builds a reusable slogan widget.
|
||||
/// This contains the logo and the slogan text.
|
||||
/// The elements are arranged in a column.
|
||||
/// The elements are arranged in a column or row.
|
||||
class SloganBuilder {
|
||||
|
||||
final bool arrangedByHorizontal;
|
||||
|
||||
Key? _key;
|
||||
String? _text;
|
||||
TextStyle? _textStyle;
|
||||
TextAlign? _textAlign;
|
||||
String? _logoSVG;
|
||||
String? _logo;
|
||||
double? _sizeLogo;
|
||||
|
||||
SloganBuilder key(Key key) {
|
||||
SloganBuilder({this.arrangedByHorizontal = false});
|
||||
|
||||
void key(Key key) {
|
||||
_key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setSloganText(String text) {
|
||||
void setSloganText(String text) {
|
||||
_text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setSloganTextStyle(TextStyle textStyle) {
|
||||
void setSloganTextStyle(TextStyle textStyle) {
|
||||
_textStyle = textStyle;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setSloganTextAlign(TextAlign textAlign) {
|
||||
void setSloganTextAlign(TextAlign textAlign) {
|
||||
_textAlign = textAlign;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setLogo(String logo) {
|
||||
void setLogo(String logo) {
|
||||
_logo = logo;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setLogoSVG(String logoSVG) {
|
||||
void setLogoSVG(String logoSVG) {
|
||||
_logoSVG = logoSVG;
|
||||
return this;
|
||||
}
|
||||
|
||||
void setSizeLogo(double? size) {
|
||||
_sizeLogo = size;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (!arrangedByHorizontal) {
|
||||
return Column(children: [
|
||||
_logoApp(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 16, left: 16, right: 16),
|
||||
child: Text(_text ?? '', key: _key, style: _textStyle, textAlign: _textAlign),
|
||||
),
|
||||
],
|
||||
);
|
||||
]);
|
||||
} else {
|
||||
return Row(children: [
|
||||
_logoApp(),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(_text ?? '', key: _key, style: _textStyle, textAlign: _textAlign),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _logoApp() {
|
||||
if (_logoSVG != null) {
|
||||
return SvgPicture.asset(_logoSVG!, width: 150, height: 150);
|
||||
return SvgPicture.asset(_logoSVG!, width: _sizeLogo ?? 150, height: _sizeLogo ?? 150);
|
||||
} else if (_logo != null) {
|
||||
return Image(
|
||||
image: AssetImage(_logo!),
|
||||
fit: BoxFit.fill,
|
||||
width: 150,
|
||||
height: 150,
|
||||
width: _sizeLogo ?? 150,
|
||||
height: _sizeLogo ?? 150,
|
||||
alignment: Alignment.center);
|
||||
}
|
||||
return SizedBox.shrink();
|
||||
|
||||
@@ -55,11 +55,11 @@ class LoginView extends GetWidget<LoginController> {
|
||||
}
|
||||
|
||||
Widget _buildSlogan(BuildContext context) {
|
||||
return SloganBuilder()
|
||||
.setSloganText(AppLocalizations.of(context).login_text_slogan)
|
||||
.setSloganTextAlign(TextAlign.center)
|
||||
.setSloganTextStyle(TextStyle(color: AppColor.primaryColor, fontSize: 16, fontWeight: FontWeight.w700))
|
||||
.setLogo(imagePaths.icLogoTMail)
|
||||
return (SloganBuilder()
|
||||
..setSloganText(AppLocalizations.of(context).login_text_slogan)
|
||||
..setSloganTextAlign(TextAlign.center)
|
||||
..setSloganTextStyle(TextStyle(color: AppColor.primaryColor, fontSize: 16, fontWeight: FontWeight.w700))
|
||||
..setLogo(imagePaths.icLogoTMail))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,52 +10,65 @@ import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_fold
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_tile_builder.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget_builder.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_bar_thread_view_widget.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class MailboxView extends GetWidget<MailboxController> {
|
||||
|
||||
final imagePaths = Get.find<ImagePaths>();
|
||||
final responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _buildBodyMailbox(context);
|
||||
}
|
||||
|
||||
Widget _buildBodyMailbox(BuildContext context) {
|
||||
return SafeArea(
|
||||
top: responsiveUtils.isMobile(context) ? true : false,
|
||||
bottom: false,
|
||||
left: false,
|
||||
right: false,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(responsiveUtils.isMobile(context) ? 14 : 0),
|
||||
topLeft: Radius.circular(responsiveUtils.isMobile(context) ? 14 : 0)),
|
||||
child: Drawer(
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Column(
|
||||
children: [
|
||||
_buildHeaderMailbox(context),
|
||||
Obx(() => controller.isSearchActive() ? _buildInputSearchFormWidget(context) : SizedBox.shrink()),
|
||||
Expanded(child: Obx(() => Container(
|
||||
color: controller.isSearchActive() ? Colors.white : AppColor.colorBgMailbox,
|
||||
child: RefreshIndicator(
|
||||
color: AppColor.primaryColor,
|
||||
onRefresh: () async => controller.refreshAllMailbox(),
|
||||
child: controller.isSearchActive()
|
||||
? _buildListMailboxSearched(context, controller.listMailboxSearched)
|
||||
: _buildListMailbox(context)),
|
||||
))),
|
||||
Obx(() => controller.isSelectionEnabled()
|
||||
? Column(children: [
|
||||
top: _responsiveUtils.isMobile(context) ? true : false,
|
||||
bottom: false,
|
||||
left: false,
|
||||
right: false,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(_responsiveUtils.isMobile(context) ? 14 : 0),
|
||||
topLeft: Radius.circular(_responsiveUtils.isMobile(context) ? 14 : 0)),
|
||||
child: Drawer(
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Column(
|
||||
children: [
|
||||
if (_responsiveUtils.isDesktop(context))
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 20, top: 30),
|
||||
child: (SloganBuilder(arrangedByHorizontal: true)
|
||||
..setSloganText(AppLocalizations.of(context).app_name)
|
||||
..setSloganTextAlign(TextAlign.center)
|
||||
..setSloganTextStyle(TextStyle(color: Colors.black, fontSize: 25, fontWeight: FontWeight.bold))
|
||||
..setSizeLogo(28)
|
||||
..setLogo(_imagePaths.icLogoTMail))
|
||||
.build()),
|
||||
_buildHeaderMailbox(context),
|
||||
Obx(() => controller.isSearchActive() ? _buildInputSearchFormWidget(context) : SizedBox.shrink()),
|
||||
Expanded(child: Obx(() => Container(
|
||||
color: controller.isSearchActive() ? Colors.white : AppColor.colorBgMailbox,
|
||||
child: RefreshIndicator(
|
||||
color: AppColor.primaryColor,
|
||||
onRefresh: () async => controller.refreshAllMailbox(),
|
||||
child: controller.isSearchActive()
|
||||
? _buildListMailboxSearched(context, controller.listMailboxSearched)
|
||||
: _buildListMailbox(context)),
|
||||
))),
|
||||
Obx(() => controller.isSelectionEnabled()
|
||||
? Column(children: [
|
||||
Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2),
|
||||
_buildOptionSelectionBottomBar(context)
|
||||
])
|
||||
: SizedBox.shrink()),
|
||||
]
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink()),
|
||||
]
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -66,10 +79,10 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: responsiveUtils.isMobile(context) ? 14 : 30,
|
||||
top: _responsiveUtils.isMobile(context) ? 14 : 30,
|
||||
bottom: 10),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
!responsiveUtils.isDesktop(context) ? _buildCloseScreenButton(context) : SizedBox(width: 50),
|
||||
!_responsiveUtils.isDesktop(context) ? _buildCloseScreenButton(context) : SizedBox(width: 50),
|
||||
Obx(() {
|
||||
if (controller.isSearchActive()) {
|
||||
return controller.listMailboxSearched.isNotEmpty
|
||||
@@ -105,7 +118,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
child: IconButton(
|
||||
key: Key('mailbox_close_button'),
|
||||
onPressed: () => controller.closeMailboxScreen(context),
|
||||
icon: SvgPicture.asset(imagePaths.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill)));
|
||||
icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill)));
|
||||
}
|
||||
|
||||
Widget _buildAddNewFolderButton(BuildContext context) {
|
||||
@@ -114,7 +127,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
child: IconButton(
|
||||
key: Key('create_new_mailbox_button'),
|
||||
onPressed: () => controller.goToCreateNewMailboxView(),
|
||||
icon: SvgPicture.asset(imagePaths.icAddNewFolder, width: 30, height: 30, fit: BoxFit.fill)));
|
||||
icon: SvgPicture.asset(_imagePaths.icAddNewFolder, width: 30, height: 30, fit: BoxFit.fill)));
|
||||
}
|
||||
|
||||
Widget _buildEditMailboxButton(BuildContext context, bool isSelectionEnabled) {
|
||||
@@ -136,7 +149,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(left: 16, top: 8.0, right: 16),
|
||||
child: Obx(() => (UserInformationWidgetBuilder(
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
context,
|
||||
controller.mailboxDashBoardController.userProfile.value)
|
||||
..addOnLogoutAction(() => controller.logoutAction()))
|
||||
@@ -145,8 +158,8 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
|
||||
Widget _buildSearchBarWidget(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 12),
|
||||
child: (SearchBarThreadViewWidget(imagePaths)
|
||||
padding: EdgeInsets.only(top: 12, bottom: 16, left: 16, right: 16),
|
||||
child: (SearchBarView(_imagePaths)
|
||||
..hintTextSearch(AppLocalizations.of(context).hint_search_mailboxes)
|
||||
..addOnOpenSearchViewAction(() => controller.enableSearch()))
|
||||
.build());
|
||||
@@ -172,10 +185,10 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
Obx(() => (controller.isSelectionEnabled() && responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context))
|
||||
Obx(() => (controller.isSelectionEnabled() && _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context))
|
||||
? SizedBox.shrink()
|
||||
: _buildUserInformationWidget(context)),
|
||||
Obx(() => (controller.isSelectionEnabled() && responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context))
|
||||
Obx(() => (controller.isSelectionEnabled() && _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context))
|
||||
? SizedBox.shrink()
|
||||
: _buildLineSpaceUserInformation()),
|
||||
_buildSearchBarWidget(context),
|
||||
@@ -253,7 +266,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
|
||||
parent: Obx(() => (MailBoxFolderTileBuilder(
|
||||
context,
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
mailboxNode,
|
||||
allSelectMode: controller.currentSelectMode.value)
|
||||
..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item))
|
||||
@@ -266,7 +279,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
padding: EdgeInsets.only(left: 16),
|
||||
child: Obx(() => (MailBoxFolderTileBuilder(
|
||||
context,
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
mailboxNode,
|
||||
allSelectMode: controller.currentSelectMode.value)
|
||||
..addOnOpenMailboxFolderClick((mailboxNode) => controller.openMailbox(context, mailboxNode.item))
|
||||
@@ -284,7 +297,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
children: [
|
||||
_buildBackSearchButton(context),
|
||||
Expanded(child: (SearchAppBarWidget(
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
controller.searchQuery.value,
|
||||
controller.searchFocus,
|
||||
controller.searchInputController,
|
||||
@@ -293,7 +306,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
..addPadding(EdgeInsets.zero)
|
||||
..setMargin(EdgeInsets.only(right: 16))
|
||||
..addDecoration(BoxDecoration(borderRadius: BorderRadius.circular(12), color: AppColor.colorBgSearchBar))
|
||||
..addIconClearText(SvgPicture.asset(imagePaths.icClearTextSearch, width: 20, height: 20, fit: BoxFit.fill))
|
||||
..addIconClearText(SvgPicture.asset(_imagePaths.icClearTextSearch, width: 20, height: 20, fit: BoxFit.fill))
|
||||
..setHintText(AppLocalizations.of(context).hint_search_mailboxes)
|
||||
..addOnClearTextSearchAction(() => controller.clearSearchText())
|
||||
..addOnTextChangeSearchAction((query) => controller.searchMailbox(query))
|
||||
@@ -313,7 +326,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
child: IconButton(
|
||||
color: AppColor.colorTextButton,
|
||||
icon: SvgPicture.asset(
|
||||
imagePaths.icBack,
|
||||
_imagePaths.icBack,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: AppColor.colorTextButton,
|
||||
@@ -332,7 +345,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
primary: false,
|
||||
itemBuilder: (context, index) =>
|
||||
Obx(() => (MailboxTileBuilder(
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
listMailbox[index],
|
||||
isSearchActive: controller.isSearchActive(),
|
||||
allSelectMode: controller.currentSelectMode.value,
|
||||
@@ -347,7 +360,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
padding: EdgeInsets.only(bottom: 30, top: 5),
|
||||
child: (BottomBarSelectionMailboxWidget(
|
||||
context,
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
controller.listMailboxSelected)
|
||||
..addOnMailboxActionsClick((actions, listMailboxSelected) =>
|
||||
controller.pressMailboxSelectionAction(context, actions, listMailboxSelected)))
|
||||
|
||||
@@ -38,9 +38,7 @@ class UserInformationWidgetBuilder {
|
||||
..textColor(Colors.black)
|
||||
..addBoxShadows([BoxShadow(
|
||||
color: AppColor.colorShadowBgContentEmail,
|
||||
spreadRadius: 2,
|
||||
blurRadius: 2,
|
||||
offset: Offset(0, 1))])
|
||||
spreadRadius: 1, blurRadius: 1, offset: Offset(0, 0.5))])
|
||||
..size(GetPlatform.isWeb ? 48 : 56))
|
||||
.build(),
|
||||
Expanded(child: Column(
|
||||
|
||||
@@ -60,6 +60,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
log('MailboxDashBoardController::onReady()');
|
||||
dispatchRoute(AppRoutes.THREAD);
|
||||
_setSessionCurrent();
|
||||
_getUserProfile();
|
||||
}
|
||||
@@ -155,13 +156,11 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
|
||||
void setSelectedMailbox(PresentationMailbox? newPresentationMailbox) {
|
||||
selectedMailbox.value = newPresentationMailbox;
|
||||
dispatchRoute(AppRoutes.THREAD);
|
||||
}
|
||||
|
||||
void setNewFirstSelectedMailbox(PresentationMailbox? newPresentationMailbox) {
|
||||
selectedMailbox.firstRebuild = true;
|
||||
selectedMailbox.value = newPresentationMailbox;
|
||||
dispatchRoute(AppRoutes.THREAD);
|
||||
}
|
||||
|
||||
void setSelectedEmail(PresentationEmail? newPresentationEmail) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/caching/state_cache_client.dart';
|
||||
@@ -43,15 +42,10 @@ class ThreadBindings extends BaseBindings {
|
||||
|
||||
@override
|
||||
void bindingsController() {
|
||||
Get.lazyPut(() => ScrollController());
|
||||
Get.put(ThreadController(
|
||||
Get.find<ResponsiveUtils>(),
|
||||
Get.find<GetEmailsInMailboxInteractor>(),
|
||||
Get.find<RefreshAllEmailsInMailboxInteractor>(),
|
||||
Get.find<ScrollController>(),
|
||||
Get.find<MarkAsMultipleEmailReadInteractor>(),
|
||||
Get.find<AppToast>(),
|
||||
Get.find<ImagePaths>(),
|
||||
Get.find<MoveMultipleEmailToMailboxInteractor>(),
|
||||
Get.find<MarkAsStarEmailInteractor>(),
|
||||
Get.find<MarkAsStarMultipleEmailInteractor>(),
|
||||
|
||||
@@ -55,13 +55,13 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
class ThreadController extends BaseController {
|
||||
|
||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final _appToast = Get.find<AppToast>();
|
||||
|
||||
final GetEmailsInMailboxInteractor _getEmailsInMailboxInteractor;
|
||||
final RefreshAllEmailsInMailboxInteractor _refreshAllEmailsInMailboxInteractor;
|
||||
final MarkAsMultipleEmailReadInteractor _markAsMultipleEmailReadInteractor;
|
||||
final AppToast _appToast;
|
||||
final ResponsiveUtils responsiveUtils;
|
||||
final ImagePaths _imagePaths;
|
||||
final ScrollController listEmailController;
|
||||
final MoveMultipleEmailToMailboxInteractor _moveMultipleEmailToMailboxInteractor;
|
||||
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
|
||||
final MarkAsStarMultipleEmailInteractor _markAsStarMultipleEmailInteractor;
|
||||
@@ -81,6 +81,7 @@ class ThreadController extends BaseController {
|
||||
get isLoadingMore => _isLoadingMore;
|
||||
MailboxId? _currentMailboxId;
|
||||
jmap.State? _currentEmailState;
|
||||
final ScrollController listEmailController = ScrollController();
|
||||
|
||||
SearchQuery? get searchQuery => mailboxDashBoardController.searchQuery;
|
||||
|
||||
@@ -91,13 +92,9 @@ class ThreadController extends BaseController {
|
||||
AccountId? get _accountId => mailboxDashBoardController.accountId.value;
|
||||
|
||||
ThreadController(
|
||||
this.responsiveUtils,
|
||||
this._getEmailsInMailboxInteractor,
|
||||
this._refreshAllEmailsInMailboxInteractor,
|
||||
this.listEmailController,
|
||||
this._markAsMultipleEmailReadInteractor,
|
||||
this._appToast,
|
||||
this._imagePaths,
|
||||
this._moveMultipleEmailToMailboxInteractor,
|
||||
this._markAsStarEmailInteractor,
|
||||
this._markAsStarMultipleEmailInteractor,
|
||||
@@ -360,7 +357,7 @@ class ThreadController extends BaseController {
|
||||
|
||||
void previewEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
|
||||
mailboxDashBoardController.setSelectedEmail(presentationEmailSelected);
|
||||
if (responsiveUtils.isDesktop(context) || responsiveUtils.isTabletLarge(context)) {
|
||||
if (_responsiveUtils.isDesktop(context) || _responsiveUtils.isTabletLarge(context)) {
|
||||
mailboxDashBoardController.dispatchRoute(AppRoutes.EMAIL);
|
||||
} else {
|
||||
goToEmail(context);
|
||||
|
||||
@@ -12,14 +12,13 @@ import 'package:tmail_ui_user/features/thread/presentation/widgets/bottom_bar_th
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/filter_message_cupertino_action_sheet_action_builder.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_bar_thread_view_widget.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/suggestion_box_widget.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class ThreadView extends GetWidget<ThreadController> {
|
||||
|
||||
final responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final imagePaths = Get.find<ImagePaths>();
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -27,63 +26,72 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
backgroundColor: Colors.white,
|
||||
backgroundColor: _responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white,
|
||||
body: SafeArea(
|
||||
right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
|
||||
left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.zero,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
right: _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context),
|
||||
left: _responsiveUtils.isMobileDevice(context) && _responsiveUtils.isLandscape(context),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildAppBarThread(context),
|
||||
Obx(() => !controller.isSearchActive()
|
||||
? (SearchBarThreadViewWidget(imagePaths)
|
||||
..hintTextSearch(AppLocalizations.of(context).hint_search_emails)
|
||||
..addOnOpenSearchViewAction(() => controller.enableSearch(context)))
|
||||
.build()
|
||||
: SizedBox.shrink()),
|
||||
Expanded(child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.zero,
|
||||
if (_responsiveUtils.isDesktop(context))
|
||||
Container(
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildStatusResultSearch(context),
|
||||
_buildLoadingView(),
|
||||
Expanded(child: _buildListEmail(context)),
|
||||
_buildLoadingViewLoadMore()
|
||||
]
|
||||
)
|
||||
),
|
||||
_buildSuggestionBox(context)
|
||||
],
|
||||
)),
|
||||
padding: EdgeInsets.only(right: 10, top: 16, bottom: 10),
|
||||
child: _buildHeader(context)),
|
||||
Obx(() => controller.isSearchActive()
|
||||
? _buildSearchForm(context)
|
||||
: _responsiveUtils.isDesktop(context) ? SizedBox.shrink() : _buildAppBarNormal(context)),
|
||||
Obx(() => !controller.isSearchActive() && !_responsiveUtils.isDesktop(context)
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, bottom: 10),
|
||||
child: (SearchBarView(_imagePaths)
|
||||
..hintTextSearch(AppLocalizations.of(context).hint_search_emails)
|
||||
..addOnOpenSearchViewAction(() => controller.enableSearch(context)))
|
||||
.build())
|
||||
: SizedBox.shrink()),
|
||||
Expanded(child: Container(
|
||||
color: AppColor.colorBgDesktop,
|
||||
margin: _responsiveUtils.isDesktop(context) ? EdgeInsets.all(16) : EdgeInsets.zero,
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: _responsiveUtils.isDesktop(context) ? BorderRadius.circular(20) : null,
|
||||
border: _responsiveUtils.isDesktop(context) ? Border.all(color: AppColor.colorBorderBodyThread, width: 1) : null,
|
||||
color: Colors.white),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildStatusResultSearch(context),
|
||||
_buildLoadingView(),
|
||||
Expanded(child: _buildListEmail(context)),
|
||||
_buildLoadingViewLoadMore(),
|
||||
]
|
||||
)
|
||||
),
|
||||
_buildSuggestionBox(context)
|
||||
],
|
||||
))
|
||||
),
|
||||
Obx(() => controller.isSelectionEnabled()
|
||||
? Column(children: [
|
||||
Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2),
|
||||
_buildOptionSelectionBottomBar(context)
|
||||
])
|
||||
: SizedBox.shrink()),
|
||||
? Column(children: [
|
||||
Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2),
|
||||
_buildOptionSelectionBottomBar(context)
|
||||
])
|
||||
: SizedBox.shrink()),
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
floatingActionButton: Obx(() => !controller.isSearchActive() && !controller.isSelectionEnabled()
|
||||
? Container(
|
||||
padding: EdgeInsets.only(bottom: controller.isSelectionEnabled()
|
||||
? 80
|
||||
: responsiveUtils.isMobileDevice(context) ? 0 : 16),
|
||||
: _responsiveUtils.isMobileDevice(context) ? 0 : 16),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: ScrollingFloatingButtonAnimated(
|
||||
icon: SvgPicture.asset(imagePaths.icCompose, width: 20, height: 20, fit: BoxFit.fill),
|
||||
icon: SvgPicture.asset(_imagePaths.icCompose, width: 20, height: 20, fit: BoxFit.fill),
|
||||
text: Padding(
|
||||
padding: EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
@@ -101,15 +109,82 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppBarThread(BuildContext context) {
|
||||
return Obx(() {
|
||||
return Stack(
|
||||
children: [
|
||||
if (!controller.isSearchActive()) _buildAppBarNormal(context),
|
||||
if (controller.isSearchActive()) _buildSearchForm(context),
|
||||
],
|
||||
);
|
||||
});
|
||||
Widget _buildHeader(BuildContext context) {
|
||||
return Row(children: [
|
||||
(ButtonBuilder(_imagePaths.icRefresh)
|
||||
..key(Key('button_reload_thread'))
|
||||
..decoration(BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppColor.colorButtonHeaderThread))
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(16)
|
||||
..radiusSplash(10)
|
||||
..padding(EdgeInsets.symmetric(horizontal: 8, vertical: 8))
|
||||
..onPressActionClick(() => controller.refreshAllEmail()))
|
||||
.build(),
|
||||
SizedBox(width: 16),
|
||||
(ButtonBuilder(_imagePaths.icSelectAll)
|
||||
..key(Key('button_select_all'))
|
||||
..decoration(BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppColor.colorButtonHeaderThread))
|
||||
..paddingIcon(EdgeInsets.only(right: 8))
|
||||
..size(16)
|
||||
..radiusSplash(10)
|
||||
..padding(EdgeInsets.symmetric(horizontal: 12, vertical: 8))
|
||||
..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButtonHeaderThread))
|
||||
..onPressActionClick(() => controller.enableSelectionEmail())
|
||||
..text(AppLocalizations.of(context).select_all, isVertical: false))
|
||||
.build(),
|
||||
SizedBox(width: 16),
|
||||
(ButtonBuilder(_imagePaths.icMarkAllAsRead)
|
||||
..key(Key('button_mark_all_as_read'))
|
||||
..decoration(BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppColor.colorButtonHeaderThread))
|
||||
..paddingIcon(EdgeInsets.only(right: 8))
|
||||
..size(16)
|
||||
..padding(EdgeInsets.symmetric(horizontal: 12, vertical: 8))
|
||||
..radiusSplash(10)
|
||||
..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButtonHeaderThread))
|
||||
..onPressActionClick(() => {})
|
||||
..text(AppLocalizations.of(context).mark_all_as_read, isVertical: false))
|
||||
.build(),
|
||||
SizedBox(width: 16),
|
||||
(ButtonBuilder(_imagePaths.icFilterWeb)
|
||||
..key(Key('button_filter_messages'))
|
||||
..context(context)
|
||||
..decoration(BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppColor.colorButtonHeaderThread))
|
||||
..paddingIcon(EdgeInsets.only(right: 8))
|
||||
..size(16)
|
||||
..padding(EdgeInsets.symmetric(horizontal: 12, vertical: 8))
|
||||
..radiusSplash(10)
|
||||
..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButtonHeaderThread))
|
||||
..addIconAction(Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: SvgPicture.asset(_imagePaths.icArrowDown, fit: BoxFit.fill)))
|
||||
..addOnPressActionWithPositionClick((position) =>
|
||||
controller.openFilterMessagesForTablet(
|
||||
context,
|
||||
position,
|
||||
_popupMenuEmailActionTile(context, controller.filterMessageOption.value)))
|
||||
..text(AppLocalizations.of(context).filter_messages, isVertical: false))
|
||||
.build(),
|
||||
SizedBox(width: 16),
|
||||
Spacer(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: (SearchBarView(_imagePaths)
|
||||
..hintTextSearch(AppLocalizations.of(context).search_emails)
|
||||
..maxSizeWidth(240)
|
||||
..addOnOpenSearchViewAction(() => controller.enableSearch(context)))
|
||||
.build()),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: (AvatarBuilder()
|
||||
..text(controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '')
|
||||
..backgroundColor(Colors.white)
|
||||
..textColor(Colors.black)
|
||||
..addBoxShadows([BoxShadow(
|
||||
color: AppColor.colorShadowBgContentEmail,
|
||||
spreadRadius: 1, blurRadius: 1, offset: Offset(0, 0.5))])
|
||||
..size(48))
|
||||
.build()),
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildOptionSelectionBottomBar(BuildContext context) {
|
||||
@@ -117,8 +192,8 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
padding: EdgeInsets.all(10),
|
||||
child: (BottomBarThreadSelectionWidget(
|
||||
context,
|
||||
imagePaths,
|
||||
responsiveUtils,
|
||||
_imagePaths,
|
||||
_responsiveUtils,
|
||||
controller.getListEmailSelected())
|
||||
..addOnPressEmailSelectionActionClick((actionType, selectionEmail) =>
|
||||
controller.pressEmailSelectionAction(context, actionType, selectionEmail)))
|
||||
@@ -127,7 +202,7 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
|
||||
Widget _buildSearchForm(BuildContext context) {
|
||||
return (SearchAppBarWidget(
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
controller.searchQuery,
|
||||
controller.mailboxDashBoardController.searchFocus,
|
||||
controller.mailboxDashBoardController.searchInputController,
|
||||
@@ -145,8 +220,8 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
Widget _buildAppBarNormal(BuildContext context) {
|
||||
return (AppBarThreadWidgetBuilder(
|
||||
context,
|
||||
imagePaths,
|
||||
responsiveUtils,
|
||||
_imagePaths,
|
||||
_responsiveUtils,
|
||||
controller.mailboxDashBoardController.selectedMailbox.value,
|
||||
controller.getListEmailSelected(),
|
||||
controller.currentSelectMode.value,
|
||||
@@ -154,7 +229,7 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
..addOpenListMailboxActionClick(() => controller.openMailboxLeftMenu())
|
||||
..addOnEditThreadAction(() => controller.enableSelectionEmail())
|
||||
..addOnFilterEmailAction((filterMessageOption, position) =>
|
||||
responsiveUtils.isMobileDevice(context)
|
||||
_responsiveUtils.isMobileDevice(context)
|
||||
? controller.openFilterMessagesCupertinoActionSheet(
|
||||
context,
|
||||
_filterMessagesCupertinoActionTile(context, filterMessageOption),
|
||||
@@ -187,17 +262,17 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
Widget _filterMessageWithAttachmentsAction(BuildContext context, FilterMessageOption optionCurrent) {
|
||||
return (FilterMessageCupertinoActionSheetActionBuilder(
|
||||
Key('filter_attachment_action'),
|
||||
SvgPicture.asset(imagePaths.icAttachment, width: 28, height: 28, fit: BoxFit.fill, color: AppColor.colorTextButton),
|
||||
SvgPicture.asset(_imagePaths.icAttachment, width: 28, height: 28, fit: BoxFit.fill, color: AppColor.colorTextButton),
|
||||
AppLocalizations.of(context).with_attachments,
|
||||
FilterMessageOption.attachments,
|
||||
optionCurrent: optionCurrent,
|
||||
iconLeftPadding: responsiveUtils.isMobile(context)
|
||||
iconLeftPadding: _responsiveUtils.isMobile(context)
|
||||
? EdgeInsets.only(left: 12, right: 16)
|
||||
: EdgeInsets.only(right: 12),
|
||||
iconRightPadding: responsiveUtils.isMobile(context)
|
||||
iconRightPadding: _responsiveUtils.isMobile(context)
|
||||
? EdgeInsets.only(right: 12)
|
||||
: EdgeInsets.zero,
|
||||
actionSelected: SvgPicture.asset(imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
actionSelected: SvgPicture.asset(_imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
..onActionClick((option) => controller.filterMessagesAction(context, option)))
|
||||
.build();
|
||||
}
|
||||
@@ -205,17 +280,17 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
Widget _filterMessagesUnreadAction(BuildContext context, FilterMessageOption optionCurrent) {
|
||||
return (FilterMessageCupertinoActionSheetActionBuilder(
|
||||
Key('filter_unread_action'),
|
||||
SvgPicture.asset(imagePaths.icUnread, width: 28, height: 28, fit: BoxFit.fill),
|
||||
SvgPicture.asset(_imagePaths.icUnread, width: 28, height: 28, fit: BoxFit.fill),
|
||||
AppLocalizations.of(context).unread,
|
||||
FilterMessageOption.unread,
|
||||
optionCurrent: optionCurrent,
|
||||
iconLeftPadding: responsiveUtils.isMobile(context)
|
||||
iconLeftPadding: _responsiveUtils.isMobile(context)
|
||||
? EdgeInsets.only(left: 12, right: 16)
|
||||
: EdgeInsets.only(right: 12),
|
||||
iconRightPadding: responsiveUtils.isMobile(context)
|
||||
iconRightPadding: _responsiveUtils.isMobile(context)
|
||||
? EdgeInsets.only(right: 12)
|
||||
: EdgeInsets.zero,
|
||||
actionSelected: SvgPicture.asset(imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
actionSelected: SvgPicture.asset(_imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
..onActionClick((option) => controller.filterMessagesAction(context, option)))
|
||||
.build();
|
||||
}
|
||||
@@ -223,17 +298,17 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
Widget _filterMessageStarredAction(BuildContext context, FilterMessageOption optionCurrent) {
|
||||
return (FilterMessageCupertinoActionSheetActionBuilder(
|
||||
Key('filter_starred_action'),
|
||||
SvgPicture.asset(imagePaths.icStar, width: 28, height: 28, fit: BoxFit.fill),
|
||||
SvgPicture.asset(_imagePaths.icStar, width: 28, height: 28, fit: BoxFit.fill),
|
||||
AppLocalizations.of(context).starred,
|
||||
FilterMessageOption.starred,
|
||||
optionCurrent: optionCurrent,
|
||||
iconLeftPadding: responsiveUtils.isMobile(context)
|
||||
iconLeftPadding: _responsiveUtils.isMobile(context)
|
||||
? EdgeInsets.only(left: 12, right: 16)
|
||||
: EdgeInsets.only(right: 12),
|
||||
iconRightPadding: responsiveUtils.isMobile(context)
|
||||
iconRightPadding: _responsiveUtils.isMobile(context)
|
||||
? EdgeInsets.only(right: 12)
|
||||
: EdgeInsets.zero,
|
||||
actionSelected: SvgPicture.asset(imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
actionSelected: SvgPicture.asset(_imagePaths.icFilterSelected, fit: BoxFit.fill))
|
||||
..onActionClick((option) => controller.filterMessagesAction(context, option)))
|
||||
.build();
|
||||
}
|
||||
@@ -254,55 +329,46 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
(success) {
|
||||
if (controller.isSearchActive()) {
|
||||
return success is SearchingState
|
||||
? Center(child: Padding(
|
||||
padding: EdgeInsets.only(top: 16, bottom: 16),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(color: AppColor.primaryColor))))
|
||||
? Padding(padding: EdgeInsets.only(top: 16), child: _loadingWidget)
|
||||
: SizedBox.shrink();
|
||||
} else {
|
||||
return success is LoadingState
|
||||
? Center(child: Padding(
|
||||
padding: EdgeInsets.only(top: 16, bottom: 16),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(color: AppColor.primaryColor))))
|
||||
: SizedBox.shrink();
|
||||
? Padding(padding: EdgeInsets.only(top: 16), child: _loadingWidget)
|
||||
: SizedBox.shrink();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Widget get _loadingWidget {
|
||||
return Center(child: Padding(
|
||||
padding: EdgeInsets.zero,
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CupertinoActivityIndicator(color: AppColor.colorTextButton))));
|
||||
}
|
||||
|
||||
Widget _buildLoadingViewLoadMore() {
|
||||
return Obx(() => controller.viewState.value.fold(
|
||||
(failure) => SizedBox.shrink(),
|
||||
(success) {
|
||||
if (controller.isSearchActive()) {
|
||||
return success is SearchingMoreState
|
||||
? Center(child: Padding(
|
||||
padding: EdgeInsets.only(top: 16, bottom: 16),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(color: AppColor.primaryColor))))
|
||||
: SizedBox.shrink();
|
||||
? Padding(padding: EdgeInsets.only(bottom: 16), child: _loadingWidget)
|
||||
: SizedBox.shrink();
|
||||
} else {
|
||||
return success is LoadingMoreState
|
||||
? Center(child: Padding(
|
||||
padding: EdgeInsets.only(top: 16, bottom: 16),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(color: AppColor.primaryColor))))
|
||||
: SizedBox.shrink();
|
||||
? Padding(padding: EdgeInsets.only(bottom: 16), child: _loadingWidget)
|
||||
: SizedBox.shrink();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Widget _buildListEmail(BuildContext context) {
|
||||
return Container(
|
||||
margin: EdgeInsets.zero,
|
||||
margin: _responsiveUtils.isDesktop(context)
|
||||
? EdgeInsets.only(top: 16, bottom: 16)
|
||||
: EdgeInsets.zero,
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
alignment: Alignment.center,
|
||||
@@ -364,12 +430,10 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
child: ListView.builder(
|
||||
controller: controller.listEmailController,
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
padding: EdgeInsets.only(top: 16),
|
||||
key: Key('presentation_email_list'),
|
||||
itemCount: listPresentationEmail.length,
|
||||
itemBuilder: (context, index) => Obx(() => (EmailTileBuilder(
|
||||
context,
|
||||
imagePaths,
|
||||
listPresentationEmail[index],
|
||||
controller.mailboxDashBoardController.selectedMailbox.value?.role,
|
||||
controller.currentSelectMode.value,
|
||||
@@ -382,7 +446,8 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
controller.previewEmail(context, selectedEmail);
|
||||
}
|
||||
})
|
||||
..onSelectEmailAction((selectedEmail) => controller.selectEmail(context, selectedEmail)))
|
||||
..onSelectEmailAction((selectedEmail) => controller.selectEmail(context, selectedEmail))
|
||||
..addOnMarkAsStarActionClick((selectedEmail) => controller.markAsStarEmail(selectedEmail)))
|
||||
.build()),
|
||||
)
|
||||
);
|
||||
@@ -394,7 +459,7 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
(success) => !(success is LoadingState) && !(success is SearchingState)
|
||||
? (BackgroundWidgetBuilder(context)
|
||||
..key(Key('empty_email_background'))
|
||||
..image(SvgPicture.asset(imagePaths.icEmptyImageDefault, width: 120, height: 120, fit: BoxFit.fill))
|
||||
..image(SvgPicture.asset(_imagePaths.icEmptyImageDefault, width: 120, height: 120, fit: BoxFit.fill))
|
||||
..text(controller.isSearchActive()
|
||||
? AppLocalizations.of(context).no_emails_matching_your_search
|
||||
: AppLocalizations.of(context).no_emails))
|
||||
@@ -407,7 +472,7 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
return Obx(() => controller.mailboxDashBoardController.suggestionSearch.isNotEmpty
|
||||
? (SuggestionBoxWidget(
|
||||
context,
|
||||
imagePaths,
|
||||
_imagePaths,
|
||||
controller.mailboxDashBoardController.suggestionSearch)
|
||||
..addOnSelectedSuggestion((suggestion) =>
|
||||
controller.mailboxDashBoardController.searchEmail(context, suggestion)))
|
||||
@@ -423,8 +488,12 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
? Container(
|
||||
width: double.infinity,
|
||||
margin: EdgeInsets.zero,
|
||||
color: AppColor.bgStatusResultSearch,
|
||||
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: _responsiveUtils.isDesktop(context)
|
||||
? BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))
|
||||
: null,
|
||||
color: AppColor.bgStatusResultSearch),
|
||||
child: Text(
|
||||
AppLocalizations.of(context).results,
|
||||
style: TextStyle(color: AppColor.baseTextColor, fontSize: 14, fontWeight: FontWeight.w500),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -8,13 +9,17 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/model/search_status.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnOpenEmailActionClick = void Function(PresentationEmail selectedEmail);
|
||||
typedef OnSelectEmailActionClick = void Function(PresentationEmail selectedEmail);
|
||||
typedef OnMarkAsStarActionClick = void Function(PresentationEmail selectedEmail);
|
||||
|
||||
class EmailTileBuilder {
|
||||
|
||||
final ImagePaths _imagePaths;
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
final PresentationEmail _presentationEmail;
|
||||
final BuildContext _context;
|
||||
final SelectMode _selectModeAll;
|
||||
@@ -24,10 +29,10 @@ class EmailTileBuilder {
|
||||
|
||||
OnOpenEmailActionClick? _onOpenEmailActionClick;
|
||||
OnSelectEmailActionClick? _onSelectEmailActionClick;
|
||||
OnMarkAsStarActionClick? _onMarkAsStarActionClick;
|
||||
|
||||
EmailTileBuilder(
|
||||
this._context,
|
||||
this._imagePaths,
|
||||
this._presentationEmail,
|
||||
this._mailboxRole,
|
||||
this._selectModeAll,
|
||||
@@ -43,126 +48,124 @@ class EmailTileBuilder {
|
||||
_onSelectEmailActionClick = onSelectEmailActionClick;
|
||||
}
|
||||
|
||||
void addOnMarkAsStarActionClick(OnMarkAsStarActionClick onMarkAsStarActionClick) {
|
||||
_onMarkAsStarActionClick = onMarkAsStarActionClick;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return Theme(
|
||||
data: ThemeData(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent),
|
||||
child: Container(
|
||||
key: Key('thread_tile'),
|
||||
margin: EdgeInsets.zero,
|
||||
key: Key('thread_tile'),
|
||||
data: ThemeData(splashColor: Colors.transparent, highlightColor: Colors.transparent),
|
||||
child: ResponsiveWidget(
|
||||
responsiveUtils: _responsiveUtils,
|
||||
mobile: _buildListTile(),
|
||||
desktop: _buildListTileForDesktop(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListTile() {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.only(bottom: 10, left: 20, right: 6),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(0),
|
||||
color: Colors.white),
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: Column(children: [
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onTap: () => {
|
||||
if (_onOpenEmailActionClick != null) {
|
||||
_onOpenEmailActionClick!(_presentationEmail)
|
||||
}
|
||||
},
|
||||
onLongPress: () => {
|
||||
if (_onSelectEmailActionClick != null) {
|
||||
_onSelectEmailActionClick!(_presentationEmail)
|
||||
}
|
||||
},
|
||||
leading: Transform(
|
||||
transform: Matrix4.translationValues(-5.0, 0.0, 0.0),
|
||||
child: _buildAvatarIcon()),
|
||||
title: Transform(
|
||||
transform: Matrix4.translationValues(-8.0, 0.0, 0.0),
|
||||
child: Row(
|
||||
children: [
|
||||
if (_presentationEmail.isUnReadEmail())
|
||||
Padding(
|
||||
child: Column(children: [
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onTap: () => _onOpenEmailActionClick?.call(_presentationEmail),
|
||||
onLongPress: () => _onSelectEmailActionClick!.call(_presentationEmail),
|
||||
leading: Transform(
|
||||
transform: Matrix4.translationValues(-5.0, 0.0, 0.0),
|
||||
child: _buildAvatarIcon()),
|
||||
title: Transform(
|
||||
transform: Matrix4.translationValues(-8.0, 0.0, 0.0),
|
||||
child: Row(
|
||||
children: [
|
||||
if (_presentationEmail.isUnReadEmail())
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 5),
|
||||
child: SvgPicture.asset(_imagePaths.icUnreadStatus, width: 9, height: 9, fit: BoxFit.fill)),
|
||||
Expanded(
|
||||
child: _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty
|
||||
? RichTextBuilder(
|
||||
_getInformationSender(),
|
||||
'${_searchQuery!.value}',
|
||||
TextStyle(fontSize: 15, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600),
|
||||
TextStyle(fontSize: 15, color: AppColor.colorNameEmail, backgroundColor: AppColor.bgWordSearch, fontWeight: FontWeight.w600)).build()
|
||||
: Text(
|
||||
_getInformationSender(),
|
||||
maxLines: 1,
|
||||
overflow:TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 15, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600))
|
||||
),
|
||||
if (_presentationEmail.hasAttachment == true)
|
||||
Padding(
|
||||
Expanded(
|
||||
child: _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty
|
||||
? RichTextBuilder(
|
||||
_getInformationSender(),
|
||||
'${_searchQuery!.value}',
|
||||
TextStyle(fontSize: 15, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600),
|
||||
TextStyle(fontSize: 15, color: AppColor.colorNameEmail, backgroundColor: AppColor.bgWordSearch, fontWeight: FontWeight.w600)).build()
|
||||
: Text(
|
||||
_getInformationSender(),
|
||||
maxLines: 1,
|
||||
overflow:TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 15, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600))
|
||||
),
|
||||
if (_presentationEmail.hasAttachment == true)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: (ButtonBuilder(_imagePaths.icAttachment)
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(16))
|
||||
.build()),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 4, left: 8),
|
||||
child: Text(
|
||||
'${_presentationEmail.getReceivedAt(Localizations.localeOf(_context).toLanguageTag())}',
|
||||
maxLines: 1,
|
||||
overflow:TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail))),
|
||||
(ButtonBuilder(_imagePaths.icChevron)
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(16))
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(16))
|
||||
.build()),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 4, left: 8),
|
||||
child: Text(
|
||||
'${_presentationEmail.getReceivedAt(Localizations.localeOf(_context).toLanguageTag())}',
|
||||
maxLines: 1,
|
||||
overflow:TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail))),
|
||||
(ButtonBuilder(_imagePaths.icChevron)
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(16))
|
||||
.build(),
|
||||
],
|
||||
)
|
||||
),
|
||||
subtitle: Transform(
|
||||
transform: Matrix4.translationValues(-8.0, 8.0, 0.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(child: _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty
|
||||
? RichTextBuilder(
|
||||
'${_presentationEmail.getEmailTitle()}',
|
||||
'${_searchQuery!.value}',
|
||||
TextStyle(fontSize: 13, color: AppColor.colorNameEmail),
|
||||
TextStyle(fontSize: 13, backgroundColor: AppColor.bgWordSearch, color: AppColor.colorNameEmail)).build()
|
||||
: Text(
|
||||
'${_presentationEmail.getEmailTitle()}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorNameEmail))
|
||||
],
|
||||
)
|
||||
),
|
||||
subtitle: Transform(
|
||||
transform: Matrix4.translationValues(-8.0, 8.0, 0.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(child: _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty
|
||||
? RichTextBuilder(
|
||||
'${_presentationEmail.getEmailTitle()}',
|
||||
'${_searchQuery!.value}',
|
||||
TextStyle(fontSize: 13, color: AppColor.colorNameEmail),
|
||||
TextStyle(fontSize: 13, backgroundColor: AppColor.bgWordSearch, color: AppColor.colorNameEmail)).build()
|
||||
: Text(
|
||||
'${_presentationEmail.getEmailTitle()}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorNameEmail))
|
||||
),
|
||||
if (_searchStatus == SearchStatus.ACTIVE && _presentationEmail.mailboxName.isNotEmpty)
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 8),
|
||||
padding: EdgeInsets.only(left: 8, right: 8, top: 3, bottom: 3),
|
||||
constraints: BoxConstraints(maxWidth: 100),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: AppColor.backgroundCounterMailboxColor),
|
||||
child: Text(
|
||||
'${_presentationEmail.mailboxName}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 10, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold),
|
||||
)
|
||||
),
|
||||
if (_searchStatus == SearchStatus.ACTIVE && _presentationEmail.mailboxName.isNotEmpty)
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 8),
|
||||
padding: EdgeInsets.only(left: 8, right: 8, top: 3, bottom: 3),
|
||||
constraints: BoxConstraints(maxWidth: 100),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: AppColor.backgroundCounterMailboxColor),
|
||||
child: Text(
|
||||
'${_presentationEmail.mailboxName}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 10, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold),
|
||||
)
|
||||
),
|
||||
if (_presentationEmail.isFlaggedEmail() )
|
||||
(ButtonBuilder(_imagePaths.icStar)
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(15))
|
||||
.build(),
|
||||
],
|
||||
)),
|
||||
Padding(
|
||||
if (_presentationEmail.isFlaggedEmail() )
|
||||
(ButtonBuilder(_imagePaths.icStar)
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(15))
|
||||
.build(),
|
||||
],
|
||||
)),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: Row(children: [
|
||||
Expanded(child: _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty
|
||||
@@ -178,27 +181,124 @@ class EmailTileBuilder {
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail))
|
||||
),
|
||||
]))
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
Padding(
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 12, right: 12),
|
||||
child: Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2)),
|
||||
]),
|
||||
)
|
||||
)
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAvatarIcon() {
|
||||
Widget _buildListTileForDesktop() {
|
||||
return InkWell(
|
||||
onTap: () => _onOpenEmailActionClick?.call(_presentationEmail),
|
||||
onLongPress: () => _onSelectEmailActionClick?.call(_presentationEmail),
|
||||
child: Column(children: [
|
||||
Row(children: [
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 16, right: 16),
|
||||
alignment: Alignment.center,
|
||||
child: _presentationEmail.isUnReadEmail()
|
||||
? SvgPicture.asset(_imagePaths.icUnreadStatus, width: 9, height: 9, fit: BoxFit.fill)
|
||||
: SizedBox(width: 9)),
|
||||
buildIconWeb(
|
||||
icon: SvgPicture.asset(
|
||||
_presentationEmail.isFlaggedEmail() ? _imagePaths.icStar : _imagePaths.icUnStar,
|
||||
width: 20,
|
||||
height: 20,
|
||||
fit: BoxFit.fill),
|
||||
tooltip: _presentationEmail.isFlaggedEmail() ? AppLocalizations.of(_context).starred : AppLocalizations.of(_context).not_starred,
|
||||
onTap: () => _onMarkAsStarActionClick?.call(_presentationEmail)),
|
||||
SizedBox(width: 8),
|
||||
_buildAvatarIcon(
|
||||
iconSize: 32,
|
||||
iconSizeSelect: 32,
|
||||
textStyle: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white),
|
||||
paddingIconSelect: EdgeInsets.all(5)),
|
||||
SizedBox(width: 10),
|
||||
Container(width: 180, child: _isSearchEnabled
|
||||
? RichTextBuilder(
|
||||
_getInformationSender(),
|
||||
'${_searchQuery!.value}',
|
||||
TextStyle(fontSize: 15, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600),
|
||||
TextStyle(fontSize: 15, color: AppColor.colorNameEmail, backgroundColor: AppColor.bgWordSearch, fontWeight: FontWeight.w600)).build()
|
||||
: Text('${_getInformationSender()}',
|
||||
maxLines: 1,
|
||||
overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 15, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600)),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
Container(width: 150, child: _isSearchEnabled
|
||||
? RichTextBuilder(
|
||||
'${_presentationEmail.getEmailTitle()}',
|
||||
'${_searchQuery!.value}',
|
||||
TextStyle(fontSize: 13, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600),
|
||||
TextStyle(fontSize: 13, backgroundColor: AppColor.bgWordSearch, color: AppColor.colorNameEmail)).build()
|
||||
: Text('${_presentationEmail.getEmailTitle()}',
|
||||
maxLines: 1,
|
||||
overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorNameEmail, fontWeight: FontWeight.w600))
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Expanded(flex: 3, child: _isSearchEnabled
|
||||
? RichTextBuilder(
|
||||
'${_presentationEmail.getPartialContent()}',
|
||||
'${_searchQuery!.value}',
|
||||
TextStyle(fontSize: 13, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal),
|
||||
TextStyle(fontSize: 13, color: AppColor.colorContentEmail, backgroundColor: AppColor.bgWordSearch)).build()
|
||||
: Text('${_presentationEmail.getPartialContent()}',
|
||||
maxLines: 1,
|
||||
overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal))
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
if (_searchStatus == SearchStatus.ACTIVE && _presentationEmail.mailboxName.isNotEmpty)
|
||||
Container(
|
||||
margin: EdgeInsets.only(left: 8),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 3),
|
||||
constraints: BoxConstraints(maxWidth: 100),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppColor.backgroundCounterMailboxColor),
|
||||
child: Text('${_presentationEmail.mailboxName}',
|
||||
maxLines: 1,
|
||||
overflow: kIsWeb ? null: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 10, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold),
|
||||
)
|
||||
),
|
||||
if (_presentationEmail.hasAttachment == true)
|
||||
Padding(padding: EdgeInsets.only(left: 8),
|
||||
child: (ButtonBuilder(_imagePaths.icAttachment)
|
||||
..paddingIcon(EdgeInsets.zero)
|
||||
..size(16))
|
||||
.build()),
|
||||
Padding(padding: EdgeInsets.only(right: 20, left: 8),
|
||||
child: Text('${_presentationEmail.getReceivedAt(Localizations.localeOf(_context).toLanguageTag())}',
|
||||
maxLines: 1,
|
||||
overflow: kIsWeb ? null: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail))),
|
||||
]),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 10, bottom: 10, left: 70),
|
||||
child: Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2)),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAvatarIcon({
|
||||
double? iconSize,
|
||||
double? iconSizeSelect,
|
||||
EdgeInsets? paddingIconSelect,
|
||||
TextStyle? textStyle
|
||||
}) {
|
||||
if (_selectModeAll == SelectMode.ACTIVE) {
|
||||
return AnimatedSwitcher(
|
||||
duration: Duration(milliseconds: 600),
|
||||
transitionBuilder: _transitionBuilder,
|
||||
child: (IconBuilder(_presentationEmail.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected)
|
||||
..padding(EdgeInsets.all(14))
|
||||
..size(GetPlatform.isWeb ? 48 : 56)
|
||||
..padding(paddingIconSelect ?? EdgeInsets.all(14))
|
||||
..size(iconSize ?? (GetPlatform.isWeb ? 48 : 56))
|
||||
..addOnTapActionClick(() {
|
||||
if (_selectModeAll == SelectMode.ACTIVE && _onSelectEmailActionClick != null) {
|
||||
_onSelectEmailActionClick!(_presentationEmail);
|
||||
@@ -208,8 +308,9 @@ class EmailTileBuilder {
|
||||
} else {
|
||||
return (AvatarBuilder()
|
||||
..text('${_presentationEmail.getAvatarText()}')
|
||||
..size(GetPlatform.isWeb ? 48 : 56)
|
||||
..size(iconSize ?? (GetPlatform.isWeb ? 48 : 56))
|
||||
..textColor(Colors.white)
|
||||
..addTextStyle(textStyle)
|
||||
..avatarColor(_presentationEmail.avatarColors))
|
||||
.build();
|
||||
}
|
||||
@@ -240,4 +341,6 @@ class EmailTileBuilder {
|
||||
}
|
||||
return '${_presentationEmail.getSenderName()}';
|
||||
}
|
||||
|
||||
bool get _isSearchEnabled => _searchStatus == SearchStatus.ACTIVE && _searchQuery != null && _searchQuery!.value.isNotEmpty;
|
||||
}
|
||||
@@ -816,4 +816,43 @@ class AppLocalizations {
|
||||
name: 'message_confirm_send_email');
|
||||
}
|
||||
|
||||
String get app_name {
|
||||
return Intl.message(
|
||||
'Tmail',
|
||||
name: 'app_name');
|
||||
}
|
||||
|
||||
String get search_emails {
|
||||
return Intl.message(
|
||||
'Search emails',
|
||||
name: 'search_emails');
|
||||
}
|
||||
|
||||
String get select_all {
|
||||
return Intl.message(
|
||||
'Select all',
|
||||
name: 'select_all',
|
||||
);
|
||||
}
|
||||
|
||||
String get mark_all_as_read {
|
||||
return Intl.message(
|
||||
'Mark all as read',
|
||||
name: 'mark_all_as_read',
|
||||
);
|
||||
}
|
||||
|
||||
String get filter_messages {
|
||||
return Intl.message(
|
||||
'Filter messages',
|
||||
name: 'filter_messages',
|
||||
);
|
||||
}
|
||||
|
||||
String get not_starred {
|
||||
return Intl.message(
|
||||
'Not starred',
|
||||
name: 'not_starred'
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user