Skip to content

Feature: delete block private messages#3030

Merged
veloce merged 7 commits into
lichess-org:mainfrom
MaartenD:feature/delete-report-block-private-messages
May 5, 2026
Merged

Feature: delete block private messages#3030
veloce merged 7 commits into
lichess-org:mainfrom
MaartenD:feature/delete-report-block-private-messages

Conversation

@MaartenD

Copy link
Copy Markdown
Contributor

Add the feature to delete message en block a user.

See video for the result.

Enjoy.

delete-block-messages-small.mp4

Fixes: #2023

@ijm8710

ijm8710 commented Apr 21, 2026

Copy link
Copy Markdown

Thanks! Would also be nice to have the block button in top right of within the convo (like you can see with the left device on web) as block, report and delete are all there

Id also love to be able to delete individual messages but not sure if server allows that

@MaartenD

Copy link
Copy Markdown
Contributor Author

Thanks! Would also be nice to have the block button in top right of within the convo (like you can see with the left device on web) as block, report and delete are all there

I would love to do that, but i didn't do it directly, because the block button was already created in this user menu. @veloce what's your opinion about this?

Id also love to be able to delete individual messages but not sure if server allows that.
This isn't possible at web, didn't take a look if it's possible. If it's possible then here the same. Is this the way veloce wants to go.

Happy to here you like it.

@ijm8710

ijm8710 commented Apr 21, 2026

Copy link
Copy Markdown

One last request :)

Understood it's not on web but I've always found these helpful

When it gives you the prompt before it deletes, I always find it super helpful to have the prompt where it clarifies: something like "“This message will be deleted for you only.”

@HaonRekcef HaonRekcef left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

https://github.com/lichess-org/mobile/blob/main/docs/internationalisation.md#mobile-translations-tips

Normally we add the features first without the translation strings and then after some time we translate them, to avoid translation contributors needing to translate unneeded/dead translations.

Comment thread lib/l10n/app_en.arb Outdated
"mobileHomeTab": "Home",
"mobileLiveStreamers": "Live streamers",
"mobileMessageDeleteConversation": "Delete conversation",
"mobileMessageDeleteConversationTitle": "Delete conversation",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We should not add the same string twice, you can reuse it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hi @HaonRekcef,

Thanks for the link. I changed it. Deleted the translations and made use of hardcoded text. Re-used the code mobileAreYouSure .

@veloce veloce left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This PR not only adds the delete thread feature but changes the logic about blocking. Usually it is better to keep one change per PR to simplify the review process.

The new logic may be better but I want to avoid regressions. That is why I'd like to see tests showcasing the new blocking logic, covering all cases (lichess user, user that blocked, user that did not block, etc.)

Navigator.push(context, UserOrProfileScreen.buildRoute(context, widget.user)),
onTap: () async {
await Navigator.push(context, UserOrProfileScreen.buildRoute(context, widget.user));
ref.invalidate(conversationControllerProvider(widget.user.id));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you tell me why you invalidate here?

And why after pushing the screen? Usually what we do is invalidate, then push.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We invalidate the provider after returning from the profile screen because the user may have blocked the contact while viewing their profile. The server's /inbox endpoint does not return blocking status, so the controller calls getUser() to fetch it separately. By invalidating after the push returns, we force the controller to rebuild and call getUser() again picking up any blocking change that happened while on the profile screen.

Invalidating before the push would not help here, since the block action hasn't occurred yet at that point and the controller would just reload with the same unblocked state.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see. I actually got confused because this is the first time I see an async onTap handler doing it.

In other parts of the code we're doing:

onTap: () {
   Navigator.push(context, UserOrProfileScreen.buildRoute(context, widget.user))
     // invalidate to refresh potential blocking status change
     .then((_) => ref.invalidate(conversationControllerProvider(widget.user.id)))
}

I know async/await is most of the time preferred to .then but in that case I find it more intuitive (and let's be consistent with the rest).

Also here I think we miss a if (context.mounted) after the async gap.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will make it consist with the rest of the code and also add the if (context.mounted) and push later today.

final controller = TextEditingController();

bool get isBlocked =>
widget.state.convo.relations.inward == false || widget.state.convo.relations.outward == false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You removed that logic. I am not sure why?

We could use tests here. At least to check which convo is blocked or not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I removed that logic because the server's /inbox/$userId endpoint returns relations: (inward: null, outward: null) even after blocking so checking inward == false or outward == false would never be true. The original check was effectively dead code. To get the actual blocking status I call getUser() instead, which correctly returns blocking: true when a user is blocked.

I agree that tests would be valuable here to document which conversations are considered blocked and why. I will add those.

@MaartenD

MaartenD commented May 4, 2026

Copy link
Copy Markdown
Contributor Author

Hi,

Tests in test/model/message/conversation_controller_test.dart

  • isBlocked is false for a normal user that is not blocked
  • isBlocked is true when you have blocked the user
  • isBlocked is false when blocking field is absent from user response
  • isBot is true for a bot account
  • postable is false when contact does not accept new messages
  • postable is true when existing conversation allows further messages

If i missed something, let me know.

@veloce veloce left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks

@veloce veloce merged commit c6d4c8f into lichess-org:main May 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add "delete" "report" and "block" for private messages

4 participants