mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
fix: riverpod reactivity regression from lint fixes
This commit is contained in:
parent
199723261c
commit
44ce9c7b17
6 changed files with 100 additions and 52 deletions
|
|
@ -316,12 +316,11 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final backupAlbums = ref.watch(backupAlbumProvider);
|
||||
|
||||
Widget buildSelectedAlbumName() {
|
||||
String text = context.t.backup_controller_page_backup_selected;
|
||||
final albums = ref
|
||||
.read(backupAlbumProvider)
|
||||
.where((album) => album.backupSelection == BackupSelection.selected)
|
||||
.toList();
|
||||
final albums = backupAlbums.where((album) => album.backupSelection == BackupSelection.selected).toList();
|
||||
|
||||
if (albums.isNotEmpty) {
|
||||
for (var album in albums) {
|
||||
|
|
@ -352,10 +351,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
|
|||
|
||||
Widget buildExcludedAlbumName() {
|
||||
String text = context.t.backup_controller_page_excluded;
|
||||
final albums = ref
|
||||
.read(backupAlbumProvider)
|
||||
.where((album) => album.backupSelection == BackupSelection.excluded)
|
||||
.toList();
|
||||
final albums = backupAlbums.where((album) => album.backupSelection == BackupSelection.excluded).toList();
|
||||
|
||||
if (albums.isNotEmpty) {
|
||||
for (var album in albums) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
|
|||
final userId = ref.watch(authProvider).userId;
|
||||
final activityEnabled = useState(album.isActivityEnabled);
|
||||
final isOwner = album.ownerId == userId;
|
||||
final owner = isOwner ? ref.watch(currentUserProvider) : null;
|
||||
final allUsers = isOwner ? null : ref.watch(driftUsersProvider);
|
||||
|
||||
void showErrorMessage() {
|
||||
ContextHelper(context).pop();
|
||||
|
|
@ -141,7 +143,6 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
|
|||
|
||||
Widget buildOwnerInfo() {
|
||||
if (isOwner) {
|
||||
final owner = ref.read(currentUserProvider);
|
||||
return ListTile(
|
||||
leading: owner != null ? UserCircleAvatar(user: owner) : const SizedBox(),
|
||||
title: Text(album.ownerName, style: const TextStyle(fontWeight: FontWeight.w500)),
|
||||
|
|
@ -149,8 +150,11 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
|
|||
trailing: Text(context.t.owner, style: context.textTheme.labelLarge),
|
||||
);
|
||||
} else {
|
||||
final usersProvider = ref.read(driftUsersProvider);
|
||||
return usersProvider.maybeWhen(
|
||||
if (allUsers == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
return allUsers.maybeWhen(
|
||||
data: (users) {
|
||||
final user = users.firstWhereOrNull((u) => u.id == album.ownerId);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/config/slideshow_config.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
|
|
@ -295,14 +296,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
|
|||
color: context.colorScheme.primary,
|
||||
);
|
||||
} else {
|
||||
return LinearProgressIndicator(
|
||||
color: context.colorScheme.primary,
|
||||
borderRadius: BorderRadius.zero,
|
||||
minHeight: 5,
|
||||
value:
|
||||
ref.read(videoPlayerProvider(asset.id).select((s) => s.position)).inMilliseconds /
|
||||
asset.duration.inMilliseconds,
|
||||
);
|
||||
return _VideoProgressBar(asset: asset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -374,25 +368,13 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
|
|||
builder: (context, value, _) => buildPhotoView(scale * (1.0 + value * _kenBurnsZoom)),
|
||||
);
|
||||
} else {
|
||||
final status = ref.read(videoPlayerProvider(asset.id).select((s) => s.status));
|
||||
final position = ref.read(videoPlayerProvider(asset.id)).position;
|
||||
|
||||
if (status == VideoPlaybackStatus.completed && isCurrent && position.inMicroseconds > 0) {
|
||||
unawaited(_nextPage());
|
||||
} else if (status == VideoPlaybackStatus.playing) {
|
||||
unawaited(ref.read(videoPlayerProvider(asset.id).notifier).setLoop(false));
|
||||
}
|
||||
|
||||
return PhotoView.customChild(
|
||||
onTapUp: (_, _, _) => _onTapUp(),
|
||||
disableScaleGestures: true,
|
||||
filterQuality: FilterQuality.high,
|
||||
initialScale: scale,
|
||||
child: NativeVideoViewer(
|
||||
asset: asset,
|
||||
isCurrent: isCurrent,
|
||||
image: Image(image: imageProvider, fit: BoxFit.contain, alignment: Alignment.center),
|
||||
),
|
||||
return _VideoChild(
|
||||
asset: asset,
|
||||
isCurrent: isCurrent,
|
||||
scale: scale,
|
||||
imageProvider: imageProvider,
|
||||
onTapUp: _onTapUp,
|
||||
onCompleted: _nextPage,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -477,6 +459,67 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
|
|||
}
|
||||
}
|
||||
|
||||
class _VideoChild extends ConsumerWidget {
|
||||
final BaseAsset asset;
|
||||
final bool isCurrent;
|
||||
final PhotoViewComputedScale scale;
|
||||
final ImageProvider imageProvider;
|
||||
final VoidCallback onTapUp;
|
||||
final VoidCallback onCompleted;
|
||||
|
||||
const _VideoChild({
|
||||
required this.asset,
|
||||
required this.isCurrent,
|
||||
required this.scale,
|
||||
required this.imageProvider,
|
||||
required this.onTapUp,
|
||||
required this.onCompleted,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
ref.listen(videoPlayerProvider(asset.id).select((s) => s.status), (_, status) {
|
||||
if (status == VideoPlaybackStatus.completed) {
|
||||
if (isCurrent && ref.read(videoPlayerProvider(asset.id)).position.inMicroseconds > 0) {
|
||||
onCompleted();
|
||||
}
|
||||
} else if (status == VideoPlaybackStatus.playing) {
|
||||
unawaited(ref.read(videoPlayerProvider(asset.id).notifier).setLoop(false));
|
||||
}
|
||||
});
|
||||
|
||||
return PhotoView.customChild(
|
||||
onTapUp: (_, _, _) => onTapUp(),
|
||||
disableScaleGestures: true,
|
||||
filterQuality: FilterQuality.high,
|
||||
initialScale: scale,
|
||||
child: NativeVideoViewer(
|
||||
asset: asset,
|
||||
isCurrent: isCurrent,
|
||||
image: Image(image: imageProvider, fit: BoxFit.contain, alignment: Alignment.center),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _VideoProgressBar extends ConsumerWidget {
|
||||
final BaseAsset asset;
|
||||
|
||||
const _VideoProgressBar({required this.asset});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final position = ref.watch(videoPlayerProvider(asset.id).select((s) => s.position));
|
||||
|
||||
return LinearProgressIndicator(
|
||||
color: context.colorScheme.primary,
|
||||
borderRadius: BorderRadius.zero,
|
||||
minHeight: 5,
|
||||
value: position.inMilliseconds / asset.duration.inMilliseconds,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Progress bar for image slides, driven by an explicit [AnimationController].
|
||||
///
|
||||
/// [TweenAnimationBuilder] creates its controller internally with the default
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class DriftUserSelectionPage extends HookConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final AsyncValue<List<UserDto>> suggestedShareUsers = ref.watch(driftUsersProvider);
|
||||
final sharedUsers = ref.watch(remoteAlbumSharedUsersProvider(album.id));
|
||||
final sharedUsersList = useState<Set<UserDto>>({});
|
||||
|
||||
void addNewUsersHandler() {
|
||||
|
|
@ -136,9 +137,6 @@ class DriftUserSelectionPage extends HookConsumerWidget {
|
|||
),
|
||||
body: suggestedShareUsers.widgetWhen(
|
||||
onData: (users) {
|
||||
// Get shared users for this album from the database
|
||||
final sharedUsers = ref.read(remoteAlbumSharedUsersProvider(album.id));
|
||||
|
||||
return sharedUsers.when(
|
||||
data: (albumSharedUsers) {
|
||||
// Filter out users that are already shared with this album and the owner
|
||||
|
|
|
|||
|
|
@ -742,9 +742,7 @@ class _SearchResultGrid extends ConsumerWidget {
|
|||
return false;
|
||||
}
|
||||
|
||||
Widget? _bottomWidget(BuildContext context, WidgetRef ref) {
|
||||
final isLoading = ref.read(paginatedSearchProvider.select((s) => s.isLoading));
|
||||
|
||||
Widget? _bottomWidget(BuildContext context, {required bool isLoading, required bool hasMore}) {
|
||||
if (isLoading) {
|
||||
return const SliverFillRemaining(
|
||||
hasScrollBody: false,
|
||||
|
|
@ -755,8 +753,6 @@ class _SearchResultGrid extends ConsumerWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final hasMore = ref.read(paginatedSearchProvider.select((s) => s.nextPage != null));
|
||||
|
||||
if (hasMore) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -778,6 +774,7 @@ class _SearchResultGrid extends ConsumerWidget {
|
|||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final hasAssets = ref.watch(paginatedSearchProvider.select((s) => s.assets.isNotEmpty));
|
||||
final isLoading = ref.watch(paginatedSearchProvider.select((s) => s.isLoading));
|
||||
final hasMore = ref.watch(paginatedSearchProvider.select((s) => s.nextPage != null));
|
||||
|
||||
if (!hasAssets && !isLoading) {
|
||||
return const _SearchNoResults();
|
||||
|
|
@ -807,7 +804,7 @@ class _SearchResultGrid extends ConsumerWidget {
|
|||
bottomSheet: const GeneralBottomSheet(minChildSize: 0.20),
|
||||
snapToMonth: false,
|
||||
loadingWidget: const SizedBox.shrink(),
|
||||
bottomSliverWidget: _bottomWidget(context, ref),
|
||||
bottomSliverWidget: _bottomWidget(context, isLoading: isLoading, hasMore: hasMore),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -177,7 +177,15 @@ class _BackupIndicator extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final indicatorIcon = _getBackupBadgeIcon(context, ref);
|
||||
final backupEnabled = ref.watch(appConfigProvider.select((c) => c.backup.enabled));
|
||||
final hasError = ref.watch(driftBackupProvider.select((state) => state.error != BackupError.none));
|
||||
final isUploading = ref.watch(driftBackupProvider.select((state) => state.uploadItems.isNotEmpty));
|
||||
final indicatorIcon = _getBackupBadgeIcon(
|
||||
context,
|
||||
backupEnabled: backupEnabled,
|
||||
hasError: hasError,
|
||||
isUploading: isUploading,
|
||||
);
|
||||
|
||||
return IconButton(
|
||||
onPressed: () => context.pushRoute(const DriftBackupRoute()),
|
||||
|
|
@ -192,12 +200,14 @@ class _BackupIndicator extends ConsumerWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Widget? _getBackupBadgeIcon(BuildContext context, WidgetRef ref) {
|
||||
final backupEnabled = ref.read(appConfigProvider.select((c) => c.backup.enabled));
|
||||
final hasError = ref.read(driftBackupProvider.select((state) => state.error != BackupError.none));
|
||||
Widget? _getBackupBadgeIcon(
|
||||
BuildContext context, {
|
||||
required bool backupEnabled,
|
||||
required bool hasError,
|
||||
required bool isUploading,
|
||||
}) {
|
||||
final isDarkTheme = context.isDarkTheme;
|
||||
final iconColor = isDarkTheme ? Colors.white : Colors.black;
|
||||
final isUploading = ref.read(driftBackupProvider.select((state) => state.uploadItems.isNotEmpty));
|
||||
|
||||
if (!backupEnabled) {
|
||||
return _BadgeLabel(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue