[mob][photos] Show banner for suggestions

This commit is contained in:
laurenspriem 2024-05-11 16:10:41 +05:30
parent 7045dbaeff
commit 45d46d5ca8

View file

@ -2,6 +2,7 @@ import "dart:async";
import "dart:developer";
import 'package:flutter/material.dart';
import "package:flutter_animate/flutter_animate.dart";
import "package:logging/logging.dart";
import 'package:photos/core/event_bus.dart';
import 'package:photos/events/files_updated_event.dart';
@ -12,11 +13,14 @@ 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/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/search_service.dart";
import "package:photos/ui/components/notification_widget.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/people/people_app_bar.dart";
import "package:photos/ui/viewer/people/person_cluster_suggestion.dart";
class PeoplePage extends StatefulWidget {
final String tagPrefix;
@ -39,6 +43,14 @@ class _PeoplePageState extends State<PeoplePage> {
final Logger _logger = Logger("_PeoplePageState");
final _selectedFiles = SelectedFiles();
List<EnteFile>? files;
int? smallestClusterSize;
Future<List<EnteFile>> filesFuture = Future.value([]);
bool get showSuggestionBanner => (smallestClusterSize != null &&
smallestClusterSize! >= kMinimumClusterSizeSearchResult &&
files != null &&
files!.isNotEmpty &&
files!.length > 200);
late final StreamSubscription<LocalPhotosUpdatedEvent> _filesUpdatedEvent;
late final StreamSubscription<PeopleChangedEvent> _peopleChangedEvent;
@ -51,6 +63,8 @@ class _PeoplePageState extends State<PeoplePage> {
setState(() {});
});
filesFuture = loadPersonFiles();
_filesUpdatedEvent =
Bus.instance.on<LocalPhotosUpdatedEvent>().listen((event) {
if (event.type == EventType.deletedFromDevice ||
@ -69,6 +83,10 @@ class _PeoplePageState extends State<PeoplePage> {
log("loadPersonFiles");
final result = await SearchService.instance
.getClusterFilesForPersonID(widget.person.remoteID);
smallestClusterSize = result.values.fold<int>(result.values.first.length,
(previousValue, element) {
return element.length < previousValue ? element.length : previousValue;
});
final List<EnteFile> resultFiles = [];
for (final e in result.entries) {
resultFiles.addAll(e.value);
@ -99,60 +117,104 @@ class _PeoplePageState extends State<PeoplePage> {
widget.person,
),
),
body: Stack(
alignment: Alignment.bottomCenter,
children: [
FutureBuilder<List<EnteFile>>(
future: loadPersonFiles(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final personFiles = snapshot.data as List<EnteFile>;
return Gallery(
asyncLoader: (
creationStartTime,
creationEndTime, {
limit,
asc,
}) async {
final result = await loadPersonFiles();
return Future.value(
FileLoadResult(
result,
false,
body: FutureBuilder<List<EnteFile>>(
future: filesFuture,
builder: (context, snapshot) {
if (snapshot.hasData) {
final personFiles = snapshot.data as List<EnteFile>;
return Column(
children: [
showSuggestionBanner
? RepaintBoundary(
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 8.0,
),
child: NotificationWidget(
startIcon: Icons.person_add_outlined,
actionIcon: Icons.search_outlined,
text: "Review suggestions",
subText:
"Improve the results by adding more suggested photos",
type: NotificationType.greenBanner,
onTap: () async {
unawaited(
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
PersonReviewClusterSuggestion(
widget.person,
),
),
),
);
},
),
)
.animate(
onPlay: (controller) => controller.repeat(),
)
.shimmer(
duration: 1000.ms,
delay: 3200.ms,
size: 0.6,
),
)
: const SizedBox.shrink(),
Expanded(
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] : [],
),
);
},
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] : [],
);
} 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(),
);
}
},
),
FileSelectionOverlayBar(
PeoplePage.overlayType,
_selectedFiles,
person: widget.person,
),
],
FileSelectionOverlayBar(
PeoplePage.overlayType,
_selectedFiles,
person: widget.person,
),
],
),
),
],
);
} 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(),
);
}
},
),
);
}