TF-4002 Apply new design for folder creation modal on web

This commit is contained in:
dab246
2025-09-04 15:06:28 +07:00
committed by Dat H. Pham
parent c09a2c92b2
commit 36e58fc990
23 changed files with 689 additions and 498 deletions
@@ -1,92 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnCancelActionClick = void Function();
typedef OnDoneActionClick = void Function();
class AppBarMailboxCreatorBuilder {
OnCancelActionClick? _cancelActionClick;
OnDoneActionClick? _onDoneActionClick;
final BuildContext _context;
final bool isValidated;
final String? title;
AppBarMailboxCreatorBuilder(
this._context,
{
this.title,
this.isValidated = false
}
);
void addOnCancelActionClick(OnCancelActionClick onCancelActionClick) {
_cancelActionClick = onCancelActionClick;
}
void addOnDoneActionClick(OnDoneActionClick onDoneActionClick) {
_onDoneActionClick = onDoneActionClick;
}
Widget build() {
return Container(
color: Colors.white,
height: 52,
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(children: [
_buildCancelButton(),
Expanded(child: _buildTitle()),
_buildCreateButton()
])
);
}
Widget _buildCancelButton() {
return Material(
borderRadius: BorderRadius.circular(20),
color: Colors.transparent,
child: TextButton(
child: Text(
AppLocalizations.of(_context).cancel,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(fontSize: 17, color: AppColor.colorTextButton),
),
onPressed: () => _cancelActionClick?.call()
)
);
}
Widget _buildCreateButton() {
return Material(
borderRadius: BorderRadius.circular(20),
color: Colors.transparent,
child: TextButton(
child: Text(
AppLocalizations.of(_context).done,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 17,
color: isValidated
? AppColor.colorTextButton
: AppColor.colorDisableMailboxCreateButton),
),
onPressed: () => isValidated ? _onDoneActionClick?.call() : null
)
);
}
Widget _buildTitle() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(
title ?? '',
textAlign: TextAlign.center,
maxLines: 1,
softWrap: CommonTextStyle.defaultSoftWrap,
overflow: CommonTextStyle.defaultTextOverFlow,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 20,
color: AppColor.colorNameEmail,
fontWeight: FontWeight.bold)));
}
}
@@ -1,36 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
class CreateMailboxNameInputDecorationBuilder extends InputDecorationBuilder {
@override
InputDecoration build() {
return InputDecoration(
enabledBorder: enabledBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.colorInputBorderCreateMailbox)),
focusedBorder: enabledBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.colorTextButton)),
errorBorder: errorBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.colorInputBorderErrorVerifyName)),
focusedErrorBorder: errorBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.colorInputBorderErrorVerifyName)),
prefixText: prefixText,
labelText: labelText,
floatingLabelBehavior: FloatingLabelBehavior.never,
labelStyle: labelStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(color: AppColor.colorNameEmail, fontSize: 16),
hintText: hintText,
hintStyle: hintStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(color: AppColor.colorHintInputCreateMailbox, fontSize: 16),
contentPadding: contentPadding ?? const EdgeInsets.all(12),
errorText: errorText,
errorStyle: errorTextStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(color: AppColor.colorInputBorderErrorVerifyName, fontSize: 13),
filled: true,
fillColor: errorText?.isNotEmpty == true
? AppColor.colorInputBackgroundErrorVerifyName
: AppColor.colorInputBackgroundCreateMailbox);
}
}
@@ -0,0 +1,114 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/list/tree_view.dart';
import 'package:flutter/material.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/expand_mode.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_displayed.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_method_action_define.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folder_item_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_item_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class ModalFolderTreeListWidget extends StatelessWidget {
final MailboxTree defaultTree;
final MailboxTree personalTree;
final ScrollController listScrollController;
final ImagePaths imagePaths;
final OnClickOpenMailboxNodeAction onSelectFolderAction;
final OnClickExpandMailboxNodeAction onToggleFolderAction;
final MailboxId? mailboxIdSelected;
const ModalFolderTreeListWidget({
super.key,
required this.defaultTree,
required this.personalTree,
required this.listScrollController,
required this.imagePaths,
required this.onSelectFolderAction,
required this.onToggleFolderAction,
this.mailboxIdSelected,
});
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
physics: const ClampingScrollPhysics(),
controller: listScrollController,
padding: const EdgeInsetsDirectional.only(end: 14),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FolderItemWidget(
folderName: AppLocalizations.of(context).personalFolders,
imagePaths: imagePaths,
isSelected: mailboxIdSelected == null,
onTapAction: () => onSelectFolderAction(null),
),
if (defaultTree.root.hasChildren())
_buildFolderTree(
mailboxTree: defaultTree,
mailboxIdSelected: mailboxIdSelected,
),
if (personalTree.root.hasChildren())
_buildFolderTree(
mailboxTree: personalTree,
mailboxIdSelected: mailboxIdSelected,
),
],
),
);
}
Widget _buildFolderTree({
required MailboxTree mailboxTree,
MailboxId? mailboxIdSelected,
}) {
return TreeView(
children: _buildListChildTileWidget(
parentNode: mailboxTree.root,
mailboxIdSelected: mailboxIdSelected,
),
);
}
List<Widget> _buildListChildTileWidget({
required MailboxNode parentNode,
MailboxId? mailboxIdSelected,
}) {
return parentNode.childrenItems?.map(
(mailboxNode) {
if (mailboxNode.hasChildren()) {
return TreeViewChild(
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
paddingChild: const EdgeInsetsDirectional.only(start: 14),
parent: MailboxItemWidget(
mailboxNode: mailboxNode,
mailboxIdAlreadySelected: mailboxIdSelected,
mailboxDisplayed: MailboxDisplayed.modalFolder,
hoverColor: AppColor.blue100,
onOpenMailboxFolderClick: onSelectFolderAction,
onExpandFolderActionClick: onToggleFolderAction,
),
children: _buildListChildTileWidget(
parentNode: mailboxNode,
mailboxIdSelected: mailboxIdSelected,
),
).build();
} else {
return MailboxItemWidget(
mailboxNode: mailboxNode,
mailboxDisplayed: MailboxDisplayed.modalFolder,
mailboxIdAlreadySelected: mailboxIdSelected,
hoverColor: AppColor.blue100,
onOpenMailboxFolderClick: onSelectFolderAction,
onExpandFolderActionClick: onToggleFolderAction,
);
}
},
).toList() ?? [];
}
}