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

195 lines
6.7 KiB
Swift

//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import UIKit
import SignalUI
import LibSignalClient
import SignalServiceKit
// MARK: - CallLinkApprovalRequestDetailsSheet
class CallLinkApprovalRequestDetailsSheet: OWSTableSheetViewController {
private struct Deps {
let contactsManager: any ContactManager
let db: any DB
}
private let deps = Deps(
contactsManager: SSKEnvironment.shared.contactManagerRef,
db: DependenciesBridge.shared.db
)
let approvalRequest: CallLinkApprovalRequest
let approvalViewModel: CallLinkApprovalViewModel
override var handleBackgroundColor: UIColor {
UIColor.Signal.transparentSeparator
}
init(
approvalRequest: CallLinkApprovalRequest,
approvalViewModel: CallLinkApprovalViewModel
) {
self.approvalRequest = approvalRequest
self.approvalViewModel = approvalViewModel
super.init()
self.overrideUserInterfaceStyle = .dark
self.tableViewController.forceDarkMode = true
}
private weak var fromViewController: UIViewController?
func present(
from viewController: UIViewController,
dismissalDelegate: (any SheetDismissalDelegate)? = nil,
animated: Bool = true
) {
self.fromViewController = viewController
self.dismissalDelegate = dismissalDelegate
viewController.present(self, animated: animated)
}
// MARK: Table contents
override func updateTableContents(shouldReload: Bool = true) {
let contents = OWSTableContents()
contents.add(.init(
items: [
// TODO: It would be nice to eventually make OWSTableItem's default values not dependent on Theme and instead use dynamic colors
.item(
icon: .checkCircle,
tintColor: UIColor.Signal.label,
name: OWSLocalizedString(
"CALL_LINK_JOIN_REQUEST_APPROVE_BUTTON",
comment: "Button on an action sheet to approve a request to join a call link."
),
textColor: UIColor.Signal.label
) { [weak self] in
guard let self else { return }
self.dismiss(animated: true)
self.approvalViewModel.performRequestAction.send((.approve, self.approvalRequest))
},
.item(
icon: .xCircle,
tintColor: UIColor.Signal.label,
name: OWSLocalizedString(
"CALL_LINK_JOIN_REQUEST_DENY_BUTTON",
comment: "Button on an action sheet to deny a request to join a call link."
),
textColor: UIColor.Signal.label
) { [weak self] in
guard let self else { return }
self.dismiss(animated: true)
self.approvalViewModel.performRequestAction.send((.deny, self.approvalRequest))
},
],
headerView: self.buildHeader()
))
tableViewController.setContents(contents, shouldReload: shouldReload)
}
// MARK: Header
private func buildHeader() -> UIView {
let vStack = UIStackView()
vStack.axis = .vertical
vStack.spacing = 8
vStack.alignment = .center
vStack.isLayoutMarginsRelativeArrangement = true
vStack.layoutMargins = .init(
top: 20,
left: tableViewController.cellHOuterLeftMargin,
bottom: 36,
right: tableViewController.cellHOuterRightMargin
)
// [CallLink] TODO: This should expand to a full-screen preview when tapped
let avatarView = ConversationAvatarView(
sizeClass: .eightyEight,
localUserDisplayMode: .asLocalUser,
badged: true
)
let (contactTitle, mutualThreads): (NSAttributedString, [TSGroupThread]) = self.deps.db.read { tx in
avatarView.update(SDSDB.shimOnlyBridge(tx)) { config in
config.dataSource = .address(self.approvalRequest.address)
}
let isSystemContact = self.deps.contactsManager.fetchSignalAccount(
for: self.approvalRequest.address,
transaction: SDSDB.shimOnlyBridge(tx)
) != nil
let mutualThreads = TSGroupThread.groupThreads(
with: self.approvalRequest.address,
transaction: SDSDB.shimOnlyBridge(tx)
)
.filter(\.isLocalUserFullMember)
.filter(\.shouldThreadBeVisible)
let contactTitle = ConversationHeaderBuilder.threadAttributedString(
threadName: self.approvalRequest.name,
isNoteToSelf: false,
isSystemContact: isSystemContact,
canTap: true,
tx: SDSDB.shimOnlyBridge(tx)
)
return (contactTitle, mutualThreads)
}
vStack.addArrangedSubview(avatarView)
let nameButton = OWSButton { [weak self] in
self?.didTapName()
}
nameButton.dimsWhenHighlighted = true
nameButton.titleLabel?.numberOfLines = 0
nameButton.titleLabel?.textAlignment = .center
nameButton.setAttributedTitle(contactTitle, for: .normal)
vStack.addArrangedSubview(nameButton)
let mutualGroupsLabel = UILabel()
mutualGroupsLabel.text = ProfileDetailLabel.mutualGroupsString(isInGroupContext: false, mutualGroups: mutualThreads)
mutualGroupsLabel.font = .dynamicTypeBody2
mutualGroupsLabel.textColor = UIColor.Signal.secondaryLabel
vStack.addArrangedSubview(mutualGroupsLabel)
return vStack
}
private func didTapName() {
guard let fromViewController else {
owsFailDebug("Parent view controller missing")
return
}
let thread = TSContactThread.getOrCreateThread(contactAddress: approvalRequest.address)
let sheet = ContactAboutSheet(thread: thread, spoilerState: .init())
sheet.overrideUserInterfaceStyle = .dark
self.dismiss(animated: true) {
sheet.present(from: fromViewController, dismissalDelegate: self.dismissalDelegate)
}
}
}
// MARK: - Previews
#if DEBUG
@available(iOS 17.0, *)
#Preview {
SheetPreviewViewController { viewController, animated in
CallLinkApprovalRequestDetailsSheet(
approvalRequest: .init(aci: .init(fromUUID: UUID()), name: "Candice"),
approvalViewModel: CallLinkApprovalViewModel()
)
.present(from: viewController, animated: animated)
}
}
#endif