mirror of
https://github.com/immich-app/immich
synced 2025-10-17 18:19:27 +00:00
feat: disable snapping when a timeline has less than 12 months (#21649)
* feat: disable snapping when a timeline has less than 12 months * fix: disable placeholders when not snapping also moved month constant to constants.dart --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
parent
d38468439b
commit
27d2f3efe2
2 changed files with 25 additions and 3 deletions
|
|
@ -45,3 +45,5 @@ const List<(String, String)> kWidgetNames = [
|
|||
|
||||
const double kUploadStatusFailed = -1.0;
|
||||
const double kUploadStatusCanceled = -2.0;
|
||||
|
||||
const int kMinMonthsToEnableScrubberSnap = 12;
|
||||
|
|
|
|||
|
|
@ -3,14 +3,15 @@ import 'dart:async';
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart';
|
||||
import 'package:intl/intl.dart' hide TextDirection;
|
||||
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
||||
import 'package:intl/intl.dart' hide TextDirection;
|
||||
|
||||
/// A widget that will display a BoxScrollView with a ScrollThumb that can be dragged
|
||||
/// for quick navigation of the BoxScrollView.
|
||||
|
|
@ -79,6 +80,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||
double _thumbTopOffset = 0.0;
|
||||
bool _isDragging = false;
|
||||
List<_Segment> _segments = [];
|
||||
int _monthCount = 0;
|
||||
|
||||
late AnimationController _thumbAnimationController;
|
||||
Timer? _fadeOutTimer;
|
||||
|
|
@ -105,6 +107,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||
_thumbAnimationController = AnimationController(vsync: this, duration: kTimelineScrubberFadeInDuration);
|
||||
_thumbAnimation = CurvedAnimation(parent: _thumbAnimationController, curve: Curves.fastEaseInToSlowEaseOut);
|
||||
_labelAnimationController = AnimationController(vsync: this, duration: kTimelineScrubberFadeInDuration);
|
||||
_monthCount = getMonthCount();
|
||||
|
||||
_labelAnimation = CurvedAnimation(parent: _labelAnimationController, curve: Curves.fastOutSlowIn);
|
||||
}
|
||||
|
|
@ -121,6 +124,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||
|
||||
if (oldWidget.layoutSegments.lastOrNull?.endOffset != widget.layoutSegments.lastOrNull?.endOffset) {
|
||||
_segments = _buildSegments(layoutSegments: widget.layoutSegments, timelineHeight: _scrubberHeight);
|
||||
_monthCount = getMonthCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,6 +144,10 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||
});
|
||||
}
|
||||
|
||||
int getMonthCount() {
|
||||
return _segments.map((e) => "${e.date.month}_${e.date.year}").toSet().length;
|
||||
}
|
||||
|
||||
bool _onScrollNotification(ScrollNotification notification) {
|
||||
if (_isDragging) {
|
||||
// If the user is dragging the thumb, we don't want to update the position
|
||||
|
|
@ -169,7 +177,10 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||
}
|
||||
|
||||
void _onDragStart(DragStartDetails _) {
|
||||
ref.read(timelineStateProvider.notifier).setScrubbing(true);
|
||||
if (_monthCount >= kMinMonthsToEnableScrubberSnap) {
|
||||
ref.read(timelineStateProvider.notifier).setScrubbing(true);
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isDragging = true;
|
||||
_labelAnimationController.forward();
|
||||
|
|
@ -191,13 +202,22 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||
final nearestMonthSegment = _findNearestMonthSegment(dragPosition);
|
||||
|
||||
if (nearestMonthSegment != null) {
|
||||
_snapToSegment(nearestMonthSegment);
|
||||
final label = nearestMonthSegment.scrollLabel;
|
||||
if (_lastLabel != label) {
|
||||
ref.read(hapticFeedbackProvider.notifier).selectionClick();
|
||||
_lastLabel = label;
|
||||
}
|
||||
}
|
||||
|
||||
if (_monthCount < kMinMonthsToEnableScrubberSnap) {
|
||||
// If there are less than kMinMonthsToEnableScrubberSnap months, we don't need to snap to segments
|
||||
setState(() {
|
||||
_thumbTopOffset = dragPosition;
|
||||
_scrollController.jumpTo((dragPosition / _scrubberHeight) * _scrollController.position.maxScrollExtent);
|
||||
});
|
||||
} else if (nearestMonthSegment != null) {
|
||||
_snapToSegment(nearestMonthSegment);
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the drag position relative to the scrubber area
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue