SimpleX-Chat/apps/ios/Shared/Views/Helpers/ShareSheet.swift

317 lines
13 KiB
Swift
Raw Normal View History

//
// ShareSheet.swift
// SimpleX
//
// Created by Evgeny Poberezkin on 30/01/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
ios: new user picker (#4821) * ios: new user picker (#4770) * current user picker progress * one hand picker * thin bullet icon * more user picker buttons * button clickable areas * divider padding * extra space after sun * send current user option to address view * add unread count badge * with anim for apperance close * edit current profile from picker * remove you section from settings * remove help and support * simplify * move settings and sun to same row * remove redundant vstack * long press on sun/moon switches to system setting * remove back button from migrate device * smooth profile transitions * close user picker on list profiles * fix dismiss on migrate from device * fix dismiss when deleting last visible user while having hidden users * picker visibility toggle tweaks * remove strange square from profile switcher click * dirty way to save auto accept settings on dismiss * Revert "dirty way to save auto accept settings on dismiss" This reverts commit e7b19ee8aa185b767941d12d5d4534d81f9ea6f5. * consistent animation on user picker toggle * change space between profiles * remove result * ignore result * unread badge * move to sheet * half sheet on one hand ui * fix dismiss on device migration * fix desktop connect * sun to meet other action icons * fill bullet list button * fix tap in settings to take full width * icon sizings and paddings * open settings in same sheet * apply same trick as other buttons for ligth toggle * layout * open profiles sheet large when +3 users * layout * layout * paddings * paddings * remove show progress * always small user picker * fixed height * open all actions as sheets * type, color * simpler and more effective way of avoid moving around on user select * dismiss user profiles sheet on user change * connect desktop back button remove * remove back buttons from user address view * remove porgress * header inside list * alert on auto accept unsaved changes * Cancel -> Discard * revert * fix connect to desktop * remove extra space * fix share inside multi sheet * user picker and options as separate sheet * revert showShareSheet * fix current profile and all profiles selection * change alert * update * cleanup user address * remove func * alert on unsaved changes in chat prefs * fix layout * cleanup --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> * ios: fix switching profiles (#4822) * ios: different user picker layout (#4826) * ios: different user picker layout * remove section * layout, color * color * remove activeUser * fix gradient * recursive sheets * gradient padding * share sheet * layout * dismiss sheets --------- Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> * ios: use the same way to share from all sheets (#4829) * ios: close user picker before opening other sheets * Revert "share sheet" This reverts commit 006415582515f85fb6f634c7727e74295d4447ad. * dismiss/show via callback * Revert "ios: close user picker before opening other sheets" This reverts commit 19110398f8b566d3e925b91074c3c19d97b35f17. * ios: show alerts from sheets (#4839) * padding * remove gradient * cleanup * simplify settings * padding --------- Co-authored-by: Diogo <diogofncunha@gmail.com> Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-09-10 09:31:53 +01:00
func getTopViewController() -> UIViewController? {
let keyWindowScene = UIApplication.shared.connectedScenes.first { $0.activationState == .foregroundActive } as? UIWindowScene
if let keyWindow = keyWindowScene?.windows.filter(\.isKeyWindow).first,
ios: new user picker (#4821) * ios: new user picker (#4770) * current user picker progress * one hand picker * thin bullet icon * more user picker buttons * button clickable areas * divider padding * extra space after sun * send current user option to address view * add unread count badge * with anim for apperance close * edit current profile from picker * remove you section from settings * remove help and support * simplify * move settings and sun to same row * remove redundant vstack * long press on sun/moon switches to system setting * remove back button from migrate device * smooth profile transitions * close user picker on list profiles * fix dismiss on migrate from device * fix dismiss when deleting last visible user while having hidden users * picker visibility toggle tweaks * remove strange square from profile switcher click * dirty way to save auto accept settings on dismiss * Revert "dirty way to save auto accept settings on dismiss" This reverts commit e7b19ee8aa185b767941d12d5d4534d81f9ea6f5. * consistent animation on user picker toggle * change space between profiles * remove result * ignore result * unread badge * move to sheet * half sheet on one hand ui * fix dismiss on device migration * fix desktop connect * sun to meet other action icons * fill bullet list button * fix tap in settings to take full width * icon sizings and paddings * open settings in same sheet * apply same trick as other buttons for ligth toggle * layout * open profiles sheet large when +3 users * layout * layout * paddings * paddings * remove show progress * always small user picker * fixed height * open all actions as sheets * type, color * simpler and more effective way of avoid moving around on user select * dismiss user profiles sheet on user change * connect desktop back button remove * remove back buttons from user address view * remove porgress * header inside list * alert on auto accept unsaved changes * Cancel -> Discard * revert * fix connect to desktop * remove extra space * fix share inside multi sheet * user picker and options as separate sheet * revert showShareSheet * fix current profile and all profiles selection * change alert * update * cleanup user address * remove func * alert on unsaved changes in chat prefs * fix layout * cleanup --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> * ios: fix switching profiles (#4822) * ios: different user picker layout (#4826) * ios: different user picker layout * remove section * layout, color * color * remove activeUser * fix gradient * recursive sheets * gradient padding * share sheet * layout * dismiss sheets --------- Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> * ios: use the same way to share from all sheets (#4829) * ios: close user picker before opening other sheets * Revert "share sheet" This reverts commit 006415582515f85fb6f634c7727e74295d4447ad. * dismiss/show via callback * Revert "ios: close user picker before opening other sheets" This reverts commit 19110398f8b566d3e925b91074c3c19d97b35f17. * ios: show alerts from sheets (#4839) * padding * remove gradient * cleanup * simplify settings * padding --------- Co-authored-by: Diogo <diogofncunha@gmail.com> Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-09-10 09:31:53 +01:00
let rootViewController = keyWindow.rootViewController {
// Find the top-most presented view controller
var topController = rootViewController
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
ios: new user picker (#4821) * ios: new user picker (#4770) * current user picker progress * one hand picker * thin bullet icon * more user picker buttons * button clickable areas * divider padding * extra space after sun * send current user option to address view * add unread count badge * with anim for apperance close * edit current profile from picker * remove you section from settings * remove help and support * simplify * move settings and sun to same row * remove redundant vstack * long press on sun/moon switches to system setting * remove back button from migrate device * smooth profile transitions * close user picker on list profiles * fix dismiss on migrate from device * fix dismiss when deleting last visible user while having hidden users * picker visibility toggle tweaks * remove strange square from profile switcher click * dirty way to save auto accept settings on dismiss * Revert "dirty way to save auto accept settings on dismiss" This reverts commit e7b19ee8aa185b767941d12d5d4534d81f9ea6f5. * consistent animation on user picker toggle * change space between profiles * remove result * ignore result * unread badge * move to sheet * half sheet on one hand ui * fix dismiss on device migration * fix desktop connect * sun to meet other action icons * fill bullet list button * fix tap in settings to take full width * icon sizings and paddings * open settings in same sheet * apply same trick as other buttons for ligth toggle * layout * open profiles sheet large when +3 users * layout * layout * paddings * paddings * remove show progress * always small user picker * fixed height * open all actions as sheets * type, color * simpler and more effective way of avoid moving around on user select * dismiss user profiles sheet on user change * connect desktop back button remove * remove back buttons from user address view * remove porgress * header inside list * alert on auto accept unsaved changes * Cancel -> Discard * revert * fix connect to desktop * remove extra space * fix share inside multi sheet * user picker and options as separate sheet * revert showShareSheet * fix current profile and all profiles selection * change alert * update * cleanup user address * remove func * alert on unsaved changes in chat prefs * fix layout * cleanup --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> * ios: fix switching profiles (#4822) * ios: different user picker layout (#4826) * ios: different user picker layout * remove section * layout, color * color * remove activeUser * fix gradient * recursive sheets * gradient padding * share sheet * layout * dismiss sheets --------- Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> * ios: use the same way to share from all sheets (#4829) * ios: close user picker before opening other sheets * Revert "share sheet" This reverts commit 006415582515f85fb6f634c7727e74295d4447ad. * dismiss/show via callback * Revert "ios: close user picker before opening other sheets" This reverts commit 19110398f8b566d3e925b91074c3c19d97b35f17. * ios: show alerts from sheets (#4839) * padding * remove gradient * cleanup * simplify settings * padding --------- Co-authored-by: Diogo <diogofncunha@gmail.com> Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-09-10 09:31:53 +01:00
return topController
}
return nil
}
func showShareSheet(items: [Any], completed: (() -> Void)? = nil) {
if let topController = getTopViewController() {
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
if let completed = completed {
activityViewController.completionWithItemsHandler = { _, _, _, _ in
completed()
}
}
topController.present(activityViewController, animated: true)
}
}
ios: new user picker (#4821) * ios: new user picker (#4770) * current user picker progress * one hand picker * thin bullet icon * more user picker buttons * button clickable areas * divider padding * extra space after sun * send current user option to address view * add unread count badge * with anim for apperance close * edit current profile from picker * remove you section from settings * remove help and support * simplify * move settings and sun to same row * remove redundant vstack * long press on sun/moon switches to system setting * remove back button from migrate device * smooth profile transitions * close user picker on list profiles * fix dismiss on migrate from device * fix dismiss when deleting last visible user while having hidden users * picker visibility toggle tweaks * remove strange square from profile switcher click * dirty way to save auto accept settings on dismiss * Revert "dirty way to save auto accept settings on dismiss" This reverts commit e7b19ee8aa185b767941d12d5d4534d81f9ea6f5. * consistent animation on user picker toggle * change space between profiles * remove result * ignore result * unread badge * move to sheet * half sheet on one hand ui * fix dismiss on device migration * fix desktop connect * sun to meet other action icons * fill bullet list button * fix tap in settings to take full width * icon sizings and paddings * open settings in same sheet * apply same trick as other buttons for ligth toggle * layout * open profiles sheet large when +3 users * layout * layout * paddings * paddings * remove show progress * always small user picker * fixed height * open all actions as sheets * type, color * simpler and more effective way of avoid moving around on user select * dismiss user profiles sheet on user change * connect desktop back button remove * remove back buttons from user address view * remove porgress * header inside list * alert on auto accept unsaved changes * Cancel -> Discard * revert * fix connect to desktop * remove extra space * fix share inside multi sheet * user picker and options as separate sheet * revert showShareSheet * fix current profile and all profiles selection * change alert * update * cleanup user address * remove func * alert on unsaved changes in chat prefs * fix layout * cleanup --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> * ios: fix switching profiles (#4822) * ios: different user picker layout (#4826) * ios: different user picker layout * remove section * layout, color * color * remove activeUser * fix gradient * recursive sheets * gradient padding * share sheet * layout * dismiss sheets --------- Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> * ios: use the same way to share from all sheets (#4829) * ios: close user picker before opening other sheets * Revert "share sheet" This reverts commit 006415582515f85fb6f634c7727e74295d4447ad. * dismiss/show via callback * Revert "ios: close user picker before opening other sheets" This reverts commit 19110398f8b566d3e925b91074c3c19d97b35f17. * ios: show alerts from sheets (#4839) * padding * remove gradient * cleanup * simplify settings * padding --------- Co-authored-by: Diogo <diogofncunha@gmail.com> Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-09-10 09:31:53 +01:00
func showAlert(
title: String,
message: String? = nil,
buttonTitle: String,
buttonAction: @escaping () -> Void,
cancelButton: Bool
) -> Void {
if let topController = getTopViewController() {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: buttonTitle, style: .default) { _ in
buttonAction()
})
if cancelButton {
alert.addAction(cancelAlertAction)
ios: new user picker (#4821) * ios: new user picker (#4770) * current user picker progress * one hand picker * thin bullet icon * more user picker buttons * button clickable areas * divider padding * extra space after sun * send current user option to address view * add unread count badge * with anim for apperance close * edit current profile from picker * remove you section from settings * remove help and support * simplify * move settings and sun to same row * remove redundant vstack * long press on sun/moon switches to system setting * remove back button from migrate device * smooth profile transitions * close user picker on list profiles * fix dismiss on migrate from device * fix dismiss when deleting last visible user while having hidden users * picker visibility toggle tweaks * remove strange square from profile switcher click * dirty way to save auto accept settings on dismiss * Revert "dirty way to save auto accept settings on dismiss" This reverts commit e7b19ee8aa185b767941d12d5d4534d81f9ea6f5. * consistent animation on user picker toggle * change space between profiles * remove result * ignore result * unread badge * move to sheet * half sheet on one hand ui * fix dismiss on device migration * fix desktop connect * sun to meet other action icons * fill bullet list button * fix tap in settings to take full width * icon sizings and paddings * open settings in same sheet * apply same trick as other buttons for ligth toggle * layout * open profiles sheet large when +3 users * layout * layout * paddings * paddings * remove show progress * always small user picker * fixed height * open all actions as sheets * type, color * simpler and more effective way of avoid moving around on user select * dismiss user profiles sheet on user change * connect desktop back button remove * remove back buttons from user address view * remove porgress * header inside list * alert on auto accept unsaved changes * Cancel -> Discard * revert * fix connect to desktop * remove extra space * fix share inside multi sheet * user picker and options as separate sheet * revert showShareSheet * fix current profile and all profiles selection * change alert * update * cleanup user address * remove func * alert on unsaved changes in chat prefs * fix layout * cleanup --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> * ios: fix switching profiles (#4822) * ios: different user picker layout (#4826) * ios: different user picker layout * remove section * layout, color * color * remove activeUser * fix gradient * recursive sheets * gradient padding * share sheet * layout * dismiss sheets --------- Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> * ios: use the same way to share from all sheets (#4829) * ios: close user picker before opening other sheets * Revert "share sheet" This reverts commit 006415582515f85fb6f634c7727e74295d4447ad. * dismiss/show via callback * Revert "ios: close user picker before opening other sheets" This reverts commit 19110398f8b566d3e925b91074c3c19d97b35f17. * ios: show alerts from sheets (#4839) * padding * remove gradient * cleanup * simplify settings * padding --------- Co-authored-by: Diogo <diogofncunha@gmail.com> Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com> Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-09-10 09:31:53 +01:00
}
topController.present(alert, animated: true)
}
}
func showAlert(
_ title: String,
message: String? = nil,
actions: () -> [UIAlertAction] = { [okAlertAction] }
) {
if let topController = getTopViewController() {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
for action in actions() { alert.addAction(action) }
topController.present(alert, animated: true)
}
}
2025-06-02 11:53:09 +00:00
func showSheet(
_ title: String?,
message: String? = nil,
actions: () -> [UIAlertAction] = { [okAlertAction] },
sourceView: UIView? = nil // For iPad support
) {
if let topController = getTopViewController() {
let sheet = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
for action in actions() { sheet.addAction(action) }
// Required for iPad: Configure popover presentation
if let popover = sheet.popoverPresentationController {
popover.sourceView = sourceView ?? topController.view
popover.sourceRect = sourceView?.bounds ?? CGRect(x: topController.view.bounds.midX, y: topController.view.bounds.midY, width: 0, height: 0)
popover.permittedArrowDirections = []
}
topController.present(sheet, animated: true)
}
}
let okAlertAction = UIAlertAction(title: NSLocalizedString("Ok", comment: "alert button"), style: .default)
let cancelAlertAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: "alert button"), style: .cancel)
let alertProfileImageSize: CGFloat = 103
let alertWidth: CGFloat = 270
let alertButtonHeight: CGFloat = 44
class OpenChatAlertViewController: UIViewController {
private let profileName: String
2025-06-25 22:45:47 +01:00
private let profileFullName: String
private let profileImage: UIView
private let cancelTitle: String
private let confirmTitle: String
private let onCancel: () -> Void
private let onConfirm: () -> Void
init(
profileName: String,
2025-06-25 22:45:47 +01:00
profileFullName: String,
profileImage: UIView,
cancelTitle: String = "Cancel",
confirmTitle: String = "Open",
onCancel: @escaping () -> Void,
onConfirm: @escaping () -> Void
) {
self.profileName = profileName
2025-06-25 22:45:47 +01:00
self.profileFullName = profileFullName
self.profileImage = profileImage
self.cancelTitle = cancelTitle
self.confirmTitle = confirmTitle
self.onCancel = onCancel
self.onConfirm = onConfirm
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .overFullScreen
modalTransitionStyle = .crossDissolve
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.black.withAlphaComponent(0.3)
// Container view
let containerView = UIView()
containerView.backgroundColor = .systemBackground
containerView.layer.cornerRadius = 12
containerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(containerView)
// Profile image sizing
profileImage.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
2025-06-25 22:45:47 +01:00
profileImage.widthAnchor.constraint(equalToConstant: alertProfileImageSize),
profileImage.heightAnchor.constraint(equalToConstant: alertProfileImageSize)
])
// Name label
let nameLabel = UILabel()
nameLabel.text = profileName
2025-06-25 22:45:47 +01:00
nameLabel.font = UIFont.preferredFont(forTextStyle: .headline)
nameLabel.textColor = .label
nameLabel.numberOfLines = 2
2025-06-25 22:45:47 +01:00
nameLabel.textAlignment = .center
nameLabel.translatesAutoresizingMaskIntoConstraints = false
2025-06-25 22:45:47 +01:00
var profileViews = [profileImage, nameLabel]
// Full name label
if !profileFullName.isEmpty && profileFullName != profileName {
let fullNameLabel = UILabel()
fullNameLabel.text = profileFullName
fullNameLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
fullNameLabel.textColor = .label
fullNameLabel.numberOfLines = 2
fullNameLabel.textAlignment = .center
fullNameLabel.translatesAutoresizingMaskIntoConstraints = false
profileViews.append(fullNameLabel)
}
// Horizontal stack for image + name
2025-06-25 22:45:47 +01:00
let stack = UIStackView(arrangedSubviews: profileViews)
stack.axis = .vertical
stack.spacing = 12
stack.alignment = .center
stack.translatesAutoresizingMaskIntoConstraints = false
let topRowContainer = UIView()
topRowContainer.translatesAutoresizingMaskIntoConstraints = false
2025-06-25 22:45:47 +01:00
topRowContainer.addSubview(stack)
NSLayoutConstraint.activate([
2025-06-25 22:45:47 +01:00
stack.topAnchor.constraint(equalTo: topRowContainer.topAnchor),
stack.bottomAnchor.constraint(equalTo: topRowContainer.bottomAnchor),
stack.leadingAnchor.constraint(equalTo: topRowContainer.leadingAnchor, constant: 20),
stack.trailingAnchor.constraint(equalTo: topRowContainer.trailingAnchor, constant: -20)
])
// Buttons
let cancelButton = UIButton(type: .system)
cancelButton.setTitle(cancelTitle, for: .normal)
2025-06-25 22:45:47 +01:00
let bodyDescr = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
cancelButton.titleLabel?.font = UIFont(descriptor: bodyDescr.withSymbolicTraits(.traitBold) ?? bodyDescr, size: 0)
cancelButton.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
let confirmButton = UIButton(type: .system)
confirmButton.setTitle(confirmTitle, for: .normal)
2025-06-25 22:45:47 +01:00
confirmButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body)
confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
let verticalButtons = cancelButton.intrinsicContentSize.width + 20 >= alertWidth / 2 || confirmButton.intrinsicContentSize.width + 20 >= alertWidth / 2
// Button stack with equal width buttons
let buttonStack = UIStackView(arrangedSubviews: verticalButtons ? [confirmButton, cancelButton] : [cancelButton, confirmButton])
buttonStack.axis = verticalButtons ? .vertical : .horizontal
buttonStack.distribution = .fillEqually
buttonStack.spacing = 0 // no spacing, use divider instead
buttonStack.translatesAutoresizingMaskIntoConstraints = false
buttonStack.heightAnchor.constraint(greaterThanOrEqualToConstant: alertButtonHeight * (verticalButtons ? 2 : 1)).isActive = true
// Vertical stack containing hStack and buttonStack
let vStack = UIStackView(arrangedSubviews: [topRowContainer, buttonStack])
vStack.axis = .vertical
vStack.spacing = 16
vStack.alignment = .fill // important: buttons stretch full width
vStack.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(vStack)
// Add horizontal divider above buttons
let horizontalDivider = UIView()
2025-06-25 22:45:47 +01:00
horizontalDivider.backgroundColor = UIColor.separator
horizontalDivider.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(horizontalDivider)
// Add divider between buttons
let buttonDivider = UIView()
buttonDivider.backgroundColor = UIColor.separator
buttonDivider.translatesAutoresizingMaskIntoConstraints = false
buttonStack.addSubview(buttonDivider)
// Constraints
let buttonDividerConstraints = if verticalButtons {
[
buttonDivider.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
buttonDivider.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
buttonDivider.centerYAnchor.constraint(equalTo: buttonStack.centerYAnchor),
buttonDivider.heightAnchor.constraint(equalToConstant: 1 / UIScreen.main.scale)
]
} else {
[
buttonDivider.topAnchor.constraint(equalTo: buttonStack.topAnchor),
buttonDivider.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
buttonDivider.centerXAnchor.constraint(equalTo: buttonStack.centerXAnchor),
buttonDivider.widthAnchor.constraint(equalToConstant: 1 / UIScreen.main.scale)
]
}
NSLayoutConstraint.activate([
// Container view centering and fixed width
containerView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
containerView.widthAnchor.constraint(equalToConstant: alertWidth),
// Vertical stack padding inside containerView
vStack.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 20),
vStack.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 0),
vStack.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: 0),
vStack.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0),
// Center hStack horizontally inside vStack's padded width
2025-06-25 22:45:47 +01:00
stack.centerXAnchor.constraint(equalTo: vStack.centerXAnchor),
// Horizontal divider above buttons
horizontalDivider.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
horizontalDivider.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
horizontalDivider.bottomAnchor.constraint(equalTo: buttonStack.topAnchor),
horizontalDivider.heightAnchor.constraint(equalToConstant: 1 / UIScreen.main.scale)
] + buttonDividerConstraints)
}
@objc private func cancelTapped() {
dismiss(animated: true) {
self.onCancel()
}
}
@objc private func confirmTapped() {
dismiss(animated: true) {
self.onConfirm()
}
}
}
func showOpenChatAlert<Content: View>(
profileName: String,
2025-06-25 22:45:47 +01:00
profileFullName: String,
profileImage: Content,
theme: AppTheme,
cancelTitle: String = "Cancel",
confirmTitle: String = "Open",
onCancel: @escaping () -> Void = {},
onConfirm: @escaping () -> Void
) {
let themedView = profileImage.environmentObject(theme)
let hostingController = UIHostingController(rootView: themedView)
let hostedView = hostingController.view!
hostedView.backgroundColor = .clear
if let topVC = getTopViewController() {
let alertVC = OpenChatAlertViewController(
profileName: profileName,
2025-06-25 22:45:47 +01:00
profileFullName: profileFullName,
profileImage: hostedView,
cancelTitle: cancelTitle,
confirmTitle: confirmTitle,
onCancel: onCancel,
onConfirm: onConfirm
)
topVC.present(alertVC, animated: true)
}
}