diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart index 0934536471..bfd9738dc7 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart @@ -7,6 +7,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/domain/models/events.model.dart'; +import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/scroll_extensions.dart'; @@ -363,7 +364,8 @@ class _AssetPageState extends ConsumerState { } BaseAsset displayAsset = asset; - final stackChildren = ref.watch(stackChildrenNotifier(asset)).valueOrNull; + final showAssetStack = ref.watch(timelineServiceProvider.select((s) => s.origin != TimelineOrigin.trash)); + final stackChildren = showAssetStack ? ref.watch(stackChildrenNotifier(asset)).valueOrNull : null; if (stackChildren != null && stackChildren.isNotEmpty) { displayAsset = stackChildren.elementAt(stackIndex); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart index 213dc92ef3..f5d75a6a86 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart @@ -1,8 +1,10 @@ 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/domain/services/timeline.service.dart'; import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; +import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; class AssetStackRow extends ConsumerWidget { final List stack; @@ -15,6 +17,11 @@ class AssetStackRow extends ConsumerWidget { return const SizedBox.shrink(); } + final hideAssetStack = ref.read(timelineServiceProvider).origin == TimelineOrigin.trash; + if (hideAssetStack) { + return const SizedBox.shrink(); + } + final showingControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); double opacity = ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)) * (showingControls ? 1 : 0); diff --git a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart index 5746414361..406ca30820 100644 --- a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart +++ b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart @@ -21,6 +21,7 @@ class ThumbnailTile extends ConsumerStatefulWidget { this.showStorageIndicator = false, this.lockSelection = false, this.heroOffset, + this.showStackIndicator = false, super.key, }); @@ -30,6 +31,7 @@ class ThumbnailTile extends ConsumerStatefulWidget { final bool showStorageIndicator; final bool lockSelection; final int? heroOffset; + final bool showStackIndicator; @override ConsumerState createState() => _ThumbnailTileState(); @@ -139,7 +141,14 @@ class _ThumbnailTileState extends ConsumerState { duration: Durations.short4, child: Align( alignment: Alignment.topRight, - child: _AssetTypeIcons(asset: asset), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + _AssetTypeIcons(asset: asset), + if (widget.showStackIndicator) _StackIndicator(asset: asset), + ], + ), ), ), if (storageIndicator && asset != null) @@ -286,8 +295,8 @@ class _AssetTypeIcons extends StatelessWidget { @override Widget build(BuildContext context) { - final hasStack = asset is RemoteAsset && (asset as RemoteAsset).stackId != null; - final isLivePhoto = asset is RemoteAsset && asset.livePhotoVideoId != null; + final remoteAsset = asset is RemoteAsset ? asset as RemoteAsset : null; + final isLivePhoto = remoteAsset?.livePhotoVideoId != null; return Column( mainAxisSize: MainAxisSize.min, @@ -295,11 +304,6 @@ class _AssetTypeIcons extends StatelessWidget { children: [ if (asset.isVideo) Padding(padding: const EdgeInsets.only(right: 10.0, top: 6.0), child: _VideoIndicator(asset.duration)), - if (hasStack) - const Padding( - padding: EdgeInsets.only(right: 10.0, top: 6.0), - child: _TileOverlayIcon(Icons.burst_mode_rounded), - ), if (isLivePhoto) const Padding( padding: EdgeInsets.only(right: 10.0, top: 6.0), @@ -312,6 +316,24 @@ class _AssetTypeIcons extends StatelessWidget { } } +class _StackIndicator extends StatelessWidget { + final BaseAsset asset; + + const _StackIndicator({required this.asset}); + + @override + Widget build(BuildContext context) { + if (asset is! RemoteAsset || (asset as RemoteAsset).stackId == null) { + return const SizedBox.shrink(); + } + + return const Padding( + padding: EdgeInsets.only(right: 10.0, top: 6.0), + child: _TileOverlayIcon(Icons.burst_mode_rounded), + ); + } +} + class _UploadProgressOverlay extends StatelessWidget { final double progress; diff --git a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart index aa2112b8dd..c62a4946c7 100644 --- a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart +++ b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart @@ -244,6 +244,7 @@ class _AssetTileWidget extends ConsumerWidget { final lockSelection = _getLockSelectionStatus(ref); final showStorageIndicator = ref.watch(timelineArgsProvider.select((args) => args.showStorageIndicator)); final isReadonlyModeEnabled = ref.watch(readonlyModeProvider); + final showStackIndicator = ref.read(timelineServiceProvider).origin != TimelineOrigin.trash; return RepaintBoundary( child: GestureDetector( @@ -253,6 +254,7 @@ class _AssetTileWidget extends ConsumerWidget { asset, lockSelection: lockSelection, showStorageIndicator: showStorageIndicator, + showStackIndicator: showStackIndicator, heroOffset: heroOffset, ), ), diff --git a/mobile/lib/utils/action_button.utils.dart b/mobile/lib/utils/action_button.utils.dart index 3edc50c847..4f7ad83093 100644 --- a/mobile/lib/utils/action_button.utils.dart +++ b/mobile/lib/utils/action_button.utils.dart @@ -148,6 +148,7 @@ enum ActionButtonType { context.selectedCount == 1, ActionButtonType.unstack => context.isOwner && // + context.timelineOrigin != TimelineOrigin.trash && !context.isInLockedView && // context.isStacked, ActionButtonType.openInBrowser => context.asset.hasRemote && !context.isInLockedView,