TM-SGNL-iOS/Signal/Calls/CallLinkAdminManager.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

111 lines
4.4 KiB
Swift

//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Combine
import SignalRingRTC
import SignalServiceKit
import SignalUI
@MainActor
class CallLinkAdminManager {
typealias CallLinkState = SignalServiceKit.CallLinkState
private let rootKey: CallLinkRootKey
private let adminPasskey: Data
let callNamePublisher: CurrentValueSubject<String?, Never>
private(set) var callLinkState: CallLinkState?
var didUpdateCallLinkState: (@MainActor (CallLinkState) -> Void)?
init(rootKey: CallLinkRootKey, adminPasskey: Data, callLinkState: CallLinkState?) {
self.rootKey = rootKey
self.adminPasskey = adminPasskey
self.callLinkState = callLinkState
self.callNamePublisher = .init(callLinkState?.name)
}
// MARK: Convenience properties
var editCallNameButtonTitle: String {
callLinkState?.name != nil ? CallStrings.editCallName : CallStrings.addCallName
}
// MARK: Actions
func updateName(_ name: String) async throws {
try await updateCallLink(
{ callLinkManager, authCredential in
return try await callLinkManager.updateCallLinkName(
name,
rootKey: self.rootKey,
adminPasskey: self.adminPasskey,
authCredential: authCredential
)
}
)
}
func toggleApproveAllMembersWithActivityIndicator(
_ sender: UISwitch,
from viewController: UIViewController
) {
let isOn = sender.isOn
ModalActivityIndicatorViewController.present(
fromViewController: viewController,
presentationDelay: 0.25,
asyncBlock: { modal in
let updateResult = await Result {
try await self.updateCallLink { callLinkManager, authCredential in
return try await callLinkManager.updateCallLinkRestrictions(
requiresAdminApproval: isOn,
rootKey: self.rootKey,
adminPasskey: self.adminPasskey,
authCredential: authCredential
)
}
}
modal.dismissIfNotCanceled {
do {
_ = try updateResult.get()
} catch {
if error.isNetworkFailureOrTimeout {
// [CallLink] TODO: Refresh switch UI, as we don't know whether the operation succeeded or failed.
} else {
Logger.warn("Call link approve members switch update failed with error \(error)")
// The operation definitely failed. Revert switch state.
sender.isOn = !isOn
OWSActionSheets.showActionSheet(
title: CallStrings.callLinkErrorSheetTitle,
message: CallStrings.callLinkUpdateErrorSheetDescription,
fromViewController: viewController
)
}
}
}
}
)
}
// MARK: Private
private func updateCallLink(
_ performUpdate: (CallLinkManager, SignalServiceKit.CallLinkAuthCredential) async throws -> CallLinkState
) async throws {
let callLinkManager = AppEnvironment.shared.callService.callLinkManager
let callLinkStateUpdater = AppEnvironment.shared.callService.callLinkStateUpdater
let databaseStorage = SSKEnvironment.shared.databaseStorageRef
_ = try await callLinkStateUpdater.updateExclusively(rootKey: rootKey) { authCredential in
let callLinkState = try await performUpdate(callLinkManager, authCredential)
await databaseStorage.awaitableWrite { [rootKey, adminPasskey] tx in
CallLinkUpdateMessageSender(
messageSenderJobQueue: SSKEnvironment.shared.messageSenderJobQueueRef
).sendCallLinkUpdateMessage(rootKey: rootKey, adminPasskey: adminPasskey, tx: tx)
}
self.callLinkState = callLinkState
self.didUpdateCallLinkState?(callLinkState)
self.callNamePublisher.send(callLinkState.name)
return callLinkState
}
}
}