TF-1194 apply new design identity to manage identity screen in mobile

This commit is contained in:
sherlockvn
2022-12-27 14:17:37 +07:00
committed by Dat H. Pham
parent 0144c2cbfa
commit 200e106c19
13 changed files with 435 additions and 176 deletions
@@ -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!)),
],
),
));
});
}
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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
);
}
}