TF-4179 Display tag list in sidebar

This commit is contained in:
dab246
2025-11-25 18:54:54 +07:00
committed by Dat H. Pham
parent 75f55e6507
commit e2fe0a0676
8 changed files with 215 additions and 4 deletions
@@ -17,6 +17,7 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_catego
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folders_bar_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_list_view.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/labels_bar_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_app_bar.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_category_widget.dart';
@@ -338,6 +339,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
: const Offstage(),
)),
buildLabelsBar(context, isDesktop),
buildLabelsList(context, isDesktop),
]),
);
}
@@ -345,11 +347,11 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
Widget buildLabelsBar(BuildContext context, bool isDesktop) {
return Obx(() {
if (controller.mailboxDashBoardController.isLabelCapabilitySupported) {
final labelController = controller
.mailboxDashBoardController
.labelController;
final labelController =
controller.mailboxDashBoardController.labelController;
final labelListExpandMode = labelController.labelListExpandMode.value;
final countLabels = labelController.labels.length;
return LabelsBarWidget(
imagePaths: controller.imagePaths,
@@ -360,6 +362,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
: const EdgeInsetsDirectional.only(start: 24, end: 12),
labelStyle: isDesktop ? null : ThemeUtils.textStyleInter500(),
expandMode: labelListExpandMode,
countLabels: countLabels,
onToggleLabelListState: labelController.toggleLabelListState,
);
} else {
@@ -367,4 +370,29 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
}
});
}
Widget buildLabelsList(BuildContext context, bool isDesktop) {
return Obx(() {
if (controller.mailboxDashBoardController.isLabelCapabilitySupported) {
final labelController =
controller.mailboxDashBoardController.labelController;
final labelListExpandMode = labelController.labelListExpandMode.value;
final labels = labelController.labels;
return AnimatedContainer(
duration: const Duration(milliseconds: 400),
child: labelListExpandMode == ExpandMode.EXPAND && labels.isNotEmpty
? LabelListView(
labels: labels,
imagePaths: controller.imagePaths,
isDesktop: isDesktop,
)
: const Offstage(),
);
} else {
return const SizedBox.shrink();
}
});
}
}
@@ -0,0 +1,36 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_icon_widget_styles.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
class LabelIconWidget extends StatelessWidget {
final String icon;
final double iconSize;
final EdgeInsetsGeometry padding;
final Color? color;
const LabelIconWidget({
super.key,
required this.icon,
this.iconSize = MailboxIconWidgetStyles.iconSize,
this.padding = const EdgeInsetsDirectional.only(
end: MailboxItemWidgetStyles.labelIconSpace,
),
this.color,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: padding,
child: SvgPicture.asset(
icon,
width: iconSize,
height: iconSize,
colorFilter: color?.asFilter(),
fit: BoxFit.fill,
),
);
}
}
@@ -0,0 +1,70 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart';
import 'package:labels/extensions/label_extension.dart';
import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_icon_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_name_widget.dart';
class LabelListItem extends StatelessWidget {
final Label label;
final ImagePaths imagePaths;
final bool isDesktop;
const LabelListItem({
super.key,
required this.label,
required this.imagePaths,
this.isDesktop = false,
});
@override
Widget build(BuildContext context) {
final borderRadius = BorderRadius.all(
Radius.circular(
isDesktop
? MailboxItemWidgetStyles.mobileBorderRadius
: MailboxItemWidgetStyles.borderRadius,
),
);
return Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
borderRadius: borderRadius,
child: Container(
decoration: BoxDecoration(borderRadius: borderRadius),
padding: EdgeInsetsDirectional.symmetric(
horizontal: isDesktop
? MailboxItemWidgetStyles.mobileItemPadding
: MailboxItemWidgetStyles.itemPadding,
),
height: isDesktop
? MailboxItemWidgetStyles.mobileHeight
: MailboxItemWidgetStyles.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
LabelIconWidget(
icon: imagePaths.icTag,
color: label.backgroundColor,
padding: EdgeInsetsDirectional.only(
end: isDesktop
? MailboxItemWidgetStyles.labelIconSpace
: MailboxItemWidgetStyles.mobileLabelIconSpace,
),
),
Expanded(
child: LabelNameWidget(
name: label.safeDisplayName,
isDesktop: isDesktop,
),
),
],
),
),
),
);
}
}
@@ -0,0 +1,44 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart';
import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_list_item.dart';
class LabelListView extends StatelessWidget {
final List<Label> labels;
final ImagePaths imagePaths;
final bool isDesktop;
const LabelListView({
super.key,
required this.labels,
required this.imagePaths,
this.isDesktop = false,
});
@override
Widget build(BuildContext context) {
Widget labelListView = ListView.builder(
key: const PageStorageKey('label_list'),
shrinkWrap: true,
primary: false,
padding: EdgeInsets.zero,
itemCount: labels.length,
itemBuilder: (context, index) {
return LabelListItem(
label: labels[index],
imagePaths: imagePaths,
isDesktop: isDesktop,
);
},
);
if (!isDesktop) {
labelListView = Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: labelListView,
);
}
return labelListView;
}
}
@@ -0,0 +1,25 @@
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
class LabelNameWidget extends StatelessWidget {
final String name;
final bool isDesktop;
const LabelNameWidget({
super.key,
required this.name,
this.isDesktop = false,
});
@override
Widget build(BuildContext context) {
return Text(
name,
style: isDesktop
? ThemeUtils.textStyleBodyBody3(color: Colors.black)
: ThemeUtils.textStyleInter500(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
}
@@ -12,6 +12,7 @@ class LabelsBarWidget extends StatelessWidget {
final ImagePaths imagePaths;
final bool isDesktop;
final double? height;
final int countLabels;
final EdgeInsetsGeometry? padding;
final TextStyle? labelStyle;
final ExpandMode? expandMode;
@@ -22,6 +23,7 @@ class LabelsBarWidget extends StatelessWidget {
super.key,
required this.imagePaths,
this.isDesktop = false,
this.countLabels = 0,
this.height,
this.padding,
this.labelStyle,
@@ -65,7 +67,7 @@ class LabelsBarWidget extends StatelessWidget {
height: height ?? 48,
child: Row(
children: [
if (expandMode != null)
if (expandMode != null && countLabels > 0)
Expanded(
child: Row(
children: [