[mob][photos] Add option to sort by most recent and most relevant on magic results screen

This commit is contained in:
ashilkn
2024-09-11 18:54:36 +05:30
parent 83ffce2a24
commit 37022f7d7d
7 changed files with 214 additions and 16 deletions

View File

@@ -0,0 +1,11 @@
import "package:photos/events/event.dart";
enum MagicSortType {
mostRecent,
mostRelevant,
}
class MagicSortChangeEvent extends Event {
final MagicSortType sortType;
MagicSortChangeEvent(this.sortType);
}

View File

@@ -20,6 +20,7 @@ enum GalleryType {
quickLink,
peopleTag,
cluster,
magic,
}
extension GalleyTypeExtension on GalleryType {
@@ -36,6 +37,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.uncategorized:
case GalleryType.peopleTag:
case GalleryType.sharedCollection:
case GalleryType.magic:
return true;
case GalleryType.hiddenSection:
@@ -65,6 +67,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.sharedCollection:
case GalleryType.locationTag:
case GalleryType.cluster:
case GalleryType.magic:
return false;
}
}
@@ -83,6 +86,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.quickLink:
case GalleryType.peopleTag:
case GalleryType.cluster:
case GalleryType.magic:
return true;
case GalleryType.trash:
case GalleryType.archive:
@@ -107,6 +111,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.locationTag:
case GalleryType.quickLink:
case GalleryType.peopleTag:
case GalleryType.magic:
return true;
case GalleryType.trash:
case GalleryType.cluster:
@@ -126,6 +131,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.locationTag:
case GalleryType.peopleTag:
case GalleryType.cluster:
case GalleryType.magic:
return true;
case GalleryType.hiddenSection:
case GalleryType.hiddenOwnedCollection:
@@ -155,6 +161,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.cluster:
case GalleryType.trash:
case GalleryType.locationTag:
case GalleryType.magic:
return false;
}
}
@@ -178,6 +185,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.sharedCollection:
case GalleryType.locationTag:
case GalleryType.cluster:
case GalleryType.magic:
return false;
}
}
@@ -195,6 +203,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.uncategorized:
case GalleryType.locationTag:
case GalleryType.quickLink:
case GalleryType.magic:
return true;
case GalleryType.hiddenSection:
@@ -222,6 +231,7 @@ extension GalleyTypeExtension on GalleryType {
case GalleryType.uncategorized:
case GalleryType.locationTag:
case GalleryType.peopleTag:
case GalleryType.magic:
return true;
case GalleryType.hiddenSection:
@@ -353,6 +363,7 @@ extension GalleryAppBarExtn on GalleryType {
case GalleryType.localFolder:
case GalleryType.locationTag:
case GalleryType.searchResults:
case GalleryType.magic:
return false;
case GalleryType.cluster:
case GalleryType.uncategorized:

View File

@@ -11,6 +11,8 @@ import "package:photos/models/search/search_types.dart";
import "package:photos/service_locator.dart";
import "package:photos/services/machine_learning/semantic_search/semantic_search_service.dart";
import "package:photos/services/remote_assets_service.dart";
import "package:photos/ui/viewer/search/result/magic_result_screen.dart";
import "package:photos/utils/navigation_util.dart";
import "package:shared_preferences/shared_preferences.dart";
class MagicCache {
@@ -59,6 +61,15 @@ extension MagicCacheServiceExtension on MagicCache {
ResultType.magic,
title,
enteFilesInMagicCache,
onResultTap: (ctx) {
routeToPage(
ctx,
MagicResultScreen(
enteFilesInMagicCache,
name: title,
),
);
},
);
}
}

View File

@@ -10,6 +10,7 @@ import 'package:photos/core/configuration.dart';
import 'package:photos/core/event_bus.dart';
import "package:photos/core/network/network.dart";
import "package:photos/db/files_db.dart";
import "package:photos/events/magic_sort_change_event.dart";
import 'package:photos/events/subscription_purchased_event.dart';
import "package:photos/gateways/cast_gw.dart";
import "package:photos/generated/l10n.dart";
@@ -58,11 +59,11 @@ class GalleryAppBarWidget extends StatefulWidget {
this.type,
this.title,
this.selectedFiles, {
Key? key,
super.key,
this.deviceCollection,
this.collection,
this.isFromCollectPhotos = false,
}) : super(key: key);
});
@override
State<GalleryAppBarWidget> createState() => _GalleryAppBarWidgetState();
@@ -84,6 +85,8 @@ enum AlbumPopupAction {
pinAlbum,
removeLink,
cleanUncategorized,
sortByMostRecent,
sortByMostRelevant
}
class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
@@ -293,6 +296,39 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
!Configuration.instance.hasConfiguredAccount()) {
return actions;
}
if (galleryType == GalleryType.magic) {
actions.add(
Tooltip(
message: "Sort",
child: PopupMenuButton(
icon: const Icon(Icons.sort_rounded),
itemBuilder: (context) {
return const [
PopupMenuItem(
value: AlbumPopupAction.sortByMostRecent,
child: Text("Most recent"),
),
PopupMenuItem(
value: AlbumPopupAction.sortByMostRelevant,
child: Text("Most relevant"),
),
];
},
onSelected: (AlbumPopupAction value) {
if (value == AlbumPopupAction.sortByMostRecent) {
Bus.instance
.fire(MagicSortChangeEvent(MagicSortType.mostRecent));
} else if (value == AlbumPopupAction.sortByMostRelevant) {
Bus.instance
.fire(MagicSortChangeEvent(MagicSortType.mostRelevant));
}
},
),
),
);
}
final int userID = Configuration.instance.getUserID()!;
isQuickLink = widget.collection?.isQuickLinkCollection() ?? false;
if (galleryType.canAddFiles(widget.collection, userID)) {

View File

@@ -0,0 +1,141 @@
import "dart:async";
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/events/magic_sort_change_event.dart";
import 'package:photos/models/file/file.dart';
import 'package:photos/models/file_load_result.dart';
import 'package:photos/models/gallery_type.dart';
import 'package:photos/models/selected_files.dart';
import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.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/state/selection_state.dart";
class MagicResultScreen extends StatefulWidget {
final List<EnteFile> files;
final String name;
final bool enableGrouping;
static const GalleryType appBarType = GalleryType.magic;
static const GalleryType overlayType = GalleryType.magic;
const MagicResultScreen(
this.files, {
required this.name,
this.enableGrouping = true,
super.key,
});
@override
State<MagicResultScreen> createState() => _MagicResultScreenState();
}
class _MagicResultScreenState extends State<MagicResultScreen> {
final _selectedFiles = SelectedFiles();
late final List<EnteFile> files;
late final StreamSubscription<LocalPhotosUpdatedEvent> _filesUpdatedEvent;
late final StreamSubscription<MagicSortChangeEvent> _magicSortChangeEvent;
late bool _enableGrouping;
@override
void initState() {
super.initState();
_enableGrouping = widget.enableGrouping;
files = widget.files;
_filesUpdatedEvent =
Bus.instance.on<LocalPhotosUpdatedEvent>().listen((event) {
if (event.type == EventType.deletedFromDevice ||
event.type == EventType.deletedFromEverywhere ||
event.type == EventType.deletedFromRemote ||
event.type == EventType.hide) {
for (var updatedFile in event.updatedFiles) {
files.remove(updatedFile);
}
setState(() {});
}
});
_magicSortChangeEvent =
Bus.instance.on<MagicSortChangeEvent>().listen((event) {
if (event.sortType == MagicSortType.mostRelevant) {
setState(() {
_enableGrouping = false;
});
} else if (event.sortType == MagicSortType.mostRecent) {
setState(() {
_enableGrouping = true;
});
}
});
}
@override
void dispose() {
_filesUpdatedEvent.cancel();
_magicSortChangeEvent.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final gallery = Gallery(
key: ValueKey(_enableGrouping),
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
final result = files
.where(
(file) =>
file.creationTime! >= creationStartTime &&
file.creationTime! <= creationEndTime,
)
.toList();
return Future.value(
FileLoadResult(
result,
result.length < files.length,
),
);
},
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
removalEventTypes: const {
EventType.deletedFromRemote,
EventType.deletedFromEverywhere,
EventType.hide,
},
tagPrefix: "",
selectedFiles: _selectedFiles,
enableFileGrouping: _enableGrouping,
initialFiles: [files.first],
);
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(50.0),
child: GalleryAppBarWidget(
MagicResultScreen.appBarType,
widget.name,
_selectedFiles,
),
),
body: SelectionState(
selectedFiles: _selectedFiles,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 250),
switchInCurve: Curves.easeInOutQuad,
switchOutCurve: Curves.easeInOutQuad,
child: gallery,
),
FileSelectionOverlayBar(
MagicResultScreen.overlayType,
_selectedFiles,
),
],
),
),
);
}
}

View File

@@ -110,7 +110,6 @@ class SearchResultWidget extends StatelessWidget {
context,
SearchResultPage(
searchResult,
enableGrouping: searchResult.type() != ResultType.magic,
),
);
}

View File

@@ -11,9 +11,7 @@ import "package:photos/models/search/search_types.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/viewer/file/no_thumbnail_widget.dart";
import "package:photos/ui/viewer/file/thumbnail_widget.dart";
import "package:photos/ui/viewer/search/result/search_result_page.dart";
import "package:photos/ui/viewer/search_tab/section_header.dart";
import "package:photos/utils/navigation_util.dart";
class MagicSection extends StatefulWidget {
final List<GenericSearchResult> magicSearchResults;
@@ -149,17 +147,8 @@ class MagicRecommendation extends StatelessWidget {
child: GestureDetector(
onTap: () {
RecentSearches().add(magicSearchResult.name());
if (magicSearchResult.onResultTap != null) {
magicSearchResult.onResultTap!(context);
} else {
routeToPage(
context,
SearchResultPage(
magicSearchResult,
enableGrouping: false,
),
);
}
magicSearchResult.onResultTap!(context);
},
child: SizedBox(
width: _width + _borderWidth * 2,