mirror of https://github.com/immich-app/immich.git
feat: show "appears in" albums on asset viewer bottom sheet (#21925)
* feat: show "appears in" albums on asset viewer bottom sheet fix: multiple RemoteAlbumPages in navigation stack this also allows us to not have to set the current album before navigating to RemoteAlbumPage chore: clarification comments handle nested album pages fix: hide "appears in" when an asset is not in any albums fix: way more bottom padding for some reason we can't query the safe area here :/ * fix: bottom sheet now is usable when navigating to another asset viewer * fix: rebase conflict * fix: restore ancestors album to currentRemoteAlbumProvider when popping * fix: view flashing when dismissing a album viewer * chore: code review changes * fix: styling and padding * chore: rework currentRemoteAlbumProvider to be scoped by the Remote album page * fix: override remote album provider on required pages * chore: convert query to all SQL calls instead of matching in Dart * fix: album query * fix: unawaited future * Update deep_link.service.dart --------- Co-authored-by: Alex <alex.tran1502@gmail.com>pull/23324/head
parent
74f2c10a5a
commit
e0c2cdddd4
@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/pages/common/large_leading_tile.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
|
||||
class AlbumTile extends StatelessWidget {
|
||||
const AlbumTile({super.key, required this.album, required this.isOwner, this.onAlbumSelected});
|
||||
|
||||
final RemoteAlbum album;
|
||||
final bool isOwner;
|
||||
final Function(RemoteAlbum)? onAlbumSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LargeLeadingTile(
|
||||
title: Text(
|
||||
album.name,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600),
|
||||
),
|
||||
subtitle: Text(
|
||||
'${'items_count'.t(context: context, args: {'count': album.assetCount})} • ${isOwner ? 'owned'.t(context: context) : 'shared_by_user'.t(context: context, args: {'user': album.ownerName})}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
|
||||
),
|
||||
onTap: () => onAlbumSelected?.call(album),
|
||||
leadingPadding: const EdgeInsets.only(right: 16),
|
||||
leading: album.thumbnailAssetId != null
|
||||
? ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(15)),
|
||||
child: SizedBox(width: 80, height: 80, child: Thumbnail.remote(remoteId: album.thumbnailAssetId!)),
|
||||
)
|
||||
: SizedBox(
|
||||
width: 80,
|
||||
height: 80,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.colorScheme.surfaceContainer,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||
border: Border.all(color: context.colorScheme.outline.withAlpha(50), width: 1),
|
||||
),
|
||||
child: const Icon(Icons.photo_album_rounded, size: 24, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,36 +1,30 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
|
||||
final currentRemoteAlbumProvider = AutoDisposeNotifierProvider<CurrentAlbumNotifier, RemoteAlbum?>(
|
||||
final currentRemoteAlbumScopedProvider = Provider<RemoteAlbum?>((ref) => null);
|
||||
final currentRemoteAlbumProvider = NotifierProvider<CurrentAlbumNotifier, RemoteAlbum?>(
|
||||
CurrentAlbumNotifier.new,
|
||||
dependencies: [currentRemoteAlbumScopedProvider, remoteAlbumServiceProvider],
|
||||
);
|
||||
|
||||
class CurrentAlbumNotifier extends AutoDisposeNotifier<RemoteAlbum?> {
|
||||
KeepAliveLink? _keepAliveLink;
|
||||
StreamSubscription<RemoteAlbum?>? _assetSubscription;
|
||||
|
||||
class CurrentAlbumNotifier extends Notifier<RemoteAlbum?> {
|
||||
@override
|
||||
RemoteAlbum? build() => null;
|
||||
RemoteAlbum? build() {
|
||||
final album = ref.watch(currentRemoteAlbumScopedProvider);
|
||||
|
||||
void setAlbum(RemoteAlbum album) {
|
||||
_keepAliveLink?.close();
|
||||
_assetSubscription?.cancel();
|
||||
state = album;
|
||||
if (album == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
_assetSubscription = ref.watch(remoteAlbumServiceProvider).watchAlbum(album.id).listen((updatedAlbum) {
|
||||
final watcher = ref.watch(remoteAlbumServiceProvider).watchAlbum(album.id).listen((updatedAlbum) {
|
||||
if (updatedAlbum != null) {
|
||||
state = updatedAlbum;
|
||||
}
|
||||
});
|
||||
_keepAliveLink = ref.keepAlive();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_keepAliveLink?.close();
|
||||
_assetSubscription?.cancel();
|
||||
state = null;
|
||||
ref.onDispose(watcher.cancel);
|
||||
|
||||
return album;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue