diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index a6f484a0fb..651780ca16 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -264,7 +264,9 @@ "exif_bottom_sheet_location_add": "Add a location", "exif_bottom_sheet_people": "PEOPLE", "exif_bottom_sheet_person_add_person": "Add name", - "exif_bottom_sheet_person_age": "Age {}", + "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", + "exif_bottom_sheet_person_age_months": "Age {} months", "experimental_settings_new_asset_list_subtitle": "Work in progress", "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", diff --git a/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart b/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart index 2e868682f8..712e939ad5 100644 --- a/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart +++ b/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart @@ -1,5 +1,3 @@ -import 'dart:math' as math; - import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -26,7 +24,6 @@ class PeopleInfo extends ConsumerWidget { .watch(assetPeopleNotifierProvider(asset)) .value ?.where((p) => !p.isHidden); - final double imageSize = math.min(context.width / 3, 150); showPersonNameEditModel( String personId, @@ -48,12 +45,9 @@ class PeopleInfo extends ConsumerWidget { (p) => SearchCuratedContent( id: p.id, label: p.name, - subtitle: p.birthDate != null - ? "exif_bottom_sheet_person_age".tr( - args: [ - _calculateAge(p.birthDate!).toString(), - ], - ) + subtitle: p.birthDate != null && + p.birthDate!.isBefore(asset.fileCreatedAt) + ? _formatAge(p.birthDate!, asset.fileCreatedAt) : null, ), ) @@ -83,27 +77,24 @@ class PeopleInfo extends ConsumerWidget { ).tr(), ), ), - SizedBox( - height: imageSize, - child: Padding( - padding: const EdgeInsets.only(top: 16.0), - child: CuratedPeopleRow( - padding: padding, - content: curatedPeople, - onTap: (content, index) { - context - .pushRoute( - PersonResultRoute( - personId: content.id, - personName: content.label, - ), - ) - .then((_) => peopleProvider.refresh()); - }, - onNameTap: (person, index) => { - showPersonNameEditModel(person.id, person.label), - }, - ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: CuratedPeopleRow( + padding: padding, + content: curatedPeople, + onTap: (content, index) { + context + .pushRoute( + PersonResultRoute( + personId: content.id, + personName: content.label, + ), + ) + .then((_) => peopleProvider.refresh()); + }, + onNameTap: (person, index) => { + showPersonNameEditModel(person.id, person.label), + }, ), ), ], @@ -112,16 +103,36 @@ class PeopleInfo extends ConsumerWidget { ); } - int _calculateAge(DateTime birthDate) { - DateTime today = DateTime.now(); - int age = today.year - birthDate.year; + String _formatAge(DateTime birthDate, DateTime referenceDate) { + int ageInYears = _calculateAge(birthDate, referenceDate); + int ageInMonths = _calculateAgeInMonths(birthDate, referenceDate); - // Check if the birthday has occurred this year - if (today.month < birthDate.month || - (today.month == birthDate.month && today.day < birthDate.day)) { + if (ageInMonths <= 11) { + return "exif_bottom_sheet_person_age_months" + .tr(args: [ageInMonths.toString()]); + } else if (ageInMonths > 12 && ageInMonths <= 23) { + return "exif_bottom_sheet_person_age_year_months" + .tr(args: [(ageInMonths - 12).toString()]); + } else { + return "exif_bottom_sheet_person_age_years" + .tr(args: [ageInYears.toString()]); + } + } + + int _calculateAge(DateTime birthDate, DateTime referenceDate) { + int age = referenceDate.year - birthDate.year; + if (referenceDate.month < birthDate.month || + (referenceDate.month == birthDate.month && + referenceDate.day < birthDate.day)) { age--; } - return age; } + + int _calculateAgeInMonths(DateTime birthDate, DateTime referenceDate) { + return (referenceDate.year - birthDate.year) * 12 + + referenceDate.month - + birthDate.month - + (referenceDate.day < birthDate.day ? 1 : 0); + } } diff --git a/mobile/lib/widgets/search/curated_people_row.dart b/mobile/lib/widgets/search/curated_people_row.dart index eece328392..10c19c7e60 100644 --- a/mobile/lib/widgets/search/curated_people_row.dart +++ b/mobile/lib/widgets/search/curated_people_row.dart @@ -26,43 +26,48 @@ class CuratedPeopleRow extends StatelessWidget { @override Widget build(BuildContext context) { return SizedBox( - height: imageSize + 50, - child: ListView.separated( + width: double.infinity, + child: SingleChildScrollView( padding: padding, scrollDirection: Axis.horizontal, - separatorBuilder: (context, index) => const SizedBox(width: 16), - itemBuilder: (context, index) { - final person = content[index]; - final headers = ApiService.getRequestHeaders(); - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - GestureDetector( - onTap: () => onTap?.call(person, index), - child: SizedBox( - height: imageSize, - child: Material( - shape: const CircleBorder(side: BorderSide.none), - elevation: 3, - child: CircleAvatar( - maxRadius: imageSize / 2, - backgroundImage: NetworkImage( - getFaceThumbnailUrl(person.id), - headers: headers, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: List.generate(content.length, (index) { + final person = content[index]; + final headers = ApiService.getRequestHeaders(); + return Padding( + padding: const EdgeInsets.only(right: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + GestureDetector( + onTap: () => onTap?.call(person, index), + child: SizedBox( + height: imageSize, + child: Material( + shape: const CircleBorder(side: BorderSide.none), + elevation: 3, + child: CircleAvatar( + maxRadius: imageSize / 2, + backgroundImage: NetworkImage( + getFaceThumbnailUrl(person.id), + headers: headers, + ), + ), ), ), ), - ), + const SizedBox(height: 8), + SizedBox( + width: imageSize, + child: _buildPersonLabel(context, person, index), + ), + ], ), - const SizedBox(height: 8), - SizedBox( - width: imageSize, - child: _buildPersonLabel(context, person, index), - ), - ], - ); - }, - itemCount: content.length, + ); + }), + ), ), ); }