mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-21 10:41:12 +00:00
Various improvements
This commit is contained in:
parent
0a1be88185
commit
4fdbe44825
@ -14383,7 +14383,7 @@ Sorry for the inconvenience.";
|
|||||||
"ChannelMessages.PriceSectionTitle" = "PRICE FOR EACH MESSAGE";
|
"ChannelMessages.PriceSectionTitle" = "PRICE FOR EACH MESSAGE";
|
||||||
"ChannelMessages.PriceSectionFooter" = "You will receive 85% of the selected fee for each incoming message.";
|
"ChannelMessages.PriceSectionFooter" = "You will receive 85% of the selected fee for each incoming message.";
|
||||||
|
|
||||||
"ChatList.MonoforumLabel" = "MESSAGES";
|
"ChatList.MonoforumLabel" = "DIRECT";
|
||||||
"ChatList.MonoforumEmptyText" = "No messages here yet...";
|
"ChatList.MonoforumEmptyText" = "No messages here yet...";
|
||||||
|
|
||||||
"Chat.InlineTopicMenu.Reorder" = "Reorder";
|
"Chat.InlineTopicMenu.Reorder" = "Reorder";
|
||||||
@ -14400,6 +14400,7 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Chat.EmptyStateMonoforum.Text" = "Send a direct message to the administrator of **%@**.";
|
"Chat.EmptyStateMonoforum.Text" = "Send a direct message to the administrator of **%@**.";
|
||||||
"Chat.EmptyStateMonoforumPaid.Text" = "**%1$@** charges **%2$@**\nper message to its admin.";
|
"Chat.EmptyStateMonoforumPaid.Text" = "**%1$@** charges **%2$@**\nper message to its admin.";
|
||||||
|
"Chat.Monoforum.Subtitle" = "Direct messages";
|
||||||
|
|
||||||
"Monoforum.NameFormat" = "%@ Messages";
|
"Monoforum.NameFormat" = "%@ Messages";
|
||||||
|
|
||||||
|
@ -97,22 +97,14 @@ open class TransformImageNode: ASDisplayNode {
|
|||||||
self.disposable.set((result |> deliverOnMainQueue).start(next: { [weak self] next in
|
self.disposable.set((result |> deliverOnMainQueue).start(next: { [weak self] next in
|
||||||
let apply: () -> Void = {
|
let apply: () -> Void = {
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
var animateFromContents: Any?
|
||||||
|
|
||||||
if strongSelf.contents == nil {
|
if strongSelf.contents == nil {
|
||||||
if strongSelf.contentAnimations.contains(.firstUpdate) && !attemptSynchronously {
|
if strongSelf.contentAnimations.contains(.firstUpdate) && !attemptSynchronously {
|
||||||
strongSelf.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
strongSelf.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||||
}
|
}
|
||||||
} else if strongSelf.contentAnimations.contains(.subsequentUpdates) {
|
} else if strongSelf.contentAnimations.contains(.subsequentUpdates) {
|
||||||
let tempLayer = CALayer()
|
animateFromContents = strongSelf.contents
|
||||||
if strongSelf.captureProtected {
|
|
||||||
setLayerDisableScreenshots(tempLayer, strongSelf.captureProtected)
|
|
||||||
}
|
|
||||||
tempLayer.frame = strongSelf.bounds
|
|
||||||
tempLayer.contentsGravity = strongSelf.layer.contentsGravity
|
|
||||||
tempLayer.contents = strongSelf.contents
|
|
||||||
strongSelf.layer.addSublayer(tempLayer)
|
|
||||||
tempLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak tempLayer] _ in
|
|
||||||
tempLayer?.removeFromSuperlayer()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageUpdate: UIImage?
|
var imageUpdate: UIImage?
|
||||||
@ -129,6 +121,23 @@ open class TransformImageNode: ASDisplayNode {
|
|||||||
if let imageUpdated = strongSelf.imageUpdated {
|
if let imageUpdated = strongSelf.imageUpdated {
|
||||||
imageUpdated(imageUpdate)
|
imageUpdated(imageUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let animateFromContents {
|
||||||
|
let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .linear)
|
||||||
|
transition.animateContents(layer: strongSelf.layer, from: animateFromContents)
|
||||||
|
|
||||||
|
/*let tempLayer = CALayer()
|
||||||
|
if strongSelf.captureProtected {
|
||||||
|
setLayerDisableScreenshots(tempLayer, strongSelf.captureProtected)
|
||||||
|
}
|
||||||
|
tempLayer.frame = strongSelf.bounds
|
||||||
|
tempLayer.contentsGravity = strongSelf.layer.contentsGravity
|
||||||
|
tempLayer.contents = animateFromContents
|
||||||
|
strongSelf.layer.addSublayer(tempLayer)
|
||||||
|
tempLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak tempLayer] _ in
|
||||||
|
tempLayer?.removeFromSuperlayer()
|
||||||
|
})*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dispatchOnDisplayLink && !attemptSynchronously {
|
if dispatchOnDisplayLink && !attemptSynchronously {
|
||||||
@ -168,6 +177,34 @@ open class TransformImageNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func asyncLayoutWithAnimation() -> (TransformImageArguments) -> ((ListViewItemUpdateAnimation) -> Void) {
|
||||||
|
let currentTransform = self.currentTransform
|
||||||
|
let currentArguments = self.currentArguments
|
||||||
|
return { [weak self] arguments in
|
||||||
|
let updatedImage: UIImage?
|
||||||
|
|
||||||
|
if currentArguments != arguments {
|
||||||
|
updatedImage = currentTransform?(arguments)?.generateImage()
|
||||||
|
} else {
|
||||||
|
updatedImage = nil
|
||||||
|
}
|
||||||
|
return { animation in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let image = updatedImage {
|
||||||
|
self.contents = image.cgImage
|
||||||
|
self.image = image
|
||||||
|
self.currentArguments = arguments
|
||||||
|
if let _ = self.overlayColor {
|
||||||
|
self.applyOverlayColor(animated: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.argumentsPromise.set(arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class func asyncLayout(_ maybeNode: TransformImageNode?) -> (TransformImageArguments) -> (() -> TransformImageNode) {
|
public class func asyncLayout(_ maybeNode: TransformImageNode?) -> (TransformImageArguments) -> (() -> TransformImageNode) {
|
||||||
return { arguments in
|
return { arguments in
|
||||||
let node: TransformImageNode
|
let node: TransformImageNode
|
||||||
|
@ -402,7 +402,7 @@ public final class MediaPlayerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateLayout() {
|
public func updateLayout() {
|
||||||
let bounds = self.bounds
|
let bounds = self.bounds
|
||||||
if bounds.isEmpty {
|
if bounds.isEmpty {
|
||||||
return
|
return
|
||||||
|
@ -858,7 +858,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
public func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ media: Media, _ mediaIndex: Int?, _ dateAndStatus: ChatMessageDateAndStatus?, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ peerId: EnginePeer.Id?, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode, _ presentationContext: ChatPresentationContext) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))) {
|
public func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ media: Media, _ mediaIndex: Int?, _ dateAndStatus: ChatMessageDateAndStatus?, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ peerId: EnginePeer.Id?, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode, _ presentationContext: ChatPresentationContext) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))) {
|
||||||
let currentMessage = self.message
|
let currentMessage = self.message
|
||||||
let currentMedia = self.media
|
let currentMedia = self.media
|
||||||
let imageLayout = self.imageNode.asyncLayout()
|
let imageLayout = self.imageNode.asyncLayoutWithAnimation()
|
||||||
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
||||||
|
|
||||||
let currentVideoNode = self.videoNode
|
let currentVideoNode = self.videoNode
|
||||||
@ -1894,7 +1894,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
timestampMaskView.image = strongSelf.generateTimestampMaskImage(corners: arguments.corners)
|
timestampMaskView.image = strongSelf.generateTimestampMaskImage(corners: arguments.corners)
|
||||||
}
|
}
|
||||||
strongSelf.currentImageArguments = arguments
|
strongSelf.currentImageArguments = arguments
|
||||||
imageApply()
|
imageApply(transition)
|
||||||
|
|
||||||
if let statusApply = statusApply {
|
if let statusApply = statusApply {
|
||||||
let dateAndStatusFrame = CGRect(origin: CGPoint(x: cleanImageFrame.width - layoutConstants.image.statusInsets.right - statusSize.width, y: cleanImageFrame.height - layoutConstants.image.statusInsets.bottom - statusSize.height), size: statusSize)
|
let dateAndStatusFrame = CGRect(origin: CGPoint(x: cleanImageFrame.width - layoutConstants.image.statusInsets.right - statusSize.width, y: cleanImageFrame.height - layoutConstants.image.statusInsets.bottom - statusSize.height), size: statusSize)
|
||||||
@ -2084,8 +2084,13 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
strongSelf.imageNode.cornerRadius = 0.0
|
strongSelf.imageNode.cornerRadius = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if videoNode.bounds.isEmpty {
|
||||||
videoNode.updateLayout(size: arguments.drawingSize, transition: .immediate)
|
videoNode.updateLayout(size: arguments.drawingSize, transition: .immediate)
|
||||||
videoNode.frame = CGRect(origin: CGPoint(), size: imageFrame.size)
|
videoNode.frame = CGRect(origin: CGPoint(), size: imageFrame.size)
|
||||||
|
} else {
|
||||||
|
videoNode.updateLayout(size: arguments.drawingSize, transition: transition.transition)
|
||||||
|
transition.animator.updateFrame(layer: videoNode.layer, frame: CGRect(origin: CGPoint(), size: imageFrame.size), completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
if strongSelf.visibility && strongSelf.internallyVisible && !presentationData.isPreview {
|
if strongSelf.visibility && strongSelf.internallyVisible && !presentationData.isPreview {
|
||||||
if !videoNode.canAttachContent {
|
if !videoNode.canAttachContent {
|
||||||
|
@ -1359,7 +1359,7 @@ public final class ChatSideTopicsPanel: Component {
|
|||||||
maximumNumberOfLines: 2
|
maximumNumberOfLines: 2
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 200.0, height: 200.0)
|
containerSize: CGSize(width: 400.0, height: 200.0)
|
||||||
)
|
)
|
||||||
|
|
||||||
let contentSize: CGFloat = leftInset + rightInset + titleSize.height
|
let contentSize: CGFloat = leftInset + rightInset + titleSize.height
|
||||||
|
@ -68,6 +68,8 @@ public enum ChatTitleContent: Equatable {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.peerPresences.count != rhs.peerPresences.count {
|
if lhs.peerPresences.count != rhs.peerPresences.count {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
for (key, value) in lhs.peerPresences {
|
for (key, value) in lhs.peerPresences {
|
||||||
if let rhsValue = rhs.peerPresences[key] {
|
if let rhsValue = rhs.peerPresences[key] {
|
||||||
if !value.isEqual(to: rhsValue) {
|
if !value.isEqual(to: rhsValue) {
|
||||||
|
@ -397,18 +397,27 @@ extension ChatControllerImpl {
|
|||||||
self.navigationActionDisposable.set((peerView.get()
|
self.navigationActionDisposable.set((peerView.get()
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).startStrict(next: { [weak self] peerView in
|
|> deliverOnMainQueue).startStrict(next: { [weak self] peerView in
|
||||||
if let strongSelf = self, let peer = peerView.peers[peerView.peerId], peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && !strongSelf.presentationInterfaceState.isNotAccessible {
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard var peer = peerView.peers[peerView.peerId] else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let channel = peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainPeer = peerView.peers[linkedMonoforumId] {
|
||||||
|
peer = mainPeer
|
||||||
|
}
|
||||||
|
|
||||||
if peer.id == strongSelf.context.account.peerId {
|
if peer.restrictionText(platform: "ios", contentSettings: self.context.currentContentSettings.with { $0 }) == nil && !self.presentationInterfaceState.isNotAccessible {
|
||||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) {
|
if peer.id == self.context.account.peerId {
|
||||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) {
|
||||||
|
self.effectiveNavigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var expandAvatar = expandAvatar
|
var expandAvatar = expandAvatar
|
||||||
if peer.smallProfileImage == nil {
|
if peer.smallProfileImage == nil {
|
||||||
expandAvatar = false
|
expandAvatar = false
|
||||||
}
|
}
|
||||||
if let validLayout = strongSelf.validLayout, validLayout.deviceMetrics.type == .tablet {
|
if let validLayout = self.validLayout, validLayout.deviceMetrics.type == .tablet {
|
||||||
expandAvatar = false
|
expandAvatar = false
|
||||||
}
|
}
|
||||||
let mode: PeerInfoControllerMode
|
let mode: PeerInfoControllerMode
|
||||||
@ -420,12 +429,12 @@ extension ChatControllerImpl {
|
|||||||
default:
|
default:
|
||||||
mode = .generic
|
mode = .generic
|
||||||
}
|
}
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: mode, avatarInitiallyExpanded: expandAvatar, fromChat: true, requestsContext: strongSelf.contentData?.inviteRequestsContext) {
|
if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: peer, mode: mode, avatarInitiallyExpanded: expandAvatar, fromChat: true, requestsContext: self.contentData?.inviteRequestsContext) {
|
||||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
self.effectiveNavigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = strongSelf.dismissPreviewing?(false)
|
let _ = self.dismissPreviewing?(false)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
case .replyThread:
|
case .replyThread:
|
||||||
|
@ -548,9 +548,9 @@ extension ChatControllerImpl {
|
|||||||
strongSelf.state.chatTitleContent = .custom(strings.Chat_TitlePinnedMessages(Int32(displayedCount ?? 1)), nil, false)
|
strongSelf.state.chatTitleContent = .custom(strings.Chat_TitlePinnedMessages(Int32(displayedCount ?? 1)), nil, false)
|
||||||
} else if let channel = peer as? TelegramChannel, channel.isMonoForum {
|
} else if let channel = peer as? TelegramChannel, channel.isMonoForum {
|
||||||
if let linkedMonoforumId = channel.linkedMonoforumId, let mainPeer = peerView.peers[linkedMonoforumId] {
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainPeer = peerView.peers[linkedMonoforumId] {
|
||||||
strongSelf.state.chatTitleContent = .custom(mainPeer.debugDisplayTitle, "Direct messages", false)
|
strongSelf.state.chatTitleContent = .custom(mainPeer.debugDisplayTitle, strings.Chat_Monoforum_Subtitle, true)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.state.chatTitleContent = .custom(channel.debugDisplayTitle, nil, false)
|
strongSelf.state.chatTitleContent = .custom(channel.debugDisplayTitle, nil, true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strongSelf.state.chatTitleContent = .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages, isMuted: nil, customMessageCount: nil, isEnabled: hasPeerInfo)
|
strongSelf.state.chatTitleContent = .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages, isMuted: nil, customMessageCount: nil, isEnabled: hasPeerInfo)
|
||||||
|
@ -2553,16 +2553,8 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
titleTopicsAccessoryPanelNode.updateGlobalOffset(globalOffset: -titleTopicsAccessoryPanelFrame.height, transition: .immediate)
|
titleTopicsAccessoryPanelNode.updateGlobalOffset(globalOffset: -titleTopicsAccessoryPanelFrame.height, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
let topPanelTransition = ComponentTransition(transition)
|
ComponentTransition(transition).setFrame(view: titleTopicsAccessoryPanelNode.view, frame: titleTopicsAccessoryPanelFrame)
|
||||||
/*switch topPanelTransition.animation {
|
titleTopicsAccessoryPanelNode.updateGlobalOffset(globalOffset: 0.0, transition: ComponentTransition(transition))
|
||||||
case let .curve(duration, _):
|
|
||||||
topPanelTransition = topPanelTransition.withAnimation(.curve(duration: duration, curve: ComponentTransition.Animation.Curve(ChatMessageTransitionNodeImpl.verticalAnimationCurve)))
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}*/
|
|
||||||
|
|
||||||
topPanelTransition.setFrame(view: titleTopicsAccessoryPanelNode.view, frame: titleTopicsAccessoryPanelFrame)
|
|
||||||
titleTopicsAccessoryPanelNode.updateGlobalOffset(globalOffset: 0.0, transition: topPanelTransition)
|
|
||||||
} else {
|
} else {
|
||||||
let previousFrame = titleTopicsAccessoryPanelNode.frame
|
let previousFrame = titleTopicsAccessoryPanelNode.frame
|
||||||
titleTopicsAccessoryPanelNode.frame = titleTopicsAccessoryPanelFrame
|
titleTopicsAccessoryPanelNode.frame = titleTopicsAccessoryPanelFrame
|
||||||
|
@ -681,6 +681,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
|
|
||||||
private var loadedMessagesFromCachedDataDisposable: Disposable?
|
private var loadedMessagesFromCachedDataDisposable: Disposable?
|
||||||
|
|
||||||
|
private var isSettingTopReplyThreadMessageShown: Bool = false
|
||||||
let isTopReplyThreadMessageShown = ValuePromise<Bool>(false, ignoreRepeated: true)
|
let isTopReplyThreadMessageShown = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||||
|
|
||||||
private var topVisibleMessageRangeValueInitialized: Bool = false
|
private var topVisibleMessageRangeValueInitialized: Bool = false
|
||||||
@ -3178,8 +3179,15 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.isSettingTopReplyThreadMessageShown {
|
||||||
|
self.isSettingTopReplyThreadMessageShown = true
|
||||||
self.isTopReplyThreadMessageShown.set(isTopReplyThreadMessageShownValue)
|
self.isTopReplyThreadMessageShown.set(isTopReplyThreadMessageShownValue)
|
||||||
|
self.isSettingTopReplyThreadMessageShown = false
|
||||||
|
} else {
|
||||||
|
#if DEBUG
|
||||||
|
print("Ignore repeated isTopReplyThreadMessageShown update")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
self.updateTopVisibleMessageRange(topVisibleMessageRange)
|
self.updateTopVisibleMessageRange(topVisibleMessageRange)
|
||||||
let _ = self.visibleMessageRange.swap(topVisibleMessageRange.flatMap { range in
|
let _ = self.visibleMessageRange.swap(topVisibleMessageRange.flatMap { range in
|
||||||
return VisibleMessageRange(lowerBound: range.lowerBound, upperBound: range.upperBound)
|
return VisibleMessageRange(lowerBound: range.lowerBound, upperBound: range.upperBound)
|
||||||
|
@ -1591,7 +1591,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let message = messages.first, message.id.namespace == Namespaces.Message.Cloud, let channel = message.peers[message.id.peerId] as? TelegramChannel, !(message.media.first is TelegramMediaAction), !isReplyThreadHead, !isMigrated {
|
if let message = messages.first, message.id.namespace == Namespaces.Message.Cloud, let channel = message.peers[message.id.peerId] as? TelegramChannel, !channel.isMonoForum, !(message.media.first is TelegramMediaAction), !isReplyThreadHead, !isMigrated {
|
||||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopyLink, icon: { theme in
|
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopyLink, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
@ -1893,8 +1893,8 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
|
|
||||||
var canViewStats = false
|
var canViewStats = false
|
||||||
var canViewAuthor = false
|
var canViewAuthor = false
|
||||||
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum {
|
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let associatedPeerId = channel.associatedPeerId {
|
||||||
if message.effectivelyIncoming(context.account.peerId) {
|
if message.effectivelyIncoming(context.account.peerId), message.author?.id == associatedPeerId {
|
||||||
canViewAuthor = true
|
canViewAuthor = true
|
||||||
}
|
}
|
||||||
} else if let messageReadStatsAreHidden = infoSummaryData.messageReadStatsAreHidden, !messageReadStatsAreHidden {
|
} else if let messageReadStatsAreHidden = infoSummaryData.messageReadStatsAreHidden, !messageReadStatsAreHidden {
|
||||||
|
@ -690,22 +690,34 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent
|
|||||||
|
|
||||||
if let dimensions = self.dimensions {
|
if let dimensions = self.dimensions {
|
||||||
let imageSize = CGSize(width: floor(dimensions.width / 2.0), height: floor(dimensions.height / 2.0))
|
let imageSize = CGSize(width: floor(dimensions.width / 2.0), height: floor(dimensions.height / 2.0))
|
||||||
let makeLayout = self.imageNode.asyncLayout()
|
let makeLayout = self.imageNode.asyncLayoutWithAnimation()
|
||||||
let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: self.fileReference.media.isInstantVideo ? .clear : self.placeholderColor))
|
let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: self.fileReference.media.isInstantVideo ? .clear : self.placeholderColor))
|
||||||
applyLayout()
|
let mappedAnimation: ListViewItemUpdateAnimation
|
||||||
|
if case let .animated(duration, curve) = transition {
|
||||||
|
mappedAnimation = .System(duration: duration, transition: ControlledTransition(duration: duration, curve: curve, interactive: false))
|
||||||
|
} else {
|
||||||
|
mappedAnimation = .None
|
||||||
|
}
|
||||||
|
applyLayout(mappedAnimation)
|
||||||
}
|
}
|
||||||
|
|
||||||
transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
let fromFrame = self.playerNode.frame
|
let fromFrame = self.playerNode.frame
|
||||||
let toFrame = CGRect(origin: CGPoint(), size: size).insetBy(dx: -1.0, dy: -1.0)
|
let toFrame = CGRect(origin: CGPoint(), size: size).insetBy(dx: -1.0, dy: -1.0)
|
||||||
if case let .animated(duration, curve) = transition, fromFrame != toFrame, !fromFrame.width.isZero, !fromFrame.height.isZero, !toFrame.width.isZero, !toFrame.height.isZero {
|
if case let .animated(duration, curve) = transition, fromFrame != toFrame, !fromFrame.width.isZero, !fromFrame.height.isZero, !toFrame.width.isZero, !toFrame.height.isZero {
|
||||||
self.playerNode.frame = toFrame
|
let _ = duration
|
||||||
transition.animatePosition(node: self.playerNode, from: CGPoint(x: fromFrame.center.x - toFrame.center.x, y: fromFrame.center.y - toFrame.center.y))
|
let _ = curve
|
||||||
|
self.playerNode.position = toFrame.center
|
||||||
|
self.playerNode.bounds = CGRect(origin: CGPoint(), size: toFrame.size)
|
||||||
|
self.playerNode.updateLayout()
|
||||||
|
transition.animatePosition(node: self.playerNode, from: CGPoint(x: fromFrame.center.x, y: fromFrame.center.y))
|
||||||
|
|
||||||
let transform = CATransform3DScale(CATransform3DIdentity, fromFrame.width / toFrame.width, fromFrame.height / toFrame.height, 1.0)
|
let transform = CATransform3DScale(CATransform3DIdentity, fromFrame.width / toFrame.width, fromFrame.height / toFrame.height, 1.0)
|
||||||
self.playerNode.layer.animate(from: NSValue(caTransform3D: transform), to: NSValue(caTransform3D: CATransform3DIdentity), keyPath: "transform", timingFunction: curve.timingFunction, duration: duration)
|
self.playerNode.layer.animate(from: NSValue(caTransform3D: transform), to: NSValue(caTransform3D: CATransform3DIdentity), keyPath: "transform", timingFunction: curve.timingFunction, duration: duration)
|
||||||
} else {
|
} else {
|
||||||
transition.updateFrame(node: self.playerNode, frame: toFrame)
|
transition.updatePosition(node: self.playerNode, position: toFrame.center)
|
||||||
|
transition.updateBounds(node: self.playerNode, bounds: CGRect(origin: CGPoint(), size: toFrame.size))
|
||||||
|
self.playerNode.updateLayout()
|
||||||
}
|
}
|
||||||
if let thumbnailNode = self.thumbnailNode {
|
if let thumbnailNode = self.thumbnailNode {
|
||||||
transition.updateFrame(node: thumbnailNode, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: -1.0, dy: -1.0))
|
transition.updateFrame(node: thumbnailNode, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: -1.0, dy: -1.0))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user