From 078799c1e26be7128e4a828e4a7190430a1a0645 Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Fri, 21 Apr 2023 13:14:27 +0200 Subject: [PATCH] Add invites badges (#819) --- .../Sources/Application/AppSettings.swift | 6 +++ .../Screens/HomeScreen/HomeScreenModels.swift | 1 + .../HomeScreen/HomeScreenViewModel.swift | 14 +++-- .../Screens/HomeScreen/View/HomeScreen.swift | 2 +- .../Screens/Invites/InvitesModels.swift | 1 + .../Screens/Invites/InvitesViewModel.swift | 25 ++++----- .../Invites/View/InvitesScreenCell.swift | 52 ++++++++++++++----- .../UserSessionFlowCoordinator.swift | 1 + .../UITests/UITestsAppCoordinator.swift | 13 +++++ .../UITests/UITestsScreenIdentifier.swift | 1 + UITests/Sources/InvitesScreenUITests.swift | 7 ++- .../en-GB-iPad-9th-generation.invites-1.png | 4 +- .../en-GB-iPad-9th-generation.invites.png | 4 +- ...-iPad-9th-generation.invitesWithBadges.png | 3 ++ .../Application/en-GB-iPhone-14.invites-1.png | 4 +- .../Application/en-GB-iPhone-14.invites.png | 4 +- .../en-GB-iPhone-14.invitesWithBadges.png | 3 ++ .../pseudo-iPad-9th-generation.invites-1.png | 4 +- .../pseudo-iPad-9th-generation.invites.png | 4 +- ...-iPad-9th-generation.invitesWithBadges.png | 3 ++ .../pseudo-iPhone-14.invites-1.png | 4 +- .../Application/pseudo-iPhone-14.invites.png | 4 +- .../pseudo-iPhone-14.invitesWithBadges.png | 3 ++ UnitTests/Sources/InvitesViewModelTests.swift | 4 +- changelog.d/714.feature | 1 + 25 files changed, 124 insertions(+), 48 deletions(-) create mode 100644 UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invitesWithBadges.png create mode 100644 UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invitesWithBadges.png create mode 100644 UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invitesWithBadges.png create mode 100644 UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invitesWithBadges.png create mode 100644 changelog.d/714.feature diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index 1f7bda484..64d91b920 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -21,6 +21,7 @@ import SwiftUI final class AppSettings: ObservableObject { private enum UserDefaultsKeys: String { case lastVersionLaunched + case seenInvites case timelineStyle case enableAnalytics case enableInAppNotifications @@ -69,6 +70,11 @@ final class AppSettings: ObservableObject { @UserPreference(key: UserDefaultsKeys.lastVersionLaunched, storageType: .userDefaults(store)) var lastVersionLaunched: String? + /// The Set of room identifiers of invites that the user already saw in the invites list. + /// This Set is being used to implement badges for unread invites. + @UserPreference(key: UserDefaultsKeys.seenInvites, defaultValue: [], storageType: .userDefaults(store)) + var seenInvites: Set + /// The default homeserver address used. This is intentionally a string without a scheme /// so that it can be passed to Rust as a ServerName for well-known discovery. let defaultHomeserverAddress = "matrix.org" diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift index 7bab99b08..d1fd2ac55 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift @@ -70,6 +70,7 @@ struct HomeScreenViewState: BindableState { let invitePermalink: URL? var hasPendingInvitations = false + var hasUnreadPendingInvitations = false var startChatFlowEnabled: Bool { ServiceLocator.shared.settings.startChatFlowEnabled diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 575504d1f..6ec4f8ed6 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -134,10 +134,18 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol } .store(in: &cancellables) - invitesSummaryProvider.countPublisher - .map { $0 > 0 } + invitesSummaryProvider.roomListPublisher + .combineLatest(ServiceLocator.shared.settings.$seenInvites) .receive(on: DispatchQueue.main) - .weakAssign(to: \.state.hasPendingInvitations, on: self) + .sink { [weak self] summaries, readInvites in + self?.state.hasPendingInvitations = !summaries.isEmpty + self?.state.hasUnreadPendingInvitations = summaries.contains(where: { + guard let roomId = $0.id else { + return false + } + return !readInvites.contains(roomId) + }) + } .store(in: &cancellables) updateRooms() diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift index b51959649..b1f10b1d8 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift @@ -33,7 +33,7 @@ struct HomeScreen: View { } if context.viewState.hasPendingInvitations, ServiceLocator.shared.settings.invitesFlowEnabled { - HomeScreenInvitesButton(title: L10n.actionInvitesList, hasBadge: true) { + HomeScreenInvitesButton(title: L10n.actionInvitesList, hasBadge: context.viewState.hasUnreadPendingInvitations) { context.send(viewAction: .selectInvites) } .padding(.trailing, 16) diff --git a/ElementX/Sources/Screens/Invites/InvitesModels.swift b/ElementX/Sources/Screens/Invites/InvitesModels.swift index f4432080c..d8f5ba324 100644 --- a/ElementX/Sources/Screens/Invites/InvitesModels.swift +++ b/ElementX/Sources/Screens/Invites/InvitesModels.swift @@ -30,6 +30,7 @@ struct InvitesViewStateBindings { struct InvitesRoomDetails { let roomDetails: RoomSummaryDetails var inviter: RoomMemberProxyProtocol? + var isUnread: Bool var isDirect: Bool { roomDetails.isDirect diff --git a/ElementX/Sources/Screens/Invites/InvitesViewModel.swift b/ElementX/Sources/Screens/Invites/InvitesViewModel.swift index 334e79bfc..a1b9caab3 100644 --- a/ElementX/Sources/Screens/Invites/InvitesViewModel.swift +++ b/ElementX/Sources/Screens/Invites/InvitesViewModel.swift @@ -22,6 +22,7 @@ typealias InvitesViewModelType = StateStoreViewModel = .init() private let userSession: UserSessionProtocol + private let previouslySeenInvites: Set var actions: AnyPublisher { actionsSubject.eraseToAnyPublisher() @@ -29,6 +30,7 @@ class InvitesViewModel: InvitesViewModelType, InvitesViewModelProtocol { init(userSession: UserSessionProtocol) { self.userSession = userSession + previouslySeenInvites = ServiceLocator.shared.settings.seenInvites super.init(initialViewState: InvitesViewState(), imageProvider: userSession.mediaProvider) setupSubscriptions() } @@ -65,7 +67,8 @@ class InvitesViewModel: InvitesViewModelType, InvitesViewModelProtocol { .sink { [weak self] roomSummaries in guard let self else { return } - let invites = roomSummaries.invites + let invites = self.buildInvites(from: roomSummaries) + ServiceLocator.shared.settings.seenInvites = Set(invites.map(\.roomDetails.id)) self.state.invites = invites for invite in invites { @@ -75,6 +78,15 @@ class InvitesViewModel: InvitesViewModelType, InvitesViewModelProtocol { .store(in: &cancellables) } + private func buildInvites(from summaries: [RoomSummary]) -> [InvitesRoomDetails] { + summaries.compactMap { summary in + guard case .filled(let details) = summary else { + return nil + } + return InvitesRoomDetails(roomDetails: details, isUnread: !previouslySeenInvites.contains(details.id)) + } + } + private func fetchInviter(for roomID: String) { Task { guard let room: RoomProxyProtocol = await self.clientProxy.roomForIdentifier(roomID) else { @@ -154,14 +166,3 @@ class InvitesViewModel: InvitesViewModelType, InvitesViewModelProtocol { message: L10n.errorUnknown) } } - -private extension Array where Element == RoomSummary { - var invites: [InvitesRoomDetails] { - compactMap { summary in - guard case .filled(let details) = summary else { - return nil - } - return .init(roomDetails: details) - } - } -} diff --git a/ElementX/Sources/Screens/Invites/View/InvitesScreenCell.swift b/ElementX/Sources/Screens/Invites/View/InvitesScreenCell.swift index 78ea1190a..fa26075cd 100644 --- a/ElementX/Sources/Screens/Invites/View/InvitesScreenCell.swift +++ b/ElementX/Sources/Screens/Invites/View/InvitesScreenCell.swift @@ -24,6 +24,7 @@ struct InvitesScreenCell: View { let declineAction: () -> Void private let verticalInsets = 16.0 + @ScaledMetric private var badgeSize = 12.0 var body: some View { HStack(alignment: .top, spacing: 16) { @@ -42,27 +43,26 @@ struct InvitesScreenCell: View { } } .padding(.top, verticalInsets) - .padding(.horizontal, 12) + .padding(.horizontal, 16) } // MARK: - Private private var mainContent: some View { - VStack(alignment: .leading, spacing: 4) { - Text(title) - .font(.element.headline) - .foregroundColor(.element.primaryContent) - - if let subtitle { - Text(subtitle) - .font(.compound.bodyMD) - .foregroundColor(.compound.textPlaceholder) + VStack(alignment: .leading, spacing: 6) { + HStack(alignment: .firstTextBaseline, spacing: 12) { + textualContent + + if invite.isUnread { + badge + } } inviterView buttons - .padding(.top, 10) + .padding(.trailing, 26) + .padding(.top, 8) } } @@ -82,6 +82,22 @@ struct InvitesScreenCell: View { } } + @ViewBuilder + private var textualContent: some View { + VStack(alignment: .leading) { + Text(title) + .font(.element.headline) + .foregroundColor(.element.primaryContent) + + if let subtitle { + Text(subtitle) + .font(.compound.bodyMD) + .foregroundColor(.compound.textPlaceholder) + } + } + .frame(maxWidth: .infinity, alignment: .leading) + } + private var buttons: some View { HStack(spacing: 12) { Button(L10n.actionDecline, action: declineAction) @@ -127,6 +143,12 @@ struct InvitesScreenCell: View { } return attributedString } + + private var badge: some View { + Circle() + .frame(width: badgeSize, height: badgeSize) + .foregroundColor(.element.brand) + } } struct InvitesScreenCell_Previews: PreviewProvider { @@ -139,6 +161,10 @@ struct InvitesScreenCell_Previews: PreviewProvider { InvitesScreenCell(invite: .room(alias: "#footest:somewhere.org"), imageProvider: MockMediaProvider(), acceptAction: { }, declineAction: { }) .previewDisplayName("Aliased room") + + InvitesScreenCell(invite: .room(alias: "#footest:somewhere.org"), imageProvider: MockMediaProvider(), acceptAction: { }, declineAction: { }) + .dynamicTypeSize(.accessibility1) + .previewDisplayName("Aliased room (AX1)") } } @@ -157,7 +183,7 @@ private extension InvitesRoomDetails { inviter.displayName = "Jack" inviter.userID = "@jack:somewhere.com" - return .init(roomDetails: dmRoom, inviter: inviter) + return .init(roomDetails: dmRoom, inviter: inviter, isUnread: false) } static func room(alias: String?) -> InvitesRoomDetails { @@ -174,6 +200,6 @@ private extension InvitesRoomDetails { inviter.userID = "@jack:somewhere.com" inviter.avatarURL = nil - return .init(roomDetails: dmRoom, inviter: inviter) + return .init(roomDetails: dmRoom, inviter: inviter, isUnread: true) } } diff --git a/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift b/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift index d032313c9..a4d4238d6 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift @@ -117,6 +117,7 @@ class UserSessionFlowCoordinator: CoordinatorProtocol { self.presentStartChat(animated: animated) case (.startChatScreen, .dismissedStartChatScreen, .roomList): break + case (.roomList, .showInvitesScreen, .invitesScreen): self.presentInvitesList(animated: animated) case (.invitesScreen, .closedInvitesScreen, .roomList): diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index d44ac1c79..e673032c6 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -364,7 +364,20 @@ class MockScreen: Identifiable { mediaProvider: MockMediaProvider())) navigationStackCoordinator.setRootCoordinator(coordinator) return navigationStackCoordinator + case .invitesWithBadges: + ServiceLocator.shared.settings.seenInvites = Set([RoomSummary].mockInvites.dropFirst(1).compactMap(\.id)) + let navigationStackCoordinator = NavigationStackCoordinator() + let clientProxy = MockClientProxy(userID: "@mock:client.com") + clientProxy.roomInviter = RoomMemberProxyMock.mockCharlie + let summaryProvider = MockRoomSummaryProvider(state: .loaded(.mockInvites)) + clientProxy.visibleRoomsSummaryProvider = summaryProvider + clientProxy.invitesSummaryProvider = summaryProvider + + let coordinator = InvitesCoordinator(parameters: .init(userSession: MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider()))) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .invites: + ServiceLocator.shared.settings.seenInvites = Set([RoomSummary].mockInvites.compactMap(\.id)) let navigationStackCoordinator = NavigationStackCoordinator() let clientProxy = MockClientProxy(userID: "@mock:client.com") clientProxy.roomInviter = RoomMemberProxyMock.mockCharlie diff --git a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift index bee3d93ce..15c92669f 100644 --- a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift +++ b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift @@ -52,6 +52,7 @@ enum UITestsScreenIdentifier: String { case startChat case startChatWithSearchResults case invites + case invitesWithBadges case invitesNoInvites case inviteUsers } diff --git a/UITests/Sources/InvitesScreenUITests.swift b/UITests/Sources/InvitesScreenUITests.swift index f0aa15418..4957f84ac 100644 --- a/UITests/Sources/InvitesScreenUITests.swift +++ b/UITests/Sources/InvitesScreenUITests.swift @@ -18,11 +18,16 @@ import ElementX import XCTest class InvitesScreenUITests: XCTestCase { - func testMixedInvites() { + func testInvitesWithNoBadges() { let app = Application.launch(.invites) app.assertScreenshot(.invites) } + func testInvitesWithBadges() { + let app = Application.launch(.invitesWithBadges) + app.assertScreenshot(.invitesWithBadges) + } + func testNoInvites() { let app = Application.launch(.invitesNoInvites) XCTAssertTrue(app.staticTexts[A11yIdentifiers.invitesScreen.noInvites].exists) diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites-1.png index bc30e79fc..0afb690cb 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites-1.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:227793880d0425d98c0dbb1d8a5f6439432383d9a9506030b9f4838bf9c0ce4d -size 188175 +oid sha256:eceabc10203dde514204abb2e9f842ec10f18ca0216c5932bda372ec8ee727a5 +size 188129 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites.png index 3512b9a32..223092ac7 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b7e4017ecafaca01e672701182dd6695573b021bc684c285e76214f311b35f6 -size 98707 +oid sha256:11505b76e0455ca673ccd716893e2fe771e34666dcedacbf998bc5c3d0a550ec +size 98629 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invitesWithBadges.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invitesWithBadges.png new file mode 100644 index 000000000..61e4d7b66 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.invitesWithBadges.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f23e94a8e39bc7adaa06136aea223b6112626f77425ff3db021c5496bff3f28 +size 98983 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites-1.png index f036f9e16..30a19883b 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites-1.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da9cae78d8cf7592e20aedd014801c912e0feb90a1a9365b6ed99bea5b11bc1f -size 356615 +oid sha256:85e5dfea417d1130ed453e1c483034b2e1f717a1418b164a4f9856bfe5a175fc +size 353862 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites.png index e714e7877..c4647f582 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:947fbd514af15087b850aae85371920b9f829fe92c0bbb4ca62ac97e95b6a92d -size 116523 +oid sha256:7cebc6d0ae1b65debda82b586a4033d83a5c21e9d125855c8544ac70631aaee3 +size 112839 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invitesWithBadges.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invitesWithBadges.png new file mode 100644 index 000000000..fd2b37679 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.invitesWithBadges.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0cdb8a004a3ca661aae6a649fdbdd0c8990f6bcc8760cf222b05490a7785fa7 +size 114708 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites-1.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites-1.png index 40dc88377..76f0797ab 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites-1.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3221977873adc6942d96a283f8625a835277201db4897a72fd6942a8191ed221 -size 233543 +oid sha256:2b33ca3e65d765ae24b1a0223198e7b42ed0686a825629f5b0f8bc93b357d6b3 +size 233512 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites.png index 9535c0cb7..e290befe0 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e4ce0956d2c9499c1d4f6e84041377263ed74a959196e4f60574c8a7f694855 -size 104489 +oid sha256:1ecf3a404f38c4c4fa376c236e50a1160f4d6eadbcd77145f156a81cec245e12 +size 104268 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invitesWithBadges.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invitesWithBadges.png new file mode 100644 index 000000000..c68d2aeca --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.invitesWithBadges.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:161305b820d23a1e29a5d80f1a4a306c68a65af933d039dcd50f49d888a1f552 +size 104655 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites-1.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites-1.png index 3fea415bd..608c11f33 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites-1.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fe7a52291eb74567927f6da56a533f1dfc616a899d1174e65d36198ca65ca11 -size 461856 +oid sha256:ef8a8fe4a9ae1bdd437a2618574962d1c57175e1893131293d6fa13f9a9dd1c1 +size 522278 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites.png index 011abc022..5ac716ede 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd3942891d03d9e67861fefd90406d51bb3189782307fc0335a1fba1c4754c0b -size 121889 +oid sha256:dc43c5d83a75af17a28421ffed097f67d1ffc026b8d0d36c5cae1f4a1c012336 +size 137190 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invitesWithBadges.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invitesWithBadges.png new file mode 100644 index 000000000..0852b37bd --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.invitesWithBadges.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7de304c4383db02fde81ede2169907a2394c27dd49a1238fb91626f110d44b3f +size 137714 diff --git a/UnitTests/Sources/InvitesViewModelTests.swift b/UnitTests/Sources/InvitesViewModelTests.swift index dc3d29dff..7cbfb87da 100644 --- a/UnitTests/Sources/InvitesViewModelTests.swift +++ b/UnitTests/Sources/InvitesViewModelTests.swift @@ -53,7 +53,7 @@ class InvitesViewModelTests: XCTestCase { return } setupViewModel(roomSummaries: invites) - context.send(viewAction: .accept(.init(roomDetails: details))) + context.send(viewAction: .accept(.init(roomDetails: details, isUnread: false))) let action: InvitesViewModelAction? = await viewModel.actions.values.first() guard case .openRoom(let roomID) = action else { XCTFail("Wrong view model action") @@ -69,7 +69,7 @@ class InvitesViewModelTests: XCTestCase { return } setupViewModel(roomSummaries: invites) - context.send(viewAction: .decline(.init(roomDetails: details))) + context.send(viewAction: .decline(.init(roomDetails: details, isUnread: false))) XCTAssertNotNil(context.alertInfo) } diff --git a/changelog.d/714.feature b/changelog.d/714.feature new file mode 100644 index 000000000..08ab9a7c6 --- /dev/null +++ b/changelog.d/714.feature @@ -0,0 +1 @@ +Added unread badges in the invites list. \ No newline at end of file