mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
[WIP] Quotes
This commit is contained in:
parent
7ea8742d33
commit
b17138d501
@ -359,6 +359,8 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatContextResultPeekContent",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatInputContextPanelNode",
|
||||
"//submodules/TelegramUI/Components/Chat/ReplyAccessoryPanelNode",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMessageCallBubbleContentNode",
|
||||
] + select({
|
||||
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
||||
"//build-system:ios_sim_arm64": [],
|
||||
|
@ -0,0 +1,26 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
|
||||
swift_library(
|
||||
name = "ChatMessageCallBubbleContentNode",
|
||||
module_name = "ChatMessageCallBubbleContentNode",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/Display",
|
||||
"//submodules/TelegramCore",
|
||||
"//submodules/Postbox",
|
||||
"//submodules/TelegramPresentationData",
|
||||
"//submodules/AppBundle",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
@ -19,13 +19,13 @@ private let incomingRedIcon = generateTintedImage(image: UIImage(bundleImageName
|
||||
private let outgoingGreenIcon = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/CallOutgoingArrow"), color: UIColor(rgb: 0x36c033))
|
||||
private let outgoingRedIcon = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/CallOutgoingArrow"), color: UIColor(rgb: 0xff4747))
|
||||
|
||||
class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
private let titleNode: TextNode
|
||||
private let labelNode: TextNode
|
||||
private let iconNode: ASImageNode
|
||||
private let buttonNode: HighlightableButtonNode
|
||||
|
||||
required init() {
|
||||
required public init() {
|
||||
self.titleNode = TextNode()
|
||||
self.labelNode = TextNode()
|
||||
|
||||
@ -57,22 +57,22 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
self.buttonNode.addTarget(self, action: #selector(self.callButtonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
override func accessibilityActivate() -> Bool {
|
||||
override public func accessibilityActivate() -> Bool {
|
||||
self.callButtonPressed()
|
||||
return true
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.view.accessibilityElementsHidden = true
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||
override public func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||
|
||||
@ -236,19 +236,19 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double) {
|
||||
override public func animateInsertion(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||
override public func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
@objc func callButtonPressed() {
|
||||
@objc private func callButtonPressed() {
|
||||
if let item = self.item {
|
||||
var isVideo = false
|
||||
for media in item.message.media {
|
||||
@ -260,7 +260,7 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||
override public func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||
if self.buttonNode.frame.contains(point) {
|
||||
return .ignore
|
||||
} else if self.bounds.contains(point), let item = self.item {
|
@ -0,0 +1,36 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
|
||||
swift_library(
|
||||
name = "ReplyAccessoryPanelNode",
|
||||
module_name = "ReplyAccessoryPanelNode",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/TelegramCore",
|
||||
"//submodules/Postbox",
|
||||
"//submodules/SSignalKit/SwiftSignalKit",
|
||||
"//submodules/Display",
|
||||
"//submodules/TelegramPresentationData",
|
||||
"//submodules/TelegramUIPreferences",
|
||||
"//submodules/AccountContext",
|
||||
"//submodules/LocalizedPeerData",
|
||||
"//submodules/PhotoResources",
|
||||
"//submodules/TelegramStringFormatting",
|
||||
"//submodules/TextFormat",
|
||||
"//submodules/ChatPresentationInterfaceState",
|
||||
"//submodules/TelegramUI/Components/TextNodeWithEntities",
|
||||
"//submodules/TelegramUI/Components/AnimationCache",
|
||||
"//submodules/TelegramUI/Components/MultiAnimationRenderer",
|
||||
"//submodules/TelegramUI/Components/Chat/AccessoryPanelNode",
|
||||
"//submodules/TelegramNotices",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
|
@ -19,29 +19,29 @@ import MultiAnimationRenderer
|
||||
import AccessoryPanelNode
|
||||
import TelegramNotices
|
||||
|
||||
final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
private let messageDisposable = MetaDisposable()
|
||||
let messageId: MessageId
|
||||
let quote: EngineMessageReplyQuote?
|
||||
public let messageId: MessageId
|
||||
public let quote: EngineMessageReplyQuote?
|
||||
|
||||
private var previousMediaReference: AnyMediaReference?
|
||||
|
||||
let closeButton: HighlightableButtonNode
|
||||
let lineNode: ASImageNode
|
||||
let iconNode: ASImageNode
|
||||
let titleNode: ImmediateTextNode
|
||||
let textNode: ImmediateTextNodeWithEntities
|
||||
let imageNode: TransformImageNode
|
||||
public let closeButton: HighlightableButtonNode
|
||||
public let lineNode: ASImageNode
|
||||
public let iconNode: ASImageNode
|
||||
public let titleNode: ImmediateTextNode
|
||||
public let textNode: ImmediateTextNodeWithEntities
|
||||
public let imageNode: TransformImageNode
|
||||
|
||||
private let actionArea: AccessibilityAreaNode
|
||||
|
||||
private let context: AccountContext
|
||||
var theme: PresentationTheme
|
||||
var strings: PresentationStrings
|
||||
public var theme: PresentationTheme
|
||||
public var strings: PresentationStrings
|
||||
|
||||
private var validLayout: (size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState)?
|
||||
|
||||
init(context: AccountContext, messageId: MessageId, quote: EngineMessageReplyQuote?, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) {
|
||||
public init(context: AccountContext, messageId: MessageId, quote: EngineMessageReplyQuote?, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) {
|
||||
self.messageId = messageId
|
||||
self.quote = quote
|
||||
|
||||
@ -264,6 +264,38 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
if let (size, inset, interfaceState) = strongSelf.validLayout {
|
||||
strongSelf.updateState(size: size, inset: inset, interfaceState: interfaceState)
|
||||
}
|
||||
|
||||
let _ = (ApplicationSpecificNotice.getChatReplyOptionsTip(accountManager: strongSelf.context.sharedContext.accountManager)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] count in
|
||||
if let strongSelf = self, count < 3 {
|
||||
Queue.mainQueue().after(3.0) {
|
||||
if let snapshotView = strongSelf.textNode.view.snapshotContentTree() {
|
||||
let text: String
|
||||
//TODO:localize
|
||||
if let (size, _, _) = strongSelf.validLayout, size.width > 320.0 {
|
||||
text = "Tap here for options"
|
||||
} else {
|
||||
text = "Tap here for forwarding options"
|
||||
}
|
||||
|
||||
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor)
|
||||
|
||||
strongSelf.view.addSubview(snapshotView)
|
||||
|
||||
if let (size, inset, interfaceState) = strongSelf.validLayout {
|
||||
strongSelf.updateState(size: size, inset: inset, interfaceState: interfaceState)
|
||||
}
|
||||
|
||||
strongSelf.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
|
||||
let _ = ApplicationSpecificNotice.incrementChatReplyOptionsTip(accountManager: strongSelf.context.sharedContext.accountManager).start()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}))
|
||||
}
|
||||
@ -272,21 +304,21 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
self.messageDisposable.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||
}
|
||||
|
||||
override func animateIn() {
|
||||
override public func animateIn() {
|
||||
self.iconNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
override func animateOut() {
|
||||
override public func animateOut() {
|
||||
self.iconNode.layer.animateScale(from: 1.0, to: 0.001, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
override public func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
self.updateThemeAndStrings(theme: theme, strings: strings, force: false)
|
||||
}
|
||||
|
||||
@ -314,11 +346,11 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
return CGSize(width: constrainedSize.width, height: 45.0)
|
||||
}
|
||||
|
||||
override func updateState(size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState) {
|
||||
override public func updateState(size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState) {
|
||||
self.validLayout = (size, inset, interfaceState)
|
||||
|
||||
let bounds = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: 45.0))
|
||||
@ -361,7 +393,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
}
|
||||
|
||||
@objc func closePressed() {
|
||||
@objc private func closePressed() {
|
||||
if let dismiss = self.dismiss {
|
||||
dismiss()
|
||||
}
|
@ -104,6 +104,7 @@ import PeerReportScreen
|
||||
import PeerSelectionController
|
||||
import SaveToCameraRoll
|
||||
import ChatMessageDateAndStatusNode
|
||||
import ReplyAccessoryPanelNode
|
||||
|
||||
public enum ChatControllerPeekActions {
|
||||
case standard
|
||||
|
@ -31,6 +31,7 @@ import ChatOverscrollControl
|
||||
import ChatInputPanelNode
|
||||
import ChatInputContextPanelNode
|
||||
import TextSelectionNode
|
||||
import ReplyAccessoryPanelNode
|
||||
|
||||
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
|
||||
let itemNode: OverlayMediaItemNode
|
||||
|
@ -7,6 +7,7 @@ import ChatPresentationInterfaceState
|
||||
import ChatControllerInteraction
|
||||
import AccessoryPanelNode
|
||||
import ForwardAccessoryPanelNode
|
||||
import ReplyAccessoryPanelNode
|
||||
|
||||
func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: AccessoryPanelNode?, chatControllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> AccessoryPanelNode? {
|
||||
if let _ = chatPresentationInterfaceState.interfaceState.selectionState {
|
||||
|
@ -36,6 +36,7 @@ import ChatHistoryEntry
|
||||
import ChatMessageTextBubbleContentNode
|
||||
import ChatMessageItemCommon
|
||||
import ChatMessageReplyInfoNode
|
||||
import ChatMessageCallBubbleContentNode
|
||||
|
||||
enum InternalBubbleTapAction {
|
||||
case action(() -> Void)
|
||||
|
@ -12,6 +12,7 @@ import ReactionSelectionNode
|
||||
import ChatControllerInteraction
|
||||
import FeaturedStickersScreen
|
||||
import ChatTextInputMediaRecordingButton
|
||||
import ReplyAccessoryPanelNode
|
||||
|
||||
private func convertAnimatingSourceRect(_ rect: CGRect, fromView: UIView, toView: UIView?) -> CGRect {
|
||||
if let presentationLayer = fromView.layer.presentation() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user