mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user