Merge commit 'cfb6c53c55904d9b8b6bfecdf8fe155d9a3a96f9'

This commit is contained in:
Ali 2020-12-15 19:25:48 +04:00
commit af29a873c3
8 changed files with 125 additions and 74 deletions

View File

@ -19,6 +19,7 @@ swift_library(
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/ShimmerEffect:ShimmerEffect",
],
visibility = [
"//visibility:public",

View File

@ -12,6 +12,7 @@ import PresentationDataUtils
import StickerResources
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import ShimmerEffect
public struct ItemListStickerPackItemEditing: Equatable {
public var editable: Bool
@ -149,6 +150,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
fileprivate let imageNode: TransformImageNode
private var animationNode: AnimatedStickerNode?
private var placeholderNode: StickerShimmerEffectNode?
private let unreadNode: ASImageNode
private let titleNode: TextNode
private let statusNode: TextNode
@ -200,6 +202,9 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
self.imageNode = TransformImageNode()
self.imageNode.isLayerBacked = !smartInvertColorsEnabled()
self.placeholderNode = StickerShimmerEffectNode()
self.placeholderNode?.isUserInteractionEnabled = false
self.titleNode = TextNode()
self.titleNode.isUserInteractionEnabled = false
self.titleNode.contentMode = .left
@ -231,7 +236,11 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
if let placeholderNode = self.placeholderNode {
self.addSubnode(placeholderNode)
}
self.addSubnode(self.imageNode)
self.addSubnode(self.titleNode)
self.addSubnode(self.statusNode)
self.addSubnode(self.unreadNode)
@ -251,12 +260,50 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
}
}
}
var firstTime = true
self.imageNode.imageUpdated = { [weak self] image in
guard let strongSelf = self else {
return
}
if image != nil {
strongSelf.removePlaceholder(animated: !firstTime)
if firstTime {
strongSelf.imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
firstTime = false
}
}
deinit {
self.fetchDisposable.dispose()
}
private func removePlaceholder(animated: Bool) {
if let placeholderNode = self.placeholderNode {
self.placeholderNode = nil
if !animated {
placeholderNode.removeFromSupernode()
} else {
placeholderNode.allowsGroupOpacity = true
placeholderNode.alpha = 0.0
placeholderNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak placeholderNode] _ in
placeholderNode?.removeFromSupernode()
placeholderNode?.allowsGroupOpacity = false
})
}
}
}
private var absoluteLocation: (CGRect, CGSize)?
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
self.absoluteLocation = (rect, containerSize)
if let placeholderNode = placeholderNode {
placeholderNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + placeholderNode.frame.minX, y: rect.minY + placeholderNode.frame.minY), size: placeholderNode.frame.size), within: containerSize)
}
}
func asyncLayout() -> (_ item: ItemListStickerPackItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, (Bool) -> Void) {
let makeImageLayout = self.imageNode.asyncLayout()
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
@ -397,14 +444,14 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
if fileUpdated {
imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: stillImageSize, boundingSize: stillImageSize, intrinsicInsets: UIEdgeInsets()))
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, resource: representation.resource)
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, resource: representation.resource, nilIfEmpty: true)
}
case let .animated(resource):
imageSize = imageBoundingSize
if fileUpdated {
imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageBoundingSize, boundingSize: imageBoundingSize, intrinsicInsets: UIEdgeInsets()))
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, resource: resource, animated: true)
updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, resource: resource, animated: true, nilIfEmpty: true)
}
}
if fileUpdated, let resourceReference = resourceReference {
@ -610,6 +657,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
animationNode = AnimatedStickerNode()
strongSelf.animationNode = animationNode
strongSelf.addSubnode(animationNode)
animationNode.setup(source: AnimatedStickerResourceSource(account: item.account, resource: resource), width: 80, height: 80, mode: .cached)
}
animationNode.visibility = strongSelf.visibility != .none && item.playAnimatedStickers
@ -619,6 +667,12 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
transition.updateFrame(node: animationNode, frame: imageFrame)
}
}
if let placeholderNode = strongSelf.placeholderNode {
placeholderNode.frame = imageFrame
placeholderNode.update(backgroundColor: nil, foregroundColor: item.presentationData.theme.list.disclosureArrowColor.blitOver(item.presentationData.theme.list.itemBlocksBackgroundColor, alpha: 0.55), shimmeringColor: item.presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4), data: item.packInfo.immediateThumbnailData, size: imageFrame.size, small: true)
}
}
if let updatedImageSignal = updatedImageSignal {

View File

@ -168,7 +168,7 @@ public class StickerShimmerEffectNode: ASDisplayNode {
self.effectNode.updateAbsoluteRect(rect, within: containerSize)
}
public func update(backgroundColor: UIColor?, foregroundColor: UIColor, shimmeringColor: UIColor, data: Data?, size: CGSize) {
public func update(backgroundColor: UIColor?, foregroundColor: UIColor, shimmeringColor: UIColor, data: Data?, size: CGSize, small: Bool = false) {
if data == nil {
return
}
@ -205,7 +205,7 @@ public class StickerShimmerEffectNode: ASDisplayNode {
let reader = PathDataReader(input: path)
let segments = reader.read()
let scale = size.width / 512.0
let scale = size.width / (small ? 100.0 : 512.0)
context.scaleBy(x: scale, y: scale)
renderPath(segments, context: context)
} else {

View File

@ -1,3 +1,4 @@
import Foundation
import Postbox
public struct StickerPackCollectionInfoFlags: OptionSet {
@ -40,16 +41,18 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
public let title: String
public let shortName: String
public let thumbnail: TelegramMediaImageRepresentation?
public let immediateThumbnailData: Data?
public let hash: Int32
public let count: Int32
public init(id: ItemCollectionId, flags: StickerPackCollectionInfoFlags, accessHash: Int64, title: String, shortName: String, thumbnail: TelegramMediaImageRepresentation?, hash: Int32, count: Int32) {
public init(id: ItemCollectionId, flags: StickerPackCollectionInfoFlags, accessHash: Int64, title: String, shortName: String, thumbnail: TelegramMediaImageRepresentation?, immediateThumbnailData: Data?, hash: Int32, count: Int32) {
self.id = id
self.flags = flags
self.accessHash = accessHash
self.title = title
self.shortName = shortName
self.thumbnail = thumbnail
self.immediateThumbnailData = immediateThumbnailData
self.hash = hash
self.count = count
}
@ -60,6 +63,7 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
self.title = decoder.decodeStringForKey("t", orElse: "")
self.shortName = decoder.decodeStringForKey("s", orElse: "")
self.thumbnail = decoder.decodeObjectForKey("th", decoder: { TelegramMediaImageRepresentation(decoder: $0) }) as? TelegramMediaImageRepresentation
self.immediateThumbnailData = decoder.decodeDataForKey("itd")
self.hash = decoder.decodeInt32ForKey("h", orElse: 0)
self.flags = StickerPackCollectionInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
self.count = decoder.decodeInt32ForKey("n", orElse: 0)
@ -76,6 +80,11 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
} else {
encoder.encodeNil(forKey: "th")
}
if let immediateThumbnailData = self.immediateThumbnailData {
encoder.encodeData(immediateThumbnailData, forKey: "itd")
} else {
encoder.encodeNil(forKey: "itd")
}
encoder.encodeInt32(self.hash, forKey: "h")
encoder.encodeInt32(self.flags.rawValue, forKey: "f")
encoder.encodeInt32(self.count, forKey: "n")
@ -98,6 +107,10 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
return false
}
if lhs.immediateThumbnailData != rhs.immediateThumbnailData {
return false
}
if lhs.flags != rhs.flags {
return false
}

View File

@ -5,33 +5,38 @@ import SwiftSignalKit
import SyncCore
import MtProtoKit
func telegramStickerPackThumbnailRepresentationFromApiSize(datacenterId: Int32, size: Api.PhotoSize) -> TelegramMediaImageRepresentation? {
func telegramStickerPackThumbnailRepresentationFromApiSizes(datacenterId: Int32, sizes: [Api.PhotoSize]) -> (immediateThumbnail: Data?, representations: [TelegramMediaImageRepresentation]) {
var immediateThumbnailData: Data?
var representations: [TelegramMediaImageRepresentation] = []
for size in sizes {
switch size {
case let .photoCachedSize(_, location, w, h, _):
switch location {
case let .fileLocationToBeDeprecated(volumeId, localId):
let resource = CloudStickerPackThumbnailMediaResource(datacenterId: datacenterId, volumeId: volumeId, localId: localId)
return TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [])
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: []))
}
case let .photoSize(_, location, w, h, _):
switch location {
case let .fileLocationToBeDeprecated(volumeId, localId):
let resource = CloudStickerPackThumbnailMediaResource(datacenterId: datacenterId, volumeId: volumeId, localId: localId)
return TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [])
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: []))
}
case let .photoSizeProgressive(_, location, w, h, sizes):
switch location {
case let .fileLocationToBeDeprecated(volumeId, localId):
let resource = CloudStickerPackThumbnailMediaResource(datacenterId: datacenterId, volumeId: volumeId, localId: localId)
return TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes))
}
case let .photoPathSize(_, data):
return nil
immediateThumbnailData = data.makeData()
case .photoStrippedSize:
return nil
break
case .photoSizeEmpty:
return nil
break
}
}
return (immediateThumbnailData, representations)
}
extension StickerPackCollectionInfo {
@ -50,11 +55,14 @@ extension StickerPackCollectionInfo {
}
var thumbnailRepresentation: TelegramMediaImageRepresentation?
if let thumb = thumbs?.first, let thumbDcId = thumbDcId {
thumbnailRepresentation = telegramStickerPackThumbnailRepresentationFromApiSize(datacenterId: thumbDcId, size: thumb)
var immediateThumbnailData: Data?
if let thumbs = thumbs, let thumbDcId = thumbDcId {
let (data, representations) = telegramStickerPackThumbnailRepresentationFromApiSizes(datacenterId: thumbDcId, sizes: thumbs)
thumbnailRepresentation = representations.first
immediateThumbnailData = data
}
self.init(id: ItemCollectionId(namespace: namespace, id: id), flags: setFlags, accessHash: accessHash, title: title, shortName: shortName, thumbnail: thumbnailRepresentation, hash: nHash, count: count)
self.init(id: ItemCollectionId(namespace: namespace, id: id), flags: setFlags, accessHash: accessHash, title: title, shortName: shortName, thumbnail: thumbnailRepresentation, immediateThumbnailData: immediateThumbnailData, hash: nHash, count: count)
}
}
}

View File

@ -18,7 +18,7 @@ public func addStickerPackInteractively(postbox: Postbox, info: StickerPackColle
if let namespace = namespace {
var mappedInfo = info
if items.isEmpty {
mappedInfo = StickerPackCollectionInfo(id: info.id, flags: info.flags, accessHash: info.accessHash, title: info.title, shortName: info.shortName, thumbnail: info.thumbnail, hash: Int32(bitPattern: arc4random()), count: info.count)
mappedInfo = StickerPackCollectionInfo(id: info.id, flags: info.flags, accessHash: info.accessHash, title: info.title, shortName: info.shortName, thumbnail: info.thumbnail, immediateThumbnailData: info.immediateThumbnailData, hash: Int32(bitPattern: arc4random()), count: info.count)
}
addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: namespace, content: .add([mappedInfo.id]), noDelay: items.isEmpty)
var updatedInfos = transaction.getItemCollectionsInfos(namespace: mappedInfo.id.namespace).map { $0.1 as! StickerPackCollectionInfo }

View File

@ -238,7 +238,7 @@ func chatMediaInputGridEntries(view: ItemCollectionsView, savedStickers: Ordered
if view.lower == nil {
var savedStickerIds = Set<Int64>()
if let savedStickers = savedStickers, !savedStickers.items.isEmpty {
let packInfo = StickerPackCollectionInfo(id: ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.savedStickers.rawValue, id: 0), flags: [], accessHash: 0, title: strings.Stickers_FavoriteStickers.uppercased(), shortName: "", thumbnail: nil, hash: 0, count: 0)
let packInfo = StickerPackCollectionInfo(id: ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.savedStickers.rawValue, id: 0), flags: [], accessHash: 0, title: strings.Stickers_FavoriteStickers.uppercased(), shortName: "", thumbnail: nil, immediateThumbnailData: nil, hash: 0, count: 0)
for i in 0 ..< savedStickers.items.count {
if let item = savedStickers.items[i].contents as? SavedStickerItem {
savedStickerIds.insert(item.file.fileId.id)
@ -250,7 +250,7 @@ func chatMediaInputGridEntries(view: ItemCollectionsView, savedStickers: Ordered
}
if let recentStickers = recentStickers, !recentStickers.items.isEmpty {
let packInfo = StickerPackCollectionInfo(id: ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.recentStickers.rawValue, id: 0), flags: [], accessHash: 0, title: strings.Stickers_FrequentlyUsed.uppercased(), shortName: "", thumbnail: nil, hash: 0, count: 0)
let packInfo = StickerPackCollectionInfo(id: ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.recentStickers.rawValue, id: 0), flags: [], accessHash: 0, title: strings.Stickers_FrequentlyUsed.uppercased(), shortName: "", thumbnail: nil, immediateThumbnailData: nil, hash: 0, count: 0)
var addedCount = 0
for i in 0 ..< recentStickers.items.count {
if addedCount >= 20 {
@ -278,7 +278,7 @@ func chatMediaInputGridEntries(view: ItemCollectionsView, savedStickers: Ordered
if let peerSpecificPack = peerSpecificPack {
for i in 0 ..< peerSpecificPack.items.count {
let packInfo = StickerPackCollectionInfo(id: ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.peerSpecific.rawValue, id: 0), flags: [], accessHash: 0, title: strings.Stickers_GroupStickers, shortName: "", thumbnail: nil, hash: 0, count: 0)
let packInfo = StickerPackCollectionInfo(id: ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.peerSpecific.rawValue, id: 0), flags: [], accessHash: 0, title: strings.Stickers_GroupStickers, shortName: "", thumbnail: nil, immediateThumbnailData: nil, hash: 0, count: 0)
if let item = peerSpecificPack.items[i] as? StickerPackItem {
let index = ItemCollectionItemIndex(index: Int32(i), id: item.file.fileId.id)

View File

@ -76,8 +76,7 @@ private let verticalOffset: CGFloat = 3.0
final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
private let imageNode: TransformImageNode
private var animatedStickerNode: AnimatedStickerNode?
private var placeholderNode: ShimmerEffectNode?
private var placeholderImageNode: ASImageNode?
private var placeholderNode: StickerShimmerEffectNode?
private let highlightNode: ASImageNode
var inputNodeInteraction: ChatMediaInputNodeInteraction?
@ -110,10 +109,8 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
self.imageNode = TransformImageNode()
self.imageNode.isLayerBacked = !smartInvertColorsEnabled()
self.placeholderImageNode = ASImageNode()
self.placeholderImageNode?.isUserInteractionEnabled = false
//self.placeholderNode = ShimmerEffectNode()
self.placeholderNode = StickerShimmerEffectNode()
self.placeholderNode?.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
self.highlightNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - highlightSize.width) / 2.0) + verticalOffset - UIScreenPixel, y: floor((boundingSize.height - highlightSize.height) / 2.0) - UIScreenPixel), size: highlightSize)
@ -124,9 +121,6 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
self.addSubnode(self.highlightNode)
self.addSubnode(self.imageNode)
if let placeholderImageNode = self.placeholderImageNode {
self.addSubnode(placeholderImageNode)
}
if let placeholderNode = self.placeholderNode {
self.addSubnode(placeholderNode)
}
@ -138,6 +132,9 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
}
if image != nil {
strongSelf.removePlaceholder(animated: !firstTime)
if firstTime {
strongSelf.imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
firstTime = false
}
@ -159,17 +156,6 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
})
}
}
if let placeholderImageNode = self.placeholderImageNode {
self.placeholderImageNode = nil
if !animated {
placeholderImageNode.removeFromSupernode()
} else {
placeholderImageNode.alpha = 0.0
placeholderImageNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak placeholderImageNode] _ in
placeholderImageNode?.removeFromSupernode()
})
}
}
}
func updateStickerPackItem(account: Account, info: StickerPackCollectionInfo, item: StickerPackItem?, collectionId: ItemCollectionId, theme: PresentationTheme) {
@ -245,23 +231,12 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
}
}
if let placeholderImageNode = self.placeholderImageNode {
if placeholderImageNode.image == nil {
placeholderImageNode.image = generateStretchableFilledCircleImage(diameter: 10.0, color: theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor.withMultipliedAlpha(0.3))
}
let size = boundingSize
let imageSize = boundingImageSize
let placeholderFrame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
placeholderImageNode.frame = placeholderFrame
}
if let placeholderNode = self.placeholderNode {
let size = boundingSize
let imageSize = boundingImageSize
let placeholderFrame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
placeholderNode.frame = CGRect(origin: CGPoint(), size: size)
placeholderNode.frame = placeholderFrame
placeholderNode.update(backgroundColor: theme.chat.inputPanel.panelBackgroundColor, foregroundColor: theme.chat.inputMediaPanel.stickersSectionTextColor.blitOver(theme.chat.inputPanel.panelBackgroundColor, alpha: 0.4), shimmeringColor: theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor.withMultipliedAlpha(0.2), shapes: [.roundedRect(rect: placeholderFrame, cornerRadius: 5.0)], size: bounds.size)
placeholderNode.update(backgroundColor: nil, foregroundColor: theme.chat.inputMediaPanel.stickersSectionTextColor.blitOver(theme.chat.inputPanel.panelBackgroundColor, alpha: 0.4), shimmeringColor: theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor.withMultipliedAlpha(0.2), data: info.immediateThumbnailData, size: imageSize, small: true)
}
self.updateIsHighlighted()
@ -270,7 +245,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
if let placeholderNode = self.placeholderNode {
//placeholderNode.updateAbsoluteRect(rect, within: containerSize)
placeholderNode.updateAbsoluteRect(rect, within: containerSize)
}
}