mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
* Fixes #2360 - Add support for manually marking rooms as unread * Add analytics for marking rooms as (un)read * Remove unnecessary analytics abstraction levels * Fix breaking API changes following SDK bump * Add changelog * Handle PR comments * Fix unit tests
This commit is contained in:
@@ -51,6 +51,8 @@ enum HomeScreenViewAction {
|
||||
case updateVisibleItemRange(range: Range<Int>, isScrolling: Bool)
|
||||
case selectInvites
|
||||
case globalSearch
|
||||
case markRoomAsUnread(roomIdentifier: String)
|
||||
case markRoomAsRead(roomIdentifier: String)
|
||||
}
|
||||
|
||||
enum HomeScreenRoomListMode: CustomStringConvertible {
|
||||
@@ -102,7 +104,9 @@ struct HomeScreenViewState: BindableState {
|
||||
|
||||
var rooms: [HomeScreenRoom] = []
|
||||
var roomListMode: HomeScreenRoomListMode = .skeletons
|
||||
|
||||
var shouldShowFilters = false
|
||||
var markAsUnreadEnabled = false
|
||||
|
||||
var hasPendingInvitations = false
|
||||
var hasUnreadPendingInvitations = false
|
||||
@@ -153,6 +157,8 @@ struct HomeScreenRoom: Identifiable, Equatable {
|
||||
|
||||
var name = ""
|
||||
|
||||
var isMarkedUnread: Bool
|
||||
|
||||
var hasUnreadMessages = false
|
||||
|
||||
var hasUnreadMentions = false
|
||||
@@ -171,10 +177,15 @@ struct HomeScreenRoom: Identifiable, Equatable {
|
||||
|
||||
var isPlaceholder = false
|
||||
|
||||
var hasNewContent: Bool {
|
||||
hasUnreadMessages || hasUnreadMentions || hasUnreadNotifications || isMarkedUnread
|
||||
}
|
||||
|
||||
static func placeholder() -> HomeScreenRoom {
|
||||
HomeScreenRoom(id: UUID().uuidString,
|
||||
roomId: nil,
|
||||
name: "Placeholder room name",
|
||||
isMarkedUnread: false,
|
||||
hasUnreadMessages: false,
|
||||
hasUnreadMentions: false,
|
||||
hasUnreadNotifications: false,
|
||||
|
||||
@@ -86,6 +86,10 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
.weakAssign(to: \.state.shouldShowFilters, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
appSettings.$markAsUnreadEnabled
|
||||
.weakAssign(to: \.state.markAsUnreadEnabled, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
let isSearchFieldFocused = context.$viewState.map(\.bindings.isSearchFieldFocused)
|
||||
let searchQuery = context.$viewState.map(\.bindings.searchQuery)
|
||||
isSearchFieldFocused
|
||||
@@ -143,6 +147,34 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
actionsSubject.send(.presentInvitesScreen)
|
||||
case .globalSearch:
|
||||
actionsSubject.send(.presentGlobalSearch)
|
||||
case .markRoomAsUnread(let roomIdentifier):
|
||||
Task {
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomIdentifier) else {
|
||||
MXLog.error("Failed retrieving room for identifier: \(roomIdentifier)")
|
||||
return
|
||||
}
|
||||
|
||||
switch await roomProxy.markAsUnread() {
|
||||
case .success:
|
||||
ServiceLocator.shared.analytics.trackInteraction(name: .MobileRoomListRoomContextMenuUnreadToggle)
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed marking room \(roomIdentifier) as unread with error: \(error)")
|
||||
}
|
||||
}
|
||||
case .markRoomAsRead(let roomIdentifier):
|
||||
Task {
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomIdentifier) else {
|
||||
MXLog.error("Failed retrieving room for identifier: \(roomIdentifier)")
|
||||
return
|
||||
}
|
||||
|
||||
switch await roomProxy.markAsRead(sendReadReceipts: true, receiptType: appSettings.sendReadReceiptsEnabled ? .read : .readPrivate) {
|
||||
case .success:
|
||||
ServiceLocator.shared.analytics.trackInteraction(name: .MobileRoomListRoomContextMenuUnreadToggle)
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed marking room \(roomIdentifier) as read with error: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +359,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
return HomeScreenRoom(id: identifier,
|
||||
roomId: details.id,
|
||||
name: details.name,
|
||||
isMarkedUnread: details.isMarkedUnread,
|
||||
hasUnreadMessages: details.unreadMessagesCount > 0,
|
||||
hasUnreadMentions: details.unreadMentionsCount > 0,
|
||||
hasUnreadNotifications: details.unreadNotificationsCount > 0,
|
||||
|
||||
@@ -40,7 +40,7 @@ struct HomeScreen: View {
|
||||
.navigationTitle(L10n.screenRoomlistMainSpaceTitle)
|
||||
.toolbar { toolbar }
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.track(screen: .home)
|
||||
.track(screen: .Home)
|
||||
.introspect(.viewController, on: .supportedVersions) { controller in
|
||||
Task {
|
||||
if bloomView == nil {
|
||||
|
||||
@@ -133,7 +133,7 @@ struct HomeScreenRoomCell: View {
|
||||
.foregroundColor(.compound.iconAccentTertiary)
|
||||
}
|
||||
|
||||
if hasNewContent {
|
||||
if room.hasNewContent {
|
||||
Circle()
|
||||
.frame(width: 12, height: 12)
|
||||
.foregroundColor(isHighlighted ? .compound.iconAccentTertiary : .compound.iconQuaternary)
|
||||
@@ -141,21 +141,15 @@ struct HomeScreenRoomCell: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var hasNewContent: Bool {
|
||||
room.hasUnreadMessages ||
|
||||
room.hasUnreadMentions ||
|
||||
room.hasUnreadNotifications
|
||||
}
|
||||
|
||||
|
||||
private var isHighlighted: Bool {
|
||||
guard !room.isPlaceholder &&
|
||||
room.notificationMode != .mute else {
|
||||
guard !room.isPlaceholder && room.notificationMode != .mute else {
|
||||
return false
|
||||
}
|
||||
return room.hasUnreadNotifications || room.hasUnreadMentions
|
||||
}
|
||||
|
||||
return room.hasUnreadNotifications || room.hasUnreadMentions || room.isMarkedUnread
|
||||
}
|
||||
|
||||
private var mentionIcon: some View {
|
||||
CompoundIcon(\.mention, size: .custom(15), relativeTo: .compound.bodyMD)
|
||||
.accessibilityLabel(L10n.a11yNotificationsMentionsOnly)
|
||||
@@ -223,6 +217,7 @@ struct HomeScreenRoomCell_Previews: PreviewProvider, TestablePreview {
|
||||
return HomeScreenRoom(id: UUID().uuidString,
|
||||
roomId: details.id,
|
||||
name: details.name,
|
||||
isMarkedUnread: details.isMarkedUnread,
|
||||
hasUnreadMessages: details.unreadMessagesCount > 0,
|
||||
hasUnreadMentions: details.unreadMentionsCount > 0,
|
||||
hasUnreadNotifications: details.unreadNotificationsCount > 0,
|
||||
|
||||
@@ -44,8 +44,25 @@ struct HomeScreenRoomList: View {
|
||||
.redacted(reason: .placeholder)
|
||||
} else {
|
||||
let isSelected = context.viewState.selectedRoomID == room.id
|
||||
|
||||
HomeScreenRoomCell(room: room, context: context, isSelected: isSelected)
|
||||
.contextMenu {
|
||||
if context.viewState.markAsUnreadEnabled {
|
||||
if room.hasNewContent {
|
||||
Button {
|
||||
context.send(viewAction: .markRoomAsRead(roomIdentifier: room.id))
|
||||
} label: {
|
||||
Text(L10n.screenRoomlistMarkAsRead)
|
||||
}
|
||||
} else {
|
||||
Button {
|
||||
context.send(viewAction: .markRoomAsUnread(roomIdentifier: room.id))
|
||||
} label: {
|
||||
Text(L10n.screenRoomlistMarkAsUnread)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
context.send(viewAction: .showRoomDetails(roomIdentifier: room.id))
|
||||
} label: {
|
||||
|
||||
Reference in New Issue
Block a user