mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
@@ -31,15 +31,24 @@ class RoomProxy: RoomProxyProtocol {
|
||||
|
||||
private var sendMessageBackgroundTask: BackgroundTaskProtocol?
|
||||
|
||||
private(set) var displayName: String?
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var roomInfoObservationToken: TaskHandle?
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var typingNotificationObservationToken: TaskHandle?
|
||||
|
||||
private var subscribedForUpdates = false
|
||||
|
||||
private(set) var displayName: String?
|
||||
|
||||
private let membersSubject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([])
|
||||
var members: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> {
|
||||
membersSubject.asCurrentValuePublisher()
|
||||
}
|
||||
|
||||
private let typingMembersSubject = CurrentValueSubject<[String], Never>([])
|
||||
var typingMembers: CurrentValuePublisher<[String], Never> {
|
||||
typingMembersSubject.asCurrentValuePublisher()
|
||||
}
|
||||
|
||||
private let actionsSubject = PassthroughSubject<RoomProxyAction, Never>()
|
||||
var actions: AnyPublisher<RoomProxyAction, Never> {
|
||||
@@ -86,6 +95,8 @@ class RoomProxy: RoomProxyProtocol {
|
||||
await timeline.subscribeForUpdates()
|
||||
|
||||
subscribeToRoomStateUpdates()
|
||||
|
||||
subscribeToTypingNotifications()
|
||||
}
|
||||
|
||||
func unsubscribeFromUpdates() {
|
||||
@@ -386,6 +397,18 @@ class RoomProxy: RoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func sendTypingNotification(isTyping: Bool) async -> Result<Void, RoomProxyError> {
|
||||
MXLog.info("Sending typing notification isTyping: \(isTyping)")
|
||||
|
||||
do {
|
||||
try await room.typingNotice(isTyping: isTyping)
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed sending typing notice with error: \(error)")
|
||||
return .failure(.failedSendingTypingNotice)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Element Call
|
||||
|
||||
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||
@@ -409,6 +432,26 @@ class RoomProxy: RoomProxyProtocol {
|
||||
self?.actionsSubject.send(.stateUpdate)
|
||||
})
|
||||
}
|
||||
|
||||
private func subscribeToTypingNotifications() {
|
||||
Task {
|
||||
typingNotificationObservationToken = await room.subscribeToTypingNotifications(listener: RoomTypingNotificationUpdateListener { [weak self] typingUserIDs in
|
||||
guard let self else { return }
|
||||
|
||||
MXLog.info("Received typing notification update, typingUsers: \(typingUserIDs)")
|
||||
|
||||
let typingMembers = typingUserIDs.compactMap { userID in
|
||||
if let member = self.members.value.filter({ $0.userID == userID }).first {
|
||||
return member.displayName ?? member.userID
|
||||
} else {
|
||||
return userID
|
||||
}
|
||||
}
|
||||
|
||||
typingMembersSubject.send(typingMembers)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class RoomInfoUpdateListener: RoomInfoListener {
|
||||
@@ -422,3 +465,15 @@ private final class RoomInfoUpdateListener: RoomInfoListener {
|
||||
onUpdateClosure()
|
||||
}
|
||||
}
|
||||
|
||||
private final class RoomTypingNotificationUpdateListener: TypingNotificationsListener {
|
||||
private let onUpdateClosure: ([String]) -> Void
|
||||
|
||||
init(_ onUpdateClosure: @escaping ([String]) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func call(typingUserIds: [String]) {
|
||||
onUpdateClosure(typingUserIds)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ enum RoomProxyError: Error, Equatable {
|
||||
case failedCheckingPermission
|
||||
case failedMarkingAsRead
|
||||
case failedMarkingAsUnread
|
||||
case failedSendingTypingNotice
|
||||
}
|
||||
|
||||
enum RoomProxyAction {
|
||||
@@ -52,6 +53,7 @@ protocol RoomProxyProtocol {
|
||||
var ownUserID: String { get }
|
||||
|
||||
var name: String? { get }
|
||||
|
||||
var displayName: String? { get }
|
||||
|
||||
var topic: String? { get }
|
||||
@@ -59,6 +61,8 @@ protocol RoomProxyProtocol {
|
||||
var avatarURL: URL? { get }
|
||||
|
||||
var members: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> { get }
|
||||
|
||||
var typingMembers: CurrentValuePublisher<[String], Never> { get }
|
||||
|
||||
var joinedMembersCount: Int { get }
|
||||
|
||||
@@ -108,6 +112,9 @@ protocol RoomProxyProtocol {
|
||||
|
||||
func markAsRead(sendReadReceipts: Bool, 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: - Element Call
|
||||
|
||||
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError>
|
||||
|
||||
@@ -97,7 +97,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
}
|
||||
|
||||
switch await roomProxy.timeline.sendReadReceipt(for: eventID,
|
||||
type: appSettings.sendReadReceiptsEnabled ? .read : .readPrivate) {
|
||||
type: appSettings.sharePresence ? .read : .readPrivate) {
|
||||
case .success:
|
||||
return .success(())
|
||||
case .failure:
|
||||
|
||||
Reference in New Issue
Block a user