TF-80 Create pick destination screen
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_api.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/data/repository/mailbox_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart';
|
||||
|
||||
class DestinationPickerBindings extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut(() => MailboxDataSourceImpl(Get.find<MailboxAPI>()));
|
||||
Get.lazyPut<MailboxDataSource>(() => Get.find<MailboxDataSourceImpl>());
|
||||
Get.lazyPut(() => MailboxRepositoryImpl(Get.find<MailboxDataSource>()));
|
||||
Get.lazyPut<MailboxRepository>(() => Get.find<MailboxRepositoryImpl>());
|
||||
Get.lazyPut(() => GetAllMailboxInteractor(Get.find<MailboxRepository>()));
|
||||
Get.lazyPut(() => TreeBuilder());
|
||||
Get.put(DestinationPickerController(
|
||||
Get.find<GetAllMailboxInteractor>(),
|
||||
Get.find<TreeBuilder>()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.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/model/mailbox_tree_builder.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
class DestinationPickerController extends BaseController {
|
||||
|
||||
final GetAllMailboxInteractor _getAllMailboxInteractor;
|
||||
final TreeBuilder _treeBuilder;
|
||||
|
||||
final folderMailboxTree = MailboxTree(MailboxNode.root()).obs;
|
||||
|
||||
DestinationPickerArguments? destinationPickerArguments;
|
||||
|
||||
DestinationPickerController(
|
||||
this._getAllMailboxInteractor,
|
||||
this._treeBuilder,
|
||||
);
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
if (Get.arguments != null && Get.arguments is DestinationPickerArguments) {
|
||||
destinationPickerArguments = Get.arguments;
|
||||
getAllMailboxAction();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onData(Either<Failure, Success> newState) {
|
||||
super.onData(newState);
|
||||
newState.map((success) {
|
||||
if (success is GetAllMailboxSuccess) {
|
||||
_buildTree(success.folderMailboxList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onDone() {}
|
||||
|
||||
@override
|
||||
void onError(error) {}
|
||||
|
||||
void getAllMailboxAction() {
|
||||
final accountId = destinationPickerArguments?.accountId;
|
||||
if (accountId != null) {
|
||||
consumeState(_getAllMailboxInteractor.execute(accountId));
|
||||
}
|
||||
}
|
||||
|
||||
void _buildTree(List<PresentationMailbox> folderMailboxList) async {
|
||||
folderMailboxTree.value = await _treeBuilder.generateMailboxTree(folderMailboxList);
|
||||
}
|
||||
|
||||
void moveEmailToMailboxAction(PresentationMailbox destinationMailbox) {
|
||||
popBack();
|
||||
}
|
||||
|
||||
void closeDestinationPicker() {
|
||||
popBack();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
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/destination_picker/presentation/destination_picker_controller.dart';
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.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/widgets/mailbox_folder_tile_builder.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_tile_builder.dart';
|
||||
|
||||
class DestinationPickerView extends GetWidget<DestinationPickerController> {
|
||||
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () => controller.closeDestinationPicker(),
|
||||
child: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
borderOnForeground: false,
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
margin: _responsiveUtils.getMarginDestinationPicker(context),
|
||||
child: ClipRRect(
|
||||
borderRadius: _responsiveUtils.radiusDestinationPicker(context, 20),
|
||||
child: GestureDetector(
|
||||
onTap: () => {},
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
backgroundColor: Colors.white,
|
||||
body: SafeArea(
|
||||
right: false,
|
||||
left: false,
|
||||
child: Column(
|
||||
children: [
|
||||
_buildAppBar(context),
|
||||
Expanded(child: _buildBodyDestinationPicker(context))
|
||||
],
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppBar(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 12),
|
||||
child: (AppBarDestinationPickerBuilder(context, _imagePaths, _responsiveUtils)
|
||||
..addCloseActionClick(() => controller.closeDestinationPicker()))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBodyDestinationPicker(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
color: AppColor.primaryColor,
|
||||
onRefresh: () async => controller.getAllMailboxAction(),
|
||||
child: SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
color: AppColor.bgMailboxListMail,
|
||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildLoadingView(),
|
||||
_buildListMailbox(context)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoadingView() {
|
||||
return Obx(() => controller.viewState.value.fold(
|
||||
(failure) => SizedBox.shrink(),
|
||||
(success) => success == UIState.loading
|
||||
? Center(child: Padding(
|
||||
padding: EdgeInsets.only(top: 16),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(color: AppColor.primaryColor))))
|
||||
: SizedBox.shrink()));
|
||||
}
|
||||
|
||||
Widget _buildListMailbox(BuildContext context) {
|
||||
return ListView(
|
||||
primary: false,
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
_buildDefaultMailbox(context),
|
||||
SizedBox(height: 20),
|
||||
_buildFolderMailbox(context),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDefaultMailbox(BuildContext context) {
|
||||
return Obx(() => controller.viewState.value.fold(
|
||||
(failure) => SizedBox.shrink(),
|
||||
(success) {
|
||||
if (success is GetAllMailboxSuccess) {
|
||||
final defaultMailboxList = success.defaultMailboxList;
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.only(top: 16, right: 10),
|
||||
key: Key('default_mailbox_list'),
|
||||
itemCount: defaultMailboxList.length,
|
||||
shrinkWrap: true,
|
||||
primary: false,
|
||||
itemBuilder: (context, index) => (MailboxTileBuilder(
|
||||
context,
|
||||
_imagePaths,
|
||||
_responsiveUtils,
|
||||
defaultMailboxList[index],
|
||||
mailboxDisplayed: MailboxDisplayed.destinationPicker)
|
||||
..onOpenMailboxAction((mailbox) => controller.moveEmailToMailboxAction(mailbox)))
|
||||
.build());
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFolderMailbox(BuildContext context) {
|
||||
return Obx(() => controller.folderMailboxTree.value.root.hasChildren()
|
||||
? Transform(
|
||||
transform: Matrix4.translationValues(-12.0, 0.0, 0.0),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.zero,
|
||||
child: TreeView(
|
||||
startExpanded: false,
|
||||
key: Key('folder_mailbox_list'),
|
||||
children: _buildListChildTileWidget(context, controller.folderMailboxTree.value.root.childrenItems!))))
|
||||
: SizedBox.shrink()
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildListChildTileWidget(BuildContext context, List<MailboxNode> listMailboxNode) {
|
||||
return listMailboxNode
|
||||
.map((mailboxNode) => mailboxNode.hasChildren()
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(left: 20),
|
||||
child: TreeViewChild(
|
||||
key: Key('children_tree_mailbox_child'),
|
||||
parent: MailBoxFolderTileBuilder(
|
||||
context,
|
||||
_imagePaths,
|
||||
_responsiveUtils,
|
||||
mailboxNode,
|
||||
mailboxDisplayed: MailboxDisplayed.destinationPicker)
|
||||
.build(),
|
||||
children: _buildListChildTileWidget(context, mailboxNode.childrenItems!)))
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(left: 20),
|
||||
child: GestureDetector(
|
||||
onTap: () => controller.moveEmailToMailboxAction(mailboxNode.item),
|
||||
child: MailBoxFolderTileBuilder(
|
||||
context,
|
||||
_imagePaths,
|
||||
_responsiveUtils,
|
||||
mailboxNode,
|
||||
mailboxDisplayed: MailboxDisplayed.destinationPicker)
|
||||
.build(),
|
||||
)))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
|
||||
class DestinationPickerArguments with EquatableMixin{
|
||||
final AccountId accountId;
|
||||
final List<EmailId> emailIds;
|
||||
final MailboxId currentMailboxId;
|
||||
|
||||
DestinationPickerArguments(this.accountId, this.emailIds, this.currentMailboxId);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [accountId, emailIds, currentMailboxId];
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnCloseActionClick = void Function();
|
||||
|
||||
class AppBarDestinationPickerBuilder {
|
||||
OnCloseActionClick? _onCloseActionClick;
|
||||
|
||||
final BuildContext _context;
|
||||
final ImagePaths _imagePaths;
|
||||
final ResponsiveUtils _responsiveUtils;
|
||||
|
||||
AppBarDestinationPickerBuilder(this._context, this._imagePaths, this._responsiveUtils);
|
||||
|
||||
void addCloseActionClick(OnCloseActionClick onCloseActionClick) {
|
||||
_onCloseActionClick = onCloseActionClick;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return Container(
|
||||
key: Key('app_bar_destination_picker'),
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
color: Colors.white,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
_buildBackButton(),
|
||||
Expanded(child: _buildCountItemSelected())
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBackButton() {
|
||||
return ButtonBuilder(_imagePaths.icComposerClose)
|
||||
.padding(5)
|
||||
.size(30)
|
||||
.onPressActionClick(() {
|
||||
if (_onCloseActionClick != null) {
|
||||
_onCloseActionClick!();
|
||||
}})
|
||||
.build();
|
||||
}
|
||||
|
||||
Widget _buildCountItemSelected() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 12,
|
||||
right: _responsiveUtils.isMobile(_context) ? 0 : 47),
|
||||
child: Text(
|
||||
AppLocalizations.of(_context).move_to_mailbox,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: _responsiveUtils.isMobile(_context) ? TextAlign.start : TextAlign.center,
|
||||
style: TextStyle(fontSize: 18, color: AppColor.nameUserColor, fontWeight: FontWeight.w500)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user