mirror of
https://github.com/immich-app/immich.git
synced 2025-05-31 04:05:39 -04:00
fix(mobile): rework album detail page header (#3035)
This commit is contained in:
parent
621fa5ba54
commit
b7ae3be394
@ -21,6 +21,8 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
required this.selected,
|
required this.selected,
|
||||||
required this.selectionDisabled,
|
required this.selectionDisabled,
|
||||||
required this.titleFocusNode,
|
required this.titleFocusNode,
|
||||||
|
this.onAddPhotos,
|
||||||
|
this.onAddUsers,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Album album;
|
final Album album;
|
||||||
@ -28,6 +30,8 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
final Set<Asset> selected;
|
final Set<Asset> selected;
|
||||||
final void Function() selectionDisabled;
|
final void Function() selectionDisabled;
|
||||||
final FocusNode titleFocusNode;
|
final FocusNode titleFocusNode;
|
||||||
|
final Function(Album album)? onAddPhotos;
|
||||||
|
final Function(Album album)? onAddUsers;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@ -157,6 +161,32 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
buildBottomSheetActionButton(),
|
buildBottomSheetActionButton(),
|
||||||
|
if (selected.isEmpty && onAddPhotos != null)
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.add_photo_alternate_outlined),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
onAddPhotos!(album);
|
||||||
|
},
|
||||||
|
title: const Text(
|
||||||
|
"share_add_photos",
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
).tr(),
|
||||||
|
),
|
||||||
|
if (selected.isEmpty &&
|
||||||
|
onAddPhotos != null &&
|
||||||
|
userId == album.ownerId)
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.person_add_alt_rounded),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
onAddUsers!(album);
|
||||||
|
},
|
||||||
|
title: const Text(
|
||||||
|
"album_viewer_page_share_add_users",
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
).tr(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -18,7 +18,6 @@ import 'package:immich_mobile/routing/router.dart';
|
|||||||
import 'package:immich_mobile/shared/models/album.dart';
|
import 'package:immich_mobile/shared/models/album.dart';
|
||||||
import 'package:immich_mobile/shared/models/asset.dart';
|
import 'package:immich_mobile/shared/models/asset.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_sliver_persistent_app_bar_delegate.dart';
|
|
||||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||||
|
|
||||||
class AlbumViewerPage extends HookConsumerWidget {
|
class AlbumViewerPage extends HookConsumerWidget {
|
||||||
@ -33,7 +32,6 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
final userId = ref.watch(authenticationProvider).userId;
|
final userId = ref.watch(authenticationProvider).userId;
|
||||||
final selection = useState<Set<Asset>>({});
|
final selection = useState<Set<Asset>>({});
|
||||||
final multiSelectEnabled = useState(false);
|
final multiSelectEnabled = useState(false);
|
||||||
bool? isTop;
|
|
||||||
|
|
||||||
Future<bool> onWillPop() async {
|
Future<bool> onWillPop() async {
|
||||||
if (multiSelectEnabled.value) {
|
if (multiSelectEnabled.value) {
|
||||||
@ -219,8 +217,6 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final scroll = ScrollController();
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: album.when(
|
appBar: album.when(
|
||||||
data: (data) => AlbumViewerAppbar(
|
data: (data) => AlbumViewerAppbar(
|
||||||
@ -229,6 +225,8 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
userId: userId,
|
userId: userId,
|
||||||
selected: selection.value,
|
selected: selection.value,
|
||||||
selectionDisabled: disableSelection,
|
selectionDisabled: disableSelection,
|
||||||
|
onAddPhotos: onAddPhotosPressed,
|
||||||
|
onAddUsers: onAddUsersPressed,
|
||||||
),
|
),
|
||||||
error: (error, stackTrace) => AppBar(title: const Text("Error")),
|
error: (error, stackTrace) => AppBar(title: const Text("Error")),
|
||||||
loading: () => AppBar(),
|
loading: () => AppBar(),
|
||||||
@ -240,41 +238,17 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
titleFocusNode.unfocus();
|
titleFocusNode.unfocus();
|
||||||
},
|
},
|
||||||
child: NestedScrollView(
|
child: ImmichAssetGrid(
|
||||||
controller: scroll,
|
renderList: data.renderList,
|
||||||
floatHeaderSlivers: true,
|
listener: selectionListener,
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
selectionActive: multiSelectEnabled.value,
|
||||||
SliverToBoxAdapter(child: buildHeader(data)),
|
showMultiSelectIndicator: false,
|
||||||
SliverPersistentHeader(
|
topWidget: Column(
|
||||||
pinned: true,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
delegate: ImmichSliverPersistentAppBarDelegate(
|
children: [
|
||||||
minHeight: 50,
|
buildHeader(data),
|
||||||
maxHeight: 50,
|
if (data.isRemote) buildControlButton(data),
|
||||||
child: Container(
|
],
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
child: buildControlButton(data),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
body: ImmichAssetGrid(
|
|
||||||
renderList: data.renderList,
|
|
||||||
listener: selectionListener,
|
|
||||||
selectionActive: multiSelectEnabled.value,
|
|
||||||
showMultiSelectIndicator: false,
|
|
||||||
visibleItemsListener: (start, end) {
|
|
||||||
final top = start.index == 0 && start.itemLeadingEdge == 0.0;
|
|
||||||
if (top != isTop) {
|
|
||||||
isTop = top;
|
|
||||||
scroll.animateTo(
|
|
||||||
top
|
|
||||||
? scroll.position.minScrollExtent
|
|
||||||
: scroll.position.maxScrollExtent,
|
|
||||||
duration: const Duration(milliseconds: 500),
|
|
||||||
curve: top ? Curves.easeOut : Curves.easeIn,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class ImmichSliverPersistentAppBarDelegate
|
|
||||||
extends SliverPersistentHeaderDelegate {
|
|
||||||
final double minHeight;
|
|
||||||
final double maxHeight;
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
ImmichSliverPersistentAppBarDelegate({
|
|
||||||
required this.minHeight,
|
|
||||||
required this.maxHeight,
|
|
||||||
required this.child,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
double get minExtent => minHeight;
|
|
||||||
|
|
||||||
@override
|
|
||||||
double get maxExtent => max(maxHeight, minHeight);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(
|
|
||||||
BuildContext context,
|
|
||||||
double shrinkOffset,
|
|
||||||
bool overlapsContent,
|
|
||||||
) {
|
|
||||||
return SizedBox.expand(child: child);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool shouldRebuild(ImmichSliverPersistentAppBarDelegate oldDelegate) {
|
|
||||||
return maxHeight != oldDelegate.maxHeight ||
|
|
||||||
minHeight != oldDelegate.minHeight ||
|
|
||||||
child != oldDelegate.child;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user