fix(mobile): fix overflow text in backup card (#24448)

* fix(mobile): fix overflow text in backup card

* refactor: use intrinsicheight

* chore: fix spelling of entitycounttile
This commit is contained in:
Yaros
2025-12-09 16:03:29 +01:00
committed by GitHub
parent 287f6d5c94
commit c360781565
2 changed files with 113 additions and 102 deletions

View File

@@ -2,26 +2,27 @@ import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart';
class EntitiyCountTile extends StatelessWidget { class EntityCountTile extends StatelessWidget {
final int count; final int count;
final String label; final String label;
final IconData icon; final IconData icon;
const EntitiyCountTile({super.key, required this.count, required this.label, required this.icon}); const EntityCountTile({super.key, required this.count, required this.label, required this.icon});
String zeroPadding(int number, int targetWidth) { String zeroPadding(int number, int targetWidth) {
final numStr = number.toString(); final numStr = number.toString();
return numStr.length < targetWidth ? "0" * (targetWidth - numStr.length) : ""; return numStr.length < targetWidth ? "0" * (targetWidth - numStr.length) : "";
} }
int calculateMaxDigits(double availableWidth) {
const double charWidth = 11.0;
return (availableWidth / charWidth).floor().clamp(1, 8);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final availableWidth = (screenWidth - 32 - 8) / 2;
const double charWidth = 11.0;
final maxDigits = ((availableWidth - 32) / charWidth).floor().clamp(1, 8);
return Container( return Container(
height: double.infinity,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: context.colorScheme.surfaceContainerLow, color: context.colorScheme.surfaceContainerLow,
@@ -29,7 +30,6 @@ class EntitiyCountTile extends StatelessWidget {
border: Border.all(width: 0.5, color: context.colorScheme.outline.withAlpha(25)), border: Border.all(width: 0.5, color: context.colorScheme.outline.withAlpha(25)),
), ),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
// Icon and Label // Icon and Label
@@ -38,18 +38,17 @@ class EntitiyCountTile extends StatelessWidget {
children: [ children: [
Icon(icon, color: context.primaryColor), Icon(icon, color: context.primaryColor),
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Flexible(
child: Text(
label, label,
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16), style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16),
), ),
),
], ],
), ),
const SizedBox(height: 12),
// Number // Number
LayoutBuilder( const Spacer(),
builder: (context, constraints) { RichText(
final maxDigits = calculateMaxDigits(constraints.maxWidth);
return RichText(
text: TextSpan( text: TextSpan(
style: const TextStyle(fontSize: 18, fontFamily: 'OverpassMono', fontWeight: FontWeight.w600), style: const TextStyle(fontSize: 18, fontFamily: 'OverpassMono', fontWeight: FontWeight.w600),
children: [ children: [
@@ -63,8 +62,6 @@ class EntitiyCountTile extends StatelessWidget {
), ),
], ],
), ),
);
},
), ),
], ],
), ),

View File

@@ -282,20 +282,24 @@ class _SyncStatsCounts extends ConsumerWidget {
_SectionHeaderText(text: "assets".t(context: context)), _SectionHeaderText(text: "assets".t(context: context)),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
// 1. Wrap in IntrinsicHeight
child: IntrinsicHeight(
child: Flex( child: Flex(
direction: Axis.horizontal, direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
// 2. Stretch children vertically to fill the IntrinsicHeight
crossAxisAlignment: CrossAxisAlignment.stretch,
spacing: 8.0, spacing: 8.0,
children: [ children: [
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "local".t(context: context), label: "local".t(context: context),
count: localAssetCount, count: localAssetCount,
icon: Icons.smartphone, icon: Icons.smartphone,
), ),
), ),
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "remote".t(context: context), label: "remote".t(context: context),
count: remoteAssetCount, count: remoteAssetCount,
icon: Icons.cloud, icon: Icons.cloud,
@@ -304,23 +308,26 @@ class _SyncStatsCounts extends ConsumerWidget {
], ],
), ),
), ),
),
_SectionHeaderText(text: "albums".t(context: context)), _SectionHeaderText(text: "albums".t(context: context)),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
child: IntrinsicHeight(
child: Flex( child: Flex(
direction: Axis.horizontal, direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch, // Added
spacing: 8.0, spacing: 8.0,
children: [ children: [
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "local".t(context: context), label: "local".t(context: context),
count: localAlbumCount, count: localAlbumCount,
icon: Icons.smartphone, icon: Icons.smartphone,
), ),
), ),
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "remote".t(context: context), label: "remote".t(context: context),
count: remoteAlbumCount, count: remoteAlbumCount,
icon: Icons.cloud, icon: Icons.cloud,
@@ -329,23 +336,26 @@ class _SyncStatsCounts extends ConsumerWidget {
], ],
), ),
), ),
),
_SectionHeaderText(text: "other".t(context: context)), _SectionHeaderText(text: "other".t(context: context)),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
child: IntrinsicHeight(
child: Flex( child: Flex(
direction: Axis.horizontal, direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch, // Added
spacing: 8.0, spacing: 8.0,
children: [ children: [
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "memories".t(context: context), label: "memories".t(context: context),
count: memoryCount, count: memoryCount,
icon: Icons.calendar_today, icon: Icons.calendar_today,
), ),
), ),
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "hashed_assets".t(context: context), label: "hashed_assets".t(context: context),
count: localHashedCount, count: localHashedCount,
icon: Icons.tag, icon: Icons.tag,
@@ -354,6 +364,7 @@ class _SyncStatsCounts extends ConsumerWidget {
], ],
), ),
), ),
),
// To be removed once the experimental feature is stable // To be removed once the experimental feature is stable
if (CurrentPlatform.isAndroid && if (CurrentPlatform.isAndroid &&
appSettingsService.getSetting<bool>(AppSettingsEnum.manageLocalMediaAndroid)) ...[ appSettingsService.getSetting<bool>(AppSettingsEnum.manageLocalMediaAndroid)) ...[
@@ -364,20 +375,22 @@ class _SyncStatsCounts extends ConsumerWidget {
return counts.when( return counts.when(
data: (c) => Padding( data: (c) => Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
child: IntrinsicHeight(
child: Flex( child: Flex(
direction: Axis.horizontal, direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch, // Added
spacing: 8.0, spacing: 8.0,
children: [ children: [
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "local".t(context: context), label: "local".t(context: context),
count: c.total, count: c.total,
icon: Icons.delete_outline, icon: Icons.delete_outline,
), ),
), ),
Expanded( Expanded(
child: EntitiyCountTile( child: EntityCountTile(
label: "hashed_assets".t(context: context), label: "hashed_assets".t(context: context),
count: c.hashed, count: c.hashed,
icon: Icons.tag, icon: Icons.tag,
@@ -386,6 +399,7 @@ class _SyncStatsCounts extends ConsumerWidget {
], ],
), ),
), ),
),
loading: () => const CircularProgressIndicator(), loading: () => const CircularProgressIndicator(),
error: (e, st) => Text('Error: $e'), error: (e, st) => Text('Error: $e'),
); );