Files
ichmagmaus111andClaude Opus 5.5 0622057a4f Ghostgram: open-source release
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 17:57:09 +01:00

42 lines
2.0 KiB
Swift

import Foundation
import UIKit
import Display
import ContextUI
import TelegramPresentationData
/// Presents an owner-built media context menu as a Telegram `ContextController`, anchored to the tapped
/// control's view. Shared by both editor hosts (chat composer + attachment screen); only the ContextController
/// anchoring/presentation boilerplate is shared — the `items` are owner-specific. Mirrors
/// `RichTextActionContextReferenceSource` (the attachment screen's action menu): the ContextController
/// references `anchorView` **directly** and snapshots it for the transition — it does NOT reparent it or add
/// subviews to it. (Unlike `presentTableStructuralMenu`, which must synthesize a transient anchor view because
/// a drawn table handle has no real view at its rect; `anchorView` here IS the tapped control — the glass
/// "more" button — so adding a transient subview would trip `GlassBackgroundContainerView.didAddSubview`.)
@available(iOS 13.0, *)
public func presentMediaControlMenu(
anchorView: UIView,
items: [ContextMenuItem],
presentationData: PresentationData,
present: (ViewController) -> Void
) {
let controller = makeContextController(
presentationData: presentationData,
source: .reference(MediaControlMenuReferenceSource(sourceView: anchorView)),
items: .single(ContextController.Items(content: .list(items))),
gesture: nil
)
present(controller)
}
/// Anchors a `ContextController` to the tapped control's view (referenced directly, not reparented).
@available(iOS 13.0, *)
private final class MediaControlMenuReferenceSource: ContextReferenceContentSource {
private let sourceView: UIView
init(sourceView: UIView) { self.sourceView = sourceView }
func transitionInfo() -> ContextControllerReferenceViewInfo? {
return ContextControllerReferenceViewInfo(referenceView: self.sourceView,
contentAreaInScreenSpace: UIScreen.main.bounds,
insets: UIEdgeInsets(top: -4.0, left: 0.0, bottom: -4.0, right: 0.0), actionsPosition: .bottom)
}
}