project-robius / project-robius/robrix

InviteScreen can get stuck loading forever when the invite is resolved elsewhere (spaces always; rooms when rejected)

Open
#1,050 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
487
Forks
68
Avg merge
1h 22m
Merged PRs (30d)
54

Description

Summary

An InviteScreen showing an invite to a space can get stuck permanently in its
"loading" state if that space has already been joined by the time the screen is displayed.

The recovery path that handles "this invite was already accepted" works for rooms but can
never fire for spaces, because the check it relies on cannot report a joined space.

Details

InviteScreen::set_displayed_invite() has three outcomes:

  1. the room is present in the invited-rooms map, so render the invite;
  2. otherwise, if the room is already joined, upgrade this screen to the joined room's screen;
  3. otherwise, fall through to restore_status_view ("still loading").

Branch 2 is gated on (src/home/invite_screen.rs:546-547):

else if cx.has_global::<RoomsListRef>()
    && cx.get_global::<RoomsListRef>().get_room_state(room_name_id.room_id()) == Some(RoomState::Joined)

But RoomsList::get_room_state() (src/home/rooms_list.rs:581) can only answer from two
collections:

if self.all_joined_rooms.contains_key(room_id) { return Some(RoomState::Joined); }
if self.invited_rooms.borrow().contains_key(room_id) { return Some(RoomState::Invited); }
None

A joined space is in neither:

  • joined spaces are excluded from the room list service by the not(space) clause of the
    filter in room_list_service_loop() (src/sliding_sync.rs:3538-3542), and
  • even if one slipped through, add_new_room() early-returns for joined spaces
    (src/sliding_sync.rs:4089), so it never enters all_joined_rooms.

So get_room_state() returns None for a joined space, branch 2 is skipped, and the screen
falls through to the loading state with nothing left to resolve it.

How to reproduce
  1. Be invited to a space and open its InviteScreen (from the Invites section of the rooms
    list, or by clicking the space in the spaces bar).
  2. Join that space somewhere the in-app upgrade path doesn't cover, e.g. from another client,
    or in a previous session.
  3. Restore the tab (it is persisted in the saved dock state) and open it.

Expected: the screen upgrades to that space's SpaceLobbyScreen.
Actual: the screen stays on the "loading" restore status view indefinitely; the user has to
close the tab manually.

No crash and no data loss; the tab is simply stuck.

Related

This is the space-shaped instance of a more general gap: an invite accepted in another
client
leaves a stale InviteScreen, because the in-app accept handshake is gated on
InviteState::WaitingForJoinResult | WaitingForJoinedRoom, which is only set when the user
accepts from within Robrix. The two probably want a single fix.

Possible approaches

Neither is a one-liner, which is why this is filed rather than patched:

  • Teach get_room_state() about joined spaces. Requires giving RoomsList visibility of
    joined spaces, which currently live in SpacesBar / the space service, not the rooms list.
  • Ask the space service. Add an async round-trip (in the shape of the existing
    SpaceRequest::ResolveJoinedSpaceAncestor) so the InviteScreen can learn that the space is
    joined and upgrade itself. Keeps the ownership boundary intact at the cost of another
    request/response pair.

Found while adding support for displaying invited spaces.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/home/invite_screen.rs at InviteScreen::set_displayed_invite() and trace get_room_state() in src/home/rooms_list.rs. Then read the joined-space filtering and add_new_room() paths in src/sliding_sync.rs, along with the existing SpaceRequest::ResolveJoinedSpaceAncestor flow. Done means a stale invite for an already joined space resolves to its SpaceLobbyScreen instead of remaining in the loading view.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.