Skip to content

feat: add "or invite a lichess user" button to the "share challenge link" dialog#2881

Merged
veloce merged 4 commits into
lichess-org:mainfrom
tom-anders:pick-player-screen
Apr 2, 2026
Merged

feat: add "or invite a lichess user" button to the "share challenge link" dialog#2881
veloce merged 4 commits into
lichess-org:mainfrom
tom-anders:pick-player-screen

Conversation

@tom-anders

Copy link
Copy Markdown
Collaborator

This also adds a new PickPlayerScreen that immediately displays your online/offline friends, instead of having to use the search bar to find them. I also made use of that in "challenge from position".

Demo:

inviteuser.webm

Also, fix a bug where creating an open correspondence challenge would not show the "share link" screen.

Copilot AI 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.

Pull request overview

This PR enhances the challenge-sharing flow by adding a logged-in “invite a Lichess user” entry point and introducing a new player picker screen that surfaces online/offline friends immediately. It also adjusts challenge creation to fix the “open correspondence challenge” flow so it can reach the share-link UI.

Changes:

  • Added PickPlayerScreen to quickly pick from following/online friends, with search navigation.
  • Updated open-challenge share-link UI to optionally offer “Or invite a Lichess user” when authenticated.
  • Adjusted challenge creation/loading logic to support open correspondence/unlimited challenges reaching the share-link screen.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/view/game/game_screen_test.dart Expands open-challenge share-link test to cover logged-in vs anonymous UI.
lib/src/view/user/search_screen.dart Adds a mounted guard before saving search history in a debounced callback.
lib/src/view/user/pick_player_screen.dart New screen to browse online/offline following and navigate to search.
lib/src/view/play/create_challenge_bottom_sheet.dart Routes open correspondence/unlimited challenges into GameScreen (share-link flow).
lib/src/view/game/game_screen.dart Updates open-challenge loading widget parameters and app bar title logic.
lib/src/view/game/game_screen_providers.dart Creates “directed real-time or open” challenge and mounts guard before updating state.
lib/src/view/game/game_loading_board.dart Adds authenticated “invite user” button to the open-challenge share-link UI.
lib/src/view/board_editor/board_editor_screen.dart Uses PickPlayerScreen for “Challenge from position” user selection.
lib/src/model/lobby/create_game_service.dart Renames/expands real-time challenge creation; adds (currently unused) correspondence option param.
lib/src/model/challenge/challenge.dart Adds isOpenOrRealTime helper on Challenge and ChallengeRequest.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/src/view/user/pick_player_screen.dart
Comment thread lib/src/view/user/pick_player_screen.dart
Comment thread lib/src/view/game/game_loading_board.dart
Comment thread lib/src/view/game/game_loading_board.dart Outdated
Comment thread lib/src/view/game/game_loading_board.dart Outdated
Comment thread lib/src/model/lobby/create_game_service.dart Outdated
Comment thread lib/src/view/play/create_challenge_bottom_sheet.dart

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/src/view/user/pick_player_screen.dart
Comment on lines +113 to +118
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: PlatformSearchBar(
hintText: context.l10n.searchSearch,
focusNode: _AlwaysDisabledFocusNode(),
onTap: () => Navigator.of(context).push(

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

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

PlatformSearchBar is given a new _AlwaysDisabledFocusNode() on every build, but _PlayersList is a StatelessWidget so the FocusNode is never disposed. This can leak focus nodes; prefer avoiding a custom focus node (e.g., use canRequestFocus: false / readOnly patterns) or manage/dispose a single node in a StatefulWidget.

Copilot uses AI. Check for mistakes.

@tom-anders tom-anders Mar 31, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Copied from PlayerScreen 🤷

Comment thread lib/src/view/game/game_loading_board.dart
Comment thread lib/src/view/game/game_loading_board.dart Outdated
Comment thread lib/src/model/lobby/create_game_service.dart Outdated
Comment thread lib/src/model/lobby/create_game_service.dart Outdated
…enge

It used to just show the "challenge created" snackbar, which of course
is useless for an open challenge
@tom-anders tom-anders marked this pull request as ready for review March 31, 2026 21:35
@tom-anders tom-anders requested a review from veloce March 31, 2026 21:35

@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.

Great stuff!

Challenges are always more complicated that what we think...

One UI suggestion: I find that the "share link or invite user" card look a bit too cramped. Some more vertical space around elements would be nice.
Or perhaps just more padding around the "Invite user" button would do it.

ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
context.l10n.mobileChallengeCreated.replaceAll('\\n', '\n'),

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'm surprised you have to do that... it should not be necessary. And I saw an \n in the snackbar of the screen recording in the PR description.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

hmm i copied this from #2882, but yeah it looks like a bug with the translation generation.

I created the video before I cherry-picked that change, that's why it's still broken there

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.

Fixed in b304c45

padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: PlatformSearchBar(
hintText: context.l10n.searchSearch,
focusNode: _AlwaysDisabledFocusNode(),

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.

Copilot comment makes sense. We should convert the _PlayersList to a StatefulWidget and initialise the _AlwaysDisabledFocusNode() in a field of that class to be able to dispose it.

(and do the same in PlayerScreen)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fixed 👍

@tom-anders

Copy link
Copy Markdown
Collaborator Author

Increased spacing a bit:

Screenshot_1775037028

@veloce veloce merged commit 3fc3498 into lichess-org:main Apr 2, 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.

3 participants