Skip to content

Commit dd50675

Browse files
authored
Merge 1a729b7 into f7fe987
2 parents f7fe987 + 1a729b7 commit dd50675

File tree

12 files changed

+380
-4
lines changed

12 files changed

+380
-4
lines changed

assets/images/ic_tag.svg

Lines changed: 5 additions & 0 deletions
Loading

core/lib/presentation/resources/image_paths.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ class ImagePaths {
261261
String get icRemoveLink => _getImagePath('ic_remove_link.svg');
262262
String get icText => _getImagePath('ic_text.svg');
263263
String get icUser => _getImagePath('ic_user.svg');
264+
String get icTag => _getImagePath('ic_tag.svg');
264265

265266
String _getImagePath(String imageName) {
266267
return AssetsPaths.images + imageName;

lib/features/labels/presentation/label_controller.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
55
import 'package:jmap_dart_client/jmap/core/session/session.dart';
66
import 'package:labels/model/label.dart';
77
import 'package:labels/utils/labels_constants.dart';
8+
import 'package:model/mailbox/expand_mode.dart';
89
import 'package:tmail_ui_user/features/base/base_controller.dart';
910
import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart';
1011
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
@@ -14,6 +15,7 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart';
1415

1516
class LabelController extends BaseController {
1617
final labels = <Label>[].obs;
18+
final labelListExpandMode = Rx(ExpandMode.EXPAND);
1719

1820
GetAllLabelInteractor? _getAllLabelInteractor;
1921

@@ -32,6 +34,12 @@ class LabelController extends BaseController {
3234
consumeState(_getAllLabelInteractor!.execute(accountId));
3335
}
3436

37+
void toggleLabelListState() {
38+
labelListExpandMode.value = labelListExpandMode.value == ExpandMode.COLLAPSE
39+
? ExpandMode.EXPAND
40+
: ExpandMode.COLLAPSE;
41+
}
42+
3543
@override
3644
void handleSuccessViewState(Success success) {
3745
if (success is GetAllLabelSuccess) {

lib/features/mailbox/presentation/base_mailbox_view.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_catego
1717
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
1818
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
1919
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folders_bar_widget.dart';
20+
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_list_view.dart';
21+
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/labels_bar_widget.dart';
2022
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_app_bar.dart';
2123
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_category_widget.dart';
2224
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_item_widget.dart';
@@ -333,7 +335,61 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
333335
? buildFolders(context)
334336
: const Offstage(),
335337
)),
338+
buildLabelsBar(context, isDesktop),
339+
buildLabelsList(context, isDesktop),
336340
]),
337341
);
338342
}
343+
344+
Widget buildLabelsBar(BuildContext context, bool isDesktop) {
345+
return Obx(() {
346+
if (controller.mailboxDashBoardController.isLabelCapabilitySupported) {
347+
final labelController =
348+
controller.mailboxDashBoardController.labelController;
349+
350+
final labelListExpandMode = labelController.labelListExpandMode.value;
351+
final countLabels = labelController.labels.length;
352+
353+
return LabelsBarWidget(
354+
imagePaths: controller.imagePaths,
355+
isDesktop: isDesktop,
356+
height: isDesktop ? 48 : 40,
357+
padding: isDesktop
358+
? null
359+
: const EdgeInsetsDirectional.only(start: 24, end: 12),
360+
labelStyle: isDesktop ? null : ThemeUtils.textStyleInter500(),
361+
expandMode: labelListExpandMode,
362+
countLabels: countLabels,
363+
onToggleLabelListState: labelController.toggleLabelListState,
364+
);
365+
} else {
366+
return const SizedBox.shrink();
367+
}
368+
});
369+
}
370+
371+
Widget buildLabelsList(BuildContext context, bool isDesktop) {
372+
return Obx(() {
373+
if (controller.mailboxDashBoardController.isLabelCapabilitySupported) {
374+
final labelController =
375+
controller.mailboxDashBoardController.labelController;
376+
377+
final labelListExpandMode = labelController.labelListExpandMode.value;
378+
final labels = labelController.labels;
379+
380+
return AnimatedContainer(
381+
duration: const Duration(milliseconds: 400),
382+
child: labelListExpandMode == ExpandMode.EXPAND && labels.isNotEmpty
383+
? LabelListView(
384+
labels: labels,
385+
imagePaths: controller.imagePaths,
386+
isDesktop: isDesktop,
387+
)
388+
: const Offstage(),
389+
);
390+
} else {
391+
return const SizedBox.shrink();
392+
}
393+
});
394+
}
339395
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'package:core/presentation/extensions/color_extension.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_svg/flutter_svg.dart';
4+
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_icon_widget_styles.dart';
5+
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
6+
7+
class LabelIconWidget extends StatelessWidget {
8+
final String icon;
9+
final double iconSize;
10+
final EdgeInsetsGeometry padding;
11+
final Color? color;
12+
13+
const LabelIconWidget({
14+
super.key,
15+
required this.icon,
16+
this.iconSize = MailboxIconWidgetStyles.iconSize,
17+
this.padding = const EdgeInsetsDirectional.only(
18+
end: MailboxItemWidgetStyles.labelIconSpace,
19+
),
20+
this.color,
21+
});
22+
23+
@override
24+
Widget build(BuildContext context) {
25+
return Padding(
26+
padding: padding,
27+
child: SvgPicture.asset(
28+
icon,
29+
width: iconSize,
30+
height: iconSize,
31+
colorFilter: color?.asFilter(),
32+
fit: BoxFit.fill,
33+
),
34+
);
35+
}
36+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import 'package:core/presentation/resources/image_paths.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:labels/extensions/label_extension.dart';
4+
import 'package:labels/model/label.dart';
5+
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
6+
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_icon_widget.dart';
7+
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_name_widget.dart';
8+
9+
class LabelListItem extends StatelessWidget {
10+
final Label label;
11+
final ImagePaths imagePaths;
12+
final bool isDesktop;
13+
14+
const LabelListItem({
15+
super.key,
16+
required this.label,
17+
required this.imagePaths,
18+
this.isDesktop = false,
19+
});
20+
21+
@override
22+
Widget build(BuildContext context) {
23+
final borderRadius = BorderRadius.all(
24+
Radius.circular(
25+
isDesktop
26+
? MailboxItemWidgetStyles.borderRadius
27+
: MailboxItemWidgetStyles.mobileBorderRadius,
28+
),
29+
);
30+
31+
return Material(
32+
type: MaterialType.transparency,
33+
child: InkWell(
34+
borderRadius: borderRadius,
35+
child: Container(
36+
decoration: BoxDecoration(borderRadius: borderRadius),
37+
padding: EdgeInsetsDirectional.symmetric(
38+
horizontal: isDesktop
39+
? MailboxItemWidgetStyles.itemPadding
40+
: MailboxItemWidgetStyles.mobileItemPadding,
41+
),
42+
height: isDesktop
43+
? MailboxItemWidgetStyles.height
44+
: MailboxItemWidgetStyles.mobileHeight,
45+
child: Row(
46+
mainAxisAlignment: MainAxisAlignment.center,
47+
children: [
48+
LabelIconWidget(
49+
icon: imagePaths.icTag,
50+
color: label.backgroundColor,
51+
padding: EdgeInsetsDirectional.only(
52+
end: isDesktop
53+
? MailboxItemWidgetStyles.mobileLabelIconSpace
54+
: MailboxItemWidgetStyles.labelIconSpace,
55+
),
56+
),
57+
Expanded(
58+
child: LabelNameWidget(
59+
name: label.safeDisplayName,
60+
isDesktop: isDesktop,
61+
),
62+
),
63+
],
64+
),
65+
),
66+
),
67+
);
68+
}
69+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'package:core/presentation/resources/image_paths.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:labels/model/label.dart';
4+
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_list_item.dart';
5+
6+
class LabelListView extends StatelessWidget {
7+
final List<Label> labels;
8+
final ImagePaths imagePaths;
9+
final bool isDesktop;
10+
11+
const LabelListView({
12+
super.key,
13+
required this.labels,
14+
required this.imagePaths,
15+
this.isDesktop = false,
16+
});
17+
18+
@override
19+
Widget build(BuildContext context) {
20+
Widget labelListView = ListView.builder(
21+
key: const PageStorageKey('label_list'),
22+
shrinkWrap: true,
23+
primary: false,
24+
padding: EdgeInsets.zero,
25+
itemCount: labels.length,
26+
itemBuilder: (context, index) {
27+
return LabelListItem(
28+
label: labels[index],
29+
imagePaths: imagePaths,
30+
isDesktop: isDesktop,
31+
);
32+
},
33+
);
34+
35+
if (!isDesktop) {
36+
labelListView = Padding(
37+
padding: const EdgeInsets.symmetric(horizontal: 12),
38+
child: labelListView,
39+
);
40+
}
41+
42+
return labelListView;
43+
}
44+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'package:core/presentation/utils/theme_utils.dart';
2+
import 'package:flutter/material.dart';
3+
4+
class LabelNameWidget extends StatelessWidget {
5+
final String name;
6+
final bool isDesktop;
7+
8+
const LabelNameWidget({
9+
super.key,
10+
required this.name,
11+
this.isDesktop = false,
12+
});
13+
14+
@override
15+
Widget build(BuildContext context) {
16+
return Text(
17+
name,
18+
style: isDesktop
19+
? ThemeUtils.textStyleBodyBody3(color: Colors.black)
20+
: ThemeUtils.textStyleInter500(),
21+
maxLines: 1,
22+
overflow: TextOverflow.ellipsis,
23+
);
24+
}
25+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import 'package:core/presentation/extensions/color_extension.dart';
2+
import 'package:core/presentation/resources/image_paths.dart';
3+
import 'package:core/presentation/utils/theme_utils.dart';
4+
import 'package:core/presentation/views/button/tmail_button_widget.dart';
5+
import 'package:core/utils/direction_utils.dart';
6+
import 'package:flutter/material.dart';
7+
import 'package:model/mailbox/expand_mode.dart';
8+
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/expand_mode_extension.dart';
9+
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
10+
11+
class LabelsBarWidget extends StatelessWidget {
12+
final ImagePaths imagePaths;
13+
final bool isDesktop;
14+
final double? height;
15+
final int countLabels;
16+
final EdgeInsetsGeometry? padding;
17+
final TextStyle? labelStyle;
18+
final ExpandMode? expandMode;
19+
final VoidCallback? onToggleLabelListState;
20+
final VoidCallback? onAddNewLabel;
21+
22+
const LabelsBarWidget({
23+
super.key,
24+
required this.imagePaths,
25+
this.isDesktop = false,
26+
this.countLabels = 0,
27+
this.height,
28+
this.padding,
29+
this.labelStyle,
30+
this.expandMode,
31+
this.onToggleLabelListState,
32+
this.onAddNewLabel,
33+
});
34+
35+
@override
36+
Widget build(BuildContext context) {
37+
Widget addNewLabelIcon = TMailButtonWidget.fromIcon(
38+
icon: imagePaths.icAddNewFolder,
39+
backgroundColor: Colors.transparent,
40+
iconColor: AppColor.steelGrayA540,
41+
iconSize: 20,
42+
padding: const EdgeInsets.all(5),
43+
tooltipMessage: AppLocalizations.of(context).newLabel,
44+
onTapActionCallback: onAddNewLabel,
45+
);
46+
47+
if (isDesktop) {
48+
addNewLabelIcon = Transform(
49+
transform: Matrix4.translationValues(8, 0, 0),
50+
child: addNewLabelIcon,
51+
);
52+
}
53+
54+
final labelText = Text(
55+
AppLocalizations.of(context).labels,
56+
style: labelStyle ?? ThemeUtils.textStyleInter700(),
57+
maxLines: 1,
58+
overflow: TextOverflow.ellipsis,
59+
);
60+
61+
return Container(
62+
padding: padding ??
63+
EdgeInsetsDirectional.only(
64+
start: isDesktop ? 10 : 26,
65+
end: isDesktop ? 0 : 8,
66+
),
67+
height: height ?? 48,
68+
child: Row(
69+
children: [
70+
if (expandMode != null && countLabels > 0)
71+
Expanded(
72+
child: Row(
73+
children: [
74+
Flexible(child: labelText),
75+
TMailButtonWidget.fromIcon(
76+
icon: expandMode!.getIcon(
77+
imagePaths,
78+
DirectionUtils.isDirectionRTLByLanguage(context),
79+
),
80+
iconColor: Colors.black,
81+
iconSize: 17,
82+
margin: isDesktop
83+
? const EdgeInsetsDirectional.only(start: 8)
84+
: null,
85+
backgroundColor: Colors.transparent,
86+
padding: const EdgeInsets.all(3),
87+
tooltipMessage: expandMode!
88+
.getTooltipMessage(AppLocalizations.of(context)),
89+
onTapActionCallback: onToggleLabelListState,
90+
),
91+
],
92+
),
93+
)
94+
else
95+
Expanded(child: labelText),
96+
if (onAddNewLabel != null)
97+
addNewLabelIcon,
98+
],
99+
),
100+
);
101+
}
102+
}

0 commit comments

Comments
 (0)