mirror of
https://github.com/ente-io/ente.git
synced 2025-08-08 07:28:26 +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(
|
||||
tagPrefix: "${ResultType.faces.toString()}_${p.data.name}",
|
||||
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(
|
||||
builder: (context) => PeoplePage(
|
||||
person: widget.person!,
|
||||
searchResult: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -8,6 +8,7 @@ class InheritedSearchFilterData extends InheritedWidget {
|
||||
required super.child,
|
||||
});
|
||||
|
||||
/// Pass null if gallery doesn't need hierarchical search
|
||||
final SearchFilterDataProvider? searchFilterDataProvider;
|
||||
|
||||
bool get isHierarchicalSearchable => searchFilterDataProvider != null;
|
||||
|
@ -200,13 +200,22 @@ class _ClusterPageState extends State<ClusterPage> {
|
||||
// ignore: unawaited_futures
|
||||
routeToPage(
|
||||
context,
|
||||
PeoplePage(person: result.$1),
|
||||
PeoplePage(
|
||||
person: result.$1,
|
||||
searchResult: null,
|
||||
),
|
||||
);
|
||||
} else if (result != null &&
|
||||
result is PersonEntity) {
|
||||
Navigator.pop(context);
|
||||
// ignore: unawaited_futures
|
||||
routeToPage(context, PeoplePage(person: result));
|
||||
routeToPage(
|
||||
context,
|
||||
PeoplePage(
|
||||
person: result,
|
||||
searchResult: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
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/machine_learning/face_ml/person/person_service.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/people_page.dart";
|
||||
import "package:photos/ui/viewer/people/person_cluster_suggestion.dart";
|
||||
@ -34,8 +36,8 @@ class PeopleAppBar extends StatefulWidget {
|
||||
this.title,
|
||||
this.selectedFiles,
|
||||
this.person, {
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PeopleAppBar> createState() => _AppBarWidgetState();
|
||||
@ -87,12 +89,39 @@ class _AppBarWidgetState extends State<PeopleAppBar> {
|
||||
return AppBar(
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
title: Text(
|
||||
_appBarTitle!,
|
||||
style:
|
||||
Theme.of(context).textTheme.headlineSmall!.copyWith(fontSize: 16),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
// title: Text(
|
||||
// _appBarTitle!,
|
||||
// style:
|
||||
// Theme.of(context).textTheme.headlineSmall!.copyWith(fontSize: 16),
|
||||
// maxLines: 2,
|
||||
// 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),
|
||||
);
|
||||
@ -294,10 +323,22 @@ class _AppBarWidgetState extends State<PeopleAppBar> {
|
||||
Navigator.pop(context);
|
||||
if (result != null && result is (PersonEntity, EnteFile)) {
|
||||
// ignore: unawaited_futures
|
||||
routeToPage(context, PeoplePage(person: result.$1));
|
||||
routeToPage(
|
||||
context,
|
||||
PeoplePage(
|
||||
person: result.$1,
|
||||
searchResult: null,
|
||||
),
|
||||
);
|
||||
} else if (result != null && result is PersonEntity) {
|
||||
// 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/gallery_type.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/services/machine_learning/face_ml/face_filtering/face_filtering_constants.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/gallery/gallery.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/people/people_app_bar.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 {
|
||||
final String tagPrefix;
|
||||
final PersonEntity person;
|
||||
final SearchResult? searchResult;
|
||||
|
||||
static const GalleryType appBarType = GalleryType.peopleTag;
|
||||
static const GalleryType overlayType = GalleryType.peopleTag;
|
||||
@ -33,8 +37,9 @@ class PeoplePage extends StatefulWidget {
|
||||
const PeoplePage({
|
||||
this.tagPrefix = "",
|
||||
required this.person,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
required this.searchResult,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PeoplePage> createState() => _PeoplePageState();
|
||||
@ -112,111 +117,119 @@ class _PeoplePageState extends State<PeoplePage> {
|
||||
Widget build(BuildContext context) {
|
||||
_logger.info("Building for ${widget.person.data.name}");
|
||||
return GalleryFilesState(
|
||||
child: Scaffold(
|
||||
appBar: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(50.0),
|
||||
child: PeopleAppBar(
|
||||
GalleryType.peopleTag,
|
||||
widget.person.data.name,
|
||||
_selectedFiles,
|
||||
widget.person,
|
||||
child: InheritedSearchFilterData(
|
||||
searchFilterDataProvider: widget.searchResult != null
|
||||
? SearchFilterDataProvider(
|
||||
initialGalleryFilter:
|
||||
widget.searchResult!.getHierarchicalSearchFilter(),
|
||||
)
|
||||
: null,
|
||||
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>>(
|
||||
future: filesFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final personFiles = snapshot.data as List<EnteFile>;
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SelectionState(
|
||||
selectedFiles: _selectedFiles,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
Gallery(
|
||||
asyncLoader: (
|
||||
creationStartTime,
|
||||
creationEndTime, {
|
||||
limit,
|
||||
asc,
|
||||
}) async {
|
||||
final result = await loadPersonFiles();
|
||||
return Future.value(
|
||||
FileLoadResult(
|
||||
result,
|
||||
false,
|
||||
),
|
||||
);
|
||||
},
|
||||
reloadEvent:
|
||||
Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
||||
forceReloadEvents: [
|
||||
Bus.instance.on<PeopleChangedEvent>(),
|
||||
],
|
||||
removalEventTypes: const {
|
||||
EventType.deletedFromRemote,
|
||||
EventType.deletedFromEverywhere,
|
||||
EventType.hide,
|
||||
},
|
||||
tagPrefix: widget.tagPrefix + widget.tagPrefix,
|
||||
selectedFiles: _selectedFiles,
|
||||
initialFiles: personFiles.isNotEmpty
|
||||
? [personFiles.first]
|
||||
: [],
|
||||
),
|
||||
FileSelectionOverlayBar(
|
||||
PeoplePage.overlayType,
|
||||
_selectedFiles,
|
||||
person: widget.person,
|
||||
),
|
||||
],
|
||||
body: FutureBuilder<List<EnteFile>>(
|
||||
future: filesFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final personFiles = snapshot.data as List<EnteFile>;
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SelectionState(
|
||||
selectedFiles: _selectedFiles,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
Gallery(
|
||||
asyncLoader: (
|
||||
creationStartTime,
|
||||
creationEndTime, {
|
||||
limit,
|
||||
asc,
|
||||
}) async {
|
||||
final result = await loadPersonFiles();
|
||||
return Future.value(
|
||||
FileLoadResult(
|
||||
result,
|
||||
false,
|
||||
),
|
||||
);
|
||||
},
|
||||
reloadEvent:
|
||||
Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
||||
forceReloadEvents: [
|
||||
Bus.instance.on<PeopleChangedEvent>(),
|
||||
],
|
||||
removalEventTypes: const {
|
||||
EventType.deletedFromRemote,
|
||||
EventType.deletedFromEverywhere,
|
||||
EventType.hide,
|
||||
},
|
||||
tagPrefix: widget.tagPrefix + widget.tagPrefix,
|
||||
selectedFiles: _selectedFiles,
|
||||
initialFiles: personFiles.isNotEmpty
|
||||
? [personFiles.first]
|
||||
: [],
|
||||
),
|
||||
FileSelectionOverlayBar(
|
||||
PeoplePage.overlayType,
|
||||
_selectedFiles,
|
||||
person: widget.person,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
showSuggestionBanner
|
||||
? Dismissible(
|
||||
key: const Key("suggestionBanner"),
|
||||
direction: DismissDirection.horizontal,
|
||||
onDismissed: (direction) {
|
||||
setState(() {
|
||||
userDismissedSuggestionBanner = true;
|
||||
});
|
||||
},
|
||||
child: PeopleBanner(
|
||||
type: PeopleBannerType.suggestion,
|
||||
startIcon: Icons.face_retouching_natural,
|
||||
actionIcon: Icons.search_outlined,
|
||||
text: "Review suggestions",
|
||||
subText: "Improve the results",
|
||||
onTap: () async {
|
||||
unawaited(
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
PersonReviewClusterSuggestion(
|
||||
widget.person,
|
||||
showSuggestionBanner
|
||||
? Dismissible(
|
||||
key: const Key("suggestionBanner"),
|
||||
direction: DismissDirection.horizontal,
|
||||
onDismissed: (direction) {
|
||||
setState(() {
|
||||
userDismissedSuggestionBanner = true;
|
||||
});
|
||||
},
|
||||
child: PeopleBanner(
|
||||
type: PeopleBannerType.suggestion,
|
||||
startIcon: Icons.face_retouching_natural,
|
||||
actionIcon: Icons.search_outlined,
|
||||
text: "Review suggestions",
|
||||
subText: "Improve the results",
|
||||
onTap: () async {
|
||||
unawaited(
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
PersonReviewClusterSuggestion(
|
||||
widget.person,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
],
|
||||
);
|
||||
} else if (snapshot.hasError) {
|
||||
log("Error: ${snapshot.error} ${snapshot.stackTrace}}");
|
||||
//Need to show an error on the UI here
|
||||
return const SizedBox.shrink();
|
||||
} else {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
],
|
||||
);
|
||||
} else if (snapshot.hasError) {
|
||||
log("Error: ${snapshot.error} ${snapshot.stackTrace}}");
|
||||
//Need to show an error on the UI here
|
||||
return const SizedBox.shrink();
|
||||
} else {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -265,10 +265,22 @@ class SearchExample extends StatelessWidget {
|
||||
if (result != null &&
|
||||
result is (PersonEntity, EnteFile)) {
|
||||
// ignore: unawaited_futures
|
||||
routeToPage(context, PeoplePage(person: result.$1));
|
||||
routeToPage(
|
||||
context,
|
||||
PeoplePage(
|
||||
person: result.$1,
|
||||
searchResult: null,
|
||||
),
|
||||
);
|
||||
} else if (result != null && result is PersonEntity) {
|
||||
// ignore: unawaited_futures
|
||||
routeToPage(context, PeoplePage(person: result));
|
||||
routeToPage(
|
||||
context,
|
||||
PeoplePage(
|
||||
person: result,
|
||||
searchResult: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
|
Loading…
x
Reference in New Issue
Block a user