TF-1194 apply new design identity to manage identity screen in mobile
This commit is contained in:
+95
-176
@@ -1,22 +1,12 @@
|
||||
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/views/button/button_builder.dart';
|
||||
import 'package:core/presentation/views/responsive/responsive_widget.dart';
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.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/base/widget/drop_down_button_widget.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_bottom_sheet_action_tile_builder.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/identity_info_tile_builder.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<IdentitiesController> with PopupMenuWidgetMixin, AppLoaderMixin {
|
||||
|
||||
@@ -27,177 +17,106 @@ class IdentitiesView extends GetWidget<IdentitiesController> with PopupMenuWidge
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final buttonSelectIdentity = Row(children: [
|
||||
Expanded(child: Obx(() => DropDownButtonWidget<Identity>(
|
||||
items: controller.listAllIdentities,
|
||||
itemSelected: controller.identitySelected.value,
|
||||
onChanged: (newIdentity) => controller.selectIdentity(newIdentity),
|
||||
supportSelectionIcon: true))),
|
||||
if (!_responsiveUtils.isMobile(context)) const SizedBox(width: 12),
|
||||
if (!_responsiveUtils.isMobile(context))
|
||||
(ButtonBuilder(_imagePaths.icAddIdentity)
|
||||
..key(const Key('button_new_identity'))
|
||||
..decoration(BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: AppColor.colorTextButton))
|
||||
..paddingIcon(const EdgeInsets.only(right: 8))
|
||||
..iconColor(Colors.white)
|
||||
..maxWidth(170)
|
||||
..size(20)
|
||||
..radiusSplash(10)
|
||||
..padding(const EdgeInsets.symmetric(vertical: 12))
|
||||
..textStyle(const TextStyle(fontSize: 17, color: Colors.white, fontWeight: FontWeight.w500))
|
||||
..onPressActionClick(() => controller.goToCreateNewIdentity(context))
|
||||
..text(AppLocalizations.of(context).new_identity, isVertical: false))
|
||||
.build()
|
||||
]);
|
||||
return ResponsiveWidget(
|
||||
responsiveUtils: _responsiveUtils,
|
||||
mobile: _buildIdentitiesViewMobile(context),
|
||||
tablet: _buildIdentitiesViewMobile(context),
|
||||
desktop: _buildIdentitiesViewWeb(context),
|
||||
tabletLarge: _buildIdentitiesViewMobile(context),
|
||||
);
|
||||
}
|
||||
|
||||
return LayoutBuilder(builder: (context, constraints) => ResponsiveWidget(
|
||||
responsiveUtils: _responsiveUtils,
|
||||
mobile: Scaffold(
|
||||
body: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buttonSelectIdentity,
|
||||
const SizedBox(height: 24),
|
||||
_buildLoadingView(),
|
||||
Expanded(child: Obx(() => MasonryGridView.count(
|
||||
key: const Key('list_identities'),
|
||||
crossAxisSpacing: 24.0,
|
||||
mainAxisSpacing: 24.0,
|
||||
crossAxisCount: _responsiveUtils.isDesktop(context) || _responsiveUtils.isTabletLarge(context)
|
||||
? 2 : 1,
|
||||
itemCount: controller.listSelectedIdentities.length,
|
||||
itemBuilder: (context, index) =>
|
||||
IdentityInfoTileBuilder(_imagePaths, _responsiveUtils,
|
||||
controller.listSelectedIdentities[index],
|
||||
onMenuItemIdentityAction: (identity, position) =>
|
||||
_openIdentityMenuAction(context, identity, position))
|
||||
)))
|
||||
]
|
||||
)
|
||||
),
|
||||
floatingActionButton: _responsiveUtils.isMobile(context)
|
||||
? FloatingActionButton(
|
||||
key: const Key('add_new_identity'),
|
||||
onPressed: () => controller.goToCreateNewIdentity(context),
|
||||
backgroundColor: AppColor.primaryColor,
|
||||
child: SvgPicture.asset(_imagePaths.icAddIdentity, width: 24, height: 24))
|
||||
: null),
|
||||
desktop: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 24, horizontal: 16),
|
||||
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: [
|
||||
SizedBox(
|
||||
width: constraints.maxWidth / 2,
|
||||
child: buttonSelectIdentity),
|
||||
const SizedBox(height: 24),
|
||||
_buildLoadingView(),
|
||||
Expanded(child: Obx(() => MasonryGridView.count(
|
||||
key: const Key('list_identities'),
|
||||
crossAxisSpacing: 24.0,
|
||||
mainAxisSpacing: 24.0,
|
||||
crossAxisCount: _responsiveUtils.isDesktop(context) || _responsiveUtils.isTabletLarge(context)
|
||||
? 2 : 1,
|
||||
itemCount: controller.listSelectedIdentities.length,
|
||||
itemBuilder: (context, index) =>
|
||||
IdentityInfoTileBuilder(_imagePaths, _responsiveUtils,
|
||||
controller.listSelectedIdentities[index],
|
||||
onMenuItemIdentityAction: (identity, position) =>
|
||||
_openIdentityMenuAction(context, identity, position))
|
||||
)))
|
||||
]
|
||||
)
|
||||
)
|
||||
));
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for(Widget widget in _buildIdentitiesTitles(context))
|
||||
widget,
|
||||
_buildCreateIdentityButton(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: identities_listview_web.IdentitiesRadioListBuilder(controller: controller),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoadingView() {
|
||||
return Obx(() => controller.viewState.value.fold(
|
||||
(failure) => const SizedBox.shrink(),
|
||||
(success) => success is LoadingState
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(bottom: 24),
|
||||
child: loadingWidget)
|
||||
: const SizedBox.shrink()
|
||||
));
|
||||
}
|
||||
|
||||
void _openIdentityMenuAction(BuildContext context, Identity identity,
|
||||
RelativeRect? position) {
|
||||
if (_responsiveUtils.isScreenWithShortestSide(context)) {
|
||||
controller.openContextMenuAction(context, _bottomSheetIdentityActionTiles(context, identity));
|
||||
} else {
|
||||
controller.openPopupMenuAction(context, position, _popupMenuIdentityActionTiles(context, identity));
|
||||
}
|
||||
}
|
||||
|
||||
List<PopupMenuEntry> _popupMenuIdentityActionTiles(BuildContext context, Identity identity) {
|
||||
List<Widget> _buildIdentitiesTitles(BuildContext context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
padding: EdgeInsets.zero,
|
||||
child: popupItem(_imagePaths.icEdit,
|
||||
AppLocalizations.of(context).edit_identity,
|
||||
styleName: const TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 17,
|
||||
color: Colors.black),
|
||||
onCallbackAction: () => controller.goToEditIdentity(context, identity))),
|
||||
if (identity.mayDelete == true)
|
||||
PopupMenuItem(
|
||||
padding: EdgeInsets.zero,
|
||||
child: popupItem(_imagePaths.icDeleteComposer,
|
||||
AppLocalizations.of(context).delete_identity,
|
||||
colorIcon: AppColor.colorActionDeleteConfirmDialog,
|
||||
styleName: const TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 17,
|
||||
color: AppColor.colorActionDeleteConfirmDialog),
|
||||
onCallbackAction: () => controller.openConfirmationDialogDeleteIdentityAction(context, identity))),
|
||||
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),
|
||||
];
|
||||
}
|
||||
|
||||
List<Widget> _bottomSheetIdentityActionTiles(BuildContext context, Identity identity) {
|
||||
return <Widget>[
|
||||
_editIdentityActionTile(context, identity),
|
||||
if (identity.mayDelete == true)
|
||||
_deleteIdentityActionTile(context, identity),
|
||||
];
|
||||
Widget _buildCreateIdentityButton(BuildContext context) {
|
||||
return Row(
|
||||
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(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _deleteIdentityActionTile(BuildContext context, Identity identity) {
|
||||
return (IdentityBottomSheetActionTileBuilder(
|
||||
const Key('delete_identity_action'),
|
||||
SvgPicture.asset(_imagePaths.icDeleteComposer,
|
||||
color: AppColor.colorActionDeleteConfirmDialog),
|
||||
AppLocalizations.of(context).delete_identity,
|
||||
identity,
|
||||
iconLeftPadding: _responsiveUtils.isMobile(context)
|
||||
? const EdgeInsets.only(left: 12, right: 16)
|
||||
: const EdgeInsets.only(right: 12),
|
||||
iconRightPadding: _responsiveUtils.isMobile(context)
|
||||
? const EdgeInsets.only(right: 12)
|
||||
: EdgeInsets.zero)
|
||||
..onActionClick((identity) => controller.openConfirmationDialogDeleteIdentityAction(context, identity)))
|
||||
.build();
|
||||
}
|
||||
|
||||
Widget _editIdentityActionTile(BuildContext context, Identity identity) {
|
||||
return (IdentityBottomSheetActionTileBuilder(
|
||||
const Key('edit_identity_action'),
|
||||
SvgPicture.asset(_imagePaths.icEdit),
|
||||
AppLocalizations.of(context).edit_identity,
|
||||
identity,
|
||||
iconLeftPadding: _responsiveUtils.isMobile(context)
|
||||
? const EdgeInsets.only(left: 12, right: 16)
|
||||
: const EdgeInsets.only(right: 12),
|
||||
iconRightPadding: _responsiveUtils.isMobile(context)
|
||||
? const EdgeInsets.only(right: 12)
|
||||
: EdgeInsets.zero)
|
||||
..onActionClick((identity) => controller.goToEditIdentity(context, identity)))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.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<StatefulWidget> createState() => _IdentitiesRadioListBuilderState();
|
||||
}
|
||||
|
||||
class _IdentitiesRadioListBuilderState extends State<IdentitiesRadioListBuilder> {
|
||||
late final controller = widget.controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() {
|
||||
if (controller.listAllIdentities.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Container(
|
||||
foregroundDecoration: BoxDecoration(
|
||||
border: Border.all(color: AppColor.colorBorderIdentityInfo, width: 1),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
|
||||
),
|
||||
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!)),
|
||||
],
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
import 'package:core/core.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';
|
||||
|
||||
class IdentityListTileBuilder extends StatelessWidget {
|
||||
const IdentityListTileBuilder({
|
||||
Key? key,
|
||||
required this.controller,
|
||||
required this.index,
|
||||
required this.selected
|
||||
}) : super(key: key);
|
||||
|
||||
final IdentitiesController controller;
|
||||
final int index;
|
||||
final int? selected;
|
||||
|
||||
@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<int>(
|
||||
value: index,
|
||||
groupValue: selected,
|
||||
onChanged: (selectedValue) => controller.selectIdentity(index),
|
||||
),
|
||||
),
|
||||
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!),
|
||||
),
|
||||
buildSVGIconButton(
|
||||
padding: const EdgeInsets.only(right: 0.0),
|
||||
icon: imagePaths.icDeleteOutline,
|
||||
iconSize: 24,
|
||||
iconColor: AppColor.colorActionDeleteConfirmDialog,
|
||||
onTap: () => controller.openConfirmationDialogDeleteIdentityAction(context, controller.identitySelected.value!),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _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
|
||||
Expanded(child: Text(
|
||||
text ?? '', style: const TextStyle(
|
||||
color: AppColor.colorEmailAddressFull,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 13,
|
||||
),
|
||||
overflow: CommonTextStyle.defaultTextOverFlow,
|
||||
softWrap: CommonTextStyle.defaultSoftWrap,
|
||||
)),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
bool isIdentitySelected(int index) {
|
||||
return index == selected;
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import 'package:core/core.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({
|
||||
Key? key,
|
||||
this.width,
|
||||
this.height,
|
||||
this.htmlSignature,
|
||||
this.textSignature,
|
||||
}) : super(key: key);
|
||||
|
||||
final Signature? htmlSignature;
|
||||
final Signature? textSignature;
|
||||
final double? width;
|
||||
final double? height;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final signatureWidth = width ?? constraints.biggest.width;
|
||||
final signatureHeight = height ?? constraints.biggest.height;
|
||||
return Container(
|
||||
width: signatureWidth,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
child: _buildSignature(signatureWidth, signatureHeight),
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSignature(double width, double height) {
|
||||
Widget signature;
|
||||
if (htmlSignature != null && htmlSignature!.value.isNotEmpty) {
|
||||
final htmlSignatureDecoded = _decodeHtml(htmlSignature!.value);
|
||||
if (BuildUtils.isWeb) {
|
||||
signature = HtmlContentViewerOnWeb(
|
||||
contentHtml: htmlSignatureDecoded,
|
||||
widthContent: width,
|
||||
heightContent: height,
|
||||
controller: HtmlViewerControllerForWeb(),
|
||||
allowResizeToDocumentSize: false);
|
||||
} else {
|
||||
signature = HtmlContentViewer(contentHtml: htmlSignatureDecoded, heightContent: height);
|
||||
}
|
||||
} else if (textSignature != null) {
|
||||
signature = Text(textSignature!.value);
|
||||
} else {
|
||||
signature = SizedBox.fromSize(size: Size(width, height));
|
||||
}
|
||||
return signature;
|
||||
}
|
||||
|
||||
String _decodeHtml(String htmlString) {
|
||||
final unescape = HtmlUnescape();
|
||||
return unescape.convert(htmlString);
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/signature_builder.dart';
|
||||
|
||||
class SignatureOfIdentityBuilder extends StatelessWidget {
|
||||
|
||||
SignatureOfIdentityBuilder({required this.identity});
|
||||
|
||||
final Identity identity;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SignatureBuilder(
|
||||
height: 256,
|
||||
htmlSignature: identity.htmlSignature,
|
||||
textSignature: identity.textSignature
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user