mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-19 08:03:50 +02:00
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import MatrixSDK
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
class RoomUpgradeService: RoomUpgradeServiceProtocol {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
|
||||
private let versionOverride: String
|
||||
private var currentOperation: MXHTTPOperation?
|
||||
private var didBuildSpaceGraphObserver: Any?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
private(set) var upgradingSubject: CurrentValueSubject<Bool, Never>
|
||||
private(set) var errorSubject: CurrentValueSubject<Error?, Never>
|
||||
private(set) var currentRoomId: String
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession, roomId: String, versionOverride: String) {
|
||||
self.session = session
|
||||
self.currentRoomId = roomId
|
||||
self.versionOverride = versionOverride
|
||||
self.upgradingSubject = CurrentValueSubject(false)
|
||||
self.errorSubject = CurrentValueSubject(nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
currentOperation?.cancel()
|
||||
if let observer = self.didBuildSpaceGraphObserver {
|
||||
NotificationCenter.default.removeObserver(observer)
|
||||
}
|
||||
}
|
||||
|
||||
func upgradeRoom(autoInviteUsers: Bool, completion: @escaping (Bool, String) -> Void) {
|
||||
upgradingSubject.send(true)
|
||||
|
||||
if autoInviteUsers, let room = session.room(withRoomId: self.currentRoomId) {
|
||||
self.currentOperation = room.members { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
switch response {
|
||||
case .success(let members):
|
||||
let memberIds: [String] = members?.members.compactMap({ member in
|
||||
guard member.membership == .join, member.userId != self.session.myUserId else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return member.userId
|
||||
}) ?? []
|
||||
self.upgradeRoom(to: self.versionOverride, inviteUsers: memberIds, completion: completion)
|
||||
case .failure(let error):
|
||||
self.upgradingSubject.send(false)
|
||||
self.errorSubject.send(error)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.upgradeRoom(to: versionOverride, inviteUsers: [], completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func upgradeRoom(to versionOverride: String, inviteUsers userIds: [String], completion: @escaping (Bool, String) -> Void) {
|
||||
// Need to disable graph update during this process as a lot of syncs will occure
|
||||
session.spaceService.graphUpdateEnabled = false
|
||||
currentOperation = session.matrixRestClient.upgradeRoom(withId: self.currentRoomId, to: versionOverride) { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch response {
|
||||
case .success(let replacementRoomId):
|
||||
let oldRoomId = self.currentRoomId
|
||||
self.currentRoomId = replacementRoomId
|
||||
let parentSpaces = self.session.spaceService.directParentIds(ofRoomWithId: oldRoomId)
|
||||
self.moveRoom(from: oldRoomId, to: replacementRoomId, within: Array(parentSpaces), at: 0) {
|
||||
self.session.spaceService.graphUpdateEnabled = true
|
||||
self.didBuildSpaceGraphObserver = NotificationCenter.default.addObserver(forName: MXSpaceService.didBuildSpaceGraph, object: nil, queue: OperationQueue.main) { [weak self] notification in
|
||||
guard let self = self else { return }
|
||||
|
||||
if let observer = self.didBuildSpaceGraphObserver {
|
||||
NotificationCenter.default.removeObserver(observer)
|
||||
self.didBuildSpaceGraphObserver = nil
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.inviteUser(from: userIds, at: 0, completion: completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
self.session.spaceService.graphUpdateEnabled = true
|
||||
self.upgradingSubject.send(false)
|
||||
self.errorSubject.send(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Move room with roomId to new room ID for each space which ID belongs to`parentIds` list.
|
||||
/// Recurse to the next index once done.
|
||||
private func moveRoom(from roomId: String, to newRoomId: String, within parentIds: [String], at index: Int, completion: @escaping () -> Void) {
|
||||
guard index < parentIds.count else {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
|
||||
guard let space = session.spaceService.getSpace(withId: parentIds[index]) else {
|
||||
MXLog.warning("[RoomUpgradeService] moveRoom \(roomId) to \(newRoomId) within \(parentIds[index]): space not found")
|
||||
moveRoom(from: roomId, to: newRoomId, within: parentIds, at: index + 1, completion: completion)
|
||||
return
|
||||
}
|
||||
|
||||
space.moveChild(withRoomId: roomId, to: newRoomId) { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
|
||||
if let error = response.error {
|
||||
MXLog.warning("[RoomUpgradeService] moveRoom \(roomId) to \(newRoomId) within \(space.spaceId): failed due to error: \(error)")
|
||||
}
|
||||
|
||||
self.moveRoom(from: roomId, to: newRoomId, within: parentIds, at: index + 1, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
/// Invite all users within `userIds` list
|
||||
/// Recurse to the next index once done.
|
||||
private func inviteUser(from userIds: [String], at index: Int, completion: @escaping (Bool, String) -> Void) {
|
||||
guard index < userIds.count else {
|
||||
self.upgradingSubject.send(false)
|
||||
completion(true, currentRoomId)
|
||||
return
|
||||
}
|
||||
|
||||
currentOperation = session.matrixRestClient.invite(.userId(userIds[index]), toRoom: currentRoomId) { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.currentOperation = nil
|
||||
if let error = response.error {
|
||||
MXLog.warning("[RoomUpgradeService] inviteUser: failed to invite \(userIds[index]) to \(self.currentRoomId) due to error: \(error)")
|
||||
}
|
||||
|
||||
self.inviteUser(from: userIds, at: index + 1, completion: completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user