Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin
2022-08-28 15:08:55 +02:00
79 changed files with 1821 additions and 725 deletions

View File

@@ -255,7 +255,7 @@ public final class EntityKeyboardAnimationData: Equatable {
}
}
public final class PassthroughLayer: CALayer {
public class PassthroughLayer: CALayer {
public var mirrorLayer: CALayer?
override init() {
@@ -1778,6 +1778,7 @@ public final class EmojiPagerContentComponent: Component {
public let itemLayoutType: ItemLayoutType
public let warpContentsOnEdges: Bool
public let enableLongPress: Bool
public let selectedItems: Set<MediaId>
public init(
id: AnyHashable,
@@ -1789,7 +1790,8 @@ public final class EmojiPagerContentComponent: Component {
itemGroups: [ItemGroup],
itemLayoutType: ItemLayoutType,
warpContentsOnEdges: Bool,
enableLongPress: Bool
enableLongPress: Bool,
selectedItems: Set<MediaId>
) {
self.id = id
self.context = context
@@ -1801,6 +1803,7 @@ public final class EmojiPagerContentComponent: Component {
self.itemLayoutType = itemLayoutType
self.warpContentsOnEdges = warpContentsOnEdges
self.enableLongPress = enableLongPress
self.selectedItems = selectedItems
}
public static func ==(lhs: EmojiPagerContentComponent, rhs: EmojiPagerContentComponent) -> Bool {
@@ -1837,6 +1840,9 @@ public final class EmojiPagerContentComponent: Component {
if lhs.enableLongPress != rhs.enableLongPress {
return false
}
if lhs.selectedItems != rhs.selectedItems {
return false
}
return true
}
@@ -2441,6 +2447,32 @@ public final class EmojiPagerContentComponent: Component {
}
}
private final class ItemSelectionLayer: PassthroughLayer {
let tintContainerLayer: SimpleLayer
override init() {
self.tintContainerLayer = SimpleLayer()
super.init()
self.mirrorLayer = self.tintContainerLayer
}
override func action(forKey event: String) -> CAAction? {
return nullAction
}
override init(layer: Any) {
self.tintContainerLayer = SimpleLayer()
super.init(layer: layer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
private final class ContentScrollLayer: CALayer {
var mirrorLayer: CALayer?
@@ -2546,6 +2578,7 @@ public final class EmojiPagerContentComponent: Component {
private let placeholdersContainerView: UIView
private var visibleItemPlaceholderViews: [ItemLayer.Key: ItemPlaceholderView] = [:]
private var visibleItemSelectionLayers: [ItemLayer.Key: ItemSelectionLayer] = [:]
private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:]
private var visibleGroupHeaders: [AnyHashable: GroupHeaderLayer] = [:]
private var visibleGroupBorders: [AnyHashable: GroupBorderLayer] = [:]
@@ -2674,13 +2707,17 @@ public final class EmojiPagerContentComponent: Component {
public func animateIn(fromLocation: CGPoint) {
let scrollLocation = self.convert(fromLocation, to: self.scrollView)
for (_, itemLayer) in self.visibleItemLayers {
for (key, itemLayer) in self.visibleItemLayers {
let distanceVector = CGPoint(x: scrollLocation.x - itemLayer.position.x, y: scrollLocation.y - itemLayer.position.y)
let distance = sqrt(distanceVector.x * distanceVector.x + distanceVector.y * distanceVector.y)
let distanceNorm = min(1.0, max(0.0, distance / self.bounds.width))
let delay = 0.05 + (distanceNorm) * 0.3
itemLayer.animateScale(from: 0.01, to: 1.0, duration: 0.18, delay: delay, timingFunction: kCAMediaTimingFunctionSpring)
if let itemSelectionLayer = self.visibleItemSelectionLayers[key] {
itemSelectionLayer.animateScale(from: 0.01, to: 1.0, duration: 0.18, delay: delay, timingFunction: kCAMediaTimingFunctionSpring)
}
}
}
@@ -2689,7 +2726,7 @@ public final class EmojiPagerContentComponent: Component {
return
}
for (_, itemLayer) in self.visibleItemLayers {
for (key, itemLayer) in self.visibleItemLayers {
guard case let .animation(animationData) = itemLayer.item.content else {
continue
}
@@ -2699,6 +2736,10 @@ public final class EmojiPagerContentComponent: Component {
if let sourceItem = sourceItems[file.fileId] {
itemLayer.animatePosition(from: CGPoint(x: sourceItem.position.x - itemLayer.position.x, y: 0.0), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
if let itemSelectionLayer = self.visibleItemSelectionLayers[key] {
itemSelectionLayer.animatePosition(from: CGPoint(x: sourceItem.position.x - itemLayer.position.x, y: 0.0), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
}
component.animationRenderer.setFrameIndex(itemId: animationData.resource.resource.id.stringRepresentation, size: itemLayer.pixelSize, frameIndex: sourceItem.frameIndex, placeholder: sourceItem.placeholder)
} else {
let distance = itemLayer.position.y - itemLayout.frame(groupIndex: 0, itemIndex: 0).midY
@@ -2710,6 +2751,11 @@ public final class EmojiPagerContentComponent: Component {
itemLayer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: delay)
itemLayer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.6, delay: delay)
if let itemSelectionLayer = self.visibleItemSelectionLayers[key] {
itemSelectionLayer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: delay)
itemSelectionLayer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.6, delay: delay)
}
}
}
@@ -2728,6 +2774,15 @@ public final class EmojiPagerContentComponent: Component {
}
}
public func layerForItem(groupId: AnyHashable, item: EmojiPagerContentComponent.Item) -> CALayer? {
let itemKey = EmojiPagerContentComponent.View.ItemLayer.Key(groupId: groupId, itemId: item.content.id)
if let itemLayer = self.visibleItemLayers[itemKey] {
return itemLayer
} else {
return nil
}
}
public func scrollToItemGroup(id supergroupId: AnyHashable, subgroupId: Int32?) {
guard let component = self.component, let pagerEnvironment = self.pagerEnvironment, let itemLayout = self.itemLayout else {
return
@@ -2777,6 +2832,10 @@ public final class EmojiPagerContentComponent: Component {
for (id, layer) in self.visibleItemLayers {
previousVisibleLayers[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY))
}
var previousVisibleItemSelectionLayers: [ItemLayer.Key: (CALayer, CGRect)] = [:]
for (id, layer) in self.visibleItemSelectionLayers {
previousVisibleItemSelectionLayers[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY))
}
var previousVisiblePlaceholderViews: [ItemLayer.Key: (UIView, CGRect)] = [:]
for (id, view) in self.visibleItemPlaceholderViews {
previousVisiblePlaceholderViews[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY))
@@ -3075,6 +3134,9 @@ public final class EmojiPagerContentComponent: Component {
for (_, layer) in self.visibleItemLayers {
layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true)
}
for (_, layer) in self.visibleItemSelectionLayers {
layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true)
}
for (id, layerAndFrame) in previousVisibleLayers {
if self.visibleItemLayers[id] != nil {
continue
@@ -3086,6 +3148,17 @@ public final class EmojiPagerContentComponent: Component {
layer?.removeFromSuperlayer()
})
}
for (id, layerAndFrame) in previousVisibleItemSelectionLayers {
if self.visibleItemSelectionLayers[id] != nil {
continue
}
let layer = layerAndFrame.0
layer.frame = layerAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY)
self.scrollView.layer.addSublayer(layer)
layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer] _ in
layer?.removeFromSuperlayer()
})
}
for (_, view) in self.visibleItemPlaceholderViews {
view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true)
@@ -3785,10 +3858,6 @@ public final class EmojiPagerContentComponent: Component {
} else {
pointSize = itemPlaybackSize
}
/*if case let .animation(animationData) = item.content, animationData.isReaction {
pointSize.width += pointSize.width
pointSize.height += pointSize.height
}*/
let placeholderColor = keyboardChildEnvironment.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1)
itemLayer = ItemLayer(
@@ -3849,12 +3918,13 @@ public final class EmojiPagerContentComponent: Component {
}
}
)
//itemLayer.backgroundColor = UIColor.lightGray.cgColor
self.scrollView.layer.addSublayer(itemLayer)
self.visibleItemLayers[itemId] = itemLayer
}
var itemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: index)
let baseItemFrame = itemFrame
itemFrame.origin.x += floor((itemFrame.width - itemVisibleFitSize.width) / 2.0)
itemFrame.origin.y += floor((itemFrame.height - itemVisibleFitSize.height) / 2.0)
@@ -3880,33 +3950,6 @@ public final class EmojiPagerContentComponent: Component {
let itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY)
itemTransition.setPosition(layer: itemLayer, position: itemPosition)
if itemLayout.curveNearBounds && !"".isEmpty {
let fractionLength: CGFloat = itemFrame.height
let rotationX: CGFloat = 1.0 - max(0.0, min(1.0, (effectiveVisibleBounds.maxY + 4.0 + itemFrame.height / 2.0 - itemPosition.y) / fractionLength))
if rotationX.isZero {
itemTransition.setTransform(layer: itemLayer, transform: CATransform3DIdentity)
} else {
var transform = CATransform3DIdentity
let centralOffset = itemFrame.midX - effectiveVisibleBounds.width / 2.0
transform = CATransform3DTranslate(transform, centralOffset * 2.0, 0.0, 0.0)
var projectionMatrix = CATransform3DIdentity
projectionMatrix.m34 = -1.0 / 500.0
transform = CATransform3DConcat(projectionMatrix, transform)
transform = CATransform3DTranslate(transform, -centralOffset * 2.0, 0.0, 0.0)
let rotationAngle = CGFloat.pi * 0.5 * rotationX
let rotationOffset = sin(rotationAngle)
let zOffset: CGFloat = 0.0
transform = CATransform3DTranslate(transform, 0.0, -rotationOffset * itemFrame.height * 0.5, -zOffset * itemFrame.height * 0.5)
transform = CATransform3DRotate(transform, rotationAngle, 1.0, 0.0, 0.0)
itemTransition.setTransform(layer: itemLayer, transform: transform)
}
}
var badge: ItemLayer.Badge?
if itemGroup.displayPremiumBadges, let file = item.itemFile, file.isPremiumSticker {
badge = .premium
@@ -3924,6 +3967,24 @@ public final class EmojiPagerContentComponent: Component {
}
}
if let itemFile = item.itemFile, component.selectedItems.contains(itemFile.fileId) {
let itemSelectionLayer: ItemSelectionLayer
if let current = self.visibleItemSelectionLayers[itemId] {
itemSelectionLayer = current
} else {
itemSelectionLayer = ItemSelectionLayer()
itemSelectionLayer.cornerRadius = 8.0
itemSelectionLayer.tintContainerLayer.cornerRadius = 8.0
self.scrollView.layer.insertSublayer(itemSelectionLayer, below: itemLayer)
self.mirrorContentScrollView.layer.addSublayer(itemSelectionLayer.tintContainerLayer)
self.visibleItemSelectionLayers[itemId] = itemSelectionLayer
}
itemSelectionLayer.backgroundColor = keyboardChildEnvironment.theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor
itemSelectionLayer.tintContainerLayer.backgroundColor = UIColor.white.cgColor
itemSelectionLayer.frame = baseItemFrame
}
if animateItemIn, !transition.animation.isImmediate, let contentAnimation = contentAnimation, case .groupExpanded(id: itemGroup.groupId) = contentAnimation.type, let placeholderView = self.visibleItemPlaceholderViews[itemId] {
placeholderView.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4)
placeholderView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
@@ -3940,6 +4001,8 @@ public final class EmojiPagerContentComponent: Component {
if !validIds.contains(id) {
removedIds.append(id)
let itemSelectionLayer = self.visibleItemSelectionLayers[id]
if !transition.animation.isImmediate {
if let hintDisappearingGroupFrame = hintDisappearingGroupFrame, hintDisappearingGroupFrame.groupId == id.groupId {
if let previousAbsolutePosition = previousAbsoluteItemPositions?[.item(id: id)] {
@@ -3952,30 +4015,93 @@ public final class EmojiPagerContentComponent: Component {
itemLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.16, completion: { [weak itemLayer] _ in
itemLayer?.removeFromSuperlayer()
})
if let itemSelectionLayer = itemSelectionLayer {
itemSelectionLayer.opacity = 0.0
itemSelectionLayer.animateScale(from: 1.0, to: 0.01, duration: 0.16)
itemSelectionLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.16, completion: { [weak itemSelectionLayer] _ in
itemSelectionLayer?.removeFromSuperlayer()
})
let itemSelectionTintContainerLayer = itemSelectionLayer.tintContainerLayer
itemSelectionTintContainerLayer.opacity = 0.0
itemSelectionTintContainerLayer.animateScale(from: 1.0, to: 0.01, duration: 0.16)
itemSelectionTintContainerLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.16, completion: { [weak itemSelectionTintContainerLayer] _ in
itemSelectionTintContainerLayer?.removeFromSuperlayer()
})
}
} else if let position = updatedItemPositions?[.item(id: id)], transitionHintInstalledGroupId != id.groupId {
transition.setPosition(layer: itemLayer, position: position, completion: { [weak itemLayer] _ in
itemLayer?.removeFromSuperlayer()
})
if let itemSelectionLayer = itemSelectionLayer {
transition.setPosition(layer: itemSelectionLayer, position: position, completion: { [weak itemSelectionLayer] _ in
itemSelectionLayer?.removeFromSuperlayer()
})
}
} else {
itemLayer.opacity = 0.0
itemLayer.animateScale(from: 1.0, to: 0.01, duration: 0.2)
itemLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak itemLayer] _ in
itemLayer?.removeFromSuperlayer()
})
if let itemSelectionLayer = itemSelectionLayer {
itemSelectionLayer.opacity = 0.0
itemSelectionLayer.animateScale(from: 1.0, to: 0.01, duration: 0.2)
itemSelectionLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak itemSelectionLayer] _ in
itemSelectionLayer?.removeFromSuperlayer()
})
let itemSelectionTintContainerLayer = itemSelectionLayer.tintContainerLayer
itemSelectionTintContainerLayer.opacity = 0.0
itemSelectionTintContainerLayer.animateScale(from: 1.0, to: 0.01, duration: 0.2)
itemSelectionTintContainerLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak itemSelectionTintContainerLayer] _ in
itemSelectionTintContainerLayer?.removeFromSuperlayer()
})
}
}
} else {
itemLayer.removeFromSuperlayer()
if let itemSelectionLayer = itemSelectionLayer {
itemSelectionLayer.removeFromSuperlayer()
}
}
}
}
for id in removedIds {
self.visibleItemLayers.removeValue(forKey: id)
self.visibleItemSelectionLayers.removeValue(forKey: id)
if let view = self.visibleItemPlaceholderViews.removeValue(forKey: id) {
view.removeFromSuperview()
removedPlaceholerViews = true
}
}
var removedItemSelectionLayerIds: [ItemLayer.Key] = []
for (id, itemSelectionLayer) in self.visibleItemSelectionLayers {
var fileId: MediaId?
switch id.itemId {
case let .animation(id):
switch id {
case let .file(fileIdValue):
fileId = fileIdValue
default:
break
}
default:
break
}
if let fileId = fileId, component.selectedItems.contains(fileId) {
} else {
itemSelectionLayer.removeFromSuperlayer()
removedItemSelectionLayerIds.append(id)
}
}
for id in removedItemSelectionLayerIds {
self.visibleItemSelectionLayers.removeValue(forKey: id)
}
var removedGroupHeaderIds: [AnyHashable] = []
for (id, groupHeaderLayer) in self.visibleGroupHeaders {
@@ -4554,7 +4680,7 @@ public final class EmojiPagerContentComponent: Component {
return hasPremium
}
public static func emojiInputData(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, isStandalone: Bool, isStatusSelection: Bool, isReactionSelection: Bool, topReactionItems: [AvailableReactions.Reaction], areUnicodeEmojiEnabled: Bool, areCustomEmojiEnabled: Bool, chatPeerId: EnginePeer.Id?) -> Signal<EmojiPagerContentComponent, NoError> {
public static func emojiInputData(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, isStandalone: Bool, isStatusSelection: Bool, isReactionSelection: Bool, isQuickReactionSelection: Bool = false, topReactionItems: [AvailableReactions.Reaction], areUnicodeEmojiEnabled: Bool, areCustomEmojiEnabled: Bool, chatPeerId: EnginePeer.Id?, selectedItems: Set<MediaId> = Set()) -> Signal<EmojiPagerContentComponent, NoError> {
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
@@ -4568,6 +4694,7 @@ public final class EmojiPagerContentComponent: Component {
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudFeaturedStatusEmoji)
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudRecentStatusEmoji)
} else if isReactionSelection {
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudTopReactions)
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudRecentReactions)
}
@@ -4593,6 +4720,7 @@ public final class EmojiPagerContentComponent: Component {
var isPremiumLocked: Bool
var isFeatured: Bool
var isExpandable: Bool
var isClearable: Bool
var headerItem: EntityKeyboardAnimationData?
var items: [EmojiPagerContentComponent.Item]
}
@@ -4602,6 +4730,7 @@ public final class EmojiPagerContentComponent: Component {
var recentEmoji: OrderedItemListView?
var featuredStatusEmoji: OrderedItemListView?
var recentStatusEmoji: OrderedItemListView?
var topReactions: OrderedItemListView?
var recentReactions: OrderedItemListView?
for orderedView in view.orderedItemListsViews {
if orderedView.collectionId == Namespaces.OrderedItemList.LocalRecentEmoji {
@@ -4612,6 +4741,8 @@ public final class EmojiPagerContentComponent: Component {
recentStatusEmoji = orderedView
} else if orderedView.collectionId == Namespaces.OrderedItemList.CloudRecentReactions {
recentReactions = orderedView
} else if orderedView.collectionId == Namespaces.OrderedItemList.CloudTopReactions {
topReactions = orderedView
}
}
@@ -4628,7 +4759,7 @@ public final class EmojiPagerContentComponent: Component {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: true, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: true, isClearable: false, headerItem: nil, items: [resultItem]))
}
var existingIds = Set<MediaId>()
@@ -4688,6 +4819,41 @@ public final class EmojiPagerContentComponent: Component {
}
} else if isReactionSelection {
var existingIds = Set<MessageReaction.Reaction>()
var topReactionItems = topReactionItems
if topReactionItems.isEmpty {
if let topReactions = topReactions {
for item in topReactions.items {
guard let topReaction = item.contents.get(RecentReactionItem.self) else {
continue
}
switch topReaction.content {
case let .builtin(value):
if let reaction = availableReactions?.reactions.first(where: { $0.value == .builtin(value) }) {
topReactionItems.append(reaction)
} else {
continue
}
case let .custom(file):
topReactionItems.append(AvailableReactions.Reaction(
isEnabled: true,
isPremium: false,
value: .custom(file.fileId.id),
title: "",
staticIcon: file,
appearAnimation: file,
selectAnimation: file,
activateAnimation: file,
effectAnimation: file,
aroundAnimation: file,
centerAnimation: file
))
}
}
}
}
for reactionItem in topReactionItems {
if existingIds.contains(reactionItem.value) {
continue
@@ -4706,56 +4872,112 @@ public final class EmojiPagerContentComponent: Component {
let groupId = "recent"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
if itemGroups[groupIndex].items.count >= 8 * 2 {
break
}
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
if let recentReactions = recentReactions {
for item in recentReactions.items {
guard let item = item.contents.get(RecentReactionItem.self) else {
continue
}
let animationFile: TelegramMediaFile
switch item.content {
case let .builtin(value):
if existingIds.contains(.builtin(value)) {
if hasPremium {
var hasRecent = false
if let recentReactions = recentReactions, !recentReactions.items.isEmpty {
hasRecent = true
}
let maxRecentLineCount: Int
#if DEBUG
maxRecentLineCount = 4
#else
maxRecentLineCount = 10
#endif
//TODO:localize
let popularTitle = hasRecent ? "Recently Used" : "Popular"
if let availableReactions = availableReactions {
for reactionItem in availableReactions.reactions {
if !reactionItem.isEnabled {
continue
}
existingIds.insert(.builtin(value))
if let availableReactions = availableReactions, let availableReaction = availableReactions.reactions.first(where: { $0.value == .builtin(value) }) {
if let centerAnimation = availableReaction.centerAnimation {
animationFile = centerAnimation
if existingIds.contains(reactionItem.value) {
continue
}
existingIds.insert(reactionItem.value)
let animationFile = reactionItem.selectAnimation
let animationData = EntityKeyboardAnimationData(file: animationFile, isReaction: true)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: animationFile,
subgroupId: nil
)
let groupId = "popular"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: hasRecent && !isQuickReactionSelection, headerItem: nil, items: [resultItem]))
}
}
}
if let recentReactions = recentReactions {
var popularInsertIndex = 0
for item in recentReactions.items {
guard let item = item.contents.get(RecentReactionItem.self) else {
continue
}
let animationFile: TelegramMediaFile
switch item.content {
case let .builtin(value):
if existingIds.contains(.builtin(value)) {
continue
}
existingIds.insert(.builtin(value))
if let availableReactions = availableReactions, let availableReaction = availableReactions.reactions.first(where: { $0.value == .builtin(value) }) {
if let centerAnimation = availableReaction.centerAnimation {
animationFile = centerAnimation
} else {
continue
}
} else {
continue
}
case let .custom(file):
if existingIds.contains(.custom(file.fileId.id)) {
continue
}
existingIds.insert(.custom(file.fileId.id))
animationFile = file
}
let animationData = EntityKeyboardAnimationData(file: animationFile, isReaction: true)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: animationFile,
subgroupId: nil
)
let groupId = "popular"
if let groupIndex = itemGroupIndexById[groupId] {
if itemGroups[groupIndex].items.count + 1 >= maxRecentLineCount * 8 {
break
}
itemGroups[groupIndex].items.insert(resultItem, at: popularInsertIndex)
popularInsertIndex += 1
} else {
continue
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: hasRecent && !isQuickReactionSelection, headerItem: nil, items: [resultItem]))
}
case let .custom(file):
if existingIds.contains(.custom(file.fileId.id)) {
continue
}
existingIds.insert(.custom(file.fileId.id))
animationFile = file
}
let animationData = EntityKeyboardAnimationData(file: animationFile, isReaction: true)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: animationFile,
subgroupId: nil
)
let groupId = "recent"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, headerItem: nil, items: [resultItem]))
}
}
}
@@ -4799,7 +5021,7 @@ public final class EmojiPagerContentComponent: Component {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: true, headerItem: nil, items: [resultItem]))
}
}
}
@@ -4819,7 +5041,7 @@ public final class EmojiPagerContentComponent: Component {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@@ -4883,7 +5105,7 @@ public final class EmojiPagerContentComponent: Component {
break inner
}
}
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, isExpandable: false, headerItem: headerItem, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, isExpandable: false, isClearable: false, headerItem: headerItem, items: [resultItem]))
}
}
@@ -4937,7 +5159,7 @@ public final class EmojiPagerContentComponent: Component {
)
}
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: true, isExpandable: true, headerItem: headerItem, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: true, isExpandable: true, isClearable: false, headerItem: headerItem, items: [resultItem]))
}
}
}
@@ -4952,11 +5174,6 @@ public final class EmojiPagerContentComponent: Component {
animationRenderer: animationRenderer,
inputInteractionHolder: EmojiPagerContentComponent.InputInteractionHolder(),
itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in
var hasClear = false
if group.id == AnyHashable("recent") {
hasClear = true
}
var headerItem = group.headerItem
if let groupId = group.id.base as? ItemCollectionId {
@@ -4983,7 +5200,7 @@ public final class EmojiPagerContentComponent: Component {
isFeatured: group.isFeatured,
isPremiumLocked: group.isPremiumLocked,
isEmbedded: false,
hasClear: hasClear,
hasClear: group.isClearable,
isExpandable: group.isExpandable,
displayPremiumBadges: false,
headerItem: headerItem,
@@ -4992,7 +5209,8 @@ public final class EmojiPagerContentComponent: Component {
},
itemLayoutType: .compact,
warpContentsOnEdges: isReactionSelection || isStatusSelection,
enableLongPress: isReactionSelection
enableLongPress: isReactionSelection && !isQuickReactionSelection,
selectedItems: selectedItems
)
}
return emojiItems