mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
[WIP] Video message send context menu
This commit is contained in:
parent
8736981248
commit
3da1b96775
@ -32,13 +32,20 @@ func convertFrame(_ frame: CGRect, from fromView: UIView, to toView: UIView) ->
|
|||||||
return targetWindowFrame
|
return targetWindowFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ChatSendMessageContextScreenMediaPreviewLayoutType {
|
||||||
|
case message
|
||||||
|
case videoMessage
|
||||||
|
}
|
||||||
|
|
||||||
public protocol ChatSendMessageContextScreenMediaPreview: AnyObject {
|
public protocol ChatSendMessageContextScreenMediaPreview: AnyObject {
|
||||||
var isReady: Signal<Bool, NoError> { get }
|
var isReady: Signal<Bool, NoError> { get }
|
||||||
var view: UIView { get }
|
var view: UIView { get }
|
||||||
var globalClippingRect: CGRect? { get }
|
var globalClippingRect: CGRect? { get }
|
||||||
|
var layoutType: ChatSendMessageContextScreenMediaPreviewLayoutType { get }
|
||||||
|
|
||||||
func animateIn(transition: Transition)
|
func animateIn(transition: Transition)
|
||||||
func animateOut(transition: Transition)
|
func animateOut(transition: Transition)
|
||||||
|
func animateOutOnSend(transition: Transition)
|
||||||
func update(containerSize: CGSize, transition: Transition) -> CGSize
|
func update(containerSize: CGSize, transition: Transition) -> CGSize
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,6 +489,18 @@ final class ChatSendMessageContextScreenComponent: Component {
|
|||||||
maxTextHeight -= environment.safeInsets.bottom
|
maxTextHeight -= environment.safeInsets.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let messageItemViewContainerSize: CGSize
|
||||||
|
if let mediaPreview = component.mediaPreview {
|
||||||
|
switch mediaPreview.layoutType {
|
||||||
|
case .message:
|
||||||
|
messageItemViewContainerSize = CGSize(width: availableSize.width - 16.0 - 40.0, height: availableSize.height)
|
||||||
|
case .videoMessage:
|
||||||
|
messageItemViewContainerSize = CGSize(width: availableSize.width, height: availableSize.height)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
messageItemViewContainerSize = CGSize(width: availableSize.width - 16.0 - 40.0, height: availableSize.height)
|
||||||
|
}
|
||||||
|
|
||||||
let messageItemSize = messageItemView.update(
|
let messageItemSize = messageItemView.update(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
@ -494,7 +513,7 @@ final class ChatSendMessageContextScreenComponent: Component {
|
|||||||
explicitBackgroundSize: explicitMessageBackgroundSize,
|
explicitBackgroundSize: explicitMessageBackgroundSize,
|
||||||
maxTextWidth: localSourceTextInputViewFrame.width,
|
maxTextWidth: localSourceTextInputViewFrame.width,
|
||||||
maxTextHeight: maxTextHeight,
|
maxTextHeight: maxTextHeight,
|
||||||
containerSize: CGSize(width: availableSize.width - 16.0 - 40.0, height: availableSize.height),
|
containerSize: messageItemViewContainerSize,
|
||||||
effect: self.presentationAnimationState.key == .animatedIn ? self.selectedMessageEffect : nil,
|
effect: self.presentationAnimationState.key == .animatedIn ? self.selectedMessageEffect : nil,
|
||||||
transition: transition
|
transition: transition
|
||||||
)
|
)
|
||||||
@ -799,6 +818,15 @@ final class ChatSendMessageContextScreenComponent: Component {
|
|||||||
let sourceActionsStackFrame = CGRect(origin: CGPoint(x: readySendButtonFrame.minX + 1.0 - actionsStackSize.width, y: sourceMessageItemFrame.maxY + messageActionsSpacing), size: actionsStackSize)
|
let sourceActionsStackFrame = CGRect(origin: CGPoint(x: readySendButtonFrame.minX + 1.0 - actionsStackSize.width, y: sourceMessageItemFrame.maxY + messageActionsSpacing), size: actionsStackSize)
|
||||||
|
|
||||||
var readyMessageItemFrame = CGRect(origin: CGPoint(x: readySendButtonFrame.minX + 8.0 - messageItemSize.width, y: readySendButtonFrame.maxY - 6.0 - messageItemSize.height), size: messageItemSize)
|
var readyMessageItemFrame = CGRect(origin: CGPoint(x: readySendButtonFrame.minX + 8.0 - messageItemSize.width, y: readySendButtonFrame.maxY - 6.0 - messageItemSize.height), size: messageItemSize)
|
||||||
|
if let mediaPreview = component.mediaPreview {
|
||||||
|
switch mediaPreview.layoutType {
|
||||||
|
case .message:
|
||||||
|
break
|
||||||
|
case .videoMessage:
|
||||||
|
readyMessageItemFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - messageItemSize.width) * 0.5), y: readySendButtonFrame.maxY - 6.0 - messageItemSize.height), size: messageItemSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var readyActionsStackFrame = CGRect(origin: CGPoint(x: readySendButtonFrame.minX + 1.0 - actionsStackSize.width, y: readyMessageItemFrame.maxY + messageActionsSpacing), size: actionsStackSize)
|
var readyActionsStackFrame = CGRect(origin: CGPoint(x: readySendButtonFrame.minX + 1.0 - actionsStackSize.width, y: readyMessageItemFrame.maxY + messageActionsSpacing), size: actionsStackSize)
|
||||||
|
|
||||||
let bottomOverflow = readyActionsStackFrame.maxY - (availableSize.height - environment.safeInsets.bottom)
|
let bottomOverflow = readyActionsStackFrame.maxY - (availableSize.height - environment.safeInsets.bottom)
|
||||||
@ -874,7 +902,7 @@ final class ChatSendMessageContextScreenComponent: Component {
|
|||||||
transition.setAlpha(view: actionsStackNode.view, alpha: 0.0)
|
transition.setAlpha(view: actionsStackNode.view, alpha: 0.0)
|
||||||
transition.setScale(view: actionsStackNode.view, scale: 0.001)
|
transition.setScale(view: actionsStackNode.view, scale: 0.001)
|
||||||
|
|
||||||
messageItemView.animateOut(transition: transition)
|
messageItemView.animateOut(toEmpty: self.animateOutToEmpty, transition: transition)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch self.presentationAnimationState {
|
switch self.presentationAnimationState {
|
||||||
|
@ -166,6 +166,8 @@ final class MessageItemView: UIView {
|
|||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.isUserInteractionEnabled = false
|
||||||
|
|
||||||
self.addSubview(self.backgroundWallpaperNode.view)
|
self.addSubview(self.backgroundWallpaperNode.view)
|
||||||
self.addSubview(self.backgroundNode.view)
|
self.addSubview(self.backgroundNode.view)
|
||||||
|
|
||||||
@ -182,9 +184,13 @@ final class MessageItemView: UIView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateOut(transition: Transition) {
|
func animateOut(toEmpty: Bool, transition: Transition) {
|
||||||
if let mediaPreview = self.mediaPreview {
|
if let mediaPreview = self.mediaPreview {
|
||||||
mediaPreview.animateOut(transition: transition)
|
if toEmpty {
|
||||||
|
mediaPreview.animateOutOnSend(transition: transition)
|
||||||
|
} else {
|
||||||
|
mediaPreview.animateOut(transition: transition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,9 +280,16 @@ final class MessageItemView: UIView {
|
|||||||
|
|
||||||
let mediaPreviewSize = sourceMediaPreview.update(containerSize: containerSize, transition: transition)
|
let mediaPreviewSize = sourceMediaPreview.update(containerSize: containerSize, transition: transition)
|
||||||
|
|
||||||
let backgroundSize = CGSize(width: mediaPreviewSize.width + 7.0, height: mediaPreviewSize.height)
|
var backgroundSize = CGSize(width: mediaPreviewSize.width, height: mediaPreviewSize.height)
|
||||||
|
let mediaPreviewFrame: CGRect
|
||||||
|
switch sourceMediaPreview.layoutType {
|
||||||
|
case .message:
|
||||||
|
backgroundSize.width += 7.0
|
||||||
|
mediaPreviewFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: mediaPreviewSize)
|
||||||
|
case .videoMessage:
|
||||||
|
mediaPreviewFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: mediaPreviewSize)
|
||||||
|
}
|
||||||
|
|
||||||
let mediaPreviewFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: mediaPreviewSize)
|
|
||||||
transition.setFrame(view: sourceMediaPreview.view, frame: mediaPreviewFrame)
|
transition.setFrame(view: sourceMediaPreview.view, frame: mediaPreviewFrame)
|
||||||
|
|
||||||
if let effectIcon = self.effectIcon, let effectIconSize {
|
if let effectIcon = self.effectIcon, let effectIconSize {
|
||||||
@ -295,10 +308,21 @@ final class MessageItemView: UIView {
|
|||||||
self.effectIconBackgroundView = effectIconBackgroundView
|
self.effectIconBackgroundView = effectIconBackgroundView
|
||||||
self.insertSubview(effectIconBackgroundView, belowSubview: effectIconView)
|
self.insertSubview(effectIconBackgroundView, belowSubview: effectIconView)
|
||||||
}
|
}
|
||||||
effectIconBackgroundView.backgroundColor = presentationData.theme.chat.message.mediaDateAndStatusFillColor
|
|
||||||
|
|
||||||
let effectIconBackgroundSize = CGSize(width: effectIconSize.width + 8.0 * 2.0, height: 18.0)
|
let effectIconBackgroundSize = CGSize(width: effectIconSize.width + 8.0 * 2.0, height: 18.0)
|
||||||
let effectIconBackgroundFrame = CGRect(origin: CGPoint(x: mediaPreviewFrame.maxX - effectIconBackgroundSize.width - 6.0, y: mediaPreviewFrame.maxY - effectIconBackgroundSize.height - 6.0), size: effectIconBackgroundSize)
|
|
||||||
|
let effectIconBackgroundFrame: CGRect
|
||||||
|
switch sourceMediaPreview.layoutType {
|
||||||
|
case .message:
|
||||||
|
effectIconBackgroundFrame = CGRect(origin: CGPoint(x: mediaPreviewFrame.maxX - effectIconBackgroundSize.width - 6.0, y: mediaPreviewFrame.maxY - effectIconBackgroundSize.height - 6.0), size: effectIconBackgroundSize)
|
||||||
|
effectIconBackgroundView.backgroundColor = presentationData.theme.chat.message.mediaDateAndStatusFillColor
|
||||||
|
case .videoMessage:
|
||||||
|
effectIconBackgroundFrame = CGRect(origin: CGPoint(x: mediaPreviewFrame.maxX - effectIconBackgroundSize.width - 34.0, y: mediaPreviewFrame.maxY - effectIconBackgroundSize.height - 6.0), size: effectIconBackgroundSize)
|
||||||
|
|
||||||
|
let serviceMessageColors = serviceMessageColorComponents(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper)
|
||||||
|
|
||||||
|
effectIconBackgroundView.backgroundColor = serviceMessageColors.dateFillStatic
|
||||||
|
}
|
||||||
|
|
||||||
let effectIconFrame = CGRect(origin: CGPoint(x: effectIconBackgroundFrame.minX + floor((effectIconBackgroundFrame.width - effectIconSize.width) * 0.5), y: effectIconBackgroundFrame.minY + floor((effectIconBackgroundFrame.height - effectIconSize.height) * 0.5)), size: effectIconSize)
|
let effectIconFrame = CGRect(origin: CGPoint(x: effectIconBackgroundFrame.minX + floor((effectIconBackgroundFrame.width - effectIconSize.width) * 0.5), y: effectIconBackgroundFrame.minY + floor((effectIconBackgroundFrame.height - effectIconSize.height) * 0.5)), size: effectIconSize)
|
||||||
|
|
||||||
|
@ -511,6 +511,9 @@ final class MediaPickerSelectedListNode: ASDisplayNode, ASScrollViewDelegate, AS
|
|||||||
private let persistentItems: Bool
|
private let persistentItems: Bool
|
||||||
private let isExternalPreview: Bool
|
private let isExternalPreview: Bool
|
||||||
var globalClippingRect: CGRect?
|
var globalClippingRect: CGRect?
|
||||||
|
var layoutType: ChatSendMessageContextScreenMediaPreviewLayoutType {
|
||||||
|
return .message
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate var wallpaperBackgroundNode: WallpaperBackgroundNode?
|
fileprivate var wallpaperBackgroundNode: WallpaperBackgroundNode?
|
||||||
private let scrollNode: ASScrollNode
|
private let scrollNode: ASScrollNode
|
||||||
@ -656,7 +659,7 @@ final class MediaPickerSelectedListNode: ASDisplayNode, ASScrollViewDelegate, AS
|
|||||||
}
|
}
|
||||||
|
|
||||||
func animateOut(transition: ContainedViewLayoutTransition, completion: @escaping () -> Void = {}) {
|
func animateOut(transition: ContainedViewLayoutTransition, completion: @escaping () -> Void = {}) {
|
||||||
if let wallpaperBackgroundNode = self.wallpaperBackgroundNode{
|
if let wallpaperBackgroundNode = self.wallpaperBackgroundNode {
|
||||||
wallpaperBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { [weak self] _ in
|
wallpaperBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { [weak self] _ in
|
||||||
completion()
|
completion()
|
||||||
|
|
||||||
@ -714,6 +717,10 @@ final class MediaPickerSelectedListNode: ASDisplayNode, ASScrollViewDelegate, AS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func animateOutOnSend(transition: Transition) {
|
||||||
|
transition.setAlpha(view: self.view, alpha: 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/MediaEditor",
|
"//submodules/TelegramUI/Components/MediaEditor",
|
||||||
"//submodules/LegacyMediaPickerUI",
|
"//submodules/LegacyMediaPickerUI",
|
||||||
"//submodules/TelegramAudio",
|
"//submodules/TelegramAudio",
|
||||||
|
"//submodules/ChatSendMessageActionUI",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -27,6 +27,7 @@ import LocalMediaResources
|
|||||||
import ImageCompression
|
import ImageCompression
|
||||||
import LegacyMediaPickerUI
|
import LegacyMediaPickerUI
|
||||||
import TelegramAudio
|
import TelegramAudio
|
||||||
|
import ChatSendMessageActionUI
|
||||||
|
|
||||||
struct CameraState: Equatable {
|
struct CameraState: Equatable {
|
||||||
enum Recording: Equatable {
|
enum Recording: Equatable {
|
||||||
@ -553,6 +554,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
fileprivate let containerView: UIView
|
fileprivate let containerView: UIView
|
||||||
fileprivate let componentHost: ComponentView<ViewControllerComponentContainer.Environment>
|
fileprivate let componentHost: ComponentView<ViewControllerComponentContainer.Environment>
|
||||||
fileprivate let previewContainerView: UIView
|
fileprivate let previewContainerView: UIView
|
||||||
|
fileprivate let previewContainerContentView: UIView
|
||||||
private var previewSnapshotView: UIView?
|
private var previewSnapshotView: UIView?
|
||||||
private var previewBlurView: BlurView
|
private var previewBlurView: BlurView
|
||||||
|
|
||||||
@ -625,7 +627,10 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
self.componentHost = ComponentView<ViewControllerComponentContainer.Environment>()
|
self.componentHost = ComponentView<ViewControllerComponentContainer.Environment>()
|
||||||
|
|
||||||
self.previewContainerView = UIView()
|
self.previewContainerView = UIView()
|
||||||
self.previewContainerView.clipsToBounds = true
|
|
||||||
|
self.previewContainerContentView = UIView()
|
||||||
|
self.previewContainerContentView.clipsToBounds = true
|
||||||
|
self.previewContainerView.addSubview(self.previewContainerContentView)
|
||||||
|
|
||||||
let isDualCameraEnabled = Camera.isDualCameraSupported(forRoundVideo: true)
|
let isDualCameraEnabled = Camera.isDualCameraSupported(forRoundVideo: true)
|
||||||
let isFrontPosition = "".isEmpty
|
let isFrontPosition = "".isEmpty
|
||||||
@ -666,13 +671,13 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
|
|
||||||
self.containerView.addSubview(self.previewContainerView)
|
self.containerView.addSubview(self.previewContainerView)
|
||||||
|
|
||||||
self.previewContainerView.addSubview(self.mainPreviewView)
|
self.previewContainerContentView.addSubview(self.mainPreviewView)
|
||||||
if isDualCameraEnabled {
|
if isDualCameraEnabled {
|
||||||
self.previewContainerView.addSubview(self.additionalPreviewView)
|
self.previewContainerContentView.addSubview(self.additionalPreviewView)
|
||||||
}
|
}
|
||||||
self.previewContainerView.addSubview(self.progressView)
|
self.previewContainerContentView.addSubview(self.progressView)
|
||||||
self.previewContainerView.addSubview(self.previewBlurView)
|
self.previewContainerContentView.addSubview(self.previewBlurView)
|
||||||
self.previewContainerView.addSubview(self.loadingView)
|
self.previewContainerContentView.addSubview(self.loadingView)
|
||||||
|
|
||||||
self.completion.connect { [weak self] result in
|
self.completion.connect { [weak self] result in
|
||||||
if let self {
|
if let self {
|
||||||
@ -837,7 +842,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
|
|
||||||
private func animatePositionChange() {
|
private func animatePositionChange() {
|
||||||
if let snapshotView = self.mainPreviewView.snapshotView(afterScreenUpdates: false) {
|
if let snapshotView = self.mainPreviewView.snapshotView(afterScreenUpdates: false) {
|
||||||
self.previewContainerView.insertSubview(snapshotView, belowSubview: self.progressView)
|
self.previewContainerContentView.insertSubview(snapshotView, belowSubview: self.progressView)
|
||||||
self.previewSnapshotView = snapshotView
|
self.previewSnapshotView = snapshotView
|
||||||
|
|
||||||
let action = { [weak self] in
|
let action = { [weak self] in
|
||||||
@ -872,7 +877,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
func resumeCameraCapture() {
|
func resumeCameraCapture() {
|
||||||
if !self.mainPreviewView.isEnabled {
|
if !self.mainPreviewView.isEnabled {
|
||||||
if let snapshotView = self.resultPreviewView?.snapshotView(afterScreenUpdates: false) {
|
if let snapshotView = self.resultPreviewView?.snapshotView(afterScreenUpdates: false) {
|
||||||
self.previewContainerView.insertSubview(snapshotView, belowSubview: self.previewBlurView)
|
self.previewContainerContentView.insertSubview(snapshotView, belowSubview: self.previewBlurView)
|
||||||
self.previewSnapshotView = snapshotView
|
self.previewSnapshotView = snapshotView
|
||||||
}
|
}
|
||||||
self.mainPreviewView.isEnabled = true
|
self.mainPreviewView.isEnabled = true
|
||||||
@ -1148,8 +1153,9 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
}
|
}
|
||||||
if !self.animatingIn {
|
if !self.animatingIn {
|
||||||
transition.setFrame(view: self.previewContainerView, frame: previewFrame)
|
transition.setFrame(view: self.previewContainerView, frame: previewFrame)
|
||||||
|
transition.setFrame(view: self.previewContainerContentView, frame: CGRect(origin: CGPoint(), size: previewFrame.size))
|
||||||
}
|
}
|
||||||
transition.setCornerRadius(layer: self.previewContainerView.layer, cornerRadius: previewSide / 2.0)
|
transition.setCornerRadius(layer: self.previewContainerContentView.layer, cornerRadius: previewSide / 2.0)
|
||||||
|
|
||||||
let previewBounds = CGRect(origin: .zero, size: previewFrame.size)
|
let previewBounds = CGRect(origin: .zero, size: previewFrame.size)
|
||||||
|
|
||||||
@ -1244,7 +1250,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
}, transition: .easeInOut(duration: 0.2))
|
}, transition: .easeInOut(duration: 0.2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.previewContainerView.addSubview(resultPreviewView)
|
self.previewContainerContentView.addSubview(resultPreviewView)
|
||||||
|
|
||||||
self.resultPreviewView = resultPreviewView
|
self.resultPreviewView = resultPreviewView
|
||||||
resultPreviewView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
resultPreviewView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
@ -1730,6 +1736,10 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
(self.displayNode as! Node).containerLayoutUpdated(layout: layout, transition: Transition(transition))
|
(self.displayNode as! Node).containerLayoutUpdated(layout: layout, transition: Transition(transition))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func makeSendMessageContextPreview() -> ChatSendMessageContextScreenMediaPreview? {
|
||||||
|
return VideoMessageSendMessageContextPreview(node: self.node)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func composition(with results: [VideoMessageCameraScreen.CaptureResult]) -> AVComposition {
|
private func composition(with results: [VideoMessageCameraScreen.CaptureResult]) -> AVComposition {
|
||||||
@ -1797,3 +1807,84 @@ private class BlurView: UIVisualEffectView {
|
|||||||
self.setup()
|
self.setup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class VideoMessageSendMessageContextPreview: UIView, ChatSendMessageContextScreenMediaPreview {
|
||||||
|
var isReady: Signal<Bool, NoError> {
|
||||||
|
return .single(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
var view: UIView {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
var globalClippingRect: CGRect? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var layoutType: ChatSendMessageContextScreenMediaPreviewLayoutType {
|
||||||
|
return .videoMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
private weak var previewContainerContentParentView: UIView?
|
||||||
|
private let previewContainerContentView: UIView
|
||||||
|
|
||||||
|
init(node: VideoMessageCameraScreen.Node) {
|
||||||
|
self.previewContainerContentParentView = node.previewContainerView
|
||||||
|
self.previewContainerContentView = node.previewContainerContentView
|
||||||
|
|
||||||
|
super.init(frame: CGRect())
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(coder: NSCoder) {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
|
||||||
|
func animateIn(transition: Transition) {
|
||||||
|
self.addSubview(self.previewContainerContentView)
|
||||||
|
|
||||||
|
guard let previewContainerContentParentView = self.previewContainerContentParentView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let fromFrame = previewContainerContentParentView.convert(CGRect(origin: CGPoint(), size: self.previewContainerContentView.bounds.size), to: self)
|
||||||
|
let toFrame = self.previewContainerContentView.frame
|
||||||
|
|
||||||
|
transition.animatePosition(view: self.previewContainerContentView, from: CGPoint(x: fromFrame.midX - toFrame.midX, y: fromFrame.midY - toFrame.midY), to: CGPoint(), additive: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func animateOut(transition: Transition) {
|
||||||
|
guard let previewContainerContentParentView = self.previewContainerContentParentView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let toFrame = previewContainerContentParentView.convert(CGRect(origin: CGPoint(), size: self.previewContainerContentView.bounds.size), to: self)
|
||||||
|
|
||||||
|
let previewContainerContentView = self.previewContainerContentView
|
||||||
|
transition.setPosition(view: self.previewContainerContentView, position: toFrame.center, completion: { [weak previewContainerContentParentView, weak previewContainerContentView] _ in
|
||||||
|
guard let previewContainerContentParentView, let previewContainerContentView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
previewContainerContentView.frame = CGRect(origin: CGPoint(), size: previewContainerContentView.bounds.size)
|
||||||
|
previewContainerContentParentView.addSubview(previewContainerContentView)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func animateOutOnSend(transition: Transition) {
|
||||||
|
guard let previewContainerContentParentView = self.previewContainerContentParentView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let snapshotView = self.previewContainerContentView.snapshotView(afterScreenUpdates: false) {
|
||||||
|
self.addSubview(snapshotView)
|
||||||
|
transition.setAlpha(view: snapshotView, alpha: 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.previewContainerContentView.frame = CGRect(origin: CGPoint(), size: self.previewContainerContentView.bounds.size)
|
||||||
|
previewContainerContentParentView.addSubview(self.previewContainerContentView)
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(containerSize: CGSize, transition: Transition) -> CGSize {
|
||||||
|
return self.previewContainerContentView.bounds.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -79,37 +79,61 @@ func chatMessageDisplaySendMessageOptions(selfController: ChatControllerImpl, no
|
|||||||
let _ = ApplicationSpecificNotice.incrementSendWhenOnlineTip(accountManager: selfController.context.sharedContext.accountManager, count: 4).startStandalone()
|
let _ = ApplicationSpecificNotice.incrementSendWhenOnlineTip(accountManager: selfController.context.sharedContext.accountManager, count: 4).startStandalone()
|
||||||
}
|
}
|
||||||
|
|
||||||
let controller = makeChatSendMessageActionSheetController(context: selfController.context, updatedPresentationData: selfController.updatedPresentationData, peerId: selfController.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: selfController.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputView: textInputView, emojiViewProvider: selfController.chatDisplayNode.textInputPanelNode?.emojiViewProvider, wallpaperBackgroundNode: selfController.chatDisplayNode.backgroundNode, canSendWhenOnline: sendWhenOnlineAvailable, completion: { [weak selfController] in
|
var mediaPreview: ChatSendMessageContextScreenMediaPreview?
|
||||||
guard let selfController else {
|
if let videoRecorderValue = selfController.videoRecorderValue {
|
||||||
return
|
mediaPreview = videoRecorderValue.makeSendMessageContextPreview()
|
||||||
}
|
}
|
||||||
selfController.supportedOrientations = previousSupportedOrientations
|
|
||||||
}, sendMessage: { [weak selfController] mode, messageEffect in
|
let controller = makeChatSendMessageActionSheetController(
|
||||||
guard let selfController else {
|
context: selfController.context,
|
||||||
return
|
updatedPresentationData: selfController.updatedPresentationData,
|
||||||
}
|
peerId: selfController.presentationInterfaceState.chatLocation.peerId,
|
||||||
switch mode {
|
forwardMessageIds: selfController.presentationInterfaceState.interfaceState.forwardMessageIds,
|
||||||
case .generic:
|
hasEntityKeyboard: hasEntityKeyboard,
|
||||||
selfController.controllerInteraction?.sendCurrentMessage(false, messageEffect.flatMap(ChatSendMessageEffect.init))
|
gesture: gesture,
|
||||||
case .silently:
|
sourceSendButton: node,
|
||||||
selfController.controllerInteraction?.sendCurrentMessage(true, messageEffect.flatMap(ChatSendMessageEffect.init))
|
textInputView: textInputView,
|
||||||
case .whenOnline:
|
mediaPreview: mediaPreview,
|
||||||
selfController.chatDisplayNode.sendCurrentMessage(scheduleTime: scheduleWhenOnlineTimestamp, messageEffect: messageEffect.flatMap(ChatSendMessageEffect.init)) { [weak selfController] in
|
emojiViewProvider: selfController.chatDisplayNode.textInputPanelNode?.emojiViewProvider,
|
||||||
guard let selfController else {
|
wallpaperBackgroundNode: selfController.chatDisplayNode.backgroundNode,
|
||||||
return
|
canSendWhenOnline: sendWhenOnlineAvailable,
|
||||||
}
|
completion: { [weak selfController] in
|
||||||
selfController.updateChatPresentationInterfaceState(animated: true, interactive: false, saveInterfaceState: selfController.presentationInterfaceState.subject != .scheduledMessages, {
|
guard let selfController else {
|
||||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
return
|
||||||
})
|
|
||||||
selfController.openScheduledMessages()
|
|
||||||
}
|
}
|
||||||
}
|
selfController.supportedOrientations = previousSupportedOrientations
|
||||||
}, schedule: { [weak selfController] messageEffect in
|
},
|
||||||
guard let selfController else {
|
sendMessage: { [weak selfController] mode, messageEffect in
|
||||||
return
|
guard let selfController else {
|
||||||
}
|
return
|
||||||
selfController.controllerInteraction?.scheduleCurrentMessage()
|
}
|
||||||
}, reactionItems: effectItems, availableMessageEffects: availableMessageEffects, isPremium: hasPremium)
|
switch mode {
|
||||||
|
case .generic:
|
||||||
|
selfController.controllerInteraction?.sendCurrentMessage(false, messageEffect.flatMap(ChatSendMessageEffect.init))
|
||||||
|
case .silently:
|
||||||
|
selfController.controllerInteraction?.sendCurrentMessage(true, messageEffect.flatMap(ChatSendMessageEffect.init))
|
||||||
|
case .whenOnline:
|
||||||
|
selfController.chatDisplayNode.sendCurrentMessage(scheduleTime: scheduleWhenOnlineTimestamp, messageEffect: messageEffect.flatMap(ChatSendMessageEffect.init)) { [weak selfController] in
|
||||||
|
guard let selfController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selfController.updateChatPresentationInterfaceState(animated: true, interactive: false, saveInterfaceState: selfController.presentationInterfaceState.subject != .scheduledMessages, {
|
||||||
|
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
||||||
|
})
|
||||||
|
selfController.openScheduledMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
schedule: { [weak selfController] messageEffect in
|
||||||
|
guard let selfController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selfController.controllerInteraction?.scheduleCurrentMessage()
|
||||||
|
},
|
||||||
|
reactionItems: effectItems,
|
||||||
|
availableMessageEffects: availableMessageEffects,
|
||||||
|
isPremium: hasPremium
|
||||||
|
)
|
||||||
selfController.sendMessageActionsController = controller
|
selfController.sendMessageActionsController = controller
|
||||||
if layout.isNonExclusive {
|
if layout.isNonExclusive {
|
||||||
selfController.present(controller, in: .window(.root))
|
selfController.present(controller, in: .window(.root))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user