fix: Show correct photo name in buttom sheet and backup details page (#22978)

fix: Show correct name in buttom sheet and backup details page
This commit is contained in:
FawenYo 2025-10-17 22:19:16 +08:00 committed by GitHub
parent 82a4c28606
commit d626f86e8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 95 additions and 57 deletions

View file

@ -10,6 +10,7 @@ import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/pages/common/large_leading_tile.dart'; import 'package:immich_mobile/pages/common/large_leading_tile.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
import 'package:immich_mobile/repositories/asset_media.repository.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
@RoutePage() @RoutePage()
@ -30,53 +31,60 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
final asset = candidates[index]; final asset = candidates[index];
final albumsAsyncValue = ref.watch(driftCandidateBackupAlbumInfoProvider(asset.id)); final albumsAsyncValue = ref.watch(driftCandidateBackupAlbumInfoProvider(asset.id));
return LargeLeadingTile( final assetMediaRepository = ref.watch(assetMediaRepositoryProvider);
title: Text( return FutureBuilder<String?>(
asset.name, future: assetMediaRepository.getOriginalFilename(asset.id),
style: context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w500, fontSize: 16), builder: (context, snapshot) {
), final displayName = snapshot.data ?? asset.name;
subtitle: Column( return LargeLeadingTile(
crossAxisAlignment: CrossAxisAlignment.start, title: Text(
children: [ displayName,
Text( style: context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w500, fontSize: 16),
asset.createdAt.toString(),
style: TextStyle(fontSize: 13.0, color: context.colorScheme.onSurfaceSecondary),
), ),
Text( subtitle: Column(
asset.checksum ?? "N/A", crossAxisAlignment: CrossAxisAlignment.start,
style: TextStyle(fontSize: 13.0, color: context.colorScheme.onSurfaceSecondary), children: [
overflow: TextOverflow.ellipsis, Text(
), asset.createdAt.toString(),
albumsAsyncValue.when( style: TextStyle(fontSize: 13.0, color: context.colorScheme.onSurfaceSecondary),
data: (albums) { ),
if (albums.isEmpty) { Text(
return const SizedBox.shrink(); asset.checksum ?? "N/A",
} style: TextStyle(fontSize: 13.0, color: context.colorScheme.onSurfaceSecondary),
return Text(
albums.map((a) => a.name).join(', '),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
); ),
}, albumsAsyncValue.when(
error: (error, stackTrace) => data: (albums) {
Text('Error: $error', style: TextStyle(color: context.colorScheme.error)), if (albums.isEmpty) {
loading: () => const SizedBox(height: 16, width: 16, child: CircularProgressIndicator.adaptive()), return const SizedBox.shrink();
}
return Text(
albums.map((a) => a.name).join(', '),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
overflow: TextOverflow.ellipsis,
);
},
error: (error, stackTrace) =>
Text('Error: $error', style: TextStyle(color: context.colorScheme.error)),
loading: () => const SizedBox(height: 16, width: 16, child: CircularProgressIndicator.adaptive()),
),
],
), ),
], leading: ClipRRect(
), borderRadius: const BorderRadius.all(Radius.circular(12)),
leading: ClipRRect( child: SizedBox(
borderRadius: const BorderRadius.all(Radius.circular(12)), width: 64,
child: SizedBox( height: 64,
width: 64, child: Thumbnail.fromAsset(asset: asset, size: const Size(64, 64), fit: BoxFit.cover),
height: 64, ),
child: Thumbnail.fromAsset(asset: asset, size: const Size(64, 64), fit: BoxFit.cover), ),
), trailing: const Padding(padding: EdgeInsets.only(right: 24, left: 8), child: Icon(Icons.image_search)),
), onTap: () async {
trailing: const Padding(padding: EdgeInsets.only(right: 24, left: 8), child: Icon(Icons.image_search)), await context.maybePop();
onTap: () async { await context.navigateTo(const TabShellRoute(children: [MainTimelineRoute()]));
await context.maybePop(); EventStream.shared.emit(ScrollToDateEvent(asset.createdAt));
await context.navigateTo(const TabShellRoute(children: [MainTimelineRoute()])); },
EventStream.shared.emit(ScrollToDateEvent(asset.createdAt)); );
}, },
); );
}, },

View file

@ -19,6 +19,7 @@ import 'package:immich_mobile/providers/infrastructure/setting.provider.dart';
import 'package:immich_mobile/providers/routes.provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/repositories/asset_media.repository.dart';
import 'package:immich_mobile/utils/action_button.utils.dart'; import 'package:immich_mobile/utils/action_button.utils.dart';
import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/utils/bytes_units.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart';
@ -140,6 +141,47 @@ class _AssetDetailBottomSheet extends ConsumerWidget {
final exifInfo = ref.watch(currentAssetExifProvider).valueOrNull; final exifInfo = ref.watch(currentAssetExifProvider).valueOrNull;
final cameraTitle = _getCameraInfoTitle(exifInfo); final cameraTitle = _getCameraInfoTitle(exifInfo);
// Build file info tile based on asset type
Widget buildFileInfoTile() {
if (asset is LocalAsset) {
final assetMediaRepository = ref.watch(assetMediaRepositoryProvider);
return FutureBuilder<String?>(
future: assetMediaRepository.getOriginalFilename(asset.id),
builder: (context, snapshot) {
final displayName = snapshot.data ?? asset.name;
return _SheetTile(
title: displayName,
titleStyle: context.textTheme.labelLarge,
leading: Icon(
asset.isImage ? Icons.image_outlined : Icons.videocam_outlined,
size: 24,
color: context.textTheme.labelLarge?.color,
),
subtitle: _getFileInfo(asset, exifInfo),
subtitleStyle: context.textTheme.bodyMedium?.copyWith(
color: context.textTheme.bodyMedium?.color?.withAlpha(155),
),
);
},
);
} else {
// For remote assets, use the name directly
return _SheetTile(
title: asset.name,
titleStyle: context.textTheme.labelLarge,
leading: Icon(
asset.isImage ? Icons.image_outlined : Icons.videocam_outlined,
size: 24,
color: context.textTheme.labelLarge?.color,
),
subtitle: _getFileInfo(asset, exifInfo),
subtitleStyle: context.textTheme.bodyMedium?.copyWith(
color: context.textTheme.bodyMedium?.color?.withAlpha(155),
),
);
}
}
return SliverList.list( return SliverList.list(
children: [ children: [
// Asset Date and Time // Asset Date and Time
@ -161,19 +203,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget {
), ),
), ),
// File info // File info
_SheetTile( buildFileInfoTile(),
title: asset.name,
titleStyle: context.textTheme.labelLarge,
leading: Icon(
asset.isImage ? Icons.image_outlined : Icons.videocam_outlined,
size: 24,
color: context.textTheme.labelLarge?.color,
),
subtitle: _getFileInfo(asset, exifInfo),
subtitleStyle: context.textTheme.bodyMedium?.copyWith(
color: context.textTheme.bodyMedium?.color?.withAlpha(155),
),
),
// Camera info // Camera info
if (cameraTitle != null) if (cameraTitle != null)
_SheetTile( _SheetTile(