[mob][photos] Use first letter avatar for contact in contacts section and all contacts screen if no person is linked to contact

This commit is contained in:
ashilkn
2025-02-05 17:28:13 +05:30
parent b855d38864
commit 46c941fb8c
5 changed files with 112 additions and 63 deletions

View File

@@ -2,3 +2,4 @@ const kPersonParamID = 'person_id';
const kPersonWidgetKey = 'person_widget_key';
const kClusterParamId = 'cluster_id';
const kFileID = 'file_id';
const kContactEmail = 'contact_email';

View File

@@ -1728,6 +1728,7 @@ class SearchService {
),
params: {
kPersonParamID: key.linkedPersonID,
kContactEmail: key.email,
},
),
);
@@ -1803,6 +1804,7 @@ class SearchService {
),
params: {
kPersonParamID: key.linkedPersonID,
kContactEmail: key.email,
},
),
);

View File

@@ -3,6 +3,7 @@ import "dart:async";
import "package:collection/collection.dart";
import 'package:flutter/material.dart';
import "package:logging/logging.dart";
import "package:photos/core/configuration.dart";
import "package:photos/core/event_bus.dart";
import "package:photos/events/people_changed_event.dart";
import "package:photos/extensions/user_extension.dart";
@@ -130,7 +131,7 @@ class _UserAvatarWidgetState extends State<UserAvatarWidget> {
);
} else if (snapshot.hasError) {
_logger.severe("Error loading personID", snapshot.error);
return _FirstLetterAvatar(
return _FirstLetterCircularAvatar(
user: widget.user,
currentUserID: widget.currentUserID,
thumbnailView: widget.thumbnailView,
@@ -138,7 +139,7 @@ class _UserAvatarWidgetState extends State<UserAvatarWidget> {
);
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.data == null) {
return _FirstLetterAvatar(
return _FirstLetterCircularAvatar(
user: widget.user,
currentUserID: widget.currentUserID,
thumbnailView: widget.thumbnailView,
@@ -150,7 +151,7 @@ class _UserAvatarWidgetState extends State<UserAvatarWidget> {
),
),
)
: _FirstLetterAvatar(
: _FirstLetterCircularAvatar(
user: widget.user,
currentUserID: widget.currentUserID,
thumbnailView: widget.thumbnailView,
@@ -159,12 +160,12 @@ class _UserAvatarWidgetState extends State<UserAvatarWidget> {
}
}
class _FirstLetterAvatar extends StatefulWidget {
class _FirstLetterCircularAvatar extends StatefulWidget {
final User user;
final int currentUserID;
final bool thumbnailView;
final AvatarType type;
const _FirstLetterAvatar({
const _FirstLetterCircularAvatar({
required this.user,
required this.currentUserID,
required this.thumbnailView,
@@ -172,10 +173,12 @@ class _FirstLetterAvatar extends StatefulWidget {
});
@override
State<_FirstLetterAvatar> createState() => _FirstLetterAvatarState();
State<_FirstLetterCircularAvatar> createState() =>
_FirstLetterCircularAvatarState();
}
class _FirstLetterAvatarState extends State<_FirstLetterAvatar> {
class _FirstLetterCircularAvatarState
extends State<_FirstLetterCircularAvatar> {
@override
Widget build(BuildContext context) {
final colorScheme = getEnteColorScheme(context);
@@ -186,13 +189,12 @@ class _FirstLetterAvatarState extends State<_FirstLetterAvatar> {
: widget.user.email.substring(0, 1))
: widget.user.displayName!.substring(0, 1);
Color decorationColor;
if (widget.user.id == null ||
widget.user.id! <= 0 ||
widget.user.id == widget.currentUserID) {
if ((widget.user.id != null && widget.user.id! < 0) ||
widget.user.email == Configuration.instance.getEmail()) {
decorationColor = Colors.black;
} else {
decorationColor = colorScheme.avatarColors[
(widget.user.id!).remainder(colorScheme.avatarColors.length)];
decorationColor = colorScheme.avatarColors[(widget.user.email.length)
.remainder(colorScheme.avatarColors.length)];
}
final avatarStyle = getAvatarStyle(context, widget.type);
@@ -257,3 +259,57 @@ double getAvatarSize(
return 18.0;
}
}
class FirstLetterUserAvatar extends StatefulWidget {
final User user;
const FirstLetterUserAvatar(this.user, {super.key});
@override
State<FirstLetterUserAvatar> createState() => _FirstLetterUserAvatarState();
}
class _FirstLetterUserAvatarState extends State<FirstLetterUserAvatar> {
final currentUserEmail = Configuration.instance.getEmail();
late User user;
@override
void initState() {
super.initState();
user = widget.user;
}
@override
void didUpdateWidget(covariant FirstLetterUserAvatar oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.user != widget.user) {
setState(() {
user = widget.user;
});
}
}
@override
Widget build(BuildContext context) {
final colorScheme = getEnteColorScheme(context);
final displayChar = (user.displayName == null || user.displayName!.isEmpty)
? ((user.email.isEmpty) ? " " : user.email.substring(0, 1))
: user.displayName!.substring(0, 1);
Color decorationColor;
if ((widget.user.id != null && widget.user.id! < 0) ||
user.email == currentUserEmail) {
decorationColor = Colors.black;
} else {
decorationColor = colorScheme.avatarColors[
(user.email.length).remainder(colorScheme.avatarColors.length)];
}
return Container(
color: decorationColor,
child: Center(
child: Text(
displayChar.toUpperCase(),
style: getEnteTextTheme(context).small.copyWith(color: Colors.white),
),
),
);
}
}

View File

@@ -1,5 +1,6 @@
import "package:flutter/material.dart";
import "package:logging/logging.dart";
import "package:photos/models/api/collection/user.dart";
import 'package:photos/models/file/file.dart';
import "package:photos/models/search/generic_search_result.dart";
import "package:photos/models/search/search_constants.dart";
@@ -8,6 +9,7 @@ import "package:photos/models/search/search_types.dart";
import "package:photos/services/machine_learning/face_ml/person/person_service.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/common/loading_widget.dart";
import "package:photos/ui/sharing/user_avator_widget.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/person_face_widget.dart';
@@ -73,14 +75,14 @@ class _ContactSearchThumbnailWidgetState
extends State<ContactSearchThumbnailWidget> {
Future<EnteFile?>? _mostRecentFileOfPerson;
late String? _personID;
late String _email;
final _logger = Logger("_ContactSearchThumbnailWidgetState");
late final EnteFile? _previewThumbnail;
@override
void initState() {
super.initState();
_previewThumbnail = widget.searchResult.previewThumbnail();
_personID = widget.searchResult.params[kPersonParamID];
_email = widget.searchResult.params[kContactEmail];
if (_personID != null) {
_mostRecentFileOfPerson =
PersonService.instance.getPerson(_personID!).then((person) {
@@ -118,35 +120,38 @@ class _ContactSearchThumbnailWidgetState
);
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.data == null) {
return _previewThumbnail != null
? ThumbnailWidget(
_previewThumbnail!,
)
: const NoFaceOrFileContactWidget();
return NoFaceForContactWidget(
user: User(email: _email),
);
} else if (snapshot.hasError) {
_logger.severe(
"Error loading personID",
snapshot.error,
);
return const NoFaceOrFileContactWidget();
return NoFaceForContactWidget(
user: User(email: _email),
);
} else {
return const EnteLoadingWidget();
}
},
)
: _previewThumbnail != null
? ThumbnailWidget(
_previewThumbnail!,
)
: const NoFaceOrFileContactWidget(),
: NoFaceForContactWidget(
user: User(email: _email),
),
),
);
}
}
class NoFaceOrFileContactWidget extends StatelessWidget {
class NoFaceForContactWidget extends StatelessWidget {
final User user;
final bool addBorder;
const NoFaceOrFileContactWidget({this.addBorder = true, super.key});
const NoFaceForContactWidget({
this.addBorder = true,
required this.user,
super.key,
});
@override
Widget build(BuildContext context) {
@@ -164,13 +169,7 @@ class NoFaceOrFileContactWidget extends StatelessWidget {
: null,
color: enteColorScheme.fillFaint,
),
child: Center(
child: Icon(
Icons.person_2_outlined,
color: enteColorScheme.strokeMuted,
size: 24,
),
),
child: Center(child: FirstLetterUserAvatar(user)),
);
}
}

View File

@@ -6,6 +6,7 @@ import "package:logging/logging.dart";
import "package:photos/core/constants.dart";
import "package:photos/events/event.dart";
import "package:photos/generated/l10n.dart";
import "package:photos/models/api/collection/user.dart";
import "package:photos/models/file/file.dart";
import "package:photos/models/search/generic_search_result.dart";
import "package:photos/models/search/recent_searches.dart";
@@ -14,8 +15,7 @@ import "package:photos/models/search/search_types.dart";
import "package:photos/services/machine_learning/face_ml/person/person_service.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/common/loading_widget.dart";
import "package:photos/ui/viewer/file/no_thumbnail_widget.dart";
import "package:photos/ui/viewer/file/thumbnail_widget.dart";
import "package:photos/ui/sharing/user_avator_widget.dart";
import "package:photos/ui/viewer/search/result/contact_result_page.dart";
import "package:photos/ui/viewer/search/result/person_face_widget.dart";
import "package:photos/ui/viewer/search/search_section_cta.dart";
@@ -224,43 +224,34 @@ class _ContactRecommendationState extends State<ContactRecommendation> {
} else if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.data == null) {
if (widget.contactSearchResult
.previewThumbnail() !=
null) {
return Hero(
tag: heroTag,
child: ThumbnailWidget(
widget.contactSearchResult
.previewThumbnail()!,
shouldShowArchiveStatus: false,
shouldShowSyncStatus: false,
),
);
} else {
return const NoThumbnailWidget();
}
return FirstLetterUserAvatar(
User(
email: widget.contactSearchResult
.params[kContactEmail],
),
);
} else if (snapshot.hasError) {
_logger.severe(
"Error loading personID",
snapshot.error,
);
return const NoThumbnailWidget();
return FirstLetterUserAvatar(
User(
email: widget.contactSearchResult
.params[kContactEmail],
),
);
} else {
return const EnteLoadingWidget();
}
},
)
: widget.contactSearchResult.previewThumbnail() != null
? Hero(
tag: heroTag,
child: ThumbnailWidget(
widget.contactSearchResult
.previewThumbnail()!,
shouldShowArchiveStatus: false,
shouldShowSyncStatus: false,
),
)
: const NoThumbnailWidget(),
: FirstLetterUserAvatar(
User(
email: widget
.contactSearchResult.params[kContactEmail],
),
),
),
),
const SizedBox(height: 10.5),