mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
UI improvements
This commit is contained in:
parent
f173aaa5e5
commit
04d97739cd
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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() {
|
||||||
|
@ -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
|
||||||
|
@ -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() {
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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: {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user