mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Update the SDK and use RoomHero.status and subscribeToOwnProfile. (#5905)
* Update the SDK and hook up the status from Room Heroes. Also start requesting profiles via sss when the feature flag is enabled. * Add support for subscribing to your own profile.
This commit is contained in:
@@ -32,6 +32,9 @@ class ClientProxy: ClientProxyProtocol {
|
||||
// periphery: ignore - only for retain
|
||||
private var syncServiceStateUpdateTaskHandle: TaskHandle?
|
||||
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var userProfileListenerTaskHandle: TaskHandle?
|
||||
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var ignoredUsersListenerTaskHandle: TaskHandle?
|
||||
|
||||
@@ -278,9 +281,13 @@ class ClientProxy: ClientProxyProtocol {
|
||||
|
||||
try await client.setUtdDelegate(utdDelegate: ClientDecryptionErrorDelegate(actionsSubject: actionsSubject))
|
||||
|
||||
loadUserAvatarURLFromCache()
|
||||
let canSubscribeToUserProfile = appSettings.userStatusEnabled // TODO: @pixlwave to add a /versions check too.
|
||||
|
||||
await setupSubscriptions()
|
||||
if !canSubscribeToUserProfile {
|
||||
loadUserAvatarURLFromCache()
|
||||
}
|
||||
|
||||
await setupSubscriptions(canSubscribeToUserProfile: canSubscribeToUserProfile)
|
||||
|
||||
Task {
|
||||
do {
|
||||
@@ -686,14 +693,18 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func loadUserProfile() async -> Result<Void, ClientProxyError> {
|
||||
func loadUserProfileIfNeeded() async -> Result<Void, ClientProxyError> {
|
||||
// There's no need to load the profile if we're subscribed to it via /sync
|
||||
guard userProfileListenerTaskHandle == nil else { return .success(()) }
|
||||
|
||||
do {
|
||||
async let displayName = client.displayName()
|
||||
async let avatarURLString = client.avatarUrl()
|
||||
|
||||
let profile = try await UserProfile(userID: userID,
|
||||
displayName: displayName,
|
||||
avatarURL: avatarURLString.flatMap(URL.init))
|
||||
avatarURL: avatarURLString.flatMap(URL.init),
|
||||
status: userProfileSubject.value.status)
|
||||
loadCachedAvatarURLTask?.cancel()
|
||||
userProfileSubject.send(profile)
|
||||
return .success(())
|
||||
@@ -706,7 +717,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
func setUserDisplayName(_ name: String) async -> Result<Void, ClientProxyError> {
|
||||
do {
|
||||
try await client.setDisplayName(name: name)
|
||||
Task { await self.loadUserProfile() }
|
||||
Task { await self.loadUserProfileIfNeeded() }
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed setting user display name with error: \(error)")
|
||||
@@ -723,7 +734,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
do {
|
||||
let data = try Data(contentsOf: imageURL)
|
||||
try await client.uploadAvatar(mimeType: mimeType, data: data)
|
||||
Task { await self.loadUserProfile() }
|
||||
Task { await self.loadUserProfileIfNeeded() }
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed setting user avatar with error: \(error)")
|
||||
@@ -734,7 +745,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
func removeUserAvatar() async -> Result<Void, ClientProxyError> {
|
||||
do {
|
||||
try await client.removeAvatar()
|
||||
Task { await self.loadUserProfile() }
|
||||
Task { await self.loadUserProfileIfNeeded() }
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed removing user avatar with error: \(error)")
|
||||
@@ -746,7 +757,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
func setUserStatus(_ status: UserStatus.Raw) async -> Result<Void, ClientProxyError> {
|
||||
do {
|
||||
try await client.setUserStatus(status: status.rustValue)
|
||||
Task { await self.loadUserProfile() }
|
||||
// No need to refresh the profile, we only support user status with the profiles /sync extension.
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed setting user status with error: \(error)")
|
||||
@@ -758,7 +769,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
func removeUserStatus() async -> Result<Void, ClientProxyError> {
|
||||
do {
|
||||
try await client.clearUserStatus()
|
||||
Task { await self.loadUserProfile() }
|
||||
Task { await self.loadUserProfileIfNeeded() }
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed removing user status with error: \(error)")
|
||||
@@ -1017,7 +1028,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupSubscriptions() async {
|
||||
private func setupSubscriptions(canSubscribeToUserProfile: Bool) async {
|
||||
networkMonitor.reachabilityPublisher
|
||||
.removeDuplicates()
|
||||
.receive(on: DispatchQueue.main)
|
||||
@@ -1030,6 +1041,12 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
if canSubscribeToUserProfile {
|
||||
userProfileListenerTaskHandle = try? client.subscribeToOwnProfile(listener: SDKListener.onMainActor { [weak self] profile in
|
||||
self?.userProfileSubject.send(.init(rustUserProfile: profile))
|
||||
})
|
||||
}
|
||||
|
||||
ignoredUsersListenerTaskHandle = client.subscribeToIgnoredUsers(listener: SDKListener.onMainActor { [weak self] ignoredUsers in
|
||||
self?.ignoredUsersSubject.send(ignoredUsers)
|
||||
})
|
||||
@@ -1201,7 +1218,8 @@ class ClientProxy: ClientProxyProtocol {
|
||||
let profile = self.userProfileSubject.value
|
||||
self.userProfileSubject.value = UserProfile(userID: profile.id,
|
||||
displayName: profile.displayName,
|
||||
avatarURL: urlString.flatMap(URL.init))
|
||||
avatarURL: urlString.flatMap(URL.init),
|
||||
status: profile.status)
|
||||
} catch {
|
||||
MXLog.error("Failed to look for the avatar url in the cache: \(error)")
|
||||
}
|
||||
@@ -1481,11 +1499,14 @@ private struct ClientProxyServices {
|
||||
init(client: ClientProtocol,
|
||||
notificationSettings: NotificationSettingsProxyProtocol,
|
||||
appSettings: AppSettings) async throws {
|
||||
let syncService = try await client
|
||||
var syncServiceBuilder = client
|
||||
.syncService()
|
||||
.withOfflineMode()
|
||||
.withSharePos(enable: true)
|
||||
.finish()
|
||||
if appSettings.userStatusEnabled {
|
||||
syncServiceBuilder = syncServiceBuilder.withProfilesExtension()
|
||||
}
|
||||
let syncService = try await syncServiceBuilder.finish()
|
||||
|
||||
let roomListService = syncService.roomListService()
|
||||
|
||||
|
||||
@@ -212,7 +212,11 @@ protocol ClientProxyProtocol: AnyObject {
|
||||
/// Will only work for rooms that are in our room list/local store
|
||||
func reportRoomForIdentifier(_ identifier: String, reason: String) async -> Result<Void, ClientProxyError>
|
||||
|
||||
@discardableResult func loadUserProfile() async -> Result<Void, ClientProxyError>
|
||||
/// Loads the user's own profile when the server doesn't support MSC4262 and both returns the profile
|
||||
/// as well as publishing it via ``userProfilePublisher``.
|
||||
///
|
||||
/// When the server does support the MSC, then the client automatically publishes profile and keeps it up to date.
|
||||
@discardableResult func loadUserProfileIfNeeded() async -> Result<Void, ClientProxyError>
|
||||
func setUserDisplayName(_ name: String) async -> Result<Void, ClientProxyError>
|
||||
func setUserAvatar(media: MediaInfo) async -> Result<Void, ClientProxyError>
|
||||
func removeUserAvatar() async -> Result<Void, ClientProxyError>
|
||||
|
||||
Reference in New Issue
Block a user