Merge pull request #482 from ente-io/search_refactor
This commit is contained in:
commit
bea8aded44
|
@ -1,4 +1,10 @@
|
||||||
import 'package:photos/models/search/holiday_search_result.dart';
|
class HolidayData {
|
||||||
|
final String name;
|
||||||
|
final int month;
|
||||||
|
final int day;
|
||||||
|
|
||||||
|
const HolidayData(this.name, {required this.month, required this.day});
|
||||||
|
}
|
||||||
|
|
||||||
const List<HolidayData> allHolidays = [
|
const List<HolidayData> allHolidays = [
|
||||||
HolidayData('New Year', month: 1, day: 1),
|
HolidayData('New Year', month: 1, day: 1),
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'package:photos/models/search/month_search_result.dart';
|
|
||||||
|
|
||||||
List<MonthData> allMonths = [
|
List<MonthData> allMonths = [
|
||||||
MonthData('January', 1),
|
MonthData('January', 1),
|
||||||
MonthData('February', 2),
|
MonthData('February', 2),
|
||||||
|
@ -14,3 +12,10 @@ List<MonthData> allMonths = [
|
||||||
MonthData('November', 11),
|
MonthData('November', 11),
|
||||||
MonthData('December', 12),
|
MonthData('December', 12),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
class MonthData {
|
||||||
|
final String name;
|
||||||
|
final int monthNumber;
|
||||||
|
|
||||||
|
MonthData(this.name, this.monthNumber);
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,30 @@
|
||||||
import 'package:photos/models/collection_items.dart';
|
import 'package:photos/models/collection_items.dart';
|
||||||
import 'package:photos/models/search/search_results.dart';
|
import 'package:photos/models/file.dart';
|
||||||
|
import 'package:photos/models/search/search_result.dart';
|
||||||
|
|
||||||
class AlbumSearchResult extends SearchResult {
|
class AlbumSearchResult extends SearchResult {
|
||||||
final CollectionWithThumbnail collectionWithThumbnail;
|
final CollectionWithThumbnail collectionWithThumbnail;
|
||||||
|
|
||||||
AlbumSearchResult(this.collectionWithThumbnail);
|
AlbumSearchResult(this.collectionWithThumbnail);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ResultType type() {
|
||||||
|
return ResultType.collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String name() {
|
||||||
|
return collectionWithThumbnail.collection.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
File previewThumbnail() {
|
||||||
|
return collectionWithThumbnail.thumbnail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<File> resultFiles() {
|
||||||
|
// for album search result, we should open the album page directly
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,29 @@
|
||||||
import 'package:photos/models/file.dart';
|
import 'package:photos/models/file.dart';
|
||||||
import 'package:photos/models/search/search_results.dart';
|
import 'package:photos/models/search/search_result.dart';
|
||||||
|
|
||||||
class FileSearchResult extends SearchResult {
|
class FileSearchResult extends SearchResult {
|
||||||
final File file;
|
final File file;
|
||||||
|
|
||||||
FileSearchResult(this.file);
|
FileSearchResult(this.file);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String name() {
|
||||||
|
return file.getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ResultType type() {
|
||||||
|
return ResultType.file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
File previewThumbnail() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<File> resultFiles() {
|
||||||
|
// for fileSearchResult, the file detailed page view will be opened
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
30
lib/models/search/generic_search_result.dart
Normal file
30
lib/models/search/generic_search_result.dart
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:photos/models/file.dart';
|
||||||
|
import 'package:photos/models/search/search_result.dart';
|
||||||
|
|
||||||
|
class GenericSearchResult extends SearchResult {
|
||||||
|
final String _name;
|
||||||
|
final List<File> _files;
|
||||||
|
final ResultType _type;
|
||||||
|
|
||||||
|
GenericSearchResult(this._type, this._name, this._files);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String name() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ResultType type() {
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
File previewThumbnail() {
|
||||||
|
return _files.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<File> resultFiles() {
|
||||||
|
return _files;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
import 'package:photos/models/file.dart';
|
|
||||||
import 'package:photos/models/search/search_results.dart';
|
|
||||||
|
|
||||||
class HolidaySearchResult extends SearchResult {
|
|
||||||
final String holidayName;
|
|
||||||
final List<File> files;
|
|
||||||
HolidaySearchResult(this.holidayName, this.files);
|
|
||||||
}
|
|
||||||
|
|
||||||
class HolidayData {
|
|
||||||
final String name;
|
|
||||||
final int month;
|
|
||||||
final int day;
|
|
||||||
const HolidayData(this.name, {required this.month, required this.day});
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import 'package:photos/models/file.dart';
|
|
||||||
import 'package:photos/models/search/search_results.dart';
|
|
||||||
|
|
||||||
class LocationSearchResult extends SearchResult {
|
|
||||||
final String location;
|
|
||||||
final List<File> files;
|
|
||||||
|
|
||||||
LocationSearchResult(this.location, this.files);
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
import 'package:photos/models/file.dart';
|
|
||||||
import 'package:photos/models/search/search_results.dart';
|
|
||||||
|
|
||||||
class MonthSearchResult extends SearchResult {
|
|
||||||
final String month;
|
|
||||||
final List<File> files;
|
|
||||||
MonthSearchResult(this.month, this.files);
|
|
||||||
}
|
|
||||||
|
|
||||||
class MonthData {
|
|
||||||
final String name;
|
|
||||||
final int monthNumber;
|
|
||||||
MonthData(this.name, this.monthNumber);
|
|
||||||
}
|
|
17
lib/models/search/search_result.dart
Normal file
17
lib/models/search/search_result.dart
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import 'package:photos/models/file.dart';
|
||||||
|
|
||||||
|
abstract class SearchResult {
|
||||||
|
ResultType type();
|
||||||
|
|
||||||
|
String name();
|
||||||
|
|
||||||
|
File previewThumbnail();
|
||||||
|
|
||||||
|
String heroTag() {
|
||||||
|
return '${type().toString()}_${name()}';
|
||||||
|
}
|
||||||
|
|
||||||
|
List<File> resultFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ResultType { collection, file, location, month, year, fileType, event }
|
|
@ -1 +0,0 @@
|
||||||
class SearchResult {}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import 'package:photos/models/file.dart';
|
|
||||||
import 'package:photos/models/search/search_results.dart';
|
|
||||||
|
|
||||||
class YearSearchResult extends SearchResult {
|
|
||||||
final String year;
|
|
||||||
final List<File> files;
|
|
||||||
|
|
||||||
YearSearchResult(this.year, this.files);
|
|
||||||
}
|
|
|
@ -15,11 +15,9 @@ import 'package:photos/models/collection_items.dart';
|
||||||
import 'package:photos/models/file.dart';
|
import 'package:photos/models/file.dart';
|
||||||
import 'package:photos/models/location.dart';
|
import 'package:photos/models/location.dart';
|
||||||
import 'package:photos/models/search/album_search_result.dart';
|
import 'package:photos/models/search/album_search_result.dart';
|
||||||
import 'package:photos/models/search/holiday_search_result.dart';
|
import 'package:photos/models/search/generic_search_result.dart';
|
||||||
import 'package:photos/models/search/location_api_response.dart';
|
import 'package:photos/models/search/location_api_response.dart';
|
||||||
import 'package:photos/models/search/location_search_result.dart';
|
import 'package:photos/models/search/search_result.dart';
|
||||||
import 'package:photos/models/search/month_search_result.dart';
|
|
||||||
import 'package:photos/models/search/year_search_result.dart';
|
|
||||||
import 'package:photos/services/collections_service.dart';
|
import 'package:photos/services/collections_service.dart';
|
||||||
import 'package:photos/utils/date_time_util.dart';
|
import 'package:photos/utils/date_time_util.dart';
|
||||||
|
|
||||||
|
@ -40,27 +38,28 @@ class SearchService {
|
||||||
/* In case home screen loads before 5 seconds and user starts search,
|
/* In case home screen loads before 5 seconds and user starts search,
|
||||||
future will not be null.So here getAllFiles won't run again in that case. */
|
future will not be null.So here getAllFiles won't run again in that case. */
|
||||||
if (_cachedFilesFuture == null) {
|
if (_cachedFilesFuture == null) {
|
||||||
getAllFiles();
|
_getAllFiles();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Bus.instance.on<LocalPhotosUpdatedEvent>().listen((event) {
|
Bus.instance.on<LocalPhotosUpdatedEvent>().listen((event) {
|
||||||
_cachedFilesFuture = null;
|
_cachedFilesFuture = null;
|
||||||
getAllFiles();
|
_getAllFiles();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<File>> getAllFiles() async {
|
Future<List<File>> _getAllFiles() async {
|
||||||
if (_cachedFilesFuture != null) {
|
if (_cachedFilesFuture != null) {
|
||||||
return _cachedFilesFuture;
|
return _cachedFilesFuture;
|
||||||
}
|
}
|
||||||
|
_logger.fine("Reading all files from db");
|
||||||
_cachedFilesFuture = FilesDB.instance.getAllFilesFromDB();
|
_cachedFilesFuture = FilesDB.instance.getAllFilesFromDB();
|
||||||
return _cachedFilesFuture;
|
return _cachedFilesFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<File>> getFileSearchResults(String query) async {
|
Future<List<File>> getFileSearchResults(String query) async {
|
||||||
final List<File> fileSearchResults = [];
|
final List<File> fileSearchResults = [];
|
||||||
final List<File> files = await getAllFiles();
|
final List<File> files = await _getAllFiles();
|
||||||
final nonCaseSensitiveRegexForQuery = RegExp(query, caseSensitive: false);
|
final nonCaseSensitiveRegexForQuery = RegExp(query, caseSensitive: false);
|
||||||
for (var file in files) {
|
for (var file in files) {
|
||||||
if (fileSearchResults.length >= _maximumResultsLimit) {
|
if (fileSearchResults.length >= _maximumResultsLimit) {
|
||||||
|
@ -77,12 +76,12 @@ class SearchService {
|
||||||
_cachedFilesFuture = null;
|
_cachedFilesFuture = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<LocationSearchResult>> getLocationSearchResults(
|
Future<List<GenericSearchResult>> getLocationSearchResults(
|
||||||
String query,
|
String query,
|
||||||
) async {
|
) async {
|
||||||
final List<LocationSearchResult> locationSearchResults = [];
|
final List<GenericSearchResult> searchResults = [];
|
||||||
try {
|
try {
|
||||||
final List<File> allFiles = await SearchService.instance.getAllFiles();
|
final List<File> allFiles = await _getAllFiles();
|
||||||
|
|
||||||
final response = await _dio.get(
|
final response = await _dio.get(
|
||||||
_config.getHttpEndpoint() + "/search/location",
|
_config.getHttpEndpoint() + "/search/location",
|
||||||
|
@ -108,15 +107,16 @@ class SearchService {
|
||||||
(first, second) => second.creationTime.compareTo(first.creationTime),
|
(first, second) => second.creationTime.compareTo(first.creationTime),
|
||||||
);
|
);
|
||||||
if (filesInLocation.isNotEmpty) {
|
if (filesInLocation.isNotEmpty) {
|
||||||
locationSearchResults.add(
|
searchResults.add(
|
||||||
LocationSearchResult(locationData.place, filesInLocation),
|
GenericSearchResult(
|
||||||
|
ResultType.location, locationData.place, filesInLocation),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_logger.severe(e);
|
_logger.severe(e);
|
||||||
}
|
}
|
||||||
return locationSearchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFilteredCollectionsWithThumbnail removes deleted or archived or
|
// getFilteredCollectionsWithThumbnail removes deleted or archived or
|
||||||
|
@ -149,16 +149,17 @@ class SearchService {
|
||||||
return collectionSearchResults;
|
return collectionSearchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<YearSearchResult>> getYearSearchResults(
|
Future<List<GenericSearchResult>> getYearSearchResults(
|
||||||
String yearFromQuery,
|
String yearFromQuery,
|
||||||
) async {
|
) async {
|
||||||
final List<YearSearchResult> yearSearchResults = [];
|
final List<GenericSearchResult> searchResults = [];
|
||||||
for (var yearData in YearsData.instance.yearsData) {
|
for (var yearData in YearsData.instance.yearsData) {
|
||||||
if (yearData.year.startsWith(yearFromQuery)) {
|
if (yearData.year.startsWith(yearFromQuery)) {
|
||||||
final List<File> filesInYear = await _getFilesInYear(yearData.duration);
|
final List<File> filesInYear = await _getFilesInYear(yearData.duration);
|
||||||
if (filesInYear.isNotEmpty) {
|
if (filesInYear.isNotEmpty) {
|
||||||
yearSearchResults.add(
|
searchResults.add(
|
||||||
YearSearchResult(
|
GenericSearchResult(
|
||||||
|
ResultType.year,
|
||||||
yearData.year,
|
yearData.year,
|
||||||
filesInYear,
|
filesInYear,
|
||||||
),
|
),
|
||||||
|
@ -166,13 +167,13 @@ class SearchService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return yearSearchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<HolidaySearchResult>> getHolidaySearchResults(
|
Future<List<GenericSearchResult>> getHolidaySearchResults(
|
||||||
String query,
|
String query,
|
||||||
) async {
|
) async {
|
||||||
final List<HolidaySearchResult> holidaySearchResults = [];
|
final List<GenericSearchResult> searchResults = [];
|
||||||
|
|
||||||
final nonCaseSensitiveRegexForQuery = RegExp(query, caseSensitive: false);
|
final nonCaseSensitiveRegexForQuery = RegExp(query, caseSensitive: false);
|
||||||
|
|
||||||
|
@ -185,17 +186,17 @@ class SearchService {
|
||||||
order: 'DESC',
|
order: 'DESC',
|
||||||
);
|
);
|
||||||
if (matchedFiles.isNotEmpty) {
|
if (matchedFiles.isNotEmpty) {
|
||||||
holidaySearchResults.add(
|
searchResults.add(
|
||||||
HolidaySearchResult(holiday.name, matchedFiles),
|
GenericSearchResult(ResultType.event, holiday.name, matchedFiles),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return holidaySearchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<MonthSearchResult>> getMonthSearchResults(String query) async {
|
Future<List<GenericSearchResult>> getMonthSearchResults(String query) async {
|
||||||
final List<MonthSearchResult> monthSearchResults = [];
|
final List<GenericSearchResult> searchResults = [];
|
||||||
final nonCaseSensitiveRegexForQuery = RegExp(query, caseSensitive: false);
|
final nonCaseSensitiveRegexForQuery = RegExp(query, caseSensitive: false);
|
||||||
|
|
||||||
for (var month in allMonths) {
|
for (var month in allMonths) {
|
||||||
|
@ -207,8 +208,9 @@ class SearchService {
|
||||||
order: 'DESC',
|
order: 'DESC',
|
||||||
);
|
);
|
||||||
if (matchedFiles.isNotEmpty) {
|
if (matchedFiles.isNotEmpty) {
|
||||||
monthSearchResults.add(
|
searchResults.add(
|
||||||
MonthSearchResult(
|
GenericSearchResult(
|
||||||
|
ResultType.month,
|
||||||
month.name,
|
month.name,
|
||||||
matchedFiles,
|
matchedFiles,
|
||||||
),
|
),
|
||||||
|
@ -217,7 +219,7 @@ class SearchService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return monthSearchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<File>> _getFilesInYear(List<int> durationOfYear) async {
|
Future<List<File>> _getFilesInYear(List<int> durationOfYear) async {
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:photos/core/event_bus.dart';
|
|
||||||
import 'package:photos/events/files_updated_event.dart';
|
|
||||||
import 'package:photos/events/local_photos_updated_event.dart';
|
|
||||||
import 'package:photos/models/file_load_result.dart';
|
|
||||||
import 'package:photos/models/gallery_type.dart';
|
|
||||||
import 'package:photos/models/search/holiday_search_result.dart';
|
|
||||||
import 'package:photos/models/selected_files.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_overlay_widget.dart';
|
|
||||||
|
|
||||||
class FilesFromHolidayPage extends StatelessWidget {
|
|
||||||
final HolidaySearchResult holidaySearchResult;
|
|
||||||
final String tagPrefix;
|
|
||||||
|
|
||||||
final _selectedFiles = SelectedFiles();
|
|
||||||
static const GalleryType appBarType = GalleryType.searchResults;
|
|
||||||
static const GalleryType overlayType = GalleryType.searchResults;
|
|
||||||
|
|
||||||
FilesFromHolidayPage(
|
|
||||||
this.holidaySearchResult,
|
|
||||||
this.tagPrefix, {
|
|
||||||
Key key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final gallery = Gallery(
|
|
||||||
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
|
|
||||||
final result = holidaySearchResult.files
|
|
||||||
.where(
|
|
||||||
(file) =>
|
|
||||||
file.creationTime >= creationStartTime &&
|
|
||||||
file.creationTime <= creationEndTime,
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
return Future.value(
|
|
||||||
FileLoadResult(
|
|
||||||
result,
|
|
||||||
result.length < holidaySearchResult.files.length,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
|
||||||
removalEventTypes: const {
|
|
||||||
EventType.deletedFromRemote,
|
|
||||||
EventType.deletedFromEverywhere,
|
|
||||||
},
|
|
||||||
tagPrefix: tagPrefix,
|
|
||||||
selectedFiles: _selectedFiles,
|
|
||||||
initialFiles: [holidaySearchResult.files[0]],
|
|
||||||
);
|
|
||||||
return Scaffold(
|
|
||||||
appBar: PreferredSize(
|
|
||||||
preferredSize: const Size.fromHeight(50.0),
|
|
||||||
child: GalleryAppBarWidget(
|
|
||||||
appBarType,
|
|
||||||
holidaySearchResult.holidayName,
|
|
||||||
_selectedFiles,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: Stack(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
children: [
|
|
||||||
gallery,
|
|
||||||
GalleryOverlayWidget(
|
|
||||||
overlayType,
|
|
||||||
_selectedFiles,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:photos/core/event_bus.dart';
|
|
||||||
import 'package:photos/events/files_updated_event.dart';
|
|
||||||
import 'package:photos/events/local_photos_updated_event.dart';
|
|
||||||
import 'package:photos/models/file_load_result.dart';
|
|
||||||
import 'package:photos/models/gallery_type.dart';
|
|
||||||
import 'package:photos/models/search/year_search_result.dart';
|
|
||||||
import 'package:photos/models/selected_files.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_overlay_widget.dart';
|
|
||||||
|
|
||||||
class FilesFromYearPage extends StatelessWidget {
|
|
||||||
final YearSearchResult yearSearchResult;
|
|
||||||
final String tagPrefix;
|
|
||||||
|
|
||||||
final _selectedFiles = SelectedFiles();
|
|
||||||
static const GalleryType appBarType = GalleryType.searchResults;
|
|
||||||
static const GalleryType overlayType = GalleryType.searchResults;
|
|
||||||
|
|
||||||
FilesFromYearPage(
|
|
||||||
this.yearSearchResult,
|
|
||||||
this.tagPrefix, {
|
|
||||||
Key key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final gallery = Gallery(
|
|
||||||
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
|
|
||||||
final result = yearSearchResult.files
|
|
||||||
.where(
|
|
||||||
(file) =>
|
|
||||||
file.creationTime >= creationStartTime &&
|
|
||||||
file.creationTime <= creationEndTime,
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
return Future.value(
|
|
||||||
FileLoadResult(
|
|
||||||
result,
|
|
||||||
result.length < yearSearchResult.files.length,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
|
||||||
removalEventTypes: const {
|
|
||||||
EventType.deletedFromRemote,
|
|
||||||
EventType.deletedFromEverywhere,
|
|
||||||
},
|
|
||||||
tagPrefix: tagPrefix,
|
|
||||||
selectedFiles: _selectedFiles,
|
|
||||||
initialFiles: [yearSearchResult.files[0]],
|
|
||||||
);
|
|
||||||
return Scaffold(
|
|
||||||
appBar: PreferredSize(
|
|
||||||
preferredSize: const Size.fromHeight(50.0),
|
|
||||||
child: GalleryAppBarWidget(
|
|
||||||
appBarType,
|
|
||||||
yearSearchResult.year.toString(),
|
|
||||||
_selectedFiles,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: Stack(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
children: [
|
|
||||||
gallery,
|
|
||||||
GalleryOverlayWidget(
|
|
||||||
overlayType,
|
|
||||||
_selectedFiles,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:photos/core/event_bus.dart';
|
|
||||||
import 'package:photos/events/files_updated_event.dart';
|
|
||||||
import 'package:photos/events/local_photos_updated_event.dart';
|
|
||||||
import 'package:photos/models/file_load_result.dart';
|
|
||||||
import 'package:photos/models/gallery_type.dart';
|
|
||||||
import 'package:photos/models/search/location_search_result.dart';
|
|
||||||
import 'package:photos/models/selected_files.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart';
|
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_overlay_widget.dart';
|
|
||||||
|
|
||||||
class FilesInLocationPage extends StatelessWidget {
|
|
||||||
final LocationSearchResult locationSearchResult;
|
|
||||||
final String tagPrefix;
|
|
||||||
|
|
||||||
final _selectedFiles = SelectedFiles();
|
|
||||||
static const GalleryType appBarType = GalleryType.searchResults;
|
|
||||||
static const GalleryType overlayType = GalleryType.searchResults;
|
|
||||||
|
|
||||||
FilesInLocationPage(
|
|
||||||
this.locationSearchResult,
|
|
||||||
this.tagPrefix, {
|
|
||||||
Key key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final gallery = Gallery(
|
|
||||||
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
|
|
||||||
final result = locationSearchResult.files
|
|
||||||
.where(
|
|
||||||
(file) =>
|
|
||||||
file.creationTime >= creationStartTime &&
|
|
||||||
file.creationTime <= creationEndTime,
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
return Future.value(
|
|
||||||
FileLoadResult(
|
|
||||||
result,
|
|
||||||
result.length < locationSearchResult.files.length,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
|
||||||
removalEventTypes: const {
|
|
||||||
EventType.deletedFromRemote,
|
|
||||||
EventType.deletedFromEverywhere,
|
|
||||||
},
|
|
||||||
tagPrefix: tagPrefix,
|
|
||||||
selectedFiles: _selectedFiles,
|
|
||||||
initialFiles: [locationSearchResult.files[0]],
|
|
||||||
);
|
|
||||||
return Scaffold(
|
|
||||||
appBar: PreferredSize(
|
|
||||||
preferredSize: const Size.fromHeight(50.0),
|
|
||||||
child: GalleryAppBarWidget(
|
|
||||||
appBarType,
|
|
||||||
locationSearchResult.location,
|
|
||||||
_selectedFiles,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: Stack(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
children: [
|
|
||||||
gallery,
|
|
||||||
GalleryOverlayWidget(
|
|
||||||
overlayType,
|
|
||||||
_selectedFiles,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,11 +5,12 @@ import 'package:photos/ente_theme_data.dart';
|
||||||
import 'package:photos/models/file.dart';
|
import 'package:photos/models/file.dart';
|
||||||
import 'package:photos/models/search/file_search_result.dart';
|
import 'package:photos/models/search/file_search_result.dart';
|
||||||
import 'package:photos/ui/viewer/file/detail_page.dart';
|
import 'package:photos/ui/viewer/file/detail_page.dart';
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/search_result_thumbnail_widget.dart';
|
import 'package:photos/ui/viewer/search/result/search_thumbnail_widget.dart';
|
||||||
import 'package:photos/utils/navigation_util.dart';
|
import 'package:photos/utils/navigation_util.dart';
|
||||||
|
|
||||||
class FileSearchResultWidget extends StatelessWidget {
|
class FileSearchResultWidget extends StatelessWidget {
|
||||||
final FileSearchResult matchedFile;
|
final FileSearchResult matchedFile;
|
||||||
|
|
||||||
const FileSearchResultWidget(this.matchedFile, {Key key}) : super(key: key);
|
const FileSearchResultWidget(this.matchedFile, {Key key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -24,7 +25,7 @@ class FileSearchResultWidget extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
SearchResultThumbnailWidget(
|
SearchThumbnailWidget(
|
||||||
matchedFile.file,
|
matchedFile.file,
|
||||||
"file_details",
|
"file_details",
|
||||||
),
|
),
|
|
@ -4,33 +4,33 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:photos/core/event_bus.dart';
|
import 'package:photos/core/event_bus.dart';
|
||||||
import 'package:photos/events/files_updated_event.dart';
|
import 'package:photos/events/files_updated_event.dart';
|
||||||
import 'package:photos/events/local_photos_updated_event.dart';
|
import 'package:photos/events/local_photos_updated_event.dart';
|
||||||
|
import 'package:photos/models/file.dart';
|
||||||
import 'package:photos/models/file_load_result.dart';
|
import 'package:photos/models/file_load_result.dart';
|
||||||
import 'package:photos/models/gallery_type.dart';
|
import 'package:photos/models/gallery_type.dart';
|
||||||
import 'package:photos/models/search/month_search_result.dart';
|
import 'package:photos/models/search/search_result.dart';
|
||||||
import 'package:photos/models/selected_files.dart';
|
import 'package:photos/models/selected_files.dart';
|
||||||
import 'package:photos/ui/viewer/gallery/gallery.dart';
|
import 'package:photos/ui/viewer/gallery/gallery.dart';
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart';
|
import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart';
|
||||||
import 'package:photos/ui/viewer/gallery/gallery_overlay_widget.dart';
|
import 'package:photos/ui/viewer/gallery/gallery_overlay_widget.dart';
|
||||||
|
|
||||||
class FilesFromMonthPage extends StatelessWidget {
|
class SearchResultPage extends StatelessWidget {
|
||||||
final MonthSearchResult monthSearchResult;
|
final SearchResult searchResult;
|
||||||
final String tagPrefix;
|
|
||||||
|
|
||||||
final _selectedFiles = SelectedFiles();
|
final _selectedFiles = SelectedFiles();
|
||||||
static const GalleryType appBarType = GalleryType.searchResults;
|
static const GalleryType appBarType = GalleryType.searchResults;
|
||||||
static const GalleryType overlayType = GalleryType.searchResults;
|
static const GalleryType overlayType = GalleryType.searchResults;
|
||||||
|
|
||||||
FilesFromMonthPage(
|
SearchResultPage(
|
||||||
this.monthSearchResult,
|
this.searchResult, {
|
||||||
this.tagPrefix, {
|
|
||||||
Key key,
|
Key key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final List<File> files = searchResult.resultFiles();
|
||||||
final gallery = Gallery(
|
final gallery = Gallery(
|
||||||
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
|
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
|
||||||
final result = monthSearchResult.files
|
final result = files
|
||||||
.where(
|
.where(
|
||||||
(file) =>
|
(file) =>
|
||||||
file.creationTime >= creationStartTime &&
|
file.creationTime >= creationStartTime &&
|
||||||
|
@ -40,7 +40,7 @@ class FilesFromMonthPage extends StatelessWidget {
|
||||||
return Future.value(
|
return Future.value(
|
||||||
FileLoadResult(
|
FileLoadResult(
|
||||||
result,
|
result,
|
||||||
result.length < monthSearchResult.files.length,
|
result.length < files.length,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -49,16 +49,16 @@ class FilesFromMonthPage extends StatelessWidget {
|
||||||
EventType.deletedFromRemote,
|
EventType.deletedFromRemote,
|
||||||
EventType.deletedFromEverywhere,
|
EventType.deletedFromEverywhere,
|
||||||
},
|
},
|
||||||
tagPrefix: tagPrefix,
|
tagPrefix: searchResult.heroTag(),
|
||||||
selectedFiles: _selectedFiles,
|
selectedFiles: _selectedFiles,
|
||||||
initialFiles: [monthSearchResult.files[0]],
|
initialFiles: [searchResult.previewThumbnail()],
|
||||||
);
|
);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: PreferredSize(
|
appBar: PreferredSize(
|
||||||
preferredSize: const Size.fromHeight(50.0),
|
preferredSize: const Size.fromHeight(50.0),
|
||||||
child: GalleryAppBarWidget(
|
child: GalleryAppBarWidget(
|
||||||
appBarType,
|
appBarType,
|
||||||
monthSearchResult.month,
|
searchResult.name(),
|
||||||
_selectedFiles,
|
_selectedFiles,
|
||||||
),
|
),
|
||||||
),
|
),
|
|
@ -1,21 +1,26 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:photos/db/files_db.dart';
|
|
||||||
import 'package:photos/ente_theme_data.dart';
|
import 'package:photos/ente_theme_data.dart';
|
||||||
import 'package:photos/models/search/album_search_result.dart';
|
import 'package:photos/models/search/search_result.dart';
|
||||||
import 'package:photos/ui/viewer/gallery/collection_page.dart';
|
import 'package:photos/ui/viewer/search/result/search_result_page.dart';
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/search_result_thumbnail_widget.dart';
|
import 'package:photos/ui/viewer/search/result/search_thumbnail_widget.dart';
|
||||||
import 'package:photos/utils/navigation_util.dart';
|
import 'package:photos/utils/navigation_util.dart';
|
||||||
|
|
||||||
class AlbumSearchResultWidget extends StatelessWidget {
|
class SearchResultWidget extends StatelessWidget {
|
||||||
final AlbumSearchResult albumSearchResult;
|
final SearchResult searchResult;
|
||||||
|
final Future<int>? resultCount;
|
||||||
|
final Function? onResultTap;
|
||||||
|
|
||||||
const AlbumSearchResultWidget(this.albumSearchResult, {Key key})
|
const SearchResultWidget(
|
||||||
: super(key: key);
|
this.searchResult, {
|
||||||
|
Key? key,
|
||||||
|
this.resultCount,
|
||||||
|
this.onResultTap,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final heroTagPrefix = searchResult.heroTag();
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -23,19 +28,19 @@ class AlbumSearchResultWidget extends StatelessWidget {
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
SearchResultThumbnailWidget(
|
SearchThumbnailWidget(
|
||||||
albumSearchResult.collectionWithThumbnail.thumbnail,
|
searchResult.previewThumbnail(),
|
||||||
"collection_search",
|
heroTagPrefix,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Album',
|
_resultTypeName(searchResult.type()),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
color: Theme.of(context).colorScheme.subTextColor,
|
||||||
|
@ -45,18 +50,17 @@ class AlbumSearchResultWidget extends StatelessWidget {
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 220,
|
width: 220,
|
||||||
child: Text(
|
child: Text(
|
||||||
albumSearchResult.collectionWithThumbnail.collection.name,
|
searchResult.name(),
|
||||||
style: const TextStyle(fontSize: 18),
|
style: const TextStyle(fontSize: 18),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
FutureBuilder<int>(
|
FutureBuilder<int>(
|
||||||
future: FilesDB.instance.collectionFileCount(
|
future: resultCount ??
|
||||||
albumSearchResult.collectionWithThumbnail.collection.id,
|
Future.value(searchResult.resultFiles().length),
|
||||||
),
|
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data > 0) {
|
if (snapshot.hasData && snapshot.data! > 0) {
|
||||||
final noOfMemories = snapshot.data;
|
final noOfMemories = snapshot.data;
|
||||||
return RichText(
|
return RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
|
@ -78,7 +82,7 @@ class AlbumSearchResultWidget extends StatelessWidget {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
|
@ -91,14 +95,34 @@ class AlbumSearchResultWidget extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
routeToPage(
|
if (onResultTap != null) {
|
||||||
context,
|
onResultTap!();
|
||||||
CollectionPage(
|
} else {
|
||||||
albumSearchResult.collectionWithThumbnail,
|
routeToPage(
|
||||||
tagPrefix: "collection_search",
|
context,
|
||||||
),
|
SearchResultPage(searchResult),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _resultTypeName(ResultType type) {
|
||||||
|
switch (type) {
|
||||||
|
case ResultType.collection:
|
||||||
|
return "Album";
|
||||||
|
case ResultType.year:
|
||||||
|
return "Year";
|
||||||
|
case ResultType.month:
|
||||||
|
return "Month";
|
||||||
|
case ResultType.file:
|
||||||
|
return "Memory";
|
||||||
|
case ResultType.event:
|
||||||
|
return "Day";
|
||||||
|
case ResultType.location:
|
||||||
|
return "Day";
|
||||||
|
default:
|
||||||
|
return type.name.toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,11 +4,11 @@ import 'package:flutter/widgets.dart';
|
||||||
import 'package:photos/models/file.dart';
|
import 'package:photos/models/file.dart';
|
||||||
import 'package:photos/ui/viewer/file/thumbnail_widget.dart';
|
import 'package:photos/ui/viewer/file/thumbnail_widget.dart';
|
||||||
|
|
||||||
class SearchResultThumbnailWidget extends StatelessWidget {
|
class SearchThumbnailWidget extends StatelessWidget {
|
||||||
final File file;
|
final File file;
|
||||||
final String tagPrefix;
|
final String tagPrefix;
|
||||||
|
|
||||||
const SearchResultThumbnailWidget(
|
const SearchThumbnailWidget(
|
||||||
this.file,
|
this.file,
|
||||||
this.tagPrefix, {
|
this.tagPrefix, {
|
||||||
Key key,
|
Key key,
|
|
@ -1,91 +0,0 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:photos/ente_theme_data.dart';
|
|
||||||
import 'package:photos/models/search/holiday_search_result.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/collections/files_from_holiday_page.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/search_result_thumbnail_widget.dart';
|
|
||||||
import 'package:photos/utils/navigation_util.dart';
|
|
||||||
|
|
||||||
class HolidaySearchResultWidget extends StatelessWidget {
|
|
||||||
static const String _tagPrefix = "holiday_search";
|
|
||||||
|
|
||||||
final HolidaySearchResult holidaySearchResult;
|
|
||||||
const HolidaySearchResultWidget(this.holidaySearchResult, {Key key})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final noOfMemories = holidaySearchResult.files.length;
|
|
||||||
final heroTagPrefix = _tagPrefix + holidaySearchResult.holidayName;
|
|
||||||
|
|
||||||
return GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
child: Container(
|
|
||||||
color: Theme.of(context).colorScheme.searchResultsColor,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
SearchResultThumbnailWidget(
|
|
||||||
holidaySearchResult.files[0],
|
|
||||||
heroTagPrefix,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Date',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
SizedBox(
|
|
||||||
width: 220,
|
|
||||||
child: Text(
|
|
||||||
holidaySearchResult.holidayName,
|
|
||||||
style: const TextStyle(fontSize: 18),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.searchResultsCountTextColor,
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(text: noOfMemories.toString()),
|
|
||||||
TextSpan(
|
|
||||||
text: noOfMemories != 1 ? ' memories' : ' memory',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Icon(
|
|
||||||
Icons.chevron_right,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
routeToPage(
|
|
||||||
context,
|
|
||||||
FilesFromHolidayPage(holidaySearchResult, heroTagPrefix),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:photos/ente_theme_data.dart';
|
|
||||||
import 'package:photos/models/search/location_search_result.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/collections/files_in_location_page.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/search_result_thumbnail_widget.dart';
|
|
||||||
import 'package:photos/utils/navigation_util.dart';
|
|
||||||
|
|
||||||
class LocationSearchResultWidget extends StatelessWidget {
|
|
||||||
static const String _tagPrefix = "location_search";
|
|
||||||
|
|
||||||
final LocationSearchResult locationSearchResult;
|
|
||||||
const LocationSearchResultWidget(this.locationSearchResult, {Key key})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final noOfMemories = locationSearchResult.files.length;
|
|
||||||
final heroTagPrefix = _tagPrefix + locationSearchResult.location;
|
|
||||||
|
|
||||||
return GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
child: Container(
|
|
||||||
color: Theme.of(context).colorScheme.searchResultsColor,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
SearchResultThumbnailWidget(
|
|
||||||
locationSearchResult.files[0],
|
|
||||||
heroTagPrefix,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Location',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
SizedBox(
|
|
||||||
width: 220,
|
|
||||||
child: Text(
|
|
||||||
locationSearchResult.location,
|
|
||||||
style: const TextStyle(fontSize: 18),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.searchResultsCountTextColor,
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(text: noOfMemories.toString()),
|
|
||||||
TextSpan(
|
|
||||||
text: noOfMemories != 1 ? ' memories' : ' memory',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Icon(
|
|
||||||
Icons.chevron_right,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
routeToPage(
|
|
||||||
context,
|
|
||||||
FilesInLocationPage(locationSearchResult, heroTagPrefix),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:photos/ente_theme_data.dart';
|
|
||||||
import 'package:photos/models/search/month_search_result.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/collections/files_from_month_page.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/search_result_thumbnail_widget.dart';
|
|
||||||
import 'package:photos/utils/navigation_util.dart';
|
|
||||||
|
|
||||||
class MonthSearchResultWidget extends StatelessWidget {
|
|
||||||
static const String _tagPrefix = "month_search";
|
|
||||||
|
|
||||||
final MonthSearchResult monthSearchResult;
|
|
||||||
const MonthSearchResultWidget(this.monthSearchResult, {Key key})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final noOfMemories = monthSearchResult.files.length;
|
|
||||||
final heroTagPrefix = _tagPrefix + monthSearchResult.month;
|
|
||||||
|
|
||||||
return GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
child: Container(
|
|
||||||
color: Theme.of(context).colorScheme.searchResultsColor,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
SearchResultThumbnailWidget(
|
|
||||||
monthSearchResult.files[0],
|
|
||||||
heroTagPrefix,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Month',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
SizedBox(
|
|
||||||
width: 220,
|
|
||||||
child: Text(
|
|
||||||
monthSearchResult.month,
|
|
||||||
style: const TextStyle(fontSize: 18),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.searchResultsCountTextColor,
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(text: noOfMemories.toString()),
|
|
||||||
TextSpan(
|
|
||||||
text: noOfMemories != 1 ? ' memories' : ' memory',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Icon(
|
|
||||||
Icons.chevron_right,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
routeToPage(
|
|
||||||
context,
|
|
||||||
FilesFromMonthPage(monthSearchResult, heroTagPrefix),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
// @dart=2.9
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:photos/ente_theme_data.dart';
|
|
||||||
import 'package:photos/models/search/year_search_result.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/collections/files_from_year_page.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/search_result_thumbnail_widget.dart';
|
|
||||||
import 'package:photos/utils/navigation_util.dart';
|
|
||||||
|
|
||||||
class YearSearchResultWidget extends StatelessWidget {
|
|
||||||
static const String _tagPrefix = "year_search";
|
|
||||||
|
|
||||||
final YearSearchResult yearSearchResult;
|
|
||||||
const YearSearchResultWidget(this.yearSearchResult, {Key key})
|
|
||||||
: super(key: key);
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final noOfMemories = yearSearchResult.files.length;
|
|
||||||
final heroTagPrefix = _tagPrefix + yearSearchResult.year;
|
|
||||||
|
|
||||||
return GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
child: Container(
|
|
||||||
color: Theme.of(context).colorScheme.searchResultsColor,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
SearchResultThumbnailWidget(
|
|
||||||
yearSearchResult.files[0],
|
|
||||||
heroTagPrefix,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Year',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
Text(
|
|
||||||
yearSearchResult.year,
|
|
||||||
style: const TextStyle(fontSize: 18),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.searchResultsCountTextColor,
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(text: noOfMemories.toString()),
|
|
||||||
TextSpan(
|
|
||||||
text: noOfMemories != 1 ? ' memories' : ' memory',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Icon(
|
|
||||||
Icons.chevron_right,
|
|
||||||
color: Theme.of(context).colorScheme.subTextColor,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
routeToPage(
|
|
||||||
context,
|
|
||||||
FilesFromYearPage(yearSearchResult, heroTagPrefix),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,23 +2,20 @@
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:photos/db/files_db.dart';
|
||||||
import 'package:photos/ente_theme_data.dart';
|
import 'package:photos/ente_theme_data.dart';
|
||||||
import 'package:photos/models/search/album_search_result.dart';
|
import 'package:photos/models/search/album_search_result.dart';
|
||||||
import 'package:photos/models/search/file_search_result.dart';
|
import 'package:photos/models/search/file_search_result.dart';
|
||||||
import 'package:photos/models/search/holiday_search_result.dart';
|
import 'package:photos/models/search/generic_search_result.dart';
|
||||||
import 'package:photos/models/search/location_search_result.dart';
|
import 'package:photos/models/search/search_result.dart';
|
||||||
import 'package:photos/models/search/month_search_result.dart';
|
import 'package:photos/ui/viewer/gallery/collection_page.dart';
|
||||||
import 'package:photos/models/search/search_results.dart';
|
import 'package:photos/ui/viewer/search/result/file_result_widget.dart';
|
||||||
import 'package:photos/models/search/year_search_result.dart';
|
import 'package:photos/ui/viewer/search/result/search_result_widget.dart';
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/collection_result_widget.dart';
|
import 'package:photos/utils/navigation_util.dart';
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/file_result_widget.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/holiday_result_widget.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/location_result_widget.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/month_result_widget.dart';
|
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/year_result_widget.dart';
|
|
||||||
|
|
||||||
class SearchSuggestionsWidget extends StatelessWidget {
|
class SearchSuggestionsWidget extends StatelessWidget {
|
||||||
final List<SearchResult> results;
|
final List<SearchResult> results;
|
||||||
|
|
||||||
const SearchSuggestionsWidget(
|
const SearchSuggestionsWidget(
|
||||||
this.results, {
|
this.results, {
|
||||||
Key key,
|
Key key,
|
||||||
|
@ -62,17 +59,24 @@ class SearchSuggestionsWidget extends StatelessWidget {
|
||||||
}
|
}
|
||||||
final result = results[index];
|
final result = results[index];
|
||||||
if (result is AlbumSearchResult) {
|
if (result is AlbumSearchResult) {
|
||||||
return AlbumSearchResultWidget(result);
|
final AlbumSearchResult albumSearchResult = result;
|
||||||
} else if (result is LocationSearchResult) {
|
return SearchResultWidget(
|
||||||
return LocationSearchResultWidget(result);
|
result,
|
||||||
|
resultCount: FilesDB.instance.collectionFileCount(
|
||||||
|
albumSearchResult.collectionWithThumbnail.collection.id,
|
||||||
|
),
|
||||||
|
onResultTap: () => routeToPage(
|
||||||
|
context,
|
||||||
|
CollectionPage(
|
||||||
|
albumSearchResult.collectionWithThumbnail,
|
||||||
|
tagPrefix: result.heroTag(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
} else if (result is FileSearchResult) {
|
} else if (result is FileSearchResult) {
|
||||||
return FileSearchResultWidget(result);
|
return FileSearchResultWidget(result);
|
||||||
} else if (result is YearSearchResult) {
|
} else if (result is GenericSearchResult) {
|
||||||
return YearSearchResultWidget(result);
|
return SearchResultWidget(result);
|
||||||
} else if (result is HolidaySearchResult) {
|
|
||||||
return HolidaySearchResultWidget(result);
|
|
||||||
} else if (result is MonthSearchResult) {
|
|
||||||
return MonthSearchResultWidget(result);
|
|
||||||
} else {
|
} else {
|
||||||
Logger('SearchSuggestionsWidget')
|
Logger('SearchSuggestionsWidget')
|
||||||
.info("Invalid/Unsupported value");
|
.info("Invalid/Unsupported value");
|
||||||
|
|
|
@ -4,9 +4,9 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:photos/ente_theme_data.dart';
|
import 'package:photos/ente_theme_data.dart';
|
||||||
import 'package:photos/models/search/search_results.dart';
|
import 'package:photos/models/search/search_result.dart';
|
||||||
import 'package:photos/services/search_service.dart';
|
import 'package:photos/services/search_service.dart';
|
||||||
import 'package:photos/ui/viewer/search/search_result_widgets/no_result_widget.dart';
|
import 'package:photos/ui/viewer/search/result/no_result_widget.dart';
|
||||||
import 'package:photos/ui/viewer/search/search_suffix_icon_widget.dart';
|
import 'package:photos/ui/viewer/search/search_suffix_icon_widget.dart';
|
||||||
import 'package:photos/ui/viewer/search/search_suggestions.dart';
|
import 'package:photos/ui/viewer/search/search_suggestions.dart';
|
||||||
import 'package:photos/utils/date_time_util.dart';
|
import 'package:photos/utils/date_time_util.dart';
|
||||||
|
|
Loading…
Reference in a new issue