mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Permalink polish (#2771)
* Fix unbalanced padding. * Animate the scroll to an event when it is already loaded. * Perform the timeline clearance immediately before replacing the items. Hides the empty timeline that was briefly shown. * Make switching timeline more resilient.
This commit is contained in:
@@ -88,8 +88,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
roomAvatarURL: roomProxy.avatarURL,
|
||||
timelineStyle: appSettings.timelineStyle,
|
||||
isEncryptedOneToOneRoom: roomProxy.isEncryptedOneToOneRoom,
|
||||
timelineViewState: TimelineViewState(focussedEventID: focussedEventID,
|
||||
focussedEventNeedsDisplay: focussedEventID != nil),
|
||||
timelineViewState: TimelineViewState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }),
|
||||
ownUserID: roomProxy.ownUserID,
|
||||
hasOngoingCall: roomProxy.hasOngoingCall,
|
||||
bindings: .init(reactionsCollapsed: [:])),
|
||||
@@ -119,7 +118,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
return self.roomScreenInteractionHandler.audioPlayerState(for: itemID)
|
||||
}
|
||||
|
||||
buildTimelineViews()
|
||||
buildTimelineViews(timelineItems: timelineController.timelineItems)
|
||||
|
||||
updateMembers(roomProxy.membersPublisher.value)
|
||||
|
||||
@@ -192,9 +191,11 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
focusLive()
|
||||
case .scrolledToFocussedItem:
|
||||
Task { // Use a Task to mutate view state after the current view update.
|
||||
state.timelineViewState.focussedEventNeedsDisplay = false
|
||||
state.timelineViewState.focussedEvent?.appearance = .hasAppeared
|
||||
hideFocusLoadingIndicator()
|
||||
}
|
||||
case .hasSwitchedTimeline:
|
||||
Task { state.timelineViewState.isSwitchingTimelines = false }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +231,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
func focusOnEvent(eventID: String) async {
|
||||
if state.timelineViewState.hasLoadedItem(with: eventID) {
|
||||
state.timelineViewState.focussedEventID = eventID
|
||||
state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .animated)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -239,7 +240,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
switch await timelineController.focusOnEvent(eventID, timelineSize: Constants.detachedTimelineSize) {
|
||||
case .success:
|
||||
state.timelineViewState.focussedEventID = eventID
|
||||
state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .immediate)
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed to focus on event \(eventID)")
|
||||
|
||||
@@ -255,7 +256,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
private func focusLive() {
|
||||
timelineController.focusLive()
|
||||
state.timelineViewState.focussedEventID = nil
|
||||
}
|
||||
|
||||
private func attach(_ attachment: ComposerAttachmentType) {
|
||||
@@ -336,8 +336,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
guard let self else { return }
|
||||
|
||||
switch callback {
|
||||
case .updatedTimelineItems:
|
||||
buildTimelineViews()
|
||||
case .updatedTimelineItems(let updatedItems, let isSwitchingTimelines):
|
||||
buildTimelineViews(timelineItems: updatedItems, isSwitchingTimelines: isSwitchingTimelines)
|
||||
case .paginationState(let paginationState):
|
||||
if state.timelineViewState.paginationState != paginationState {
|
||||
state.timelineViewState.paginationState = paginationState
|
||||
@@ -347,8 +347,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
state.timelineViewState.isLive = isLive
|
||||
|
||||
// Remove the event highlight *only* when transitioning from non-live to live.
|
||||
if isLive, state.timelineViewState.focussedEventID != nil {
|
||||
state.timelineViewState.focussedEventID = nil
|
||||
if isLive, state.timelineViewState.focussedEvent != nil {
|
||||
state.timelineViewState.focussedEvent = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -568,10 +568,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
// MARK: - Timeline Item Building
|
||||
|
||||
private func buildTimelineViews() {
|
||||
private func buildTimelineViews(timelineItems: [RoomTimelineItemProtocol], isSwitchingTimelines: Bool = false) {
|
||||
var timelineItemsDictionary = OrderedDictionary<String, RoomTimelineItemViewState>()
|
||||
|
||||
timelineController.timelineItems.filter { $0 is RedactedRoomTimelineItem }.forEach { timelineItem in
|
||||
timelineItems.filter { $0 is RedactedRoomTimelineItem }.forEach { timelineItem in
|
||||
// Stops the audio player when a voice message is redacted.
|
||||
guard let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(timelineItem.id)) else {
|
||||
return
|
||||
@@ -583,7 +583,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
}
|
||||
}
|
||||
|
||||
let itemsGroupedByTimelineDisplayStyle = timelineController.timelineItems.chunked { current, next in
|
||||
let itemsGroupedByTimelineDisplayStyle = timelineItems.chunked { current, next in
|
||||
canGroupItem(timelineItem: current, with: next)
|
||||
}
|
||||
|
||||
@@ -614,6 +614,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
}
|
||||
}
|
||||
|
||||
if isSwitchingTimelines {
|
||||
state.timelineViewState.isSwitchingTimelines = true
|
||||
}
|
||||
|
||||
state.timelineViewState.itemsDictionary = timelineItemsDictionary
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user