Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle unknown users everywhere #1012

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mofirojean
Copy link

@mofirojean mofirojean commented Oct 19, 2024

As described in the issue, I was able to reference the various instances of the store.users[userId] and most of the reference cases found had the null cases handled already, and what was left to do was to include a placeholder to adhere to Zulip's internalisation standard. Most of this could be traced to other instances that followed a similar pattern. I also performed a test to make sure nothing was broken while I implemented the changes.

fixes: #716

@gnprice gnprice added the maintainer review PR ready for review by Zulip maintainers label Oct 19, 2024
@chrisbobbe
Copy link
Collaborator

@PIG208 could you take this one? :)

@PIG208
Copy link
Member

PIG208 commented Oct 22, 2024

Hi! Please take a look at the commit-discipline to fix the commit messages. Per this suggestion, I think our goal for this PR is to fix part of #716, before going over all the places that need to be updated.

Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the second commit can be squashed into the first one.

One other thing to note is that you can use the NFC tag for your commits if they don't affect the behavior.

This is a change that we would like to have but it is not addressing #716 by finding places where we don't have unknown users. Nevertheless, this should be a good checkpoint before we start working on a PR.


// TODO(i18n): List formatting, like you can do in JavaScript:
// new Intl.ListFormat('ja').format(['Chris', 'Greg', 'Alya', 'Shu'])
// // 'Chris、Greg、Alya、Shu'
_ => narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)').join(', '),
_ => narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? zulipLocalizations.unknownUserName).join(', '),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was already quite long:

Suggested change
_ => narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? zulipLocalizations.unknownUserName).join(', '),
_ => narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName,
).join(', '),

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the code with the suggestions you gave, and also joined the two commits to one.

Moving next to implement the issue at hand.

@mofirojean mofirojean force-pushed the Handle-unknown-users-everywhere branch from d5f8afe to cc5c85c Compare October 23, 2024 21:25
Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The [nfc] tag is usually used as a suffix. Here are some examples:

  • 402f998 color [nfc]: Fix a straggling reference to Color.value, in a pigeon's doc
  • 2737d4c store [nfc]: Comment in _PerAccountStoreWidgetState.didChangeDependencies
  • 26069bd store [nfc]: Add indirection doLoadPerAccount
  • fc80be1 store [nfc]: Offer singleton global store on binding

So we should update [nfc]: handle unknown users everywhere to maybe i18n [nfc]: Handle unknown users everywhere (also note the capitalization change).

_ => narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)').join(', '),
_ => narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', '),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the updated code is not properly indented. Could you check again?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, i will do that right away

@@ -322,6 +322,8 @@ class MessageListAppBarTitle extends StatelessWidget {
Widget build(BuildContext context) {
final zulipLocalizations = ZulipLocalizations.of(context);

// TODO(i18n): provide tranlations just as 'zulipLocalizations.unknownUserName'
// for 'unknown channel'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: tranlations -> translations

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to move this comment to right before any of the lines containing (unknown channel), so it is easier to spot where the translation is applicable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay 👍 , just noticed i didn't spell that right

@@ -349,7 +351,7 @@ class MessageListAppBarTitle extends StatelessWidget {
if (otherRecipientIds.isEmpty) {
return const Text("DMs with yourself");
} else {
final names = otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)');
final names = otherRecipientIds.map((id) => store.users[id]?.fullName ?? zulipLocalizations.unknownUserName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
final names = otherRecipientIds.map((id) => store.users[id]?.fullName ?? zulipLocalizations.unknownUserName);
final names = otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName);

avatar = AvatarImage(userId: otherUserId, size: _avatarSize);
default:
// TODO(i18n): List formatting, like you can do in JavaScript:
// new Intl.ListFormat('ja').format(['Chris', 'Greg', 'Alya'])
// // 'Chris、Greg、Alya'
title = narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)').join(', ');
title = narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? zulipLocalizations.unknownUserName).join(', ');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
title = narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? zulipLocalizations.unknownUserName).join(', ');
title = narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', ');

@mofirojean mofirojean force-pushed the Handle-unknown-users-everywhere branch from cc5c85c to 9a36ab5 Compare October 28, 2024 06:29
@mofirojean
Copy link
Author

Hi @PIG208 , I updated the changes you requested. I have some questions with regards to the issue. As I understand it, the app has a map called PerAccountStore.users (also referred to as store.users), which holds information about all known users, and sometimes this list may not include all the users in the realm. Also, in some cases, when you try to look up a user by their userId in store.users, the result might be null (i.e., that user doesn’t exist in the map) and this may result in a crash.

Amongst the solutions, it was said not to use ! or assertions and use the dart's null-safety operator and then provide fallbacks for missing users, along with other solutions. I checked the codebase with the reference store.users and identified a few areas that match the description of the issue.

for the first case i worked on adding the placeholders and changing some translations as well.

I then saw this area with an assertion, models/compose.dart

String quoteAndReplyPlaceholder(PerAccountStore store, {
  required Message message,
}) {
  final sender = store.users[message.senderId];
  // Is this the area i should resolve
  assert(sender != null);

  final url = narrowLink(store,
    SendableNarrow.ofMessage(message, selfUserId: store.selfUserId),
    nearMessageId: message.id);
  ....
}

Is this an area, that requires the changes that address our issue?

Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the revision! Just one more comment from me.

Regarding the question on quoteAndReplyPlaceholder, I think that one in particular is one of the places we have access to the message that contains the sender information. #716 mentioned that we should fallback to that if the user is unknown.

When we have a context like a Message that provides its own details on a user (like the message sender), we should fall back to those if the user is unknown. That way we not only don't crash, but provide helpful information, in cases like a guest user looking at older messages sent by someone no longer subscribed to their streams.

Comment on lines 384 to 386
_ => narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', '),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use 2-space indentation

Suggested change
_ => narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', '),
_ => narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', '),

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thanks for pointing that out
Let me make the changes

@PIG208
Copy link
Member

PIG208 commented Oct 29, 2024

We should also update the commit summary, because we haven' handled unknown users everywhere yet.

@mofirojean mofirojean force-pushed the Handle-unknown-users-everywhere branch from 9a36ab5 to ea6a44b Compare October 29, 2024 21:35
@mofirojean
Copy link
Author

We should also update the commit summary, because we haven' handled unknown users everywhere yet.

About this, I checked other areas that didn't handle the null cases and it seems to me that they have been handled to resolve unknown users. Unless i might be confuse with what is required of me.

@PIG208
Copy link
Member

PIG208 commented Oct 29, 2024

In this change we only start to use the translation string, but there are some other cases where we do not handle unknown users yet.


// TODO(i18n): List formatting, like you can do in JavaScript:
// new Intl.ListFormat('ja').format(['Chris', 'Greg', 'Alya', 'Shu'])
// // 'Chris、Greg、Alya、Shu'
_ => narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)').join(', '),
_ => narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump: we use 2 spaces for indentation

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

I am using android studio as my IDE and i configured it to use 2 spaces, and the changes I provided used this 2 spaces for indentation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. That should work for most cases automatically, but looks like at the line (started with store.users[id]?.fullName) I commented, there is only one space indented from the text it aligns to (started with narrow.otherRecipientIds.map) in the previous line.

You can count the number of spaces at the column where the n from narrow.otherRecipientIds.map is at, at line store.users[id]?.fullName to see what I mean.

I would suggest the following change:

before:

      _ => narrow.otherRecipientIds.map((id) =>
            store.users[id]?.fullName ?? zulipLocalizations.unknownUserName

after:

      _ => narrow.otherRecipientIds.map((id) =>
             store.users[id]?.fullName ?? zulipLocalizations.unknownUserName

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to add the changes as requested and i updated the PR description.

@mofirojean
Copy link
Author

In this change we only start to use the translation string, but there are some other cases where we do not handle unknown users yet.

Okay, I get it now. Please can you look this code from the widget/content.dart, which i referenced using store.users[userId],

class AvatarImage extends StatelessWidget {
  ...
  @override
  Widget build(BuildContext context) {
    final store = PerAccountStoreWidget.of(context);
    final user = store.users[userId];
   
   /// In this case we have a condition to check if the user is null, does this mean
   ///  i need to add more logic to this or it handles the case as the issue describes ?
    if (user == null) { // TODO(log)
      return const SizedBox.shrink();
    }
  ...
  }
}

@PIG208
Copy link
Member

PIG208 commented Oct 31, 2024

Thanks for the update! For the question on widget/content.dart, I think in that case the unknown users have been taken care of.

We should also update the commit summary, because we haven' handled unknown users everywhere yet.

We have been focusing on using the translation strings for this PR/commit, so the summary should reflect that.

@PIG208
Copy link
Member

PIG208 commented Nov 6, 2024

Looks good overall! This message i18n [nfc]: Handle unknown users everywhere doesn't seem to reflect on what this is doing though, because this commit is mostly about switching to localized strings.

How about something like i18n: Use translation for "(unknown users)"?
(Looking at the change, I realized that this is not an nfc because this is a behavior change to support languages other than English)

@mofirojean
Copy link
Author

Looks good overall! This message i18n [nfc]: Handle unknown users everywhere doesn't seem to reflect on what this is doing, though, because this commit is mostly about switching to localized strings.

How about something like i18n: Use translation for "(unknown users)"?

Yes that true, let me make the changes

@mofirojean mofirojean force-pushed the Handle-unknown-users-everywhere branch from a6a0be0 to c3de2bb Compare November 7, 2024 11:50
@mofirojean mofirojean force-pushed the Handle-unknown-users-everywhere branch from c3de2bb to 12a4cb6 Compare November 7, 2024 11:54
@PIG208 PIG208 added integration review Added by maintainers when PR may be ready for integration and removed maintainer review PR ready for review by Zulip maintainers labels Nov 7, 2024
@PIG208 PIG208 assigned gnprice and unassigned PIG208 Nov 7, 2024
@PIG208 PIG208 removed their request for review November 7, 2024 15:25
@PIG208 PIG208 requested a review from gnprice November 7, 2024 15:25
@PIG208
Copy link
Member

PIG208 commented Nov 7, 2024

Thanks! This looks good to me.

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mofirojean for taking care of this, and @PIG208 for the previous reviews!

Generally this looks good. A few small comments below.

The PR description also needs to be fixed (just like the commit message was earlier) so it doesn't say this will fix #716.

@@ -157,7 +159,7 @@ class ReactionChip extends StatelessWidget {
? userIds.map((id) {
return id == store.selfUserId
? 'You'
: store.users[id]?.fullName ?? '(unknown user)'; // TODO(i18n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: commit message doesn't quite match actual string:

i18n: Use translation for "(unknown users)"

Comment on lines +346 to 347
// TODO(i18n): provide translations for 'unknown channel'
final streamName = stream?.name ?? '(unknown channel)';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it's just one translation

Suggested change
// TODO(i18n): provide translations for 'unknown channel'
final streamName = stream?.name ?? '(unknown channel)';
// TODO(i18n): provide translation for 'unknown channel'
final streamName = stream?.name ?? '(unknown channel)';

Comment on lines +338 to +339
// TODO(i18n): provide translations just as
// 'zulipLocalizations.unknownUserName' for 'unknown channel'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: simplify comment

Suggested change
// TODO(i18n): provide translations just as
// 'zulipLocalizations.unknownUserName' for 'unknown channel'
// TODO(i18n): provide translation for 'unknown channel'

Comment on lines +117 to +119
title = narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', ');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation

Suggested change
title = narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', ');
title = narrow.otherRecipientIds.map((id) =>
store.users[id]?.fullName ?? zulipLocalizations.unknownUserName
).join(', ');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integration review Added by maintainers when PR may be ready for integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle unknown users everywhere
4 participants