Files
GLEGram-iOS/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift
T
Leeksov 4647310322 GLEGram 12.5 — Initial public release
Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
2026-04-06 09:48:12 +03:00

181 lines
6.3 KiB
Swift

import Foundation
import UIKit
import Display
import ComponentFlow
import PagerComponent
import TelegramPresentationData
import TelegramCore
import Postbox
import AnimationCache
import MultiAnimationRenderer
import AccountContext
import AsyncDisplayKit
import ComponentDisplayAdapters
public protocol EntitySearchContainerNode: ASDisplayNode {
var onCancel: (() -> Void)? { get set }
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, inputHeight: CGFloat, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition)
}
public final class EntitySearchContainerController: ViewController {
private var node: Node {
return self.displayNode as! Node
}
private let containerNode: EntitySearchContainerNode
public init(containerNode: EntitySearchContainerNode) {
self.containerNode = containerNode
super.init(navigationBarPresentationData: nil)
self.navigationPresentation = .modal
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func loadDisplayNode() {
self.displayNode = Node(containerNode: self.containerNode, controller: self)
self.displayNodeDidLoad()
}
public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
self.node.containerLayoutUpdated(layout, transition: transition)
}
private class Node: ViewControllerTracingNode, ASScrollViewDelegate {
private weak var controller: EntitySearchContainerController?
private let containerNode: EntitySearchContainerNode
init(containerNode: EntitySearchContainerNode, controller: EntitySearchContainerController) {
self.containerNode = containerNode
self.controller = controller
super.init()
self.addSubnode(containerNode)
containerNode.onCancel = { [weak self] in
self?.controller?.dismiss()
}
}
func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
self.containerNode.updateLayout(size: layout.size, leftInset: 0.0, rightInset: 0.0, bottomInset: layout.intrinsicInsets.bottom, inputHeight: layout.inputHeight ?? 0.0, deviceMetrics: layout.deviceMetrics, transition: transition)
transition.updateFrame(node: self.containerNode, frame: CGRect(origin: .zero, size: layout.size))
}
}
}
final class EntitySearchContentEnvironment: Equatable {
let context: AccountContext
let theme: PresentationTheme
let deviceMetrics: DeviceMetrics
let inputHeight: CGFloat
init(
context: AccountContext,
theme: PresentationTheme,
deviceMetrics: DeviceMetrics,
inputHeight: CGFloat
) {
self.context = context
self.theme = theme
self.deviceMetrics = deviceMetrics
self.inputHeight = inputHeight
}
static func ==(lhs: EntitySearchContentEnvironment, rhs: EntitySearchContentEnvironment) -> Bool {
if lhs.context !== rhs.context {
return false
}
if lhs.theme !== rhs.theme {
return false
}
if lhs.deviceMetrics != rhs.deviceMetrics {
return false
}
if lhs.inputHeight != rhs.inputHeight {
return false
}
return true
}
}
final class EntitySearchContentComponent: Component {
typealias EnvironmentType = EntitySearchContentEnvironment
let makeContainerNode: () -> EntitySearchContainerNode?
let dismissSearch: () -> Void
init(
makeContainerNode: @escaping () -> EntitySearchContainerNode?,
dismissSearch: @escaping () -> Void
) {
self.makeContainerNode = makeContainerNode
self.dismissSearch = dismissSearch
}
static func ==(lhs: EntitySearchContentComponent, rhs: EntitySearchContentComponent) -> Bool {
return true
}
final class View: UIView {
private var containerNode: EntitySearchContainerNode?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(component: EntitySearchContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
let containerNode: EntitySearchContainerNode?
if let current = self.containerNode {
containerNode = current
} else {
containerNode = component.makeContainerNode()
if let containerNode = containerNode {
self.containerNode = containerNode
self.addSubnode(containerNode)
}
}
if let containerNode = containerNode {
let environmentValue = environment[EntitySearchContentEnvironment.self].value
transition.setFrame(view: containerNode.view, frame: CGRect(origin: CGPoint(), size: availableSize))
containerNode.updateLayout(
size: availableSize,
leftInset: 0.0,
rightInset: 0.0,
bottomInset: 0.0,
inputHeight: environmentValue.inputHeight,
deviceMetrics: environmentValue.deviceMetrics,
transition: transition.containedViewLayoutTransition
)
containerNode.onCancel = {
component.dismissSearch()
}
}
return availableSize
}
}
func makeView() -> View {
return View(frame: CGRect())
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}