Refactoring

This commit is contained in:
Ali 2023-10-13 16:49:57 +04:00
parent e2243b4205
commit cd215242ac
8 changed files with 160 additions and 86 deletions

View File

@ -363,6 +363,8 @@ swift_library(
"//submodules/TelegramUI/Components/Chat/ChatMessageCallBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageInteractiveInstantVideoNode",
"//submodules/TelegramUI/Components/Chat/InstantVideoRadialStatusNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode",
] + select({
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
"//build-system:ios_sim_arm64": [],

View File

@ -0,0 +1,29 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatMessageFileBubbleContentNode",
module_name = "ChatMessageFileBubbleContentNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/Postbox",
"//submodules/TelegramCore",
"//submodules/TelegramUIPreferences",
"//submodules/ComponentFlow",
"//submodules/TelegramUI/Components/AudioTranscriptionButtonComponent",
"//submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
"//submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode",
],
visibility = [
"//visibility:public",
],
)

View File

@ -11,11 +11,12 @@ import AudioTranscriptionButtonComponent
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
import ChatMessageInteractiveFileNode
class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
let interactiveFileNode: ChatMessageInteractiveFileNode
public class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
public let interactiveFileNode: ChatMessageInteractiveFileNode
override var visibility: ListViewItemNodeVisibility {
override public var visibility: ListViewItemNodeVisibility {
didSet {
var wasVisible = false
if case .visible = oldValue {
@ -31,7 +32,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
}
}
required init() {
required public init() {
self.interactiveFileNode = ChatMessageInteractiveFileNode()
super.init()
@ -83,18 +84,18 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func accessibilityActivate() -> Bool {
override public func accessibilityActivate() -> Bool {
if let item = self.item {
let _ = item.controllerInteraction.openMessage(item.message, .default)
}
return 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 interactiveFileLayout = self.interactiveFileNode.asyncLayout()
return { item, layoutConstants, preparePosition, selection, constrainedSize, _ in
@ -186,7 +187,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
if self.item?.message.id == messageId {
return self.interactiveFileNode.transitionNode(media: media)
} else {
@ -194,31 +195,31 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func updateHiddenMedia(_ media: [Media]?) -> Bool {
override public func updateHiddenMedia(_ media: [Media]?) -> Bool {
return self.interactiveFileNode.updateHiddenMedia(media)
}
override func animateInsertion(_ currentTimestamp: Double, duration: Double) {
override public func animateInsertion(_ currentTimestamp: Double, duration: Double) {
self.interactiveFileNode.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.interactiveFileNode.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.interactiveFileNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
}
override func willUpdateIsExtractedToContextPreview(_ value: Bool) {
override public func willUpdateIsExtractedToContextPreview(_ value: Bool) {
self.interactiveFileNode.willUpdateIsExtractedToContextPreview(value)
}
override func updateIsExtractedToContextPreview(_ value: Bool) {
override public func updateIsExtractedToContextPreview(_ value: Bool) {
self.interactiveFileNode.updateIsExtractedToContextPreview(value)
}
override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
override public func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
if self.interactiveFileNode.dateAndStatusNode.supernode != nil, let _ = self.interactiveFileNode.dateAndStatusNode.hitTest(self.view.convert(point, to: self.interactiveFileNode.dateAndStatusNode.view), with: nil) {
return .ignore
}
@ -228,14 +229,14 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
return super.tapActionAtPoint(point, gesture: gesture, isEstimating: isEstimating)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let result = self.interactiveFileNode.hitTest(self.view.convert(point, to: self.interactiveFileNode.view), with: event) {
return result
}
return super.hitTest(point, with: event)
}
override func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
override public func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
if !self.interactiveFileNode.dateAndStatusNode.isHidden {
return self.interactiveFileNode.dateAndStatusNode.reactionView(value: value)
}

View File

@ -0,0 +1,49 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatMessageInteractiveFileNode",
module_name = "ChatMessageInteractiveFileNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Postbox",
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/Display",
"//submodules/TelegramCore",
"//submodules/MediaPlayer:UniversalMediaPlayer",
"//submodules/TelegramPresentationData",
"//submodules/AccountContext",
"//submodules/PhotoResources",
"//submodules/TelegramStringFormatting",
"//submodules/RadialStatusNode",
"//submodules/SemanticStatusNode",
"//submodules/FileMediaResourceStatus",
"//submodules/CheckNode",
"//submodules/MusicAlbumArtResources",
"//submodules/AudioBlob",
"//submodules/ContextUI",
"//submodules/ChatPresentationInterfaceState",
"//submodules/ComponentFlow",
"//submodules/TelegramUI/Components/AudioTranscriptionButtonComponent",
"//submodules/TelegramUI/Components/AudioWaveformComponent",
"//submodules/ShimmerEffect",
"//submodules/Media/ConvertOpusToAAC",
"//submodules/Media/LocalAudioTranscription",
"//submodules/TextSelectionNode",
"//submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent",
"//submodules/UndoUI",
"//submodules/TelegramNotices",
"//submodules/TelegramUI/Components/ChatControllerInteraction",
"//submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode",
"//submodules/TelegramUI/Components/Chat/ChatHistoryEntry",
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
],
visibility = [
"//visibility:public",
],
)

View File

@ -32,37 +32,36 @@ import ChatControllerInteraction
import ChatMessageDateAndStatusNode
import ChatHistoryEntry
import ChatMessageItemCommon
import ChatMessageInteractiveInstantVideoNode
private struct FetchControls {
let fetch: (Bool) -> Void
let cancel: () -> Void
}
final class ChatMessageInteractiveFileNode: ASDisplayNode {
final class Arguments {
let context: AccountContext
let presentationData: ChatPresentationData
let message: Message
let topMessage: Message
let associatedData: ChatMessageItemAssociatedData
let chatLocation: ChatLocation
let attributes: ChatMessageEntryAttributes
let isPinned: Bool
let forcedIsEdited: Bool
let file: TelegramMediaFile
let automaticDownload: Bool
let incoming: Bool
let isRecentActions: Bool
let forcedResourceStatus: FileMediaResourceStatus?
let dateAndStatusType: ChatMessageDateAndStatusType?
let displayReactions: Bool
let messageSelection: Bool?
let layoutConstants: ChatMessageItemLayoutConstants
let constrainedSize: CGSize
let controllerInteraction: ChatControllerInteraction
public final class ChatMessageInteractiveFileNode: ASDisplayNode {
public final class Arguments {
public let context: AccountContext
public let presentationData: ChatPresentationData
public let message: Message
public let topMessage: Message
public let associatedData: ChatMessageItemAssociatedData
public let chatLocation: ChatLocation
public let attributes: ChatMessageEntryAttributes
public let isPinned: Bool
public let forcedIsEdited: Bool
public let file: TelegramMediaFile
public let automaticDownload: Bool
public let incoming: Bool
public let isRecentActions: Bool
public let forcedResourceStatus: FileMediaResourceStatus?
public let dateAndStatusType: ChatMessageDateAndStatusType?
public let displayReactions: Bool
public let messageSelection: Bool?
public let layoutConstants: ChatMessageItemLayoutConstants
public let constrainedSize: CGSize
public let controllerInteraction: ChatControllerInteraction
init(
public init(
context: AccountContext,
presentationData: ChatPresentationData,
message: Message,
@ -112,31 +111,25 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
private let titleNode: TextNode
private let descriptionNode: TextNode
private let descriptionMeasuringNode: TextNode
let fetchingTextNode: ImmediateTextNode
let fetchingCompactTextNode: ImmediateTextNode
public let fetchingTextNode: ImmediateTextNode
public let fetchingCompactTextNode: ImmediateTextNode
var waveformView: ComponentHostView<Empty>?
public var waveformView: ComponentHostView<Empty>?
/*private let waveformNode: AudioWaveformNode
private let waveformForegroundNode: AudioWaveformNode
private var waveformShimmerNode: ShimmerEffectNode?
private var waveformMaskNode: AudioWaveformNode?
private var waveformScrubbingNode: MediaPlayerScrubbingNode?*/
var audioTranscriptionButton: ComponentHostView<Empty>?
public var audioTranscriptionButton: ComponentHostView<Empty>?
private var transcriptionPendingIndicator: ComponentHostView<Empty>?
let textNode: TextNode
let textClippingNode: ASDisplayNode
public let textNode: TextNode
public let textClippingNode: ASDisplayNode
private var textSelectionNode: TextSelectionNode?
var updateIsTextSelectionActive: ((Bool) -> Void)?
public var updateIsTextSelectionActive: ((Bool) -> Void)?
let dateAndStatusNode: ChatMessageDateAndStatusNode
public let dateAndStatusNode: ChatMessageDateAndStatusNode
private let consumableContentNode: ASImageNode
private var iconNode: TransformImageNode?
let statusContainerNode: ContextExtractedContentContainingNode
var statusNode: SemanticStatusNode?
public let statusContainerNode: ContextExtractedContentContainingNode
public var statusNode: SemanticStatusNode?
private var playbackAudioLevelNode: VoiceBlobNode?
private var streamingStatusNode: SemanticStatusNode?
private var tapRecognizer: UITapGestureRecognizer?
@ -164,7 +157,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
private var inputAudioLevel: CGFloat = 0.0
private var currentAudioLevel: CGFloat = 0.0
var visibility: Bool = false {
public var visibility: Bool = false {
didSet {
guard self.visibility != oldValue else { return }
@ -179,12 +172,12 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
private var actualFetchStatus: MediaResourceStatus?
private let fetchDisposable = MetaDisposable()
var toggleSelection: (Bool) -> Void = { _ in }
var activateLocalContent: () -> Void = { }
var requestUpdateLayout: (Bool) -> Void = { _ in }
var displayImportedTooltip: (ASDisplayNode) -> Void = { _ in }
public var toggleSelection: (Bool) -> Void = { _ in }
public var activateLocalContent: () -> Void = { }
public var requestUpdateLayout: (Bool) -> Void = { _ in }
public var displayImportedTooltip: (ASDisplayNode) -> Void = { _ in }
var updateTranscriptionExpanded: ((AudioTranscriptionButtonComponent.TranscriptionState) -> Void)?
public var updateTranscriptionExpanded: ((AudioTranscriptionButtonComponent.TranscriptionState) -> Void)?
private var context: AccountContext?
private var message: Message?
@ -195,10 +188,10 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
private var streamingCacheStatusFrame: CGRect?
private var fileIconImage: UIImage?
var audioTranscriptionState: AudioTranscriptionButtonComponent.TranscriptionState = .collapsed
var forcedAudioTranscriptionText: TranscribedText?
public var audioTranscriptionState: AudioTranscriptionButtonComponent.TranscriptionState = .collapsed
public var forcedAudioTranscriptionText: TranscribedText?
private var transcribeDisposable: Disposable?
var hasExpandedAudioTranscription: Bool {
public var hasExpandedAudioTranscription: Bool {
if case .expanded = audioTranscriptionState {
return true
} else {
@ -209,7 +202,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
private var hapticFeedback: HapticFeedback?
override init() {
override public init() {
self.titleNode = TextNode()
self.titleNode.displaysAsynchronously = false
self.titleNode.isUserInteractionEnabled = false
@ -272,13 +265,13 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
self.transcribeDisposable?.dispose()
}
override func didLoad() {
override public func didLoad() {
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.fileTap(_:)))
self.view.addGestureRecognizer(tapRecognizer)
self.tapRecognizer = tapRecognizer
}
@objc func cacheProgressPressed() {
@objc private func cacheProgressPressed() {
guard let resourceStatus = self.resourceStatus else {
return
}
@ -296,7 +289,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
}
}
@objc func progressPressed() {
@objc private func progressPressed() {
if let resourceStatus = self.resourceStatus {
switch resourceStatus.mediaStatus {
case let .fetchStatus(fetchStatus):
@ -324,7 +317,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
}
}
@objc func fileTap(_ recognizer: UITapGestureRecognizer) {
@objc private func fileTap(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
if let streamingCacheStatusFrame = self.streamingCacheStatusFrame, streamingCacheStatusFrame.contains(recognizer.location(in: self.view)) {
self.cacheProgressPressed()
@ -470,7 +463,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
}
}
func asyncLayout() -> (Arguments) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool, ListViewItemUpdateAnimation, ListViewItemApply?) -> Void))) {
public func asyncLayout() -> (Arguments) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool, ListViewItemUpdateAnimation, ListViewItemApply?) -> Void))) {
let currentFile = self.file
let titleAsyncLayout = TextNode.asyncLayout(self.titleNode)
@ -1714,7 +1707,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
self.fetchingCompactTextNode.frame = CGRect(origin: self.descriptionNode.frame.origin, size: fetchingCompactSize)
}
static func asyncLayout(_ node: ChatMessageInteractiveFileNode?) -> (Arguments) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool, ListViewItemUpdateAnimation, ListViewItemApply?) -> ChatMessageInteractiveFileNode))) {
public static func asyncLayout(_ node: ChatMessageInteractiveFileNode?) -> (Arguments) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool, ListViewItemUpdateAnimation, ListViewItemApply?) -> ChatMessageInteractiveFileNode))) {
let currentAsyncLayout = node?.asyncLayout()
return { arguments in
@ -1746,7 +1739,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
}
}
func willUpdateIsExtractedToContextPreview(_ value: Bool) {
public func willUpdateIsExtractedToContextPreview(_ value: Bool) {
if !value {
if let textSelectionNode = self.textSelectionNode {
self.textSelectionNode = nil
@ -1759,7 +1752,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
}
}
func updateIsExtractedToContextPreview(_ value: Bool) {
public func updateIsExtractedToContextPreview(_ value: Bool) {
if value {
if self.textSelectionNode == nil, self.textClippingNode.supernode != nil, let item = self.arguments, !item.associatedData.isCopyProtectionEnabled && !item.message.isCopyProtected(), let rootNode = item.controllerInteraction.chatControllerNode() {
let selectionColor: UIColor
@ -1804,7 +1797,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
}
}
func transitionNode(media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
public func transitionNode(media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
if let iconNode = self.iconNode, let file = self.file, file.isEqual(to: media) {
return (iconNode, iconNode.bounds, { [weak iconNode] in
return (iconNode?.view.snapshotContentTree(unhide: true), nil)
@ -1814,7 +1807,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
}
}
func updateHiddenMedia(_ media: [Media]?) -> Bool {
public func updateHiddenMedia(_ media: [Media]?) -> Bool {
var isHidden = false
if let file = self.file, let media = media {
for m in media {
@ -1843,7 +1836,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
self.playerUpdateTimer = nil
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.dateAndStatusNode.supernode != nil {
if let result = self.dateAndStatusNode.hitTest(self.view.convert(point, to: self.dateAndStatusNode.view), with: event) {
return result
@ -1862,27 +1855,23 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
return super.hitTest(point, with: event)
}
func hasTapAction(at point: CGPoint) -> Bool {
public func hasTapAction(at point: CGPoint) -> Bool {
if let _ = self.dateAndStatusNode.hitTest(self.view.convert(point, to: self.dateAndStatusNode.view), with: nil) {
return true
}
return false
}
func animateSent() {
public func animateSent() {
if let view = self.waveformView?.componentView as? AudioWaveformComponent.View {
view.animateIn()
}
}
func animateTo(_ node: ChatMessageInteractiveInstantVideoNode) {
}
}
final class FileMessageSelectionNode: ASDisplayNode {
enum NodeType {
public final class FileMessageSelectionNode: ASDisplayNode {
public enum NodeType {
case media
case file
case voice

View File

@ -24,6 +24,7 @@ import ChatHistoryEntry
import ChatMessageItemCommon
import ChatMessageBubbleContentNode
import ChatMessageInteractiveInstantVideoNode
import ChatMessageInteractiveFileNode
private let buttonFont = Font.semibold(13.0)

View File

@ -37,6 +37,8 @@ import ChatMessageTextBubbleContentNode
import ChatMessageItemCommon
import ChatMessageReplyInfoNode
import ChatMessageCallBubbleContentNode
import ChatMessageInteractiveFileNode
import ChatMessageFileBubbleContentNode
enum InternalBubbleTapAction {
case action(() -> Void)

View File

@ -12,6 +12,7 @@ import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
import ChatMessageInteractiveInstantVideoNode
import ChatMessageInteractiveFileNode
extension ChatMessageInteractiveInstantVideoNode.AnimateFileNodeDescription {
convenience init(_ node: ChatMessageInteractiveFileNode) {