[mob][photos] More robust caching and models
This commit is contained in:
@@ -47,27 +47,32 @@ class ToShowMemory {
|
||||
final MemoryType type;
|
||||
final int firstTimeToShow;
|
||||
final int lastTimeToShow;
|
||||
final int calculationTime;
|
||||
|
||||
final String? personID;
|
||||
final PeopleMemoryType? peopleMemoryType;
|
||||
final Location? location;
|
||||
|
||||
bool get shouldShowNow {
|
||||
final now = DateTime.now().microsecondsSinceEpoch;
|
||||
return now >= firstTimeToShow && now <= lastTimeToShow;
|
||||
}
|
||||
|
||||
bool get isOld {
|
||||
final now = DateTime.now().microsecondsSinceEpoch;
|
||||
return now > lastTimeToShow;
|
||||
}
|
||||
|
||||
bool shouldShowNow() {
|
||||
final now = DateTime.now().microsecondsSinceEpoch;
|
||||
final relevantForNow = now >= firstTimeToShow && now < lastTimeToShow;
|
||||
final calculatedForNow = (now >= calculationTime) &&
|
||||
(now < calculationTime + kMemoriesUpdateFrequency.inMicroseconds);
|
||||
return relevantForNow && calculatedForNow;
|
||||
}
|
||||
|
||||
ToShowMemory(
|
||||
this.title,
|
||||
this.fileUploadedIDs,
|
||||
this.type,
|
||||
this.firstTimeToShow,
|
||||
this.lastTimeToShow, {
|
||||
this.lastTimeToShow,
|
||||
this.calculationTime, {
|
||||
this.personID,
|
||||
this.peopleMemoryType,
|
||||
this.location,
|
||||
@@ -80,8 +85,7 @@ class ToShowMemory {
|
||||
"PersonID and peopleMemoryType must be provided for people memory type, and location must be provided for trips memory type",
|
||||
);
|
||||
|
||||
factory ToShowMemory.fromSmartMemory(SmartMemory memory) {
|
||||
assert(memory.firstDateToShow != null && memory.lastDateToShow != null);
|
||||
factory ToShowMemory.fromSmartMemory(SmartMemory memory, DateTime calcTime) {
|
||||
String? personID;
|
||||
PeopleMemoryType? peopleMemoryType;
|
||||
Location? location;
|
||||
@@ -92,11 +96,12 @@ class ToShowMemory {
|
||||
location = memory.location;
|
||||
}
|
||||
return ToShowMemory(
|
||||
memory.name,
|
||||
memory.title,
|
||||
memory.memories.map((m) => m.file.uploadedFileID!).toList(),
|
||||
memory.type,
|
||||
memory.firstDateToShow!,
|
||||
memory.lastDateToShow!,
|
||||
memory.firstDateToShow,
|
||||
memory.lastDateToShow,
|
||||
calcTime.microsecondsSinceEpoch,
|
||||
personID: personID,
|
||||
peopleMemoryType: peopleMemoryType,
|
||||
location: location,
|
||||
@@ -110,6 +115,7 @@ class ToShowMemory {
|
||||
memoryTypeFromString(json['type']),
|
||||
json['firstTimeToShow'],
|
||||
json['lastTimeToShow'],
|
||||
json['calculationTime'],
|
||||
personID: json['personID'],
|
||||
peopleMemoryType: peopleMemoryTypeFromString(json['peopleMemoryType']),
|
||||
location: json['location'] != null
|
||||
@@ -128,6 +134,7 @@ class ToShowMemory {
|
||||
'type': type.toString().split('.').last,
|
||||
'firstTimeToShow': firstTimeToShow,
|
||||
'lastTimeToShow': lastTimeToShow,
|
||||
'calculationTime': calculationTime,
|
||||
'personID': personID,
|
||||
'peopleMemoryType': peopleMemoryType.toString().split('.').last,
|
||||
'location': location != null
|
||||
|
||||
@@ -61,35 +61,40 @@ class PeopleMemory extends SmartMemory {
|
||||
|
||||
PeopleMemory(
|
||||
List<Memory> memories,
|
||||
String title,
|
||||
int firstDateToShow,
|
||||
int lastDateToShow,
|
||||
this.peopleMemoryType,
|
||||
this.personID, {
|
||||
super.name,
|
||||
super.firstCreationTime,
|
||||
super.lastCreationTime,
|
||||
super.firstDateToShow,
|
||||
super.lastDateToShow,
|
||||
}) : super(memories, MemoryType.people);
|
||||
}) : super(
|
||||
memories,
|
||||
MemoryType.people,
|
||||
title,
|
||||
firstDateToShow,
|
||||
lastDateToShow,
|
||||
);
|
||||
|
||||
@override
|
||||
PeopleMemory copyWith({
|
||||
List<Memory>? memories,
|
||||
PeopleMemoryType? peopleMemoryType,
|
||||
String? personID,
|
||||
String? name,
|
||||
int? firstCreationTime,
|
||||
int? lastCreationTime,
|
||||
String? title,
|
||||
int? firstDateToShow,
|
||||
int? lastDateToShow,
|
||||
PeopleMemoryType? peopleMemoryType,
|
||||
String? personID,
|
||||
int? firstCreationTime,
|
||||
int? lastCreationTime,
|
||||
}) {
|
||||
return PeopleMemory(
|
||||
memories ?? super.memories,
|
||||
memories ?? this.memories,
|
||||
title ?? this.title,
|
||||
firstDateToShow ?? this.firstDateToShow,
|
||||
lastDateToShow ?? this.lastDateToShow,
|
||||
peopleMemoryType ?? this.peopleMemoryType,
|
||||
personID ?? this.personID,
|
||||
name: name ?? super.name,
|
||||
firstCreationTime: firstCreationTime ?? super.firstCreationTime,
|
||||
lastCreationTime: lastCreationTime ?? super.lastCreationTime,
|
||||
firstDateToShow: firstDateToShow ?? super.firstDateToShow,
|
||||
lastDateToShow: lastDateToShow ?? super.lastDateToShow,
|
||||
firstCreationTime: firstCreationTime ?? this.firstCreationTime,
|
||||
lastCreationTime: lastCreationTime ?? this.lastCreationTime,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import "package:photos/models/memory.dart";
|
||||
|
||||
const kMemoriesUpdateFrequency = Duration(days: 7);
|
||||
const kMemoriesMargin = Duration(days: 2);
|
||||
|
||||
enum MemoryType {
|
||||
people,
|
||||
trips,
|
||||
@@ -25,44 +28,34 @@ MemoryType memoryTypeFromString(String type) {
|
||||
class SmartMemory {
|
||||
final List<Memory> memories;
|
||||
final MemoryType type;
|
||||
String name;
|
||||
String title;
|
||||
int firstDateToShow;
|
||||
int lastDateToShow;
|
||||
|
||||
int? firstCreationTime;
|
||||
int? lastCreationTime;
|
||||
|
||||
int? firstDateToShow;
|
||||
int? lastDateToShow;
|
||||
// TODO: lau: make the above two non-nullable!!!
|
||||
// TODO: lau: actually use this in calculated filters
|
||||
|
||||
SmartMemory(
|
||||
this.memories,
|
||||
this.type, {
|
||||
name,
|
||||
this.type,
|
||||
title,
|
||||
this.firstDateToShow,
|
||||
this.lastDateToShow, {
|
||||
this.firstCreationTime,
|
||||
this.lastCreationTime,
|
||||
this.firstDateToShow,
|
||||
this.lastDateToShow,
|
||||
}) : name = name != null ? name + "(I)" : null;
|
||||
}) : title = title + "(I)";
|
||||
// TODO: lau: remove (I) from name when opening up the feature flag
|
||||
|
||||
bool get notForShow => firstDateToShow == 0 && lastDateToShow == 0;
|
||||
|
||||
bool isOld() {
|
||||
if (firstDateToShow == null || lastDateToShow == null) {
|
||||
return false;
|
||||
}
|
||||
final now = DateTime.now().microsecondsSinceEpoch;
|
||||
return lastDateToShow! < now;
|
||||
}
|
||||
|
||||
bool hasShowTime() {
|
||||
return firstDateToShow != null && lastDateToShow != null;
|
||||
return lastDateToShow < DateTime.now().microsecondsSinceEpoch;
|
||||
}
|
||||
|
||||
bool shouldShowNow() {
|
||||
if (!hasShowTime()) {
|
||||
return false;
|
||||
}
|
||||
final int now = DateTime.now().microsecondsSinceEpoch;
|
||||
return now >= firstDateToShow! && now <= lastDateToShow!;
|
||||
return now >= firstDateToShow && now <= lastDateToShow;
|
||||
}
|
||||
|
||||
int averageCreationTime() {
|
||||
@@ -74,6 +67,11 @@ class SmartMemory {
|
||||
.map((memory) => memory.file.creationTime!)
|
||||
.toList();
|
||||
if (creationTimes.length < 2) {
|
||||
if (creationTimes.isEmpty) {
|
||||
firstCreationTime = 0;
|
||||
lastCreationTime = 0;
|
||||
return 0;
|
||||
}
|
||||
return creationTimes.isEmpty ? 0 : creationTimes.first;
|
||||
}
|
||||
creationTimes.sort();
|
||||
|
||||
@@ -3,38 +3,17 @@ import "package:photos/models/smart_memory.dart";
|
||||
|
||||
class TimeMemory extends SmartMemory {
|
||||
TimeMemory(
|
||||
List<Memory> memories, {
|
||||
String? name,
|
||||
List<Memory> memories,
|
||||
String title,
|
||||
int firstDateToShow,
|
||||
int lastDateToShow, {
|
||||
int? firstCreationTime,
|
||||
int? lastCreationTime,
|
||||
int? firstDateToShow,
|
||||
int? lastDateToShow,
|
||||
}) : super(
|
||||
memories,
|
||||
MemoryType.time,
|
||||
name: name,
|
||||
firstCreationTime: firstCreationTime,
|
||||
lastCreationTime: lastCreationTime,
|
||||
firstDateToShow: firstDateToShow,
|
||||
lastDateToShow: lastDateToShow,
|
||||
title,
|
||||
firstDateToShow,
|
||||
lastDateToShow,
|
||||
);
|
||||
|
||||
@override
|
||||
TimeMemory copyWith({
|
||||
List<Memory>? memories,
|
||||
String? name,
|
||||
int? firstCreationTime,
|
||||
int? lastCreationTime,
|
||||
int? firstDateToShow,
|
||||
int? lastDateToShow,
|
||||
}) {
|
||||
return TimeMemory(
|
||||
memories ?? this.memories,
|
||||
name: name ?? this.name,
|
||||
firstCreationTime: firstCreationTime ?? super.firstCreationTime,
|
||||
lastCreationTime: lastCreationTime ?? super.lastCreationTime,
|
||||
firstDateToShow: firstDateToShow ?? super.firstDateToShow,
|
||||
lastDateToShow: lastDateToShow ?? super.lastDateToShow,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,32 +7,37 @@ class TripMemory extends SmartMemory {
|
||||
|
||||
TripMemory(
|
||||
List<Memory> memories,
|
||||
String title,
|
||||
int firstDateToShow,
|
||||
int lastDateToShow,
|
||||
this.location, {
|
||||
super.name,
|
||||
super.firstCreationTime,
|
||||
super.lastCreationTime,
|
||||
super.firstDateToShow,
|
||||
super.lastDateToShow,
|
||||
}) : super(memories, MemoryType.trips);
|
||||
}) : super(
|
||||
memories,
|
||||
MemoryType.trips,
|
||||
title,
|
||||
firstDateToShow,
|
||||
lastDateToShow,
|
||||
);
|
||||
|
||||
@override
|
||||
TripMemory copyWith({
|
||||
List<Memory>? memories,
|
||||
Location? location,
|
||||
String? name,
|
||||
int? firstCreationTime,
|
||||
int? lastCreationTime,
|
||||
String? title,
|
||||
int? firstDateToShow,
|
||||
int? lastDateToShow,
|
||||
Location? location,
|
||||
int? firstCreationTime,
|
||||
int? lastCreationTime,
|
||||
}) {
|
||||
return TripMemory(
|
||||
memories ?? super.memories,
|
||||
memories ?? this.memories,
|
||||
title ?? this.title,
|
||||
firstDateToShow ?? this.firstDateToShow,
|
||||
lastDateToShow ?? this.lastDateToShow,
|
||||
location ?? this.location,
|
||||
name: name ?? super.name,
|
||||
firstCreationTime: firstCreationTime ?? super.firstCreationTime,
|
||||
lastCreationTime: lastCreationTime ?? super.lastCreationTime,
|
||||
firstDateToShow: firstDateToShow ?? super.firstDateToShow,
|
||||
lastDateToShow: lastDateToShow ?? super.lastDateToShow,
|
||||
firstCreationTime: firstCreationTime ?? this.firstCreationTime,
|
||||
lastCreationTime: lastCreationTime ?? this.lastCreationTime,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ class MemoriesCacheService {
|
||||
/// Delay is for cache update to be done not during app init, during which a
|
||||
/// lot of other things are happening.
|
||||
static const _kCacheUpdateDelay = Duration(seconds: 10);
|
||||
static const _kUpdateFrequency = Duration(days: 7);
|
||||
|
||||
final SharedPreferences _prefs;
|
||||
late final Logger _logger = Logger("MemoriesCacheService");
|
||||
@@ -48,7 +47,9 @@ class MemoriesCacheService {
|
||||
unawaited(_memoriesDB.getSeenTimes().then((value) => _seenTimes = value));
|
||||
unawaited(
|
||||
_memoriesDB.clearMemoriesSeenBeforeTime(
|
||||
DateTime.now().subtract(_kUpdateFrequency).microsecondsSinceEpoch,
|
||||
DateTime.now()
|
||||
.subtract(kMemoriesUpdateFrequency)
|
||||
.microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -86,14 +87,16 @@ class MemoriesCacheService {
|
||||
|
||||
Future<void> _checkIfTimeToUpdateCache() async {
|
||||
if (lastMemoriesCacheUpdateTime <
|
||||
DateTime.now().subtract(_kUpdateFrequency).microsecondsSinceEpoch) {
|
||||
DateTime.now()
|
||||
.subtract(kMemoriesUpdateFrequency)
|
||||
.microsecondsSinceEpoch) {
|
||||
_shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> _getCachePath() async {
|
||||
return (await getApplicationSupportDirectory()).path +
|
||||
"/cache//test1/memories_cache";
|
||||
"/cache//test2/memories_cache";
|
||||
// TODO: lau: remove the test1 directory after testing
|
||||
}
|
||||
|
||||
@@ -133,20 +136,21 @@ class MemoriesCacheService {
|
||||
w?.start();
|
||||
// calculate memories for this period and for the next period
|
||||
final now = DateTime.now();
|
||||
final next = now.add(_kUpdateFrequency);
|
||||
final List<SmartMemory> memories = [];
|
||||
memories.addAll(await SmartMemoriesService.instance.calcMemories(now));
|
||||
memories.addAll(await SmartMemoriesService.instance.calcMemories(next));
|
||||
final next = now.add(kMemoriesUpdateFrequency);
|
||||
final nowMemories = await SmartMemoriesService.instance.calcMemories(now);
|
||||
final nextMemories =
|
||||
await SmartMemoriesService.instance.calcMemories(next);
|
||||
w?.log("calculated new memories");
|
||||
final oldCache = await _readCacheFromDisk();
|
||||
w?.log("gotten old cache");
|
||||
final MemoriesCache memoryCache = _toCache(memories, oldCache);
|
||||
final MemoriesCache memoryCache =
|
||||
_toCache(nowMemories, now, nextMemories, next, oldCache);
|
||||
w?.log("gotten cache from memories");
|
||||
final file = File(await _getCachePath());
|
||||
if (!file.existsSync()) {
|
||||
file.createSync(recursive: true);
|
||||
}
|
||||
_cachedMemories = memories;
|
||||
_cachedMemories = nowMemories;
|
||||
await file.writeAsBytes(
|
||||
MemoriesCache.encodeToJsonString(memoryCache).codeUnits,
|
||||
);
|
||||
@@ -162,18 +166,20 @@ class MemoriesCacheService {
|
||||
}
|
||||
|
||||
MemoriesCache _toCache(
|
||||
List<SmartMemory> memories,
|
||||
List<SmartMemory> nowMemories,
|
||||
DateTime now,
|
||||
List<SmartMemory> nextMemories,
|
||||
DateTime next,
|
||||
MemoriesCache? oldCache,
|
||||
) {
|
||||
final List<ToShowMemory> toShowMemories = [];
|
||||
final List<PeopleShownLog> peopleShownLogs = [];
|
||||
final List<TripsShownLog> tripsShownLogs = [];
|
||||
for (final memory in memories) {
|
||||
if (memory.hasShowTime()) {
|
||||
toShowMemories.add(ToShowMemory.fromSmartMemory(memory));
|
||||
} else {
|
||||
_logger.severe('Memory has no first or last date to show');
|
||||
}
|
||||
for (final nowMemory in nowMemories) {
|
||||
toShowMemories.add(ToShowMemory.fromSmartMemory(nowMemory, now));
|
||||
}
|
||||
for (final nextMemory in nextMemories) {
|
||||
toShowMemories.add(ToShowMemory.fromSmartMemory(nextMemory, next));
|
||||
}
|
||||
if (oldCache != null) {
|
||||
peopleShownLogs.addAll(oldCache.peopleShownLogs);
|
||||
@@ -224,7 +230,7 @@ class MemoriesCacheService {
|
||||
}
|
||||
|
||||
for (final ToShowMemory memory in cache.toShowMemories) {
|
||||
if (memory.shouldShowNow) {
|
||||
if (memory.shouldShowNow()) {
|
||||
memories.add(
|
||||
SmartMemory(
|
||||
memory.fileUploadedIDs
|
||||
@@ -234,9 +240,9 @@ class MemoriesCacheService {
|
||||
)
|
||||
.toList(),
|
||||
memory.type,
|
||||
name: memory.title,
|
||||
firstDateToShow: memory.firstTimeToShow,
|
||||
lastDateToShow: memory.lastTimeToShow,
|
||||
memory.title,
|
||||
memory.firstTimeToShow,
|
||||
memory.lastTimeToShow,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1196,15 +1196,14 @@ class SearchService {
|
||||
final memories = await memoriesCacheService.getMemories(limit);
|
||||
final searchResults = <GenericSearchResult>[];
|
||||
for (final memory in memories) {
|
||||
final name = memory.name ?? "memory";
|
||||
final files = Memory.filesFromMemories(memory.memories);
|
||||
searchResults.add(
|
||||
GenericSearchResult(
|
||||
ResultType.event,
|
||||
name,
|
||||
memory.title,
|
||||
files,
|
||||
hierarchicalSearchFilter: TopLevelGenericFilter(
|
||||
filterName: name,
|
||||
filterName: memory.title,
|
||||
occurrence: kMostRelevantFilter,
|
||||
filterResultType: ResultType.event,
|
||||
matchedUploadedIDs: filesToUploadedFileIDs(files),
|
||||
|
||||
@@ -208,9 +208,11 @@ class SmartMemoriesService {
|
||||
);
|
||||
final spotlightMemory = PeopleMemory(
|
||||
selectSpotlightMemories,
|
||||
title,
|
||||
currentTime.microsecondsSinceEpoch,
|
||||
currentTime.add(kMemoriesUpdateFrequency).microsecondsSinceEpoch,
|
||||
PeopleMemoryType.spotlight,
|
||||
personID,
|
||||
name: title,
|
||||
);
|
||||
personToMemories
|
||||
.putIfAbsent(personID, () => {})
|
||||
@@ -236,9 +238,11 @@ class SmartMemoriesService {
|
||||
);
|
||||
final youAndThemMemory = PeopleMemory(
|
||||
selectYouAndThemMemories,
|
||||
title,
|
||||
currentTime.microsecondsSinceEpoch,
|
||||
currentTime.add(kMemoriesUpdateFrequency).microsecondsSinceEpoch,
|
||||
PeopleMemoryType.youAndThem,
|
||||
personID,
|
||||
name: title,
|
||||
);
|
||||
personToMemories
|
||||
.putIfAbsent(personID, () => {})
|
||||
@@ -281,9 +285,11 @@ class SmartMemoriesService {
|
||||
);
|
||||
final activityMemory = PeopleMemory(
|
||||
selectActivityMemories,
|
||||
title,
|
||||
currentTime.microsecondsSinceEpoch,
|
||||
currentTime.add(kMemoriesUpdateFrequency).microsecondsSinceEpoch,
|
||||
PeopleMemoryType.doingSomethingTogether,
|
||||
personID,
|
||||
name: title,
|
||||
);
|
||||
personToMemories.putIfAbsent(personID, () => {}).putIfAbsent(
|
||||
PeopleMemoryType.doingSomethingTogether,
|
||||
@@ -326,9 +332,11 @@ class SmartMemoriesService {
|
||||
lastTimeYouSawThemFiles
|
||||
.map((f) => Memory.fromFile(f, _seenTimes))
|
||||
.toList(),
|
||||
title,
|
||||
currentTime.microsecondsSinceEpoch,
|
||||
currentTime.add(kMemoriesUpdateFrequency).microsecondsSinceEpoch,
|
||||
PeopleMemoryType.lastTimeYouSawThem,
|
||||
personID,
|
||||
name: title,
|
||||
);
|
||||
personToMemories.putIfAbsent(personID, () => {}).putIfAbsent(
|
||||
PeopleMemoryType.lastTimeYouSawThem,
|
||||
@@ -528,7 +536,10 @@ class SmartMemoriesService {
|
||||
Memory.fromFiles(
|
||||
currentBlockFiles,
|
||||
_seenTimes,
|
||||
), // TODO: lau: properly check last seen times
|
||||
),
|
||||
'Trip1',
|
||||
0,
|
||||
0,
|
||||
location,
|
||||
firstCreationTime: blockStart,
|
||||
lastCreationTime: lastTime,
|
||||
@@ -553,6 +564,9 @@ class SmartMemoriesService {
|
||||
tripLocations.add(
|
||||
TripMemory(
|
||||
Memory.fromFiles(currentBlockFiles, _seenTimes),
|
||||
'Trip2',
|
||||
0,
|
||||
0,
|
||||
location,
|
||||
firstCreationTime: blockStart,
|
||||
lastCreationTime: lastTime,
|
||||
@@ -584,6 +598,9 @@ class SmartMemoriesService {
|
||||
)) {
|
||||
mergedTrips[idx] = TripMemory(
|
||||
otherTrip.memories + trip.memories,
|
||||
'Trip3',
|
||||
0,
|
||||
0,
|
||||
otherTrip.location,
|
||||
firstCreationTime:
|
||||
min(otherTrip.firstCreationTime!, trip.firstCreationTime!),
|
||||
@@ -599,6 +616,9 @@ class SmartMemoriesService {
|
||||
mergedTrips.add(
|
||||
TripMemory(
|
||||
trip.memories,
|
||||
'Trip4',
|
||||
0,
|
||||
0,
|
||||
trip.location,
|
||||
firstCreationTime: trip.firstCreationTime,
|
||||
lastCreationTime: trip.lastCreationTime,
|
||||
@@ -629,8 +649,10 @@ class SmartMemoriesService {
|
||||
memoryResults.add(
|
||||
TripMemory(
|
||||
Memory.fromFiles(baseLocation.files, _seenTimes),
|
||||
name,
|
||||
0,
|
||||
0,
|
||||
baseLocation.location,
|
||||
name: name,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -676,10 +698,28 @@ class SmartMemoriesService {
|
||||
name = "Last year's trip";
|
||||
}
|
||||
final photoSelection = await _bestSelection(trip.memories);
|
||||
final firstCreationDate = DateTime.fromMicrosecondsSinceEpoch(
|
||||
trip.firstCreationTime!,
|
||||
);
|
||||
final firstDateToShow = DateTime(
|
||||
currentTime.year,
|
||||
firstCreationDate.month,
|
||||
firstCreationDate.day,
|
||||
).subtract(kMemoriesMargin).microsecondsSinceEpoch;
|
||||
final lastCreationDate = DateTime.fromMicrosecondsSinceEpoch(
|
||||
trip.lastCreationTime!,
|
||||
);
|
||||
final lastDateToShow = DateTime(
|
||||
currentTime.year,
|
||||
lastCreationDate.month,
|
||||
lastCreationDate.day,
|
||||
).add(kMemoriesMargin).microsecondsSinceEpoch;
|
||||
memoryResults.add(
|
||||
trip.copyWith(
|
||||
memories: photoSelection,
|
||||
name: name,
|
||||
title: name,
|
||||
firstDateToShow: firstDateToShow,
|
||||
lastDateToShow: lastDateToShow,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -717,10 +757,28 @@ class SmartMemoriesService {
|
||||
name = "Last year's trip";
|
||||
}
|
||||
final photoSelection = await _bestSelection(trip.memories);
|
||||
final firstCreationDate = DateTime.fromMicrosecondsSinceEpoch(
|
||||
trip.firstCreationTime!,
|
||||
);
|
||||
final firstDateToShow = DateTime(
|
||||
currentTime.year,
|
||||
firstCreationDate.month,
|
||||
firstCreationDate.day,
|
||||
).subtract(kMemoriesMargin).microsecondsSinceEpoch;
|
||||
final lastCreationDate = DateTime.fromMicrosecondsSinceEpoch(
|
||||
trip.lastCreationTime!,
|
||||
);
|
||||
final lastDateToShow = DateTime(
|
||||
currentTime.year,
|
||||
lastCreationDate.month,
|
||||
lastCreationDate.day,
|
||||
).add(kMemoriesMargin).microsecondsSinceEpoch;
|
||||
memoryResults.add(
|
||||
trip.copyWith(
|
||||
memories: photoSelection,
|
||||
name: name,
|
||||
title: name,
|
||||
firstDateToShow: firstDateToShow,
|
||||
lastDateToShow: lastDateToShow,
|
||||
),
|
||||
);
|
||||
break checkUpcomingMonths;
|
||||
@@ -741,6 +799,7 @@ class SmartMemoriesService {
|
||||
final currentDayMonth = currentTime.month * 100 + currentTime.day;
|
||||
final currentWeek = _getWeekNumber(currentTime);
|
||||
final currentMonth = currentTime.month;
|
||||
final currentYear = currentTime.year;
|
||||
final cutOffTime = currentTime.subtract(const Duration(days: 365));
|
||||
final averageDailyPhotos = allFiles.length / 365;
|
||||
final significantDayThreshold = averageDailyPhotos * 0.25;
|
||||
@@ -766,7 +825,7 @@ class SmartMemoriesService {
|
||||
// Process each nearby day-month to find significant days
|
||||
for (final dayMonth in dayMonthYearGroups.keys) {
|
||||
final dayDiff = dayMonth - currentDayMonth;
|
||||
if (dayDiff < 0 || dayDiff > 2) continue;
|
||||
if (dayDiff < 0 || dayDiff > kMemoriesUpdateFrequency.inDays) continue;
|
||||
// TODO: lau: this doesn't cover month changes properly
|
||||
|
||||
final yearGroups = dayMonthYearGroups[dayMonth]!;
|
||||
@@ -776,7 +835,6 @@ class SmartMemoriesService {
|
||||
.toList();
|
||||
|
||||
if (significantDays.length >= 3) {
|
||||
// THE ISSUE IS HERE, MOST LIKELY IN THE SELECTION!
|
||||
// Combine all years for this day-month
|
||||
final date =
|
||||
DateTime(currentTime.year, dayMonth ~/ 100, dayMonth % 100);
|
||||
@@ -786,24 +844,35 @@ class SmartMemoriesService {
|
||||
memoryResult.add(
|
||||
TimeMemory(
|
||||
photoSelection,
|
||||
name: "${DateFormat('MMMM d').format(date)} through the years",
|
||||
"${DateFormat('MMMM d').format(date)} through the years",
|
||||
date.subtract(kMemoriesMargin).microsecondsSinceEpoch,
|
||||
date.add(const Duration(days: 1)).microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Individual entries for significant years
|
||||
for (final year in significantDays) {
|
||||
final date = DateTime(year, dayMonth ~/ 100, dayMonth % 100);
|
||||
final showDate =
|
||||
DateTime(currentYear, dayMonth ~/ 100, dayMonth % 100);
|
||||
final files = yearGroups[year]!;
|
||||
final photoSelection = await _bestSelection(files);
|
||||
String name = DateFormat.yMMMd(_locale?.languageCode).format(date);
|
||||
if (date.day == currentTime.day && date.month == currentTime.month) {
|
||||
name = "This day, ${currentTime.year - date.year} years back";
|
||||
}
|
||||
|
||||
memoryResult.add(
|
||||
TimeMemory(
|
||||
photoSelection,
|
||||
name: name,
|
||||
name,
|
||||
showDate.subtract(kMemoriesMargin).microsecondsSinceEpoch,
|
||||
showDate.microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
name = "This day, ${currentTime.year - date.year} years back";
|
||||
memoryResult.add(
|
||||
TimeMemory(
|
||||
photoSelection,
|
||||
name,
|
||||
showDate.microsecondsSinceEpoch,
|
||||
showDate.add(const Duration(days: 1)).microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -843,7 +912,9 @@ class SmartMemoriesService {
|
||||
memoryResult.add(
|
||||
TimeMemory(
|
||||
photoSelection,
|
||||
name: name,
|
||||
name,
|
||||
currentTime.subtract(kMemoriesMargin).microsecondsSinceEpoch,
|
||||
currentTime.add(kMemoriesUpdateFrequency).microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -860,7 +931,11 @@ class SmartMemoriesService {
|
||||
memoryResult.add(
|
||||
TimeMemory(
|
||||
photoSelection,
|
||||
name: name,
|
||||
name,
|
||||
currentTime.subtract(kMemoriesMargin).microsecondsSinceEpoch,
|
||||
currentTime
|
||||
.add(kMemoriesUpdateFrequency)
|
||||
.microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -908,11 +983,18 @@ class SmartMemoriesService {
|
||||
);
|
||||
final monthName = DateFormat.MMMM(_locale?.languageCode)
|
||||
.format(DateTime(year, currentMonth));
|
||||
final daysLeftInMonth = DateTime(currentYear, currentMonth + 1, 0).day -
|
||||
currentTime.day +
|
||||
1;
|
||||
final name = monthName + ", ${currentTime.year - year} years back";
|
||||
memoryResult.add(
|
||||
TimeMemory(
|
||||
photoSelection,
|
||||
name: name,
|
||||
name,
|
||||
currentTime.microsecondsSinceEpoch,
|
||||
currentTime
|
||||
.add(Duration(days: daysLeftInMonth))
|
||||
.microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -926,17 +1008,22 @@ class SmartMemoriesService {
|
||||
await _bestSelection(allPhotos, prefferedSize: monthSelectionSize);
|
||||
final monthName = DateFormat.MMMM(_locale?.languageCode)
|
||||
.format(DateTime(currentTime.year, currentMonth));
|
||||
final daysLeftInMonth =
|
||||
DateTime(currentYear, currentMonth + 1, 0).day - currentTime.day + 1;
|
||||
final name = monthName + " through the years";
|
||||
memoryResult.add(
|
||||
TimeMemory(
|
||||
photoSelection,
|
||||
name: name,
|
||||
name,
|
||||
currentTime.microsecondsSinceEpoch,
|
||||
currentTime.add(Duration(days: daysLeftInMonth)).microsecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
|
||||
return memoryResult;
|
||||
}
|
||||
|
||||
/// TODO: lau: replace this by just taking next 7 days
|
||||
int _getWeekNumber(DateTime date) {
|
||||
// Get day of year (1-366)
|
||||
final int dayOfYear = int.parse(DateFormat('D').format(date));
|
||||
|
||||
@@ -128,7 +128,8 @@ class _MemoriesWidgetState extends State<MemoriesWidget> {
|
||||
}
|
||||
|
||||
Widget _buildSmartMemories(List<SmartMemory> memories) {
|
||||
final collatedMemories = memories.map((e) => (e.memories, e.name)).toList();
|
||||
final collatedMemories =
|
||||
memories.map((e) => (e.memories, e.title)).toList();
|
||||
|
||||
return SizedBox(
|
||||
height: _maxHeight + MemoryCoverWidget.outerStrokeWidth * 2,
|
||||
|
||||
Reference in New Issue
Block a user