Files
simplex-chat/apps/ios/Shared/Views/Helpers/ContextMenu.swift
T
Stanislav Dmitrenko 5fde879fea ios: better layout performance for chat item (#3911)
* ios: better layout performance for chat item

* different way of disabling menu

* two fixes

---------

Co-authored-by: Avently <avently@local>
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-19 14:40:46 +00:00

99 lines
3.3 KiB
Swift

//
// ContextMenu2.swift
// SimpleX (iOS)
//
// Created by Evgeny on 09/08/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import Foundation
import UIKit
import SwiftUI
extension View {
func uiKitContextMenu(maxWidth: CGFloat, menu: Binding<UIMenu>, allowMenu: Binding<Bool>) -> some View {
Group {
if allowMenu.wrappedValue {
InteractionView(content: self, maxWidth: maxWidth, menu: menu)
.fixedSize(horizontal: true, vertical: false)
} else {
self
}
}
}
}
private class HostingViewHolder: UIView {
var contentSize: CGSize = CGSizeMake(0, 0)
override var intrinsicContentSize: CGSize { get { contentSize } }
}
struct InteractionView<Content: View>: UIViewRepresentable {
let content: Content
var maxWidth: CGFloat
@Binding var menu: UIMenu
func makeUIView(context: Context) -> UIView {
let view = HostingViewHolder()
view.contentSize = CGSizeMake(maxWidth, .infinity)
view.backgroundColor = .clear
let hostView = UIHostingController(rootView: content)
hostView.view.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
hostView.view.topAnchor.constraint(equalTo: view.topAnchor),
hostView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
hostView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
hostView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
hostView.view.widthAnchor.constraint(equalTo: view.widthAnchor),
hostView.view.heightAnchor.constraint(equalTo: view.heightAnchor)
]
view.addSubview(hostView.view)
view.addConstraints(constraints)
view.layer.cornerRadius = 18
hostView.view.layer.cornerRadius = 18
let menuInteraction = UIContextMenuInteraction(delegate: context.coordinator)
view.addInteraction(menuInteraction)
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
(uiView as! HostingViewHolder).contentSize = uiView.subviews[0].sizeThatFits(CGSizeMake(maxWidth, .infinity))
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UIContextMenuInteractionDelegate {
let parent: InteractionView<Content>
init(_ parent: InteractionView<Content>) {
self.parent = parent
}
func contextMenuInteraction(
_ interaction: UIContextMenuInteraction,
configurationForMenuAtLocation location: CGPoint
) -> UIContextMenuConfiguration? {
UIContextMenuConfiguration(
identifier: nil,
previewProvider: nil,
actionProvider: { [weak self] _ in
guard let self = self else { return nil }
return self.parent.menu
}
)
}
// func contextMenuInteraction(
// _ interaction: UIContextMenuInteraction,
// willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration,
// animator: UIContextMenuInteractionCommitAnimating
// ) {
// animator.addCompletion {
// print("user tapped")
// }
// }
}
}