mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Cleanup [skip ci]
This commit is contained in:
parent
3b2b1e3660
commit
40f0dae1af
@ -1503,9 +1503,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
let previousSelectedMessages = previousValueAndVersion?.2
|
let previousSelectedMessages = previousValueAndVersion?.2
|
||||||
|
|
||||||
if let previousVersion = previousValueAndVersion?.1 {
|
if let previousVersion = previousValueAndVersion?.1 {
|
||||||
if !GlobalExperimentalSettings.isAppStoreBuild {
|
|
||||||
precondition(update.1 >= previousVersion)
|
|
||||||
}
|
|
||||||
assert(update.1 >= previousVersion)
|
assert(update.1 >= previousVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,8 +353,6 @@ final class ChatHistorySearchContainerNode: SearchDisplayControllerContentNode {
|
|||||||
itemNode.updateHiddenMedia()
|
itemNode.updateHiddenMedia()
|
||||||
} else if let itemNode = itemNode as? ListMessageNode {
|
} else if let itemNode = itemNode as? ListMessageNode {
|
||||||
itemNode.updateHiddenMedia()
|
itemNode.updateHiddenMedia()
|
||||||
} else if let itemNode = itemNode as? GridMessageItemNode {
|
|
||||||
itemNode.updateHiddenMedia()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,10 +368,6 @@ final class ChatHistorySearchContainerNode: SearchDisplayControllerContentNode {
|
|||||||
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
||||||
transitionNode = result
|
transitionNode = result
|
||||||
}
|
}
|
||||||
} else if let itemNode = itemNode as? GridMessageItemNode {
|
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
|
||||||
transitionNode = result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return transitionNode
|
return transitionNode
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
import Display
|
|
||||||
import AsyncDisplayKit
|
|
||||||
|
|
||||||
final class GridHoleItem: GridItem {
|
|
||||||
let section: GridSection? = nil
|
|
||||||
|
|
||||||
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
|
||||||
return GridHoleItemNode()
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(node: GridItemNode) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GridHoleItemNode: GridItemNode {
|
|
||||||
private let activityIndicatorView: UIActivityIndicatorView
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
self.activityIndicatorView = UIActivityIndicatorView(style: .gray)
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.view.addSubview(self.activityIndicatorView)
|
|
||||||
self.activityIndicatorView.startAnimating()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func layout() {
|
|
||||||
super.layout()
|
|
||||||
|
|
||||||
let size = self.bounds.size
|
|
||||||
let activityIndicatorSize = self.activityIndicatorView.bounds.size
|
|
||||||
self.activityIndicatorView.frame = CGRect(origin: CGPoint(x: floor((size.width - activityIndicatorSize.width) / 2.0), y: floor((size.height - activityIndicatorSize.height) / 2.0)), size: activityIndicatorSize)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,471 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
import Display
|
|
||||||
import AsyncDisplayKit
|
|
||||||
import TelegramCore
|
|
||||||
import Postbox
|
|
||||||
import SwiftSignalKit
|
|
||||||
import TelegramPresentationData
|
|
||||||
import TelegramUIPreferences
|
|
||||||
import TelegramStringFormatting
|
|
||||||
import AccountContext
|
|
||||||
import RadialStatusNode
|
|
||||||
import PhotoResources
|
|
||||||
import GridMessageSelectionNode
|
|
||||||
import ContextUI
|
|
||||||
import ChatMessageInteractiveMediaBadge
|
|
||||||
import ChatControllerInteraction
|
|
||||||
|
|
||||||
private func mediaForMessage(_ message: Message) -> Media? {
|
|
||||||
for media in message.media {
|
|
||||||
if let media = media as? TelegramMediaImage {
|
|
||||||
return media
|
|
||||||
} else if let file = media as? TelegramMediaFile {
|
|
||||||
if file.mimeType.hasPrefix("audio/") {
|
|
||||||
return nil
|
|
||||||
} else if !file.isVideo && file.mimeType.hasPrefix("video/") {
|
|
||||||
return file
|
|
||||||
} else {
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
private let mediaBadgeBackgroundColor = UIColor(white: 0.0, alpha: 0.6)
|
|
||||||
private let mediaBadgeTextColor = UIColor.white
|
|
||||||
|
|
||||||
final class GridMessageItemSection: GridSection {
|
|
||||||
let height: CGFloat = 36.0
|
|
||||||
|
|
||||||
fileprivate let theme: PresentationTheme
|
|
||||||
private let strings: PresentationStrings
|
|
||||||
private let fontSize: PresentationFontSize
|
|
||||||
|
|
||||||
private let roundedTimestamp: Int32
|
|
||||||
private let month: Int32
|
|
||||||
private let year: Int32
|
|
||||||
|
|
||||||
var hashValue: Int {
|
|
||||||
return self.roundedTimestamp.hashValue
|
|
||||||
}
|
|
||||||
|
|
||||||
init(timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
|
|
||||||
self.theme = theme
|
|
||||||
self.strings = strings
|
|
||||||
self.fontSize = fontSize
|
|
||||||
|
|
||||||
var now = time_t(timestamp)
|
|
||||||
var timeinfoNow: tm = tm()
|
|
||||||
localtime_r(&now, &timeinfoNow)
|
|
||||||
|
|
||||||
self.roundedTimestamp = timeinfoNow.tm_year * 100 + timeinfoNow.tm_mon
|
|
||||||
self.month = timeinfoNow.tm_mon
|
|
||||||
self.year = timeinfoNow.tm_year
|
|
||||||
}
|
|
||||||
|
|
||||||
func isEqual(to: GridSection) -> Bool {
|
|
||||||
if let to = to as? GridMessageItemSection {
|
|
||||||
return self.roundedTimestamp == to.roundedTimestamp && theme === to.theme
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func node() -> ASDisplayNode {
|
|
||||||
return GridMessageItemSectionNode(theme: self.theme, strings: self.strings, fontSize: self.fontSize, roundedTimestamp: self.roundedTimestamp, month: self.month, year: self.year)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class GridMessageItemSectionNode: ASDisplayNode {
|
|
||||||
var theme: PresentationTheme
|
|
||||||
var strings: PresentationStrings
|
|
||||||
var fontSize: PresentationFontSize
|
|
||||||
let titleNode: ASTextNode
|
|
||||||
|
|
||||||
init(theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, roundedTimestamp: Int32, month: Int32, year: Int32) {
|
|
||||||
self.theme = theme
|
|
||||||
self.strings = strings
|
|
||||||
self.fontSize = fontSize
|
|
||||||
|
|
||||||
self.titleNode = ASTextNode()
|
|
||||||
self.titleNode.isUserInteractionEnabled = false
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.backgroundColor = theme.list.plainBackgroundColor.withAlphaComponent(0.9)
|
|
||||||
|
|
||||||
let sectionTitleFont = Font.regular(floor(fontSize.baseDisplaySize * 14.0 / 17.0))
|
|
||||||
|
|
||||||
let dateText = stringForMonth(strings: strings, month: month, ofYear: year)
|
|
||||||
self.addSubnode(self.titleNode)
|
|
||||||
self.titleNode.attributedText = NSAttributedString(string: dateText, font: sectionTitleFont, textColor: theme.list.itemPrimaryTextColor)
|
|
||||||
self.titleNode.maximumNumberOfLines = 1
|
|
||||||
self.titleNode.truncationMode = .byTruncatingTail
|
|
||||||
}
|
|
||||||
|
|
||||||
override func layout() {
|
|
||||||
super.layout()
|
|
||||||
|
|
||||||
let bounds = self.bounds
|
|
||||||
|
|
||||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - 24.0, height: CGFloat.greatestFiniteMagnitude))
|
|
||||||
self.titleNode.frame = CGRect(origin: CGPoint(x: 12.0, y: floor((bounds.size.height - titleSize.height) / 2.0)), size: titleSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class GridMessageItem: GridItem {
|
|
||||||
fileprivate let theme: PresentationTheme
|
|
||||||
private let strings: PresentationStrings
|
|
||||||
private let context: AccountContext
|
|
||||||
fileprivate let message: Message
|
|
||||||
private let controllerInteraction: ChatControllerInteraction
|
|
||||||
let section: GridSection?
|
|
||||||
|
|
||||||
init(theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, context: AccountContext, message: Message, controllerInteraction: ChatControllerInteraction) {
|
|
||||||
self.theme = theme
|
|
||||||
self.strings = strings
|
|
||||||
self.context = context
|
|
||||||
self.message = message
|
|
||||||
self.controllerInteraction = controllerInteraction
|
|
||||||
self.section = GridMessageItemSection(timestamp: message.timestamp, theme: theme, strings: strings, fontSize: fontSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
|
||||||
let node = GridMessageItemNode()
|
|
||||||
if let media = mediaForMessage(self.message) {
|
|
||||||
node.setup(context: self.context, item: self, media: media, messageId: self.message.id, controllerInteraction: self.controllerInteraction, synchronousLoad: synchronousLoad)
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(node: GridItemNode) {
|
|
||||||
guard let node = node as? GridMessageItemNode else {
|
|
||||||
assertionFailure()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if let media = mediaForMessage(self.message) {
|
|
||||||
node.setup(context: self.context, item: self, media: media, messageId: self.message.id, controllerInteraction: self.controllerInteraction, synchronousLoad: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class GridMessageItemNode: GridItemNode {
|
|
||||||
private var currentState: (AccountContext, Media, CGSize)?
|
|
||||||
private let containerNode: ContextControllerSourceNode
|
|
||||||
private let imageNode: TransformImageNode
|
|
||||||
private(set) var messageId: MessageId?
|
|
||||||
private var item: GridMessageItem?
|
|
||||||
private var controllerInteraction: ChatControllerInteraction?
|
|
||||||
private var statusNode: RadialStatusNode
|
|
||||||
private let mediaBadgeNode: ChatMessageInteractiveMediaBadge
|
|
||||||
|
|
||||||
private var selectionNode: GridMessageSelectionNode?
|
|
||||||
|
|
||||||
private let fetchStatusDisposable = MetaDisposable()
|
|
||||||
private let fetchDisposable = MetaDisposable()
|
|
||||||
private var resourceStatus: MediaResourceStatus?
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
self.containerNode = ContextControllerSourceNode()
|
|
||||||
self.imageNode = TransformImageNode()
|
|
||||||
self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6))
|
|
||||||
let progressDiameter: CGFloat = 40.0
|
|
||||||
self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter)
|
|
||||||
self.statusNode.isUserInteractionEnabled = false
|
|
||||||
|
|
||||||
self.mediaBadgeNode = ChatMessageInteractiveMediaBadge()
|
|
||||||
self.mediaBadgeNode.frame = CGRect(origin: CGPoint(x: 6.0, y: 6.0), size: CGSize(width: 50.0, height: 50.0))
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.addSubnode(self.containerNode)
|
|
||||||
self.containerNode.addSubnode(self.imageNode)
|
|
||||||
self.containerNode.addSubnode(self.mediaBadgeNode)
|
|
||||||
|
|
||||||
self.containerNode.activated = { [weak self] gesture, _ in
|
|
||||||
guard let strongSelf = self, let item = strongSelf.item, let controllerInteraction = strongSelf.controllerInteraction else {
|
|
||||||
gesture.cancel()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
controllerInteraction.openMessageContextActions(item.message, strongSelf.containerNode, strongSelf.containerNode.bounds, gesture)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.fetchStatusDisposable.dispose()
|
|
||||||
self.fetchDisposable.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func didLoad() {
|
|
||||||
super.didLoad()
|
|
||||||
|
|
||||||
self.mediaBadgeNode.pressed = { [weak self] in
|
|
||||||
self?.progressPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
|
||||||
recognizer.tapActionAtPoint = { _ in
|
|
||||||
return .waitForSingleTap
|
|
||||||
}
|
|
||||||
self.imageNode.view.addGestureRecognizer(recognizer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setup(context: AccountContext, item: GridMessageItem, media: Media, messageId: MessageId, controllerInteraction: ChatControllerInteraction, synchronousLoad: Bool) {
|
|
||||||
self.item = item
|
|
||||||
|
|
||||||
if self.currentState == nil || self.currentState!.0 !== context || !self.currentState!.1.isEqual(to: media) {
|
|
||||||
var mediaDimensions: CGSize?
|
|
||||||
if let image = media as? TelegramMediaImage, let largestSize = largestImageRepresentation(image.representations)?.dimensions {
|
|
||||||
mediaDimensions = largestSize.cgSize
|
|
||||||
|
|
||||||
self.imageNode.setSignal(mediaGridMessagePhoto(account: context.account, userLocation: .peer(item.message.id.peerId), photoReference: .message(message: MessageReference(item.message), media: image), synchronousLoad: synchronousLoad), attemptSynchronously: synchronousLoad, dispatchOnDisplayLink: true)
|
|
||||||
|
|
||||||
self.fetchStatusDisposable.set(nil)
|
|
||||||
self.statusNode.transitionToState(.none, completion: { [weak self] in
|
|
||||||
self?.statusNode.isHidden = true
|
|
||||||
})
|
|
||||||
self.mediaBadgeNode.isHidden = true
|
|
||||||
self.resourceStatus = nil
|
|
||||||
} else if let file = media as? TelegramMediaFile, file.isVideo {
|
|
||||||
mediaDimensions = file.dimensions?.cgSize
|
|
||||||
self.imageNode.setSignal(mediaGridMessageVideo(postbox: context.account.postbox, userLocation: .peer(item.message.id.peerId), videoReference: .message(message: MessageReference(item.message), media: file), synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: true), attemptSynchronously: synchronousLoad)
|
|
||||||
|
|
||||||
self.mediaBadgeNode.isHidden = false
|
|
||||||
|
|
||||||
self.resourceStatus = nil
|
|
||||||
self.fetchStatusDisposable.set((messageMediaFileStatus(context: context, messageId: messageId, file: file) |> deliverOnMainQueue).startStrict(next: { [weak self] status in
|
|
||||||
if let strongSelf = self, let item = strongSelf.item {
|
|
||||||
strongSelf.resourceStatus = status
|
|
||||||
|
|
||||||
let isStreamable = isMediaStreamable(message: item.message, media: file)
|
|
||||||
|
|
||||||
let statusState: RadialStatusNodeState
|
|
||||||
if isStreamable {
|
|
||||||
statusState = .none
|
|
||||||
} else {
|
|
||||||
switch status {
|
|
||||||
case let .Fetching(_, progress):
|
|
||||||
let adjustedProgress = max(progress, 0.027)
|
|
||||||
statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
|
|
||||||
case .Local:
|
|
||||||
statusState = .none
|
|
||||||
case .Remote, .Paused:
|
|
||||||
statusState = .download(.white)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch statusState {
|
|
||||||
case .none:
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
strongSelf.statusNode.isHidden = false
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.statusNode.transitionToState(statusState, animated: true, completion: {
|
|
||||||
if let strongSelf = self {
|
|
||||||
if case .none = statusState {
|
|
||||||
strongSelf.statusNode.isHidden = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if let duration = file.duration {
|
|
||||||
let durationString = stringForDuration(Int32(duration))
|
|
||||||
|
|
||||||
var badgeContent: ChatMessageInteractiveMediaBadgeContent?
|
|
||||||
var mediaDownloadState: ChatMessageInteractiveMediaDownloadState?
|
|
||||||
|
|
||||||
if isStreamable {
|
|
||||||
switch status {
|
|
||||||
case let .Fetching(_, progress):
|
|
||||||
let progressString = String(format: "%d%%", Int(progress * 100.0))
|
|
||||||
badgeContent = .text(inset: 12.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: progressString), iconName: nil)
|
|
||||||
mediaDownloadState = .compactFetching(progress: 0.0)
|
|
||||||
case .Local:
|
|
||||||
badgeContent = .text(inset: 0.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString), iconName: nil)
|
|
||||||
case .Remote, .Paused:
|
|
||||||
badgeContent = .text(inset: 12.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString), iconName: nil)
|
|
||||||
mediaDownloadState = .compactRemote
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
badgeContent = .text(inset: 0.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString), iconName: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.mediaBadgeNode.update(theme: item.theme, content: badgeContent, mediaDownloadState: mediaDownloadState, alignment: .right, animated: false, badgeAnimated: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
if self.statusNode.supernode == nil {
|
|
||||||
self.imageNode.addSubnode(self.statusNode)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.mediaBadgeNode.isHidden = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if let mediaDimensions = mediaDimensions {
|
|
||||||
self.currentState = (context, media, mediaDimensions)
|
|
||||||
self.setNeedsLayout()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.messageId = messageId
|
|
||||||
self.controllerInteraction = controllerInteraction
|
|
||||||
|
|
||||||
self.updateSelectionState(animated: false)
|
|
||||||
self.updateHiddenMedia()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func layout() {
|
|
||||||
super.layout()
|
|
||||||
|
|
||||||
let imageFrame = self.bounds
|
|
||||||
|
|
||||||
self.containerNode.frame = imageFrame
|
|
||||||
|
|
||||||
self.imageNode.frame = imageFrame
|
|
||||||
|
|
||||||
if let item = self.item, let (_, _, mediaDimensions) = self.currentState {
|
|
||||||
let imageSize = mediaDimensions.aspectFilled(imageFrame.size)
|
|
||||||
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageFrame.size, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor))()
|
|
||||||
}
|
|
||||||
|
|
||||||
self.selectionNode?.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
|
|
||||||
let progressDiameter: CGFloat = 40.0
|
|
||||||
self.statusNode.frame = CGRect(origin: CGPoint(x: floor((imageFrame.size.width - progressDiameter) / 2.0), y: floor((imageFrame.size.height - progressDiameter) / 2.0)), size: CGSize(width: progressDiameter, height: progressDiameter))
|
|
||||||
|
|
||||||
self.mediaBadgeNode.frame = CGRect(origin: CGPoint(x: imageFrame.width - 3.0, y: imageFrame.height - 18.0 - 3.0), size: CGSize(width: 50.0, height: 50.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateSelectionState(animated: Bool) {
|
|
||||||
if let messageId = self.messageId, let controllerInteraction = self.controllerInteraction {
|
|
||||||
if let selectionState = controllerInteraction.selectionState {
|
|
||||||
guard let item = self.item else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let selected = selectionState.selectedIds.contains(messageId)
|
|
||||||
|
|
||||||
if let selectionNode = self.selectionNode {
|
|
||||||
selectionNode.updateSelected(selected, animated: animated)
|
|
||||||
selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
|
|
||||||
} else {
|
|
||||||
let selectionNode = GridMessageSelectionNode(theme: item.theme, toggle: { [weak self] value in
|
|
||||||
if let strongSelf = self, let messageId = strongSelf.messageId {
|
|
||||||
strongSelf.controllerInteraction?.toggleMessagesSelection([messageId], value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
|
|
||||||
self.containerNode.addSubnode(selectionNode)
|
|
||||||
self.selectionNode = selectionNode
|
|
||||||
selectionNode.updateSelected(selected, animated: false)
|
|
||||||
if animated {
|
|
||||||
selectionNode.animateIn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let selectionNode = self.selectionNode {
|
|
||||||
self.selectionNode = nil
|
|
||||||
if animated {
|
|
||||||
selectionNode.animateOut { [weak selectionNode] in
|
|
||||||
selectionNode?.removeFromSupernode()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
selectionNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
|
||||||
if self.messageId == id {
|
|
||||||
let imageNode = self.imageNode
|
|
||||||
return (self.imageNode, self.imageNode.bounds, { [weak self, weak imageNode] in
|
|
||||||
var statusNodeHidden = false
|
|
||||||
var accessoryHidden = false
|
|
||||||
if let strongSelf = self {
|
|
||||||
statusNodeHidden = strongSelf.statusNode.isHidden
|
|
||||||
accessoryHidden = strongSelf.mediaBadgeNode.isHidden
|
|
||||||
strongSelf.statusNode.isHidden = true
|
|
||||||
strongSelf.mediaBadgeNode.isHidden = true
|
|
||||||
}
|
|
||||||
let view = imageNode?.view.snapshotContentTree(unhide: true)
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.statusNode.isHidden = statusNodeHidden
|
|
||||||
strongSelf.mediaBadgeNode.isHidden = accessoryHidden
|
|
||||||
}
|
|
||||||
return (view, nil)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateHiddenMedia() {
|
|
||||||
if let controllerInteraction = self.controllerInteraction, let messageId = self.messageId, controllerInteraction.hiddenMedia[messageId] != nil {
|
|
||||||
self.imageNode.isHidden = true
|
|
||||||
self.mediaBadgeNode.alpha = 0.0
|
|
||||||
self.statusNode.alpha = 0.0
|
|
||||||
} else {
|
|
||||||
self.imageNode.isHidden = false
|
|
||||||
if self.statusNode.alpha < 1.0 {
|
|
||||||
self.statusNode.alpha = 1.0
|
|
||||||
self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
|
||||||
}
|
|
||||||
if self.mediaBadgeNode.alpha < 1.0 {
|
|
||||||
self.mediaBadgeNode.alpha = 1.0
|
|
||||||
self.mediaBadgeNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func progressPressed() {
|
|
||||||
guard let controllerInteraction = self.controllerInteraction, let message = self.item?.message else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if let (context, media, _) = self.currentState, let resourceStatus = self.resourceStatus, let file = media as? TelegramMediaFile {
|
|
||||||
switch resourceStatus {
|
|
||||||
case .Fetching:
|
|
||||||
messageMediaFileCancelInteractiveFetch(context: context, messageId: message.id, file: file)
|
|
||||||
case .Local:
|
|
||||||
let _ = controllerInteraction.openMessage(message, .default)
|
|
||||||
case .Remote, .Paused:
|
|
||||||
self.fetchDisposable.set(messageMediaFileInteractiveFetched(context: context, message: message, file: file, userInitiated: true).startStrict())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
|
||||||
guard let controllerInteraction = self.controllerInteraction, let message = self.item?.message else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch recognizer.state {
|
|
||||||
case .ended:
|
|
||||||
if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation {
|
|
||||||
switch gesture {
|
|
||||||
case .tap:
|
|
||||||
if let (_, media, _) = self.currentState, let file = media as? TelegramMediaFile {
|
|
||||||
if isMediaStreamable(message: message, media: file) {
|
|
||||||
let _ = controllerInteraction.openMessage(message, .default)
|
|
||||||
} else {
|
|
||||||
self.progressPressed()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let _ = controllerInteraction.openMessage(message, .default)
|
|
||||||
}
|
|
||||||
case .longTap:
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user