mirror of
https://github.com/immich-app/immich.git
synced 2025-06-21 14:31:03 -04:00
* wip: timeline * more segment extensions * added scrubber * refactor: timeline state * more refactors * fix scrubber segments * added remote thumb & thumbhash provider * feat: merged view * scrub / merged asset fixes * rename stuff & add tile indicators * fix local album timeline query * ignore hidden assets during sync * ignore recovered assets during sync * old scrubber * add video indicator * handle groupBy * handle partner inTimeline * show duration * reduce widget nesting in thumb tile * merge main * chore: extend cacheExtent * ignore touch events on scrub label when not visible * scrub label ignore events and hide immediately * auto reload on sync * refactor image providers * throttle db updates --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
101 lines
3.2 KiB
Dart
101 lines
3.2 KiB
Dart
import 'package:collection/collection.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
|
|
|
// Segments are the time groups buckets in the timeline view.
|
|
// Each segment contains a header and a list of asset rows.
|
|
abstract class Segment {
|
|
// The index of the first row of the segment, usually the header, but if not, it can be any asset.
|
|
final int firstIndex;
|
|
// The index of the last asset of the segment.
|
|
final int lastIndex;
|
|
// The offset of the first row from beginning of the timeline.
|
|
final double startOffset;
|
|
// The offset of the last row from beginning of the timeline.
|
|
final double endOffset;
|
|
// The spacing between the header and the first row of the segment.
|
|
final double spacing;
|
|
final double headerExtent;
|
|
// the start index of the asset of this segment from the beginning of the timeline.
|
|
final int firstAssetIndex;
|
|
final Bucket bucket;
|
|
|
|
// The index of the row after the header
|
|
final int gridIndex;
|
|
// The offset of the row after the header
|
|
final double gridOffset;
|
|
// The type of the header
|
|
final HeaderType header;
|
|
|
|
const Segment({
|
|
required this.firstIndex,
|
|
required this.lastIndex,
|
|
required this.startOffset,
|
|
required this.endOffset,
|
|
required this.firstAssetIndex,
|
|
required this.bucket,
|
|
required this.headerExtent,
|
|
required this.spacing,
|
|
required this.header,
|
|
}) : gridIndex = firstIndex + 1,
|
|
gridOffset = startOffset + headerExtent + spacing;
|
|
|
|
bool containsIndex(int index) => firstIndex <= index && index <= lastIndex;
|
|
|
|
bool isWithinOffset(double offset) =>
|
|
startOffset <= offset && offset <= endOffset;
|
|
|
|
int getMinChildIndexForScrollOffset(double scrollOffset);
|
|
int getMaxChildIndexForScrollOffset(double scrollOffset);
|
|
double indexToLayoutOffset(int index);
|
|
|
|
Widget builder(BuildContext context, int index);
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (identical(this, other)) return true;
|
|
|
|
return other is Segment &&
|
|
other.firstIndex == firstIndex &&
|
|
other.lastIndex == lastIndex &&
|
|
other.startOffset == startOffset &&
|
|
other.endOffset == endOffset &&
|
|
other.spacing == spacing &&
|
|
other.firstAssetIndex == firstAssetIndex &&
|
|
other.headerExtent == headerExtent &&
|
|
other.gridIndex == gridIndex &&
|
|
other.gridOffset == gridOffset &&
|
|
other.header == header;
|
|
}
|
|
|
|
@override
|
|
int get hashCode =>
|
|
firstIndex.hashCode ^
|
|
lastIndex.hashCode ^
|
|
startOffset.hashCode ^
|
|
endOffset.hashCode ^
|
|
spacing.hashCode ^
|
|
headerExtent.hashCode ^
|
|
firstAssetIndex.hashCode ^
|
|
gridIndex.hashCode ^
|
|
gridOffset.hashCode ^
|
|
header.hashCode;
|
|
|
|
@override
|
|
String toString() {
|
|
return 'Segment(firstIndex: $firstIndex, lastIndex: $lastIndex)';
|
|
}
|
|
}
|
|
|
|
extension SegmentListExtension on List<Segment> {
|
|
bool equals(List<Segment> other) =>
|
|
length == other.length &&
|
|
lastOrNull?.endOffset == other.lastOrNull?.endOffset;
|
|
|
|
Segment? findByIndex(int index) =>
|
|
firstWhereOrNull((s) => s.containsIndex(index));
|
|
|
|
Segment? findByOffset(double offset) =>
|
|
firstWhereOrNull((s) => s.isWithinOffset(offset)) ?? lastOrNull;
|
|
}
|