diff --git a/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift b/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift index 4f186d65d9..6bef3c79bd 100644 --- a/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift +++ b/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift @@ -775,24 +775,6 @@ public protocol AnimatedStickerNodeSource { func directDataPath() -> Signal } -public final class AnimatedStickerNodeLocalFileSource: AnimatedStickerNodeSource { - public var fitzModifier: EmojiFitzModifier? = nil - - public let path: String - - public init(path: String) { - self.path = path - } - - public func directDataPath() -> Signal { - return .single(self.path) - } - - public func cachedDataPath(width: Int, height: Int) -> Signal<(String, Bool), NoError> { - return .never() - } -} - public final class AnimatedStickerNode: ASDisplayNode { private let queue: Queue private let disposable = MetaDisposable() diff --git a/submodules/CallListUI/BUILD b/submodules/CallListUI/BUILD index 6f02400710..636bbe2779 100644 --- a/submodules/CallListUI/BUILD +++ b/submodules/CallListUI/BUILD @@ -29,6 +29,7 @@ swift_library( "//submodules/ContextUI:ContextUI", "//submodules/TelegramBaseController:TelegramBaseController", "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", ], visibility = [ "//visibility:public", diff --git a/submodules/CallListUI/Sources/CallListControllerNode.swift b/submodules/CallListUI/Sources/CallListControllerNode.swift index bd995283c0..d654650987 100644 --- a/submodules/CallListUI/Sources/CallListControllerNode.swift +++ b/submodules/CallListUI/Sources/CallListControllerNode.swift @@ -12,6 +12,7 @@ import AccountContext import TelegramNotices import ChatListSearchItemHeader import AnimatedStickerNode +import TelegramAnimatedStickerNode import AppBundle private struct CallListNodeListViewTransition { @@ -281,11 +282,8 @@ final class CallListControllerNode: ASDisplayNode { self.listNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor } - - if let path = getAppBundle().path(forResource: "CallsPlaceholder", ofType: "tgs") { - self.emptyAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 256, height: 256, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) - self.emptyAnimationSize = CGSize(width: 148.0, height: 148.0) - } + self.emptyAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "CallsPlaceholder"), width: 256, height: 256, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) + self.emptyAnimationSize = CGSize(width: 148.0, height: 148.0) self.emptyButtonIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Call List/CallIcon"), color: presentationData.theme.list.itemAccentColor) diff --git a/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift b/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift index 87e2b7603a..9271eeb8bb 100644 --- a/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift +++ b/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift @@ -9,6 +9,7 @@ import AccountContext import PresentationDataUtils import RadialStatusNode import AnimatedStickerNode +import TelegramAnimatedStickerNode import AppBundle import ZipArchive import MimeTypes @@ -380,20 +381,17 @@ public final class ChatImportActivityScreen: ViewController { self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor - if let path = getAppBundle().path(forResource: "HistoryImport", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 190 * 2, height: 190 * 2, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) - self.animationNode.visibility = true - } - if let path = getAppBundle().path(forResource: "HistoryImportDone", ofType: "tgs") { - self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 190 * 2, height: 190 * 2, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.doneAnimationNode.started = { [weak self] in - guard let strongSelf = self else { - return - } - strongSelf.animationNode.isHidden = true + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "HistoryImport"), width: 190 * 2, height: 190 * 2, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) + self.animationNode.visibility = true + + self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "HistoryImportDone"), width: 190 * 2, height: 190 * 2, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.doneAnimationNode.started = { [weak self] in + guard let strongSelf = self else { + return } - self.doneAnimationNode.visibility = false + strongSelf.animationNode.isHidden = true } + self.doneAnimationNode.visibility = false self.addSubnode(self.animationNode) self.addSubnode(self.doneAnimationNode) diff --git a/submodules/ChatListFilterSettingsHeaderItem/BUILD b/submodules/ChatListFilterSettingsHeaderItem/BUILD index 9fc2439438..0868cf13ab 100644 --- a/submodules/ChatListFilterSettingsHeaderItem/BUILD +++ b/submodules/ChatListFilterSettingsHeaderItem/BUILD @@ -13,11 +13,12 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", + "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/ItemListUI:ItemListUI", "//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/AnimatedStickerNode:AnimatedStickerNode", - "//submodules/AppBundle:AppBundle", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", ], visibility = [ "//visibility:public", diff --git a/submodules/ChatListFilterSettingsHeaderItem/Sources/ChatListFilterSettingsHeaderItem.swift b/submodules/ChatListFilterSettingsHeaderItem/Sources/ChatListFilterSettingsHeaderItem.swift index 078a24be76..1e5d6a341d 100644 --- a/submodules/ChatListFilterSettingsHeaderItem/Sources/ChatListFilterSettingsHeaderItem.swift +++ b/submodules/ChatListFilterSettingsHeaderItem/Sources/ChatListFilterSettingsHeaderItem.swift @@ -3,11 +3,13 @@ import UIKit import Display import AsyncDisplayKit import SwiftSignalKit +import TelegramCore import TelegramPresentationData import ItemListUI import PresentationDataUtils import AnimatedStickerNode -import AppBundle +import TelegramAnimatedStickerNode +import AccountContext public enum ChatListFilterSettingsHeaderAnimation { case folders @@ -17,12 +19,14 @@ public enum ChatListFilterSettingsHeaderAnimation { } public class ChatListFilterSettingsHeaderItem: ListViewItem, ItemListItem { + let context: AccountContext let theme: PresentationTheme let text: String let animation: ChatListFilterSettingsHeaderAnimation public let sectionId: ItemListSectionId - public init(theme: PresentationTheme, text: String, animation: ChatListFilterSettingsHeaderAnimation, sectionId: ItemListSectionId) { + public init(context: AccountContext, theme: PresentationTheme, text: String, animation: ChatListFilterSettingsHeaderAnimation, sectionId: ItemListSectionId) { + self.context = context self.theme = theme self.text = text self.animation = animation @@ -148,10 +152,8 @@ class ChatListFilterSettingsHeaderItemNode: ListViewItemNode { return (layout, { [weak self] in if let strongSelf = self { if strongSelf.item == nil { - if let path = getAppBundle().path(forResource: animationName, ofType: "tgs") { - strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: size, height: size, playbackMode: playbackMode, mode: .direct(cachePathPrefix: nil)) - strongSelf.animationNode.visibility = true - } + strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: size, height: size, playbackMode: playbackMode, mode: .direct(cachePathPrefix: nil)) + strongSelf.animationNode.visibility = true } strongSelf.item = item diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 5e20fd528e..13841020bc 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1343,7 +1343,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let location = CGRect(origin: CGPoint(x: absoluteFrame.midX, y: absoluteFrame.minY - 8.0), size: CGSize()) - parentController.present(TooltipScreen(text: text, icon: .chatListPress, location: .point(location, .bottom), shouldDismissOnTouch: { point in + parentController.present(TooltipScreen(account: strongSelf.context.account, text: text, icon: .chatListPress, location: .point(location, .bottom), shouldDismissOnTouch: { point in guard let strongSelf = self, let parentController = strongSelf.parent as? TabBarController else { return .dismiss(consume: false) } diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 6ff6c48ad8..bb2f79857e 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -304,7 +304,7 @@ private final class ChatListContainerItemNode: ASDisplayNode { if let currentNode = strongSelf.emptyNode { currentNode.updateIsLoading(isLoading) } else { - let emptyNode = ChatListEmptyNode(isFilter: filter != nil, isLoading: isLoading, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, action: { + let emptyNode = ChatListEmptyNode(context: context, isFilter: filter != nil, isLoading: isLoading, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, action: { self?.emptyAction(filter) }) strongSelf.emptyNode = emptyNode diff --git a/submodules/ChatListUI/Sources/ChatListEmptyNode.swift b/submodules/ChatListUI/Sources/ChatListEmptyNode.swift index 8cb64b4e0f..fec66a70dc 100644 --- a/submodules/ChatListUI/Sources/ChatListEmptyNode.swift +++ b/submodules/ChatListUI/Sources/ChatListEmptyNode.swift @@ -4,9 +4,11 @@ import AsyncDisplayKit import Display import TelegramPresentationData import AnimatedStickerNode +import TelegramAnimatedStickerNode import AppBundle import SolidRoundedButtonNode import ActivityIndicator +import AccountContext final class ChatListEmptyNode: ASDisplayNode { private let action: () -> Void @@ -24,7 +26,7 @@ final class ChatListEmptyNode: ASDisplayNode { private var validLayout: CGSize? - init(isFilter: Bool, isLoading: Bool, theme: PresentationTheme, strings: PresentationStrings, action: @escaping () -> Void) { + init(context: AccountContext, isFilter: Bool, isLoading: Bool, theme: PresentationTheme, strings: PresentationStrings, action: @escaping () -> Void) { self.action = action self.isFilter = isFilter self.isLoading = isLoading @@ -67,11 +69,10 @@ final class ChatListEmptyNode: ASDisplayNode { } else { animationName = "ChatListEmpty" } - if let path = getAppBundle().path(forResource: animationName, ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.animationSize = CGSize(width: 124.0, height: 124.0) - self.animationNode.visibility = true - } + + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 248, height: 248, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.animationSize = CGSize(width: 124.0, height: 124.0) + self.animationNode.visibility = true self.animationNode.isHidden = self.isLoading self.textNode.isHidden = self.isLoading diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index a4d2703731..6810b3f778 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -326,7 +326,7 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { let arguments = arguments as! ChatListFilterPresetControllerArguments switch self { case .screenHeader: - return ChatListFilterSettingsHeaderItem(theme: presentationData.theme, text: "", animation: .newFolder, sectionId: self.section) + return ChatListFilterSettingsHeaderItem(context: arguments.context, theme: presentationData.theme, text: "", animation: .newFolder, sectionId: self.section) case let .nameHeader(title): return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) case let .name(placeholder, value): diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index e9a86e85ff..5fbc264b6a 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -138,7 +138,7 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { let arguments = arguments as! ChatListFilterPresetListControllerArguments switch self { case let .screenHeader(text): - return ChatListFilterSettingsHeaderItem(theme: presentationData.theme, text: text, animation: .folders, sectionId: self.section) + return ChatListFilterSettingsHeaderItem(context: arguments.context, theme: presentationData.theme, text: text, animation: .folders, sectionId: self.section) case let .suggestedListHeader(text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section) case let .suggestedPreset(_, title, label, preset): diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 30b18e6ca3..6e3323b3fd 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -18,6 +18,7 @@ import TelegramBaseController import OverlayStatusController import ListMessageItem import AnimatedStickerNode +import TelegramAnimatedStickerNode import ChatListSearchItemHeader import PhoneNumberFormat import InstantPageUI @@ -794,10 +795,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { super.init() - if let path = getAppBundle().path(forResource: "ChatListNoResults", ofType: "tgs") { - self.emptyResultsAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 256, height: 256, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.emptyResultsAnimationSize = CGSize(width: 148.0, height: 148.0) - } + self.emptyResultsAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ChatListNoResults"), width: 256, height: 256, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.emptyResultsAnimationSize = CGSize(width: 148.0, height: 148.0) self.addSubnode(self.recentListNode) self.addSubnode(self.listNode) diff --git a/submodules/ContactListUI/Sources/ContactListNode.swift b/submodules/ContactListUI/Sources/ContactListNode.swift index 63b019afa2..3cbc0e937f 100644 --- a/submodules/ContactListUI/Sources/ContactListNode.swift +++ b/submodules/ContactListUI/Sources/ContactListNode.swift @@ -920,7 +920,7 @@ public final class ContactListNode: ASDisplayNode { var authorizeImpl: (() -> Void)? var openPrivacyPolicyImpl: (() -> Void)? - self.authorizationNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: .image(UIImage(bundleImageName: "Settings/Permissions/Contacts")), title: self.presentationData.strings.Contacts_PermissionsTitle, text: self.presentationData.strings.Contacts_PermissionsText, buttonTitle: self.presentationData.strings.Contacts_PermissionsAllow, buttonAction: { + self.authorizationNode = PermissionContentNode(context: self.context, theme: self.presentationData.theme, strings: self.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: .image(UIImage(bundleImageName: "Settings/Permissions/Contacts")), title: self.presentationData.strings.Contacts_PermissionsTitle, text: self.presentationData.strings.Contacts_PermissionsText, buttonTitle: self.presentationData.strings.Contacts_PermissionsAllow, buttonAction: { authorizeImpl?() }, openPrivacyPolicy: { openPrivacyPolicyImpl?() @@ -1376,7 +1376,7 @@ public final class ContactListNode: ASDisplayNode { let authorizationPreviousHidden = strongSelf.authorizationNode.isHidden strongSelf.authorizationNode.removeFromSupernode() - strongSelf.authorizationNode = PermissionContentNode(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: .image(UIImage(bundleImageName: "Settings/Permissions/Contacts")), title: strongSelf.presentationData.strings.Contacts_PermissionsTitle, text: strongSelf.presentationData.strings.Contacts_PermissionsText, buttonTitle: strongSelf.presentationData.strings.Contacts_PermissionsAllow, buttonAction: { + strongSelf.authorizationNode = PermissionContentNode(context: strongSelf.context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: .image(UIImage(bundleImageName: "Settings/Permissions/Contacts")), title: strongSelf.presentationData.strings.Contacts_PermissionsTitle, text: strongSelf.presentationData.strings.Contacts_PermissionsText, buttonTitle: strongSelf.presentationData.strings.Contacts_PermissionsAllow, buttonAction: { authorizeImpl?() }, openPrivacyPolicy: { openPrivacyPolicyImpl?() diff --git a/submodules/InviteLinksUI/BUILD b/submodules/InviteLinksUI/BUILD index 3e7f32d48a..073baefda8 100644 --- a/submodules/InviteLinksUI/BUILD +++ b/submodules/InviteLinksUI/BUILD @@ -52,6 +52,8 @@ swift_library( "//submodules/SectionHeaderItem:SectionHeaderItem", "//submodules/DirectionalPanGesture:DirectionalPanGesture", "//submodules/ShimmerEffect:ShimmerEffect", + "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", ], visibility = [ "//visibility:public", diff --git a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift index 64dd3c37b1..e8f48f404c 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift @@ -7,14 +7,17 @@ import TelegramPresentationData import ItemListUI import PresentationDataUtils import AnimatedStickerNode -import AppBundle +import TelegramAnimatedStickerNode +import AccountContext class InviteLinkHeaderItem: ListViewItem, ItemListItem { + let context: AccountContext let theme: PresentationTheme let text: String let sectionId: ItemListSectionId - init(theme: PresentationTheme, text: String, sectionId: ItemListSectionId) { + init(context: AccountContext, theme: PresentationTheme, text: String, sectionId: ItemListSectionId) { + self.context = context self.theme = theme self.text = text self.sectionId = sectionId @@ -72,10 +75,6 @@ class InviteLinkHeaderItemNode: ListViewItemNode { self.titleNode.contentsScale = UIScreen.main.scale self.animationNode = AnimatedStickerNode() - if let path = getAppBundle().path(forResource: "Invite", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) - self.animationNode.visibility = true - } super.init(layerBacked: false, dynamicBounce: false) @@ -100,6 +99,10 @@ class InviteLinkHeaderItemNode: ListViewItemNode { return (layout, { [weak self] in if let strongSelf = self { + if strongSelf.item == nil { + strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Invite"), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) + strongSelf.animationNode.visibility = true + } strongSelf.item = item strongSelf.accessibilityLabel = attributedText.string diff --git a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift index 14becb0baa..507b469514 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift @@ -211,7 +211,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry { let arguments = arguments as! InviteLinkListControllerArguments switch self { case let .header(theme, text): - return InviteLinkHeaderItem(theme: theme, text: text, sectionId: self.section) + return InviteLinkHeaderItem(context: arguments.context, theme: theme, text: text, sectionId: self.section) case let .mainLinkHeader(_, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .mainLink(_, invite, peers, importersCount, isPublic): diff --git a/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift b/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift index 49fcbbfd09..7895fba2e6 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift @@ -9,6 +9,7 @@ import QrCode import AccountContext import SolidRoundedButtonNode import AnimatedStickerNode +import TelegramAnimatedStickerNode import TelegramCore private func shareQrCode(context: AccountContext, link: String, view: UIView) { @@ -226,10 +227,9 @@ public final class InviteLinkQRCodeController: ViewController { self.qrImageNode.cornerRadius = 16.0 self.qrIconNode = AnimatedStickerNode() - if let path = getAppBundle().path(forResource: "PlaneLogo", ofType: "tgs") { - self.qrIconNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 240, height: 240, mode: .direct(cachePathPrefix: nil)) - self.qrIconNode.visibility = true - } + + self.qrIconNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "PlaneLogo"), width: 240, height: 240, mode: .direct(cachePathPrefix: nil)) + self.qrIconNode.visibility = true super.init() diff --git a/submodules/LocalMediaResources/BUILD b/submodules/LocalMediaResources/BUILD index 297f8b73d8..b0f3f832fe 100644 --- a/submodules/LocalMediaResources/BUILD +++ b/submodules/LocalMediaResources/BUILD @@ -14,6 +14,7 @@ swift_library( "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/ImageCompression:ImageCompression", + "//submodules/PersistentStringHash:PersistentStringHash", ], visibility = [ "//visibility:public", diff --git a/submodules/LocalMediaResources/Sources/MediaResources.swift b/submodules/LocalMediaResources/Sources/MediaResources.swift index ce75f53326..a7c0272aeb 100644 --- a/submodules/LocalMediaResources/Sources/MediaResources.swift +++ b/submodules/LocalMediaResources/Sources/MediaResources.swift @@ -2,6 +2,7 @@ import Foundation import UIKit import Postbox import TelegramCore +import PersistentStringHash public final class VideoMediaResourceAdjustments: PostboxCoding, Equatable { public let data: MemoryBuffer @@ -318,3 +319,56 @@ public final class LocalFileGifMediaResource: TelegramMediaResource { } } } + + +public struct BundleResourceId: MediaResourceId { + public let nameHash: Int64 + + public var uniqueId: String { + return "bundle-\(nameHash)" + } + + public var hashValue: Int { + return self.nameHash.hashValue + } + + public func isEqual(to: MediaResourceId) -> Bool { + if let to = to as? BundleResourceId { + return self.nameHash == to.nameHash + } else { + return false + } + } +} + +public class BundleResource: TelegramMediaResource { + public let nameHash: Int64 + public let path: String + + public init(name: String, path: String) { + self.nameHash = Int64(bitPattern: name.persistentHashValue) + self.path = path + } + + public required init(decoder: PostboxDecoder) { + self.nameHash = decoder.decodeInt64ForKey("h", orElse: 0) + self.path = decoder.decodeStringForKey("p", orElse: "") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt64(self.nameHash, forKey: "h") + encoder.encodeString(self.path, forKey: "p") + } + + public var id: MediaResourceId { + return BundleResourceId(nameHash: self.nameHash) + } + + public func isEqual(to: MediaResource) -> Bool { + if let to = to as? BundleResource { + return self.nameHash == to.nameHash + } else { + return false + } + } +} diff --git a/submodules/LocationUI/Sources/LocationViewControllerNode.swift b/submodules/LocationUI/Sources/LocationViewControllerNode.swift index 23b4965d89..4671b10bcd 100644 --- a/submodules/LocationUI/Sources/LocationViewControllerNode.swift +++ b/submodules/LocationUI/Sources/LocationViewControllerNode.swift @@ -723,7 +723,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan text = strongSelf.presentationData.strings.Location_ProximityTip(peer.compactDisplayTitle).string } - strongSelf.interaction.present(TooltipScreen(text: text, icon: nil, location: .point(location.offsetBy(dx: -9.0, dy: 0.0), .right), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in + strongSelf.interaction.present(TooltipScreen(account: strongSelf.context.account, text: text, icon: nil, location: .point(location.offsetBy(dx: -9.0, dy: 0.0), .right), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in return .dismiss(consume: false) })) }) diff --git a/submodules/PasswordSetupUI/BUILD b/submodules/PasswordSetupUI/BUILD index a0da0b6d88..00943960e7 100644 --- a/submodules/PasswordSetupUI/BUILD +++ b/submodules/PasswordSetupUI/BUILD @@ -37,6 +37,7 @@ swift_library( "//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/ItemListUI:ItemListUI", "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", "//submodules/AppBundle:AppBundle", "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode", "//submodules/OverlayStatusController:OverlayStatusController", diff --git a/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift index ce057a6901..ffd7790f00 100644 --- a/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift +++ b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift @@ -11,6 +11,7 @@ import TelegramPresentationData import PresentationDataUtils import TelegramCore import AnimatedStickerNode +import TelegramAnimatedStickerNode import ActivityIndicator public enum TwoFactorDataInputMode { @@ -104,7 +105,7 @@ public final class TwoFactorDataInputScreen: ViewController { } override public func loadDisplayNode() { - self.displayNode = TwoFactorDataInputScreenNode(presentationData: self.presentationData, mode: self.mode, action: { [weak self] in + self.displayNode = TwoFactorDataInputScreenNode(sharedContext: self.sharedContext, presentationData: self.presentationData, mode: self.mode, action: { [weak self] in guard let strongSelf = self else { return } @@ -1247,7 +1248,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS } } - init(presentationData: PresentationData, mode: TwoFactorDataInputMode, action: @escaping () -> Void, skipAction: @escaping () -> Void, changeEmailAction: @escaping () -> Void, resendCodeAction: @escaping () -> Void) { + init(sharedContext: SharedAccountContext, presentationData: PresentationData, mode: TwoFactorDataInputMode, action: @escaping () -> Void, skipAction: @escaping () -> Void, changeEmailAction: @escaping () -> Void, resendCodeAction: @escaping () -> Void) { self.presentationData = presentationData self.mode = mode self.action = action @@ -1268,26 +1269,20 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS case .password, .passwordRecovery, .emailAddress, .updateEmailAddress: self.monkeyNode = ManagedMonkeyAnimationNode() case .emailConfirmation, .passwordRecoveryEmail: - if let path = getAppBundle().path(forResource: "TwoFactorSetupMail", ofType: "tgs") { - let animatedStickerNode = AnimatedStickerNode() - animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 272, height: 272, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + let animatedStickerNode = AnimatedStickerNode() + animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "TwoFactorSetupMail"), width: 272, height: 272, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) animatedStickerNode.visibility = true - self.animatedStickerNode = animatedStickerNode - } + self.animatedStickerNode = animatedStickerNode case .passwordHint: - if let path = getAppBundle().path(forResource: "TwoFactorSetupHint", ofType: "tgs") { - let animatedStickerNode = AnimatedStickerNode() - animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 272, height: 272, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - animatedStickerNode.visibility = true - self.animatedStickerNode = animatedStickerNode - } + let animatedStickerNode = AnimatedStickerNode() + animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "TwoFactorSetupHint"), width: 272, height: 272, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + animatedStickerNode.visibility = true + self.animatedStickerNode = animatedStickerNode case .rememberPassword: - if let path = getAppBundle().path(forResource: "TwoFactorSetupRemember", ofType: "tgs") { - let animatedStickerNode = AnimatedStickerNode() - animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 272, height: 272, playbackMode: .count(3), mode: .direct(cachePathPrefix: nil)) - animatedStickerNode.visibility = true - self.animatedStickerNode = animatedStickerNode - } + let animatedStickerNode = AnimatedStickerNode() + animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "TwoFactorSetupRemember"), width: 272, height: 272, playbackMode: .count(3), mode: .direct(cachePathPrefix: nil)) + animatedStickerNode.visibility = true + self.animatedStickerNode = animatedStickerNode } let title: String diff --git a/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift b/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift index 64074345a2..968092fea7 100644 --- a/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift +++ b/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift @@ -1,12 +1,12 @@ import Foundation import UIKit -import AppBundle import AsyncDisplayKit import Display import SolidRoundedButtonNode import SwiftSignalKit import OverlayStatusController import AnimatedStickerNode +import TelegramAnimatedStickerNode import AccountContext import TelegramPresentationData import PresentationDataUtils @@ -141,21 +141,17 @@ private final class TwoFactorAuthSplashScreenNode: ViewControllerTracingNode { texts = [NSAttributedString(string: self.presentationData.strings.TwoFactorSetup_Intro_Text, font: textFont, textColor: textColor)] buttonText = self.presentationData.strings.TwoFactorSetup_Intro_Action - if let path = getAppBundle().path(forResource: "TwoFactorSetupIntro", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.animationSize = CGSize(width: 124.0, height: 124.0) - self.animationNode.visibility = true - } + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "TwoFactorSetupIntro"), width: 248, height: 248, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.animationSize = CGSize(width: 124.0, height: 124.0) + self.animationNode.visibility = true case .done: title = self.presentationData.strings.TwoFactorSetup_Done_Title texts = [NSAttributedString(string: self.presentationData.strings.TwoFactorSetup_Done_Text, font: textFont, textColor: textColor)] buttonText = self.presentationData.strings.TwoFactorSetup_Done_Action - if let path = getAppBundle().path(forResource: "TwoFactorSetupDone", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, mode: .direct(cachePathPrefix: nil)) - self.animationSize = CGSize(width: 124.0, height: 124.0) - self.animationNode.visibility = true - } + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "TwoFactorSetupDone"), width: 248, height: 248, mode: .direct(cachePathPrefix: nil)) + self.animationSize = CGSize(width: 124.0, height: 124.0) + self.animationNode.visibility = true case let .recoveryDone(_, _, isPasswordSet): title = isPasswordSet ? self.presentationData.strings.TwoFactorSetup_ResetDone_Title : self.presentationData.strings.TwoFactorSetup_ResetDone_TitleNoPassword @@ -176,21 +172,17 @@ private final class TwoFactorAuthSplashScreenNode: ViewControllerTracingNode { texts = splitTexts.map { NSAttributedString(string: $0, font: textFont, textColor: textColor) } buttonText = self.presentationData.strings.TwoFactorSetup_ResetDone_Action - if let path = getAppBundle().path(forResource: isPasswordSet ? "TwoFactorSetupDone" : "TwoFactorRemovePasswordDone", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, playbackMode: isPasswordSet ? .loop : .once, mode: .direct(cachePathPrefix: nil)) - self.animationSize = CGSize(width: 124.0, height: 124.0) - self.animationNode.visibility = true - } + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: isPasswordSet ? "TwoFactorSetupDone" : "TwoFactorRemovePasswordDone"), width: 248, height: 248, playbackMode: isPasswordSet ? .loop : .once, mode: .direct(cachePathPrefix: nil)) + self.animationSize = CGSize(width: 124.0, height: 124.0) + self.animationNode.visibility = true case .remember: title = self.presentationData.strings.TwoFactorRemember_Done_Title texts = [NSAttributedString(string: self.presentationData.strings.TwoFactorRemember_Done_Text, font: textFont, textColor: textColor)] buttonText = self.presentationData.strings.TwoFactorRemember_Done_Action - if let path = getAppBundle().path(forResource: "TwoFactorSetupRememberSuccess", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, mode: .direct(cachePathPrefix: nil)) - self.animationSize = CGSize(width: 124.0, height: 124.0) - self.animationNode.visibility = true - } + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "TwoFactorSetupRememberSuccess"), width: 248, height: 248, mode: .direct(cachePathPrefix: nil)) + self.animationSize = CGSize(width: 124.0, height: 124.0) + self.animationNode.visibility = true } self.titleNode = ImmediateTextNode() diff --git a/submodules/PeerInfoUI/BUILD b/submodules/PeerInfoUI/BUILD index 87c4038f92..25accba0be 100644 --- a/submodules/PeerInfoUI/BUILD +++ b/submodules/PeerInfoUI/BUILD @@ -71,6 +71,8 @@ swift_library( "//submodules/ChatListFilterSettingsHeaderItem:ChatListFilterSettingsHeaderItem", "//submodules/InviteLinksUI:InviteLinksUI", "//submodules/UIKitRuntimeUtils:UIKitRuntimeUtils", + "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", ], visibility = [ "//visibility:public", diff --git a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift index 7e306b8939..d0c546daef 100644 --- a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift @@ -142,7 +142,7 @@ private enum ChannelDiscussionGroupSetupControllerEntry: ItemListNodeEntry { } else { text = presentationData.strings.Channel_CommentsGroup_Header } - return ChatListFilterSettingsHeaderItem(theme: presentationData.theme, text: text, animation: .discussionGroupSetup, sectionId: self.section) + return ChatListFilterSettingsHeaderItem(context: arguments.context, theme: presentationData.theme, text: text, animation: .discussionGroupSetup, sectionId: self.section) case let .create(theme, text): return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.plusIconImage(theme), title: text, sectionId: self.section, editing: false, action: { arguments.createGroup() diff --git a/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift b/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift index ae304b1de4..37535b2d6d 100644 --- a/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift +++ b/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift @@ -11,9 +11,11 @@ import AccountContext import ChatListFilterSettingsHeaderItem private final class PeerAutoremoveSetupArguments { + let context: AccountContext let updateValue: (Int32) -> Void - init(updateValue: @escaping (Int32) -> Void) { + init(context: AccountContext, updateValue: @escaping (Int32) -> Void) { + self.context = context self.updateValue = updateValue } } @@ -86,7 +88,7 @@ private enum PeerAutoremoveSetupEntry: ItemListNodeEntry { let arguments = arguments as! PeerAutoremoveSetupArguments switch self { case .header: - return ChatListFilterSettingsHeaderItem(theme: presentationData.theme, text: "", animation: .autoRemove, sectionId: self.section) + return ChatListFilterSettingsHeaderItem(context: arguments.context, theme: presentationData.theme, text: "", animation: .autoRemove, sectionId: self.section) case let .timeHeader(text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .timeValue(value, availableValues): @@ -157,7 +159,7 @@ public func peerAutoremoveSetupScreen(context: AccountContext, updatedPresentati let applyDisposable = MetaDisposable() actionsDisposable.add(applyDisposable) - let arguments = PeerAutoremoveSetupArguments(updateValue: { value in + let arguments = PeerAutoremoveSetupArguments(context: context, updateValue: { value in updateState { state in var state = state state.changedValue = value diff --git a/submodules/PeerInfoUI/Sources/PeerReportController.swift b/submodules/PeerInfoUI/Sources/PeerReportController.swift index f61ca0c2d9..9b628f73fd 100644 --- a/submodules/PeerInfoUI/Sources/PeerReportController.swift +++ b/submodules/PeerInfoUI/Sources/PeerReportController.swift @@ -92,9 +92,7 @@ public func presentPeerReportOptions(context: AccountContext, parent: ViewContro } let displaySuccess = { - if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") { - parent?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current) - } + parent?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current) } if passthrough { @@ -221,9 +219,7 @@ public func peerReportOptionsController(context: AccountContext, subject: PeerRe } let displaySuccess = { - if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") { - present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), nil) - } + present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), nil) } let action: (String) -> Void = { message in diff --git a/submodules/PeerInfoUI/Sources/ReportPeerHeaderActionSheetItem.swift b/submodules/PeerInfoUI/Sources/ReportPeerHeaderActionSheetItem.swift index 8fd1972cd4..0cc726e9a9 100644 --- a/submodules/PeerInfoUI/Sources/ReportPeerHeaderActionSheetItem.swift +++ b/submodules/PeerInfoUI/Sources/ReportPeerHeaderActionSheetItem.swift @@ -7,7 +7,7 @@ import TelegramPresentationData import TelegramUIPreferences import AccountContext import AnimatedStickerNode -import AppBundle +import TelegramAnimatedStickerNode public final class ReportPeerHeaderActionSheetItem: ActionSheetItem { let context: AccountContext @@ -40,10 +40,8 @@ private final class ReportPeerHeaderActionSheetItemNode: ActionSheetItemNode { let textFont = Font.regular(floor(theme.baseFontSize * 13.0 / 17.0)) self.animationNode = AnimatedStickerNode() - if let path = getAppBundle().path(forResource: "Cop", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 192, height: 192, playbackMode: .count(2), mode: .direct(cachePathPrefix: nil)) - self.animationNode.visibility = true - } + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Cop"), width: 192, height: 192, playbackMode: .count(2), mode: .direct(cachePathPrefix: nil)) + self.animationNode.visibility = true self.textNode = ImmediateTextNode() self.textNode.displaysAsynchronously = false diff --git a/submodules/PeersNearbyUI/BUILD b/submodules/PeersNearbyUI/BUILD index 2350ad063c..a83643a764 100644 --- a/submodules/PeersNearbyUI/BUILD +++ b/submodules/PeersNearbyUI/BUILD @@ -30,6 +30,7 @@ swift_library( "//submodules/Geocoding:Geocoding", "//submodules/AppBundle:AppBundle", "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", "//submodules/TelegramStringFormatting:TelegramStringFormatting", "//submodules/TelegramNotices:TelegramNotices", ], diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift index 13bb221089..c40e9db53f 100644 --- a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift +++ b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift @@ -215,7 +215,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry { let arguments = arguments as! PeersNearbyControllerArguments switch self { case let .header(theme, text): - return PeersNearbyHeaderItem(theme: theme, text: text, sectionId: self.section) + return PeersNearbyHeaderItem(context: arguments.context, theme: theme, text: text, sectionId: self.section) case let .usersHeader(_, text, loading): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section) case let .empty(theme, text): diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyHeaderItem.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyHeaderItem.swift index 223449a8ff..cf15453d83 100644 --- a/submodules/PeersNearbyUI/Sources/PeersNearbyHeaderItem.swift +++ b/submodules/PeersNearbyUI/Sources/PeersNearbyHeaderItem.swift @@ -7,14 +7,17 @@ import TelegramPresentationData import ItemListUI import PresentationDataUtils import AnimatedStickerNode -import AppBundle +import TelegramAnimatedStickerNode +import AccountContext class PeersNearbyHeaderItem: ListViewItem, ItemListItem { + let context: AccountContext let theme: PresentationTheme let text: String let sectionId: ItemListSectionId - init(theme: PresentationTheme, text: String, sectionId: ItemListSectionId) { + init(context: AccountContext, theme: PresentationTheme, text: String, sectionId: ItemListSectionId) { + self.context = context self.theme = theme self.text = text self.sectionId = sectionId @@ -72,11 +75,7 @@ class PeersNearbyHeaderItemNode: ListViewItemNode { self.titleNode.contentsScale = UIScreen.main.scale self.animationNode = AnimatedStickerNode() - if let path = getAppBundle().path(forResource: "Compass", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 192, height: 192, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.animationNode.visibility = true - } - + super.init(layerBacked: false, dynamicBounce: false) self.addSubnode(self.titleNode) @@ -100,6 +99,10 @@ class PeersNearbyHeaderItemNode: ListViewItemNode { return (layout, { [weak self] in if let strongSelf = self { + if strongSelf.item == nil { + strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Compass"), width: 192, height: 192, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + strongSelf.animationNode.visibility = true + } strongSelf.item = item strongSelf.accessibilityLabel = attributedText.string diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index b14a544894..25f019a1aa 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -228,6 +228,7 @@ private struct EditThemeControllerState: Equatable { var slug: String var updatedTheme: PresentationTheme? var updating: Bool + var converting: Bool } private func editThemeControllerEntries(presentationData: PresentationData, state: EditThemeControllerState, previewTheme: PresentationTheme, hasSettings: Bool) -> [EditThemeControllerEntry] { @@ -326,7 +327,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll settingsPromise.set(.single(nil)) hasSettings = false } - initialState = EditThemeControllerState(mode: mode, title: generateThemeName(accentColor: theme.rootController.navigationBar.buttonColor), slug: "", updatedTheme: nil, updating: false) + initialState = EditThemeControllerState(mode: mode, title: generateThemeName(accentColor: theme.rootController.navigationBar.buttonColor), slug: "", updatedTheme: nil, updating: false, converting: false) previewThemePromise.set(.single(theme.withUpdated(name: "", defaultWallpaper: wallpaper))) case let .edit(info): hasSettings = info.theme.settings != nil @@ -348,7 +349,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll previewThemePromise.set(.single(presentationData.theme.withUpdated(name: "", defaultWallpaper: presentationData.chatWallpaper))) } - initialState = EditThemeControllerState(mode: mode, title: info.theme.title, slug: info.theme.slug, updatedTheme: nil, updating: false) + initialState = EditThemeControllerState(mode: mode, title: info.theme.title, slug: info.theme.slug, updatedTheme: nil, updating: false, converting: false) } let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -484,6 +485,11 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll } let settings = TelegramThemeSettings(baseTheme: theme.referenceTheme.baseTheme, accentColor: theme.rootController.navigationBar.accentTextColor, outgoingAccentColor: outgoingAccentColor, messageColors: theme.chat.message.outgoing.bubble.withWallpaper.fill.map { $0.argb }, animateMessageColors: theme.chat.animateMessageColors, wallpaper: theme.chat.defaultWallpaper) settingsPromise.set(.single(settings)) + updateState { current in + var state = current + state.converting = true + return state + } }) }) @@ -657,7 +663,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll }) } case let .edit(info): - let _ = (prepare |> then(updateTheme(account: context.account, accountManager: context.sharedContext.accountManager, theme: info.theme, title: state.title, slug: state.slug, resource: themeResource, settings: settings) + let _ = (prepare |> then(updateTheme(account: context.account, accountManager: context.sharedContext.accountManager, theme: info.theme, title: state.title, slug: state.slug, resource: state.converting ? nil : themeResource, settings: settings, resetFile: state.converting ? true : false) |> deliverOnMainQueue)).start(next: { next in if case let .result(resultTheme) = next { let _ = applyTheme(accountManager: context.sharedContext.accountManager, account: context.account, theme: resultTheme).start() diff --git a/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift b/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift index ed20d0b6f7..f12f6816a7 100644 --- a/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift +++ b/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift @@ -157,13 +157,13 @@ public final class SlotMachineAnimationNode: ASDisplayNode { public var success: ((Bool) -> Void)? - public init(size: CGSize = CGSize(width: 184.0, height: 184.0)) { + public init(account: Account, size: CGSize = CGSize(width: 184.0, height: 184.0)) { self.animationSize = size self.backNode = ManagedAnimationNode(size: self.animationSize) let reelSize = CGSize(width: 384.0, height: 384.0) - self.leftReelNode = DiceAnimatedStickerNode(size: reelSize) - self.centerReelNode = DiceAnimatedStickerNode(size: reelSize) - self.rightReelNode = DiceAnimatedStickerNode(size: reelSize) + self.leftReelNode = DiceAnimatedStickerNode(account: account, size: reelSize) + self.centerReelNode = DiceAnimatedStickerNode(account: account,size: reelSize) + self.rightReelNode = DiceAnimatedStickerNode(account: account,size: reelSize) self.frontNode = ManagedAnimationNode(size: self.animationSize) super.init() @@ -252,6 +252,7 @@ public final class SlotMachineAnimationNode: ASDisplayNode { } class DiceAnimatedStickerNode: ASDisplayNode { + private let account: Account public let intrinsicSize: CGSize private let animationNode: AnimatedStickerNode @@ -260,7 +261,8 @@ class DiceAnimatedStickerNode: ASDisplayNode { public var trackStack: [ManagedAnimationItem] = [] public var didTryAdvancingState = false - init(size: CGSize) { + init(account: Account, size: CGSize) { + self.account = account self.intrinsicSize = size self.animationNode = AnimatedStickerNode() @@ -309,9 +311,7 @@ class DiceAnimatedStickerNode: ASDisplayNode { var source: AnimatedStickerNodeSource? switch item.source { case let .local(animationName): - if let path = getAppBundle().path(forResource: animationName, ofType: "tgs") { - source = AnimatedStickerNodeLocalFileSource(path: path) - } + source = AnimatedStickerNodeLocalFileSource(name: animationName) case let .resource(account, resource): source = AnimatedStickerResourceSource(account: account, resource: resource) } diff --git a/submodules/StatisticsUI/BUILD b/submodules/StatisticsUI/BUILD index c09203364d..299a082dee 100644 --- a/submodules/StatisticsUI/BUILD +++ b/submodules/StatisticsUI/BUILD @@ -28,6 +28,7 @@ swift_library( "//submodules/GraphCore:GraphCore", "//submodules/GraphUI:GraphUI", "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", "//submodules/ItemListPeerItem:ItemListPeerItem", "//submodules/ItemListPeerActionItem:ItemListPeerActionItem", "//submodules/ContextUI:ContextUI", diff --git a/submodules/StatisticsUI/Sources/ChannelStatsController.swift b/submodules/StatisticsUI/Sources/ChannelStatsController.swift index 26e31fadeb..3367448abd 100644 --- a/submodules/StatisticsUI/Sources/ChannelStatsController.swift +++ b/submodules/StatisticsUI/Sources/ChannelStatsController.swift @@ -468,7 +468,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD var emptyStateItem: ItemListControllerEmptyStateItem? if data == nil { if longLoading { - emptyStateItem = StatsEmptyStateItem(theme: presentationData.theme, strings: presentationData.strings) + emptyStateItem = StatsEmptyStateItem(context: context, theme: presentationData.theme, strings: presentationData.strings) } else { emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme) } diff --git a/submodules/StatisticsUI/Sources/GroupStatsController.swift b/submodules/StatisticsUI/Sources/GroupStatsController.swift index 22251f924f..c30312174b 100644 --- a/submodules/StatisticsUI/Sources/GroupStatsController.swift +++ b/submodules/StatisticsUI/Sources/GroupStatsController.swift @@ -841,7 +841,7 @@ public func groupStatsController(context: AccountContext, updatedPresentationDat var emptyStateItem: ItemListControllerEmptyStateItem? if data == nil { if longLoading { - emptyStateItem = StatsEmptyStateItem(theme: presentationData.theme, strings: presentationData.strings) + emptyStateItem = StatsEmptyStateItem(context: context, theme: presentationData.theme, strings: presentationData.strings) } else { emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme) } diff --git a/submodules/StatisticsUI/Sources/MessageStatsController.swift b/submodules/StatisticsUI/Sources/MessageStatsController.swift index 81b1fa6dd4..327578570d 100644 --- a/submodules/StatisticsUI/Sources/MessageStatsController.swift +++ b/submodules/StatisticsUI/Sources/MessageStatsController.swift @@ -234,7 +234,7 @@ public func messageStatsController(context: AccountContext, messageId: MessageId var emptyStateItem: ItemListControllerEmptyStateItem? if data == nil { if longLoading { - emptyStateItem = StatsEmptyStateItem(theme: presentationData.theme, strings: presentationData.strings) + emptyStateItem = StatsEmptyStateItem(context: context, theme: presentationData.theme, strings: presentationData.strings) } else { emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme) } diff --git a/submodules/StatisticsUI/Sources/StatsEmptyItem.swift b/submodules/StatisticsUI/Sources/StatsEmptyItem.swift index 5ffd086023..6d87af1967 100644 --- a/submodules/StatisticsUI/Sources/StatsEmptyItem.swift +++ b/submodules/StatisticsUI/Sources/StatsEmptyItem.swift @@ -6,13 +6,16 @@ import TelegramPresentationData import ItemListUI import PresentationDataUtils import AnimatedStickerNode -import AppBundle +import TelegramAnimatedStickerNode +import AccountContext final class StatsEmptyStateItem: ItemListControllerEmptyStateItem { + let context: AccountContext let theme: PresentationTheme let strings: PresentationStrings - init(theme: PresentationTheme, strings: PresentationStrings) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) { + self.context = context self.theme = theme self.strings = strings } @@ -54,10 +57,8 @@ final class StatsEmptyStateItemNode: ItemListControllerEmptyStateItemNode { self.item = item self.animationNode = AnimatedStickerNode() - if let path = getAppBundle().path(forResource: "Charts", ofType: "tgs") { - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) - self.animationNode.visibility = true - } + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Charts"), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) + self.animationNode.visibility = true self.titleNode = ASTextNode() self.titleNode.isUserInteractionEnabled = false diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift index e183f6393e..b959aef453 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift @@ -292,7 +292,7 @@ public func preloadedStickerPackThumbnail(account: Account, info: StickerPackCol let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)).start() let dataDisposable: Disposable if info.flags.contains(.isAnimated) { - dataDisposable = chatMessageAnimationData(postbox: account.postbox, resource: thumbnail.resource, width: 80, height: 80, synchronousLoad: false).start(next: { data in + dataDisposable = chatMessageAnimationData(mediaBox: account.postbox.mediaBox, resource: thumbnail.resource, width: 80, height: 80, synchronousLoad: false).start(next: { data in if data.complete { subscriber.putNext(true) subscriber.putCompletion() diff --git a/submodules/StickerResources/Sources/StickerResources.swift b/submodules/StickerResources/Sources/StickerResources.swift index 3a7710be48..a600bf4bca 100644 --- a/submodules/StickerResources/Sources/StickerResources.swift +++ b/submodules/StickerResources/Sources/StickerResources.swift @@ -225,9 +225,9 @@ private func chatMessageStickerPackThumbnailData(postbox: Postbox, resource: Med } } -public func chatMessageAnimationData(postbox: Postbox, resource: MediaResource, fitzModifier: EmojiFitzModifier? = nil, width: Int, height: Int, synchronousLoad: Bool) -> Signal { +public func chatMessageAnimationData(mediaBox: MediaBox, resource: MediaResource, fitzModifier: EmojiFitzModifier? = nil, width: Int, height: Int, synchronousLoad: Bool) -> Signal { let representation = CachedAnimatedStickerRepresentation(width: Int32(width), height: Int32(height), fitzModifier: fitzModifier) - let maybeFetched = postbox.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false, fetch: false, attemptSynchronously: synchronousLoad) + let maybeFetched = mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false, fetch: false, attemptSynchronously: synchronousLoad) return maybeFetched |> take(1) @@ -235,7 +235,7 @@ public func chatMessageAnimationData(postbox: Postbox, resource: MediaResource, if maybeData.complete { return .single(maybeData) } else { - return postbox.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false) + return mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false) } } } diff --git a/submodules/TelegramAnimatedStickerNode/BUILD b/submodules/TelegramAnimatedStickerNode/BUILD index f67d3887d4..8515400051 100644 --- a/submodules/TelegramAnimatedStickerNode/BUILD +++ b/submodules/TelegramAnimatedStickerNode/BUILD @@ -14,6 +14,7 @@ swift_library( "//submodules/TelegramCore:TelegramCore", "//submodules/StickerResources:StickerResources", "//submodules/MediaResources:MediaResources", + "//submodules/LocalMediaResources:LocalMediaResources", "//submodules/Tuples:Tuples", "//submodules/AnimatedStickerNode:AnimatedStickerNode", "//submodules/rlottie:RLottieBinding", diff --git a/submodules/TelegramAnimatedStickerNode/Sources/TelegramAnimatedStickerNode.swift b/submodules/TelegramAnimatedStickerNode/Sources/TelegramAnimatedStickerNode.swift index 88f784aaab..4337e7f729 100644 --- a/submodules/TelegramAnimatedStickerNode/Sources/TelegramAnimatedStickerNode.swift +++ b/submodules/TelegramAnimatedStickerNode/Sources/TelegramAnimatedStickerNode.swift @@ -5,6 +5,40 @@ import Postbox import TelegramCore import MediaResources import StickerResources +import LocalMediaResources +import AppBundle + +public final class AnimatedStickerNodeLocalFileSource: AnimatedStickerNodeSource { + public var fitzModifier: EmojiFitzModifier? = nil + + public let name: String + + public init(name: String) { + self.name = name + } + + public func directDataPath() -> Signal { + if let path = self.path { + return .single(path) + } else { + return .never() + } + } + + public func cachedDataPath(width: Int, height: Int) -> Signal<(String, Bool), NoError> { + return .never() + } + + public var path: String? { + if let path = getAppBundle().path(forResource: self.name, ofType: "tgs") { + return path + } else if let path = getAppBundle().path(forResource: self.name, ofType: "json") { + return path + } else { + return nil + } + } +} public final class AnimatedStickerResourceSource: AnimatedStickerNodeSource { public let account: Account @@ -18,7 +52,7 @@ public final class AnimatedStickerResourceSource: AnimatedStickerNodeSource { } public func cachedDataPath(width: Int, height: Int) -> Signal<(String, Bool), NoError> { - return chatMessageAnimationData(postbox: self.account.postbox, resource: self.resource, fitzModifier: self.fitzModifier, width: width, height: height, synchronousLoad: false) + return chatMessageAnimationData(mediaBox: self.account.postbox.mediaBox, resource: self.resource, fitzModifier: self.fitzModifier, width: width, height: height, synchronousLoad: false) |> filter { data in return data.size != 0 } diff --git a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift index 05e561d4c4..d50d67a57a 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift @@ -726,7 +726,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro return } - self.present?(TooltipScreen(text: self.presentationData.strings.Call_CameraOrScreenTooltip, style: .light, icon: nil, location: .point(location.offsetBy(dx: 0.0, dy: -14.0), .bottom), displayDuration: .custom(5.0), shouldDismissOnTouch: { _ in + self.present?(TooltipScreen(account: self.account, text: self.presentationData.strings.Call_CameraOrScreenTooltip, style: .light, icon: nil, location: .point(location.offsetBy(dx: 0.0, dy: -14.0), .bottom), displayDuration: .custom(5.0), shouldDismissOnTouch: { _ in return .dismiss(consume: false) })) } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index f179275c4e..1252e78f81 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -2264,7 +2264,7 @@ public final class VoiceChatController: ViewController { } else { text = presentationData.strings.VoiceChat_RecordingInProgress } - strongSelf.controller?.present(TooltipScreen(text: text, icon: nil, location: .point(location.offsetBy(dx: 1.0, dy: 0.0), .top), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in + strongSelf.controller?.present(TooltipScreen(account: strongSelf.context.account, text: text, icon: nil, location: .point(location.offsetBy(dx: 1.0, dy: 0.0), .top), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in return .dismiss(consume: true) }), in: .window(.root)) } @@ -3437,7 +3437,7 @@ public final class VoiceChatController: ViewController { if !callState.subscribedToScheduled { let location = self.actionButton.view.convert(self.actionButton.bounds, to: self.view).center let point = CGRect(origin: CGPoint(x: location.x - 5.0, y: location.y - 5.0 - 68.0), size: CGSize(width: 10.0, height: 10.0)) - self.controller?.present(TooltipScreen(text: self.presentationData.strings.VoiceChat_ReminderNotify, style: .gradient(UIColor(rgb: 0x262c5a), UIColor(rgb: 0x5d2835)), icon: nil, location: .point(point, .bottom), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in + self.controller?.present(TooltipScreen(account: self.context.account, text: self.presentationData.strings.VoiceChat_ReminderNotify, style: .gradient(UIColor(rgb: 0x262c5a), UIColor(rgb: 0x5d2835)), icon: nil, location: .point(point, .bottom), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in return .dismiss(consume: false) }), in: .window(.root)) } @@ -6323,7 +6323,7 @@ public final class VoiceChatController: ViewController { point.origin.y += 32.0 } } - self.controller?.present(TooltipScreen(text: self.presentationData.strings.VoiceChat_UnmuteSuggestion, style: .gradient(UIColor(rgb: 0x1d446c), UIColor(rgb: 0x193e63)), icon: nil, location: .point(point, position), displayDuration: .custom(8.0), shouldDismissOnTouch: { _ in + self.controller?.present(TooltipScreen(account: self.context.account, text: self.presentationData.strings.VoiceChat_UnmuteSuggestion, style: .gradient(UIColor(rgb: 0x1d446c), UIColor(rgb: 0x193e63)), icon: nil, location: .point(point, position), displayDuration: .custom(8.0), shouldDismissOnTouch: { _ in return .dismiss(consume: false) }), in: .window(.root)) } diff --git a/submodules/TelegramCore/Sources/Themes.swift b/submodules/TelegramCore/Sources/Themes.swift index 5c6ab6d937..29cddd16c9 100644 --- a/submodules/TelegramCore/Sources/Themes.swift +++ b/submodules/TelegramCore/Sources/Themes.swift @@ -357,7 +357,7 @@ public func createTheme(account: Account, title: String, resource: MediaResource } } -public func updateTheme(account: Account, accountManager: AccountManager, theme: TelegramTheme, title: String?, slug: String?, resource: MediaResource?, thumbnailData: Data? = nil, settings: TelegramThemeSettings?) -> Signal { +public func updateTheme(account: Account, accountManager: AccountManager, theme: TelegramTheme, title: String?, slug: String?, resource: MediaResource?, thumbnailData: Data? = nil, settings: TelegramThemeSettings?, resetFile: Bool = false) -> Signal { guard title != nil || slug != nil || resource != nil else { return .complete() } @@ -370,6 +370,8 @@ public func updateTheme(account: Account, accountManager: AccountManager mapToSignal { result -> Signal in let inputDocument: Api.InputDocument? - if let status = result { + if resetFile { + inputDocument = .inputDocumentEmpty + } else if let status = result { switch status { case let .complete(file): if let resource = file.resource as? CloudDocumentMediaResource { diff --git a/submodules/TelegramPermissionsUI/BUILD b/submodules/TelegramPermissionsUI/BUILD index ec40edd53e..54bc103cd8 100644 --- a/submodules/TelegramPermissionsUI/BUILD +++ b/submodules/TelegramPermissionsUI/BUILD @@ -26,6 +26,7 @@ swift_library( "//submodules/AppBundle:AppBundle", "//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramPermissionsUI/Sources/PermissionContentNode.swift b/submodules/TelegramPermissionsUI/Sources/PermissionContentNode.swift index 7d3a07c73f..72c94adb4d 100644 --- a/submodules/TelegramPermissionsUI/Sources/PermissionContentNode.swift +++ b/submodules/TelegramPermissionsUI/Sources/PermissionContentNode.swift @@ -2,6 +2,7 @@ import Foundation import UIKit import Display import AsyncDisplayKit +import TelegramCore import TelegramPresentationData import TextFormat import TelegramPermissions @@ -10,7 +11,9 @@ import SolidRoundedButtonNode import PresentationDataUtils import Markdown import AnimatedStickerNode +import TelegramAnimatedStickerNode import AppBundle +import AccountContext public enum PermissionContentIcon: Equatable { case image(UIImage?) @@ -52,7 +55,7 @@ public final class PermissionContentNode: ASDisplayNode { public var validLayout: (CGSize, UIEdgeInsets)? - public init(theme: PresentationTheme, strings: PresentationStrings, kind: Int32, icon: PermissionContentIcon, title: String, subtitle: String? = nil, text: String, buttonTitle: String, secondaryButtonTitle: String? = nil, footerText: String? = nil, buttonAction: @escaping () -> Void, openPrivacyPolicy: (() -> Void)?) { + public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, kind: Int32, icon: PermissionContentIcon, title: String, subtitle: String? = nil, text: String, buttonTitle: String, secondaryButtonTitle: String? = nil, footerText: String? = nil, buttonAction: @escaping () -> Void, openPrivacyPolicy: (() -> Void)?) { self.theme = theme self.kind = kind @@ -70,10 +73,10 @@ public final class PermissionContentNode: ASDisplayNode { if case let .animation(animation) = icon { self.animationNode = AnimatedStickerNode() - if let path = getAppBundle().path(forResource: animation, ofType: "tgs") { - self.animationNode?.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 320, height: 320, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.animationNode?.visibility = true - } + + self.animationNode?.setup(source: AnimatedStickerNodeLocalFileSource(name: animation), width: 320, height: 320, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.animationNode?.visibility = true + self.nearbyIconNode = nil } else if kind == PermissionKind.nearbyLocation.rawValue { self.nearbyIconNode = PeersNearbyIconNode(theme: theme) diff --git a/submodules/TelegramPermissionsUI/Sources/PermissionControllerNode.swift b/submodules/TelegramPermissionsUI/Sources/PermissionControllerNode.swift index d84a4e2e60..538b5a3925 100644 --- a/submodules/TelegramPermissionsUI/Sources/PermissionControllerNode.swift +++ b/submodules/TelegramPermissionsUI/Sources/PermissionControllerNode.swift @@ -207,7 +207,7 @@ final class PermissionControllerNode: ASDisplayNode { hasPrivacyPolicy = false } - let contentNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: dataState.kind.rawValue, icon: .image(icon), title: title, text: text, buttonTitle: buttonTitle, secondaryButtonTitle: nil, buttonAction: { [weak self] in + let contentNode = PermissionContentNode(context: self.context, theme: self.presentationData.theme, strings: self.presentationData.strings, kind: dataState.kind.rawValue, icon: .image(icon), title: title, text: text, buttonTitle: buttonTitle, secondaryButtonTitle: nil, buttonAction: { [weak self] in self?.allow?() }, openPrivacyPolicy: hasPrivacyPolicy ? self.openPrivacyPolicy : nil) self.insertSubnode(contentNode, at: 0) @@ -237,7 +237,7 @@ final class PermissionControllerNode: ASDisplayNode { transition.updateFrame(node: contentNode, frame: contentFrame) contentNode.updateLayout(size: contentFrame.size, insets: insets, transition: transition) } else { - let contentNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: 0, icon: icon, title: title, subtitle: subtitle, text: text, buttonTitle: buttonTitle, secondaryButtonTitle: secondaryButtonTitle, footerText: footerText, buttonAction: { [weak self] in + let contentNode = PermissionContentNode(context: self.context, theme: self.presentationData.theme, strings: self.presentationData.strings, kind: 0, icon: icon, title: title, subtitle: subtitle, text: text, buttonTitle: buttonTitle, secondaryButtonTitle: secondaryButtonTitle, footerText: footerText, buttonAction: { [weak self] in self?.allow?() }, openPrivacyPolicy: secondaryButtonTitle != nil ? { [weak self] in self?.dismiss?() diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index ac2a4bd0aa..5eb378ebec 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -5416,9 +5416,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }, completion: { _ in let _ = (strongSelf.context.engine.peers.reportPeerMessages(messageIds: Array(messageIds), reason: reportReason, message: message) |> deliverOnMainQueue).start(completed: { [weak self] in - if let strongSelf = self, let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") { - strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current) - } + strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current) }) }) })) @@ -7080,9 +7078,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.reportIrrelvantGeoNoticePromise.set(.single(true)) let _ = ApplicationSpecificNotice.setIrrelevantPeerGeoReport(postbox: strongSelf.context.account.postbox, peerId: peerId).start() - if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") { - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .emoji(path: path, text: strongSelf.presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current) - } + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .emoji(name: "PoliceCar", text: strongSelf.presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current) } }) })] @@ -9918,7 +9914,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } - let tooltipScreen = TooltipScreen(text: solution.text, textEntities: solution.entities, icon: .info, location: .top, shouldDismissOnTouch: { point in + let tooltipScreen = TooltipScreen(account: self.context.account, text: solution.text, textEntities: solution.entities, icon: .info, location: .top, shouldDismissOnTouch: { point in return .ignore }, openActiveTextItem: { [weak self] item, action in guard let strongSelf = self else { @@ -10006,7 +10002,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } - let tooltipScreen = TooltipScreen(text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in + let tooltipScreen = TooltipScreen(account: self.context.account, text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in return .ignore }, openActiveTextItem: { [weak self] item, action in guard let strongSelf = self else { @@ -10115,7 +10111,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } - let tooltipScreen = TooltipScreen(text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in + let tooltipScreen = TooltipScreen(account: self.context.account, text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in return .ignore }, openActiveTextItem: { [weak self] item, action in guard let strongSelf = self else { diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 30724f6d0e..45555eeb24 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -22,6 +22,7 @@ import SlotMachineAnimationNode import UniversalMediaPlayer import ShimmerEffect import WallpaperBackgroundNode +import LocalMediaResources import AppBundle private let nameFont = Font.medium(14.0) @@ -407,7 +408,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let telegramDice = self.telegramDice { if telegramDice.emoji == "🎰" { - let animationNode = SlotMachineAnimationNode() + let animationNode = SlotMachineAnimationNode(account: item.context.account) if !item.message.effectivelyIncoming(item.context.account.peerId) { animationNode.success = { [weak self] onlyHaptic in if let strongSelf = self, let item = strongSelf.item { @@ -1290,20 +1291,28 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } private func playAdditionalAnimation(_ name: String) { - guard let path = getAppBundle().path(forResource: name, ofType: "tgs"), let animationSize = self.animationSize, let animationNode = self.animationNode, self.additionalAnimationNodes.count < 4 else { + let source = AnimatedStickerNodeLocalFileSource(name: name) + guard let item = self.item, let path = source.path, let animationSize = self.animationSize, let animationNode = self.animationNode, self.additionalAnimationNodes.count < 4 else { return } + let incoming = item.message.effectivelyIncoming(item.context.account.peerId) + self.supernode?.view.bringSubviewToFront(self.view) - let source = AnimatedStickerNodeLocalFileSource(path: path) + let resource = BundleResource(name: name, path: path) + let pathPrefix = item.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(resource.id) let additionalAnimationNode = AnimatedStickerNode() - additionalAnimationNode.setup(source: source, width: Int(animationSize.width * 3.0), height: Int(animationSize.height * 3.0), playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + additionalAnimationNode.setup(source: source, width: Int(animationSize.width * 3.0), height: Int(animationSize.height * 3.0), playbackMode: .once, mode: .direct(cachePathPrefix: pathPrefix)) additionalAnimationNode.completed = { [weak self, weak additionalAnimationNode] _ in self?.additionalAnimationNodes.removeAll(where: { $0 === additionalAnimationNode }) additionalAnimationNode?.removeFromSupernode() } additionalAnimationNode.frame = animationNode.frame.insetBy(dx: -animationNode.frame.width, dy: -animationNode.frame.height) +// .offsetBy(dx: incoming ? animationNode.frame.width : -animationNode.frame.width, dy: 0.0) + if incoming { + additionalAnimationNode.transform = CATransform3DMakeScale(-1.0, 1.0, 1.0) + } self.addSubnode(additionalAnimationNode) self.additionalAnimationNodes.append(additionalAnimationNode) @@ -1638,11 +1647,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } if let selectionState = item.controllerInteraction.selectionState { - var selected = false - var incoming = true - - selected = selectionState.selectedIds.contains(item.message.id) - incoming = item.message.effectivelyIncoming(item.context.account.peerId) + let selected = selectionState.selectedIds.contains(item.message.id) + let incoming = item.message.effectivelyIncoming(item.context.account.peerId) let offset: CGFloat = incoming ? 42.0 : 0.0 diff --git a/submodules/TelegramUI/Sources/ChatThemeScreen.swift b/submodules/TelegramUI/Sources/ChatThemeScreen.swift index 5a4f4498bd..163f0dac1a 100644 --- a/submodules/TelegramUI/Sources/ChatThemeScreen.swift +++ b/submodules/TelegramUI/Sources/ChatThemeScreen.swift @@ -895,7 +895,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega if let strongSelf = self, count < 3 { Queue.mainQueue().after(1.0) { if !strongSelf.animatedOut { - strongSelf.present?(TooltipScreen(text: strongSelf.presentationData.theme.overallDarkAppearance ? strongSelf.presentationData.strings.Conversation_Theme_SwitchToLight : strongSelf.presentationData.strings.Conversation_Theme_SwitchToDark, style: .default, icon: nil, location: .point(frame.offsetBy(dx: 3.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in + strongSelf.present?(TooltipScreen(account: strongSelf.context.account, text: strongSelf.presentationData.theme.overallDarkAppearance ? strongSelf.presentationData.strings.Conversation_Theme_SwitchToLight : strongSelf.presentationData.strings.Conversation_Theme_SwitchToDark, style: .default, icon: nil, location: .point(frame.offsetBy(dx: 3.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in return .dismiss(consume: false) })) diff --git a/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift b/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift index 0a5a2cdb37..4f689a4b72 100644 --- a/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift +++ b/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift @@ -40,7 +40,7 @@ private func animationItem(account: Account, emojis: Signal<[TelegramMediaFile], let fetched = freeMediaFileInteractiveFetched(account: account, fileReference: .standalone(media: file)) let animationItem = Signal { subscriber in let fetchedDisposable = fetched.start() - let resourceDisposable = (chatMessageAnimationData(postbox: account.postbox, resource: file.resource, fitzModifier: nil, width: Int(fittedSize.width), height: Int(fittedSize.height), synchronousLoad: false) + let resourceDisposable = (chatMessageAnimationData(mediaBox: account.postbox.mediaBox, resource: file.resource, fitzModifier: nil, width: Int(fittedSize.width), height: Int(fittedSize.height), synchronousLoad: false) |> filter { data in return data.complete }).start(next: { next in diff --git a/submodules/TelegramUI/Sources/PrefetchManager.swift b/submodules/TelegramUI/Sources/PrefetchManager.swift index 08dcbcd4dd..c71e394ffe 100644 --- a/submodules/TelegramUI/Sources/PrefetchManager.swift +++ b/submodules/TelegramUI/Sources/PrefetchManager.swift @@ -245,7 +245,7 @@ private final class PrefetchManagerInnerImpl { |> mapToSignal { sticker -> Signal in if let sticker = sticker { let _ = freeMediaFileInteractiveFetched(account: account, fileReference: .standalone(media: sticker)).start() - return chatMessageAnimationData(postbox: account.postbox, resource: sticker.resource, fitzModifier: nil, width: 384, height: 384, synchronousLoad: false) + return chatMessageAnimationData(mediaBox: account.postbox.mediaBox, resource: sticker.resource, fitzModifier: nil, width: 384, height: 384, synchronousLoad: false) |> mapToSignal { _ -> Signal in return .complete() } diff --git a/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift b/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift index 3e06830a34..b3482cbf1e 100644 --- a/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift +++ b/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift @@ -33,6 +33,14 @@ public let telegramAccountAuxiliaryMethods = AccountAuxiliaryMethods(fetchResour return fetchEmojiSpriteResource(account: account, resource: resource) } else if let resource = resource as? VenueIconResource { return fetchVenueIconResource(account: account, resource: resource) + } else if let resource = resource as? BundleResource { + return Signal { subscriber in + subscriber.putNext(.reset) + if let data = try? Data(contentsOf: URL(fileURLWithPath: resource.path), options: .mappedRead) { + subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true)) + } + return EmptyDisposable + } } else if let wallpaperResource = resource as? WallpaperDataResource { let builtinWallpapers: [String] = [ "fqv01SQemVIBAAAApND8LDRUhRU" diff --git a/submodules/TooltipUI/BUILD b/submodules/TooltipUI/BUILD index fe81ac954d..cb1e093076 100644 --- a/submodules/TooltipUI/BUILD +++ b/submodules/TooltipUI/BUILD @@ -15,9 +15,11 @@ swift_library( "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/AppBundle:AppBundle", "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", "//submodules/TelegramCore:TelegramCore", "//submodules/TextFormat:TextFormat", "//submodules/UrlEscaping:UrlEscaping", + "//submodules/AccountContext:AccountContext", ], visibility = [ "//visibility:public", diff --git a/submodules/TooltipUI/Sources/TooltipScreen.swift b/submodules/TooltipUI/Sources/TooltipScreen.swift index 8d595bb935..67e02469f0 100644 --- a/submodules/TooltipUI/Sources/TooltipScreen.swift +++ b/submodules/TooltipUI/Sources/TooltipScreen.swift @@ -4,6 +4,7 @@ import AsyncDisplayKit import Display import TelegramPresentationData import AnimatedStickerNode +import TelegramAnimatedStickerNode import AppBundle import TelegramCore import TextFormat @@ -57,7 +58,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode { private var validLayout: ContainerViewLayout? - init(text: String, textEntities: [MessageTextEntity], style: TooltipScreen.Style, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: TooltipScreen.DisplayDuration, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?) { + init(account: Account, text: String, textEntities: [MessageTextEntity], style: TooltipScreen.Style, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: TooltipScreen.DisplayDuration, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?) { self.tooltipStyle = style self.icon = icon self.customContentNode = customContentNode @@ -198,15 +199,11 @@ private final class TooltipScreenNode: ViewControllerTracingNode { case .none: break case .chatListPress: - if let path = getAppBundle().path(forResource: "ChatListFoldersTooltip", ofType: "json") { - self.animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: Int(70 * UIScreenScale), height: Int(70 * UIScreenScale), playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.animatedStickerNode.automaticallyLoadFirstFrame = true - } + self.animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ChatListFoldersTooltip"), width: Int(70 * UIScreenScale), height: Int(70 * UIScreenScale), playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.animatedStickerNode.automaticallyLoadFirstFrame = true case .info: - if let path = getAppBundle().path(forResource: "anim_infotip", ofType: "json") { - self.animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: Int(70 * UIScreenScale), height: Int(70 * UIScreenScale), playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.animatedStickerNode.automaticallyLoadFirstFrame = true - } + self.animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "anim_infotip"), width: Int(70 * UIScreenScale), height: Int(70 * UIScreenScale), playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.animatedStickerNode.automaticallyLoadFirstFrame = true } super.init() @@ -559,6 +556,7 @@ public final class TooltipScreen: ViewController { case gradient(UIColor, UIColor) } + private let account: Account public let text: String public let textEntities: [MessageTextEntity] private let style: TooltipScreen.Style @@ -582,7 +580,8 @@ public final class TooltipScreen: ViewController { private var dismissTimer: Foundation.Timer? - public init(text: String, textEntities: [MessageTextEntity] = [], style: TooltipScreen.Style = .default, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: DisplayDuration = .default, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)? = nil) { + public init(account: Account, text: String, textEntities: [MessageTextEntity] = [], style: TooltipScreen.Style = .default, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: DisplayDuration = .default, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)? = nil) { + self.account = account self.text = text self.textEntities = textEntities self.style = style @@ -647,7 +646,7 @@ public final class TooltipScreen: ViewController { } override public func loadDisplayNode() { - self.displayNode = TooltipScreenNode(text: self.text, textEntities: self.textEntities, style: self.style, icon: self.icon, customContentNode: self.customContentNode, location: self.location, displayDuration: self.displayDuration, inset: self.inset, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in + self.displayNode = TooltipScreenNode(account: self.account, text: self.text, textEntities: self.textEntities, style: self.style, icon: self.icon, customContentNode: self.customContentNode, location: self.location, displayDuration: self.displayDuration, inset: self.inset, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in guard let strongSelf = self else { return } diff --git a/submodules/UndoUI/Sources/UndoOverlayController.swift b/submodules/UndoUI/Sources/UndoOverlayController.swift index 71d5ec6c68..d9e96ec777 100644 --- a/submodules/UndoUI/Sources/UndoOverlayController.swift +++ b/submodules/UndoUI/Sources/UndoOverlayController.swift @@ -13,7 +13,7 @@ public enum UndoOverlayContent { case revealedArchive(title: String, text: String, undo: Bool) case succeed(text: String) case info(text: String) - case emoji(path: String, text: String) + case emoji(name: String, text: String) case swipeToReply(title: String, text: String) case actionSucceeded(title: String, text: String, cancel: String) case stickersModified(title: String, text: String, undo: Bool, info: StickerPackCollectionInfo, topItem: ItemCollectionItem?, context: AccountContext) diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index f22d8dc8a3..7801fced47 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -303,14 +303,14 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { displayUndo = undo self.originalRemainingSeconds = 5 - case let .emoji(path, text): + case let .emoji(name, text): self.avatarNode = nil self.iconNode = nil self.iconCheckNode = nil self.animationNode = nil self.animatedStickerNode = AnimatedStickerNode() self.animatedStickerNode?.visibility = true - self.animatedStickerNode?.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 100, height: 100, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.animatedStickerNode?.setup(source: AnimatedStickerNodeLocalFileSource(name: name), width: 100, height: 100, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -447,7 +447,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { } if dice.emoji == "🎰" { - let slotMachineNode = SlotMachineAnimationNode(size: CGSize(width: 42.0, height: 42.0)) + let slotMachineNode = SlotMachineAnimationNode(account: context.account, size: CGSize(width: 42.0, height: 42.0)) self.slotMachineNode = slotMachineNode slotMachineNode.setState(.rolling) @@ -714,10 +714,9 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { let animatedStickerNode = AnimatedStickerNode() self.animatedStickerNode = animatedStickerNode - if let path = getAppBundle().path(forResource: "anim_savemedia", ofType: "tgs") { - animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 80, height: 80, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - animatedStickerNode.visibility = true - } + + animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "anim_savemedia"), width: 80, height: 80, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + animatedStickerNode.visibility = true let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)