Handle media previews and invite avatars through the account data (#4142)

* added account data media display policy handling to NSE

* pr suggestions

* update compound

* code improvement
This commit is contained in:
Mauro
2025-05-28 19:51:34 +02:00
committed by GitHub
parent 256292c5a9
commit aef91b5bc9
24 changed files with 626 additions and 61 deletions
@@ -39,6 +39,9 @@ class ClientProxy: ClientProxyProtocol {
// periphery:ignore - required for instance retention in the rust codebase
private var sendQueueListenerTaskHandle: TaskHandle?
// periphery:ignore - required for instance retention in the rust codebase
private var mediaPreviewConfigListenerTaskHandle: TaskHandle?
private var delegateHandle: TaskHandle?
// These following summary providers both operate on the same allRooms() list but
@@ -132,6 +135,16 @@ class ClientProxy: ClientProxyProtocol {
verificationStateSubject.asCurrentValuePublisher()
}
private let timelineMediaVisibilitySubject = CurrentValueSubject<TimelineMediaVisibility, Never>(.always)
var timelineMediaVisibilityPublisher: CurrentValuePublisher<TimelineMediaVisibility, Never> {
timelineMediaVisibilitySubject.asCurrentValuePublisher()
}
private let hideInviteAvatarsSubject = CurrentValueSubject<Bool, Never>(false)
var hideInviteAvatarsPublisher: CurrentValuePublisher<Bool, Never> {
hideInviteAvatarsSubject.asCurrentValuePublisher()
}
var roomsToAwait: Set<String> = []
private let sendQueueStatusSubject = CurrentValueSubject<Bool, Never>(false)
@@ -230,6 +243,10 @@ class ClientProxy: ClientProxyProtocol {
MXLog.error("Failed setting media retention policy with error: \(error)")
}
}
Task {
mediaPreviewConfigListenerTaskHandle = await createMediaPreviewConfigObserver()
}
}
var userID: String {
@@ -724,6 +741,16 @@ class ClientProxy: ClientProxyProtocol {
return .failure(.sdkError(error))
}
}
func fetchMediaPreviewConfiguration() async -> Result<MediaPreviewConfig?, ClientProxyError> {
do {
let config = try await client.fetchMediaPreviewConfig()
return .success(config)
} catch {
MXLog.error("Failed fetching media preview config with error: \(error)")
return .failure(.sdkError(error))
}
}
// MARK: Ignored users
@@ -798,6 +825,28 @@ class ClientProxy: ClientProxyProtocol {
return users.elements
}
// MARK: Moderation & Safety
func setTimelineMediaVisibility(_ value: TimelineMediaVisibility) async -> Result<Void, ClientProxyError> {
do {
try await client.setMediaPreviewDisplayPolicy(policy: value.rustValue)
return .success(())
} catch {
MXLog.error("Failed to set timeline media visibility: \(error)")
return .failure(.sdkError(error))
}
}
func setHideInviteAvatars(_ value: Bool) async -> Result<Void, ClientProxyError> {
do {
try await client.setInviteAvatarsDisplayPolicy(policy: value ? .off : .on)
return .success(())
} catch {
MXLog.error("Failed to set hide invite avatars: \(error)")
return .failure(.sdkError(error))
}
}
// MARK: - Private
private func cacheAccountURL() async {
@@ -867,6 +916,26 @@ class ClientProxy: ClientProxyProtocol {
}
})
}
private func createMediaPreviewConfigObserver() async -> TaskHandle? {
do {
return try await client.subscribeToMediaPreviewConfig(listener: SDKListener { [weak self] config in
guard let self else { return }
if let config {
timelineMediaVisibilitySubject.send(config.mediaPreviewVisibility)
hideInviteAvatarsSubject.send(config.hideInviteAvatars)
} else {
// return default values
timelineMediaVisibilitySubject.send(.always)
hideInviteAvatarsSubject.send(false)
}
})
} catch {
MXLog.error("Failed creating media preview config observer: \(error)")
return nil
}
}
private func createRoomListServiceObserver(_ roomListService: RoomListService) -> TaskHandle {
roomListService.state(listener: SDKListener { [weak self] state in
@@ -1133,3 +1202,38 @@ private struct ClientProxyServices {
self.roomListService = roomListService
}
}
private extension MediaPreviewConfig {
var mediaPreviewVisibility: TimelineMediaVisibility {
switch mediaPreviews {
case .on:
.always
case .private:
.privateOnly
case .off:
.never
}
}
var hideInviteAvatars: Bool {
switch inviteAvatars {
case .off:
true
case .on:
false
}
}
}
private extension TimelineMediaVisibility {
var rustValue: MediaPreviews {
switch self {
case .always:
.on
case .never:
.off
case .privateOnly:
.private
}
}
}