nc-photos/app/lib/widget/photo_list_util.dart

151 lines
4 KiB
Dart

import 'dart:math' as math;
import 'package:clock/clock.dart';
import 'package:collection/collection.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/date_time_extension.dart';
import 'package:nc_photos/entity/collection.dart';
import 'package:nc_photos/entity/collection/content_provider/memory.dart';
import 'package:nc_photos/entity/file_descriptor.dart';
import 'package:np_codegen/np_codegen.dart';
part 'photo_list_util.g.dart';
class DateGroupHelper {
DateGroupHelper({
required this.isMonthOnly,
}) : _tzOffset = clock.now().timeZoneOffset;
DateTime? onFile(
FileDescriptor file, {
DateTime? localDate,
}) {
// toLocal is way too slow
// final localDate = file.fdDateTime.toLocal();
localDate ??= file.fdDateTime.add(_tzOffset);
if (localDate.year != _currentDate?.year ||
localDate.month != _currentDate?.month ||
(!isMonthOnly && localDate.day != _currentDate?.day)) {
_currentDate = localDate;
return localDate;
} else {
return null;
}
}
final bool isMonthOnly;
DateTime? _currentDate;
final Duration _tzOffset;
}
/// Build memory collection from files
///
/// Feb 29 is treated as Mar 1 on non leap years
@npLog
class MemoryCollectionHelper {
MemoryCollectionHelper(
this.account, {
DateTime? today,
required int dayRange,
}) : _tzOffset = clock.now().timeZoneOffset,
// today = (today?.toLocal() ?? clock.now()).toMidnight(),
dayRange = math.max(dayRange, 0) {
this.today = (today ?? clock.now()).toUtc().add(_tzOffset).toMidnight();
}
void addFile(
FileDescriptor f, {
DateTime? localDate,
}) {
// too slow
// final localDate = f.fdDateTime.toLocal().toMidnight();
localDate = (localDate ?? f.fdDateTime.add(_tzOffset)).toMidnight();
final diff = today.difference(localDate).inDays;
if (diff < 300) {
return;
}
for (final dy in [0, -1, 1]) {
if (today
.copyWith(year: localDate.year + dy)
.difference(localDate)
.abs()
.inDays <=
dayRange) {
_log.fine(
"[addFile] Add file (${f.fdDateTime}) to ${localDate.year + dy}");
_addFileToYear(f, localDate.year + dy);
break;
}
}
}
/// Build list of memory albums
///
/// [nameBuilder] is a function that return the name of the album for a
/// particular year
List<Collection> build(String Function(int year) nameBuilder) {
return _data.entries
.sorted((a, b) => b.key.compareTo(a.key))
.map((e) => Collection(
name: nameBuilder(e.key),
contentProvider: CollectionMemoryProvider(
account: account,
year: e.key,
month: today.month,
day: today.day,
cover: e.value.coverFile,
),
))
.toList();
}
void _addFileToYear(FileDescriptor f, int year) {
final item = _data[year];
final date = today.copyWith(year: year);
if (item == null) {
_data[year] = _MemoryCollectionHelperItem(date, f);
} else {
final coverDiff = _MemoryCollectionHelperItem.getCoverDiff(date, f);
if (coverDiff < item.coverDiff) {
item.coverFile = f;
item.coverDiff = coverDiff;
}
}
}
final Account account;
late final DateTime today;
final int dayRange;
final Duration _tzOffset;
final _data = <int, _MemoryCollectionHelperItem>{};
}
int getThumbSize(int zoomLevel) {
switch (zoomLevel) {
case -1:
return 96;
case 1:
return 176;
case 2:
return 256;
case 0:
default:
return 112;
}
}
class _MemoryCollectionHelperItem {
_MemoryCollectionHelperItem(this.date, this.coverFile)
: coverDiff = getCoverDiff(date, coverFile);
static Duration getCoverDiff(DateTime date, FileDescriptor f) =>
f.fdDateTime.difference(date.copyWith(hour: 12)).abs();
final DateTime date;
FileDescriptor coverFile;
Duration coverDiff;
}