TF-295 Apply new UI for composer web browser
@@ -1,4 +0,0 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M13 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V9L13 2Z" stroke="#3840F7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M13 2V9H20" stroke="#3840F7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 544 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M17.3558 14.1983C17.7077 13.8473 18.2776 13.8479 18.6286 14.1998C18.9797 14.5517 18.979 15.1216 18.6271 15.4726L14.0643 20.0247C11.5536 22.5294 7.48776 22.5246 4.98298 20.0139C4.95572 19.9865 4.95572 19.9865 4.92868 19.9588C2.34868 17.3097 2.35833 13.0844 4.95042 10.4471L11.7862 3.49188C13.588 1.65866 16.5347 1.63314 18.3679 3.43489C18.407 3.47336 18.4455 3.51253 18.4833 3.55236L18.5148 3.58567C20.3243 5.49447 20.304 8.49133 18.4689 10.3755L11.5768 17.452C10.5166 18.5406 8.79579 18.6261 7.63278 17.6481L7.55711 17.5845C6.39786 16.6095 6.24841 14.8795 7.22332 13.7202C7.25904 13.6777 7.29605 13.6363 7.33428 13.5961L11.9727 8.71536C12.3151 8.35505 12.8847 8.34055 13.245 8.68296C13.6053 9.02537 13.6198 9.59503 13.2774 9.95534L8.63906 14.8361C8.62592 14.8499 8.6132 14.8641 8.60092 14.8787C8.26586 15.2772 8.31722 15.8718 8.71565 16.2068L8.79132 16.2705C9.23246 16.6415 9.88516 16.609 10.2873 16.1961L17.1795 9.11961C18.3404 7.92759 18.3532 6.03162 17.2085 4.82401L17.1769 4.79069C17.1538 4.76627 17.1302 4.74225 17.1062 4.71866C15.982 3.61374 14.1749 3.62939 13.07 4.75361L6.23418 11.7088C4.32817 13.6481 4.32107 16.755 6.2182 18.703C6.23766 18.7229 6.23766 18.7229 6.25728 18.7426C8.05994 20.5496 10.9861 20.553 12.793 18.7504L17.3558 14.1983Z" fill="#99A2AD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8.0056 6.82733C7.68016 6.50189 7.15252 6.50189 6.82709 6.82733C6.50165 7.15277 6.50165 7.6804 6.82709 8.00584L10.8212 11.9999L6.82709 15.994C6.50165 16.3194 6.50165 16.8471 6.82709 17.1725C7.15252 17.4979 7.68016 17.4979 8.0056 17.1725L11.9997 13.1784L15.9938 17.1725C16.3192 17.4979 16.8468 17.4979 17.1723 17.1725C17.4977 16.8471 17.4977 16.3194 17.1723 15.994L13.1782 11.9999L17.1723 8.00584C17.4977 7.6804 17.4977 7.15277 17.1723 6.82733C16.8468 6.50189 16.3192 6.50189 15.9938 6.82733L11.9997 10.8214L8.0056 6.82733Z" fill="#99A2AD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 653 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="13" height="12" viewBox="0 0 13 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path opacity="0.24" d="M6.66699 12C9.9807 12 12.667 9.31371 12.667 6C12.667 2.68629 9.9807 0 6.66699 0C3.35328 0 0.666992 2.68629 0.666992 6C0.666992 9.31371 3.35328 12 6.66699 12Z" fill="black"/>
|
||||||
|
<path d="M9.0352 3.6318C9.21093 3.80754 9.21093 4.09246 9.0352 4.2682L7.30349 6L9.0352 7.73181C9.19629 7.8929 9.20971 8.14574 9.07547 8.32212L9.0352 8.3682C8.85946 8.54394 8.57454 8.54394 8.3988 8.3682L6.66699 6.6365L4.93519 8.3682C4.75945 8.54394 4.47453 8.54394 4.29879 8.3682C4.12306 8.19247 4.12306 7.90754 4.29879 7.73181L6.03049 6L4.29879 4.2682C4.1377 4.10711 4.12428 3.85427 4.25852 3.67788L4.29879 3.6318C4.47453 3.45607 4.75945 3.45607 4.93519 3.6318L6.66699 5.3635L8.3988 3.6318C8.57454 3.45607 8.85946 3.45607 9.0352 3.6318Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 854 B |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5567 7.10185C13.0528 7.13286 13.4298 7.56015 13.3988 8.05624L12.8988 16.0562C12.8678 16.5523 12.4405 16.9294 11.9444 16.8983C11.4484 16.8673 11.0713 16.44 11.1023 15.944L11.6023 7.94396C11.6333 7.44787 12.0606 7.07085 12.5567 7.10185Z" fill="#959DAD"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.44445 7.10185C6.94836 7.13286 6.57133 7.56015 6.60234 8.05624L7.10234 16.0562C7.13334 16.5523 7.56064 16.9294 8.05673 16.8983C8.55281 16.8673 8.92984 16.44 8.89883 15.944L8.39883 7.94396C8.36783 7.44787 7.94053 7.07085 7.44445 7.10185Z" fill="#959DAD"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.00059 3.1001C0.50353 3.1001 0.100586 3.50304 0.100586 4.0001C0.100586 4.49715 0.50353 4.9001 1.00059 4.9001H2.18101L3.33564 17.2161C3.38098 17.6999 3.41978 18.1139 3.47866 18.4534C3.54079 18.8117 3.6356 19.1568 3.82955 19.4828C4.12375 19.9773 4.55842 20.3732 5.07825 20.6199C5.42094 20.7826 5.77339 20.8448 6.13588 20.8732C6.47946 20.9001 6.89528 20.9001 7.38125 20.9001H12.6199C13.1059 20.9001 13.5217 20.9001 13.8653 20.8732C14.2278 20.8448 14.5802 20.7826 14.9229 20.6199C15.4427 20.3732 15.8774 19.9773 16.1716 19.4828C16.3656 19.1568 16.4604 18.8117 16.5225 18.4534C16.5814 18.1139 16.6202 17.6999 16.6655 17.2161L17.8202 4.9001H19.0006C19.4976 4.9001 19.9006 4.49715 19.9006 4.0001C19.9006 3.50304 19.4976 3.1001 19.0006 3.1001H13.7962C13.3899 1.38008 11.8447 0.100098 10.0006 0.100098C8.15644 0.100098 6.61124 1.38008 6.20495 3.1001H1.00059ZM5.12466 17.0148C5.174 17.541 5.20681 17.8842 5.25219 18.1459C5.29568 18.3966 5.34007 18.5013 5.3765 18.5625C5.48809 18.7501 5.65297 18.9002 5.85014 18.9938C5.91452 19.0244 6.02283 19.0588 6.27655 19.0787C6.54136 19.0995 6.88605 19.1001 7.41462 19.1001H12.5866C13.1151 19.1001 13.4598 19.0995 13.7246 19.0787C13.9783 19.0588 14.0867 19.0244 14.151 18.9938C14.3482 18.9002 14.5131 18.7501 14.6247 18.5625C14.6611 18.5013 14.7055 18.3966 14.749 18.1459C14.7944 17.8842 14.8272 17.541 14.8765 17.0148L16.0123 4.9001H3.98891L5.12466 17.0148ZM10.0006 1.9001C9.16287 1.9001 8.43971 2.39061 8.10268 3.1001H11.8985C11.5615 2.39061 10.8383 1.9001 10.0006 1.9001Z" fill="#959DAD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,8 @@
|
|||||||
|
<svg width="29" height="38" viewBox="0 0 29 38" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M27.8914 10.7609L18.783 1.21875C18.2769 1.86935 17.2215 3.17056 17.048 3.17056C16.8312 3.17056 17.2649 7.07417 17.2649 7.29104C17.2649 7.46453 19.1444 10.5441 20.0842 12.0621L27.8914 10.7609Z"
|
||||||
|
fill="white" stroke="#E0E0E0" stroke-width="0.433735" stroke-linejoin="round" />
|
||||||
|
<path
|
||||||
|
d="M17.9157 1H2.73494C1.77676 1 1 1.77676 1 2.73494V35.2651C1 36.2232 1.77676 37 2.73494 37H26.3735C27.3317 37 28.1084 36.2232 28.1084 35.2651V11.6265C28.1084 10.6683 27.3317 9.89157 26.3735 9.89157H21.3855C20.4274 9.89157 19.6506 9.11481 19.6506 8.15663V2.73494C19.6506 1.77676 18.8738 1 17.9157 1Z"
|
||||||
|
fill="#FAFAFA" stroke="#E0E0E0" stroke-width="0.433735" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 792 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 4.9C14 4.40294 14.4029 4 14.9 4H19.1C19.5971 4 20 4.40294 20 4.9V9.10001C20 9.59706 19.5971 10 19.1 10C18.6029 10 18.2 9.59706 18.2 9.10001V7.07279L14.5364 10.7364C14.1849 11.0879 13.6151 11.0879 13.2636 10.7364C12.9121 10.3849 12.9121 9.81508 13.2636 9.46361L16.9272 5.8H14.9C14.4029 5.8 14 5.39706 14 4.9Z" fill="#99A2AD"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.7364 13.2636C11.0879 13.6151 11.0879 14.1849 10.7364 14.5364L7.07279 18.2H9.09818C9.59524 18.2 9.99818 18.6029 9.99818 19.1C9.99818 19.5971 9.59524 20 9.09818 20H4.9C4.40294 20 4 19.5971 4 19.1V14.9C4 14.403 4.40294 14 4.9 14C5.39706 14 5.8 14.403 5.8 14.9V16.9272L9.46361 13.2636C9.81508 12.9121 10.3849 12.9121 10.7364 13.2636Z" fill="#99A2AD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 883 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="4" y="18.5" width="16" height="1.5" rx="0.75" fill="#99A2AD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 175 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5.73868 15.7541C5.05303 17.609 4.62218 18.9122 4.44611 19.6638C3.89277 22.026 3.49042 22.5581 5.55279 21.4355C7.61516 20.3129 17.5994 14.7519 19.8269 13.516C22.7306 11.905 22.7694 12.0309 19.6711 10.3204C17.3114 9.0176 7.4442 3.60166 5.55279 2.53825C3.66138 1.47483 3.89277 1.94771 4.44611 4.30986C4.62446 5.07122 5.06157 6.38609 5.75745 8.25446C6.24415 9.56121 7.37624 10.5202 8.74523 10.7854L14.5097 11.9019C14.5639 11.9128 14.599 11.9655 14.5882 12.0196C14.5802 12.0592 14.5493 12.0901 14.5097 12.0981L8.73224 13.2136C7.3588 13.4788 6.22367 14.4421 5.73868 15.7541Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 698 B |
@@ -32,6 +32,7 @@ export 'presentation/views/text/rich_text_builder.dart';
|
|||||||
export 'presentation/views/responsive/responsive_widget.dart';
|
export 'presentation/views/responsive/responsive_widget.dart';
|
||||||
export 'presentation/views/list/tree_view.dart';
|
export 'presentation/views/list/tree_view.dart';
|
||||||
export 'presentation/views/button/button_builder.dart';
|
export 'presentation/views/button/button_builder.dart';
|
||||||
|
export 'presentation/views/button/icon_button_web.dart';
|
||||||
export 'presentation/views/image/avatar_builder.dart';
|
export 'presentation/views/image/avatar_builder.dart';
|
||||||
export 'presentation/views/list/sliver_grid_delegate_fixed_height.dart';
|
export 'presentation/views/list/sliver_grid_delegate_fixed_height.dart';
|
||||||
export 'presentation/views/text/text_form_field_builder.dart';
|
export 'presentation/views/text/text_form_field_builder.dart';
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ extension AppColor on Color {
|
|||||||
static const colorInputBorderCreateMailbox = Color(0x1F000000);
|
static const colorInputBorderCreateMailbox = Color(0x1F000000);
|
||||||
static const colorInputBackgroundErrorVerifyName = Color(0xFFFAEBEB);
|
static const colorInputBackgroundErrorVerifyName = Color(0xFFFAEBEB);
|
||||||
static const colorInputBackgroundCreateMailbox = Color(0xFFF2F3F5);
|
static const colorInputBackgroundCreateMailbox = Color(0xFFF2F3F5);
|
||||||
static const colorHintInputCreateMailbox= Color(0xFFA9B4C2);
|
static const colorHintInputCreateMailbox = Color(0xFFA9B4C2);
|
||||||
static const colorMessageConfirmDialog= Color(0xFF6D7885);
|
static const colorMessageConfirmDialog = Color(0xFF6D7885);
|
||||||
static const colorActionDeleteConfirmDialog= Color(0xFFE64646);
|
static const colorActionDeleteConfirmDialog = Color(0xFFE64646);
|
||||||
static const colorActionCancelDialog= Color(0xFF007AFF);
|
static const colorActionCancelDialog = Color(0xFF007AFF);
|
||||||
static const colorMessageDialog= Color(0xFF222222);
|
static const colorMessageDialog = Color(0xFF222222);
|
||||||
static const colorConfirmActionDialog= Color(0xFFF2F2F2);
|
static const colorConfirmActionDialog = Color(0xFFF2F2F2);
|
||||||
static const colorEmailAddress = Color(0xFF333333);
|
static const colorEmailAddress = Color(0xFF333333);
|
||||||
static const colorHintEmailAddressInput = Color(0x993C3C43);
|
static const colorHintEmailAddressInput = Color(0x993C3C43);
|
||||||
static const colorDividerComposer = Color(0xFFC6C6C8);
|
static const colorDividerComposer = Color(0xFFC6C6C8);
|
||||||
@@ -94,6 +94,10 @@ extension AppColor on Color {
|
|||||||
static const colorEmailAddressPrefix = Color(0xFF9AA7B6);
|
static const colorEmailAddressPrefix = Color(0xFF9AA7B6);
|
||||||
static const colorEmailAddressTag = Color(0x146D7885);
|
static const colorEmailAddressTag = Color(0x146D7885);
|
||||||
static const colorLineLeftEmailView = Color(0x2999A2AD);
|
static const colorLineLeftEmailView = Color(0x2999A2AD);
|
||||||
|
static const colorShadowComposer = Color(0x1F000000);
|
||||||
|
static const colorBottomBarComposer = Color(0x5CEBEDF0);
|
||||||
|
static const colorShadowComposerFullScreen = Color(0x33000000);
|
||||||
|
static const colorCancelButton = Color(0xFFF2F2F2);
|
||||||
|
|
||||||
static const mapGradientColor = [
|
static const mapGradientColor = [
|
||||||
[Color(0xFF21D4FD), Color(0xFFB721FF)],
|
[Color(0xFF21D4FD), Color(0xFFB721FF)],
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ class ImagePaths {
|
|||||||
String get icBack => _getImagePath('ic_back.svg');
|
String get icBack => _getImagePath('ic_back.svg');
|
||||||
String get icEyeDisable => _getImagePath('ic_eye_disable.svg');
|
String get icEyeDisable => _getImagePath('ic_eye_disable.svg');
|
||||||
String get icShare => _getImagePath('ic_share.svg');
|
String get icShare => _getImagePath('ic_share.svg');
|
||||||
String get icAttachmentFile => _getImagePath('ic_attachment_file.svg');
|
|
||||||
String get icMoreReceiver => _getImagePath('ic_more_receiver.svg');
|
String get icMoreReceiver => _getImagePath('ic_more_receiver.svg');
|
||||||
String get icComposerClose => _getImagePath('ic_composer_close.svg');
|
String get icComposerClose => _getImagePath('ic_composer_close.svg');
|
||||||
String get icComposerSend => _getImagePath('ic_composer_send.svg');
|
String get icComposerSend => _getImagePath('ic_composer_send.svg');
|
||||||
@@ -66,6 +65,14 @@ class ImagePaths {
|
|||||||
String get icDeleteEmail => _getImagePath('ic_delete_email.svg');
|
String get icDeleteEmail => _getImagePath('ic_delete_email.svg');
|
||||||
String get icNewMessage => _getImagePath('ic_new_message.svg');
|
String get icNewMessage => _getImagePath('ic_new_message.svg');
|
||||||
String get icUnreadStatus => _getImagePath('ic_unread_status.svg');
|
String get icUnreadStatus => _getImagePath('ic_unread_status.svg');
|
||||||
|
String get icAttachmentsComposer => _getImagePath('ic_attachments_composer.svg');
|
||||||
|
String get icCloseComposer => _getImagePath('ic_close_composer.svg');
|
||||||
|
String get icFullScreenComposer => _getImagePath('ic_fullscreen_composer.svg');
|
||||||
|
String get icMinimizeComposer => _getImagePath('ic_minimize_composer.svg');
|
||||||
|
String get icSendComposer => _getImagePath('ic_send_composer.svg');
|
||||||
|
String get icDeleteComposer => _getImagePath('ic_delete_composer.svg');
|
||||||
|
String get icFileAttachment => _getImagePath('ic_file_attachment.svg');
|
||||||
|
String get icDeleteAttachment => _getImagePath('ic_delete_attachment.svg');
|
||||||
|
|
||||||
String _getImagePath(String imageName) {
|
String _getImagePath(String imageName) {
|
||||||
return AssetsPaths.images + imageName;
|
return AssetsPaths.images + imageName;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ResponsiveUtils {
|
|||||||
final double desktopVerticalMargin = 120.0;
|
final double desktopVerticalMargin = 120.0;
|
||||||
final double desktopHorizontalMargin = 200.0;
|
final double desktopHorizontalMargin = 200.0;
|
||||||
|
|
||||||
bool isMobileDevice(BuildContext context) => MediaQuery.of(context).size.shortestSide < 600;
|
bool isMobileDevice(BuildContext context) => MediaQuery.of(context).size.shortestSide < minTabletWidth;
|
||||||
|
|
||||||
double getSizeWidthScreen(BuildContext context) => MediaQuery.of(context).size.width;
|
double getSizeWidthScreen(BuildContext context) => MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
|
|
||||||
typedef OnConfirmActionClick = void Function();
|
typedef OnConfirmActionClick = void Function();
|
||||||
typedef OnCancelActionClick = void Function();
|
typedef OnCancelActionClick = void Function();
|
||||||
@@ -15,6 +16,9 @@ class ConfirmationDialogActionSheetBuilder {
|
|||||||
String? _cancelText;
|
String? _cancelText;
|
||||||
OnConfirmActionClick?_onConfirmActionClick;
|
OnConfirmActionClick?_onConfirmActionClick;
|
||||||
OnCancelActionClick? _onCancelActionClick;
|
OnCancelActionClick? _onCancelActionClick;
|
||||||
|
TextStyle? _styleConfirmButton;
|
||||||
|
TextStyle? _styleCancelButton;
|
||||||
|
TextStyle? _styleMessage;
|
||||||
|
|
||||||
ConfirmationDialogActionSheetBuilder(this._context);
|
ConfirmationDialogActionSheetBuilder(this._context);
|
||||||
|
|
||||||
@@ -32,11 +36,23 @@ class ConfirmationDialogActionSheetBuilder {
|
|||||||
_messageText = message;
|
_messageText = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void styleMessage(TextStyle? style) {
|
||||||
|
_styleMessage = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void styleConfirmButton(TextStyle? style) {
|
||||||
|
_styleConfirmButton = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void styleCancelButton(TextStyle? style) {
|
||||||
|
_styleCancelButton = style;
|
||||||
|
}
|
||||||
|
|
||||||
void show() {
|
void show() {
|
||||||
showCupertinoModalPopup(
|
showCupertinoModalPopup(
|
||||||
context: _context,
|
context: _context,
|
||||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||||
builder: (context) => CupertinoActionSheet(
|
builder: (context) => PointerInterceptor(child: CupertinoActionSheet(
|
||||||
actions: [
|
actions: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 10),
|
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 10),
|
||||||
@@ -45,27 +61,27 @@ class ConfirmationDialogActionSheetBuilder {
|
|||||||
child: Text(
|
child: Text(
|
||||||
_messageText ?? '',
|
_messageText ?? '',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 14, color: AppColor.colorMessageConfirmDialog)),
|
style: _styleMessage ?? TextStyle(fontSize: 14, color: AppColor.colorMessageConfirmDialog)),
|
||||||
onPressed: () => {},
|
onPressed: () => {},
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: CupertinoActionSheetAction(
|
child: CupertinoActionSheetAction(
|
||||||
child: Text(
|
child: Text(
|
||||||
_confirmText ?? '',
|
_confirmText ?? '',
|
||||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20, color: AppColor.colorActionDeleteConfirmDialog)),
|
style: _styleConfirmButton ?? TextStyle(fontWeight: FontWeight.w500, fontSize: 20, color: AppColor.colorActionDeleteConfirmDialog)),
|
||||||
onPressed: () => _onConfirmActionClick?.call(),
|
onPressed: () => _onConfirmActionClick?.call(),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
cancelButton: CupertinoActionSheetAction(
|
cancelButton: CupertinoActionSheetAction(
|
||||||
child: Text(
|
child: Text(
|
||||||
_cancelText ?? '',
|
_cancelText ?? '',
|
||||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20, color: AppColor.colorActionCancelDialog)),
|
style: _styleCancelButton ?? TextStyle(fontWeight: FontWeight.w500, fontSize: 20, color: AppColor.colorActionCancelDialog)),
|
||||||
onPressed: () => _onCancelActionClick?.call(),
|
onPressed: () => _onCancelActionClick?.call(),
|
||||||
),
|
),
|
||||||
)
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
typedef IconWebCallback = void Function();
|
||||||
|
typedef IconWebHasPositionCallback = void Function(RelativeRect);
|
||||||
|
|
||||||
|
Widget buildIconWeb({
|
||||||
|
required Widget icon,
|
||||||
|
String? tooltip,
|
||||||
|
IconWebCallback? onTap,
|
||||||
|
EdgeInsets? iconPadding,
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildIconWebHasPosition(BuildContext context, {
|
||||||
|
required Widget icon,
|
||||||
|
String? tooltip,
|
||||||
|
IconWebHasPositionCallback? onTap
|
||||||
|
}) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTapDown: (detail) {
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
onTap?.call(position);
|
||||||
|
},
|
||||||
|
child: Tooltip(
|
||||||
|
message: tooltip,
|
||||||
|
child: icon,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -16,6 +16,13 @@ class ConfirmDialogBuilder {
|
|||||||
String _confirmText = '';
|
String _confirmText = '';
|
||||||
String _cancelText = '';
|
String _cancelText = '';
|
||||||
Widget? _iconWidget;
|
Widget? _iconWidget;
|
||||||
|
Color? _colorCancelButton;
|
||||||
|
Color? _colorConfirmButton;
|
||||||
|
TextStyle? _styleTextCancelButton;
|
||||||
|
TextStyle? _styleTextConfirmButton;
|
||||||
|
TextStyle? _styleTitle;
|
||||||
|
TextStyle? _styleContent;
|
||||||
|
double? _radiusButton;
|
||||||
|
|
||||||
OnConfirmButtonAction? _onConfirmButtonAction;
|
OnConfirmButtonAction? _onConfirmButtonAction;
|
||||||
OnCancelButtonAction? _onCancelButtonAction;
|
OnCancelButtonAction? _onCancelButtonAction;
|
||||||
@@ -39,6 +46,34 @@ class ConfirmDialogBuilder {
|
|||||||
_iconWidget = icon;
|
_iconWidget = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void colorCancelButton(Color? color) {
|
||||||
|
_colorCancelButton = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorConfirmButton(Color? color) {
|
||||||
|
_colorConfirmButton = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void styleTextCancelButton(TextStyle? style) {
|
||||||
|
_styleTextCancelButton = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void styleTextConfirmButton(TextStyle? style) {
|
||||||
|
_styleTextConfirmButton = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void styleTitle(TextStyle? style) {
|
||||||
|
_styleTitle = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void styleContent(TextStyle? style) {
|
||||||
|
_styleContent = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void radiusButton(double? radius) {
|
||||||
|
_radiusButton = radius;
|
||||||
|
}
|
||||||
|
|
||||||
void onConfirmButtonAction(String confirmText, OnConfirmButtonAction? onConfirmButtonAction) {
|
void onConfirmButtonAction(String confirmText, OnConfirmButtonAction? onConfirmButtonAction) {
|
||||||
_confirmText = confirmText;
|
_confirmText = confirmText;
|
||||||
_onConfirmButtonAction = onConfirmButtonAction;
|
_onConfirmButtonAction = onConfirmButtonAction;
|
||||||
@@ -66,52 +101,57 @@ class ConfirmDialogBuilder {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(16))),
|
borderRadius: BorderRadius.all(Radius.circular(16))),
|
||||||
child: Wrap(children: [
|
child: Wrap(children: [
|
||||||
Align(
|
if (_onCloseButtonAction != null)
|
||||||
alignment: Alignment.centerRight,
|
Align(
|
||||||
child: IconButton(
|
alignment: Alignment.centerRight,
|
||||||
padding: EdgeInsets.only(top: 16, right: 16),
|
child: IconButton(
|
||||||
onPressed: () => _onCloseButtonAction?.call(),
|
padding: EdgeInsets.only(top: 16, right: 16),
|
||||||
icon: SvgPicture.asset(_imagePath.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill))),
|
onPressed: () => _onCloseButtonAction?.call(),
|
||||||
|
icon: SvgPicture.asset(_imagePath.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill))),
|
||||||
if (_iconWidget != null)
|
if (_iconWidget != null)
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.only(top: 24),
|
margin: EdgeInsets.only(top: 24),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: _iconWidget,
|
child: _iconWidget,
|
||||||
),
|
),
|
||||||
Padding(
|
if (_title.isNotEmpty)
|
||||||
padding: EdgeInsets.only(top: 12),
|
Padding(
|
||||||
child: Center(
|
padding: EdgeInsets.only(top: 12),
|
||||||
child: Text(
|
child: Center(
|
||||||
_title,
|
child: Text(
|
||||||
textAlign: TextAlign.center,
|
_title,
|
||||||
style: TextStyle(fontSize: 20.0, color: AppColor.colorActionDeleteConfirmDialog, fontWeight: FontWeight.w500)
|
textAlign: TextAlign.center,
|
||||||
|
style: _styleTitle ?? TextStyle(fontSize: 20.0, color: AppColor.colorActionDeleteConfirmDialog, fontWeight: FontWeight.w500)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
),
|
if (_content.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(_content,
|
child: Text(_content,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 17.0, color: AppColor.colorMessageDialog)
|
style: _styleContent ?? TextStyle(fontSize: 17.0, color: AppColor.colorMessageDialog)
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(bottom: 16, left: 16, right: 16),
|
padding: EdgeInsets.only(bottom: 16, left: 16, right: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(child: _buildButton(
|
||||||
child: _buildButton(name: _cancelText, action: _onCancelButtonAction)
|
name: _cancelText,
|
||||||
),
|
bgColor: _colorCancelButton,
|
||||||
|
radius: _radiusButton,
|
||||||
|
textStyle: _styleTextCancelButton,
|
||||||
|
action: _onCancelButtonAction)),
|
||||||
SizedBox(width: 16),
|
SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(child: _buildButton(
|
||||||
child: _buildButton(
|
name: _confirmText,
|
||||||
name: _confirmText,
|
bgColor: _colorConfirmButton,
|
||||||
bgColor: AppColor.colorConfirmActionDialog,
|
radius: _radiusButton,
|
||||||
nameColor: AppColor.colorActionDeleteConfirmDialog,
|
textStyle: _styleTextConfirmButton,
|
||||||
action: _onConfirmButtonAction)
|
action: _onConfirmButtonAction))
|
||||||
)
|
|
||||||
]
|
]
|
||||||
))
|
))
|
||||||
])
|
])
|
||||||
@@ -120,7 +160,7 @@ class ConfirmDialogBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildButton({
|
Widget _buildButton({
|
||||||
String? name, Color? nameColor, Color? bgColor, Function? action
|
String? name, TextStyle? textStyle, Color? bgColor, double? radius, Function? action
|
||||||
}) {
|
}) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@@ -133,7 +173,7 @@ class ConfirmDialogBuilder {
|
|||||||
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||||
(Set<MaterialState> states) => bgColor ?? AppColor.colorTextButton),
|
(Set<MaterialState> states) => bgColor ?? AppColor.colorTextButton),
|
||||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(radius ?? 8),
|
||||||
side: BorderSide(width: 0, color: bgColor ?? AppColor.colorTextButton),
|
side: BorderSide(width: 0, color: bgColor ?? AppColor.colorTextButton),
|
||||||
)),
|
)),
|
||||||
padding: MaterialStateProperty.resolveWith<EdgeInsets>(
|
padding: MaterialStateProperty.resolveWith<EdgeInsets>(
|
||||||
@@ -141,7 +181,7 @@ class ConfirmDialogBuilder {
|
|||||||
elevation: MaterialStateProperty.resolveWith<double>((Set<MaterialState> states) => 0)),
|
elevation: MaterialStateProperty.resolveWith<double>((Set<MaterialState> states) => 0)),
|
||||||
child: Text(name ?? '',
|
child: Text(name ?? '',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: nameColor ?? Colors.white)),
|
style: textStyle ?? TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'dart:math';
|
|||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/views/html_viewer/html_viewer_controller_for_web.dart';
|
import 'package:core/presentation/views/html_viewer/html_viewer_controller_for_web.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'package:universal_html/html.dart' as html;
|
import 'package:universal_html/html.dart' as html;
|
||||||
import 'package:core/presentation/utils/shims/dart_ui.dart' as ui;
|
import 'package:core/presentation/utils/shims/dart_ui.dart' as ui;
|
||||||
@@ -221,10 +222,10 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
|
|||||||
future: webInit,
|
future: webInit,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
return HtmlElementView(
|
return PointerInterceptor(child: HtmlElementView(
|
||||||
key: ValueKey(htmlData),
|
key: ValueKey(htmlData),
|
||||||
viewType: createdViewId,
|
viewType: createdViewId,
|
||||||
);
|
));
|
||||||
} else {
|
} else {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ dependencies:
|
|||||||
|
|
||||||
http: 0.13.4
|
http: 0.13.4
|
||||||
|
|
||||||
|
pointer_interceptor: 0.9.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ class ComposerBindings extends BaseBindings {
|
|||||||
Get.find<GetAutoCompleteWithDeviceContactInteractor>(),
|
Get.find<GetAutoCompleteWithDeviceContactInteractor>(),
|
||||||
Get.find<AppToast>(),
|
Get.find<AppToast>(),
|
||||||
Get.find<ImagePaths>(),
|
Get.find<ImagePaths>(),
|
||||||
|
Get.find<ResponsiveUtils>(),
|
||||||
Get.find<Uuid>(),
|
Get.find<Uuid>(),
|
||||||
Get.find<DeviceInfoPlugin>(),
|
Get.find<DeviceInfoPlugin>(),
|
||||||
Get.find<LocalFilePickerInteractor>(),
|
Get.find<LocalFilePickerInteractor>(),
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
|
|||||||
import 'package:jmap_dart_client/jmap/mail/email/email_body_value.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_body_value.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/domain/model/auto_complete_pattern.dart';
|
import 'package:tmail_ui_user/features/composer/domain/model/auto_complete_pattern.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart';
|
import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart';
|
||||||
@@ -35,15 +37,16 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_inter
|
|||||||
import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_drafts_interactor.dart';
|
import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_drafts_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/domain/usecases/upload_mutiple_attachment_interactor.dart';
|
import 'package:tmail_ui_user/features/composer/domain/usecases/upload_mutiple_attachment_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart';
|
||||||
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
|
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
|
||||||
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
|
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class ComposerController extends BaseController {
|
class ComposerController extends BaseController {
|
||||||
@@ -51,11 +54,14 @@ class ComposerController extends BaseController {
|
|||||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||||
|
|
||||||
final expandMode = ExpandMode.COLLAPSE.obs;
|
final expandMode = ExpandMode.COLLAPSE.obs;
|
||||||
|
final expandModeAttachments = ExpandMode.EXPAND.obs;
|
||||||
final composerArguments = Rxn<ComposerArguments>();
|
final composerArguments = Rxn<ComposerArguments>();
|
||||||
final isEnableEmailSendButton = false.obs;
|
final isEnableEmailSendButton = false.obs;
|
||||||
final isInitialRecipient = false.obs;
|
final isInitialRecipient = false.obs;
|
||||||
final attachments = <Attachment>[].obs;
|
final attachments = <Attachment>[].obs;
|
||||||
final emailContents = <EmailContent>[].obs;
|
final emailContents = <EmailContent>[].obs;
|
||||||
|
final subjectEmail = Rxn<String>();
|
||||||
|
final screenDisplayMode = ScreenDisplayMode.normal.obs;
|
||||||
|
|
||||||
final SendEmailInteractor _sendEmailInteractor;
|
final SendEmailInteractor _sendEmailInteractor;
|
||||||
final SaveEmailAddressesInteractor _saveEmailAddressInteractor;
|
final SaveEmailAddressesInteractor _saveEmailAddressInteractor;
|
||||||
@@ -63,6 +69,7 @@ class ComposerController extends BaseController {
|
|||||||
final GetAutoCompleteWithDeviceContactInteractor _getAutoCompleteWithDeviceContactInteractor;
|
final GetAutoCompleteWithDeviceContactInteractor _getAutoCompleteWithDeviceContactInteractor;
|
||||||
final AppToast _appToast;
|
final AppToast _appToast;
|
||||||
final ImagePaths _imagePaths;
|
final ImagePaths _imagePaths;
|
||||||
|
final ResponsiveUtils responsiveUtils;
|
||||||
final Uuid _uuid;
|
final Uuid _uuid;
|
||||||
final LocalFilePickerInteractor _localFilePickerInteractor;
|
final LocalFilePickerInteractor _localFilePickerInteractor;
|
||||||
final UploadMultipleAttachmentInteractor _uploadMultipleAttachmentInteractor;
|
final UploadMultipleAttachmentInteractor _uploadMultipleAttachmentInteractor;
|
||||||
@@ -74,7 +81,6 @@ class ComposerController extends BaseController {
|
|||||||
List<EmailAddress> listToEmailAddress = <EmailAddress>[];
|
List<EmailAddress> listToEmailAddress = <EmailAddress>[];
|
||||||
List<EmailAddress> listCcEmailAddress = <EmailAddress>[];
|
List<EmailAddress> listCcEmailAddress = <EmailAddress>[];
|
||||||
List<EmailAddress> listBccEmailAddress = <EmailAddress>[];
|
List<EmailAddress> listBccEmailAddress = <EmailAddress>[];
|
||||||
String? _subjectEmail;
|
|
||||||
ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.localContact;
|
ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.localContact;
|
||||||
HtmlEditorApi? htmlEditorApi;
|
HtmlEditorApi? htmlEditorApi;
|
||||||
final HtmlEditorBrowser.HtmlEditorController htmlControllerBrowser = HtmlEditorBrowser.HtmlEditorController();
|
final HtmlEditorBrowser.HtmlEditorController htmlControllerBrowser = HtmlEditorBrowser.HtmlEditorController();
|
||||||
@@ -85,8 +91,13 @@ class ComposerController extends BaseController {
|
|||||||
final bccEmailAddressController = TextEditingController();
|
final bccEmailAddressController = TextEditingController();
|
||||||
|
|
||||||
List<Attachment> initialAttachments = <Attachment>[];
|
List<Attachment> initialAttachments = <Attachment>[];
|
||||||
|
String? _textEditor;
|
||||||
|
|
||||||
void setSubjectEmail(String subject) => _subjectEmail = subject;
|
void setTextEditor(String? text) => _textEditor = text;
|
||||||
|
|
||||||
|
String? get textEditor => _textEditor;
|
||||||
|
|
||||||
|
void setSubjectEmail(String subject) => subjectEmail.value = subject;
|
||||||
|
|
||||||
Future<String> _getEmailBodyText({bool onlyText = false}) async {
|
Future<String> _getEmailBodyText({bool onlyText = false}) async {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
@@ -107,6 +118,7 @@ class ComposerController extends BaseController {
|
|||||||
this._getAutoCompleteWithDeviceContactInteractor,
|
this._getAutoCompleteWithDeviceContactInteractor,
|
||||||
this._appToast,
|
this._appToast,
|
||||||
this._imagePaths,
|
this._imagePaths,
|
||||||
|
this.responsiveUtils,
|
||||||
this._uuid,
|
this._uuid,
|
||||||
this._deviceInfoPlugin,
|
this._deviceInfoPlugin,
|
||||||
this._localFilePickerInteractor,
|
this._localFilePickerInteractor,
|
||||||
@@ -178,7 +190,7 @@ class ComposerController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _initEmail() {
|
void _initEmail() {
|
||||||
final arguments = Get.arguments;
|
final arguments = kIsWeb ? mailboxDashBoardController.routerArguments : Get.arguments;
|
||||||
if (arguments is ComposerArguments) {
|
if (arguments is ComposerArguments) {
|
||||||
composerArguments.value = arguments;
|
composerArguments.value = arguments;
|
||||||
if (arguments.emailActionType == EmailActionType.edit) {
|
if (arguments.emailActionType == EmailActionType.edit) {
|
||||||
@@ -211,6 +223,14 @@ class ComposerController extends BaseController {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String? get initTextEditorComposer {
|
||||||
|
if (composerArguments.value?.emailActionType == EmailActionType.compose) {
|
||||||
|
return textEditor;
|
||||||
|
} else {
|
||||||
|
return textEditor ?? getContentEmail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Tuple2<String, String>? _getHeaderEmailQuoted(String locale, ComposerArguments arguments) {
|
Tuple2<String, String>? _getHeaderEmailQuoted(String locale, ComposerArguments arguments) {
|
||||||
if (arguments.presentationEmail != null) {
|
if (arguments.presentationEmail != null) {
|
||||||
final sentDate = arguments.presentationEmail?.sentAt;
|
final sentDate = arguments.presentationEmail?.sentAt;
|
||||||
@@ -226,8 +246,9 @@ class ComposerController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _initToEmailAddress(ComposerArguments arguments) {
|
void _initToEmailAddress(ComposerArguments arguments) {
|
||||||
if (arguments.presentationEmail != null) {
|
final userProfile = mailboxDashBoardController.userProfile.value;
|
||||||
final userEmailAddress = EmailAddress(null, arguments.userProfile.email);
|
if (arguments.presentationEmail != null && userProfile != null) {
|
||||||
|
final userEmailAddress = EmailAddress(null, userProfile.email);
|
||||||
|
|
||||||
final recipients = arguments.presentationEmail!.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole);
|
final recipients = arguments.presentationEmail!.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole);
|
||||||
|
|
||||||
@@ -302,12 +323,12 @@ class ComposerController extends BaseController {
|
|||||||
return emailQuotedHtml;
|
return emailQuotedHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Email> _generateEmail(ComposerArguments arguments, {bool asDrafts = false}) async {
|
Future<Email> _generateEmail(Map<Role, MailboxId> mapDefaultMailboxId, UserProfile userProfile, {bool asDrafts = false}) async {
|
||||||
final generateEmailId = EmailId(Id(_uuid.v1()));
|
final generateEmailId = EmailId(Id(_uuid.v1()));
|
||||||
final outboxMailboxId = arguments.mapMailboxId[PresentationMailbox.roleOutbox];
|
final outboxMailboxId = mapDefaultMailboxId[PresentationMailbox.roleOutbox];
|
||||||
final draftMailboxId = arguments.mapMailboxId[PresentationMailbox.roleDrafts];
|
final draftMailboxId = mapDefaultMailboxId[PresentationMailbox.roleDrafts];
|
||||||
final listFromEmailAddress = {
|
final listFromEmailAddress = {
|
||||||
EmailAddress(null, arguments.userProfile.email)
|
EmailAddress(null, userProfile.email)
|
||||||
};
|
};
|
||||||
final generatePartId = PartId(_uuid.v1());
|
final generatePartId = PartId(_uuid.v1());
|
||||||
final generateBlobId = Id(_uuid.v1());
|
final generateBlobId = Id(_uuid.v1());
|
||||||
@@ -323,7 +344,7 @@ class ComposerController extends BaseController {
|
|||||||
cc: listCcEmailAddress.toSet(),
|
cc: listCcEmailAddress.toSet(),
|
||||||
bcc: listBccEmailAddress.toSet(),
|
bcc: listBccEmailAddress.toSet(),
|
||||||
keywords: asDrafts ? {KeyWordIdentifier.emailDraft : true} : null,
|
keywords: asDrafts ? {KeyWordIdentifier.emailDraft : true} : null,
|
||||||
subject: _subjectEmail,
|
subject: subjectEmail.value,
|
||||||
htmlBody: {
|
htmlBody: {
|
||||||
EmailBodyPart(
|
EmailBodyPart(
|
||||||
partId: generatePartId,
|
partId: generatePartId,
|
||||||
@@ -363,30 +384,44 @@ class ComposerController extends BaseController {
|
|||||||
clearFocusEditor(context);
|
clearFocusEditor(context);
|
||||||
|
|
||||||
if (isEnableEmailSendButton.value) {
|
if (isEnableEmailSendButton.value) {
|
||||||
final arguments = composerArguments.value;
|
if (subjectEmail.value?.isNotEmpty == true) {
|
||||||
if (arguments != null) {
|
_handleSendMessages(context);
|
||||||
_saveEmailAddress();
|
} else {
|
||||||
|
_showConfirmDialogSendEmail(context);
|
||||||
final email = await _generateEmail(arguments);
|
|
||||||
final accountId = arguments.session.accounts.keys.first;
|
|
||||||
final sentMailboxId = arguments.mapMailboxId[PresentationMailbox.roleSent];
|
|
||||||
final submissionCreateId = Id(_uuid.v1());
|
|
||||||
|
|
||||||
mailboxDashBoardController.consumeState(_sendEmailInteractor.execute(
|
|
||||||
accountId,
|
|
||||||
EmailRequest(
|
|
||||||
email,
|
|
||||||
submissionCreateId,
|
|
||||||
mailboxIdSaved: sentMailboxId,
|
|
||||||
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit ? arguments.presentationEmail?.id : null)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
popBack();
|
|
||||||
} else {
|
} else {
|
||||||
_appToast.showErrorToast(AppLocalizations.of(context).your_email_should_have_at_least_one_recipient);
|
_appToast.showErrorToast(AppLocalizations.of(context).your_email_should_have_at_least_one_recipient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleSendMessages(BuildContext context) async {
|
||||||
|
final arguments = composerArguments.value;
|
||||||
|
final session = mailboxDashBoardController.sessionCurrent;
|
||||||
|
final mapDefaultMailboxId = mailboxDashBoardController.mapDefaultMailboxId;
|
||||||
|
final userProfile = mailboxDashBoardController.userProfile.value;
|
||||||
|
if (arguments != null && session != null && mapDefaultMailboxId.isNotEmpty && userProfile != null) {
|
||||||
|
_saveEmailAddress();
|
||||||
|
|
||||||
|
final email = await _generateEmail(mapDefaultMailboxId, userProfile);
|
||||||
|
final accountId = session.accounts.keys.first;
|
||||||
|
final sentMailboxId = mapDefaultMailboxId[PresentationMailbox.roleSent];
|
||||||
|
final submissionCreateId = Id(_uuid.v1());
|
||||||
|
|
||||||
|
mailboxDashBoardController.consumeState(_sendEmailInteractor.execute(
|
||||||
|
accountId,
|
||||||
|
EmailRequest(email, submissionCreateId, mailboxIdSaved: sentMailboxId,
|
||||||
|
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
|
||||||
|
? arguments.presentationEmail?.id
|
||||||
|
: null)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kIsWeb) {
|
||||||
|
closeComposerWeb();
|
||||||
|
} else {
|
||||||
|
popBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _saveEmailAddress() async {
|
void _saveEmailAddress() async {
|
||||||
final listEmailAddressCanSave = Set<EmailAddress>();
|
final listEmailAddressCanSave = Set<EmailAddress>();
|
||||||
listEmailAddressCanSave.addAll(listToEmailAddress + listCcEmailAddress + listBccEmailAddress);
|
listEmailAddressCanSave.addAll(listToEmailAddress + listCcEmailAddress + listBccEmailAddress);
|
||||||
@@ -460,10 +495,10 @@ class ComposerController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _uploadAttachmentsAction(List<FileInfo> pickedFiles) async {
|
void _uploadAttachmentsAction(List<FileInfo> pickedFiles) async {
|
||||||
if (composerArguments.value != null) {
|
final session = mailboxDashBoardController.sessionCurrent;
|
||||||
final accountId = composerArguments.value!.session.accounts.keys.first;
|
if (session != null) {
|
||||||
final uploadUrl = composerArguments.value!.session.getUploadUrl(accountId);
|
final accountId = session.accounts.keys.first;
|
||||||
|
final uploadUrl = session.getUploadUrl(accountId);
|
||||||
consumeState(_uploadMultipleAttachmentInteractor.execute(pickedFiles, accountId, uploadUrl));
|
consumeState(_uploadMultipleAttachmentInteractor.execute(pickedFiles, accountId, uploadUrl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,9 +543,9 @@ class ComposerController extends BaseController {
|
|||||||
final oldEmailBody = kIsWeb ? getContentEmail() : '\n${getContentEmail()}\n';
|
final oldEmailBody = kIsWeb ? getContentEmail() : '\n${getContentEmail()}\n';
|
||||||
final isEmailBodyChanged = !oldEmailBody.isSame(newEmailBody);
|
final isEmailBodyChanged = !oldEmailBody.isSame(newEmailBody);
|
||||||
|
|
||||||
final newEmailSubject = _subjectEmail;
|
final newEmailSubject = subjectEmail.value;
|
||||||
final subjectEmail = arguments.presentationEmail?.getEmailTitle().trim() ?? '';
|
final titleEmail = arguments.presentationEmail?.getEmailTitle().trim() ?? '';
|
||||||
final oldEmailSubject = arguments.emailActionType.getSubjectComposer(Get.context!, subjectEmail);
|
final oldEmailSubject = arguments.emailActionType.getSubjectComposer(Get.context!, titleEmail);
|
||||||
final isEmailSubjectChanged = !oldEmailSubject.isSame(newEmailSubject);
|
final isEmailSubjectChanged = !oldEmailSubject.isSame(newEmailSubject);
|
||||||
|
|
||||||
final recipients = arguments.presentationEmail
|
final recipients = arguments.presentationEmail
|
||||||
@@ -544,13 +579,18 @@ class ComposerController extends BaseController {
|
|||||||
clearFocusEditor(context);
|
clearFocusEditor(context);
|
||||||
|
|
||||||
final arguments = composerArguments.value;
|
final arguments = composerArguments.value;
|
||||||
if (arguments != null && Get.context != null) {
|
final mapDefaultMailboxId = mailboxDashBoardController.mapDefaultMailboxId;
|
||||||
|
final userProfile = mailboxDashBoardController.userProfile.value;
|
||||||
|
final session = mailboxDashBoardController.sessionCurrent;
|
||||||
|
|
||||||
|
if (arguments != null && Get.context != null && mapDefaultMailboxId.isNotEmpty
|
||||||
|
&& userProfile != null && session != null) {
|
||||||
final isChanged = await _isEmailChanged(arguments);
|
final isChanged = await _isEmailChanged(arguments);
|
||||||
if (isChanged) {
|
if (isChanged) {
|
||||||
_saveEmailAddress();
|
_saveEmailAddress();
|
||||||
|
|
||||||
final newEmail = await _generateEmail(arguments, asDrafts: true);
|
final newEmail = await _generateEmail(mapDefaultMailboxId, userProfile, asDrafts: true);
|
||||||
final accountId = arguments.session.accounts.keys.first;
|
final accountId = session.accounts.keys.first;
|
||||||
final oldEmail = arguments.presentationEmail;
|
final oldEmail = arguments.presentationEmail;
|
||||||
|
|
||||||
if (arguments.emailActionType == EmailActionType.edit && oldEmail != null) {
|
if (arguments.emailActionType == EmailActionType.edit && oldEmail != null) {
|
||||||
@@ -563,10 +603,10 @@ class ComposerController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _getEmailContentAction(ComposerArguments arguments) async {
|
void _getEmailContentAction(ComposerArguments arguments) async {
|
||||||
final baseDownloadUrl = arguments.session.getDownloadUrl();
|
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl();
|
||||||
final accountId = arguments.session.accounts.keys.first;
|
final accountId = mailboxDashBoardController.sessionCurrent?.accounts.keys.first;
|
||||||
final emailId = arguments.presentationEmail?.id;
|
final emailId = arguments.presentationEmail?.id;
|
||||||
if (emailId != null) {
|
if (emailId != null && baseDownloadUrl != null && accountId != null) {
|
||||||
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl));
|
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -594,7 +634,7 @@ class ComposerController extends BaseController {
|
|||||||
if (arguments.emailActionType == EmailActionType.edit) {
|
if (arguments.emailActionType == EmailActionType.edit) {
|
||||||
return arguments.presentationEmail?.from?.first.emailAddress ?? '';
|
return arguments.presentationEmail?.from?.first.emailAddress ?? '';
|
||||||
} else {
|
} else {
|
||||||
return arguments.userProfile.email;
|
return mailboxDashBoardController.userProfile.value?.email ?? '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@@ -603,6 +643,69 @@ class ComposerController extends BaseController {
|
|||||||
void clearFocusEditor(BuildContext context) {
|
void clearFocusEditor(BuildContext context) {
|
||||||
if (!kIsWeb) {
|
if (!kIsWeb) {
|
||||||
htmlEditorApi?.unfocus(context);
|
htmlEditorApi?.unfocus(context);
|
||||||
|
htmlControllerBrowser.clearFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void closeComposerWeb() {
|
||||||
|
mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.none);
|
||||||
|
}
|
||||||
|
|
||||||
|
void minimizeComposer() {
|
||||||
|
_updateTextForEditor();
|
||||||
|
final newDisplayMode = screenDisplayMode.value == ScreenDisplayMode.minimize ? ScreenDisplayMode.normal : ScreenDisplayMode.minimize;
|
||||||
|
screenDisplayMode.value = newDisplayMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFullScreenComposer() {
|
||||||
|
_updateTextForEditor();
|
||||||
|
final newDisplayMode = screenDisplayMode.value == ScreenDisplayMode.fullScreen ? ScreenDisplayMode.normal : ScreenDisplayMode.fullScreen;
|
||||||
|
screenDisplayMode.value = newDisplayMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateTextForEditor() async {
|
||||||
|
final textCurrent = await htmlControllerBrowser.getText();
|
||||||
|
log('_updateTextForEditor() | textCurrent: $textCurrent');
|
||||||
|
htmlControllerBrowser.insertHtml(textCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteComposer() {
|
||||||
|
mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.none);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleDisplayAttachments() {
|
||||||
|
final newExpandMode = expandModeAttachments.value == ExpandMode.COLLAPSE ? ExpandMode.EXPAND : ExpandMode.COLLAPSE;
|
||||||
|
expandModeAttachments.value = newExpandMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showConfirmDialogSendEmail(BuildContext context) {
|
||||||
|
if (responsiveUtils.isMobileDevice(context)) {
|
||||||
|
(ConfirmationDialogActionSheetBuilder(context)
|
||||||
|
..messageText(AppLocalizations.of(context).message_confirm_send_email)
|
||||||
|
..styleConfirmButton(TextStyle(fontSize: 20, fontWeight: FontWeight.normal, color: Colors.black))
|
||||||
|
..onCancelAction(AppLocalizations.of(context).cancel, () => popBack())
|
||||||
|
..onConfirmAction(AppLocalizations.of(context).send, () {
|
||||||
|
popBack();
|
||||||
|
_handleSendMessages(context);
|
||||||
|
})).show();
|
||||||
|
} else {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||||
|
builder: (BuildContext context) => PointerInterceptor(child: (ConfirmDialogBuilder(_imagePaths)
|
||||||
|
..key(Key('confirm_dialog_send_message'))
|
||||||
|
..content(AppLocalizations.of(context).message_confirm_send_email)
|
||||||
|
..colorConfirmButton(AppColor.colorTextButton)
|
||||||
|
..colorCancelButton(AppColor.colorCancelButton)
|
||||||
|
..styleContent(TextStyle(fontSize: 15, fontWeight: FontWeight.normal, color: AppColor.colorMessageDialog))
|
||||||
|
..styleTextCancelButton(TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorTextButton))
|
||||||
|
..styleTextConfirmButton(TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: Colors.white))
|
||||||
|
..onConfirmButtonAction(AppLocalizations.of(context).send, () {
|
||||||
|
popBack();
|
||||||
|
_handleSendMessages(context);
|
||||||
|
})
|
||||||
|
..onCancelButtonAction(AppLocalizations.of(context).cancel, () => popBack()))
|
||||||
|
.build()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,529 @@
|
|||||||
|
import 'package:core/core.dart';
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:filesize/filesize.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:html_editor_enhanced/html_editor.dart' as HtmlEditorBrowser;
|
||||||
|
import 'package:model/model.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
|
class ComposerView extends GetWidget<ComposerController> {
|
||||||
|
|
||||||
|
final responsiveUtils = Get.find<ResponsiveUtils>();
|
||||||
|
final imagePaths = Get.find<ImagePaths>();
|
||||||
|
final appToast = Get.find<AppToast>();
|
||||||
|
final keyboardUtils = Get.find<KeyboardUtils>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ResponsiveWidget(
|
||||||
|
responsiveUtils: responsiveUtils,
|
||||||
|
mobile: Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
body: Align(alignment: Alignment.center, child: Card(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: PointerInterceptor(child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Obx(() => _buildAppBarForMobile(context, controller.isEnableEmailSendButton.value)),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildEmailAddress(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildSubjectEmail(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Expanded(child: Padding(padding: EdgeInsets.symmetric(horizontal: 10), child: _buildEditorAndAttachments(context))),
|
||||||
|
]
|
||||||
|
))
|
||||||
|
)
|
||||||
|
))
|
||||||
|
),
|
||||||
|
desktop: Obx(() {
|
||||||
|
return Stack(children: [
|
||||||
|
if (controller.screenDisplayMode == ScreenDisplayMode.normal)
|
||||||
|
Positioned(right: 10, bottom: 10, child: Card(
|
||||||
|
elevation: 20,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||||
|
width: responsiveUtils.getSizeWidthScreen(context) * 0.5,
|
||||||
|
height: responsiveUtils.getSizeHeightScreen(context) * 0.65,
|
||||||
|
child: PointerInterceptor(child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildAppBar(context)),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildTitleComposer(context)),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildEmailAddress(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildSubjectEmail(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Expanded(child: Padding(padding: EdgeInsets.symmetric(horizontal: 10), child: _buildEditorAndAttachments(context))),
|
||||||
|
Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)),
|
||||||
|
if (controller.screenDisplayMode == ScreenDisplayMode.minimize)
|
||||||
|
Positioned(right: 10, bottom: 10, child: Card(
|
||||||
|
elevation: 20,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(color: AppColor.colorTextButton, borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||||
|
width: 500,
|
||||||
|
height: 50,
|
||||||
|
child: PointerInterceptor(child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 20, right: 16),
|
||||||
|
child: _buildTitleComposer(context),
|
||||||
|
)),
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icMinimizeComposer, color: Colors.white, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).minimize,
|
||||||
|
onTap: () => controller.minimizeComposer()),
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icFullScreenComposer, color: Colors.white, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).fullscreen,
|
||||||
|
onTap: () => controller.setFullScreenComposer()),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(right: 8),
|
||||||
|
child: buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icCloseComposer, color: Colors.white, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).close,
|
||||||
|
onTap: () => controller.closeComposerWeb())),
|
||||||
|
]
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)),
|
||||||
|
if (controller.screenDisplayMode == ScreenDisplayMode.fullScreen)
|
||||||
|
Scaffold(
|
||||||
|
backgroundColor: Colors.black38,
|
||||||
|
body: Align(alignment: Alignment.center, child: Card(
|
||||||
|
color: Colors.transparent,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||||
|
width: responsiveUtils.getSizeWidthScreen(context) * 0.8,
|
||||||
|
height: responsiveUtils.getSizeHeightScreen(context) * 0.85,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
child: PointerInterceptor(child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildAppBar(context)),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildTitleComposer(context)),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildEmailAddress(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildSubjectEmail(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Expanded(child: Padding(padding: EdgeInsets.symmetric(horizontal: 10), child: _buildEditorAndAttachments(context))),
|
||||||
|
Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)),
|
||||||
|
]
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}),
|
||||||
|
tablet: Scaffold(
|
||||||
|
backgroundColor: Colors.black38,
|
||||||
|
body: Align(alignment: Alignment.center, child: Card(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
child: PointerInterceptor(child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildAppBar(context)),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildTitleComposer(context)),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildEmailAddress(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: _buildSubjectEmail(context)),
|
||||||
|
Padding(padding: EdgeInsets.symmetric(horizontal: 20), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
|
||||||
|
Expanded(child: Padding(padding: EdgeInsets.symmetric(horizontal: 10), child: _buildEditorAndAttachments(context))),
|
||||||
|
Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)),
|
||||||
|
]
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAppBar(BuildContext context) {
|
||||||
|
return Transform(
|
||||||
|
transform: Matrix4.translationValues(15.0, 0.0, 0.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Spacer(),
|
||||||
|
if (responsiveUtils.isDesktop(context))
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icMinimizeComposer, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).minimize,
|
||||||
|
onTap: () => controller.minimizeComposer()),
|
||||||
|
if (responsiveUtils.isDesktop(context))
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icFullScreenComposer, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).fullscreen,
|
||||||
|
onTap: () => controller.setFullScreenComposer()),
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icCloseComposer, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).close,
|
||||||
|
onTap: () => controller.closeComposerWeb()),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAppBarForMobile(BuildContext context, bool isEnableSendButton) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
|
||||||
|
color: Colors.white,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icCloseComposer, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).close,
|
||||||
|
onTap: () => controller.closeComposerWeb()),
|
||||||
|
Spacer(),
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).pick_attachments,
|
||||||
|
onTap: () => controller.openFilePickerByType(context, FileType.any)),
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
imagePaths.icSendComposer,
|
||||||
|
color: isEnableSendButton ? AppColor.colorTextButton : AppColor.colorDisableMailboxCreateButton,
|
||||||
|
fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).send,
|
||||||
|
onTap: () => controller.sendEmailAction(context)),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildBottomBar(BuildContext context, bool isEnableSendButton) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 20, top: 18, bottom: 18),
|
||||||
|
color: AppColor.colorBottomBarComposer,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icDeleteComposer, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).delete,
|
||||||
|
onTap: () => controller.deleteComposer()),
|
||||||
|
Spacer(),
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).pick_attachments,
|
||||||
|
onTap: () => controller.openFilePickerByType(context, FileType.any)),
|
||||||
|
SizedBox(width: 16),
|
||||||
|
SizedBox(
|
||||||
|
width: 102,
|
||||||
|
height: 36,
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.resolveWith(
|
||||||
|
(states) => isEnableSendButton ? AppColor.colorTextButton : AppColor.colorDisableMailboxCreateButton),
|
||||||
|
padding: MaterialStateProperty.resolveWith((states) => EdgeInsets.symmetric(horizontal: 16, vertical: 10)),
|
||||||
|
elevation: MaterialStateProperty.resolveWith((states) => 0),
|
||||||
|
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
side: BorderSide(width: 0, color: isEnableSendButton ? AppColor.colorTextButton : AppColor.colorDisableMailboxCreateButton)))),
|
||||||
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
|
Text(AppLocalizations.of(context).send.toUpperCase(), style: TextStyle(fontSize: 17, color: Colors.white, fontWeight: FontWeight.w500)),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
SvgPicture.asset(imagePaths.icSendComposer, width: 18, height: 18, fit: BoxFit.fill),
|
||||||
|
]),
|
||||||
|
onPressed: () => controller.sendEmailAction(context)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTitleComposer(BuildContext context) {
|
||||||
|
return Obx(() => Text(
|
||||||
|
controller.subjectEmail.isNotEmpty == true
|
||||||
|
? controller.subjectEmail.value ?? ''
|
||||||
|
: AppLocalizations.of(context).new_message.capitalizeFirstEach,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(fontSize: 22, fontWeight: FontWeight.w500,
|
||||||
|
color: controller.screenDisplayMode == ScreenDisplayMode.minimize ? Colors.white : Colors.black),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildEmailAddress(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 12),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(right: 8),
|
||||||
|
child: Text(
|
||||||
|
'${AppLocalizations.of(context).from_email_address_prefix}:',
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() => controller.composerArguments.value != null
|
||||||
|
? Text(
|
||||||
|
'<${controller.getEmailAddressSender()}>',
|
||||||
|
style: TextStyle(fontSize: 16, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal))
|
||||||
|
: SizedBox.shrink()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Divider(color: AppColor.colorDividerComposer, height: 1),
|
||||||
|
Obx(() => (EmailAddressInputBuilder(
|
||||||
|
context,
|
||||||
|
imagePaths,
|
||||||
|
appToast,
|
||||||
|
PrefixEmailAddress.to,
|
||||||
|
controller.listToEmailAddress,
|
||||||
|
controller: controller.toEmailAddressController,
|
||||||
|
isInitial: controller.isInitialRecipient.value,
|
||||||
|
expandMode: controller.expandMode.value)
|
||||||
|
..addExpandAddressActionClick(() => controller.expandEmailAddressAction())
|
||||||
|
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
|
||||||
|
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
|
||||||
|
.build()
|
||||||
|
),
|
||||||
|
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
|
||||||
|
? Divider(color: AppColor.colorDividerComposer, height: 1)
|
||||||
|
: SizedBox.shrink()),
|
||||||
|
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
|
||||||
|
? (EmailAddressInputBuilder(
|
||||||
|
context,
|
||||||
|
imagePaths,
|
||||||
|
appToast,
|
||||||
|
PrefixEmailAddress.cc,
|
||||||
|
controller.listCcEmailAddress,
|
||||||
|
controller: controller.ccEmailAddressController,
|
||||||
|
isInitial: controller.isInitialRecipient.value,)
|
||||||
|
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
|
||||||
|
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
|
||||||
|
.build()
|
||||||
|
: SizedBox.shrink()
|
||||||
|
),
|
||||||
|
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
|
||||||
|
? Divider(color: AppColor.colorDividerComposer, height: 1)
|
||||||
|
: SizedBox.shrink()),
|
||||||
|
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
|
||||||
|
? (EmailAddressInputBuilder(
|
||||||
|
context,
|
||||||
|
imagePaths,
|
||||||
|
appToast,
|
||||||
|
PrefixEmailAddress.bcc,
|
||||||
|
controller.listBccEmailAddress,
|
||||||
|
controller: controller.bccEmailAddressController,
|
||||||
|
isInitial: controller.isInitialRecipient.value,)
|
||||||
|
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
|
||||||
|
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
|
||||||
|
.build()
|
||||||
|
: SizedBox.shrink()
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSubjectEmail(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(right: 8, top: 16),
|
||||||
|
child: Text(
|
||||||
|
'${AppLocalizations.of(context).subject_email}:',
|
||||||
|
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
|
||||||
|
Expanded(child: (TextFieldBuilder()
|
||||||
|
..key(Key('subject_email_input'))
|
||||||
|
..cursorColor(AppColor.colorTextButton)
|
||||||
|
..onChange((value) => controller.setSubjectEmail(value))
|
||||||
|
..textStyle(TextStyle(color: AppColor.colorEmailAddress, fontSize: 15))
|
||||||
|
..textDecoration(InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none))
|
||||||
|
..addController(controller.subjectEmailInputController))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildEditorAndAttachments(BuildContext context) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
physics: ClampingScrollPhysics(),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Obx(() => controller.attachments.isNotEmpty
|
||||||
|
? Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 10),
|
||||||
|
child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value))
|
||||||
|
: SizedBox.shrink()),
|
||||||
|
Obx(() => controller.attachments.isEmpty
|
||||||
|
? _buildAttachmentsLoadingView()
|
||||||
|
: SizedBox.shrink()),
|
||||||
|
Obx(() => controller.attachments.isNotEmpty
|
||||||
|
? Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 8, left: 10, right: 10),
|
||||||
|
child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value))
|
||||||
|
: SizedBox.shrink()),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: _buildComposerEditor(context)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildComposerEditor(BuildContext context) {
|
||||||
|
return Obx(() => HtmlEditorBrowser.HtmlEditor(
|
||||||
|
key: Key('composer_editor_web'),
|
||||||
|
controller: controller.htmlControllerBrowser,
|
||||||
|
htmlEditorOptions: HtmlEditorBrowser.HtmlEditorOptions(
|
||||||
|
hint: '',
|
||||||
|
initialText: controller.initTextEditorComposer,
|
||||||
|
autoAdjustHeight: true,
|
||||||
|
darkMode: false,
|
||||||
|
disableScrollbarEditor: true,
|
||||||
|
),
|
||||||
|
htmlToolbarOptions: HtmlEditorBrowser.HtmlToolbarOptions(
|
||||||
|
toolbarPosition: HtmlEditorBrowser.ToolbarPosition.custom
|
||||||
|
),
|
||||||
|
otherOptions: HtmlEditorBrowser.OtherOptions(height: 550),
|
||||||
|
callbacks: HtmlEditorBrowser.Callbacks(onBeforeCommand: (String? currentHtml) {
|
||||||
|
controller.setTextEditor(currentHtml);
|
||||||
|
}, onChangeContent: (String? changed) {
|
||||||
|
controller.setTextEditor(changed);
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) {
|
||||||
|
return Obx(() => controller.viewState.value.fold(
|
||||||
|
(failure) => SizedBox.shrink(),
|
||||||
|
(success) => success is UploadingAttachmentState
|
||||||
|
? Center(child: Padding(
|
||||||
|
padding: padding ?? EdgeInsets.all(10),
|
||||||
|
child: SizedBox(
|
||||||
|
width: size ?? 20,
|
||||||
|
height: size ?? 20,
|
||||||
|
child: CupertinoActivityIndicator(color: AppColor.colorTextButton))))
|
||||||
|
: SizedBox.shrink()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAttachmentsTitle(BuildContext context, List<Attachment> attachments, ExpandMode expandModeAttachment) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):',
|
||||||
|
style: TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)),
|
||||||
|
_buildAttachmentsLoadingView(padding: EdgeInsets.only(left: 16), size: 16),
|
||||||
|
Spacer(),
|
||||||
|
Material(
|
||||||
|
type: MaterialType.circle,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: TextButton(
|
||||||
|
child: Text(
|
||||||
|
expandModeAttachment == ExpandMode.EXPAND
|
||||||
|
? AppLocalizations.of(context).hide
|
||||||
|
: '${AppLocalizations.of(context).show_all} (${attachments.length})',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)),
|
||||||
|
onPressed: () => controller.toggleDisplayAttachments()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAttachmentsList(BuildContext context, List<Attachment> attachments, ExpandMode expandMode) {
|
||||||
|
if (expandMode == ExpandMode.EXPAND) {
|
||||||
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
|
return GridView.builder(
|
||||||
|
key: Key('list_attachment_full'),
|
||||||
|
primary: false,
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: attachments.length,
|
||||||
|
gridDelegate: SliverGridDelegateFixedHeight(
|
||||||
|
height: 60,
|
||||||
|
crossAxisCount: _getMaxItemRowListAttachment(context, constraints),
|
||||||
|
crossAxisSpacing: 8.0,
|
||||||
|
mainAxisSpacing: 8.0),
|
||||||
|
itemBuilder: (context, index) =>
|
||||||
|
(AttachmentFileComposerBuilder(context, imagePaths, attachments[index])
|
||||||
|
..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment)))
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 60,
|
||||||
|
child: ListView.builder(
|
||||||
|
key: Key('list_attachment_minimize'),
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: ClampingScrollPhysics(),
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemCount: attachments.length,
|
||||||
|
itemBuilder: (context, index) =>
|
||||||
|
(AttachmentFileComposerBuilder(context, imagePaths, attachments[index],
|
||||||
|
itemMargin: EdgeInsets.only(right: 8),
|
||||||
|
maxWidth: _getMaxWidthItemListAttachment(context, constraints),
|
||||||
|
maxHeight: 60)
|
||||||
|
..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment)))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getMaxItemRowListAttachment(BuildContext context, BoxConstraints constraints) {
|
||||||
|
if (constraints.maxWidth < ResponsiveUtils.minTabletWidth) {
|
||||||
|
return 2;
|
||||||
|
} else if (constraints.maxWidth < ResponsiveUtils.minTabletLargeWidth) {
|
||||||
|
return 3;
|
||||||
|
} else {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double _getMaxWidthItemListAttachment(BuildContext context, BoxConstraints constraints) {
|
||||||
|
final currentWidth = constraints.maxWidth - 40;
|
||||||
|
return currentWidth / _getMaxItemRowListAttachment(context, constraints);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
enum ScreenDisplayMode {
|
||||||
|
fullScreen,
|
||||||
|
minimize,
|
||||||
|
normal
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
import 'package:core/core.dart';
|
||||||
|
import 'package:filesize/filesize.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:model/model.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
|
typedef OnDeleteAttachmentAction = void Function(Attachment attachment);
|
||||||
|
|
||||||
|
class AttachmentFileComposerBuilder {
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
final ImagePaths imagePaths;
|
||||||
|
final Attachment attachment;
|
||||||
|
final double? maxWidth;
|
||||||
|
final double? maxHeight;
|
||||||
|
final EdgeInsets? itemMargin;
|
||||||
|
|
||||||
|
OnDeleteAttachmentAction? _onDeleteAttachmentAction;
|
||||||
|
|
||||||
|
Widget? buttonAction;
|
||||||
|
|
||||||
|
AttachmentFileComposerBuilder(
|
||||||
|
this.context,
|
||||||
|
this.imagePaths,
|
||||||
|
this.attachment,
|
||||||
|
{
|
||||||
|
this.maxWidth,
|
||||||
|
this.maxHeight,
|
||||||
|
this.itemMargin,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
void addOnDeleteAttachmentAction(OnDeleteAttachmentAction onDeleteAttachmentAction) {
|
||||||
|
_onDeleteAttachmentAction = onDeleteAttachmentAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget build() {
|
||||||
|
return Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
splashColor: Colors.transparent ,
|
||||||
|
highlightColor: Colors.transparent),
|
||||||
|
child: Container(
|
||||||
|
margin: itemMargin ?? EdgeInsets.zero,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
border: Border.all(color: AppColor.colorInputBorderCreateMailbox),
|
||||||
|
color: Colors.white),
|
||||||
|
child: Stack(children: [
|
||||||
|
ListTile(
|
||||||
|
contentPadding: EdgeInsets.only(right: 16),
|
||||||
|
onTap: () {},
|
||||||
|
leading: Transform(
|
||||||
|
transform: Matrix4.translationValues(8.0, -3.0, 0.0),
|
||||||
|
child: SvgPicture.asset(imagePaths.icFileAttachment, fit: BoxFit.fill)),
|
||||||
|
title: Transform(
|
||||||
|
transform: Matrix4.translationValues(-4.0, -6.0, 0.0),
|
||||||
|
child: Text(
|
||||||
|
attachment.name ?? '',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(fontSize: 12, color: AppColor.colorNameEmail, fontWeight: FontWeight.w500),
|
||||||
|
)),
|
||||||
|
subtitle: attachment.size != null && attachment.size?.value != 0
|
||||||
|
? Transform(
|
||||||
|
transform: Matrix4.translationValues(-4.0, -5.0, 0.0),
|
||||||
|
child: Text(
|
||||||
|
filesize(attachment.size?.value, 0),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(fontSize: 10, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal)))
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
Positioned(right: -5, top: -5, child: buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(imagePaths.icDeleteAttachment, fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).delete,
|
||||||
|
onTap: () => _onDeleteAttachmentAction?.call(attachment)))
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ class EmailAddressInputBuilder {
|
|||||||
final List<EmailAddress> _listEmailAddress;
|
final List<EmailAddress> _listEmailAddress;
|
||||||
final TextEditingController? controller;
|
final TextEditingController? controller;
|
||||||
final bool? isInitial;
|
final bool? isInitial;
|
||||||
|
final bool hasAvatar;
|
||||||
|
|
||||||
OnOpenExpandAddressActionClick? _onOpenExpandAddressActionClick;
|
OnOpenExpandAddressActionClick? _onOpenExpandAddressActionClick;
|
||||||
OnUpdateListEmailAddressAction? _onUpdateListEmailAddressAction;
|
OnUpdateListEmailAddressAction? _onUpdateListEmailAddressAction;
|
||||||
@@ -51,6 +52,7 @@ class EmailAddressInputBuilder {
|
|||||||
this._listEmailAddress,
|
this._listEmailAddress,
|
||||||
{
|
{
|
||||||
this.isInitial,
|
this.isInitial,
|
||||||
|
this.hasAvatar = false,
|
||||||
this.controller,
|
this.controller,
|
||||||
this.expandMode = ExpandMode.COLLAPSE,
|
this.expandMode = ExpandMode.COLLAPSE,
|
||||||
}
|
}
|
||||||
@@ -69,7 +71,7 @@ class EmailAddressInputBuilder {
|
|||||||
Expanded(child: _buildTagEditor()),
|
Expanded(child: _buildTagEditor()),
|
||||||
if (_prefixEmailAddress == PrefixEmailAddress.to)
|
if (_prefixEmailAddress == PrefixEmailAddress.to)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 4),
|
padding: EdgeInsets.only(top: 8),
|
||||||
child: _buildButtonExpandAddress())
|
child: _buildButtonExpandAddress())
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@@ -79,12 +81,10 @@ class EmailAddressInputBuilder {
|
|||||||
return Material(
|
return Material(
|
||||||
type: MaterialType.circle,
|
type: MaterialType.circle,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: IconButton(
|
child: TextButton(
|
||||||
icon: SvgPicture.asset(
|
child: Text(
|
||||||
expandMode == ExpandMode.EXPAND ? _imagePaths.icExpandAddress : _imagePaths.icMoreReceiver,
|
expandMode == ExpandMode.EXPAND ? AppLocalizations.of(_context).hide : AppLocalizations.of(_context).details,
|
||||||
width: 20,
|
style: TextStyle(fontWeight: FontWeight.normal, fontSize: 16, color: AppColor.colorTextButton)),
|
||||||
height: 20,
|
|
||||||
fit: BoxFit.fill),
|
|
||||||
onPressed: () => _onOpenExpandAddressActionClick?.call()
|
onPressed: () => _onOpenExpandAddressActionClick?.call()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -98,6 +98,7 @@ class EmailAddressInputBuilder {
|
|||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
textInputAction: TextInputAction.done,
|
textInputAction: TextInputAction.done,
|
||||||
hasAddButton: false,
|
hasAddButton: false,
|
||||||
|
tagSpacing: 8,
|
||||||
resetTextOnSubmitted: true,
|
resetTextOnSubmitted: true,
|
||||||
textStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500),
|
textStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500),
|
||||||
onSubmitted: (value) {
|
onSubmitted: (value) {
|
||||||
@@ -117,16 +118,22 @@ class EmailAddressInputBuilder {
|
|||||||
tagBuilder: (context, index) => Padding(
|
tagBuilder: (context, index) => Padding(
|
||||||
padding: EdgeInsets.only(top: kIsWeb ? 8 : 0),
|
padding: EdgeInsets.only(top: kIsWeb ? 8 : 0),
|
||||||
child: Chip(
|
child: Chip(
|
||||||
labelPadding: EdgeInsets.only(left: 8, right: 8, bottom: 2),
|
labelPadding: EdgeInsets.only(left: 12, right: 12, bottom: 2),
|
||||||
label: Text(_listEmail[index], maxLines: 1, overflow: TextOverflow.ellipsis),
|
label: Text(_listEmail[index], maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||||
deleteIcon: SvgPicture.asset(_imagePaths.icDeleteEmailAddress, fit: BoxFit.fill),
|
deleteIcon: SvgPicture.asset(_imagePaths.icDeleteEmailAddress, fit: BoxFit.fill),
|
||||||
labelStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500),
|
labelStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500),
|
||||||
backgroundColor: AppColor.emailAddressChipColor,
|
backgroundColor: AppColor.emailAddressChipColor,
|
||||||
avatar: CircleAvatar(
|
shape: RoundedRectangleBorder(
|
||||||
backgroundColor: AppColor.colorTextButton,
|
borderRadius: BorderRadius.circular(10),
|
||||||
child: Text(
|
side: BorderSide(width: 0, color: AppColor.emailAddressChipColor),
|
||||||
_listEmail[index].isNotEmpty ? _listEmail[index][0].toUpperCase() : '',
|
),
|
||||||
style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500))),
|
avatar: hasAvatar == true
|
||||||
|
? CircleAvatar(
|
||||||
|
backgroundColor: AppColor.colorTextButton,
|
||||||
|
child: Text(
|
||||||
|
_listEmail[index].isNotEmpty ? _listEmail[index][0].toUpperCase() : '',
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500)))
|
||||||
|
: null,
|
||||||
onDeleted: () {
|
onDeleted: () {
|
||||||
setState(() => _listEmailAddress.removeAt(index));
|
setState(() => _listEmailAddress.removeAt(index));
|
||||||
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress);
|
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:core/core.dart';
|
|||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -33,6 +34,7 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_
|
|||||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_dialog_builder.dart';
|
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_dialog_builder.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
@@ -480,16 +482,16 @@ class EmailController extends BaseController {
|
|||||||
void composeEmailFromEmailAddress(EmailAddress emailAddress) {
|
void composeEmailFromEmailAddress(EmailAddress emailAddress) {
|
||||||
popBack();
|
popBack();
|
||||||
|
|
||||||
if (canComposeEmail()) {
|
final arguments = ComposerArguments(
|
||||||
push(
|
emailActionType: EmailActionType.composeFromEmailAddress,
|
||||||
AppRoutes.COMPOSER,
|
emailAddress: emailAddress,
|
||||||
arguments: ComposerArguments(
|
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role);
|
||||||
emailActionType: EmailActionType.composeFromEmailAddress,
|
if (kIsWeb) {
|
||||||
emailAddress: emailAddress,
|
if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
|
||||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: arguments);
|
||||||
session: mailboxDashBoardController.sessionCurrent!,
|
}
|
||||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
} else {
|
||||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
push(AppRoutes.COMPOSER, arguments: arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,11 +499,6 @@ class EmailController extends BaseController {
|
|||||||
popBack();
|
popBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
|
|
||||||
&& mailboxDashBoardController.userProfile.value != null
|
|
||||||
&& mailboxDashBoardController.mapDefaultMailboxId.isNotEmpty
|
|
||||||
&& mailboxDashBoardController.selectedEmail.value != null;
|
|
||||||
|
|
||||||
void backToThreadView() {
|
void backToThreadView() {
|
||||||
attachmentsExpandMode.value = ExpandMode.COLLAPSE;
|
attachmentsExpandMode.value = ExpandMode.COLLAPSE;
|
||||||
emailAddressExpandMode.value = ExpandMode.COLLAPSE;
|
emailAddressExpandMode.value = ExpandMode.COLLAPSE;
|
||||||
@@ -513,30 +510,36 @@ class EmailController extends BaseController {
|
|||||||
if (emailActionType == EmailActionType.compose) {
|
if (emailActionType == EmailActionType.compose) {
|
||||||
composeEmailAction();
|
composeEmailAction();
|
||||||
} else {
|
} else {
|
||||||
if (canComposeEmail()) {
|
final arguments = ComposerArguments(
|
||||||
push(
|
emailActionType: emailActionType,
|
||||||
AppRoutes.COMPOSER,
|
presentationEmail: mailboxDashBoardController.selectedEmail.value!,
|
||||||
arguments: ComposerArguments(
|
emailContents: emailContents,
|
||||||
emailActionType: emailActionType,
|
attachments: attachments,
|
||||||
presentationEmail: mailboxDashBoardController.selectedEmail.value!,
|
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role);
|
||||||
emailContents: emailContents,
|
|
||||||
attachments: attachments,
|
if (kIsWeb) {
|
||||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
|
||||||
session: mailboxDashBoardController.sessionCurrent!,
|
mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: arguments);
|
||||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
}
|
||||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
if (Get.currentRoute == AppRoutes.EMAIL) {
|
||||||
|
popBack();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push(AppRoutes.COMPOSER, arguments: arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void composeEmailAction() {
|
void composeEmailAction() {
|
||||||
if (canComposeEmail()) {
|
if (kIsWeb) {
|
||||||
push(
|
if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
|
||||||
AppRoutes.COMPOSER,
|
mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: ComposerArguments());
|
||||||
arguments: ComposerArguments(
|
}
|
||||||
session: mailboxDashBoardController.sessionCurrent!,
|
if (Get.currentRoute == AppRoutes.EMAIL) {
|
||||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
popBack();
|
||||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
}
|
||||||
|
} else {
|
||||||
|
push(AppRoutes.COMPOSER, arguments: ComposerArguments());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ class EmailView extends GetView {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 20),
|
padding: EdgeInsets.only(top: kIsWeb ? 10: 20),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${prefixEmailAddress.asName(context)}:',
|
'${prefixEmailAddress.asName(context)}:',
|
||||||
style: TextStyle(fontSize: 14, color: AppColor.colorEmailAddressPrefix))),
|
style: TextStyle(fontSize: 14, color: AppColor.colorEmailAddressPrefix))),
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
|
import 'package:tmail_ui_user/main/routes/router_arguments.dart';
|
||||||
|
|
||||||
class ComposerArguments with EquatableMixin {
|
class ComposerArguments extends RouterArguments {
|
||||||
final EmailActionType emailActionType;
|
final EmailActionType emailActionType;
|
||||||
final PresentationEmail? presentationEmail;
|
final PresentationEmail? presentationEmail;
|
||||||
final List<EmailContent>? emailContents;
|
final List<EmailContent>? emailContents;
|
||||||
final EmailAddress? emailAddress;
|
final EmailAddress? emailAddress;
|
||||||
final List<Attachment>? attachments;
|
final List<Attachment>? attachments;
|
||||||
final Session session;
|
|
||||||
final UserProfile userProfile;
|
|
||||||
final Map<Role, MailboxId> mapMailboxId;
|
|
||||||
final Role? mailboxRole;
|
final Role? mailboxRole;
|
||||||
|
|
||||||
ComposerArguments({
|
ComposerArguments({
|
||||||
@@ -23,9 +19,6 @@ class ComposerArguments with EquatableMixin {
|
|||||||
this.attachments,
|
this.attachments,
|
||||||
this.mailboxRole,
|
this.mailboxRole,
|
||||||
this.emailAddress,
|
this.emailAddress,
|
||||||
required this.session,
|
|
||||||
required this.userProfile,
|
|
||||||
required this.mapMailboxId,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -35,8 +28,5 @@ class ComposerArguments with EquatableMixin {
|
|||||||
attachments,
|
attachments,
|
||||||
mailboxRole,
|
mailboxRole,
|
||||||
emailAddress,
|
emailAddress,
|
||||||
session,
|
|
||||||
userProfile,
|
|
||||||
mapMailboxId,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,9 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
|
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||||
|
|
||||||
typedef OnBackActionClick = void Function();
|
typedef OnBackActionClick = void Function();
|
||||||
typedef OnEmailActionClick = void Function(PresentationEmail, EmailActionType);
|
typedef OnEmailActionClick = void Function(PresentationEmail, EmailActionType);
|
||||||
@@ -51,9 +53,9 @@ class AppBarMailWidgetBuilder {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
if ((!_responsiveUtils.isDesktop(_context) && !_responsiveUtils.isTabletLarge(_context)))
|
if (_conditionShowBackButton())
|
||||||
_buildBackButton(),
|
_buildBackButton(),
|
||||||
if ((!_responsiveUtils.isDesktop(_context) && !_responsiveUtils.isTabletLarge(_context)))
|
if (_conditionShowBackButton())
|
||||||
Expanded(child: _buildMailboxName()),
|
Expanded(child: _buildMailboxName()),
|
||||||
if (_presentationEmail != null) _buildListOptionButton(),
|
if (_presentationEmail != null) _buildListOptionButton(),
|
||||||
]
|
]
|
||||||
@@ -62,6 +64,16 @@ class AppBarMailWidgetBuilder {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _conditionShowBackButton() {
|
||||||
|
if (Get.currentRoute == AppRoutes.MAILBOX_DASHBOARD) {
|
||||||
|
return !_responsiveUtils.isDesktop(_context) && !_responsiveUtils.isTabletLarge(_context);
|
||||||
|
} else if (Get.currentRoute == AppRoutes.EMAIL) {
|
||||||
|
return _responsiveUtils.isMobileDevice(_context) || _responsiveUtils.isTablet(_context);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildBackButton() {
|
Widget _buildBackButton() {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
icon: SvgPicture.asset(_imagePaths.icBack, width: 20, height: 20, color: AppColor.colorTextButton, fit: BoxFit.fill),
|
icon: SvgPicture.asset(_imagePaths.icBack, width: 20, height: 20, color: AppColor.colorTextButton, fit: BoxFit.fill),
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class AttachmentFileTileBuilder {
|
|||||||
}},
|
}},
|
||||||
leading: Transform(
|
leading: Transform(
|
||||||
transform: Matrix4.translationValues(14.0, 2.0, 0.0),
|
transform: Matrix4.translationValues(14.0, 2.0, 0.0),
|
||||||
child: SvgPicture.asset(_imagePaths.icAttachmentFile, width: 24, height: 24, fit: BoxFit.fill)),
|
child: SvgPicture.asset(_imagePaths.icFileAttachment, width: 24, height: 24, fit: BoxFit.fill)),
|
||||||
title: Transform(
|
title: Transform(
|
||||||
transform: Matrix4.translationValues(-8.0, -8.0, 0.0),
|
transform: Matrix4.translationValues(-8.0, -8.0, 0.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@@ -453,6 +453,8 @@ class MailboxController extends BaseMailboxController {
|
|||||||
..title(AppLocalizations.of(context).delete_mailboxes)
|
..title(AppLocalizations.of(context).delete_mailboxes)
|
||||||
..content(AppLocalizations.of(context).message_confirmation_dialog_delete_mailbox(presentationMailbox.name?.name ?? ''))
|
..content(AppLocalizations.of(context).message_confirmation_dialog_delete_mailbox(presentationMailbox.name?.name ?? ''))
|
||||||
..addIcon(SvgPicture.asset(_imagePaths.icRemoveDialog, fit: BoxFit.fill))
|
..addIcon(SvgPicture.asset(_imagePaths.icRemoveDialog, fit: BoxFit.fill))
|
||||||
|
..colorConfirmButton(AppColor.colorConfirmActionDialog)
|
||||||
|
..styleTextConfirmButton(TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorActionDeleteConfirmDialog))
|
||||||
..onCloseButtonAction(() => popBack())
|
..onCloseButtonAction(() => popBack())
|
||||||
..onConfirmButtonAction(AppLocalizations.of(context).delete, () => _deleteMailboxAction(presentationMailbox))
|
..onConfirmButtonAction(AppLocalizations.of(context).delete, () => _deleteMailboxAction(presentationMailbox))
|
||||||
..onCancelButtonAction(AppLocalizations.of(context).cancel, () => popBack()))
|
..onCancelButtonAction(AppLocalizations.of(context).cancel, () => popBack()))
|
||||||
|
|||||||
@@ -11,16 +11,20 @@ import 'package:tmail_ui_user/features/base/base_controller.dart';
|
|||||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
|
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart';
|
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.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/email/presentation/email_controller.dart';
|
import 'package:tmail_ui_user/features/email/presentation/email_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_user_profile_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_user_profile_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
|
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/presentation/model/search_state.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/model/search_state.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/presentation/model/search_status.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/model/search_status.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
import 'package:tmail_ui_user/main/routes/router_arguments.dart';
|
||||||
|
|
||||||
class MailboxDashBoardController extends BaseController {
|
class MailboxDashBoardController extends BaseController {
|
||||||
|
|
||||||
@@ -36,6 +40,7 @@ class MailboxDashBoardController extends BaseController {
|
|||||||
final userProfile = Rxn<UserProfile>();
|
final userProfile = Rxn<UserProfile>();
|
||||||
final searchState = SearchState.initial().obs;
|
final searchState = SearchState.initial().obs;
|
||||||
final suggestionSearch = <String>[].obs;
|
final suggestionSearch = <String>[].obs;
|
||||||
|
final dashBoardAction = DashBoardAction.none.obs;
|
||||||
|
|
||||||
SearchQuery? searchQuery;
|
SearchQuery? searchQuery;
|
||||||
Session? sessionCurrent;
|
Session? sessionCurrent;
|
||||||
@@ -43,6 +48,7 @@ class MailboxDashBoardController extends BaseController {
|
|||||||
Map<MailboxId, PresentationMailbox> mapMailbox = Map();
|
Map<MailboxId, PresentationMailbox> mapMailbox = Map();
|
||||||
TextEditingController searchInputController = TextEditingController();
|
TextEditingController searchInputController = TextEditingController();
|
||||||
FocusNode searchFocus = FocusNode();
|
FocusNode searchFocus = FocusNode();
|
||||||
|
RouterArguments? routerArguments;
|
||||||
|
|
||||||
MailboxDashBoardController(
|
MailboxDashBoardController(
|
||||||
this._getUserProfileInteractor,
|
this._getUserProfileInteractor,
|
||||||
@@ -225,6 +231,20 @@ class MailboxDashBoardController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dispatchDashBoardAction(DashBoardAction action, {RouterArguments? arguments}) {
|
||||||
|
switch(action) {
|
||||||
|
case DashBoardAction.none:
|
||||||
|
routerArguments = null;
|
||||||
|
Get.delete<ComposerController>();
|
||||||
|
break;
|
||||||
|
case DashBoardAction.compose:
|
||||||
|
routerArguments = arguments;
|
||||||
|
ComposerBindings().dependencies();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dashBoardAction.value = action;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
searchInputController.dispose();
|
searchInputController.dispose();
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart'
|
||||||
|
if (dart.library.html) 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
|
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
|
||||||
|
|
||||||
class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> {
|
class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> {
|
||||||
@@ -30,35 +33,40 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> {
|
|||||||
desktop: SizedBox.shrink()
|
desktop: SizedBox.shrink()
|
||||||
),
|
),
|
||||||
drawerEnableOpenDragGesture: !responsiveUtils.isDesktop(context),
|
drawerEnableOpenDragGesture: !responsiveUtils.isDesktop(context),
|
||||||
body: ResponsiveWidget(
|
body: Stack(children: [
|
||||||
responsiveUtils: responsiveUtils,
|
ResponsiveWidget(
|
||||||
desktop: Container(
|
responsiveUtils: responsiveUtils,
|
||||||
child: Row(
|
desktop: Container(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
Expanded(flex: 1, child: MailboxView()),
|
children: [
|
||||||
Expanded(flex: 1, child: ThreadView()),
|
Expanded(flex: 1, child: MailboxView()),
|
||||||
Expanded(flex: 2, child: EmailView()),
|
Expanded(flex: 1, child: ThreadView()),
|
||||||
],
|
Expanded(flex: 2, child: EmailView()),
|
||||||
),
|
],
|
||||||
),
|
|
||||||
tabletLarge: Container(
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: responsiveUtils.getSizeWidthScreen(context) * 0.35,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
child: ThreadView()
|
|
||||||
),
|
),
|
||||||
Expanded(child: EmailView()),
|
),
|
||||||
],
|
tabletLarge: Container(
|
||||||
),
|
child: Row(
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
tablet: ThreadView(),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mobile: ThreadView()),
|
children: [
|
||||||
|
Container(
|
||||||
|
width: responsiveUtils.getSizeWidthScreen(context) * 0.35,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: ThreadView()
|
||||||
|
),
|
||||||
|
Expanded(child: EmailView()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tablet: ThreadView(),
|
||||||
|
mobile: ThreadView()),
|
||||||
|
Obx(() => controller.dashBoardAction == DashBoardAction.compose
|
||||||
|
? ComposerView()
|
||||||
|
: SizedBox.shrink()),
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
enum DashBoardAction {
|
||||||
|
none,
|
||||||
|
compose
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
@@ -28,6 +27,7 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
|
|||||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_action.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
|
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
|
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
|
||||||
@@ -675,10 +675,6 @@ class ThreadController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
|
|
||||||
&& mailboxDashBoardController.userProfile.value != null
|
|
||||||
&& mailboxDashBoardController.mapDefaultMailboxId.isNotEmpty;
|
|
||||||
|
|
||||||
bool isSelectionEnabled() => currentSelectMode.value == SelectMode.ACTIVE;
|
bool isSelectionEnabled() => currentSelectMode.value == SelectMode.ACTIVE;
|
||||||
|
|
||||||
void pressEmailSelectionAction(BuildContext context, EmailActionType actionType, List<PresentationEmail> selectionEmail) {
|
void pressEmailSelectionAction(BuildContext context, EmailActionType actionType, List<PresentationEmail> selectionEmail) {
|
||||||
@@ -709,27 +705,25 @@ class ThreadController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void editEmail(PresentationEmail presentationEmail) {
|
void editEmail(PresentationEmail presentationEmail) {
|
||||||
if (canComposeEmail()) {
|
final arguments = ComposerArguments(
|
||||||
push(
|
emailActionType: EmailActionType.edit,
|
||||||
AppRoutes.COMPOSER,
|
presentationEmail: presentationEmail,
|
||||||
arguments: ComposerArguments(
|
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role);
|
||||||
emailActionType: EmailActionType.edit,
|
|
||||||
presentationEmail: presentationEmail,
|
if (kIsWeb) {
|
||||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: arguments);
|
||||||
session: mailboxDashBoardController.sessionCurrent!,
|
} else {
|
||||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
push(AppRoutes.COMPOSER, arguments: arguments);
|
||||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void composeEmailAction() {
|
void composeEmailAction() {
|
||||||
if (canComposeEmail()) {
|
if (kIsWeb) {
|
||||||
push(
|
if (mailboxDashBoardController.dashBoardAction != DashBoardAction.compose) {
|
||||||
AppRoutes.COMPOSER,
|
mailboxDashBoardController.dispatchDashBoardAction(DashBoardAction.compose, arguments: ComposerArguments());
|
||||||
arguments: ComposerArguments(
|
}
|
||||||
session: mailboxDashBoardController.sessionCurrent!,
|
} else {
|
||||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
push(AppRoutes.COMPOSER, arguments: ComposerArguments());
|
||||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -773,4 +773,47 @@ class AppLocalizations {
|
|||||||
'Email address copied to clipboard',
|
'Email address copied to clipboard',
|
||||||
name: 'email_address_copied_to_clipboard');
|
name: 'email_address_copied_to_clipboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get minimize {
|
||||||
|
return Intl.message(
|
||||||
|
'Minimize',
|
||||||
|
name: 'minimize');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get fullscreen {
|
||||||
|
return Intl.message(
|
||||||
|
'Fullscreen',
|
||||||
|
name: 'fullscreen');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get close {
|
||||||
|
return Intl.message(
|
||||||
|
'Close',
|
||||||
|
name: 'close');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get send {
|
||||||
|
return Intl.message(
|
||||||
|
'Send',
|
||||||
|
name: 'send');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get attachments {
|
||||||
|
return Intl.message(
|
||||||
|
'Attachments',
|
||||||
|
name: 'attachments');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get show_all {
|
||||||
|
return Intl.message(
|
||||||
|
'Show all',
|
||||||
|
name: 'show_all');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get message_confirm_send_email {
|
||||||
|
return Intl.message(
|
||||||
|
'Are you sure to send messages without a subject?',
|
||||||
|
name: 'message_confirm_send_email');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:get/get_navigation/src/routes/get_route.dart';
|
import 'package:get/get_navigation/src/routes/get_route.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart'
|
||||||
|
if (dart.library.html) 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
|
||||||
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_bindings.dart';
|
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_bindings.dart';
|
||||||
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_view.dart';
|
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_view.dart';
|
||||||
import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart';
|
import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart';
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class RouterArguments with EquatableMixin {}
|
||||||
@@ -125,11 +125,16 @@ dependencies:
|
|||||||
url: https://github.com/Enough-Software/enough_html_editor.git
|
url: https://github.com/Enough-Software/enough_html_editor.git
|
||||||
|
|
||||||
# html_editor_enhanced: Compose email for Web Browser
|
# html_editor_enhanced: Compose email for Web Browser
|
||||||
html_editor_enhanced: 2.4.0+1
|
html_editor_enhanced:
|
||||||
|
git:
|
||||||
|
url: https://github.com/dab246/html-editor-enhanced.git
|
||||||
|
ref: html_editor_for_web
|
||||||
|
|
||||||
# fk_user_agent
|
# fk_user_agent
|
||||||
fk_user_agent: 2.1.0
|
fk_user_agent: 2.1.0
|
||||||
|
|
||||||
|
pointer_interceptor: 0.9.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||