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

Port the Sliding Sync view logic from iOS into the SDK. #1644

Closed
pixlwave opened this issue Mar 10, 2023 · 3 comments
Closed

Port the Sliding Sync view logic from iOS into the SDK. #1644

pixlwave opened this issue Mar 10, 2023 · 3 comments
Assignees

Comments

@pixlwave
Copy link
Member

pixlwave commented Mar 10, 2023

Whilst implementing sliding sync in Element X iOS we have landed on a solution that uses 2 views and combines them into a single list for the app to display. We should move this code into the SDK so that it doesn't need to be re-implemented in Android and for other clients to benefit from this solution. Drawing from element-hq/element-x-android#143 an overview of how this works is as follows:

  • The first view is AllRooms and runs using the growingFullSync sync mode. It has a fixed limit = 0 and grows in batches of 100.
  • The second view is VisibleRooms and runs using the selective sync mode. The first sync is run with limit = 0 and a range of [0, 20] to get the rooms at the top of the list as quickly as possible. Once this first sync is completed, the limit is increased to 1 to load the last message for each room. This is also the point in time that AllRooms will be started, as went want the first sync of VisibleRooms to have priority during app launch.
  • From this point on, VisibleRooms is driven by the home screen based on the range of visible cells and whether or not the list is scrolling. These 2 values are passed as a tuple which is run through a 0.5 second throttle followed by a de-dupe before being used to update the view. The view's range is set to [firstVisibleIndex - 5, lastVisibleIndex + 5] and the limit is set to 1 when scrolling and 20 when stationary.
  • These 2 views are merged by enumerating through the items in VisibleRooms and applying the following logic:
    • Use the room from VisibleRooms if it is filled.
    • Otherwise if the index is valid in AllRooms get that room and
      • If it is filled show a room that is loading.
      • If it is invalidated show an invalidated room that is loading.
      • If it is empty show a placeholder room.
    • Otherwise whilst waiting for AllRooms to catch up continue with the room from VisibleRooms
      • If it is invalidated show an invalidated room that is not loading.
      • If it is empty show a placeholder room.
    • The final list is uniqued based on the room's ID, but invalidated rooms are given a unique ID to allow for the case of a room being invalidated and then added to the list higher up.

Future details

Additional Views
Its also worth considering how this will interact with the need for different options for example filtering the list for:

  • Only DMs.
  • Rooms in a particular space.
  • A list of spaces.
  • A list of invites.

In the case of say invites, some apps might like to be able to get the count of invites without showing the list e.g. to show a button with 4 Invites that will show just the invites when tapped.

@pixlwave
Copy link
Member Author

pixlwave commented Mar 10, 2023

The code we have is a bit intermingled between the UI layer and the data layer but I would imagine an API that looked something like this would be nice to create the 2 views.

let easySlidingSync = EasySlidingSyncListBuilder()
    .initialRange(from: 0, to: 20) // To customise for different window sizes
    .requiredState(requiredState: slidingSyncRequiredState)
    .filters(filters: slidingSyncFilters)
    .build(client: client) // Would need to manage the call to `client.slidingSync()` and add the views internally.

easySlidingSync.setObserver(observer: SomeObserver())



let (visibleRange, isScrolling) = homeScreenListState()
easySlidingSync.updateVisibleRange(start: visibleRange.lowerBound, end: visibleRange.upperBound, isScrolling: isScrolling)

@alfogrillo
Copy link
Contributor

FYI we started using a new SS for invites on EX-iOS.
This is how we configured it

Swift

let invitesView = try SlidingSyncListBuilder()
    .noTimelineLimit()
    .requiredState(requiredState: slidingSyncInvitesRequiredState)
    .filters(filters: slidingSyncInviteFilters)
    .name(name: "Invites")
    .syncMode(mode: .growing)
    .batchSize(batchSize: 100)
    .build()

Request

"Invites": {
      "ranges": [
        [
          0,
          99
        ]
      ],
      "sort": [
        "by_recency",
        "by_name"
      ],
      "required_state": [
        [
          "m.room.avatar",
          ""
        ],
        [
          "m.room.encryption",
          ""
        ],
        [
          "m.room.member",
          "$ME"
        ],
        [
          "m.room.canonical_alias",
          ""
        ]
      ],
      "filters": {
        "is_invite": true,
        "is_tombstoned": false,
        "not_room_types": [
          "m.space"
        ]
      }
    }

@Hywan Hywan mentioned this issue May 11, 2023
62 tasks
@Hywan
Copy link
Member

Hywan commented Aug 10, 2023

Closed by #1911.

@Hywan Hywan closed this as completed Aug 10, 2023
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

No branches or pull requests

3 participants