Swiftgram/TelegramUI/GridMessageItem.swift
2016-10-07 19:14:56 +03:00

161 lines
6.1 KiB
Swift

import Foundation
import Display
import AsyncDisplayKit
import TelegramCore
import Postbox
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
}
final class GridMessageItem: GridItem {
private let account: Account
private let message: Message
private let controllerInteraction: ChatControllerInteraction
init(account: Account, message: Message, controllerInteraction: ChatControllerInteraction) {
self.account = account
self.message = message
self.controllerInteraction = controllerInteraction
}
func node(layout: GridNodeLayout) -> GridItemNode {
let node = GridMessageItemNode()
if let media = mediaForMessage(self.message) {
node.setup(account: self.account, media: media, messageId: self.message.id, controllerInteraction: self.controllerInteraction)
}
return node
}
}
final class GridMessageItemNode: GridItemNode {
private var currentState: (Account, Media, CGSize)?
private let imageNode: TransformImageNode
private var messageId: MessageId?
private var controllerInteraction: ChatControllerInteraction?
private var selectionNode: GridMessageSelectionNode?
override init() {
self.imageNode = TransformImageNode()
super.init()
self.addSubnode(self.imageNode)
}
override func didLoad() {
super.didLoad()
self.imageNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
}
func setup(account: Account, media: Media, messageId: MessageId, controllerInteraction: ChatControllerInteraction) {
if self.currentState == nil || self.currentState!.0 !== account || !self.currentState!.1.isEqual(media) {
var mediaDimensions: CGSize?
if let image = media as? TelegramMediaImage, let largestSize = largestImageRepresentation(image.representations)?.dimensions {
mediaDimensions = largestSize
self.imageNode.setSignal(account: account, signal: mediaGridMessagePhoto(account: account, photo: image), dispatchOnDisplayLink: true)
}
if let mediaDimensions = mediaDimensions {
self.currentState = (account, 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.insetBy(dx: 1.0, dy: 1.0)
self.imageNode.frame = imageFrame
if let (_, _, mediaDimensions) = self.currentState {
let imageSize = mediaDimensions.aspectFilled(imageFrame.size)
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageFrame.size, intrinsicInsets: UIEdgeInsets()))()
}
self.selectionNode?.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
}
func updateSelectionState(animated: Bool) {
if let messageId = self.messageId, let controllerInteraction = self.controllerInteraction {
if let selectionState = controllerInteraction.selectionState {
var 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(toggle: { [weak self] in
if let strongSelf = self, let messageId = strongSelf.messageId {
strongSelf.controllerInteraction?.toggleMessageSelection(messageId)
}
})
selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
self.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) -> ASDisplayNode? {
if self.messageId == id {
return self.imageNode
} else {
return nil
}
}
func updateHiddenMedia() {
if let controllerInteraction = self.controllerInteraction, let messageId = self.messageId, controllerInteraction.hiddenMedia[messageId] != nil {
self.imageNode.isHidden = true
} else {
self.imageNode.isHidden = false
}
}
@objc func imageNodeTap(_ recognizer: UITapGestureRecognizer) {
if let controllerInteraction = self.controllerInteraction, let messageId = self.messageId, case .ended = recognizer.state {
controllerInteraction.openMessage(messageId)
}
}
}