Rename Provider Items to Item Proxies. (#205)

This commit is contained in:
Doug
2022-09-22 11:18:18 +01:00
committed by GitHub
parent a807301746
commit b9f8fb0b6f
12 changed files with 88 additions and 84 deletions
@@ -25,7 +25,10 @@ struct SomeRoomMessage: RoomMessageProtocol {
}
struct RoomMessageFactory: RoomMessageFactoryProtocol {
func buildRoomMessageFrom(_ eventItem: EventTimelineItem) -> RoomMessageProtocol {
SomeRoomMessage(id: eventItem.id, body: eventItem.body ?? "", sender: eventItem.sender, originServerTs: eventItem.originServerTs)
func buildRoomMessageFrom(_ eventItemProxy: EventTimelineItemProxy) -> RoomMessageProtocol {
SomeRoomMessage(id: eventItemProxy.id,
body: eventItemProxy.body ?? "",
sender: eventItemProxy.sender,
originServerTs: eventItemProxy.originServerTs)
}
}
@@ -18,5 +18,5 @@ import Foundation
import MatrixRustSDK
protocol RoomMessageFactoryProtocol {
func buildRoomMessageFrom(_ message: EventTimelineItem) -> RoomMessageProtocol
func buildRoomMessageFrom(_ eventItemProxy: EventTimelineItemProxy) -> RoomMessageProtocol
}
@@ -163,7 +163,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
var attributedLastMessage: AttributedString?
var lastMessageTimestamp: Date?
if let latestRoomMessage = room.latestRoomMessage() {
let lastMessage = roomMessageFactory.buildRoomMessageFrom(EventTimelineItem(item: latestRoomMessage))
let lastMessage = roomMessageFactory.buildRoomMessageFrom(EventTimelineItemProxy(item: latestRoomMessage))
if let lastMessageSender = try? AttributedString(markdown: "**\(lastMessage.sender)**") {
// Don't include the message body in the markdown otherwise it makes tappable links.
attributedLastMessage = lastMessageSender + ": " + AttributedString(lastMessage.body)
@@ -18,7 +18,7 @@ import Combine
struct MockRoomTimelineProvider: RoomTimelineProviderProtocol {
var callbacks = PassthroughSubject<RoomTimelineProviderCallback, Never>()
var items = [RoomTimelineProviderItem]()
var itemProxies = [TimelineItemProxy]()
func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineProviderError> {
.failure(.failedPaginatingBackwards)
@@ -134,21 +134,21 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
private func asyncUpdateTimelineItems() async {
var newTimelineItems = [RoomTimelineItemProtocol]()
for (index, item) in timelineProvider.items.enumerated() {
for (index, itemProxy) in timelineProvider.itemProxies.enumerated() {
if Task.isCancelled {
return
}
let previousItem = timelineProvider.items[safe: index - 1]
let nextItem = timelineProvider.items[safe: index + 1]
let previousItemProxy = timelineProvider.itemProxies[safe: index - 1]
let nextItemProxy = timelineProvider.itemProxies[safe: index + 1]
let inGroupState = inGroupState(for: item, previousItem: previousItem, nextItem: nextItem)
let inGroupState = inGroupState(for: itemProxy, previousItemProxy: previousItemProxy, nextItemProxy: nextItemProxy)
switch item {
switch itemProxy {
case .event(let eventItem):
guard eventItem.isMessage || eventItem.isRedacted else { break } // To be handled in the future
newTimelineItems.append(await timelineItemFactory.buildTimelineItemFor(eventItem: eventItem,
newTimelineItems.append(await timelineItemFactory.buildTimelineItemFor(eventItemProxy: eventItem,
showSenderDetails: inGroupState.shouldShowSenderDetails,
inGroupState: inGroupState))
case .virtual:
@@ -172,16 +172,16 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
callbacks.send(.updatedTimelineItems)
}
private func inGroupState(for item: RoomTimelineProviderItem,
previousItem: RoomTimelineProviderItem?,
nextItem: RoomTimelineProviderItem?) -> TimelineItemInGroupState {
guard let previousItem = previousItem else {
private func inGroupState(for itemProxy: TimelineItemProxy,
previousItemProxy: TimelineItemProxy?,
nextItemProxy: TimelineItemProxy?) -> TimelineItemInGroupState {
guard let previousItem = previousItemProxy else {
// no previous item, check next item
guard let nextItem = nextItem else {
guard let nextItem = nextItemProxy else {
// no next item neither, this is single
return .single
}
guard nextItem.canBeGrouped(with: item) else {
guard nextItem.canBeGrouped(with: itemProxy) else {
// there is a next item but can't be grouped, this is single
return .single
}
@@ -189,9 +189,9 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
return .beginning
}
guard let nextItem = nextItem else {
guard let nextItem = nextItemProxy else {
// no next item
guard item.canBeGrouped(with: previousItem) else {
guard itemProxy.canBeGrouped(with: previousItem) else {
// there is a previous item but can't be grouped, this is single
return .single
}
@@ -199,8 +199,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
return .end
}
guard item.canBeGrouped(with: previousItem) else {
guard nextItem.canBeGrouped(with: item) else {
guard itemProxy.canBeGrouped(with: previousItem) else {
guard nextItem.canBeGrouped(with: itemProxy) else {
// there is a next item but can't be grouped, this is single
return .single
}
@@ -208,7 +208,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
return .beginning
}
guard nextItem.canBeGrouped(with: item) else {
guard nextItem.canBeGrouped(with: itemProxy) else {
// there is a next item but can't be grouped, this is the end
return .end
}
@@ -36,11 +36,11 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
let callbacks = PassthroughSubject<RoomTimelineProviderCallback, Never>()
private(set) var items: [RoomTimelineProviderItem]
private(set) var itemProxies: [TimelineItemProxy]
init(roomProxy: RoomProxyProtocol) {
self.roomProxy = roomProxy
items = []
itemProxies = []
}
func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineProviderError> {
@@ -103,41 +103,41 @@ private extension RoomTimelineProvider {
private func replaceItems(_ items: [MatrixRustSDK.TimelineItem]?) {
guard let items = items else { return }
self.items = items.map(RoomTimelineProviderItem.init)
itemProxies = items.map(TimelineItemProxy.init)
}
private func insertItem(_ data: InsertAtData?) {
guard let data = data else { return }
let item = RoomTimelineProviderItem(item: data.item)
items.insert(item, at: Int(data.index))
let itemProxy = TimelineItemProxy(item: data.item)
itemProxies.insert(itemProxy, at: Int(data.index))
}
private func updateItem(_ data: UpdateAtData?) {
guard let data = data else { return }
let item = RoomTimelineProviderItem(item: data.item)
items[Int(data.index)] = item
let itemProxy = TimelineItemProxy(item: data.item)
itemProxies[Int(data.index)] = itemProxy
}
private func removeItem(at index: UInt32?) {
guard let index = index else { return }
items.remove(at: Int(index))
itemProxies.remove(at: Int(index))
}
private func moveItem(_ data: MoveData?) {
guard let data = data else { return }
items.move(fromOffsets: IndexSet(integer: Int(data.oldIndex)), toOffset: Int(data.newIndex))
itemProxies.move(fromOffsets: IndexSet(integer: Int(data.oldIndex)), toOffset: Int(data.newIndex))
}
private func pushItem(_ item: MatrixRustSDK.TimelineItem?) {
guard let item = item else { return }
items.append(RoomTimelineProviderItem(item: item))
itemProxies.append(TimelineItemProxy(item: item))
}
private func popItem() {
items.removeLast()
itemProxies.removeLast()
}
private func clearAllItems() {
items.removeAll()
itemProxies.removeAll()
}
}
@@ -32,7 +32,7 @@ enum RoomTimelineProviderError: Error {
protocol RoomTimelineProviderProtocol {
var callbacks: PassthroughSubject<RoomTimelineProviderCallback, Never> { get }
var items: [RoomTimelineProviderItem] { get }
var itemProxies: [TimelineItemProxy] { get }
func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineProviderError>
@@ -16,15 +16,15 @@
import MatrixRustSDK
/// A light wrapper around timeline items returned from Rust for use in `RoomTimelineProvider`.
enum RoomTimelineProviderItem {
case event(EventTimelineItem)
/// A light wrapper around timeline items returned from Rust.
enum TimelineItemProxy {
case event(EventTimelineItemProxy)
case virtual(MatrixRustSDK.VirtualTimelineItem)
case other(MatrixRustSDK.TimelineItem)
init(item: MatrixRustSDK.TimelineItem) {
if let eventItem = item.asEvent() {
self = .event(EventTimelineItem(item: eventItem))
self = .event(EventTimelineItemProxy(item: eventItem))
} else if let virtualItem = item.asVirtual() {
self = .virtual(virtualItem)
} else {
@@ -32,17 +32,17 @@ enum RoomTimelineProviderItem {
}
}
func canBeGrouped(with prevItem: RoomTimelineProviderItem) -> Bool {
guard case let .event(selfEventItem) = self, case let .event(prevEventItem) = prevItem else {
func canBeGrouped(with previousItemProxy: TimelineItemProxy) -> Bool {
guard case let .event(selfEventItemProxy) = self, case let .event(previousEventItemProxy) = previousItemProxy else {
return false
}
// can be improved by adding a date threshold
return prevEventItem.reactions.isEmpty && selfEventItem.sender == prevEventItem.sender
return previousEventItemProxy.reactions.isEmpty && selfEventItemProxy.sender == previousEventItemProxy.sender
}
}
/// A light wrapper around event timeline items returned from Rust, used in `RoomTimelineProviderItem`.
struct EventTimelineItem {
/// A light wrapper around event timeline items returned from Rust.
struct EventTimelineItemProxy {
let item: MatrixRustSDK.EventTimelineItem
init(item: MatrixRustSDK.EventTimelineItem) {
@@ -35,35 +35,35 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
self.attributedStringBuilder = attributedStringBuilder
}
func buildTimelineItemFor(eventItem: EventTimelineItem,
func buildTimelineItemFor(eventItemProxy: EventTimelineItemProxy,
showSenderDetails: Bool,
inGroupState: TimelineItemInGroupState) async -> RoomTimelineItemProtocol {
let displayName = roomProxy.displayNameForUserId(eventItem.sender)
let avatarURL = roomProxy.avatarURLStringForUserId(eventItem.sender)
let displayName = roomProxy.displayNameForUserId(eventItemProxy.sender)
let avatarURL = roomProxy.avatarURLStringForUserId(eventItemProxy.sender)
let avatarImage = mediaProvider.imageFromURLString(avatarURL, size: MediaProviderDefaultAvatarSize)
let isOutgoing = eventItem.isOwn
let isOutgoing = eventItemProxy.isOwn
if eventItem.isRedacted {
return buildRedactedTimelineItemFromEvent(eventItem, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
if eventItemProxy.isRedacted {
return buildRedactedTimelineItem(eventItemProxy, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
}
guard let messageContent = eventItem.content.asMessage() else { fatalError("Must be a message for now.") }
guard let messageContent = eventItemProxy.content.asMessage() else { fatalError("Must be a message for now.") }
switch messageContent.msgtype() {
case .text(content: let content):
let message = MessageTimelineItem(item: eventItem.item, content: content)
let message = MessageTimelineItem(item: eventItemProxy.item, content: content)
return await buildTextTimelineItemFromMessage(message, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
case .image(content: let content):
let message = MessageTimelineItem(item: eventItem.item, content: content)
let message = MessageTimelineItem(item: eventItemProxy.item, content: content)
return await buildImageTimelineItemFromMessage(message, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
case .notice(content: let content):
let message = MessageTimelineItem(item: eventItem.item, content: content)
let message = MessageTimelineItem(item: eventItemProxy.item, content: content)
return await buildNoticeTimelineItemFromMessage(message, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
case .emote(content: let content):
let message = MessageTimelineItem(item: eventItem.item, content: content)
let message = MessageTimelineItem(item: eventItemProxy.item, content: content)
return await buildEmoteTimelineItemFromMessage(message, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
case .none:
return await buildFallbackTimelineItem(eventItem, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
return await buildFallbackTimelineItem(eventItemProxy, isOutgoing, showSenderDetails, inGroupState, displayName, avatarImage)
}
}
@@ -71,45 +71,45 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
// swiftformat:disable function_parameter_count
// swiftlint:disable function_parameter_count
private func buildRedactedTimelineItemFromEvent(_ event: EventTimelineItem,
_ isOutgoing: Bool,
_ showSenderDetails: Bool,
_ inGroupState: TimelineItemInGroupState,
_ displayName: String?,
_ avatarImage: UIImage?) -> RoomTimelineItemProtocol {
RedactedRoomTimelineItem(id: event.id,
private func buildRedactedTimelineItem(_ eventItemProxy: EventTimelineItemProxy,
_ isOutgoing: Bool,
_ showSenderDetails: Bool,
_ inGroupState: TimelineItemInGroupState,
_ displayName: String?,
_ avatarImage: UIImage?) -> RoomTimelineItemProtocol {
RedactedRoomTimelineItem(id: eventItemProxy.id,
text: ElementL10n.eventRedacted,
timestamp: event.originServerTs.formatted(date: .omitted, time: .shortened),
timestamp: eventItemProxy.originServerTs.formatted(date: .omitted, time: .shortened),
shouldShowSenderDetails: showSenderDetails,
inGroupState: inGroupState,
isOutgoing: isOutgoing,
senderId: event.sender,
senderId: eventItemProxy.sender,
senderDisplayName: displayName,
senderAvatar: avatarImage,
properties: RoomTimelineItemProperties())
}
private func buildFallbackTimelineItem(_ item: EventTimelineItem,
private func buildFallbackTimelineItem(_ eventItemProxy: EventTimelineItemProxy,
_ isOutgoing: Bool,
_ showSenderDetails: Bool,
_ inGroupState: TimelineItemInGroupState,
_ displayName: String?,
_ avatarImage: UIImage?) async -> RoomTimelineItemProtocol {
let attributedText = await attributedStringBuilder.fromPlain(item.body)
let attributedText = await attributedStringBuilder.fromPlain(eventItemProxy.body)
let attributedComponents = attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedText)
return TextRoomTimelineItem(id: item.id,
text: item.body ?? "",
return TextRoomTimelineItem(id: eventItemProxy.id,
text: eventItemProxy.body ?? "",
attributedComponents: attributedComponents,
timestamp: item.originServerTs.formatted(date: .omitted, time: .shortened),
timestamp: eventItemProxy.originServerTs.formatted(date: .omitted, time: .shortened),
shouldShowSenderDetails: showSenderDetails,
inGroupState: inGroupState,
isOutgoing: isOutgoing,
senderId: item.sender,
senderId: eventItemProxy.sender,
senderDisplayName: displayName,
senderAvatar: avatarImage,
properties: RoomTimelineItemProperties(isEdited: item.content.asMessage()?.isEdited() ?? false,
reactions: aggregateReactions(item.reactions)))
properties: RoomTimelineItemProperties(isEdited: eventItemProxy.content.asMessage()?.isEdited() ?? false,
reactions: aggregateReactions(eventItemProxy.reactions)))
}
private func buildTextTimelineItemFromMessage(_ message: MessageTimelineItem<TextMessageContent>,
@@ -18,7 +18,7 @@ import Foundation
@MainActor
protocol RoomTimelineItemFactoryProtocol {
func buildTimelineItemFor(eventItem: EventTimelineItem,
func buildTimelineItemFor(eventItemProxy: EventTimelineItemProxy,
showSenderDetails: Bool,
inGroupState: TimelineItemInGroupState) async -> RoomTimelineItemProtocol
}