UI improvements

This commit is contained in:
Ali 2023-03-02 16:24:52 +04:00
parent f173aaa5e5
commit 04d97739cd
14 changed files with 138 additions and 77 deletions

View File

@ -3371,9 +3371,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
strongSelf.updateLayout(size: CGSize(width: layout.contentSize.width, height: itemHeight), leftInset: params.leftInset, rightInset: params.rightInset) strongSelf.updateLayout(size: CGSize(width: layout.contentSize.width, height: itemHeight), leftInset: params.leftInset, rightInset: params.rightInset)
if item.editing { if item.editing {
strongSelf.setRevealOptions((left: [], right: [])) strongSelf.setRevealOptions((left: [], right: []), enableAnimations: item.context.sharedContext.energyUsageSettings.fullTranslucency)
} else { } else {
strongSelf.setRevealOptions((left: peerLeftRevealOptions, right: peerRevealOptions)) strongSelf.setRevealOptions((left: peerLeftRevealOptions, right: peerRevealOptions), enableAnimations: item.context.sharedContext.energyUsageSettings.fullTranslucency)
} }
if !strongSelf.customAnimationInProgress { if !strongSelf.customAnimationInProgress {
strongSelf.setRevealOptionsOpened(item.hasActiveRevealControls, animated: true) strongSelf.setRevealOptionsOpened(item.hasActiveRevealControls, animated: true)

View File

@ -86,9 +86,9 @@ public final class TrendingPanePackEntry: Identifiable, Comparable {
return lhs.index < rhs.index return lhs.index < rhs.index
} }
public func item(account: Account, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem { public func item(context: AccountContext, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem {
let info = self.info let info = self.info
return StickerPaneSearchGlobalItem(account: account, theme: self.theme, strings: self.strings, listAppearance: false, info: self.info, topItems: self.topItems, topSeparator: self.topSeparator, regularInsets: false, installed: self.installed, unread: self.unread, open: { return StickerPaneSearchGlobalItem(context: context, theme: self.theme, strings: self.strings, listAppearance: false, info: self.info, topItems: self.topItems, topSeparator: self.topSeparator, regularInsets: false, installed: self.installed, unread: self.unread, open: {
interaction.openPack(info) interaction.openPack(info)
}, install: { }, install: {
interaction.installPack(info) interaction.installPack(info)
@ -147,14 +147,14 @@ private enum TrendingPaneEntry: Identifiable, Comparable {
} }
} }
func item(account: Account, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem { func item(context: AccountContext, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem {
switch self { switch self {
case let .search(theme, strings): case let .search(theme, strings):
return PaneSearchBarPlaceholderItem(theme: theme, strings: strings, type: .stickers, activate: { return PaneSearchBarPlaceholderItem(theme: theme, strings: strings, type: .stickers, activate: {
interaction.openSearch() interaction.openSearch()
}) })
case let .pack(pack): case let .pack(pack):
return pack.item(account: account, interaction: interaction, grid: grid) return pack.item(context: context, interaction: interaction, grid: grid)
} }
} }
} }
@ -166,12 +166,12 @@ private struct TrendingPaneTransition {
let initial: Bool let initial: Bool
} }
private func preparedTransition(from fromEntries: [TrendingPaneEntry], to toEntries: [TrendingPaneEntry], account: Account, interaction: TrendingPaneInteraction, initial: Bool) -> TrendingPaneTransition { private func preparedTransition(from fromEntries: [TrendingPaneEntry], to toEntries: [TrendingPaneEntry], context: AccountContext, interaction: TrendingPaneInteraction, initial: Bool) -> TrendingPaneTransition {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices let deletions = deleteIndices
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, interaction: interaction, grid: false), previousIndex: $0.2) } let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interaction: interaction, grid: false), previousIndex: $0.2) }
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction, grid: false)) } let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, interaction: interaction, grid: false)) }
return TrendingPaneTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial) return TrendingPaneTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial)
} }
@ -356,7 +356,7 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
let entries = trendingPaneEntries(trendingEntries: trendingEntries, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings, isPane: isPane) let entries = trendingPaneEntries(trendingEntries: trendingEntries, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings, isPane: isPane)
let previous = previousEntries.swap(entries) let previous = previousEntries.swap(entries)
return preparedTransition(from: previous ?? [], to: entries, account: context.account, interaction: interaction, initial: previous == nil) return preparedTransition(from: previous ?? [], to: entries, context: context, interaction: interaction, initial: previous == nil)
} }
|> deliverOnMainQueue).start(next: { [weak self] transition in |> deliverOnMainQueue).start(next: { [weak self] transition in
guard let strongSelf = self else { guard let strongSelf = self else {

View File

@ -96,9 +96,9 @@ private final class FeaturedPackEntry: Identifiable, Comparable {
return lhs.index < rhs.index return lhs.index < rhs.index
} }
func item(account: Account, interaction: FeaturedInteraction, isOther: Bool) -> GridItem { func item(context: AccountContext, interaction: FeaturedInteraction, isOther: Bool) -> GridItem {
let info = self.info let info = self.info
return StickerPaneSearchGlobalItem(account: account, theme: self.theme, strings: self.strings, listAppearance: true, fillsRow: false, info: self.info, topItems: self.topItems, topSeparator: self.topSeparator, regularInsets: self.regularInsets, installed: self.installed, unread: self.unread, open: { return StickerPaneSearchGlobalItem(context: context, theme: self.theme, strings: self.strings, listAppearance: true, fillsRow: false, info: self.info, topItems: self.topItems, topSeparator: self.topSeparator, regularInsets: self.regularInsets, installed: self.installed, unread: self.unread, open: {
interaction.openPack(info) interaction.openPack(info)
}, install: { }, install: {
interaction.installPack(info, !self.installed) interaction.installPack(info, !self.installed)
@ -143,10 +143,10 @@ private enum FeaturedEntry: Identifiable, Comparable {
} }
} }
func item(account: Account, interaction: FeaturedInteraction) -> GridItem { func item(context: AccountContext, interaction: FeaturedInteraction) -> GridItem {
switch self { switch self {
case let .pack(pack, isOther): case let .pack(pack, isOther):
return pack.item(account: account, interaction: interaction, isOther: isOther) return pack.item(context: context, interaction: interaction, isOther: isOther)
} }
} }
} }
@ -159,12 +159,12 @@ private struct FeaturedTransition {
let scrollToItem: GridNodeScrollToItem? let scrollToItem: GridNodeScrollToItem?
} }
private func preparedTransition(from fromEntries: [FeaturedEntry], to toEntries: [FeaturedEntry], account: Account, interaction: FeaturedInteraction, initial: Bool, scrollToItem: GridNodeScrollToItem?) -> FeaturedTransition { private func preparedTransition(from fromEntries: [FeaturedEntry], to toEntries: [FeaturedEntry], context: AccountContext, interaction: FeaturedInteraction, initial: Bool, scrollToItem: GridNodeScrollToItem?) -> FeaturedTransition {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices let deletions = deleteIndices
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, interaction: interaction), previousIndex: $0.2) } let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interaction: interaction), previousIndex: $0.2) }
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction)) } let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, interaction: interaction)) }
return FeaturedTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial, scrollToItem: scrollToItem) return FeaturedTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial, scrollToItem: scrollToItem)
} }
@ -401,7 +401,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
} }
} }
return preparedTransition(from: previous ?? [], to: entries, account: context.account, interaction: interaction, initial: initial, scrollToItem: scrollToItem) return preparedTransition(from: previous ?? [], to: entries, context: context, interaction: interaction, initial: initial, scrollToItem: scrollToItem)
} }
|> deliverOnMainQueue).start(next: { [weak self] transition in |> deliverOnMainQueue).start(next: { [weak self] transition in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -1034,14 +1034,14 @@ private enum FeaturedSearchEntry: Identifiable, Comparable {
} }
} }
func item(account: Account, theme: PresentationTheme, strings: PresentationStrings, interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction, itemContext: StickerPaneSearchGlobalItemContext) -> GridItem { func item(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction, itemContext: StickerPaneSearchGlobalItemContext) -> GridItem {
switch self { switch self {
case let .sticker(_, code, stickerItem, theme): case let .sticker(_, code, stickerItem, theme):
return StickerPaneSearchStickerItem(account: account, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in return StickerPaneSearchStickerItem(context: context, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in
interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect) interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect)
}) })
case let .global(_, info, topItems, installed, topSeparator): case let .global(_, info, topItems, installed, topSeparator):
return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, listAppearance: true, fillsRow: true, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: { return StickerPaneSearchGlobalItem(context: context, theme: theme, strings: strings, listAppearance: true, fillsRow: true, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
interaction.open(info) interaction.open(info)
}, install: { }, install: {
interaction.install(info, topItems, !installed) interaction.install(info, topItems, !installed)
@ -1062,7 +1062,7 @@ private struct FeaturedSearchGridTransition {
let animated: Bool let animated: Bool
} }
private func preparedFeaturedSearchEntryTransition(account: Account, theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [FeaturedSearchEntry], to toEntries: [FeaturedSearchEntry], interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction, itemContext: StickerPaneSearchGlobalItemContext) -> FeaturedSearchGridTransition { private func preparedFeaturedSearchEntryTransition(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [FeaturedSearchEntry], to toEntries: [FeaturedSearchEntry], interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction, itemContext: StickerPaneSearchGlobalItemContext) -> FeaturedSearchGridTransition {
let stationaryItems: GridNodeStationaryItems = .none let stationaryItems: GridNodeStationaryItems = .none
let scrollToItem: GridNodeScrollToItem? = nil let scrollToItem: GridNodeScrollToItem? = nil
var animated = false var animated = false
@ -1071,8 +1071,8 @@ private func preparedFeaturedSearchEntryTransition(account: Account, theme: Pres
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices let deletions = deleteIndices
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction, itemContext: itemContext), previousIndex: $0.2) } let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction, itemContext: itemContext), previousIndex: $0.2) }
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction, itemContext: itemContext)) } let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction, itemContext: itemContext)) }
let firstIndexInSectionOffset = 0 let firstIndexInSectionOffset = 0
@ -1375,7 +1375,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode {
} }
let previousEntries = strongSelf.currentEntries.swap(entries) let previousEntries = strongSelf.currentEntries.swap(entries)
let transition = preparedFeaturedSearchEntryTransition(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, from: previousEntries ?? [], to: entries, interaction: interaction, inputNodeInteraction: strongSelf.inputNodeInteraction, itemContext: strongSelf.itemContext) let transition = preparedFeaturedSearchEntryTransition(context: strongSelf.context, theme: strongSelf.theme, strings: strongSelf.strings, from: previousEntries ?? [], to: entries, interaction: interaction, inputNodeInteraction: strongSelf.inputNodeInteraction, itemContext: strongSelf.itemContext)
strongSelf.enqueueTransition(transition) strongSelf.enqueueTransition(transition)
if displayResults { if displayResults {

View File

@ -8,6 +8,7 @@ import Postbox
import TelegramPresentationData import TelegramPresentationData
import StickerPackPreviewUI import StickerPackPreviewUI
import ListSectionHeaderNode import ListSectionHeaderNode
import AccountContext
final class StickerPaneSearchGlobalSection: GridSection { final class StickerPaneSearchGlobalSection: GridSection {
let title: String? let title: String?
@ -78,7 +79,7 @@ public final class StickerPaneSearchGlobalItemContext {
} }
public final class StickerPaneSearchGlobalItem: GridItem { public final class StickerPaneSearchGlobalItem: GridItem {
public let account: Account public let context: AccountContext
public let theme: PresentationTheme public let theme: PresentationTheme
public let strings: PresentationStrings public let strings: PresentationStrings
public let listAppearance: Bool public let listAppearance: Bool
@ -110,8 +111,8 @@ public final class StickerPaneSearchGlobalItem: GridItem {
return (128.0 + additionalHeight, self.fillsRow) return (128.0 + additionalHeight, self.fillsRow)
} }
public init(account: Account, theme: PresentationTheme, strings: PresentationStrings, listAppearance: Bool, fillsRow: Bool = true, info: StickerPackCollectionInfo, topItems: [StickerPackItem], topSeparator: Bool, regularInsets: Bool, installed: Bool, installing: Bool = false, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, itemContext: StickerPaneSearchGlobalItemContext, sectionTitle: String? = nil) { public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, listAppearance: Bool, fillsRow: Bool = true, info: StickerPackCollectionInfo, topItems: [StickerPackItem], topSeparator: Bool, regularInsets: Bool, installed: Bool, installing: Bool = false, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, itemContext: StickerPaneSearchGlobalItemContext, sectionTitle: String? = nil) {
self.account = account self.context = context
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.listAppearance = listAppearance self.listAppearance = listAppearance
@ -199,7 +200,7 @@ public class StickerPaneSearchGlobalItemNode: GridItemNode {
if let item = self.item, self.isVisibleInGrid, !self.preloadedThumbnail { if let item = self.item, self.isVisibleInGrid, !self.preloadedThumbnail {
self.preloadedThumbnail = true self.preloadedThumbnail = true
self.preloadedStickerPackThumbnailDisposable.set(preloadedStickerPackThumbnail(account: item.account, info: item.info, items: item.topItems).start()) self.preloadedStickerPackThumbnailDisposable.set(preloadedStickerPackThumbnail(account: item.context.account, info: item.info, items: item.topItems).start())
} }
} }
} }
@ -320,7 +321,7 @@ public class StickerPaneSearchGlobalItemNode: GridItemNode {
public func setup(item: StickerPaneSearchGlobalItem) { public func setup(item: StickerPaneSearchGlobalItem) {
if item.topItems.count < Int(item.info.count) && item.topItems.count < 5 && self.item?.info.id != item.info.id { if item.topItems.count < Int(item.info.count) && item.topItems.count < 5 && self.item?.info.id != item.info.id {
self.preloadDisposable.set(preloadedFeaturedStickerSet(network: item.account.network, postbox: item.account.postbox, id: item.info.id).start()) self.preloadDisposable.set(preloadedFeaturedStickerSet(network: item.context.account.network, postbox: item.context.account.postbox, id: item.info.id).start())
} }
self.item = item self.item = item
@ -334,7 +335,7 @@ public class StickerPaneSearchGlobalItemNode: GridItemNode {
return return
} }
self.canPlayMedia = item.itemContext.canPlayMedia self.canPlayMedia = item.itemContext.canPlayMedia && item.context.sharedContext.energyUsageSettings.loopStickers
} }
public func highlight() { public func highlight() {
@ -486,7 +487,7 @@ public class StickerPaneSearchGlobalItemNode: GridItemNode {
strongSelf.addSubnode(node) strongSelf.addSubnode(node)
} }
if file.fileId != node.file?.fileId { if file.fileId != node.file?.fileId {
node.setup(account: item.account, item: topItems[i], itemSize: itemSize, synchronousLoads: synchronousLoads) node.setup(account: item.context.account, item: topItems[i], itemSize: itemSize, synchronousLoads: synchronousLoads)
} }
if item.theme !== node.theme { if item.theme !== node.theme {
node.update(theme: item.theme, listAppearance: item.listAppearance) node.update(theme: item.theme, listAppearance: item.listAppearance)
@ -508,7 +509,7 @@ public class StickerPaneSearchGlobalItemNode: GridItemNode {
} }
} }
self.canPlayMedia = item.itemContext.canPlayMedia self.canPlayMedia = item.itemContext.canPlayMedia && item.context.sharedContext.energyUsageSettings.loopStickers
} }
@objc func installPressed() { @objc func installPressed() {

View File

@ -67,7 +67,7 @@ final class StickerPaneSearchStickerSectionNode: ASDisplayNode {
} }
public final class StickerPaneSearchStickerItem: GridItem { public final class StickerPaneSearchStickerItem: GridItem {
public let account: Account public let context: AccountContext
public let code: String? public let code: String?
public let stickerItem: FoundStickerItem public let stickerItem: FoundStickerItem
public let selected: (ASDisplayNode, CGRect) -> Void public let selected: (ASDisplayNode, CGRect) -> Void
@ -75,8 +75,8 @@ public final class StickerPaneSearchStickerItem: GridItem {
public let section: GridSection? public let section: GridSection?
public init(account: Account, code: String?, stickerItem: FoundStickerItem, inputNodeInteraction: ChatMediaInputNodeInteraction, theme: PresentationTheme, selected: @escaping (ASDisplayNode, CGRect) -> Void) { public init(context: AccountContext, code: String?, stickerItem: FoundStickerItem, inputNodeInteraction: ChatMediaInputNodeInteraction, theme: PresentationTheme, selected: @escaping (ASDisplayNode, CGRect) -> Void) {
self.account = account self.context = context
self.stickerItem = stickerItem self.stickerItem = stickerItem
self.inputNodeInteraction = inputNodeInteraction self.inputNodeInteraction = inputNodeInteraction
self.selected = selected self.selected = selected
@ -87,7 +87,7 @@ public final class StickerPaneSearchStickerItem: GridItem {
public func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode { public func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
let node = StickerPaneSearchStickerItemNode() let node = StickerPaneSearchStickerItemNode()
node.inputNodeInteraction = self.inputNodeInteraction node.inputNodeInteraction = self.inputNodeInteraction
node.setup(account: self.account, stickerItem: self.stickerItem, code: self.code) node.setup(context: self.context, stickerItem: self.stickerItem, code: self.code)
node.selected = self.selected node.selected = self.selected
return node return node
} }
@ -98,7 +98,7 @@ public final class StickerPaneSearchStickerItem: GridItem {
return return
} }
node.inputNodeInteraction = self.inputNodeInteraction node.inputNodeInteraction = self.inputNodeInteraction
node.setup(account: self.account, stickerItem: self.stickerItem, code: self.code) node.setup(context: self.context, stickerItem: self.stickerItem, code: self.code)
node.selected = self.selected node.selected = self.selected
} }
} }
@ -106,7 +106,7 @@ public final class StickerPaneSearchStickerItem: GridItem {
private let textFont = Font.regular(20.0) private let textFont = Font.regular(20.0)
public final class StickerPaneSearchStickerItemNode: GridItemNode { public final class StickerPaneSearchStickerItemNode: GridItemNode {
private var currentState: (Account, FoundStickerItem, CGSize)? private var currentState: (AccountContext, FoundStickerItem, CGSize)?
public let imageNode: TransformImageNode public let imageNode: TransformImageNode
public private(set) var animationNode: AnimatedStickerNode? public private(set) var animationNode: AnimatedStickerNode?
private let textNode: ASTextNode private let textNode: ASTextNode
@ -152,8 +152,8 @@ public final class StickerPaneSearchStickerItemNode: GridItemNode {
self.imageNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:)))) self.imageNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
} }
func setup(account: Account, stickerItem: FoundStickerItem, code: String?) { func setup(context: AccountContext, stickerItem: FoundStickerItem, code: String?) {
if self.currentState == nil || self.currentState!.0 !== account || self.currentState!.1 != stickerItem { if self.currentState == nil || self.currentState!.0 !== context || self.currentState!.1 != stickerItem {
self.textNode.attributedText = NSAttributedString(string: code ?? "", font: textFont, textColor: .black) self.textNode.attributedText = NSAttributedString(string: code ?? "", font: textFont, textColor: .black)
if let dimensions = stickerItem.file.dimensions { if let dimensions = stickerItem.file.dimensions {
@ -166,20 +166,20 @@ public final class StickerPaneSearchStickerItemNode: GridItemNode {
} }
let dimensions = stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512) let dimensions = stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512)
let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)) let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0))
self.animationNode?.setup(source: AnimatedStickerResourceSource(account: account, resource: stickerItem.file.resource, isVideo: stickerItem.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .cached) self.animationNode?.setup(source: AnimatedStickerResourceSource(account: context.account, resource: stickerItem.file.resource, isVideo: stickerItem.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .cached)
self.animationNode?.visibility = self.isVisibleInGrid self.animationNode?.visibility = self.isVisibleInGrid && context.sharedContext.energyUsageSettings.loopStickers
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start()) self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start())
} else { } else {
if let animationNode = self.animationNode { if let animationNode = self.animationNode {
animationNode.visibility = false animationNode.visibility = false
self.animationNode = nil self.animationNode = nil
animationNode.removeFromSupernode() animationNode.removeFromSupernode()
} }
self.imageNode.setSignal(chatMessageSticker(account: account, userLocation: .other, file: stickerItem.file, small: true)) self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItem.file, small: true))
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: chatMessageStickerResource(file: stickerItem.file, small: true)).start()) self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: chatMessageStickerResource(file: stickerItem.file, small: true)).start())
} }
self.currentState = (account, stickerItem, dimensions.cgSize) self.currentState = (context, stickerItem, dimensions.cgSize)
self.setNeedsLayout() self.setNeedsLayout()
} }
} }
@ -217,7 +217,11 @@ public final class StickerPaneSearchStickerItemNode: GridItemNode {
} }
public func updateVisibility() { public func updateVisibility() {
let isPlaying = self.isVisibleInGrid guard let context = self.currentState?.0 else {
return
}
let isPlaying = self.isVisibleInGrid && context.sharedContext.energyUsageSettings.loopStickers
if self.isPlaying != isPlaying { if self.isPlaying != isPlaying {
self.isPlaying = isPlaying self.isPlaying = isPlaying
self.animationNode?.visibility = isPlaying self.animationNode?.visibility = isPlaying

View File

@ -83,19 +83,23 @@ private final class ItemListRevealOptionNode: ASDisplayNode {
private let iconNode: ASImageNode? private let iconNode: ASImageNode?
private let animationNode: SimpleAnimationNode? private let animationNode: SimpleAnimationNode?
private let enableAnimations: Bool
private var animationScale: CGFloat = 1.0 private var animationScale: CGFloat = 1.0
private var animationNodeOffset: CGFloat = 0.0 private var animationNodeOffset: CGFloat = 0.0
private var animationNodeFlip = false private var animationNodeFlip = false
var alignment: ItemListRevealOptionAlignment? var alignment: ItemListRevealOptionAlignment?
var isExpanded: Bool = false var isExpanded: Bool = false
init(title: String, icon: ItemListRevealOptionIcon, color: UIColor, textColor: UIColor) { init(title: String, icon: ItemListRevealOptionIcon, color: UIColor, textColor: UIColor, enableAnimations: Bool) {
self.backgroundNode = ASDisplayNode() self.backgroundNode = ASDisplayNode()
self.highlightNode = ASDisplayNode() self.highlightNode = ASDisplayNode()
self.titleNode = ASTextNode() self.titleNode = ASTextNode()
self.titleNode.attributedText = NSAttributedString(string: title, font: icon == .none ? titleFontWithoutIcon : titleFontWithIcon, textColor: textColor) self.titleNode.attributedText = NSAttributedString(string: title, font: icon == .none ? titleFontWithoutIcon : titleFontWithIcon, textColor: textColor)
self.enableAnimations = enableAnimations
switch icon { switch icon {
case let .image(image): case let .image(image):
let iconNode = ASImageNode() let iconNode = ASImageNode()
@ -113,6 +117,9 @@ private final class ItemListRevealOptionNode: ASDisplayNode {
} }
} }
self.animationNode = SimpleAnimationNode(animationName: animation, replaceColors: colors, size: CGSize(width: 79.0, height: 79.0), playOnce: true) self.animationNode = SimpleAnimationNode(animationName: animation, replaceColors: colors, size: CGSize(width: 79.0, height: 79.0), playOnce: true)
if !enableAnimations {
self.animationNode!.seekToEnd()
}
if flip { if flip {
self.animationNode!.transform = CATransform3DMakeScale(1.0, -1.0, 1.0) self.animationNode!.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
} }
@ -217,10 +224,12 @@ private final class ItemListRevealOptionNode: ASDisplayNode {
transition.updateFrame(node: self.titleNode, frame: titleFrame) transition.updateFrame(node: self.titleNode, frame: titleFrame)
} }
if (abs(revealFactor) >= 0.4) { if self.enableAnimations {
animationNode.play() if (abs(revealFactor) >= 0.4) {
} else if abs(revealFactor) < CGFloat.ulpOfOne && !transition.isAnimated { animationNode.play()
animationNode.reset() } else if abs(revealFactor) < CGFloat.ulpOfOne && !transition.isAnimated {
animationNode.reset()
}
} }
} else if let iconNode = self.iconNode, let imageSize = iconNode.image?.size { } else if let iconNode = self.iconNode, let imageSize = iconNode.image?.size {
let iconOffset: CGFloat = -9.0 let iconOffset: CGFloat = -9.0
@ -303,7 +312,7 @@ public final class ItemListRevealOptionsNode: ASDisplayNode {
self.view.addGestureRecognizer(gestureRecognizer) self.view.addGestureRecognizer(gestureRecognizer)
} }
public func setOptions(_ options: [ItemListRevealOption], isLeft: Bool) { public func setOptions(_ options: [ItemListRevealOption], isLeft: Bool, enableAnimations: Bool) {
if self.options != options || self.isLeft != isLeft { if self.options != options || self.isLeft != isLeft {
self.options = options self.options = options
self.isLeft = isLeft self.isLeft = isLeft
@ -311,7 +320,7 @@ public final class ItemListRevealOptionsNode: ASDisplayNode {
node.removeFromSupernode() node.removeFromSupernode()
} }
self.optionNodes = options.map { option in self.optionNodes = options.map { option in
return ItemListRevealOptionNode(title: option.title, icon: option.icon, color: option.color, textColor: option.textColor) return ItemListRevealOptionNode(title: option.title, icon: option.icon, color: option.color, textColor: option.textColor, enableAnimations: enableAnimations)
} }
if isLeft { if isLeft {
for node in self.optionNodes.reversed() { for node in self.optionNodes.reversed() {

View File

@ -64,6 +64,7 @@ open class ItemListRevealOptionsItemNode: ListViewItemNode, UIGestureRecognizerD
private var leftRevealNode: ItemListRevealOptionsNode? private var leftRevealNode: ItemListRevealOptionsNode?
private var rightRevealNode: ItemListRevealOptionsNode? private var rightRevealNode: ItemListRevealOptionsNode?
private var revealOptions: (left: [ItemListRevealOption], right: [ItemListRevealOption]) = ([], []) private var revealOptions: (left: [ItemListRevealOption], right: [ItemListRevealOption]) = ([], [])
private var enableAnimations: Bool = true
private var initialRevealOffset: CGFloat = 0.0 private var initialRevealOffset: CGFloat = 0.0
public private(set) var revealOffset: CGFloat = 0.0 public private(set) var revealOffset: CGFloat = 0.0
@ -117,13 +118,14 @@ open class ItemListRevealOptionsItemNode: ListViewItemNode, UIGestureRecognizerD
} }
} }
open func setRevealOptions(_ options: (left: [ItemListRevealOption], right: [ItemListRevealOption])) { open func setRevealOptions(_ options: (left: [ItemListRevealOption], right: [ItemListRevealOption]), enableAnimations: Bool = true) {
if self.revealOptions == options { if self.revealOptions == options {
return return
} }
let previousOptions = self.revealOptions let previousOptions = self.revealOptions
let wasEmpty = self.revealOptions.left.isEmpty && self.revealOptions.right.isEmpty let wasEmpty = self.revealOptions.left.isEmpty && self.revealOptions.right.isEmpty
self.revealOptions = options self.revealOptions = options
self.enableAnimations = enableAnimations
let isEmpty = options.left.isEmpty && options.right.isEmpty let isEmpty = options.left.isEmpty && options.right.isEmpty
if options.left.isEmpty { if options.left.isEmpty {
if let _ = self.leftRevealNode { if let _ = self.leftRevealNode {
@ -329,7 +331,7 @@ open class ItemListRevealOptionsItemNode: ListViewItemNode, UIGestureRecognizerD
}, tapticAction: { [weak self] in }, tapticAction: { [weak self] in
self?.hapticImpact() self?.hapticImpact()
}) })
revealNode.setOptions(self.revealOptions.left, isLeft: true) revealNode.setOptions(self.revealOptions.left, isLeft: true, enableAnimations: self.enableAnimations)
self.leftRevealNode = revealNode self.leftRevealNode = revealNode
if let (size, leftInset, _) = self.validLayout { if let (size, leftInset, _) = self.validLayout {
@ -351,7 +353,7 @@ open class ItemListRevealOptionsItemNode: ListViewItemNode, UIGestureRecognizerD
}, tapticAction: { [weak self] in }, tapticAction: { [weak self] in
self?.hapticImpact() self?.hapticImpact()
}) })
revealNode.setOptions(self.revealOptions.right, isLeft: false) revealNode.setOptions(self.revealOptions.right, isLeft: false, enableAnimations: self.enableAnimations)
self.rightRevealNode = revealNode self.rightRevealNode = revealNode
if let (size, _, rightInset) = self.validLayout { if let (size, _, rightInset) = self.validLayout {

View File

@ -330,6 +330,7 @@ open class ManagedAnimationNode: ASDisplayNode {
public final class SimpleAnimationNode: ManagedAnimationNode { public final class SimpleAnimationNode: ManagedAnimationNode {
private let stillItem: ManagedAnimationItem private let stillItem: ManagedAnimationItem
private let stillEndItem: ManagedAnimationItem
private let animationItem: ManagedAnimationItem private let animationItem: ManagedAnimationItem
public let size: CGSize public let size: CGSize
@ -340,6 +341,7 @@ public final class SimpleAnimationNode: ManagedAnimationNode {
self.size = size self.size = size
self.playOnce = playOnce self.playOnce = playOnce
self.stillItem = ManagedAnimationItem(source: .local(animationName), replaceColors: replaceColors, frames: .range(startFrame: 0, endFrame: 0), duration: 0.01) self.stillItem = ManagedAnimationItem(source: .local(animationName), replaceColors: replaceColors, frames: .range(startFrame: 0, endFrame: 0), duration: 0.01)
self.stillEndItem = ManagedAnimationItem(source: .local(animationName), replaceColors: replaceColors, frames: .still(.end), duration: 0.01)
self.animationItem = ManagedAnimationItem(source: .local(animationName), replaceColors: replaceColors) self.animationItem = ManagedAnimationItem(source: .local(animationName), replaceColors: replaceColors)
super.init(size: size) super.init(size: size)
@ -358,4 +360,9 @@ public final class SimpleAnimationNode: ManagedAnimationNode {
self.didPlay = false self.didPlay = false
self.trackTo(item: self.stillItem) self.trackTo(item: self.stillItem)
} }
public func seekToEnd() {
self.didPlay = false
self.trackTo(item: self.stillEndItem)
}
} }

View File

@ -39,6 +39,7 @@ public final class PasscodeEntryController: ViewController {
private let applicationBindings: TelegramApplicationBindings private let applicationBindings: TelegramApplicationBindings
private let accountManager: AccountManager<TelegramAccountManagerTypes> private let accountManager: AccountManager<TelegramAccountManagerTypes>
private var energyUsageSettings: EnergyUsageSettings?
private let appLockContext: AppLockContext private let appLockContext: AppLockContext
private let presentationDataSignal: Signal<PresentationData, NoError> private let presentationDataSignal: Signal<PresentationData, NoError>

View File

@ -12,6 +12,7 @@ import AppBundle
import PasscodeInputFieldNode import PasscodeInputFieldNode
import MonotonicTime import MonotonicTime
import GradientBackground import GradientBackground
import TelegramUIPreferences
private extension CGRect { private extension CGRect {
var center: CGPoint { var center: CGPoint {
@ -60,6 +61,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
var checkPasscode: ((String) -> Void)? var checkPasscode: ((String) -> Void)?
var requestBiometrics: (() -> Void)? var requestBiometrics: (() -> Void)?
var energyUsageSettings: EnergyUsageSettings = .default
var energyUsageSettingsDisposable: Disposable?
init(accountManager: AccountManager<TelegramAccountManagerTypes>, presentationData: PresentationData, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, passcodeType: PasscodeEntryFieldType, biometricsType: LocalAuthBiometricAuthentication?, arguments: PasscodeEntryControllerPresentationArguments, modalPresentation: Bool) { init(accountManager: AccountManager<TelegramAccountManagerTypes>, presentationData: PresentationData, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, passcodeType: PasscodeEntryFieldType, biometricsType: LocalAuthBiometricAuthentication?, arguments: PasscodeEntryControllerPresentationArguments, modalPresentation: Bool) {
self.accountManager = accountManager self.accountManager = accountManager
self.presentationData = presentationData self.presentationData = presentationData
@ -105,7 +109,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
if let strongSelf = self { if let strongSelf = self {
strongSelf.inputFieldNode.append(character) strongSelf.inputFieldNode.append(character)
if let gradientNode = strongSelf.backgroundCustomNode as? GradientBackgroundNode { if let gradientNode = strongSelf.backgroundCustomNode as? GradientBackgroundNode {
gradientNode.animateEvent(transition: .animated(duration: 0.55, curve: .spring), extendAnimation: false, backwards: false, completion: {}) if strongSelf.energyUsageSettings.fullTranslucency {
gradientNode.animateEvent(transition: .animated(duration: 0.55, curve: .spring), extendAnimation: false, backwards: false, completion: {})
}
} }
} }
} }
@ -113,7 +119,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
if let strongSelf = self { if let strongSelf = self {
let _ = strongSelf.inputFieldNode.delete() let _ = strongSelf.inputFieldNode.delete()
if let gradientNode = strongSelf.backgroundCustomNode as? GradientBackgroundNode { if let gradientNode = strongSelf.backgroundCustomNode as? GradientBackgroundNode {
gradientNode.animateEvent(transition: .animated(duration: 0.55, curve: .spring), extendAnimation: false, backwards: true, completion: {}) if strongSelf.energyUsageSettings.fullTranslucency {
gradientNode.animateEvent(transition: .animated(duration: 0.55, curve: .spring), extendAnimation: false, backwards: true, completion: {})
}
} }
} }
} }
@ -158,6 +166,24 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
if self.arguments.cancel != nil { if self.arguments.cancel != nil {
self.addSubnode(self.cancelButtonNode) self.addSubnode(self.cancelButtonNode)
} }
self.energyUsageSettingsDisposable = (accountManager.sharedData(keys: Set([ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings]))
|> deliverOnMainQueue).start(next: { [weak self] sharedData in
guard let self else {
return
}
if let mediaAutoDownloadSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings]?.get(MediaAutoDownloadSettings.self) {
if automaticEnergyUsageShouldBeOnNow(settings: mediaAutoDownloadSettings) {
self.energyUsageSettings = EnergyUsageSettings.powerSavingDefault
} else {
self.energyUsageSettings = mediaAutoDownloadSettings.energyUsageSettings
}
}
})
}
deinit {
self.energyUsageSettingsDisposable?.dispose()
} }
override func didLoad() { override func didLoad() {
@ -183,7 +209,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
self.hapticFeedback.tap() self.hapticFeedback.tap()
let result = self.inputFieldNode.delete() let result = self.inputFieldNode.delete()
if result, let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode { if result, let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode {
gradientNode.animateEvent(transition: .animated(duration: 0.55, curve: .spring), extendAnimation: false, backwards: true, completion: {}) if self.energyUsageSettings.fullTranslucency {
gradientNode.animateEvent(transition: .animated(duration: 0.55, curve: .spring), extendAnimation: false, backwards: true, completion: {})
}
} }
} }
@ -359,7 +387,10 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode { if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode {
gradientNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) gradientNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
self.backgroundDimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) self.backgroundDimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
gradientNode.animateEvent(transition: .animated(duration: 1.0, curve: .spring), extendAnimation: true, backwards: false, completion: {})
if self.energyUsageSettings.fullTranslucency {
gradientNode.animateEvent(transition: .animated(duration: 1.0, curve: .spring), extendAnimation: true, backwards: false, completion: {})
}
} }
} }
self.titleNode.setAttributedText(NSAttributedString(string: self.strings.EnterPasscode_EnterPasscode, font: titleFont, textColor: .white), animation: .none) self.titleNode.setAttributedText(NSAttributedString(string: self.strings.EnterPasscode_EnterPasscode, font: titleFont, textColor: .white), animation: .none)
@ -377,9 +408,11 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
} }
}) })
self.backgroundImageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) self.backgroundImageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode { if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode, self.energyUsageSettings.fullTranslucency {
gradientNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) gradientNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
gradientNode.animateEvent(transition: .animated(duration: 0.35, curve: .spring), extendAnimation: false, backwards: false, completion: {}) if self.energyUsageSettings.fullTranslucency {
gradientNode.animateEvent(transition: .animated(duration: 0.35, curve: .spring), extendAnimation: false, backwards: false, completion: {})
}
self.backgroundDimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.backgroundDimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
} }
if !iconFrame.isEmpty { if !iconFrame.isEmpty {
@ -411,7 +444,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
self.subtitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) self.subtitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode { if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode {
gradientNode.animateEvent(transition: .animated(duration: 1.0, curve: .spring), extendAnimation: false, backwards: false, completion: {}) if self.energyUsageSettings.fullTranslucency {
gradientNode.animateEvent(transition: .animated(duration: 1.0, curve: .spring), extendAnimation: false, backwards: false, completion: {})
}
} }
self.inputFieldNode.animateIn() self.inputFieldNode.animateIn()
self.keyboardNode.animateIn() self.keyboardNode.animateIn()
@ -454,7 +489,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
self.hapticFeedback.error() self.hapticFeedback.error()
if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode { if let gradientNode = self.backgroundCustomNode as? GradientBackgroundNode {
gradientNode.animateEvent(transition: .animated(duration: 1.5, curve: .spring), extendAnimation: true, backwards: true, completion: {}) if self.energyUsageSettings.fullTranslucency {
gradientNode.animateEvent(transition: .animated(duration: 1.5, curve: .spring), extendAnimation: true, backwards: true, completion: {})
}
} }
} }

View File

@ -259,7 +259,7 @@ class FormEditableBlockItemNode<Item: FormControllerItem>: ASDisplayNode, FormCo
}, tapticAction: { [weak self] in }, tapticAction: { [weak self] in
self?.hapticImpact() self?.hapticImpact()
}) })
revealNode.setOptions(self.revealOptions.left, isLeft: true) revealNode.setOptions(self.revealOptions.left, isLeft: true, enableAnimations: true)
self.leftRevealNode = revealNode self.leftRevealNode = revealNode
if let (size, leftInset, _) = self.validLayout { if let (size, leftInset, _) = self.validLayout {
@ -281,7 +281,7 @@ class FormEditableBlockItemNode<Item: FormControllerItem>: ASDisplayNode, FormCo
}, tapticAction: { [weak self] in }, tapticAction: { [weak self] in
self?.hapticImpact() self?.hapticImpact()
}) })
revealNode.setOptions(self.revealOptions.right, isLeft: false) revealNode.setOptions(self.revealOptions.right, isLeft: false, enableAnimations: true)
self.rightRevealNode = revealNode self.rightRevealNode = revealNode
if let (size, _, rightInset) = self.validLayout { if let (size, _, rightInset) = self.validLayout {

View File

@ -87,16 +87,16 @@ private enum StickerSearchEntry: Identifiable, Comparable {
} }
} }
func item(account: Account, theme: PresentationTheme, strings: PresentationStrings, interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) -> GridItem { func item(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) -> GridItem {
switch self { switch self {
case let .sticker(_, code, stickerItem, theme): case let .sticker(_, code, stickerItem, theme):
return StickerPaneSearchStickerItem(account: account, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in return StickerPaneSearchStickerItem(context: context, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in
interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect) interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect)
}) })
case let .global(_, info, topItems, installed, topSeparator): case let .global(_, info, topItems, installed, topSeparator):
let itemContext = StickerPaneSearchGlobalItemContext() let itemContext = StickerPaneSearchGlobalItemContext()
itemContext.canPlayMedia = true itemContext.canPlayMedia = true
return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, listAppearance: false, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: { return StickerPaneSearchGlobalItem(context: context, theme: theme, strings: strings, listAppearance: false, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
interaction.open(info) interaction.open(info)
}, install: { }, install: {
interaction.install(info, topItems, !installed) interaction.install(info, topItems, !installed)
@ -117,7 +117,7 @@ private struct StickerPaneSearchGridTransition {
let animated: Bool let animated: Bool
} }
private func preparedChatMediaInputGridEntryTransition(account: Account, theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [StickerSearchEntry], to toEntries: [StickerSearchEntry], interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) -> StickerPaneSearchGridTransition { private func preparedChatMediaInputGridEntryTransition(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [StickerSearchEntry], to toEntries: [StickerSearchEntry], interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) -> StickerPaneSearchGridTransition {
let stationaryItems: GridNodeStationaryItems = .none let stationaryItems: GridNodeStationaryItems = .none
let scrollToItem: GridNodeScrollToItem? = nil let scrollToItem: GridNodeScrollToItem? = nil
var animated = false var animated = false
@ -126,8 +126,8 @@ private func preparedChatMediaInputGridEntryTransition(account: Account, theme:
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices let deletions = deleteIndices
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction), previousIndex: $0.2) } let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction), previousIndex: $0.2) }
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction)) } let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction)) }
let firstIndexInSectionOffset = 0 let firstIndexInSectionOffset = 0
@ -508,7 +508,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
} }
let previousEntries = strongSelf.currentEntries.swap(entries) let previousEntries = strongSelf.currentEntries.swap(entries)
let transition = preparedChatMediaInputGridEntryTransition(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, from: previousEntries ?? [], to: entries, interaction: interaction, inputNodeInteraction: strongSelf.inputNodeInteraction) let transition = preparedChatMediaInputGridEntryTransition(context: strongSelf.context, theme: strongSelf.theme, strings: strongSelf.strings, from: previousEntries ?? [], to: entries, interaction: interaction, inputNodeInteraction: strongSelf.inputNodeInteraction)
strongSelf.enqueueTransition(transition) strongSelf.enqueueTransition(transition)
} }
})) }))

View File

@ -366,7 +366,7 @@ final class HashtagChatInputPanelItemNode: ListViewItemNode {
}, tapticAction: { [weak self] in }, tapticAction: { [weak self] in
self?.hapticImpact() self?.hapticImpact()
}) })
revealNode.setOptions(self.revealOptions, isLeft: false) revealNode.setOptions(self.revealOptions, isLeft: false, enableAnimations: true)
self.revealNode = revealNode self.revealNode = revealNode
if let (size, _, rightInset) = self.validLayout { if let (size, _, rightInset) = self.validLayout {

View File

@ -414,7 +414,7 @@ final class MentionChatInputPanelItemNode: ListViewItemNode {
}, tapticAction: { [weak self] in }, tapticAction: { [weak self] in
self?.hapticImpact() self?.hapticImpact()
}) })
revealNode.setOptions(self.revealOptions, isLeft: false) revealNode.setOptions(self.revealOptions, isLeft: false, enableAnimations: true)
self.revealNode = revealNode self.revealNode = revealNode
if let (size, _, rightInset) = self.validLayout { if let (size, _, rightInset) = self.validLayout {