mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
[WIP] View-once audio and video messages
This commit is contained in:
@@ -7,6 +7,7 @@ import TelegramCore
|
||||
import ReactionSelectionNode
|
||||
import ComponentFlow
|
||||
import TabSelectorComponent
|
||||
import PlainButtonComponent
|
||||
import ComponentDisplayAdapters
|
||||
|
||||
final class ContextSourceContainer: ASDisplayNode {
|
||||
@@ -16,6 +17,7 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
let id: AnyHashable
|
||||
let title: String
|
||||
let source: ContextContentSource
|
||||
let closeActionTitle: String?
|
||||
|
||||
private var _presentationNode: ContextControllerPresentationNode?
|
||||
var presentationNode: ContextControllerPresentationNode {
|
||||
@@ -40,12 +42,14 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
id: AnyHashable,
|
||||
title: String,
|
||||
source: ContextContentSource,
|
||||
items: Signal<ContextController.Items, NoError>
|
||||
items: Signal<ContextController.Items, NoError>,
|
||||
closeActionTitle: String? = nil
|
||||
) {
|
||||
self.controller = controller
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.source = source
|
||||
self.closeActionTitle = closeActionTitle
|
||||
|
||||
self.ready.set(combineLatest(queue: .mainQueue(), self.contentReady.get(), self.actionsReady.get())
|
||||
|> map { a, b -> Bool in
|
||||
@@ -162,8 +166,11 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
guard let self, let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
controller.controllerNode.dismissedForCancel?()
|
||||
controller.controllerNode.beginDismiss(result)
|
||||
if let _ = self.closeActionTitle {
|
||||
} else {
|
||||
controller.controllerNode.dismissedForCancel?()
|
||||
controller.controllerNode.beginDismiss(result)
|
||||
}
|
||||
},
|
||||
requestAnimateOut: { [weak self] result, completion in
|
||||
guard let self, let controller = self.controller else {
|
||||
@@ -341,6 +348,7 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
var activeIndex: Int = 0
|
||||
|
||||
private var tabSelector: ComponentView<Empty>?
|
||||
private var closeButton: ComponentView<Empty>?
|
||||
|
||||
private var presentationData: PresentationData?
|
||||
private var validLayout: ContainerViewLayout?
|
||||
@@ -376,7 +384,8 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
id: source.id,
|
||||
title: source.title,
|
||||
source: source.source,
|
||||
items: source.items
|
||||
items: source.items,
|
||||
closeActionTitle: source.closeActionTitle
|
||||
)
|
||||
self.sources.append(mappedSource)
|
||||
self.addSubnode(mappedSource.presentationNode)
|
||||
@@ -457,6 +466,9 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
if let tabSelectorView = self.tabSelector?.view {
|
||||
tabSelectorView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
if let closeButtonView = self.closeButton?.view {
|
||||
closeButtonView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
|
||||
func animateOut(result: ContextMenuActionResult, completion: @escaping () -> Void) {
|
||||
@@ -465,6 +477,9 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
if let tabSelectorView = self.tabSelector?.view {
|
||||
tabSelectorView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
if let closeButtonView = self.closeButton?.view {
|
||||
closeButtonView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
if let activeSource = self.activeSource {
|
||||
activeSource.animateOut(result: result, completion: completion)
|
||||
@@ -636,6 +651,43 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
}
|
||||
transition.updateFrame(view: tabSelectorView, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - tabSelectorSize.width) * 0.5), y: layout.size.height - layout.intrinsicInsets.bottom - tabSelectorSize.height), size: tabSelectorSize))
|
||||
}
|
||||
} else if let source = self.sources.first, let closeActionTitle = source.closeActionTitle {
|
||||
let closeButton: ComponentView<Empty>
|
||||
if let current = self.closeButton {
|
||||
closeButton = current
|
||||
} else {
|
||||
closeButton = ComponentView()
|
||||
self.closeButton = closeButton
|
||||
}
|
||||
|
||||
let closeButtonSize = closeButton.update(
|
||||
transition: Transition(transition),
|
||||
component: AnyComponent(PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
CloseButtonComponent(
|
||||
backgroundColor: presentationData.theme.contextMenu.primaryColor.withMultipliedAlpha(0.1),
|
||||
text: closeActionTitle
|
||||
)
|
||||
),
|
||||
effectAlignment: .center,
|
||||
action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.controller?.dismiss(result: .dismissWithoutContent, completion: nil)
|
||||
})
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: layout.size.width, height: 44.0)
|
||||
)
|
||||
childLayout.intrinsicInsets.bottom += 30.0
|
||||
|
||||
if let closeButtonView = closeButton.view {
|
||||
if closeButtonView.superview == nil {
|
||||
self.view.addSubview(closeButtonView)
|
||||
}
|
||||
transition.updateFrame(view: closeButtonView, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - closeButtonSize.width) * 0.5), y: layout.size.height - layout.intrinsicInsets.bottom - closeButtonSize.height - 10.0), size: closeButtonSize))
|
||||
}
|
||||
} else if let tabSelector = self.tabSelector {
|
||||
self.tabSelector = nil
|
||||
tabSelector.view?.removeFromSuperview()
|
||||
@@ -664,6 +716,11 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
return result
|
||||
}
|
||||
}
|
||||
if let closeButtonView = self.closeButton?.view {
|
||||
if let result = closeButtonView.hitTest(self.view.convert(point, to: closeButtonView), with: event) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
guard let activeSource = self.activeSource else {
|
||||
return nil
|
||||
@@ -671,3 +728,61 @@ final class ContextSourceContainer: ASDisplayNode {
|
||||
return activeSource.presentationNode.view.hitTest(point, with: event)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final class CloseButtonComponent: CombinedComponent {
|
||||
let backgroundColor: UIColor
|
||||
let text: String
|
||||
|
||||
init(
|
||||
backgroundColor: UIColor,
|
||||
text: String
|
||||
) {
|
||||
self.backgroundColor = backgroundColor
|
||||
self.text = text
|
||||
}
|
||||
|
||||
static func ==(lhs: CloseButtonComponent, rhs: CloseButtonComponent) -> Bool {
|
||||
if lhs.backgroundColor != rhs.backgroundColor {
|
||||
return false
|
||||
}
|
||||
if lhs.text != rhs.text {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
static var body: Body {
|
||||
let background = Child(RoundedRectangle.self)
|
||||
let text = Child(Text.self)
|
||||
|
||||
return { context in
|
||||
let text = text.update(
|
||||
component: Text(
|
||||
text: "\(context.component.text)",
|
||||
font: Font.regular(17.0),
|
||||
color: .white
|
||||
),
|
||||
availableSize: CGSize(width: 200.0, height: 100.0),
|
||||
transition: .immediate
|
||||
)
|
||||
|
||||
let backgroundSize = CGSize(width: text.size.width + 34.0, height: 36.0)
|
||||
let background = background.update(
|
||||
component: RoundedRectangle(color: context.component.backgroundColor, cornerRadius: 18.0),
|
||||
availableSize: backgroundSize,
|
||||
transition: .immediate
|
||||
)
|
||||
|
||||
context.add(background
|
||||
.position(CGPoint(x: backgroundSize.width / 2.0, y: backgroundSize.height / 2.0))
|
||||
)
|
||||
|
||||
context.add(text
|
||||
.position(CGPoint(x: backgroundSize.width / 2.0, y: backgroundSize.height / 2.0))
|
||||
)
|
||||
|
||||
return backgroundSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user