tombstoned and upgraded rooms implementation

added tests

tombstoned room avatar
This commit is contained in:
Mauro Romito
2025-06-03 12:52:31 +02:00
committed by Mauro
parent b628f5d2c2
commit 155b47e849
76 changed files with 438 additions and 171 deletions
@@ -34,6 +34,8 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
var ownUserID: String { room.ownUserId() }
lazy var predecessorRoom: PredecessorRoom? = room.predecessorRoom()
let timeline: TimelineProxyProtocol
private let infoSubject: CurrentValueSubject<RoomInfoProxy, Never>
@@ -33,6 +33,10 @@ struct RoomInfoProxy: BaseRoomInfoProxyProtocol {
var avatarURL: URL? { roomInfo.avatarUrl.flatMap(URL.init) }
/// The room's avatar info for use in a ``RoomAvatarImage``.
var avatar: RoomAvatar {
guard successor == nil else {
return .tombstoned
}
if isDirect, avatarURL == nil, heroes.count == 1 {
return .heroes(heroes.map(UserProfileProxy.init))
}
@@ -61,7 +65,7 @@ struct RoomInfoProxy: BaseRoomInfoProxyProtocol {
}
var isSpace: Bool { roomInfo.isSpace }
var tombstoneInfo: SuccessorRoom? { roomInfo.successorRoom }
var successor: SuccessorRoom? { roomInfo.successorRoom }
var isFavourite: Bool { roomInfo.isFavourite }
var canonicalAlias: String? { roomInfo.canonicalAlias }
var alternativeAliases: [String] { roomInfo.alternativeAliases }
@@ -76,6 +76,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
var timeline: TimelineProxyProtocol { get }
var predecessorRoom: PredecessorRoom? { get }
func subscribeForUpdates() async
func subscribeToRoomInfoUpdates()
@@ -56,6 +56,8 @@ struct RoomSummary {
let isMarkedUnread: Bool
let isFavourite: Bool
let isTombstoned: Bool
var hasUnreadMessages: Bool { unreadMessagesCount > 0 }
var hasUnreadMentions: Bool { unreadMentionsCount > 0 }
var hasUnreadNotifications: Bool { unreadNotificationsCount > 0 }
@@ -124,14 +126,19 @@ extension RoomSummary {
joinRequestType = nil
isMarkedUnread = false
isFavourite = false
isTombstoned = false
}
// This doesn't have to work properly for DM invites, the heroes are always empty
var avatar: RoomAvatar {
guard !isTombstoned else {
return .tombstoned
}
if isDirect, avatarURL == nil, heroes.count == 1 {
.heroes(heroes)
return .heroes(heroes)
} else {
.room(id: id, name: name, avatarURL: avatarURL)
return .room(id: id, name: name, avatarURL: avatarURL)
}
}
}
@@ -281,7 +281,8 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
alternativeAliases: .init(roomInfo.alternativeAliases),
hasOngoingCall: roomInfo.hasRoomCall,
isMarkedUnread: roomInfo.isMarkedUnread,
isFavourite: roomInfo.isFavourite)
isFavourite: roomInfo.isFavourite,
isTombstoned: roomInfo.successorRoom != nil)
}
private func buildDiff(from diff: RoomListEntriesUpdate, on rooms: [RoomSummary]) -> CollectionDifference<RoomSummary>? {
@@ -185,11 +185,13 @@ class TimelineController: TimelineControllerProtocol {
sender: nil,
attachments: nil)
let avatarURL = switch roomProxy.details.avatar {
let avatarURL: URL? = switch roomProxy.details.avatar {
case .room(_, _, let avatarURL):
avatarURL
case .heroes(let userProfiles):
userProfiles.first?.avatarURL
case .tombstoned:
nil
}
func addPlacehoder() {
@@ -389,6 +391,7 @@ class TimelineController: TimelineControllerProtocol {
let isDM = roomProxy.isDirectOneToOneRoom
let displayName = roomProxy.infoPublisher.value.displayName
let hasPredecessor = roomProxy.predecessorRoom != nil
var newTimelineItems = await Task.detached { [timelineItemFactory, activeTimeline] in
var newTimelineItems = [RoomTimelineItemProtocol]()
@@ -401,6 +404,7 @@ class TimelineController: TimelineControllerProtocol {
let items = collapsibleChunk.compactMap { itemProxy in
let timelineItem = self.buildTimelineItem(for: itemProxy,
isDM: isDM,
hasPredecessor: hasPredecessor,
roomDisplayName: displayName,
timelineItemFactory: timelineItemFactory,
activeTimeline: activeTimeline)
@@ -451,6 +455,7 @@ class TimelineController: TimelineControllerProtocol {
private nonisolated func buildTimelineItem(for itemProxy: TimelineItemProxy,
isDM: Bool,
hasPredecessor: Bool,
roomDisplayName: String?,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
activeTimeline: TimelineProxyProtocol) -> RoomTimelineItemProtocol? {
@@ -475,7 +480,11 @@ class TimelineController: TimelineControllerProtocol {
case .readMarker:
return ReadMarkerRoomTimelineItem(id: .virtual(uniqueID: uniqueID))
case .timelineStart:
return isDM ? nil : TimelineStartRoomTimelineItem(name: roomDisplayName)
if hasPredecessor {
return TimelineStartRoomTimelineItem(name: roomDisplayName)
} else {
return isDM ? nil : TimelineStartRoomTimelineItem(name: roomDisplayName)
}
}
case .unknown:
return nil
@@ -8,6 +8,6 @@
import Foundation
struct TimelineStartRoomTimelineItem: DecorationTimelineItemProtocol, Equatable {
let id: TimelineItemIdentifier = .virtual(uniqueID: .init(UUID().uuidString))
let id: TimelineItemIdentifier = .virtual(uniqueID: .init("TimelineStart"))
let name: String?
}