Skip to content

Commit

Permalink
Add support for the new TimelineStart timeline item and new paginatio…
Browse files Browse the repository at this point in the history
…n API. Remove identifiers from individual timeline items and only set them in the TimelineTableViewController
  • Loading branch information
stefanceriu committed Jan 9, 2023
1 parent d830ec5 commit 490d24b
Show file tree
Hide file tree
Showing 27 changed files with 113 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ typealias RoomScreenViewModelType = StateStoreViewModel<RoomScreenViewState, Roo

class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol {
private enum Constants {
static let backPaginationEventLimit: UInt = 20
static let backPaginationPageSize: UInt = 50
}

Expand Down Expand Up @@ -121,7 +122,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
// MARK: - Private

private func paginateBackwards() async {
switch await timelineController.paginateBackwards(Constants.backPaginationPageSize) {
switch await timelineController.paginateBackwards(eventLimit: Constants.backPaginationEventLimit, totalItemCount: Constants.backPaginationPageSize) {
case .failure:
displayError(.alert(ElementL10n.roomTimelineBackpaginationFailure))
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ struct EmoteRoomTimelineView: View {
}
}
}
.id(timelineItem.id)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,19 @@ struct EncryptedRoomTimelineView: View {
Button {
showEncryptionInfo = !showEncryptionInfo
} label: {
HStack(alignment: .top) {
Image(systemName: "lock.shield")
.foregroundColor(.red)
.padding(.top, 1.0)
Label {
if showEncryptionInfo {
FormattedBodyText(text: encryptionDetails)
} else {
FormattedBodyText(text: timelineItem.text)
}
} icon: {
Image(systemName: "lock.shield")
.foregroundColor(.red)
}
.animation(nil, value: showEncryptionInfo)
}
}
.id(timelineItem.id)
}

private var encryptionDetails: String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ struct FileRoomTimelineView: View {
.padding(.vertical, 12)
.padding(.horizontal, 6)
}
.id(timelineItem.id)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ struct ImageRoomTimelineView: View {
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
}
}
.id(timelineItem.id)
.animation(.elementDefault, value: timelineItem.image)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ struct NoticeRoomTimelineView: View {
}
}
}
.id(timelineItem.id)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ struct ReadMarkerRoomTimelineView: View {
VStack {
Spacer(minLength: 4.0)
Divider()
.id(timelineItem.id)
.frame(maxWidth: .infinity)
.overlay(Color.element.accent)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ struct RedactedRoomTimelineView: View {
FormattedBodyText(text: timelineItem.text)
}
}
.id(timelineItem.id)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// limitations under the License.
//

import Foundation
import SwiftUI

struct SeparatorRoomTimelineView: View {
Expand All @@ -24,7 +23,6 @@ struct SeparatorRoomTimelineView: View {
Text(timelineItem.text)
.font(.element.footnote)
.foregroundColor(.element.secondaryContent)
.id(timelineItem.id)
.padding(.vertical, 24)
.frame(maxWidth: .infinity)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ struct StickerRoomTimelineView: View {
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
}
}
.id(timelineItem.id)
.animation(.elementDefault, value: timelineItem.image)
.accessibilityLabel(timelineItem.text)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ struct TextRoomTimelineView: View {
FormattedBodyText(text: timelineItem.text)
}
}
.id(timelineItem.id)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright 2023 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

struct TimelineStartRoomTimelineView: View {
let timelineItem: TimelineStartRoomTimelineItem

var body: some View {
Text(title)
.font(.element.footnote)
.foregroundColor(.element.secondaryContent)
.padding(.vertical, 24)
.frame(maxWidth: .infinity)
}

var title: String {
var text = ElementL10n.thisIsTheBeginningOfRoomNoName
if let name = timelineItem.name {
text = ElementL10n.thisIsTheBeginningOfRoom(name)
}
return text
}
}

struct TimelineStartRoomTimelineView_Previews: PreviewProvider {
static var previews: some View {
let item = TimelineStartRoomTimelineItem(name: "Alice and Bob")
TimelineStartRoomTimelineView(timelineItem: item)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,22 @@ struct UnsupportedRoomTimelineView: View {

var body: some View {
TimelineStyler(timelineItem: timelineItem) {
VStack(alignment: .leading) {
Text("\(timelineItem.text): \(timelineItem.eventType)")
.fixedSize(horizontal: false, vertical: true)
.foregroundColor(.element.alert)

Text(timelineItem.error)
.fixedSize(horizontal: false, vertical: true)
.foregroundColor(.element.alert)
.font(.element.callout)
Label {
VStack(alignment: .leading) {
Text("\(timelineItem.text): \(timelineItem.eventType)")
.fixedSize(horizontal: false, vertical: true)
.foregroundColor(.element.primaryContent)

Text(timelineItem.error)
.fixedSize(horizontal: false, vertical: true)
.font(.element.footnote)
.foregroundColor(.element.primaryContent)
}
} icon: {
Image(systemName: "exclamationmark.bubble")
.foregroundColor(.red)
}
}
.id(timelineItem.id)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ struct VideoRoomTimelineView: View {
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
}
}
.id(timelineItem.id)
.animation(.elementDefault, value: timelineItem.image)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ class TimelineTableViewController: UIViewController {
cell.item = timelineItem
cell.contentConfiguration = UIHostingConfiguration {
timelineItem
.id(timelineItem.id)
.frame(maxWidth: .infinity, alignment: .leading)
.opacity(opacity)
.contextMenu {
Expand Down
2 changes: 1 addition & 1 deletion ElementX/Sources/Services/Room/MockRoomProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct MockRoomProxy: RoomProxyProtocol {
.failure(.failedAddingTimelineListener)
}

func paginateBackwards(count: UInt) async -> Result<UInt, RoomProxyError> {
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomProxyError> {
.failure(.failedPaginatingBackwards)
}

Expand Down
20 changes: 5 additions & 15 deletions ElementX/Sources/Services/Room/RoomProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ class RoomProxy: RoomProxyProtocol {

private(set) var displayName: String?

private var backPaginationOutcome: PaginationOutcome?

private var timelineObservationToken: StoppableSpawn?

deinit {
Expand Down Expand Up @@ -138,17 +136,13 @@ class RoomProxy: RoomProxyProtocol {
}
}

func paginateBackwards(count: UInt) async -> Result<UInt, RoomProxyError> {
guard backPaginationOutcome?.moreMessages != false else {
return .failure(.noMoreMessagesToBackPaginate)
}

func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomProxyError> {
do {
let outcome: PaginationOutcome = try await Task.dispatch(on: .global()) {
try self.room.paginateBackwards(limit: UInt16(count))
try await Task.dispatch(on: .global()) {
try self.room.paginateBackwards(opts: .untilNumItems(eventLimit: UInt16(eventLimit), items: UInt16(totalItemCount)))
}
update(backPaginationOutcome: outcome)
return .success(UInt(outcome.numUpdates))

return .success(())
} catch {
return .failure(.failedPaginatingBackwards)
}
Expand Down Expand Up @@ -255,8 +249,4 @@ class RoomProxy: RoomProxyProtocol {
private func update(displayName: String) {
self.displayName = displayName
}

private func update(backPaginationOutcome: PaginationOutcome) {
self.backPaginationOutcome = backPaginationOutcome
}
}
2 changes: 1 addition & 1 deletion ElementX/Sources/Services/Room/RoomProxyProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ protocol RoomProxyProtocol {

func addTimelineListener(listener: TimelineListener) -> Result<Void, RoomProxyError>

func paginateBackwards(count: UInt) async -> Result<UInt, RoomProxyError>
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomProxyError>

func sendMessage(_ message: String, inReplyToEventId: String?) async -> Result<Void, RoomProxyError>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct MockRoomTimelineProvider: RoomTimelineProviderProtocol {

private var itemProxies = [TimelineItemProxy]()

func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineProviderError> {
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomTimelineProviderError> {
.failure(.failedPaginatingBackwards)
}

Expand Down
12 changes: 4 additions & 8 deletions ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,14 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
}
}

func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineProviderError> {
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomTimelineProviderError> {
// Set this back to false after actually updating the items or if failed
backPaginationPublisher.send(true)

MXLog.info("Started back pagination request")
switch await roomProxy.paginateBackwards(count: count) {
case .success(let numberOfUpdates):
MXLog.info("Finished back pagination request. Got \(numberOfUpdates) updates")

if numberOfUpdates == 0 {
backPaginationPublisher.send(false)
}
switch await roomProxy.paginateBackwards(eventLimit: eventLimit, totalItemCount: totalItemCount) {
case .success:
MXLog.info("Finished back pagination request")
return .success(())
case .failure(let error):
MXLog.error("Failed back pagination request with error: \(error)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protocol RoomTimelineProviderProtocol {

var backPaginationPublisher: CurrentValueSubject<Bool, Never> { get }

func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineProviderError>
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomTimelineProviderError>

func sendMessage(_ message: String, inReplyToItemId: String?) async -> Result<Void, RoomTimelineProviderError>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
}
}

func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineControllerError> {
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomTimelineControllerError> {
callbacks.send(.startedBackPaginating)

guard !backPaginationResponses.isEmpty else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
}

func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineControllerError> {
switch await timelineProvider.paginateBackwards(count) {
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomTimelineControllerError> {
switch await timelineProvider.paginateBackwards(eventLimit: eventLimit, totalItemCount: totalItemCount) {
case .success:
return .success(())
case .failure(let error):
Expand Down Expand Up @@ -262,6 +262,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
}
case .loadingIndicator:
newTimelineItems.append(PaginationIndicatorRoomTimelineItem())
case .timelineStart:
newTimelineItems.append(TimelineStartRoomTimelineItem(name: roomProxy.displayName ?? roomProxy.name))
}
default:
break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ protocol RoomTimelineControllerProtocol {

func processItemTap(_ itemId: String) async -> RoomTimelineControllerAction

func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineControllerError>
func paginateBackwards(eventLimit: UInt, totalItemCount: UInt) async -> Result<Void, RoomTimelineControllerError>

func sendMessage(_ message: String) async

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// Copyright 2023 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

struct TimelineStartRoomTimelineItem: DecorationTimelineItemProtocol, Identifiable, Hashable {
let id: String = UUID().uuidString
let name: String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ struct RoomTimelineViewFactory: RoomTimelineViewFactoryProtocol {
return .sticker(item)
case let item as UnsupportedRoomTimelineItem:
return .unsupported(item)
case let item as TimelineStartRoomTimelineItem:
return .timelineStart(item)
default:
fatalError("Unknown timeline item")
}
Expand Down
Loading

0 comments on commit 490d24b

Please sign in to comment.