mirror of
https://github.com/ente-io/ente.git
synced 2025-08-08 23:39:30 +00:00
[mob][photos] Make filters useable (make them appear on appbar) in named people page
This commit is contained in:
parent
fd9269ccdf
commit
c8990d8f40
@ -951,6 +951,23 @@ class SearchService {
|
|||||||
PeoplePage(
|
PeoplePage(
|
||||||
tagPrefix: "${ResultType.faces.toString()}_${p.data.name}",
|
tagPrefix: "${ResultType.faces.toString()}_${p.data.name}",
|
||||||
person: p,
|
person: p,
|
||||||
|
searchResult: GenericSearchResult(
|
||||||
|
ResultType.faces,
|
||||||
|
p.data.name,
|
||||||
|
files,
|
||||||
|
params: {
|
||||||
|
kPersonParamID: personID,
|
||||||
|
kFileID: files.first.uploadedFileID,
|
||||||
|
},
|
||||||
|
hierarchicalSearchFilter: FaceFilter(
|
||||||
|
personId: p.remoteID,
|
||||||
|
clusterId: null,
|
||||||
|
faceName: p.data.name,
|
||||||
|
faceFile: files.first,
|
||||||
|
occurrence: kMostRelevantFilter,
|
||||||
|
matchedUploadedIDs: filesToUploadedFileIDs(files),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -119,6 +119,7 @@ class _FaceWidgetState extends State<FaceWidget> {
|
|||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => PeoplePage(
|
builder: (context) => PeoplePage(
|
||||||
person: widget.person!,
|
person: widget.person!,
|
||||||
|
searchResult: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -8,6 +8,7 @@ class InheritedSearchFilterData extends InheritedWidget {
|
|||||||
required super.child,
|
required super.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Pass null if gallery doesn't need hierarchical search
|
||||||
final SearchFilterDataProvider? searchFilterDataProvider;
|
final SearchFilterDataProvider? searchFilterDataProvider;
|
||||||
|
|
||||||
bool get isHierarchicalSearchable => searchFilterDataProvider != null;
|
bool get isHierarchicalSearchable => searchFilterDataProvider != null;
|
||||||
|
@ -200,13 +200,22 @@ class _ClusterPageState extends State<ClusterPage> {
|
|||||||
// ignore: unawaited_futures
|
// ignore: unawaited_futures
|
||||||
routeToPage(
|
routeToPage(
|
||||||
context,
|
context,
|
||||||
PeoplePage(person: result.$1),
|
PeoplePage(
|
||||||
|
person: result.$1,
|
||||||
|
searchResult: null,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else if (result != null &&
|
} else if (result != null &&
|
||||||
result is PersonEntity) {
|
result is PersonEntity) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
// ignore: unawaited_futures
|
// ignore: unawaited_futures
|
||||||
routeToPage(context, PeoplePage(person: result));
|
routeToPage(
|
||||||
|
context,
|
||||||
|
PeoplePage(
|
||||||
|
person: result,
|
||||||
|
searchResult: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showShortToast(context, "No personID or clusterID");
|
showShortToast(context, "No personID or clusterID");
|
||||||
|
@ -15,6 +15,8 @@ import 'package:photos/models/selected_files.dart';
|
|||||||
import 'package:photos/services/collections_service.dart';
|
import 'package:photos/services/collections_service.dart';
|
||||||
import "package:photos/services/machine_learning/face_ml/person/person_service.dart";
|
import "package:photos/services/machine_learning/face_ml/person/person_service.dart";
|
||||||
import 'package:photos/ui/actions/collection/collection_sharing_actions.dart';
|
import 'package:photos/ui/actions/collection/collection_sharing_actions.dart';
|
||||||
|
import "package:photos/ui/viewer/hierarchicial_search/applied_filters.dart";
|
||||||
|
import "package:photos/ui/viewer/hierarchicial_search/recommended_filters.dart";
|
||||||
import "package:photos/ui/viewer/people/add_person_action_sheet.dart";
|
import "package:photos/ui/viewer/people/add_person_action_sheet.dart";
|
||||||
import "package:photos/ui/viewer/people/people_page.dart";
|
import "package:photos/ui/viewer/people/people_page.dart";
|
||||||
import "package:photos/ui/viewer/people/person_cluster_suggestion.dart";
|
import "package:photos/ui/viewer/people/person_cluster_suggestion.dart";
|
||||||
@ -34,8 +36,8 @@ class PeopleAppBar extends StatefulWidget {
|
|||||||
this.title,
|
this.title,
|
||||||
this.selectedFiles,
|
this.selectedFiles,
|
||||||
this.person, {
|
this.person, {
|
||||||
Key? key,
|
super.key,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PeopleAppBar> createState() => _AppBarWidgetState();
|
State<PeopleAppBar> createState() => _AppBarWidgetState();
|
||||||
@ -87,12 +89,39 @@ class _AppBarWidgetState extends State<PeopleAppBar> {
|
|||||||
return AppBar(
|
return AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: Text(
|
// title: Text(
|
||||||
_appBarTitle!,
|
// _appBarTitle!,
|
||||||
style:
|
// style:
|
||||||
Theme.of(context).textTheme.headlineSmall!.copyWith(fontSize: 16),
|
// Theme.of(context).textTheme.headlineSmall!.copyWith(fontSize: 16),
|
||||||
maxLines: 2,
|
// maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
// overflow: TextOverflow.ellipsis,
|
||||||
|
// ),
|
||||||
|
title: Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
_appBarTitle!,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.headlineSmall!
|
||||||
|
.copyWith(fontSize: 16),
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 200,
|
||||||
|
height: 50,
|
||||||
|
child: AppliedFilters(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
bottom: const PreferredSize(
|
||||||
|
preferredSize: Size.fromHeight(0),
|
||||||
|
child: Flexible(child: RecommendedFilters()),
|
||||||
),
|
),
|
||||||
actions: _getDefaultActions(context),
|
actions: _getDefaultActions(context),
|
||||||
);
|
);
|
||||||
@ -294,10 +323,22 @@ class _AppBarWidgetState extends State<PeopleAppBar> {
|
|||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
if (result != null && result is (PersonEntity, EnteFile)) {
|
if (result != null && result is (PersonEntity, EnteFile)) {
|
||||||
// ignore: unawaited_futures
|
// ignore: unawaited_futures
|
||||||
routeToPage(context, PeoplePage(person: result.$1));
|
routeToPage(
|
||||||
|
context,
|
||||||
|
PeoplePage(
|
||||||
|
person: result.$1,
|
||||||
|
searchResult: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
} else if (result != null && result is PersonEntity) {
|
} else if (result != null && result is PersonEntity) {
|
||||||
// ignore: unawaited_futures
|
// ignore: unawaited_futures
|
||||||
routeToPage(context, PeoplePage(person: result));
|
routeToPage(
|
||||||
|
context,
|
||||||
|
PeoplePage(
|
||||||
|
person: result,
|
||||||
|
searchResult: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import 'package:photos/models/file/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/ml/face/person.dart";
|
import "package:photos/models/ml/face/person.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/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart";
|
import "package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart";
|
||||||
import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart";
|
import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart";
|
||||||
@ -18,6 +19,8 @@ import "package:photos/services/search_service.dart";
|
|||||||
import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.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.dart';
|
||||||
import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart";
|
import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart";
|
||||||
|
import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart";
|
||||||
|
import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart";
|
||||||
import "package:photos/ui/viewer/gallery/state/selection_state.dart";
|
import "package:photos/ui/viewer/gallery/state/selection_state.dart";
|
||||||
import "package:photos/ui/viewer/people/people_app_bar.dart";
|
import "package:photos/ui/viewer/people/people_app_bar.dart";
|
||||||
import "package:photos/ui/viewer/people/people_banner.dart";
|
import "package:photos/ui/viewer/people/people_banner.dart";
|
||||||
@ -26,6 +29,7 @@ import "package:photos/ui/viewer/people/person_cluster_suggestion.dart";
|
|||||||
class PeoplePage extends StatefulWidget {
|
class PeoplePage extends StatefulWidget {
|
||||||
final String tagPrefix;
|
final String tagPrefix;
|
||||||
final PersonEntity person;
|
final PersonEntity person;
|
||||||
|
final SearchResult? searchResult;
|
||||||
|
|
||||||
static const GalleryType appBarType = GalleryType.peopleTag;
|
static const GalleryType appBarType = GalleryType.peopleTag;
|
||||||
static const GalleryType overlayType = GalleryType.peopleTag;
|
static const GalleryType overlayType = GalleryType.peopleTag;
|
||||||
@ -33,8 +37,9 @@ class PeoplePage extends StatefulWidget {
|
|||||||
const PeoplePage({
|
const PeoplePage({
|
||||||
this.tagPrefix = "",
|
this.tagPrefix = "",
|
||||||
required this.person,
|
required this.person,
|
||||||
Key? key,
|
required this.searchResult,
|
||||||
}) : super(key: key);
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PeoplePage> createState() => _PeoplePageState();
|
State<PeoplePage> createState() => _PeoplePageState();
|
||||||
@ -112,111 +117,119 @@ class _PeoplePageState extends State<PeoplePage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_logger.info("Building for ${widget.person.data.name}");
|
_logger.info("Building for ${widget.person.data.name}");
|
||||||
return GalleryFilesState(
|
return GalleryFilesState(
|
||||||
child: Scaffold(
|
child: InheritedSearchFilterData(
|
||||||
appBar: PreferredSize(
|
searchFilterDataProvider: widget.searchResult != null
|
||||||
preferredSize: const Size.fromHeight(50.0),
|
? SearchFilterDataProvider(
|
||||||
child: PeopleAppBar(
|
initialGalleryFilter:
|
||||||
GalleryType.peopleTag,
|
widget.searchResult!.getHierarchicalSearchFilter(),
|
||||||
widget.person.data.name,
|
)
|
||||||
_selectedFiles,
|
: null,
|
||||||
widget.person,
|
child: Scaffold(
|
||||||
|
appBar: PreferredSize(
|
||||||
|
preferredSize: const Size.fromHeight(50.0),
|
||||||
|
child: PeopleAppBar(
|
||||||
|
GalleryType.peopleTag,
|
||||||
|
widget.person.data.name,
|
||||||
|
_selectedFiles,
|
||||||
|
widget.person,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
body: FutureBuilder<List<EnteFile>>(
|
||||||
body: FutureBuilder<List<EnteFile>>(
|
future: filesFuture,
|
||||||
future: filesFuture,
|
builder: (context, snapshot) {
|
||||||
builder: (context, snapshot) {
|
if (snapshot.hasData) {
|
||||||
if (snapshot.hasData) {
|
final personFiles = snapshot.data as List<EnteFile>;
|
||||||
final personFiles = snapshot.data as List<EnteFile>;
|
return Column(
|
||||||
return Column(
|
children: [
|
||||||
children: [
|
Expanded(
|
||||||
Expanded(
|
child: SelectionState(
|
||||||
child: SelectionState(
|
selectedFiles: _selectedFiles,
|
||||||
selectedFiles: _selectedFiles,
|
child: Stack(
|
||||||
child: Stack(
|
alignment: Alignment.bottomCenter,
|
||||||
alignment: Alignment.bottomCenter,
|
children: [
|
||||||
children: [
|
Gallery(
|
||||||
Gallery(
|
asyncLoader: (
|
||||||
asyncLoader: (
|
creationStartTime,
|
||||||
creationStartTime,
|
creationEndTime, {
|
||||||
creationEndTime, {
|
limit,
|
||||||
limit,
|
asc,
|
||||||
asc,
|
}) async {
|
||||||
}) async {
|
final result = await loadPersonFiles();
|
||||||
final result = await loadPersonFiles();
|
return Future.value(
|
||||||
return Future.value(
|
FileLoadResult(
|
||||||
FileLoadResult(
|
result,
|
||||||
result,
|
false,
|
||||||
false,
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
reloadEvent:
|
||||||
reloadEvent:
|
Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
||||||
Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
forceReloadEvents: [
|
||||||
forceReloadEvents: [
|
Bus.instance.on<PeopleChangedEvent>(),
|
||||||
Bus.instance.on<PeopleChangedEvent>(),
|
],
|
||||||
],
|
removalEventTypes: const {
|
||||||
removalEventTypes: const {
|
EventType.deletedFromRemote,
|
||||||
EventType.deletedFromRemote,
|
EventType.deletedFromEverywhere,
|
||||||
EventType.deletedFromEverywhere,
|
EventType.hide,
|
||||||
EventType.hide,
|
},
|
||||||
},
|
tagPrefix: widget.tagPrefix + widget.tagPrefix,
|
||||||
tagPrefix: widget.tagPrefix + widget.tagPrefix,
|
selectedFiles: _selectedFiles,
|
||||||
selectedFiles: _selectedFiles,
|
initialFiles: personFiles.isNotEmpty
|
||||||
initialFiles: personFiles.isNotEmpty
|
? [personFiles.first]
|
||||||
? [personFiles.first]
|
: [],
|
||||||
: [],
|
),
|
||||||
),
|
FileSelectionOverlayBar(
|
||||||
FileSelectionOverlayBar(
|
PeoplePage.overlayType,
|
||||||
PeoplePage.overlayType,
|
_selectedFiles,
|
||||||
_selectedFiles,
|
person: widget.person,
|
||||||
person: widget.person,
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
showSuggestionBanner
|
||||||
showSuggestionBanner
|
? Dismissible(
|
||||||
? Dismissible(
|
key: const Key("suggestionBanner"),
|
||||||
key: const Key("suggestionBanner"),
|
direction: DismissDirection.horizontal,
|
||||||
direction: DismissDirection.horizontal,
|
onDismissed: (direction) {
|
||||||
onDismissed: (direction) {
|
setState(() {
|
||||||
setState(() {
|
userDismissedSuggestionBanner = true;
|
||||||
userDismissedSuggestionBanner = true;
|
});
|
||||||
});
|
},
|
||||||
},
|
child: PeopleBanner(
|
||||||
child: PeopleBanner(
|
type: PeopleBannerType.suggestion,
|
||||||
type: PeopleBannerType.suggestion,
|
startIcon: Icons.face_retouching_natural,
|
||||||
startIcon: Icons.face_retouching_natural,
|
actionIcon: Icons.search_outlined,
|
||||||
actionIcon: Icons.search_outlined,
|
text: "Review suggestions",
|
||||||
text: "Review suggestions",
|
subText: "Improve the results",
|
||||||
subText: "Improve the results",
|
onTap: () async {
|
||||||
onTap: () async {
|
unawaited(
|
||||||
unawaited(
|
Navigator.of(context).push(
|
||||||
Navigator.of(context).push(
|
MaterialPageRoute(
|
||||||
MaterialPageRoute(
|
builder: (context) =>
|
||||||
builder: (context) =>
|
PersonReviewClusterSuggestion(
|
||||||
PersonReviewClusterSuggestion(
|
widget.person,
|
||||||
widget.person,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
)
|
||||||
)
|
: const SizedBox.shrink(),
|
||||||
: const SizedBox.shrink(),
|
],
|
||||||
],
|
);
|
||||||
);
|
} else if (snapshot.hasError) {
|
||||||
} else if (snapshot.hasError) {
|
log("Error: ${snapshot.error} ${snapshot.stackTrace}}");
|
||||||
log("Error: ${snapshot.error} ${snapshot.stackTrace}}");
|
//Need to show an error on the UI here
|
||||||
//Need to show an error on the UI here
|
return const SizedBox.shrink();
|
||||||
return const SizedBox.shrink();
|
} else {
|
||||||
} else {
|
return const Center(
|
||||||
return const Center(
|
child: CircularProgressIndicator(),
|
||||||
child: CircularProgressIndicator(),
|
);
|
||||||
);
|
}
|
||||||
}
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -265,10 +265,22 @@ class SearchExample extends StatelessWidget {
|
|||||||
if (result != null &&
|
if (result != null &&
|
||||||
result is (PersonEntity, EnteFile)) {
|
result is (PersonEntity, EnteFile)) {
|
||||||
// ignore: unawaited_futures
|
// ignore: unawaited_futures
|
||||||
routeToPage(context, PeoplePage(person: result.$1));
|
routeToPage(
|
||||||
|
context,
|
||||||
|
PeoplePage(
|
||||||
|
person: result.$1,
|
||||||
|
searchResult: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
} else if (result != null && result is PersonEntity) {
|
} else if (result != null && result is PersonEntity) {
|
||||||
// ignore: unawaited_futures
|
// ignore: unawaited_futures
|
||||||
routeToPage(context, PeoplePage(person: result));
|
routeToPage(
|
||||||
|
context,
|
||||||
|
PeoplePage(
|
||||||
|
person: result,
|
||||||
|
searchResult: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user