diff --git a/assets/images/ic_delete_outline.svg b/assets/images/ic_delete_outline.svg
deleted file mode 100644
index 214e3a8d8..000000000
--- a/assets/images/ic_delete_outline.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart
index d22cddd97..6ded7869e 100644
--- a/core/lib/presentation/extensions/color_extension.dart
+++ b/core/lib/presentation/extensions/color_extension.dart
@@ -169,6 +169,7 @@ extension AppColor on Color {
static const colorProgressQuotasWarning = Color(0xFFFFA000);
static const colorOutOfStorageQuotasWarning = Color(0xffE64646);
static const colorThumbScrollBar = Color(0xFFAEB7C2);
+ static const colorCreateNewIdentityButton = Color(0xFFEBEDF0);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index 7d9e3d0ee..de00cbe38 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -26,7 +26,6 @@ class ImagePaths {
String get icSelected => _getImagePath('ic_selected.svg');
String get icUnSelected => _getImagePath('ic_unselected.svg');
String get icDelete => _getImagePath('ic_delete.svg');
- String get icDeleteOutline => _getImagePath('ic_delete_outline.svg');
String get icSpam => _getImagePath('ic_spam.svg');
String get icMove => _getImagePath('ic_move.svg');
String get icReadToast => _getImagePath('ic_read_toast.svg');
diff --git a/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart b/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart
index ec636ec43..0f03397fa 100644
--- a/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart
+++ b/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart
@@ -36,6 +36,7 @@ class SettingsFirstLevelView extends GetWidget {
SettingFirstLevelTileBuilder(
AppLocalizations.of(context).profiles,
AccountMenuItem.profiles.getIcon(_imagePaths),
+ subtitle: AppLocalizations.of(context).profilesSettingExplanation,
() => controller.selectSettings(AccountMenuItem.profiles)
),
Divider(
diff --git a/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart b/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart
index 9121eef8b..b2b11cebd 100644
--- a/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart
+++ b/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart
@@ -43,7 +43,6 @@ class IdentitiesController extends BaseController {
final DeleteIdentityInteractor _deleteIdentityInteractor;
final EditIdentityInteractor _editIdentityInteractor;
- final selectedIndex = Rxn();
final identitySelected = Rxn();
final listAllIdentities = [].obs;
@@ -71,28 +70,22 @@ class IdentitiesController extends BaseController {
@override
void onDone() {
viewState.value.fold(
- (failure) {
- if (failure is DeleteIdentityFailure) {
- _deleteIdentityFailure(failure);
- }
- },
- (success) {
- if (success is GetAllIdentitiesSuccess) {
- if (success.identities?.isNotEmpty == true) {
- final newListIdentities = success.identities!
- .where((identity) => identity.mayDelete == true)
- .toList();
- listAllIdentities.addAll(newListIdentities);
- selectIdentity(0);
- }
- } else if (success is CreateNewIdentitySuccess) {
- _createNewIdentitySuccess(success);
- } else if (success is DeleteIdentitySuccess) {
- _deleteIdentitySuccess(success);
- } else if (success is EditIdentitySuccess) {
- _editIdentitySuccess(success);
- }
+ (failure) {
+ if (failure is DeleteIdentityFailure) {
+ _deleteIdentityFailure(failure);
}
+ },
+ (success) {
+ if (success is GetAllIdentitiesSuccess) {
+ _handleGetAllIdentitiesSuccess(success);
+ } else if (success is CreateNewIdentitySuccess) {
+ _createNewIdentitySuccess(success);
+ } else if (success is DeleteIdentitySuccess) {
+ _deleteIdentitySuccess(success);
+ } else if (success is EditIdentitySuccess) {
+ _editIdentitySuccess(success);
+ }
+ }
);
}
@@ -117,7 +110,7 @@ class IdentitiesController extends BaseController {
}
void _refreshAllIdentities() {
- selectedIndex.value = null;
+ identitySelected.value = null;
listAllIdentities.clear();
final accountId = _accountDashBoardController.accountId.value;
@@ -126,11 +119,21 @@ class IdentitiesController extends BaseController {
}
}
- void selectIdentity(int? index) {
- selectedIndex.value = index;
- if (selectedIndex.value != null) {
- identitySelected.value = listAllIdentities[selectedIndex.value!];
+ void _handleGetAllIdentitiesSuccess(GetAllIdentitiesSuccess success) {
+ if (success.identities?.isNotEmpty == true) {
+ final newListIdentities = success.identities!
+ .where((identity) => identity.mayDelete == true)
+ .toList();
+ listAllIdentities.addAll(newListIdentities);
}
+
+ if (listAllIdentities.isNotEmpty) {
+ selectIdentity(listAllIdentities.first);
+ }
+ }
+
+ void selectIdentity(Identity? newIdentity) {
+ identitySelected.value = newIdentity;
}
void goToCreateNewIdentity(BuildContext context) async {
@@ -226,6 +229,8 @@ class IdentitiesController extends BaseController {
}
void _deleteIdentityAction(Identity identity) {
+ popBack();
+
final accountId = _accountDashBoardController.accountId.value;
if (accountId != null && identity.id != null) {
consumeState(_deleteIdentityInteractor.execute(accountId, identity.id!));
@@ -319,7 +324,5 @@ class IdentitiesController extends BaseController {
ImagePaths get imagePaths => _imagePaths;
- bool isSignatureShow() {
- return selectedIndex.value!= null && selectedIndex.value! >= 0;
- }
+ bool get isSignatureShow => identitySelected.value != null;
}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/identities/identities_view.dart b/lib/features/manage_account/presentation/profiles/identities/identities_view.dart
index 153c9ab50..396758c92 100644
--- a/lib/features/manage_account/presentation/profiles/identities/identities_view.dart
+++ b/lib/features/manage_account/presentation/profiles/identities/identities_view.dart
@@ -1,12 +1,12 @@
-import 'package:core/core.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/popup_menu_widget_mixin.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/identities_controller.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/identities_header_widget.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder.dart';
-import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
-import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder_web.dart' as identities_listview_web;
class IdentitiesView extends GetWidget with PopupMenuWidgetMixin, AppLoaderMixin {
@@ -17,106 +17,52 @@ class IdentitiesView extends GetWidget with PopupMenuWidge
@override
Widget build(BuildContext context) {
- return ResponsiveWidget(
- responsiveUtils: _responsiveUtils,
- mobile: _buildIdentitiesViewMobile(context),
- tablet: _buildIdentitiesViewMobile(context),
- desktop: _buildIdentitiesViewWeb(context),
- tabletLarge: _buildIdentitiesViewMobile(context),
+ return Container(
+ color: Colors.transparent,
+ margin: const EdgeInsets.all(24),
+ child: _responsiveUtils.isWebDesktop(context)
+ ? _buildIdentitiesViewWebDesktop(context)
+ : _buildIdentitiesViewMobile(context),
);
}
Widget _buildIdentitiesViewMobile(BuildContext context) {
- return SingleChildScrollView(
- padding: const EdgeInsets.only(left: 16.0, right: 16.0, top: 24.0, bottom: 24.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- for(Widget item in _buildIdentitiesTitles(context))
- item,
- _buildCreateIdentityButton(context),
- IdentitiesRadioListBuilder(controller: controller),
- ],
- ),
- );
- }
-
- Widget _buildIdentitiesViewWeb(BuildContext context) {
- return Padding(
- padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 8.0),
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Container(
- width: 236,
- padding: const EdgeInsets.only(right: 12.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- for(Widget widget in _buildIdentitiesTitles(context))
- widget,
- _buildCreateIdentityButton(context),
- ],
- ),
- ),
- Expanded(
- child: identities_listview_web.IdentitiesRadioListBuilder(controller: controller),
- ),
- ],
- ),
- );
- }
-
- List _buildIdentitiesTitles(BuildContext context) {
- return [
- Text(
- AppLocalizations.of(context).identities.inCaps,
- style: const TextStyle(
- fontWeight: FontWeight.w500,
- fontSize: 17,
- color: Colors.black)),
- const SizedBox(height: 4.0),
- Text(
- AppLocalizations.of(context).identities_description,
- style: const TextStyle(
- fontSize: 15,
- fontWeight: FontWeight.w400,
- color: AppColor.colorSettingExplanation),
- ),
- const SizedBox(height: 12.0),
- ];
- }
-
- Widget _buildCreateIdentityButton(BuildContext context) {
- return Row(
+ return Column(
children: [
- Expanded(
- child: Padding(
- padding: const EdgeInsets.only(bottom: 12.0),
- child: (ButtonBuilder(_imagePaths.icAddIdentity)
- ..key(const Key('button_add_identity'))
- ..decoration(BoxDecoration(
- borderRadius: BorderRadius.circular(12),
- color: AppColor.colorBorderIdentityInfo))
- ..paddingIcon(const EdgeInsets.only(right: 12))
- ..iconColor(AppColor.primaryColor)
- ..size(28)
- ..padding(const EdgeInsets.symmetric(vertical: 12))
- ..textStyle(const TextStyle(
- fontSize: 16,
- color: AppColor.primaryColor,
- fontWeight: FontWeight.w500,
- ))
- ..onPressActionClick(() => controller.goToCreateNewIdentity(context))
- ..text(
- AppLocalizations.of(context).create_new_identity,
- isVertical: false,
- ))
- .build(),
- ),
+ IdentitiesHeaderWidget(
+ imagePaths: _imagePaths,
+ responsiveUtils: _responsiveUtils,
+ onAddNewIdentityAction: () => controller.goToCreateNewIdentity(context),
),
+ const SizedBox(height: 12),
+ IdentitiesRadioListBuilder(
+ controller: controller,
+ responsiveUtils: _responsiveUtils,
+ imagePaths: _imagePaths
+ )
],
);
}
+ Widget _buildIdentitiesViewWebDesktop(BuildContext context) {
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(
+ width: 224,
+ child: IdentitiesHeaderWidget(
+ imagePaths: _imagePaths,
+ responsiveUtils: _responsiveUtils,
+ onAddNewIdentityAction: () => controller.goToCreateNewIdentity(context),
+ )
+ ),
+ const SizedBox(width: 12),
+ Expanded(child: IdentitiesRadioListBuilder(
+ controller: controller,
+ responsiveUtils: _responsiveUtils,
+ imagePaths: _imagePaths
+ )),
+ ],
+ );
+ }
}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/identities/widgets/identities_header_widget.dart b/lib/features/manage_account/presentation/profiles/identities/widgets/identities_header_widget.dart
new file mode 100644
index 000000000..6d581de4c
--- /dev/null
+++ b/lib/features/manage_account/presentation/profiles/identities/widgets/identities_header_widget.dart
@@ -0,0 +1,62 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/responsive_utils.dart';
+import 'package:core/presentation/views/button/button_builder.dart';
+import 'package:flutter/material.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+typedef OnAddNewIdentityAction = Function();
+
+class IdentitiesHeaderWidget extends StatelessWidget {
+
+ const IdentitiesHeaderWidget({
+ Key? key,
+ required this.imagePaths,
+ required this.responsiveUtils,
+ this.onAddNewIdentityAction,
+ }) : super(key: key);
+
+ final ImagePaths imagePaths;
+ final ResponsiveUtils responsiveUtils;
+ final OnAddNewIdentityAction? onAddNewIdentityAction;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ color: Colors.transparent,
+ child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
+ Text(
+ AppLocalizations.of(context).identities,
+ style: const TextStyle(
+ fontSize: 17,
+ fontWeight: FontWeight.w500,
+ color: Colors.black)),
+ const SizedBox(height: 4),
+ Text(
+ AppLocalizations.of(context).identitiesSettingExplanation,
+ style: const TextStyle(
+ fontSize: 15,
+ fontWeight: FontWeight.normal,
+ color: AppColor.colorSettingExplanation)),
+ const SizedBox(height: 24),
+ (ButtonBuilder(imagePaths.icAddIdentity)
+ ..key(const Key('button_add_identity'))
+ ..decoration(BoxDecoration(
+ borderRadius: BorderRadius.circular(12),
+ color: AppColor.colorCreateNewIdentityButton))
+ ..paddingIcon(const EdgeInsets.only(right: 8))
+ ..iconColor(AppColor.colorTextButton)
+ ..size(28)
+ ..radiusSplash(12)
+ ..padding(const EdgeInsets.symmetric(vertical: 10))
+ ..textStyle(const TextStyle(
+ fontSize: 16,
+ color: AppColor.colorTextButton,
+ fontWeight: FontWeight.w500))
+ ..onPressActionClick(() => onAddNewIdentityAction?.call())
+ ..text(AppLocalizations.of(context).createNewIdentity, isVertical: false)
+ ).build()
+ ]),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder.dart b/lib/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder.dart
index 5b19dab4d..daba4d054 100644
--- a/lib/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder.dart
+++ b/lib/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder.dart
@@ -1,79 +1,105 @@
import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/responsive_utils.dart';
+import 'package:fading_edge_scrollview/fading_edge_scrollview.dart';
import 'package:flutter/material.dart';
-import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
+import 'package:get/get_state_manager/get_state_manager.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/identities_controller.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/identity_list_tile_builder.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/signature_of_identity_builder.dart';
-import 'identity_list_tile_builder.dart';
-
-class IdentitiesRadioListBuilder extends StatefulWidget {
- const IdentitiesRadioListBuilder({
- Key? key,
- required this.controller,
- }) : super(key: key);
+class IdentitiesRadioListBuilder extends StatelessWidget {
final IdentitiesController controller;
+ final ResponsiveUtils responsiveUtils;
+ final ImagePaths imagePaths;
- @override
- State createState() => _IdentitiesRadioListBuilderState();
-}
-
-class _IdentitiesRadioListBuilderState extends State {
- late final controller = widget.controller;
+ const IdentitiesRadioListBuilder({
+ Key? key,
+ required this.controller,
+ required this.responsiveUtils,
+ required this.imagePaths,
+ }) : super(key: key);
@override
Widget build(BuildContext context) {
- return Obx(() {
- if (controller.listAllIdentities.isEmpty) {
- return const SizedBox.shrink();
- }
+ return Container(
+ height: responsiveUtils.isWebDesktop(context) ? 256 : null,
+ decoration: BoxDecoration(
+ border: Border.all(color: AppColor.attachmentFileBorderColor),
+ borderRadius: const BorderRadius.all(Radius.circular(16.0)),
+ color: Colors.white
+ ),
+ child: ClipRRect(
+ borderRadius: const BorderRadius.all(Radius.circular(16.0)),
+ child: responsiveUtils.isWebDesktop(context)
+ ? _buildIdentityViewHorizontal(context)
+ : _buildIdentityViewVertical(context))
+ );
+ }
- return Container(
- foregroundDecoration: BoxDecoration(
- border: Border.all(color: AppColor.colorBorderIdentityInfo, width: 1),
- borderRadius: const BorderRadius.all(Radius.circular(16.0)),
+ Widget _buildIdentityViewVertical(BuildContext context) {
+ return Obx(() => Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ if(controller.isSignatureShow)
+ ...[
+ _buildListIdentityView(context),
+ Container(height: 1, color: AppColor.attachmentFileBorderColor),
+ Obx(() => SignatureOfIdentityBuilder(identity: controller.identitySelected.value!))
+ ]
+ else
+ _buildListIdentityView(context)
+ ],
+ ));
+ }
+
+ Widget _buildIdentityViewHorizontal(BuildContext context) {
+ return Obx(() => Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ if (controller.isSignatureShow)
+ ...[
+ _buildListIdentityView(context),
+ Container(width: 1, color: AppColor.attachmentFileBorderColor),
+ Expanded(
+ child: Obx(() => SignatureOfIdentityBuilder(identity: controller.identitySelected.value!)),
+ )
+ ]
+ else
+ Expanded(child: _buildListIdentityView(context))
+ ],
+ ));
+ }
+
+ Widget _buildListIdentityView(BuildContext context) {
+ return Container(
+ key: const Key('identities_list'),
+ width: responsiveUtils.isWebDesktop(context) ? 320 : null,
+ height: 256,
+ padding: const EdgeInsets.only(left: 12, top: 12, bottom: 12),
+ child: Obx(() => FadingEdgeScrollView.fromScrollView(
+ gradientFractionOnStart: 0.3,
+ gradientFractionOnEnd: 0.3,
+ shouldDisposeScrollController: true,
+ child: ListView.builder(
+ controller: ScrollController(),
+ padding: const EdgeInsets.only(right: 12.0),
+ itemCount: controller.listAllIdentities.length,
+ itemBuilder: ((context, index) {
+ return IdentityListTileBuilder(
+ imagePaths: imagePaths,
+ identity: controller.listAllIdentities[index],
+ identitySelected: controller.identitySelected.value,
+ onSelectIdentityAction: controller.selectIdentity,
+ onEditIdentityAction: (identitySelected) =>
+ controller.goToEditIdentity(context, identitySelected),
+ onDeleteIdentityAction: (identitySelected) =>
+ controller.openConfirmationDialogDeleteIdentityAction(context, identitySelected),
+ );
+ }),
),
- child: Obx(() => Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Container(
- key: const Key('identities_checkbox_list'),
- height: 256,
- foregroundDecoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.topCenter,
- end: Alignment.bottomCenter,
- colors: [0, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 1].map((e)
- => Colors.white.withOpacity(e.toDouble())).toList(),
- stops: const [0.8, 0.82, 0.84, 0.86, 0.88, 0.90, 0.92, 0.94, 0.96, 0.98, 1],// Gradient from https://learnui.design/tools/gradient-generator.html
- tileMode: TileMode.mirror,
- ),
- border: controller.isSignatureShow() ? const Border(bottom: BorderSide(color: AppColor.colorBorderIdentityInfo)): null,
- ),
- padding: const EdgeInsets.only(left: 12.0, bottom: 12.0, top: 12.0, right: 4.0),
- child: Scrollbar(
- child: MediaQuery.removePadding(
- context: context,
- removeTop: true,
- child: ListView.builder(
- padding: const EdgeInsets.only(right: 12.0),
- itemCount: controller.listAllIdentities.value.length,
- itemBuilder: ((context, index) {
- return IdentityListTileBuilder(
- controller: widget.controller,
- index: index,
- selected: widget.controller.selectedIndex.value,
- );
- }),
- )
- ),
- ),
- ),
- if(controller.isSignatureShow())
- Obx(() => SignatureOfIdentityBuilder(identity: controller.identitySelected.value!)),
- ],
- ),
- ));
- });
+ ))
+ );
}
}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder_web.dart b/lib/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder_web.dart
deleted file mode 100644
index c19b5a038..000000000
--- a/lib/features/manage_account/presentation/profiles/identities/widgets/identities_radio_list_builder_web.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-import 'package:core/presentation/extensions/color_extension.dart';
-import 'package:flutter/material.dart';
-import 'package:get/get_state_manager/get_state_manager.dart';
-import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/identities_controller.dart';
-import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/signature_of_identity_builder.dart';
-
-import 'identity_list_tile_builder.dart';
-
-class IdentitiesRadioListBuilder extends StatefulWidget {
- const IdentitiesRadioListBuilder({
- Key? key,
- required this.controller,
- }) : super(key: key);
-
- final IdentitiesController controller;
-
- @override
- State createState() => _IdentitiesRadioListBuilderState();
-}
-
-class _IdentitiesRadioListBuilderState extends State {
- int? selected;
- late final allIdentities = widget.controller.listAllIdentities.value;
-
- @override
- Widget build(BuildContext context) {
- return Container(
- height: 256,
- foregroundDecoration: BoxDecoration(
- border: Border.all(color: AppColor.colorBorderIdentityInfo, width: 1),
- borderRadius: const BorderRadius.all(Radius.circular(16.0)),
- ),
- child: Obx(() => Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- if(widget.controller.isSignatureShow())...[
- _buildListViewContainer(),
- Expanded(
- child: Obx(() => SignatureOfIdentityBuilder(identity: widget.controller.identitySelected.value!)),
- )
- ] else
- Expanded(child: _buildListViewContainer())
- ],
- )),
- );
- }
-
- Widget _buildListViewContainer() {
- return Container(
- key: const Key('identities_checkbox_list'),
- width: 320,
- foregroundDecoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.topCenter,
- end: Alignment.bottomCenter,
- colors: [0, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 1].map((e)
- => Colors.white.withOpacity(e.toDouble())).toList(),
- stops: const [0.8, 0.82, 0.84, 0.86, 0.88, 0.90, 0.92, 0.94, 0.96, 0.98, 1],// Gradient from https://learnui.design/tools/gradient-generator.html
- tileMode: TileMode.mirror,
- ),
- border: widget.controller.isSignatureShow() ? const Border(right: BorderSide(color: AppColor.colorBorderIdentityInfo)): null,
- ),
- padding: const EdgeInsets.only(left: 12.0, bottom: 12.0, top: 12.0, right: 4.0),
- child: Scrollbar(
- controller: ScrollController(),
- radius: const Radius.circular(5.0),
- thickness: 2.0,
- child: Obx(() => ListView.builder(
- padding: const EdgeInsets.only(right: 12.0),
- itemCount: widget.controller.listAllIdentities.value.length,
- itemBuilder: ((context, index) {
- return IdentityListTileBuilder(
- controller: widget.controller,
- index: index,
- selected: widget.controller.selectedIndex.value,
- );
- }),
- ),
- ))
- );
- }
-}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/identities/widgets/identity_list_tile_builder.dart b/lib/features/manage_account/presentation/profiles/identities/widgets/identity_list_tile_builder.dart
index 535091667..94412fea8 100644
--- a/lib/features/manage_account/presentation/profiles/identities/widgets/identity_list_tile_builder.dart
+++ b/lib/features/manage_account/presentation/profiles/identities/widgets/identity_list_tile_builder.dart
@@ -1,121 +1,167 @@
-import 'package:core/core.dart';
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/style_utils.dart';
+import 'package:core/presentation/views/button/icon_button_web.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
-import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/identities_controller.dart';
+import 'package:model/extensions/list_email_address_extension.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+typedef OnSelectIdentityAction = Function(Identity? identitySelected);
+typedef OnEditIdentityAction = Function(Identity identitySelected);
+typedef OnDeleteIdentityAction = Function(Identity identitySelected);
class IdentityListTileBuilder extends StatelessWidget {
+
const IdentityListTileBuilder({
Key? key,
- required this.controller,
- required this.index,
- required this.selected
+ required this.identity,
+ required this.identitySelected,
+ required this.imagePaths,
+ this.onSelectIdentityAction,
+ this.onEditIdentityAction,
+ this.onDeleteIdentityAction
}) : super(key: key);
- final IdentitiesController controller;
- final int index;
- final int? selected;
+ final Identity identity;
+ final Identity? identitySelected;
+ final ImagePaths imagePaths;
+ final OnSelectIdentityAction? onSelectIdentityAction;
+ final OnEditIdentityAction? onEditIdentityAction;
+ final OnDeleteIdentityAction? onDeleteIdentityAction;
@override
Widget build(BuildContext context) {
- final imagePaths = controller.imagePaths;
- final listAllIdentities = controller.listAllIdentities.value;
- final identity = listAllIdentities[index];
-
return Material(
color: Colors.transparent,
- child: InkWell(
- borderRadius: BorderRadius.circular(12.0),
- onTap: () => controller.selectIdentity(index),
- child: Container(
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(12.0),
- color: isIdentitySelected(index) ? AppColor.colorItemSelected : Colors.transparent,
- ),
- padding: const EdgeInsets.only(top: 12.0, bottom: 12.0, right: 12.0),
- child: Row(
- children: [
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: BuildUtils.isWeb ? 8.0 : 0.0),
- child: Radio(
- value: index,
- groupValue: selected,
- onChanged: (selectedValue) => controller.selectIdentity(index),
+ child: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: InkWell(
+ borderRadius: BorderRadius.circular(12.0),
+ onTap: () => onSelectIdentityAction?.call(identity),
+ child: Container(
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(12.0),
+ color: _isIdentitySelected
+ ? AppColor.colorItemSelected
+ : Colors.transparent,
+ ),
+ padding: const EdgeInsets.all(12),
+ child: Row(
+ children: [
+ Radio(
+ value: identity,
+ splashRadius: 15,
+ groupValue: identitySelected,
+ activeColor: AppColor.primaryColor,
+ onChanged: onSelectIdentityAction,
),
- ),
- Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- identity.name ?? '',
- overflow: CommonTextStyle.defaultTextOverFlow,
- softWrap: CommonTextStyle.defaultSoftWrap,
- style: const TextStyle(
- fontWeight: FontWeight.w500,
- fontSize: 16,
- color: Colors.black)),
- _buildIconWithTextLine(imagePaths.icEmail, identity.email),
- for(final widget in _buildReplyLines(identity, imagePaths))
- widget
- ],
- )
- ),
- if(isIdentitySelected(index))...[
- buildSVGIconButton(
- padding: const EdgeInsets.only(left: 12.0, right: 12.0),
- icon: imagePaths.icEdit,
- iconSize: 24,
- iconColor: AppColor.primaryColor,
- onTap: () => controller.goToEditIdentity(context, controller.identitySelected.value!),
+ const SizedBox(width: 10),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(bottom: 6),
+ child: Text(
+ identity.name ?? '',
+ overflow: CommonTextStyle.defaultTextOverFlow,
+ softWrap: CommonTextStyle.defaultSoftWrap,
+ style: const TextStyle(
+ fontWeight: FontWeight.w500,
+ fontSize: 16,
+ color: Colors.black)),
+ ),
+ if (identity.email?.isNotEmpty == true)
+ _buildIconSVGWithTextLine(imagePaths.icEmail, identity.email),
+ if (identity.replyTo?.isNotEmpty == true)
+ _buildIconSVGWithTextLine(
+ imagePaths.icReplyTo,
+ identity.replyTo?.listEmailAddressToString(isFullEmailAddress: true)
+ ),
+ if (identity.bcc?.isNotEmpty == true)
+ _buildIconCharacterWithTextLine(
+ AppLocalizations.of(context).bcc_email_address_prefix,
+ identity.bcc?.listEmailAddressToString(isFullEmailAddress: true)
+ ),
+ ],
+ )
),
- buildSVGIconButton(
- padding: const EdgeInsets.only(right: 0.0),
- icon: imagePaths.icDeleteOutline,
- iconSize: 24,
- iconColor: AppColor.colorActionDeleteConfirmDialog,
- onTap: () => controller.openConfirmationDialogDeleteIdentityAction(context, controller.identitySelected.value!),
- ),
- ]
- ],
+ if(_isIdentitySelected)
+ ...[
+ buildSVGIconButton(
+ icon: imagePaths.icEditRule,
+ iconSize: 24,
+ iconColor: AppColor.primaryColor,
+ onTap: () => onEditIdentityAction?.call(identity),
+ ),
+ buildSVGIconButton(
+ icon: imagePaths.icDeleteRule,
+ iconSize: 24,
+ iconColor: AppColor.colorDeletePermanentlyButton,
+ onTap: () => onDeleteIdentityAction?.call(identity),
+ ),
+ ]
+ ],
+ ),
),
),
),
);
}
- List _buildReplyLines(Identity? identity, ImagePaths imagePaths) {
- return [
- for(var identityReplyTo in identity?.replyTo?.toList() ?? [])
- _buildIconWithTextLine(imagePaths.icReply, identityReplyTo.email)];
- }
-
- Widget _buildIconWithTextLine(String imagePath, String? text) {
- return Row(
- children: [
- Padding(
- padding: const EdgeInsets.only(right: 8.0),
- child: SvgPicture.asset(
- imagePath,
- color: AppColor.primaryColor,
- width: 16,
- fit: BoxFit.fitHeight,
- )),
- // replacement character after ..., so wrap it inside richtext is workaround solution
+ Widget _buildIconSVGWithTextLine(String imagePath, String? text) {
+ return Padding(
+ padding: const EdgeInsets.only(bottom: 4),
+ child: Row(children: [
+ SizedBox(
+ width: 30,
+ child: Align(
+ alignment: Alignment.centerLeft,
+ child: SvgPicture.asset(imagePath, width: 15, height: 15))),
+ const SizedBox(width: 4),
Expanded(child: Text(
- text ?? '', style: const TextStyle(
+ text ?? '',
+ style: const TextStyle(
color: AppColor.colorEmailAddressFull,
- fontWeight: FontWeight.w400,
+ fontWeight: FontWeight.normal,
fontSize: 13,
),
overflow: CommonTextStyle.defaultTextOverFlow,
- softWrap: CommonTextStyle.defaultSoftWrap,
- )),
- ]
+ softWrap: CommonTextStyle.defaultSoftWrap
+ ))
+ ]),
);
}
- bool isIdentitySelected(int index) {
- return index == selected;
+ Widget _buildIconCharacterWithTextLine(String character, String? text) {
+ return Padding(
+ padding: const EdgeInsets.only(bottom: 4),
+ child: Row(children: [
+ Container(
+ width: 30,
+ alignment: Alignment.centerLeft,
+ child: Text(
+ character,
+ style: const TextStyle(
+ fontSize: 15,
+ fontWeight: FontWeight.normal,
+ decoration: TextDecoration.underline,
+ color: AppColor.colorTextButton))),
+ const SizedBox(width: 4),
+ Expanded(child: Text(text ?? '',
+ style: const TextStyle(
+ color: AppColor.colorEmailAddressFull,
+ fontWeight: FontWeight.normal,
+ fontSize: 13,
+ ),
+ overflow: CommonTextStyle.defaultTextOverFlow,
+ softWrap: CommonTextStyle.defaultSoftWrap
+ ))
+ ]),
+ );
}
+
+ bool get _isIdentitySelected => identity.id == identitySelected?.id;
}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/identities/widgets/signature_builder.dart b/lib/features/manage_account/presentation/profiles/identities/widgets/signature_builder.dart
index fa0b044a4..04bec652e 100644
--- a/lib/features/manage_account/presentation/profiles/identities/widgets/signature_builder.dart
+++ b/lib/features/manage_account/presentation/profiles/identities/widgets/signature_builder.dart
@@ -1,10 +1,14 @@
-import 'package:core/core.dart';
+import 'package:core/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart';
+import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
+import 'package:core/presentation/views/html_viewer/html_viewer_controller_for_web.dart';
+import 'package:core/utils/build_utils.dart';
import 'package:flutter/material.dart';
import 'package:html_unescape/html_unescape_small.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
class SignatureBuilder extends StatelessWidget {
- SignatureBuilder({
+
+ const SignatureBuilder({
Key? key,
this.width,
this.height,
@@ -61,5 +65,4 @@ class SignatureBuilder extends StatelessWidget {
final unescape = HtmlUnescape();
return unescape.convert(htmlString);
}
-
}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/identities/widgets/signature_of_identity_builder.dart b/lib/features/manage_account/presentation/profiles/identities/widgets/signature_of_identity_builder.dart
index 06b3b477c..c7bc148a8 100644
--- a/lib/features/manage_account/presentation/profiles/identities/widgets/signature_of_identity_builder.dart
+++ b/lib/features/manage_account/presentation/profiles/identities/widgets/signature_of_identity_builder.dart
@@ -4,7 +4,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/profiles/iden
class SignatureOfIdentityBuilder extends StatelessWidget {
- SignatureOfIdentityBuilder({required this.identity});
+ const SignatureOfIdentityBuilder({Key? key, required this.identity}) : super(key: key);
final Identity identity;
diff --git a/lib/features/manage_account/presentation/profiles/profiles_view.dart b/lib/features/manage_account/presentation/profiles/profiles_view.dart
index f0f3a6c80..a81f8512d 100644
--- a/lib/features/manage_account/presentation/profiles/profiles_view.dart
+++ b/lib/features/manage_account/presentation/profiles/profiles_view.dart
@@ -1,15 +1,18 @@
-import 'package:core/core.dart';
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/identities_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/profiles_controller.dart';
-import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/profiles/widgets/profiles_header_widget.dart';
class ProfilesView extends GetWidget {
final _responsiveUtils = Get.find();
+ final _imagePaths = Get.find();
ProfilesView({Key? key}) : super(key: key);
@@ -17,52 +20,31 @@ class ProfilesView extends GetWidget {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: SettingsUtils.getBackgroundColor(context, _responsiveUtils),
- body: ResponsiveWidget(
- responsiveUtils: _responsiveUtils,
- mobile: IdentitiesView(),
- desktop: _buildProfilesWeb(context))
- );
- }
-
- Widget _buildProfilesWeb(BuildContext context) {
- return Container(
- decoration: BoxDecoration(
- borderRadius: const BorderRadius.all(Radius.circular(16.0)),
- border: Border.all(color: AppColor.colorBorderIdentityInfo),
- color: Colors.white,
- ),
- margin: const EdgeInsets.all(16.0),
- padding: const EdgeInsets.all(16.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- for(var widget in _buildProfilesTitle(context))
- widget,
- const Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2),
- Expanded(child: IdentitiesView()),
- ],
- ),
- );
- }
-
- List _buildProfilesTitle(BuildContext context) {
- return [
- Text(
- AppLocalizations.of(context).profiles.inCaps,
- style: const TextStyle(
- fontWeight: FontWeight.w700,
- fontSize: 20,
- fontFamily: 'Inter',
- color: Colors.black)),
- const SizedBox(height: 4.0),
- Text(
- AppLocalizations.of(context).profiles_description,
- style: const TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.normal,
- color: AppColor.colorContentEmail),
+ body: Container(
+ width: double.infinity,
+ height: double.infinity,
+ color: SettingsUtils.getContentBackgroundColor(context, _responsiveUtils),
+ decoration: SettingsUtils.getBoxDecorationForContent(context, _responsiveUtils),
+ margin: SettingsUtils.getMarginViewForForwardSettingDetails(context, _responsiveUtils),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ if (_responsiveUtils.isWebDesktop(context))
+ ...[
+ ProfilesHeaderWidget(imagePaths: _imagePaths, responsiveUtils: _responsiveUtils),
+ Container(height: 1, color: AppColor.colorDividerHeaderSetting)
+ ],
+ Expanded(child: SingleChildScrollView(
+ physics: const ClampingScrollPhysics(),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ IdentitiesView()
+ ])
+ ))
+ ],
),
- const SizedBox(height: 16.0),
- ];
+ ),
+ );
}
}
\ No newline at end of file
diff --git a/lib/features/manage_account/presentation/profiles/widgets/profiles_header_widget.dart b/lib/features/manage_account/presentation/profiles/widgets/profiles_header_widget.dart
new file mode 100644
index 000000000..097894dbd
--- /dev/null
+++ b/lib/features/manage_account/presentation/profiles/widgets/profiles_header_widget.dart
@@ -0,0 +1,40 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/responsive_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class ProfilesHeaderWidget extends StatelessWidget {
+
+ const ProfilesHeaderWidget({
+ Key? key,
+ required this.imagePaths,
+ required this.responsiveUtils,
+ }) : super(key: key);
+
+ final ImagePaths imagePaths;
+ final ResponsiveUtils responsiveUtils;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ color: Colors.transparent,
+ padding: const EdgeInsets.only(top: 16, left: 16, right: 16, bottom: 15),
+ child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
+ Text(
+ AppLocalizations.of(context).profiles,
+ style: const TextStyle(
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ color: Colors.black)),
+ const SizedBox(height: 4),
+ Text(
+ AppLocalizations.of(context).profilesSettingExplanation,
+ style: const TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ color: AppColor.colorSettingExplanation)),
+ ]),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb
index 3ba13836c..c220ad6f6 100644
--- a/lib/l10n/intl_messages.arb
+++ b/lib/l10n/intl_messages.arb
@@ -1,5 +1,5 @@
{
- "@@last_modified": "2022-11-18T14:33:10.063321",
+ "@@last_modified": "2022-12-28T14:09:51.971658",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -1166,12 +1166,30 @@
"placeholders_order": [],
"placeholders": {}
},
+ "profilesSettingExplanation": "Info about you, and options to manage it",
+ "@profilesSettingExplanation": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
"identities": "Identities",
"@identities": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
+ "identitiesSettingExplanation": "Select the identity or email address you want to use to send an emails",
+ "@identitiesSettingExplanation": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "createNewIdentity": "Create new identity",
+ "@createNewIdentity": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
"new_identity": "New Identity",
"@new_identity": {
"type": "text",
@@ -2527,5 +2545,11 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
+ },
+ "regards": "Regards",
+ "@regards": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart
index 796ac8cc2..235984764 100644
--- a/lib/main/localizations/app_localizations.dart
+++ b/lib/main/localizations/app_localizations.dart
@@ -1200,9 +1200,11 @@ class AppLocalizations {
name: 'profiles');
}
- String get profiles_description {
- return Intl.message('Info about you, and options to manage it',
- name: 'profiles_description');
+ String get profilesSettingExplanation {
+ return Intl.message(
+ 'Info about you, and options to manage it',
+ name: 'profilesSettingExplanation'
+ );
}
String get identities {
@@ -1210,14 +1212,16 @@ class AppLocalizations {
name: 'identities');
}
- String get identities_description {
- return Intl.message('Select the identity or email address you want to use to send an emails',
- name: 'identities_description');
+ String get identitiesSettingExplanation {
+ return Intl.message(
+ 'Select the identity or email address you want to use to send an emails',
+ name: 'identitiesSettingExplanation');
}
- String get create_new_identity {
- return Intl.message('Create new identity',
- name: 'create_new_identity');
+ String get createNewIdentity {
+ return Intl.message(
+ 'Create new identity',
+ name: 'createNewIdentity');
}
String get new_identity {
diff --git a/pubspec.lock b/pubspec.lock
index bb7d6de08..d8744a722 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -411,6 +411,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
+ fading_edge_scrollview:
+ dependency: "direct main"
+ description:
+ name: fading_edge_scrollview
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.0"
fake_async:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 2aa563671..d6332964e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -207,7 +207,10 @@ dependencies:
# Use for flutter 3.0.5 https://github.com/EdsonBueno/focus_detector/pull/14
focus_detector:
git: https://github.com/ifnyas/focus_detector.git
- html_unescape: ^2.0.0
+
+ html_unescape: 2.0.0
+
+ fading_edge_scrollview: 3.0.0
dev_dependencies:
flutter_test: