1
0
mirror of https://github.com/immich-app/immich.git synced 2025-08-07 23:03:36 +02:00

refactor(mobile): image thumbnails (#19821)

* image thumbnail refactor

* minor const-ification in new thumbnail tile

* underscore helper classes

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Mert
2025-07-09 22:16:09 +03:00
committed by GitHub
parent a918481c0b
commit fd48a33686
6 changed files with 317 additions and 228 deletions

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/duration_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
@ -76,23 +77,33 @@ class ThumbnailTile extends ConsumerWidget {
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.only(right: 10.0, top: 6.0),
child: _VideoIndicator(asset.durationInSeconds ?? 0),
child: _VideoIndicator(asset.duration),
),
),
if (showStorageIndicator)
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 10.0, bottom: 6.0),
child: _TileOverlayIcon(
switch (asset.storage) {
AssetState.local => Icons.cloud_off_outlined,
AssetState.remote => Icons.cloud_outlined,
AssetState.merged => Icons.cloud_done_outlined,
},
switch (asset.storage) {
AssetState.local => const Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.only(right: 10.0, bottom: 6.0),
child: _TileOverlayIcon(Icons.cloud_off_outlined),
),
),
),
),
AssetState.remote => const Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.only(right: 10.0, bottom: 6.0),
child: _TileOverlayIcon(Icons.cloud_outlined),
),
),
AssetState.merged => const Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.only(right: 10.0, bottom: 6.0),
child: _TileOverlayIcon(Icons.cloud_done_outlined),
),
),
},
if (asset.isFavorite)
const Align(
alignment: Alignment.bottomLeft,
@ -138,7 +149,7 @@ class _SelectionIndicator extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (isLocked) {
return Container(
return DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color,
@ -149,7 +160,7 @@ class _SelectionIndicator extends StatelessWidget {
),
);
} else if (isSelected) {
return Container(
return DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color,
@ -169,23 +180,8 @@ class _SelectionIndicator extends StatelessWidget {
}
class _VideoIndicator extends StatelessWidget {
final int durationInSeconds;
const _VideoIndicator(this.durationInSeconds);
String _formatDuration(int durationInSec) {
final int hours = durationInSec ~/ 3600;
final int minutes = (durationInSec % 3600) ~/ 60;
final int seconds = durationInSec % 60;
final String minutesPadded = minutes.toString().padLeft(2, '0');
final String secondsPadded = seconds.toString().padLeft(2, '0');
if (hours > 0) {
return "$hours:$minutesPadded:$secondsPadded"; // H:MM:SS
} else {
return "$minutesPadded:$secondsPadded"; // MM:SS
}
}
final Duration duration;
const _VideoIndicator(this.duration);
@override
Widget build(BuildContext context) {
@ -197,15 +193,15 @@ class _VideoIndicator extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
_formatDuration(durationInSeconds),
style: TextStyle(
duration.format(),
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
shadows: [
Shadow(
blurRadius: 5.0,
color: Colors.black.withValues(alpha: 0.6),
color: Color.fromRGBO(0, 0, 0, 0.6),
),
],
),
@ -228,10 +224,10 @@ class _TileOverlayIcon extends StatelessWidget {
color: Colors.white,
size: 16,
shadows: [
Shadow(
const Shadow(
blurRadius: 5.0,
color: Colors.black.withValues(alpha: 0.6),
offset: const Offset(0.0, 0.0),
color: Color.fromRGBO(0, 0, 0, 0.6),
offset: Offset(0.0, 0.0),
),
],
);