Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mobile): Added "jump to date" functionality to the memory view #7323

Merged
merged 25 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1a33abc
implemented jump to date from memory
arnolicious Feb 21, 2024
25ca730
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Feb 21, 2024
779f210
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Feb 23, 2024
2d411e9
Changed implementation to a ValueNotifier & fixes
arnolicious Feb 23, 2024
fd3f3b0
Merge branch 'main' of github.com:immich-app/immich into pr/arnolicio…
alextran1502 Feb 27, 2024
ce66af0
remove debug code
alextran1502 Feb 27, 2024
bd85381
Merge branch 'immich-app:main' into feat(mobile)-jump-to-asset
arnolicious Feb 27, 2024
e3bb602
feat(mobile):
arnolicious Feb 27, 2024
da09de6
feat(mobile): fixed debug index offset & added debug toast for scroll…
arnolicious Feb 29, 2024
b532534
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Feb 29, 2024
0c7acb3
feat(mobile): added more debug toasts...
arnolicious Feb 29, 2024
19b9cbf
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Feb 29, 2024
669bd9f
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 2, 2024
5135a31
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 7, 2024
28beb9b
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 12, 2024
b176340
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 12, 2024
98a007b
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 16, 2024
6cd9b60
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 19, 2024
a3d5a47
Merge branch 'main' of github.com:immich-app/immich into feat(mobile)…
alextran1502 Mar 20, 2024
fd795e9
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 22, 2024
6e6b499
feat(mobile): scroll to month, if timeline is not grouped by days
arnolicious Mar 22, 2024
f736d09
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Mar 30, 2024
8e213a9
Merge branch 'main' into feat(mobile)-jump-to-asset
arnolicious Apr 7, 2024
367231d
Merge branch 'main' into feat(mobile)-jump-to-asset
alextran1502 Apr 21, 2024
3dd1d1d
Merge branch 'main' of github.com:immich-app/immich into feat(mobile)…
alextran1502 Apr 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'package:flutter/material.dart';

final scrollToDateNotifierProvider = ScrollToDateNotifier(null);

class ScrollToDateNotifier extends ValueNotifier<DateTime?> {
ScrollToDateNotifier(super.value);

void scrollToDate(DateTime date) {
value = date;

// Manually notify listeners to trigger the scroll, even if the value hasn't changed
notifyListeners();
}
}
65 changes: 65 additions & 0 deletions mobile/lib/modules/home/ui/asset_grid/immich_asset_grid_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import 'package:immich_mobile/modules/asset_viewer/providers/scroll_notifier.pro
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_drag_region.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_image.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_placeholder.dart';
import 'package:immich_mobile/shared/ui/immich_toast.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:immich_mobile/modules/home/ui/control_bottom_app_bar.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/modules/asset_viewer/providers/scroll_to_date_notifier.provider.dart';
import 'package:immich_mobile/shared/providers/haptic_feedback.provider.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

Expand Down Expand Up @@ -150,6 +153,23 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
assets.firstWhereOrNull((e) => !_selectedAssets.contains(e)) == null;
}

Future<void> _scrollToIndex(int index) async {
// if the index is so far down, that the end of the list is reached on the screen
// the scroll_position widget crashes. This is a workaround to prevent this.
// If the index is within the last 10 elements, we jump instead of scrolling.
if (widget.renderList.elements.length <= index + 10) {
_itemScrollController.jumpTo(
index: index,
);
return;
}
await _itemScrollController.scrollTo(
index: index,
alignment: 0,
duration: const Duration(milliseconds: 500),
);
}

Widget _itemBuilder(BuildContext c, int position) {
int index = position;
if (widget.topWidget != null) {
Expand Down Expand Up @@ -247,6 +267,48 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
: RefreshIndicator(onRefresh: widget.onRefresh!, child: child);
}

void _scrollToDate() {
final date = scrollToDateNotifierProvider.value;
if (date == null) {
ImmichToast.show(
context: context,
msg: "Scroll To Date failed, date is null.",
gravity: ToastGravity.BOTTOM,
toastType: ToastType.error,
);
return;
}

// Search for the index of the exact date in the list
var index = widget.renderList.elements.indexWhere(
(e) =>
e.date.year == date.year &&
e.date.month == date.month &&
e.date.day == date.day,
);

// If the exact date is not found, the timeline is grouped by month,
// thus we search for the month
if (index == -1) {
index = widget.renderList.elements.indexWhere(
(e) => e.date.year == date.year && e.date.month == date.month,
);
}

if (index != -1 && index < widget.renderList.elements.length) {
// Not sure why the index is shifted, but it works. :3
_scrollToIndex(index + 1);
} else {
ImmichToast.show(
context: context,
msg:
"The date (${DateFormat.yMd().format(date)}) could not be found in the timeline.",
gravity: ToastGravity.BOTTOM,
toastType: ToastType.error,
);
}
}

@override
void didUpdateWidget(ImmichAssetGridView oldWidget) {
super.didUpdateWidget(oldWidget);
Expand All @@ -261,6 +323,8 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
void initState() {
super.initState();
scrollToTopNotifierProvider.addListener(_scrollToTop);
scrollToDateNotifierProvider.addListener(_scrollToDate);

if (widget.visibleItemsListener != null) {
_itemPositionsListener.itemPositions.addListener(_positionListener);
}
Expand All @@ -274,6 +338,7 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
@override
void dispose() {
scrollToTopNotifierProvider.removeListener(_scrollToTop);
scrollToDateNotifierProvider.removeListener(_scrollToDate);
if (widget.visibleItemsListener != null) {
_itemPositionsListener.itemPositions.removeListener(_positionListener);
}
Expand Down
65 changes: 41 additions & 24 deletions mobile/lib/modules/memories/ui/memory_bottom_info.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// ignore_for_file: require_trailing_commas

import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:immich_mobile/modules/memories/models/memory.dart';
import 'package:immich_mobile/modules/asset_viewer/providers/scroll_to_date_notifier.provider.dart';

class MemoryBottomInfo extends StatelessWidget {
final Memory memory;
Expand All @@ -12,33 +16,46 @@ class MemoryBottomInfo extends StatelessWidget {
final df = DateFormat.yMMMMd();
return Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
memory.title,
style: TextStyle(
color: Colors.grey[400],
fontSize: 13.0,
fontWeight: FontWeight.w500,
),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
memory.title,
style: TextStyle(
color: Colors.grey[400],
fontSize: 13.0,
fontWeight: FontWeight.w500,
),
),
Text(
df.format(
memory.assets[0].fileCreatedAt,
),
Text(
df.format(
memory.assets[0].fileCreatedAt,
),
style: const TextStyle(
color: Colors.white,
fontSize: 15.0,
fontWeight: FontWeight.w500,
),
style: const TextStyle(
color: Colors.white,
fontSize: 15.0,
fontWeight: FontWeight.w500,
),
],
),
],
),
MaterialButton(
minWidth: 0,
onPressed: () {
context.popRoute();
scrollToDateNotifierProvider
.scrollToDate(memory.assets[0].fileCreatedAt);
},
shape: const CircleBorder(),
color: Colors.white.withOpacity(0.2),
elevation: 0,
child: const Icon(
Icons.open_in_new,
color: Colors.white,
),
],
),
),
]),
);
}
}
Loading