You've already forked immich
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:
@ -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),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
Reference in New Issue
Block a user