mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various Improvements
This commit is contained in:
parent
6f2c7cf03b
commit
4393227307
@ -775,24 +775,6 @@ public protocol AnimatedStickerNodeSource {
|
||||
func directDataPath() -> Signal<String, NoError>
|
||||
}
|
||||
|
||||
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<String, NoError> {
|
||||
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()
|
||||
|
@ -29,6 +29,7 @@ swift_library(
|
||||
"//submodules/ContextUI:ContextUI",
|
||||
"//submodules/TelegramBaseController:TelegramBaseController",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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?()
|
||||
|
@ -52,6 +52,8 @@ swift_library(
|
||||
"//submodules/SectionHeaderItem:SectionHeaderItem",
|
||||
"//submodules/DirectionalPanGesture:DirectionalPanGesture",
|
||||
"//submodules/ShimmerEffect:ShimmerEffect",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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()
|
||||
|
||||
|
@ -14,6 +14,7 @@ swift_library(
|
||||
"//submodules/Postbox:Postbox",
|
||||
"//submodules/TelegramCore:TelegramCore",
|
||||
"//submodules/ImageCompression:ImageCompression",
|
||||
"//submodules/PersistentStringHash:PersistentStringHash",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}))
|
||||
})
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -71,6 +71,8 @@ swift_library(
|
||||
"//submodules/ChatListFilterSettingsHeaderItem:ChatListFilterSettingsHeaderItem",
|
||||
"//submodules/InviteLinksUI:InviteLinksUI",
|
||||
"//submodules/UIKitRuntimeUtils:UIKitRuntimeUtils",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -30,6 +30,7 @@ swift_library(
|
||||
"//submodules/Geocoding:Geocoding",
|
||||
"//submodules/AppBundle:AppBundle",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
|
||||
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
|
||||
"//submodules/TelegramNotices:TelegramNotices",
|
||||
],
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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<MediaResourceData, NoError> {
|
||||
public func chatMessageAnimationData(mediaBox: MediaBox, resource: MediaResource, fitzModifier: EmojiFitzModifier? = nil, width: Int, height: Int, synchronousLoad: Bool) -> Signal<MediaResourceData, NoError> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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<String, NoError> {
|
||||
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
|
||||
}
|
||||
|
@ -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)
|
||||
}))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ public func createTheme(account: Account, title: String, resource: MediaResource
|
||||
}
|
||||
}
|
||||
|
||||
public func updateTheme(account: Account, accountManager: AccountManager<TelegramAccountManagerTypes>, theme: TelegramTheme, title: String?, slug: String?, resource: MediaResource?, thumbnailData: Data? = nil, settings: TelegramThemeSettings?) -> Signal<CreateThemeResult, CreateThemeError> {
|
||||
public func updateTheme(account: Account, accountManager: AccountManager<TelegramAccountManagerTypes>, theme: TelegramTheme, title: String?, slug: String?, resource: MediaResource?, thumbnailData: Data? = nil, settings: TelegramThemeSettings?, resetFile: Bool = false) -> Signal<CreateThemeResult, CreateThemeError> {
|
||||
guard title != nil || slug != nil || resource != nil else {
|
||||
return .complete()
|
||||
}
|
||||
@ -370,6 +370,8 @@ public func updateTheme(account: Account, accountManager: AccountManager<Telegra
|
||||
}
|
||||
if let _ = resource {
|
||||
flags |= 1 << 2
|
||||
} else if resetFile {
|
||||
flags |= 1 << 2
|
||||
}
|
||||
var inputSettings: Api.InputThemeSettings?
|
||||
if let settings = settings {
|
||||
@ -389,7 +391,9 @@ public func updateTheme(account: Account, accountManager: AccountManager<Telegra
|
||||
}
|
||||
|> mapToSignal { result -> Signal<CreateThemeResult, CreateThemeError> 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 {
|
||||
|
@ -26,6 +26,7 @@ swift_library(
|
||||
"//submodules/AppBundle:AppBundle",
|
||||
"//submodules/PresentationDataUtils:PresentationDataUtils",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -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)
|
||||
|
@ -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?()
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
}))
|
||||
|
||||
|
@ -40,7 +40,7 @@ private func animationItem(account: Account, emojis: Signal<[TelegramMediaFile],
|
||||
let fetched = freeMediaFileInteractiveFetched(account: account, fileReference: .standalone(media: file))
|
||||
let animationItem = Signal<ManagedAnimationItem?, NoError> { 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
|
||||
|
@ -245,7 +245,7 @@ private final class PrefetchManagerInnerImpl {
|
||||
|> mapToSignal { sticker -> Signal<Void, NoError> 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<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user