diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 6bbe35103..6722a03e6 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -205,16 +205,33 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol MXLog.info("Updating rooms") var rooms = [HomeScreenRoom]() + var createdRoomIdentifiers = [String: Bool]() + + #warning("This works around duplicated room list items coming out of the SDK, remove once fixed") + func appendRoom(_ room: HomeScreenRoom, allRoomsProvider: Bool) { + guard createdRoomIdentifiers[room.id] == nil else { + MXLog.error("Built duplicated room for identifier: \(room.id). AllRoomsSummaryProvider: \(allRoomsProvider). Ignoring") + return + } + + createdRoomIdentifiers[room.id] = true + rooms.append(room) + } // Try merging together results from both the visibleRoomsSummaryProvider and the allRoomsSummaryProvider // Empty or invalidated items in the visibleRoomsSummaryProvider might have more details in the allRoomsSummaryProvider // If items are unavailable in the allRoomsSummaryProvider (hasn't be added to SS yet / cold cache) then use what's available for (index, summary) in visibleRoomsSummaryProvider.roomListPublisher.value.enumerated() { switch summary { + case .filled(let details): + let room = buildRoom(with: details, invalidated: false, isLoading: false) + appendRoom(room, allRoomsProvider: false) case .empty, .invalidated: + // Try getting details from the allRoomsSummaryProvider guard let allRoomsRoomSummary = allRoomsSummaryProvider?.roomListPublisher.value[safe: index] else { if case let .invalidated(details) = summary { - rooms.append(buildRoom(with: details, invalidated: true, isLoading: false)) + let room = buildRoom(with: details, invalidated: true, isLoading: false) + appendRoom(room, allRoomsProvider: true) } else { rooms.append(HomeScreenRoom.placeholder()) } @@ -224,11 +241,13 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol switch allRoomsRoomSummary { case .empty: rooms.append(HomeScreenRoom.placeholder()) - case .filled(let details), .invalidated(let details): - rooms.append(buildRoom(with: details, invalidated: false, isLoading: true)) + case .filled(let details): + let room = buildRoom(with: details, invalidated: false, isLoading: true) + appendRoom(room, allRoomsProvider: true) + case .invalidated(let details): + let room = buildRoom(with: details, invalidated: true, isLoading: true) + appendRoom(room, allRoomsProvider: true) } - case .filled(let details): - rooms.append(buildRoom(with: details, invalidated: false, isLoading: false)) } } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index 2d2fb3efa..aa52d0f12 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -87,6 +87,8 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { return updatedItems } + detectDuplicatesInRoomList(rooms) + MXLog.info("Finished applying \(diffs.count) diffs") } @@ -185,6 +187,25 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { return CollectionDifference(changes) } + + private func detectDuplicatesInRoomList(_ rooms: [RoomSummary]) { + let filteredRooms = rooms.filter { + switch $0 { + case .empty: + return false + default: + return true + } + } + + let groupedRooms = Dictionary(grouping: filteredRooms, by: \.id) + + let duplicates = groupedRooms.filter { $1.count > 1 } + + if duplicates.count > 0 { + MXLog.error("Found duplicated room room list items: \(duplicates)") + } + } } extension SlidingSyncViewRoomsListDiff { diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift index ae62a79c0..543f347dd 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift @@ -25,7 +25,7 @@ enum RoomSummaryProviderState { case live } -enum RoomSummary { +enum RoomSummary: CustomStringConvertible { case empty case filled(details: RoomSummaryDetails) case invalidated(details: RoomSummaryDetails) @@ -38,6 +38,17 @@ enum RoomSummary { return details.id } } + + var description: String { + switch self { + case .empty: + return "\(String(describing: Self.self)): Empty" + case .invalidated(let details): + return "\(String(describing: Self.self)): Invalidated(\(details.id))" + case .filled(let details): + return "\(String(describing: Self.self)): Filled(\(details.id))" + } + } } protocol RoomSummaryProviderProtocol {