Fixes #2320 - Implement support for (un)marking rooms as favourite from the room list and room detail screens

This commit is contained in:
Stefan Ceriu
2024-02-19 15:13:15 +02:00
parent 3887403150
commit 6d9271ce59
60 changed files with 372 additions and 179 deletions
+43 -27
View File
@@ -94,7 +94,7 @@ class RoomProxy: RoomProxyProtocol {
await timeline.subscribeForUpdates()
subscribeToRoomStateUpdates()
subscribeToRoomInfoUpdates()
subscribeToTypingNotifications()
}
@@ -133,6 +133,12 @@ class RoomProxy: RoomProxyProtocol {
(try? room.isEncrypted()) ?? false
}
var isFavourite: Bool {
get async {
await (try? room.roomInfo().isFavourite) ?? false
}
}
var hasOngoingCall: Bool {
room.hasActiveRoomCall()
}
@@ -367,31 +373,7 @@ class RoomProxy: RoomProxyProtocol {
return .failure(.failedCheckingPermission)
}
}
func flagAsUnread() async -> Result<Void, RoomProxyError> {
MXLog.info("Flagging room \(id) as unread")
do {
try await room.setUnreadFlag(newValue: true)
return .success(())
} catch {
MXLog.error("Failed marking room \(id) as unread with error: \(error)")
return .failure(.failedFlaggingAsUnread)
}
}
func flagAsRead() async -> Result<Void, RoomProxyError> {
MXLog.info("Flagging room \(id) as read")
do {
try await room.setUnreadFlag(newValue: false)
return .success(())
} catch {
MXLog.error("Failed marking room \(id) as read with error: \(error)")
return .failure(.failedFlaggingAsRead)
}
}
func markAsRead(receiptType: ReceiptType) async -> Result<Void, RoomProxyError> {
do {
try await room.markAsRead(receiptType: receiptType)
@@ -414,6 +396,40 @@ class RoomProxy: RoomProxyProtocol {
}
}
// MARK: - Room flags
func flagAsUnread(_ isUnread: Bool) async -> Result<Void, RoomProxyError> {
MXLog.info("Flagging room \(id) as unread: \(isUnread)")
do {
try await room.setUnreadFlag(newValue: isUnread)
return .success(())
} catch {
MXLog.error("Failed marking room \(id) as unread: \(isUnread) with error: \(error)")
return .failure(.failedFlaggingAsUnread)
}
}
func getIsFavourite() async -> Result<Bool, RoomProxyError> {
do {
let result = try await room.roomInfo().isFavourite
return .success(result)
} catch {
MXLog.error("Failed retrieving isFavourite for room: \(id) with error: \(error)")
return .failure(.failedRetrievingIsFavourite)
}
}
func flagAsFavourite(_ isFavourite: Bool) async -> Result<Void, RoomProxyError> {
do {
try await room.setIsFavourite(isFavourite: isFavourite, tagOrder: nil)
return .success(())
} catch {
MXLog.error("Failed flagging room \(id) as favourite with error: \(error)")
return .failure(.failedFlaggingAsFavourite)
}
}
// MARK: - Element Call
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError> {
@@ -431,10 +447,10 @@ class RoomProxy: RoomProxyProtocol {
// MARK: - Private
private func subscribeToRoomStateUpdates() {
private func subscribeToRoomInfoUpdates() {
roomInfoObservationToken = room.subscribeToRoomInfoUpdates(listener: RoomInfoUpdateListener { [weak self] in
MXLog.info("Received room info update")
self?.actionsSubject.send(.stateUpdate)
self?.actionsSubject.send(.roomInfoUpdate)
})
}
@@ -32,13 +32,14 @@ enum RoomProxyError: Error, Equatable {
case failedUploadingAvatar
case failedCheckingPermission
case failedFlaggingAsUnread
case failedFlaggingAsRead
case failedMarkingAsRead
case failedSendingTypingNotice
case failedRetrievingIsFavourite
case failedFlaggingAsFavourite
}
enum RoomProxyAction {
case stateUpdate
case roomInfoUpdate
}
// sourcery: AutoMockable
@@ -48,6 +49,7 @@ protocol RoomProxyProtocol {
var isPublic: Bool { get }
var isSpace: Bool { get }
var isEncrypted: Bool { get }
var isFavourite: Bool { get async }
var membership: Membership { get }
var hasOngoingCall: Bool { get }
var canonicalAlias: String? { get }
@@ -109,15 +111,17 @@ protocol RoomProxyProtocol {
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError>
func flagAsUnread() async -> Result<Void, RoomProxyError>
func flagAsRead() async -> Result<Void, RoomProxyError>
func markAsRead(receiptType: ReceiptType) async -> Result<Void, RoomProxyError>
/// https://spec.matrix.org/v1.9/client-server-api/#typing-notifications
@discardableResult func sendTypingNotification(isTyping: Bool) async -> Result<Void, RoomProxyError>
// MARK: - Room Flags
func flagAsUnread(_ isUnread: Bool) async -> Result<Void, RoomProxyError>
func flagAsFavourite(_ isFavourite: Bool) async -> Result<Void, RoomProxyError>
// MARK: - Element Call
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError>
@@ -83,98 +83,105 @@ extension Array where Element == RoomSummary {
avatarURL: nil,
lastMessage: AttributedString("I do not wish to take the trouble to understand mysticism"),
lastMessageFormattedTimestamp: "14:56",
isMarkedUnread: false,
unreadMessagesCount: 0,
unreadMentionsCount: 0,
unreadNotificationsCount: 0,
notificationMode: .allMessages,
canonicalAlias: nil,
inviter: nil,
hasOngoingCall: false)),
hasOngoingCall: false,
isMarkedUnread: false,
isFavourite: false)),
.filled(details: RoomSummaryDetails(id: "2",
name: "Foundation and Empire",
isDirect: true,
avatarURL: URL.picturesDirectory,
lastMessage: AttributedString("How do you see the Emperor then? You think he keeps office hours?"),
lastMessageFormattedTimestamp: "2:56 PM",
isMarkedUnread: false,
unreadMessagesCount: 2,
unreadMentionsCount: 0,
unreadNotificationsCount: 2,
notificationMode: .mute,
canonicalAlias: nil,
inviter: nil,
hasOngoingCall: false)),
hasOngoingCall: false,
isMarkedUnread: false,
isFavourite: false)),
.filled(details: RoomSummaryDetails(id: "3",
name: "Second Foundation",
isDirect: true,
avatarURL: nil,
lastMessage: try? AttributedString(markdown: "He certainly seemed no *mental genius* to me"),
lastMessageFormattedTimestamp: "Some time ago",
isMarkedUnread: false,
unreadMessagesCount: 3,
unreadMentionsCount: 0,
unreadNotificationsCount: 0,
notificationMode: .mentionsAndKeywordsOnly,
canonicalAlias: nil,
inviter: nil,
hasOngoingCall: false)),
hasOngoingCall: false,
isMarkedUnread: false,
isFavourite: false)),
.filled(details: RoomSummaryDetails(id: "4",
name: "Foundation's Edge",
isDirect: true,
avatarURL: nil,
lastMessage: AttributedString("There's an archaic measure of time that's called the month"),
lastMessageFormattedTimestamp: "Just now",
isMarkedUnread: false,
unreadMessagesCount: 2,
unreadMentionsCount: 2,
unreadNotificationsCount: 2,
notificationMode: .allMessages,
canonicalAlias: nil,
inviter: nil,
hasOngoingCall: false)),
hasOngoingCall: false,
isMarkedUnread: false,
isFavourite: false)),
.filled(details: RoomSummaryDetails(id: "5",
name: "Foundation and Earth",
isDirect: true,
avatarURL: nil,
lastMessage: AttributedString("Clearly, if Earth is powerful enough to do that, it might also be capable of adjusting minds in order to force belief in its radioactivity"),
lastMessageFormattedTimestamp: "1986",
isMarkedUnread: false,
unreadMessagesCount: 1,
unreadMentionsCount: 1,
unreadNotificationsCount: 1,
notificationMode: .allMessages,
canonicalAlias: nil,
inviter: nil,
hasOngoingCall: true)),
hasOngoingCall: true,
isMarkedUnread: false,
isFavourite: false)),
.filled(details: RoomSummaryDetails(id: "6",
name: "Prelude to Foundation",
isDirect: true,
avatarURL: nil,
lastMessage: AttributedString("Are you groping for the word 'paranoia'?"),
lastMessageFormattedTimestamp: "きょうはじゅういちがつじゅういちにちです",
isMarkedUnread: false,
unreadMessagesCount: 6,
unreadMentionsCount: 0,
unreadNotificationsCount: 0,
notificationMode: .mute,
canonicalAlias: nil,
inviter: nil,
hasOngoingCall: true)),
hasOngoingCall: true,
isMarkedUnread: false,
isFavourite: false)),
.filled(details: RoomSummaryDetails(id: "0",
name: "Unknown",
isDirect: false,
avatarURL: nil,
lastMessage: nil,
lastMessageFormattedTimestamp: nil,
isMarkedUnread: false,
unreadMessagesCount: 0,
unreadMentionsCount: 0,
unreadNotificationsCount: 0,
notificationMode: nil,
canonicalAlias: nil,
inviter: nil,
hasOngoingCall: false)),
hasOngoingCall: false,
isMarkedUnread: false,
isFavourite: false)),
.empty
]
@@ -213,27 +220,29 @@ extension Array where Element == RoomSummary {
avatarURL: URL.picturesDirectory,
lastMessage: nil,
lastMessageFormattedTimestamp: nil,
isMarkedUnread: false,
unreadMessagesCount: 0,
unreadMentionsCount: 0,
unreadNotificationsCount: 0,
notificationMode: nil,
canonicalAlias: "#footest:somewhere.org",
inviter: RoomMemberProxyMock.mockCharlie,
hasOngoingCall: false)),
hasOngoingCall: false,
isMarkedUnread: false,
isFavourite: false)),
.filled(details: RoomSummaryDetails(id: "someAwesomeRoomId2",
name: "Second room",
isDirect: true,
avatarURL: nil,
lastMessage: nil,
lastMessageFormattedTimestamp: nil,
isMarkedUnread: false,
unreadMessagesCount: 0,
unreadMentionsCount: 0,
unreadNotificationsCount: 0,
notificationMode: nil,
canonicalAlias: nil,
inviter: RoomMemberProxyMock.mockCharlie,
hasOngoingCall: false))
hasOngoingCall: false,
isMarkedUnread: false,
isFavourite: false))
]
}
@@ -24,7 +24,6 @@ struct RoomSummaryDetails {
let avatarURL: URL?
let lastMessage: AttributedString?
let lastMessageFormattedTimestamp: String?
let isMarkedUnread: Bool
let unreadMessagesCount: UInt
let unreadMentionsCount: UInt
let unreadNotificationsCount: UInt
@@ -33,6 +32,9 @@ struct RoomSummaryDetails {
let inviter: RoomMemberProxyProtocol?
let hasOngoingCall: Bool
let isMarkedUnread: Bool
let isFavourite: Bool
var hasUnreadMessages: Bool { unreadMessagesCount > 0 }
var hasUnreadMentions: Bool { unreadMentionsCount > 0 }
var hasUnreadNotifications: Bool { unreadNotificationsCount > 0 }
@@ -60,7 +62,6 @@ extension RoomSummaryDetails {
avatarURL = nil
lastMessage = AttributedString(string)
lastMessageFormattedTimestamp = "Now"
isMarkedUnread = false
unreadMessagesCount = hasUnreadMessages ? 1 : 0
unreadMentionsCount = hasUnreadMentions ? 1 : 0
unreadNotificationsCount = hasUnreadNotifications ? 1 : 0
@@ -68,5 +69,8 @@ extension RoomSummaryDetails {
canonicalAlias = nil
inviter = nil
hasOngoingCall = false
isMarkedUnread = false
isFavourite = false
}
}
@@ -252,14 +252,15 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
avatarURL: roomInfo.avatarUrl.flatMap(URL.init(string:)),
lastMessage: attributedLastMessage,
lastMessageFormattedTimestamp: lastMessageFormattedTimestamp,
isMarkedUnread: appSettings.markAsUnreadEnabled ? roomInfo.isMarkedUnread : false,
unreadMessagesCount: appSettings.mentionsBadgeEnabled ? UInt(roomInfo.numUnreadMessages) : 0,
unreadMentionsCount: appSettings.mentionsBadgeEnabled ? UInt(roomInfo.numUnreadMentions) : 0,
unreadNotificationsCount: appSettings.mentionsBadgeEnabled ? UInt(roomInfo.numUnreadNotifications) : UInt(roomInfo.notificationCount),
notificationMode: notificationMode,
canonicalAlias: roomInfo.canonicalAlias,
inviter: inviterProxy,
hasOngoingCall: roomInfo.hasRoomCall)
hasOngoingCall: roomInfo.hasRoomCall,
isMarkedUnread: appSettings.markAsUnreadEnabled ? roomInfo.isMarkedUnread : false,
isFavourite: roomInfo.isFavourite)
return invalidated ? .invalidated(details: details) : .filled(details: details)
}