TF-4171 Display tag in mailbox list, search list on mobile

This commit is contained in:
dab246
2025-11-28 03:18:40 +07:00
committed by Dat H. Pham
parent 0ab57402a0
commit 5fb0aa84e8
11 changed files with 843 additions and 184 deletions
@@ -73,7 +73,7 @@ class LabelUtils {
}
final remainingCount = total - 1;
final plus = _buildPlusLabel(remainingCount);
final plus = buildPlusLabel(remainingCount);
double plusWidth = effectiveMeasure(plus);
if (plusMaxWidth != null) {
@@ -97,7 +97,7 @@ class LabelUtils {
// Normal shrink logic
while (fitCount > 0) {
final plus = _buildPlusLabel(remaining);
final plus = buildPlusLabel(remaining);
double plusWidth = effectiveMeasure(plus);
if (plusMaxWidth != null) {
@@ -151,7 +151,7 @@ class LabelUtils {
plusMaxWidth: plusMaxWidth,
measureWidth: measureWidth,
);
} catch (_, __) {
} catch (_) {
if (tags.isEmpty) {
return (displayed: const [], hiddenCount: 0);
}
@@ -186,8 +186,61 @@ class LabelUtils {
return (fitCount: fit, usedWidth: used);
}
static Label _buildPlusLabel(int n) => Label(
static Label buildPlusLabel(int n) => Label(
id: Id(LabelExtension.moreLabelId),
displayName: n > 999 ? '+999+' : '+$n',
);
static ({
List<Label> displayed,
int hiddenCount,
}) computeDisplayedLabelsByMaxDisplay({
required List<Label> labels,
int maxDisplay = 3,
}) {
if (labels.isEmpty) {
return (displayed: [], hiddenCount: 0);
}
final limited =
labels.length <= maxDisplay ? labels : labels.take(maxDisplay).toList();
final hiddenCount =
labels.length > maxDisplay ? labels.length - maxDisplay : 0;
return (displayed: limited, hiddenCount: hiddenCount);
}
static ({
List<Label> displayed,
int hiddenCount,
}) safeComputeDisplayedLabelsByMaxDisplay({
required List<Label> labels,
int maxDisplay = 3,
}) {
try {
return computeDisplayedLabelsByMaxDisplay(
labels: labels,
maxDisplay: maxDisplay,
);
} catch (_) {
if (labels.isEmpty) {
return (displayed: const [], hiddenCount: 0);
}
return (
displayed: [labels.first],
hiddenCount: labels.length - 1,
);
}
}
static String truncateLabel(String name, {int maxLength = 16}) {
try {
if (name.length <= maxLength) return name;
return '${name.substring(0, maxLength - 1)}...';
} catch (_) {
return name;
}
}
}
@@ -8,16 +8,26 @@ class LabelTagListWidget extends StatelessWidget {
final List<Label> tags;
final double horizontalPadding;
final double itemSpacing;
final bool autoWrapTagsByMaxWidth;
final bool isDesktop;
const LabelTagListWidget({
super.key,
required this.tags,
this.horizontalPadding = 4,
this.itemSpacing = 12,
this.autoWrapTagsByMaxWidth = false,
this.isDesktop = false,
});
@override
Widget build(BuildContext context) {
return autoWrapTagsByMaxWidth
? _buildAutoWrapMode()
: _buildFixedDisplayMode();
}
Widget _buildAutoWrapMode() {
return LayoutBuilder(
builder: (_, constraints) {
final maxWidth = constraints.maxWidth;
@@ -25,7 +35,7 @@ class LabelTagListWidget extends StatelessWidget {
final tagMaxWidth =
maxWidth - LabelUtils.defaultPlusMaxWidth - itemSpacing;
final displayedTagsDataResult = LabelUtils.safeComputeDisplayedTags(
final result = LabelUtils.safeComputeDisplayedTags(
tags: tags,
maxWidth: maxWidth,
textStyle: ThemeUtils.textStyleContentCaption(),
@@ -38,7 +48,7 @@ class LabelTagListWidget extends StatelessWidget {
return Wrap(
spacing: itemSpacing,
runSpacing: 6,
children: displayedTagsDataResult.displayed
children: result.displayed
.map(
(tagDisplayed) => LabelWidget(
label: tagDisplayed,
@@ -51,4 +61,35 @@ class LabelTagListWidget extends StatelessWidget {
},
);
}
Widget _buildFixedDisplayMode() {
final result = LabelUtils.safeComputeDisplayedLabelsByMaxDisplay(
labels: tags,
maxDisplay: isDesktop ? 3 : 1,
);
final displayedWidgets = result.displayed.map((label) {
return LabelWidget(
label: label,
horizontalPadding: horizontalPadding,
isTruncateLabel: true,
);
});
final plusWidget = (result.hiddenCount > 0)
? LabelWidget(
label: LabelUtils.buildPlusLabel(result.hiddenCount),
horizontalPadding: horizontalPadding,
)
: null;
return Wrap(
spacing: itemSpacing,
runSpacing: 6,
children: [
...displayedWidgets,
if (plusWidget != null) plusWidget,
],
);
}
}
@@ -1,3 +1,4 @@
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart';
import 'package:labels/extensions/label_extension.dart';
import 'package:labels/model/label.dart';
@@ -7,22 +8,29 @@ class LabelWidget extends StatelessWidget {
final Label label;
final double horizontalPadding;
final double? maxWidth;
final bool isTruncateLabel;
const LabelWidget({
super.key,
required this.label,
this.horizontalPadding = 4,
this.maxWidth,
this.isTruncateLabel = false,
});
@override
Widget build(BuildContext context) {
final showTooltip =
PlatformInfo.isWeb && label.id?.value != LabelExtension.moreLabelId;
return TagWidget(
text: label.safeDisplayName,
backgroundColor: label.backgroundColor,
textColor: label.textColor,
horizontalPadding: horizontalPadding,
maxWidth: maxWidth,
isTruncateText: isTruncateLabel,
showTooltip: showTooltip,
);
}
}