mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Channel reaction improvements
This commit is contained in:
parent
afdc11b171
commit
48a2a72a6a
@ -2246,6 +2246,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
|||||||
public var reactionItems: [ReactionContextItem]
|
public var reactionItems: [ReactionContextItem]
|
||||||
public var selectedReactionItems: Set<MessageReaction.Reaction>
|
public var selectedReactionItems: Set<MessageReaction.Reaction>
|
||||||
public var animationCache: AnimationCache?
|
public var animationCache: AnimationCache?
|
||||||
|
public var alwaysAllowPremiumReactions: Bool
|
||||||
public var getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?
|
public var getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?
|
||||||
public var disablePositionLock: Bool
|
public var disablePositionLock: Bool
|
||||||
public var tip: Tip?
|
public var tip: Tip?
|
||||||
@ -2259,6 +2260,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
|||||||
reactionItems: [ReactionContextItem] = [],
|
reactionItems: [ReactionContextItem] = [],
|
||||||
selectedReactionItems: Set<MessageReaction.Reaction> = Set(),
|
selectedReactionItems: Set<MessageReaction.Reaction> = Set(),
|
||||||
animationCache: AnimationCache? = nil,
|
animationCache: AnimationCache? = nil,
|
||||||
|
alwaysAllowPremiumReactions: Bool = false,
|
||||||
getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)? = nil,
|
getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)? = nil,
|
||||||
disablePositionLock: Bool = false,
|
disablePositionLock: Bool = false,
|
||||||
tip: Tip? = nil,
|
tip: Tip? = nil,
|
||||||
@ -2271,6 +2273,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
|||||||
self.animationCache = animationCache
|
self.animationCache = animationCache
|
||||||
self.reactionItems = reactionItems
|
self.reactionItems = reactionItems
|
||||||
self.selectedReactionItems = selectedReactionItems
|
self.selectedReactionItems = selectedReactionItems
|
||||||
|
self.alwaysAllowPremiumReactions = alwaysAllowPremiumReactions
|
||||||
self.getEmojiContent = getEmojiContent
|
self.getEmojiContent = getEmojiContent
|
||||||
self.disablePositionLock = disablePositionLock
|
self.disablePositionLock = disablePositionLock
|
||||||
self.tip = tip
|
self.tip = tip
|
||||||
@ -2284,6 +2287,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
|||||||
self.context = nil
|
self.context = nil
|
||||||
self.reactionItems = []
|
self.reactionItems = []
|
||||||
self.selectedReactionItems = Set()
|
self.selectedReactionItems = Set()
|
||||||
|
self.alwaysAllowPremiumReactions = false
|
||||||
self.getEmojiContent = nil
|
self.getEmojiContent = nil
|
||||||
self.disablePositionLock = false
|
self.disablePositionLock = false
|
||||||
self.tip = nil
|
self.tip = nil
|
||||||
|
@ -46,7 +46,7 @@ public protocol ContextControllerActionsStackItem: AnyObject {
|
|||||||
var id: AnyHashable? { get }
|
var id: AnyHashable? { get }
|
||||||
var tip: ContextController.Tip? { get }
|
var tip: ContextController.Tip? { get }
|
||||||
var tipSignal: Signal<ContextController.Tip?, NoError>? { get }
|
var tipSignal: Signal<ContextController.Tip?, NoError>? { get }
|
||||||
var reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)? { get }
|
var reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)? { get }
|
||||||
var dismissed: (() -> Void)? { get }
|
var dismissed: (() -> Void)? { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -906,7 +906,7 @@ final class ContextControllerActionsListStackItem: ContextControllerActionsStack
|
|||||||
|
|
||||||
let id: AnyHashable?
|
let id: AnyHashable?
|
||||||
let items: [ContextMenuItem]
|
let items: [ContextMenuItem]
|
||||||
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
||||||
let tip: ContextController.Tip?
|
let tip: ContextController.Tip?
|
||||||
let tipSignal: Signal<ContextController.Tip?, NoError>?
|
let tipSignal: Signal<ContextController.Tip?, NoError>?
|
||||||
let dismissed: (() -> Void)?
|
let dismissed: (() -> Void)?
|
||||||
@ -914,7 +914,7 @@ final class ContextControllerActionsListStackItem: ContextControllerActionsStack
|
|||||||
init(
|
init(
|
||||||
id: AnyHashable?,
|
id: AnyHashable?,
|
||||||
items: [ContextMenuItem],
|
items: [ContextMenuItem],
|
||||||
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
|
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
|
||||||
tip: ContextController.Tip?,
|
tip: ContextController.Tip?,
|
||||||
tipSignal: Signal<ContextController.Tip?, NoError>?,
|
tipSignal: Signal<ContextController.Tip?, NoError>?,
|
||||||
dismissed: (() -> Void)?
|
dismissed: (() -> Void)?
|
||||||
@ -1004,7 +1004,7 @@ final class ContextControllerActionsCustomStackItem: ContextControllerActionsSta
|
|||||||
|
|
||||||
let id: AnyHashable?
|
let id: AnyHashable?
|
||||||
private let content: ContextControllerItemsContent
|
private let content: ContextControllerItemsContent
|
||||||
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
||||||
let tip: ContextController.Tip?
|
let tip: ContextController.Tip?
|
||||||
let tipSignal: Signal<ContextController.Tip?, NoError>?
|
let tipSignal: Signal<ContextController.Tip?, NoError>?
|
||||||
let dismissed: (() -> Void)?
|
let dismissed: (() -> Void)?
|
||||||
@ -1012,7 +1012,7 @@ final class ContextControllerActionsCustomStackItem: ContextControllerActionsSta
|
|||||||
init(
|
init(
|
||||||
id: AnyHashable?,
|
id: AnyHashable?,
|
||||||
content: ContextControllerItemsContent,
|
content: ContextControllerItemsContent,
|
||||||
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
|
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
|
||||||
tip: ContextController.Tip?,
|
tip: ContextController.Tip?,
|
||||||
tipSignal: Signal<ContextController.Tip?, NoError>?,
|
tipSignal: Signal<ContextController.Tip?, NoError>?,
|
||||||
dismissed: (() -> Void)?
|
dismissed: (() -> Void)?
|
||||||
@ -1041,9 +1041,9 @@ final class ContextControllerActionsCustomStackItem: ContextControllerActionsSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeContextControllerActionsStackItem(items: ContextController.Items) -> [ContextControllerActionsStackItem] {
|
func makeContextControllerActionsStackItem(items: ContextController.Items) -> [ContextControllerActionsStackItem] {
|
||||||
var reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
var reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
||||||
if let context = items.context, let animationCache = items.animationCache, !items.reactionItems.isEmpty {
|
if let context = items.context, let animationCache = items.animationCache, !items.reactionItems.isEmpty {
|
||||||
reactionItems = (context, items.reactionItems, items.selectedReactionItems, animationCache, items.getEmojiContent)
|
reactionItems = (context, items.reactionItems, items.selectedReactionItems, animationCache, alwaysAllowPremiumReactions: items.alwaysAllowPremiumReactions, items.getEmojiContent)
|
||||||
}
|
}
|
||||||
switch items.content {
|
switch items.content {
|
||||||
case let .list(listItems):
|
case let .list(listItems):
|
||||||
@ -1167,7 +1167,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode {
|
|||||||
var tip: ContextController.Tip?
|
var tip: ContextController.Tip?
|
||||||
let tipSignal: Signal<ContextController.Tip?, NoError>?
|
let tipSignal: Signal<ContextController.Tip?, NoError>?
|
||||||
var tipNode: InnerTextSelectionTipContainerNode?
|
var tipNode: InnerTextSelectionTipContainerNode?
|
||||||
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
|
||||||
let itemDismissed: (() -> Void)?
|
let itemDismissed: (() -> Void)?
|
||||||
var storedScrollingState: CGFloat?
|
var storedScrollingState: CGFloat?
|
||||||
let positionLock: CGFloat?
|
let positionLock: CGFloat?
|
||||||
@ -1182,7 +1182,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode {
|
|||||||
item: ContextControllerActionsStackItem,
|
item: ContextControllerActionsStackItem,
|
||||||
tip: ContextController.Tip?,
|
tip: ContextController.Tip?,
|
||||||
tipSignal: Signal<ContextController.Tip?, NoError>?,
|
tipSignal: Signal<ContextController.Tip?, NoError>?,
|
||||||
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
|
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
|
||||||
itemDismissed: (() -> Void)?,
|
itemDismissed: (() -> Void)?,
|
||||||
positionLock: CGFloat?
|
positionLock: CGFloat?
|
||||||
) {
|
) {
|
||||||
@ -1333,7 +1333,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode {
|
|||||||
|
|
||||||
private var selectionPanGesture: UIPanGestureRecognizer?
|
private var selectionPanGesture: UIPanGestureRecognizer?
|
||||||
|
|
||||||
var topReactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)? {
|
var topReactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)? {
|
||||||
return self.itemContainers.last?.reactionItems
|
return self.itemContainers.last?.reactionItems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,6 +639,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
|
|||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
items: reactionItems.reactionItems,
|
items: reactionItems.reactionItems,
|
||||||
selectedItems: reactionItems.selectedReactionItems,
|
selectedItems: reactionItems.selectedReactionItems,
|
||||||
|
alwaysAllowPremiumReactions: reactionItems.alwaysAllowPremiumReactions,
|
||||||
getEmojiContent: reactionItems.getEmojiContent,
|
getEmojiContent: reactionItems.getEmojiContent,
|
||||||
isExpandedUpdated: { [weak self] transition in
|
isExpandedUpdated: { [weak self] transition in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -916,7 +917,11 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
|
|||||||
|
|
||||||
reactionContextNode.updateLayout(size: layout.size, insets: UIEdgeInsets(top: topInset, left: layout.safeInsets.left, bottom: 0.0, right: layout.safeInsets.right), anchorRect: reactionAnchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: isAnimatingOut, transition: reactionContextNodeTransition)
|
reactionContextNode.updateLayout(size: layout.size, insets: UIEdgeInsets(top: topInset, left: layout.safeInsets.left, bottom: 0.0, right: layout.safeInsets.right), anchorRect: reactionAnchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: isAnimatingOut, transition: reactionContextNodeTransition)
|
||||||
|
|
||||||
|
if reactionContextNode.alwaysAllowPremiumReactions {
|
||||||
|
self.proposedReactionsPositionLock = contentRect.minY - 18.0 - reactionContextNode.contentHeight
|
||||||
|
} else {
|
||||||
self.proposedReactionsPositionLock = contentRect.minY - 18.0 - reactionContextNode.contentHeight - (46.0 + 54.0 - 4.0)
|
self.proposedReactionsPositionLock = contentRect.minY - 18.0 - reactionContextNode.contentHeight - (46.0 + 54.0 - 4.0)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.proposedReactionsPositionLock = nil
|
self.proposedReactionsPositionLock = nil
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,7 @@ public class DrawingReactionEntityView: DrawingStickerEntityView {
|
|||||||
items: reactionItems.map(ReactionContextItem.reaction),
|
items: reactionItems.map(ReactionContextItem.reaction),
|
||||||
selectedItems: Set(),
|
selectedItems: Set(),
|
||||||
title: nil,
|
title: nil,
|
||||||
|
alwaysAllowPremiumReactions: false,
|
||||||
getEmojiContent: { [weak self] animationCache, animationRenderer in
|
getEmojiContent: { [weak self] animationCache, animationRenderer in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
@ -150,7 +151,7 @@ public class DrawingReactionEntityView: DrawingStickerEntityView {
|
|||||||
animationCache: animationCache,
|
animationCache: animationCache,
|
||||||
animationRenderer: animationRenderer,
|
animationRenderer: animationRenderer,
|
||||||
isStandalone: false,
|
isStandalone: false,
|
||||||
subject: .reaction,
|
subject: .reaction(onlyTop: false),
|
||||||
hasTrending: false,
|
hasTrending: false,
|
||||||
topReactionItems: mappedReactionItems,
|
topReactionItems: mappedReactionItems,
|
||||||
areUnicodeEmojiEnabled: false,
|
areUnicodeEmojiEnabled: false,
|
||||||
|
@ -1192,10 +1192,10 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
case .nameColors:
|
case .nameColors:
|
||||||
titleText = strings.ChannelBoost_EnableColors
|
titleText = strings.ChannelBoost_EnableColors
|
||||||
string = strings.ChannelBoost_EnableColorsLevelText("\(premiumConfiguration.minChannelNameColorLevel)").string
|
string = strings.ChannelBoost_EnableColorsLevelText("\(premiumConfiguration.minChannelNameColorLevel)").string
|
||||||
case .channelReactions:
|
case let .channelReactions(reactionCount):
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
titleText = "Custom Reactions"
|
titleText = "Custom Reactions"
|
||||||
string = "Your channel needs \(valueString) to add custom emoji as reactions.\n\nAsk your **Premium** subscribers to boost your channel with this link:"
|
string = "Your channel needs to reach **Level \(reactionCount)** to add **\(reactionCount)** custom emoji as reactions.\n\nAsk your **Premium** subscribers to boost your channel with this link:"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let storiesString = strings.ChannelBoost_StoriesPerDay(level)
|
let storiesString = strings.ChannelBoost_StoriesPerDay(level)
|
||||||
@ -1777,10 +1777,10 @@ public class PremiumLimitScreen: ViewControllerComponentContainer {
|
|||||||
case storiesWeekly
|
case storiesWeekly
|
||||||
case storiesMonthly
|
case storiesMonthly
|
||||||
|
|
||||||
public enum BoostSubject {
|
public enum BoostSubject: Equatable {
|
||||||
case stories
|
case stories
|
||||||
case nameColors
|
case nameColors
|
||||||
case channelReactions
|
case channelReactions(reactionCount: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
case storiesChannelBoost(peer: EnginePeer, boostSubject: BoostSubject, isCurrent: Bool, level: Int32, currentLevelBoosts: Int32, nextLevelBoosts: Int32?, link: String?, myBoostCount: Int32, canBoostAgain: Bool)
|
case storiesChannelBoost(peer: EnginePeer, boostSubject: BoostSubject, isCurrent: Bool, level: Int32, currentLevelBoosts: Int32, nextLevelBoosts: Int32?, link: String?, myBoostCount: Int32, canBoostAgain: Bool)
|
||||||
|
@ -296,6 +296,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
private var extensionDistance: CGFloat = 0.0
|
private var extensionDistance: CGFloat = 0.0
|
||||||
public private(set) var visibleExtensionDistance: CGFloat = 0.0
|
public private(set) var visibleExtensionDistance: CGFloat = 0.0
|
||||||
|
|
||||||
|
private var emojiContentHeight: CGFloat = 300.0
|
||||||
|
private var didInitializeEmojiContentHeight: Bool = false
|
||||||
private var emojiContentLayout: EmojiPagerContentComponent.CustomLayout?
|
private var emojiContentLayout: EmojiPagerContentComponent.CustomLayout?
|
||||||
private var emojiContent: EmojiPagerContentComponent?
|
private var emojiContent: EmojiPagerContentComponent?
|
||||||
private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation?
|
private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation?
|
||||||
@ -322,6 +324,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
private var availableReactions: AvailableReactions?
|
private var availableReactions: AvailableReactions?
|
||||||
private var availableReactionsDisposable: Disposable?
|
private var availableReactionsDisposable: Disposable?
|
||||||
|
|
||||||
|
public let alwaysAllowPremiumReactions: Bool
|
||||||
private var hasPremium: Bool?
|
private var hasPremium: Bool?
|
||||||
private var hasPremiumDisposable: Disposable?
|
private var hasPremiumDisposable: Disposable?
|
||||||
|
|
||||||
@ -368,7 +371,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(context: AccountContext, animationCache: AnimationCache, presentationData: PresentationData, items: [ReactionContextItem], selectedItems: Set<MessageReaction.Reaction>, title: String? = nil, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?, isExpandedUpdated: @escaping (ContainedViewLayoutTransition) -> Void, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, requestUpdateOverlayWantsToBeBelowKeyboard: @escaping (ContainedViewLayoutTransition) -> Void) {
|
public init(context: AccountContext, animationCache: AnimationCache, presentationData: PresentationData, items: [ReactionContextItem], selectedItems: Set<MessageReaction.Reaction>, title: String? = nil, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?, isExpandedUpdated: @escaping (ContainedViewLayoutTransition) -> Void, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, requestUpdateOverlayWantsToBeBelowKeyboard: @escaping (ContainedViewLayoutTransition) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.items = items
|
self.items = items
|
||||||
@ -468,6 +471,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.contentTopInset = 24.0
|
self.contentTopInset = 24.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.alwaysAllowPremiumReactions = alwaysAllowPremiumReactions
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.backgroundNode)
|
self.addSubnode(self.backgroundNode)
|
||||||
@ -486,6 +491,9 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
strongSelf.availableReactions = availableReactions
|
strongSelf.availableReactions = availableReactions
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if alwaysAllowPremiumReactions {
|
||||||
|
self.hasPremium = true
|
||||||
|
} else {
|
||||||
self.hasPremiumDisposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|
self.hasPremiumDisposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -493,6 +501,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
strongSelf.hasPremium = peer?.isPremium ?? false
|
strongSelf.hasPremium = peer?.isPremium ?? false
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if let getEmojiContent = getEmojiContent {
|
if let getEmojiContent = getEmojiContent {
|
||||||
let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)
|
let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)
|
||||||
@ -566,6 +575,13 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
emojiTransition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(contentAnimation)
|
emojiTransition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(contentAnimation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hideTopPanel = false
|
||||||
|
if strongSelf.isReactionSearchActive {
|
||||||
|
hideTopPanel = true
|
||||||
|
} else if strongSelf.alwaysAllowPremiumReactions {
|
||||||
|
hideTopPanel = true
|
||||||
|
}
|
||||||
|
|
||||||
let _ = reactionSelectionComponentHost.update(
|
let _ = reactionSelectionComponentHost.update(
|
||||||
transition: emojiTransition,
|
transition: emojiTransition,
|
||||||
component: AnyComponent(EmojiStatusSelectionComponent(
|
component: AnyComponent(EmojiStatusSelectionComponent(
|
||||||
@ -575,7 +591,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
emojiContent: emojiContent,
|
emojiContent: emojiContent,
|
||||||
backgroundColor: .clear,
|
backgroundColor: .clear,
|
||||||
separatorColor: strongSelf.presentationData.theme.list.itemPlainSeparatorColor.withMultipliedAlpha(0.5),
|
separatorColor: strongSelf.presentationData.theme.list.itemPlainSeparatorColor.withMultipliedAlpha(0.5),
|
||||||
hideTopPanel: strongSelf.isReactionSearchActive,
|
hideTopPanel: hideTopPanel,
|
||||||
hideTopPanelUpdated: { hideTopPanel, transition in
|
hideTopPanelUpdated: { hideTopPanel, transition in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -585,7 +601,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: componentView.bounds.width, height: 300.0)
|
containerSize: CGSize(width: componentView.bounds.width, height: strongSelf.emojiContentHeight)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -1023,7 +1039,13 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
expandItemSize = 30.0
|
expandItemSize = 30.0
|
||||||
expandTintOffset = 0.0
|
expandTintOffset = 0.0
|
||||||
}
|
}
|
||||||
let baseNextFrame = CGRect(origin: CGPoint(x: self.scrollNode.view.bounds.width - expandItemSize - 9.0, y: self.contentTopInset + containerHeight - contentHeight + floor((contentHeight - expandItemSize) / 2.0) + (self.isExpanded ? (46.0 + 54.0 - 4.0) : 0.0)), size: CGSize(width: expandItemSize, height: expandItemSize + self.extensionDistance))
|
var baseNextFrame = CGRect(origin: CGPoint(x: self.scrollNode.view.bounds.width - expandItemSize - 9.0, y: self.contentTopInset + containerHeight - contentHeight + floor((contentHeight - expandItemSize) / 2.0)), size: CGSize(width: expandItemSize, height: expandItemSize + self.extensionDistance))
|
||||||
|
if self.isExpanded {
|
||||||
|
if self.alwaysAllowPremiumReactions {
|
||||||
|
} else {
|
||||||
|
baseNextFrame.origin.y += 46.0 + 54.0 - 4.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
transition.updateFrame(view: expandItemView, frame: baseNextFrame)
|
transition.updateFrame(view: expandItemView, frame: baseNextFrame)
|
||||||
transition.updateFrame(view: expandItemView.tintView, frame: baseNextFrame.offsetBy(dx: 0.0, dy: expandTintOffset))
|
transition.updateFrame(view: expandItemView.tintView, frame: baseNextFrame.offsetBy(dx: 0.0, dy: expandTintOffset))
|
||||||
@ -1124,7 +1146,16 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
visibleItemCount: itemCount
|
visibleItemCount: itemCount
|
||||||
)
|
)
|
||||||
|
|
||||||
var scrollFrame = CGRect(origin: CGPoint(x: 0.0, y: self.isExpanded ? (46.0 + 54.0 - 4.0) : self.contentTopInset), size: actualBackgroundFrame.size)
|
var scrollFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: actualBackgroundFrame.size)
|
||||||
|
if self.isExpanded {
|
||||||
|
if self.alwaysAllowPremiumReactions {
|
||||||
|
scrollFrame.origin.y += 0.0
|
||||||
|
} else {
|
||||||
|
scrollFrame.origin.y += 46.0 + 54.0 - 4.0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scrollFrame.origin.y += self.contentTopInset
|
||||||
|
}
|
||||||
scrollFrame.origin.y += floorToScreenPixels(self.extensionDistance / 2.0)
|
scrollFrame.origin.y += floorToScreenPixels(self.extensionDistance / 2.0)
|
||||||
|
|
||||||
transition.updatePosition(node: self.contentContainer, position: visualBackgroundFrame.center, beginWithCurrentState: true)
|
transition.updatePosition(node: self.contentContainer, position: visualBackgroundFrame.center, beginWithCurrentState: true)
|
||||||
@ -1142,6 +1173,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.updateScrolling(transition: transition)
|
self.updateScrolling(transition: transition)
|
||||||
|
|
||||||
self.emojiContentLayout = EmojiPagerContentComponent.CustomLayout(
|
self.emojiContentLayout = EmojiPagerContentComponent.CustomLayout(
|
||||||
|
topPanelAlwaysHidden: self.alwaysAllowPremiumReactions,
|
||||||
itemsPerRow: itemCount,
|
itemsPerRow: itemCount,
|
||||||
itemSize: itemSize,
|
itemSize: itemSize,
|
||||||
sideInset: sideInset,
|
sideInset: sideInset,
|
||||||
@ -1168,6 +1200,13 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
componentTransition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(contentAnimation)
|
componentTransition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(contentAnimation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hideTopPanel = false
|
||||||
|
if self.isReactionSearchActive {
|
||||||
|
hideTopPanel = true
|
||||||
|
} else if self.alwaysAllowPremiumReactions {
|
||||||
|
hideTopPanel = true
|
||||||
|
}
|
||||||
|
|
||||||
let _ = reactionSelectionComponentHost.update(
|
let _ = reactionSelectionComponentHost.update(
|
||||||
transition: componentTransition,
|
transition: componentTransition,
|
||||||
component: AnyComponent(EmojiStatusSelectionComponent(
|
component: AnyComponent(EmojiStatusSelectionComponent(
|
||||||
@ -1177,7 +1216,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
emojiContent: emojiContent,
|
emojiContent: emojiContent,
|
||||||
backgroundColor: .clear,
|
backgroundColor: .clear,
|
||||||
separatorColor: self.presentationData.theme.list.itemPlainSeparatorColor.withMultipliedAlpha(0.5),
|
separatorColor: self.presentationData.theme.list.itemPlainSeparatorColor.withMultipliedAlpha(0.5),
|
||||||
hideTopPanel: self.isReactionSearchActive,
|
hideTopPanel: hideTopPanel,
|
||||||
hideTopPanelUpdated: { [weak self] hideTopPanel, transition in
|
hideTopPanelUpdated: { [weak self] hideTopPanel, transition in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -1187,7 +1226,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: actualBackgroundFrame.width, height: 300.0)
|
containerSize: CGSize(width: actualBackgroundFrame.width, height: self.emojiContentHeight)
|
||||||
)
|
)
|
||||||
if let componentView = reactionSelectionComponentHost.view {
|
if let componentView = reactionSelectionComponentHost.view {
|
||||||
var animateIn = false
|
var animateIn = false
|
||||||
@ -1229,7 +1268,15 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
if let mirrorContentClippingView = emojiView.mirrorContentClippingView {
|
if let mirrorContentClippingView = emojiView.mirrorContentClippingView {
|
||||||
mirrorContentClippingView.clipsToBounds = false
|
mirrorContentClippingView.clipsToBounds = false
|
||||||
Transition(transition).animateBoundsOrigin(view: mirrorContentClippingView, from: CGPoint(x: 0.0, y: 46.0 + 54.0 - 4.0), to: CGPoint(), additive: true, completion: { [weak mirrorContentClippingView] _ in
|
|
||||||
|
var animationOffsetY: CGFloat = 0.0
|
||||||
|
if self.alwaysAllowPremiumReactions {
|
||||||
|
animationOffsetY += -4.0
|
||||||
|
} else {
|
||||||
|
animationOffsetY += 46.0 + 54.0 - 4.0
|
||||||
|
}
|
||||||
|
|
||||||
|
Transition(transition).animateBoundsOrigin(view: mirrorContentClippingView, from: CGPoint(x: 0.0, y: animationOffsetY), to: CGPoint(), additive: true, completion: { [weak mirrorContentClippingView] _ in
|
||||||
mirrorContentClippingView?.clipsToBounds = true
|
mirrorContentClippingView?.clipsToBounds = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1260,7 +1307,14 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
componentTransition.setFrame(view: componentView, frame: CGRect(origin: componentFrame.origin, size: CGSize(width: componentFrame.width, height: componentFrame.height)))
|
componentTransition.setFrame(view: componentView, frame: CGRect(origin: componentFrame.origin, size: CGSize(width: componentFrame.width, height: componentFrame.height)))
|
||||||
|
|
||||||
if animateIn {
|
if animateIn {
|
||||||
transition.animatePositionAdditive(layer: componentView.layer, offset: CGPoint(x: 0.0, y: -(46.0 + 54.0 - 4.0) + floorToScreenPixels(self.animateFromExtensionDistance / 2.0)))
|
var animationOffsetY: CGFloat = 0.0
|
||||||
|
if self.alwaysAllowPremiumReactions {
|
||||||
|
animationOffsetY += 4.0
|
||||||
|
} else {
|
||||||
|
animationOffsetY += 46.0 + 54.0 - 4.0
|
||||||
|
}
|
||||||
|
|
||||||
|
transition.animatePositionAdditive(layer: componentView.layer, offset: CGPoint(x: 0.0, y: -animationOffsetY + floorToScreenPixels(self.animateFromExtensionDistance / 2.0)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1317,6 +1371,17 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.didInitializeEmojiContentHeight {
|
||||||
|
self.didInitializeEmojiContentHeight = true
|
||||||
|
|
||||||
|
if emojiContent.contentItemGroups.count == 1 {
|
||||||
|
let itemCount = emojiContent.contentItemGroups[0].items.count
|
||||||
|
let numRows = (itemCount + (emojiContentLayout.itemsPerRow - 1)) / emojiContentLayout.itemsPerRow
|
||||||
|
let proposedHeight: CGFloat = CGFloat(numRows) * emojiContentLayout.itemSize + CGFloat(numRows - 1) * emojiContentLayout.itemSpacing + emojiContentLayout.itemSpacing * 2.0 + 5.0
|
||||||
|
self.emojiContentHeight = min(300.0, proposedHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emojiContent.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction(
|
emojiContent.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction(
|
||||||
performItemAction: { [weak self] groupId, item, sourceView, sourceRect, sourceLayer, isLongPress in
|
performItemAction: { [weak self] groupId, item, sourceView, sourceRect, sourceLayer, isLongPress in
|
||||||
guard let strongSelf = self, let availableReactions = strongSelf.availableReactions, let itemFile = item.itemFile else {
|
guard let strongSelf = self, let availableReactions = strongSelf.availableReactions, let itemFile = item.itemFile else {
|
||||||
@ -2347,7 +2412,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
if let expandItemView = self.expandItemView, expandItemView.bounds.contains(self.view.convert(point, to: self.expandItemView)) {
|
if let expandItemView = self.expandItemView, expandItemView.bounds.contains(self.view.convert(point, to: self.expandItemView)) {
|
||||||
self.animateFromExtensionDistance = self.contentTopInset * 2.0 + self.extensionDistance
|
self.animateFromExtensionDistance = self.contentTopInset * 2.0 + self.extensionDistance
|
||||||
self.contentTopInset = 0.0
|
self.contentTopInset = 0.0
|
||||||
self.currentContentHeight = 300.0
|
self.currentContentHeight = self.emojiContentHeight
|
||||||
self.isExpanded = true
|
self.isExpanded = true
|
||||||
self.longPressRecognizer?.isEnabled = false
|
self.longPressRecognizer?.isEnabled = false
|
||||||
self.isExpandedUpdated(.animated(duration: 0.4, curve: .spring))
|
self.isExpandedUpdated(.animated(duration: 0.4, curve: .spring))
|
||||||
@ -2388,7 +2453,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.extensionDistance = 0.0
|
self.extensionDistance = 0.0
|
||||||
self.visibleExtensionDistance = 0.0
|
self.visibleExtensionDistance = 0.0
|
||||||
self.contentTopInset = 0.0
|
self.contentTopInset = 0.0
|
||||||
self.currentContentHeight = 300.0
|
self.currentContentHeight = self.emojiContentHeight
|
||||||
self.isExpanded = true
|
self.isExpanded = true
|
||||||
self.isExpandedUpdated(.animated(duration: 0.4, curve: .spring))
|
self.isExpandedUpdated(.animated(duration: 0.4, curve: .spring))
|
||||||
}
|
}
|
||||||
|
@ -2298,17 +2298,20 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct CustomLayout: Equatable {
|
public struct CustomLayout: Equatable {
|
||||||
|
public var topPanelAlwaysHidden: Bool
|
||||||
public var itemsPerRow: Int
|
public var itemsPerRow: Int
|
||||||
public var itemSize: CGFloat
|
public var itemSize: CGFloat
|
||||||
public var sideInset: CGFloat
|
public var sideInset: CGFloat
|
||||||
public var itemSpacing: CGFloat
|
public var itemSpacing: CGFloat
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
|
topPanelAlwaysHidden: Bool,
|
||||||
itemsPerRow: Int,
|
itemsPerRow: Int,
|
||||||
itemSize: CGFloat,
|
itemSize: CGFloat,
|
||||||
sideInset: CGFloat,
|
sideInset: CGFloat,
|
||||||
itemSpacing: CGFloat
|
itemSpacing: CGFloat
|
||||||
) {
|
) {
|
||||||
|
self.topPanelAlwaysHidden = topPanelAlwaysHidden
|
||||||
self.itemsPerRow = itemsPerRow
|
self.itemsPerRow = itemsPerRow
|
||||||
self.itemSize = itemSize
|
self.itemSize = itemSize
|
||||||
self.sideInset = sideInset
|
self.sideInset = sideInset
|
||||||
@ -3052,7 +3055,8 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
|
|
||||||
var verticalGroupOrigin: CGFloat = self.itemInsets.top
|
var verticalGroupOrigin: CGFloat = self.itemInsets.top
|
||||||
self.itemGroupLayouts = []
|
self.itemGroupLayouts = []
|
||||||
for itemGroup in itemGroups {
|
for i in 0 ..< itemGroups.count {
|
||||||
|
let itemGroup = itemGroups[i]
|
||||||
var itemsPerRow = self.itemsPerRow
|
var itemsPerRow = self.itemsPerRow
|
||||||
var nativeItemSize = self.nativeItemSize
|
var nativeItemSize = self.nativeItemSize
|
||||||
var visibleItemSize = self.visibleItemSize
|
var visibleItemSize = self.visibleItemSize
|
||||||
@ -3145,7 +3149,10 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
collapsedItemIndex: collapsedItemIndex,
|
collapsedItemIndex: collapsedItemIndex,
|
||||||
collapsedItemText: collapsedItemText
|
collapsedItemText: collapsedItemText
|
||||||
))
|
))
|
||||||
verticalGroupOrigin += groupContentSize.height + groupSpacing
|
verticalGroupOrigin += groupContentSize.height
|
||||||
|
if i != itemGroups.count - 1 {
|
||||||
|
verticalGroupOrigin += groupSpacing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
verticalGroupOrigin += itemInsets.bottom
|
verticalGroupOrigin += itemInsets.bottom
|
||||||
self.contentSize = CGSize(width: width, height: verticalGroupOrigin)
|
self.contentSize = CGSize(width: width, height: verticalGroupOrigin)
|
||||||
@ -6791,6 +6798,9 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
self.scrollView.contentSize = effectiveContentSize
|
self.scrollView.contentSize = effectiveContentSize
|
||||||
}
|
}
|
||||||
var scrollIndicatorInsets = pagerEnvironment.containerInsets
|
var scrollIndicatorInsets = pagerEnvironment.containerInsets
|
||||||
|
if let inputInteraction = component.inputInteractionHolder.inputInteraction, let customLayout = inputInteraction.customLayout, customLayout.topPanelAlwaysHidden {
|
||||||
|
scrollIndicatorInsets.top += 20.0
|
||||||
|
}
|
||||||
if self.warpView != nil {
|
if self.warpView != nil {
|
||||||
scrollIndicatorInsets.bottom += 20.0
|
scrollIndicatorInsets.bottom += 20.0
|
||||||
}
|
}
|
||||||
@ -7175,10 +7185,10 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
return hasPremium
|
return hasPremium
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Subject {
|
public enum Subject: Equatable {
|
||||||
case generic
|
case generic
|
||||||
case status
|
case status
|
||||||
case reaction
|
case reaction(onlyTop: Bool)
|
||||||
case emoji
|
case emoji
|
||||||
case topicIcon
|
case topicIcon
|
||||||
case quickReaction
|
case quickReaction
|
||||||
@ -7216,7 +7226,12 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
|
|
||||||
var orderedItemListCollectionIds: [Int32] = []
|
var orderedItemListCollectionIds: [Int32] = []
|
||||||
|
|
||||||
|
switch subject {
|
||||||
|
case .backgroundIcon, .reactionList:
|
||||||
|
break
|
||||||
|
default:
|
||||||
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.LocalRecentEmoji)
|
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.LocalRecentEmoji)
|
||||||
|
}
|
||||||
|
|
||||||
var iconStatusEmoji: Signal<[TelegramMediaFile], NoError> = .single([])
|
var iconStatusEmoji: Signal<[TelegramMediaFile], NoError> = .single([])
|
||||||
|
|
||||||
@ -7234,7 +7249,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> take(1)
|
|> take(1)
|
||||||
} else if [.reaction, .quickReaction].contains(subject) {
|
} else if [.reaction(onlyTop: false), .quickReaction].contains(subject) {
|
||||||
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudTopReactions)
|
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudTopReactions)
|
||||||
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudRecentReactions)
|
orderedItemListCollectionIds.append(Namespaces.OrderedItemList.CloudRecentReactions)
|
||||||
} else if case .topicIcon = subject {
|
} else if case .topicIcon = subject {
|
||||||
@ -7257,14 +7272,14 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let availableReactions: Signal<AvailableReactions?, NoError>
|
let availableReactions: Signal<AvailableReactions?, NoError>
|
||||||
if [.reaction, .quickReaction, .reactionList].contains(subject) {
|
if [.reaction(onlyTop: false), .quickReaction, .reactionList].contains(subject) {
|
||||||
availableReactions = context.engine.stickers.availableReactions()
|
availableReactions = context.engine.stickers.availableReactions()
|
||||||
} else {
|
} else {
|
||||||
availableReactions = .single(nil)
|
availableReactions = .single(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
let searchCategories: Signal<EmojiSearchCategories?, NoError>
|
let searchCategories: Signal<EmojiSearchCategories?, NoError>
|
||||||
if [.emoji, .reaction, .reactionList].contains(subject) {
|
if [.emoji, .reaction(onlyTop: false), .reactionList].contains(subject) {
|
||||||
searchCategories = context.engine.stickers.emojiSearchCategories(kind: .emoji)
|
searchCategories = context.engine.stickers.emojiSearchCategories(kind: .emoji)
|
||||||
} else if case .status = subject {
|
} else if case .status = subject {
|
||||||
searchCategories = context.engine.stickers.emojiSearchCategories(kind: .status)
|
searchCategories = context.engine.stickers.emojiSearchCategories(kind: .status)
|
||||||
@ -7694,7 +7709,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if [.reaction, .quickReaction].contains(subject) {
|
} else if [.reaction(onlyTop: true), .reaction(onlyTop: false), .quickReaction].contains(subject) {
|
||||||
var existingIds = Set<MessageReaction.Reaction>()
|
var existingIds = Set<MessageReaction.Reaction>()
|
||||||
|
|
||||||
var topReactionItems = topReactionItems
|
var topReactionItems = topReactionItems
|
||||||
@ -7720,7 +7735,9 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let maxTopLineCount: Int
|
let maxTopLineCount: Int
|
||||||
if hasPremium {
|
if case .reaction(onlyTop: true) = subject {
|
||||||
|
maxTopLineCount = 1000
|
||||||
|
} else if hasPremium {
|
||||||
maxTopLineCount = 2
|
maxTopLineCount = 2
|
||||||
} else {
|
} else {
|
||||||
maxTopLineCount = 6
|
maxTopLineCount = 6
|
||||||
@ -7733,7 +7750,9 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
existingIds.insert(reactionItem.reaction)
|
existingIds.insert(reactionItem.reaction)
|
||||||
|
|
||||||
let icon: EmojiPagerContentComponent.Item.Icon
|
let icon: EmojiPagerContentComponent.Item.Icon
|
||||||
if !hasPremium, case .custom = reactionItem.reaction {
|
if case .reaction(onlyTop: true) = subject {
|
||||||
|
icon = .none
|
||||||
|
} else if !hasPremium, case .custom = reactionItem.reaction {
|
||||||
icon = .locked
|
icon = .locked
|
||||||
} else {
|
} else {
|
||||||
icon = .none
|
icon = .none
|
||||||
@ -7768,6 +7787,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if case .reaction(onlyTop: false) = subject {
|
||||||
var hasRecent = false
|
var hasRecent = false
|
||||||
if let recentReactions = recentReactions, !recentReactions.items.isEmpty {
|
if let recentReactions = recentReactions, !recentReactions.items.isEmpty {
|
||||||
hasRecent = true
|
hasRecent = true
|
||||||
@ -7909,6 +7929,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if [.profilePhoto, .groupPhoto].contains(subject) {
|
} else if [.profilePhoto, .groupPhoto].contains(subject) {
|
||||||
var existingIds = Set<MediaId>()
|
var existingIds = Set<MediaId>()
|
||||||
|
|
||||||
@ -8042,7 +8063,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let hasRecentEmoji = ![.reaction, .quickReaction, .status, .profilePhoto, .groupPhoto, .topicIcon, .backgroundIcon].contains(subject)
|
let hasRecentEmoji = ![.reaction(onlyTop: true), .reaction(onlyTop: false), .quickReaction, .status, .profilePhoto, .groupPhoto, .topicIcon, .backgroundIcon, .reactionList].contains(subject)
|
||||||
|
|
||||||
if let recentEmoji = recentEmoji, hasRecentEmoji {
|
if let recentEmoji = recentEmoji, hasRecentEmoji {
|
||||||
for item in recentEmoji.items {
|
for item in recentEmoji.items {
|
||||||
@ -8108,7 +8129,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var icon: EmojiPagerContentComponent.Item.Icon = .none
|
var icon: EmojiPagerContentComponent.Item.Icon = .none
|
||||||
if [.reaction, .quickReaction].contains(subject), !hasPremium {
|
if [.reaction(onlyTop: false), .quickReaction].contains(subject), !hasPremium {
|
||||||
icon = .locked
|
icon = .locked
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8285,7 +8306,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
var displaySearchWithPlaceholder: String?
|
var displaySearchWithPlaceholder: String?
|
||||||
let searchInitiallyHidden = true
|
let searchInitiallyHidden = true
|
||||||
if hasSearch {
|
if hasSearch {
|
||||||
if [.reaction, .quickReaction].contains(subject) {
|
if [.reaction(onlyTop: false), .quickReaction].contains(subject) {
|
||||||
displaySearchWithPlaceholder = strings.EmojiSearch_SearchReactionsPlaceholder
|
displaySearchWithPlaceholder = strings.EmojiSearch_SearchReactionsPlaceholder
|
||||||
} else if case .status = subject {
|
} else if case .status = subject {
|
||||||
displaySearchWithPlaceholder = strings.EmojiSearch_SearchStatusesPlaceholder
|
displaySearchWithPlaceholder = strings.EmojiSearch_SearchStatusesPlaceholder
|
||||||
@ -8340,8 +8361,8 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let warpContentsOnEdges = [.reaction, .quickReaction, .status, .profilePhoto, .groupPhoto, .backgroundIcon].contains(subject)
|
let warpContentsOnEdges = [.reaction(onlyTop: true), .reaction(onlyTop: false), .quickReaction, .status, .profilePhoto, .groupPhoto, .backgroundIcon].contains(subject)
|
||||||
let enableLongPress = [.reaction, .status].contains(subject)
|
let enableLongPress = [.reaction(onlyTop: true), .reaction(onlyTop: false), .status].contains(subject)
|
||||||
|
|
||||||
return EmojiPagerContentComponent(
|
return EmojiPagerContentComponent(
|
||||||
id: "emoji",
|
id: "emoji",
|
||||||
|
@ -225,7 +225,7 @@ public final class EmojiSelectionComponent: Component {
|
|||||||
component: AnyComponent(EntityKeyboardComponent(
|
component: AnyComponent(EntityKeyboardComponent(
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
strings: component.strings,
|
strings: component.strings,
|
||||||
isContentInFocus: false,
|
isContentInFocus: true,
|
||||||
containerInsets: UIEdgeInsets(top: topPanelHeight - 34.0, left: component.sideInset, bottom: component.bottomInset + 16.0, right: component.sideInset),
|
containerInsets: UIEdgeInsets(top: topPanelHeight - 34.0, left: component.sideInset, bottom: component.bottomInset + 16.0, right: component.sideInset),
|
||||||
topPanelInsets: UIEdgeInsets(top: 0.0, left: 4.0, bottom: 0.0, right: 4.0),
|
topPanelInsets: UIEdgeInsets(top: 0.0, left: 4.0, bottom: 0.0, right: 4.0),
|
||||||
emojiContent: component.emojiContent.withCustomTintColor(component.theme.list.itemPrimaryTextColor),
|
emojiContent: component.emojiContent.withCustomTintColor(component.theme.list.itemPrimaryTextColor),
|
||||||
|
@ -274,7 +274,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if let boostStatus = self.boostStatus, !customReactions.isEmpty, customReactions.count > boostStatus.level {
|
if let boostStatus = self.boostStatus, !customReactions.isEmpty, customReactions.count > boostStatus.level {
|
||||||
self.displayPremiumScreen()
|
self.displayPremiumScreen(reactionCount: customReactions.count)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
|
|||||||
if !standalone {
|
if !standalone {
|
||||||
switch error {
|
switch error {
|
||||||
case .boostRequired:
|
case .boostRequired:
|
||||||
self.displayPremiumScreen()
|
self.displayPremiumScreen(reactionCount: customReactions.count)
|
||||||
case .generic:
|
case .generic:
|
||||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
@ -330,7 +330,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func displayPremiumScreen() {
|
private func displayPremiumScreen(reactionCount: Int) {
|
||||||
guard let component = self.component else {
|
guard let component = self.component else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -344,7 +344,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
|
|||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
let link = status.url
|
let link = status.url
|
||||||
let controller = PremiumLimitScreen(context: component.context, subject: .storiesChannelBoost(peer: peer, boostSubject: .channelReactions, isCurrent: true, level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), link: link, myBoostCount: 0, canBoostAgain: false), count: Int32(status.boosts), action: { [weak self] in
|
let controller = PremiumLimitScreen(context: component.context, subject: .storiesChannelBoost(peer: peer, boostSubject: .channelReactions(reactionCount: reactionCount), isCurrent: true, level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), link: link, myBoostCount: 0, canBoostAgain: false), count: Int32(status.boosts), action: { [weak self] in
|
||||||
guard let self, let component = self.component else {
|
guard let self, let component = self.component else {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -4271,6 +4271,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
items: reactionItems.map(ReactionContextItem.reaction),
|
items: reactionItems.map(ReactionContextItem.reaction),
|
||||||
selectedItems: component.slice.item.storyItem.myReaction.flatMap { Set([$0]) } ?? Set(),
|
selectedItems: component.slice.item.storyItem.myReaction.flatMap { Set([$0]) } ?? Set(),
|
||||||
title: self.displayLikeReactions ? nil : component.strings.Story_SendReactionAsMessage,
|
title: self.displayLikeReactions ? nil : component.strings.Story_SendReactionAsMessage,
|
||||||
|
alwaysAllowPremiumReactions: false,
|
||||||
getEmojiContent: { [weak self] animationCache, animationRenderer in
|
getEmojiContent: { [weak self] animationCache, animationRenderer in
|
||||||
guard let self, let component = self.component else {
|
guard let self, let component = self.component else {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
@ -4285,7 +4286,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
animationCache: animationCache,
|
animationCache: animationCache,
|
||||||
animationRenderer: animationRenderer,
|
animationRenderer: animationRenderer,
|
||||||
isStandalone: false,
|
isStandalone: false,
|
||||||
subject: .reaction,
|
subject: .reaction(onlyTop: false),
|
||||||
hasTrending: false,
|
hasTrending: false,
|
||||||
topReactionItems: mappedReactionItems,
|
topReactionItems: mappedReactionItems,
|
||||||
areUnicodeEmojiEnabled: false,
|
areUnicodeEmojiEnabled: false,
|
||||||
|
@ -112,6 +112,10 @@ extension ChatControllerImpl {
|
|||||||
actions.reactionItems = topReactions.map(ReactionContextItem.reaction)
|
actions.reactionItems = topReactions.map(ReactionContextItem.reaction)
|
||||||
actions.selectedReactionItems = selectedReactions.reactions
|
actions.selectedReactionItems = selectedReactions.reactions
|
||||||
|
|
||||||
|
if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = channel.info {
|
||||||
|
actions.alwaysAllowPremiumReactions = true
|
||||||
|
}
|
||||||
|
|
||||||
if !actions.reactionItems.isEmpty {
|
if !actions.reactionItems.isEmpty {
|
||||||
let reactionItems: [EmojiComponentReactionItem] = actions.reactionItems.compactMap { item -> EmojiComponentReactionItem? in
|
let reactionItems: [EmojiComponentReactionItem] = actions.reactionItems.compactMap { item -> EmojiComponentReactionItem? in
|
||||||
switch item {
|
switch item {
|
||||||
@ -150,7 +154,7 @@ extension ChatControllerImpl {
|
|||||||
animationCache: animationCache,
|
animationCache: animationCache,
|
||||||
animationRenderer: animationRenderer,
|
animationRenderer: animationRenderer,
|
||||||
isStandalone: false,
|
isStandalone: false,
|
||||||
subject: .reaction,
|
subject: .reaction(onlyTop: false),
|
||||||
hasTrending: false,
|
hasTrending: false,
|
||||||
topReactionItems: reactionItems,
|
topReactionItems: reactionItems,
|
||||||
areUnicodeEmojiEnabled: false,
|
areUnicodeEmojiEnabled: false,
|
||||||
@ -159,6 +163,26 @@ extension ChatControllerImpl {
|
|||||||
selectedItems: selectedReactions.files
|
selectedItems: selectedReactions.files
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else if reactionItems.count > 10 {
|
||||||
|
actions.getEmojiContent = { [weak self] animationCache, animationRenderer in
|
||||||
|
guard let self else {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
|
||||||
|
return EmojiPagerContentComponent.emojiInputData(
|
||||||
|
context: self.context,
|
||||||
|
animationCache: animationCache,
|
||||||
|
animationRenderer: animationRenderer,
|
||||||
|
isStandalone: false,
|
||||||
|
subject: .reaction(onlyTop: true),
|
||||||
|
hasTrending: false,
|
||||||
|
topReactionItems: reactionItems,
|
||||||
|
areUnicodeEmojiEnabled: false,
|
||||||
|
areCustomEmojiEnabled: false,
|
||||||
|
chatPeerId: self.chatLocation.peerId,
|
||||||
|
selectedItems: selectedReactions.files
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,11 +356,14 @@ extension ChatControllerImpl {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
if removedReaction == nil, case .custom = chosenReaction {
|
if removedReaction == nil, case .custom = chosenReaction {
|
||||||
|
if let peer = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
} else {
|
||||||
if !self.presentationInterfaceState.isPremium {
|
if !self.presentationInterfaceState.isPremium {
|
||||||
controller?.premiumReactionsSelected?()
|
controller?.premiumReactionsSelected?()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item {
|
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user