ente/lib/ui/viewer/location/add_location_gallery_widget.dart

137 lines
4.2 KiB
Dart

import "dart:developer" as dev;
import "dart:math";
import "package:flutter/material.dart";
import "package:photos/core/constants.dart";
import "package:photos/models/file.dart";
import "package:photos/models/file_load_result.dart";
import "package:photos/services/files_service.dart";
import "package:photos/services/location_service.dart";
import 'package:photos/states/location_state.dart';
import "package:photos/ui/viewer/gallery/gallery.dart";
import "package:photos/utils/local_settings.dart";
///This gallery will get rebuilt with the updated radius when
///InheritedLocationTagData notifies a change in radius.
class DynamicLocationGalleryWidget extends StatefulWidget {
final ValueNotifier<int?> memoriesCountNotifier;
final String tagPrefix;
const DynamicLocationGalleryWidget(
this.memoriesCountNotifier,
this.tagPrefix, {
super.key,
});
@override
State<DynamicLocationGalleryWidget> createState() =>
_DynamicLocationGalleryWidgetState();
}
class _DynamicLocationGalleryWidgetState
extends State<DynamicLocationGalleryWidget> {
late final Future<FileLoadResult> fileLoadResult;
late Future<void> removeIgnoredFiles;
double heightOfGallery = 0;
@override
void initState() {
fileLoadResult = FilesService.instance.fetchAllFilesWithLocationData();
removeIgnoredFiles =
FilesService.instance.removeIgnoredFiles(fileLoadResult);
super.initState();
}
@override
Widget build(BuildContext context) {
const galleryFilesLimit = 1000;
final selectedRadius = _selectedRadius();
Future<FileLoadResult> filterFiles() async {
final FileLoadResult result = await fileLoadResult;
//wait for ignored files to be removed after init
await removeIgnoredFiles;
final stopWatch = Stopwatch()..start();
final copyOfFiles = List<File>.from(result.files);
copyOfFiles.removeWhere((f) {
assert(
f.location != null &&
f.location!.latitude != null &&
f.location!.longitude != null,
);
return !LocationService.instance.isFileInsideLocationTag(
InheritedLocationTagData.of(context).centerPoint,
f.location!,
selectedRadius,
);
});
dev.log(
"Time taken to get all files in a location tag: ${stopWatch.elapsedMilliseconds} ms",
);
stopWatch.stop();
widget.memoriesCountNotifier.value = copyOfFiles.length;
final limitedResults = copyOfFiles.take(galleryFilesLimit).toList();
return Future.value(
FileLoadResult(
limitedResults,
result.hasMore,
),
);
}
return FutureBuilder(
key: ValueKey(selectedRadius),
builder: (context, snapshot) {
if (snapshot.hasData) {
return SizedBox(
height: _galleryHeight(
min(
(widget.memoriesCountNotifier.value ?? 0),
galleryFilesLimit,
),
),
child: Gallery(
key: ValueKey(selectedRadius),
loadingWidget: const SizedBox.shrink(),
disableScroll: true,
asyncLoader: (
creationStartTime,
creationEndTime, {
limit,
asc,
}) async {
return snapshot.data as FileLoadResult;
},
tagPrefix: widget.tagPrefix,
shouldCollateFilesByDay: false,
),
);
} else {
return const SizedBox.shrink();
}
},
future: filterFiles(),
);
}
int _selectedRadius() {
return radiusValues[
InheritedLocationTagData.of(context).selectedRadiusIndex];
}
double _galleryHeight(int fileCount) {
final photoGridSize = LocalSettings.instance.getPhotoGridSize();
final totalWhiteSpaceBetweenPhotos =
galleryGridSpacing * (photoGridSize - 1);
final thumbnailHeight =
((MediaQuery.of(context).size.width - totalWhiteSpaceBetweenPhotos) /
photoGridSize);
final numberOfRows = (fileCount / photoGridSize).ceil();
final galleryHeight = (thumbnailHeight * numberOfRows) +
(galleryGridSpacing * (numberOfRows - 1));
return galleryHeight + 120;
}
}