mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-08 19:10:53 +00:00
Update API
This commit is contained in:
parent
5bbc508c1a
commit
15b708791d
@ -7077,3 +7077,7 @@ Sorry for the inconvenience.";
|
||||
"AuthSessions.View.AcceptSecretChatsInfo" = "You can disable the acception of incoming secret chats on this device.";
|
||||
|
||||
"Conversation.SendMesageAs" = "Send Message As...";
|
||||
"Conversation.InviteRequestAdminGroup" = "%1$@ is an admin of %2$@, a group you requested to join.";
|
||||
"Conversation.InviteRequestAdminChannel" = "%1$@ is an admin of %2$@, a channel you requested to join.";
|
||||
"Conversation.InviteRequestInfo" = "You received this message because you requested to join %1$@ on %2$@.";
|
||||
"Conversation.InviteRequestInfoConfirm" = "I understand";
|
||||
|
@ -110,56 +110,56 @@ final class ItemListRecentSessionItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
func iconForSession(_ session: RecentAccountSession) -> (UIImage?, String?) {
|
||||
func iconForSession(_ session: RecentAccountSession) -> (UIImage?, UIColor?, String?, [String: UIColor]?) {
|
||||
let platform = session.platform.lowercased()
|
||||
let device = session.deviceModel.lowercased()
|
||||
let systemVersion = session.systemVersion.lowercased()
|
||||
if device.contains("xbox") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Xbox"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Xbox"), UIColor(rgb: 0x35c759), nil, nil)
|
||||
}
|
||||
if device.contains("chrome") && !device.contains("chromebook") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Chrome"), "device_chrome")
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Chrome"), UIColor(rgb: 0x35c759), "device_chrome", nil)
|
||||
}
|
||||
if device.contains("brave") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Brave"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Brave"), UIColor(rgb: 0xff9500), nil, nil)
|
||||
}
|
||||
if device.contains("vivaldi") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Vivaldi"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Vivaldi"), UIColor(rgb: 0xff3c30), nil, nil)
|
||||
}
|
||||
if device.contains("safari") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Safari"), "device_safari")
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Safari"), UIColor(rgb: 0x0079ff), "device_safari", nil)
|
||||
}
|
||||
if device.contains("firefox") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Firefox"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Firefox"), UIColor(rgb: 0xff9500), "device_firefox", nil)
|
||||
}
|
||||
if device.contains("opera") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Opera"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Opera"), UIColor(rgb: 0xff3c30), nil, nil)
|
||||
}
|
||||
if platform.contains("android") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Android"), "device_android")
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Android"), UIColor(rgb: 0x35c759), "device_android", nil)
|
||||
}
|
||||
if device.contains("iphone") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/iPhone"), "device_iphone")
|
||||
return (UIImage(bundleImageName: "Settings/Devices/iPhone"), UIColor(rgb: 0x0079ff), "device_iphone", nil)
|
||||
}
|
||||
if device.contains("ipad") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/iPad"), "device_ipad")
|
||||
return (UIImage(bundleImageName: "Settings/Devices/iPad"), UIColor(rgb: 0x0079ff), "device_ipad", nil)
|
||||
}
|
||||
if (platform.contains("macos") || systemVersion.contains("macos")) && device.contains("mac") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Mac"), "device_mac")
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Mac"), UIColor(rgb: 0x0079ff), "device_mac", nil)
|
||||
}
|
||||
if platform.contains("ios") || platform.contains("macos") || systemVersion.contains("macos") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/iOS"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/iOS"), UIColor(rgb: 0x0079ff), nil, nil)
|
||||
}
|
||||
if platform.contains("ubuntu") || systemVersion.contains("ubuntu") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Ubuntu"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Ubuntu"), UIColor(rgb: 0xff9500), "device_ubuntu", nil)
|
||||
}
|
||||
if platform.contains("linux") || systemVersion.contains("linux") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Linux"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Linux"), UIColor(rgb: 0x8e8e93), "device_linux", nil)
|
||||
}
|
||||
if platform.contains("windows") || systemVersion.contains("windows") {
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Windows"), nil)
|
||||
return (UIImage(bundleImageName: "Settings/Devices/Windows"), UIColor(rgb: 0x0079ff), "device_windows", nil)
|
||||
}
|
||||
return (nil, nil)
|
||||
return (nil, nil, nil, nil)
|
||||
}
|
||||
|
||||
private func trimmedLocationName(_ session: RecentAccountSession) -> String {
|
||||
|
@ -30,7 +30,10 @@ private final class RecentSessionsControllerArguments {
|
||||
let openOtherAppsUrl: () -> Void
|
||||
let setupAuthorizationTTL: () -> Void
|
||||
|
||||
init(context: AccountContext, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void, terminateOtherSessions: @escaping () -> Void, openSession: @escaping (RecentAccountSession) -> Void, openWebSession: @escaping (WebAuthorization, Peer?) -> Void, removeWebSession: @escaping (Int64) -> Void, terminateAllWebSessions: @escaping () -> Void, addDevice: @escaping () -> Void, openOtherAppsUrl: @escaping () -> Void, setupAuthorizationTTL: @escaping () -> Void) {
|
||||
let openDesktopLink: () -> Void
|
||||
let openWebLink: () -> Void
|
||||
|
||||
init(context: AccountContext, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void, terminateOtherSessions: @escaping () -> Void, openSession: @escaping (RecentAccountSession) -> Void, openWebSession: @escaping (WebAuthorization, Peer?) -> Void, removeWebSession: @escaping (Int64) -> Void, terminateAllWebSessions: @escaping () -> Void, addDevice: @escaping () -> Void, openOtherAppsUrl: @escaping () -> Void, setupAuthorizationTTL: @escaping () -> Void, openDesktopLink: @escaping () -> Void, openWebLink: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.setSessionIdWithRevealedOptions = setSessionIdWithRevealedOptions
|
||||
self.removeSession = removeSession
|
||||
@ -47,6 +50,9 @@ private final class RecentSessionsControllerArguments {
|
||||
self.openOtherAppsUrl = openOtherAppsUrl
|
||||
|
||||
self.setupAuthorizationTTL = setupAuthorizationTTL
|
||||
|
||||
self.openDesktopLink = openDesktopLink
|
||||
self.openWebLink = openWebLink
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +62,7 @@ private enum RecentSessionsMode: Int {
|
||||
}
|
||||
|
||||
private enum RecentSessionsSection: Int32 {
|
||||
case header
|
||||
case currentSession
|
||||
case pendingSessions
|
||||
case otherSessions
|
||||
@ -82,6 +89,7 @@ private struct SortIndex: Comparable {
|
||||
}
|
||||
|
||||
private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
case header(SortIndex, String)
|
||||
case currentSessionHeader(SortIndex, String)
|
||||
case currentSession(SortIndex, PresentationStrings, PresentationDateTimeFormat, RecentAccountSession)
|
||||
case terminateOtherSessions(SortIndex, String)
|
||||
@ -101,6 +109,8 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
|
||||
var section: ItemListSectionId {
|
||||
switch self {
|
||||
case .header:
|
||||
return RecentSessionsSection.header.rawValue
|
||||
case .currentSessionHeader, .currentSession, .terminateOtherSessions, .terminateAllWebSessions, .currentAddDevice, .currentSessionInfo:
|
||||
return RecentSessionsSection.currentSession.rawValue
|
||||
case .pendingSessionsHeader, .pendingSession, .pendingSessionsInfo:
|
||||
@ -114,28 +124,30 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
|
||||
var stableId: RecentSessionsEntryStableId {
|
||||
switch self {
|
||||
case .currentSessionHeader:
|
||||
case .header:
|
||||
return .index(0)
|
||||
case .currentSession:
|
||||
case .currentSessionHeader:
|
||||
return .index(1)
|
||||
case .terminateOtherSessions:
|
||||
case .currentSession:
|
||||
return .index(2)
|
||||
case .terminateAllWebSessions:
|
||||
case .terminateOtherSessions:
|
||||
return .index(3)
|
||||
case .currentAddDevice:
|
||||
case .terminateAllWebSessions:
|
||||
return .index(4)
|
||||
case .currentSessionInfo:
|
||||
case .currentAddDevice:
|
||||
return .index(5)
|
||||
case .pendingSessionsHeader:
|
||||
case .currentSessionInfo:
|
||||
return .index(6)
|
||||
case .pendingSessionsHeader:
|
||||
return .index(7)
|
||||
case let .pendingSession(_, _, _, _, session, _, _, _):
|
||||
return .session(session.hash)
|
||||
case .pendingSessionsInfo:
|
||||
return .index(7)
|
||||
case .otherSessionsHeader:
|
||||
return .index(8)
|
||||
case .addDevice:
|
||||
case .otherSessionsHeader:
|
||||
return .index(9)
|
||||
case .addDevice:
|
||||
return .index(10)
|
||||
case let .session(_, _, _, _, session, _, _, _):
|
||||
return .session(session.hash)
|
||||
case let .website(_, _, _, _, _, website, _, _, _, _):
|
||||
@ -143,14 +155,16 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
case .devicesInfo:
|
||||
return .devicesInfo
|
||||
case .ttlHeader:
|
||||
return .index(10)
|
||||
case .ttlTimeout:
|
||||
return .index(11)
|
||||
case .ttlTimeout:
|
||||
return .index(12)
|
||||
}
|
||||
}
|
||||
|
||||
var sortIndex: SortIndex {
|
||||
switch self {
|
||||
case let .header(index, _):
|
||||
return index
|
||||
case let .currentSessionHeader(index, _):
|
||||
return index
|
||||
case let .currentSession(index, _, _, _):
|
||||
@ -188,6 +202,12 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
|
||||
static func ==(lhs: RecentSessionsEntry, rhs: RecentSessionsEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .header(lhsSortIndex, lhsText):
|
||||
if case let .header(rhsSortIndex, rhsText) = rhs, lhsSortIndex == rhsSortIndex, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .currentSessionHeader(lhsSortIndex, lhsText):
|
||||
if case let .currentSessionHeader(rhsSortIndex, rhsText) = rhs, lhsSortIndex == rhsSortIndex, lhsText == rhsText {
|
||||
return true
|
||||
@ -294,6 +314,10 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! RecentSessionsControllerArguments
|
||||
switch self {
|
||||
case let .header(_, text):
|
||||
return RecentSessionsHeaderItem(context: arguments.context, theme: presentationData.theme, text: text, animationName: "Requests", sectionId: self.section, linkAction: { _ in
|
||||
arguments.openDesktopLink()
|
||||
})
|
||||
case let .currentSessionHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .currentSession(_, _, dateTimeFormat, session):
|
||||
@ -735,6 +759,10 @@ public func recentSessionsController(context: AccountContext, activeSessionsCont
|
||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||
])
|
||||
presentControllerImpl?(controller, nil)
|
||||
}, openDesktopLink: {
|
||||
|
||||
}, openWebLink: {
|
||||
|
||||
})
|
||||
|
||||
let previousMode = Atomic<RecentSessionsMode>(value: .sessions)
|
||||
|
@ -0,0 +1,169 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import AnimatedStickerNode
|
||||
import TelegramAnimatedStickerNode
|
||||
import AccountContext
|
||||
import Markdown
|
||||
import TextFormat
|
||||
|
||||
class RecentSessionsHeaderItem: ListViewItem, ItemListItem {
|
||||
let context: AccountContext
|
||||
let theme: PresentationTheme
|
||||
let text: String
|
||||
let animationName: String
|
||||
let sectionId: ItemListSectionId
|
||||
let linkAction: ((ItemListTextItemLinkAction) -> Void)?
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, text: String, animationName: String, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.text = text
|
||||
self.animationName = animationName
|
||||
self.sectionId = sectionId
|
||||
self.linkAction = linkAction
|
||||
}
|
||||
|
||||
func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||
async {
|
||||
let node = RecentSessionsHeaderItemNode()
|
||||
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
|
||||
node.contentSize = layout.contentSize
|
||||
node.insets = layout.insets
|
||||
|
||||
Queue.mainQueue().async {
|
||||
completion(node, {
|
||||
return (nil, { _ in apply() })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
||||
Queue.mainQueue().async {
|
||||
guard let nodeValue = node() as? RecentSessionsHeaderItemNode else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
let makeLayout = nodeValue.asyncLayout()
|
||||
|
||||
async {
|
||||
let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
Queue.mainQueue().async {
|
||||
completion(layout, { _ in
|
||||
apply()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(13.0)
|
||||
|
||||
class RecentSessionsHeaderItemNode: ListViewItemNode {
|
||||
private let titleNode: TextNode
|
||||
private var animationNode: AnimatedStickerNode
|
||||
|
||||
private var item: RecentSessionsHeaderItem?
|
||||
|
||||
init() {
|
||||
self.titleNode = TextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
self.titleNode.contentMode = .left
|
||||
self.titleNode.contentsScale = UIScreen.main.scale
|
||||
|
||||
self.animationNode = AnimatedStickerNode()
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.animationNode)
|
||||
}
|
||||
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
||||
recognizer.tapActionAtPoint = { _ in
|
||||
return .waitForSingleTap
|
||||
}
|
||||
self.view.addGestureRecognizer(recognizer)
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: RecentSessionsHeaderItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
|
||||
return { item, params, neighbors in
|
||||
let leftInset: CGFloat = 32.0 + params.leftInset
|
||||
let topInset: CGFloat = 92.0
|
||||
|
||||
let attributedText = parseMarkdownIntoAttributedString(item.text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.freeTextColor), link: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.itemAccentColor), linkAttribute: { contents in
|
||||
return (TelegramTextAttributes.URL, contents)
|
||||
}))
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let contentSize = CGSize(width: params.width, height: topInset + titleLayout.size.height)
|
||||
let insets = itemListNeighborsGroupedInsets(neighbors, params)
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
|
||||
return (layout, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
if strongSelf.item == nil {
|
||||
strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: item.animationName), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
|
||||
strongSelf.animationNode.visibility = true
|
||||
}
|
||||
strongSelf.item = item
|
||||
strongSelf.accessibilityLabel = attributedText.string
|
||||
|
||||
let iconSize = CGSize(width: 96.0, height: 96.0)
|
||||
strongSelf.animationNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: -10.0), size: iconSize)
|
||||
strongSelf.animationNode.updateLayout(size: iconSize)
|
||||
|
||||
let _ = titleApply()
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleLayout.size.width) / 2.0), y: topInset + 8.0), size: titleLayout.size)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
||||
}
|
||||
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
@objc private func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
||||
switch recognizer.state {
|
||||
case .ended:
|
||||
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
|
||||
switch gesture {
|
||||
case .tap:
|
||||
let titleFrame = self.titleNode.frame
|
||||
if let item = self.item, titleFrame.contains(location) {
|
||||
if let (_, attributes) = self.titleNode.attributesAtPoint(CGPoint(x: location.x - titleFrame.minX, y: location.y - titleFrame.minY)) {
|
||||
if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||
item.linkAction?(.tap(url))
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
@ -162,6 +162,7 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let contentBackgroundNode: ASDisplayNode
|
||||
private var iconNode: ASImageNode?
|
||||
private var animationBackgroundNode: ASDisplayNode?
|
||||
private var animationNode: AnimationNode?
|
||||
private var avatarNode: AvatarNode?
|
||||
private let titleNode: ImmediateTextNode
|
||||
@ -304,10 +305,17 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
location = session.country
|
||||
ip = session.ip
|
||||
|
||||
let (icon, animationName) = iconForSession(session)
|
||||
let (icon, backgroundColor, animationName, colors) = iconForSession(session)
|
||||
if let animationName = animationName {
|
||||
let animationNode = AnimationNode(animation: animationName, colors: [:], scale: 1.0)
|
||||
let animationNode = AnimationNode(animation: animationName, colors: colors ?? ["apple.apple.Заливка 1": backgroundColor ?? .black], scale: 1.0)
|
||||
self.animationNode = animationNode
|
||||
|
||||
animationNode.animationView()?.logHierarchyKeypaths()
|
||||
|
||||
let animationBackgroundNode = ASDisplayNode()
|
||||
animationBackgroundNode.cornerRadius = 20.0
|
||||
animationBackgroundNode.backgroundColor = backgroundColor
|
||||
self.animationBackgroundNode = animationBackgroundNode
|
||||
} else if let icon = icon {
|
||||
let iconNode = ASImageNode()
|
||||
iconNode.displaysAsynchronously = false
|
||||
@ -424,6 +432,7 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
self.topContentContainerNode.addSubnode(self.cancelButton)
|
||||
|
||||
self.iconNode.flatMap { self.contentContainerNode.addSubnode($0) }
|
||||
self.animationBackgroundNode.flatMap { self.contentContainerNode.addSubnode($0) }
|
||||
self.animationNode.flatMap { self.contentContainerNode.addSubnode($0) }
|
||||
self.avatarNode.flatMap { self.contentContainerNode.addSubnode($0) }
|
||||
|
||||
@ -469,6 +478,10 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
|
||||
let ipGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleIpLongPress(_:)))
|
||||
self.ipValueNode.view.addGestureRecognizer(ipGestureRecognizer)
|
||||
|
||||
if let animationNode = self.animationNode {
|
||||
animationNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.animationPressed)))
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func handleTitleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||||
@ -560,6 +573,12 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
self.terminateButton.updateTheme(SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemBlocksBackgroundColor, foregroundColor: self.presentationData.theme.list.itemDestructiveColor))
|
||||
}
|
||||
|
||||
@objc func animationPressed() {
|
||||
if let animationNode = self.animationNode, !animationNode.isPlaying {
|
||||
animationNode.playOnce()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func cancelButtonPressed() {
|
||||
self.animateOut()
|
||||
}
|
||||
@ -637,6 +656,7 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let isFirstTime = self.containerLayout == nil
|
||||
self.containerLayout = (layout, navigationBarHeight)
|
||||
|
||||
var insets = layout.insets(options: [.statusBar, .input])
|
||||
@ -655,9 +675,17 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
|
||||
if let iconNode = self.iconNode {
|
||||
transition.updateFrame(node: iconNode, frame: iconFrame)
|
||||
} else if let animationNode = self.animationNode {
|
||||
} else if let animationNode = self.animationNode, let animationBackgroundNode = self.animationBackgroundNode {
|
||||
transition.updateFrame(node: animationNode, frame: iconFrame)
|
||||
animationNode.loop()
|
||||
transition.updateFrame(node: animationBackgroundNode, frame: iconFrame)
|
||||
if #available(iOS 13.0, *) {
|
||||
animationBackgroundNode.layer.cornerCurve = .continuous
|
||||
}
|
||||
if isFirstTime {
|
||||
Queue.mainQueue().after(0.5) {
|
||||
animationNode.playOnce()
|
||||
}
|
||||
}
|
||||
} else if let avatarNode = self.avatarNode {
|
||||
transition.updateFrame(node: avatarNode, frame: iconFrame)
|
||||
}
|
||||
@ -715,7 +743,7 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
|
||||
var contentHeight = locationInfoTextFrame.maxY + bottomInset + 64.0
|
||||
|
||||
if case .session = self.subject {
|
||||
if let _ = self.secretChatsBackgroundNode.supernode {
|
||||
let secretFrame = CGRect(x: inset, y: locationInfoTextFrame.maxY + 59.0, width: width - inset * 2.0, height: fieldItemHeight)
|
||||
transition.updateFrame(node: self.secretChatsBackgroundNode, frame: secretFrame)
|
||||
|
||||
|
@ -6,6 +6,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[571523412] = { return $0.readDouble() }
|
||||
dict[-1255641564] = { return parseString($0) }
|
||||
dict[-1240849242] = { return Api.messages.StickerSet.parse_stickerSet($0) }
|
||||
dict[-738646805] = { return Api.messages.StickerSet.parse_stickerSetNotModified($0) }
|
||||
dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) }
|
||||
dict[-711498484] = { return Api.GroupCall.parse_groupCall($0) }
|
||||
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
|
||||
@ -106,7 +107,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[483104362] = { return Api.RichText.parse_textPhone($0) }
|
||||
dict[136105807] = { return Api.RichText.parse_textImage($0) }
|
||||
dict[894777186] = { return Api.RichText.parse_textAnchor($0) }
|
||||
dict[-694681851] = { return Api.UserFull.parse_userFull($0) }
|
||||
dict[-123513441] = { return Api.UserFull.parse_userFull($0) }
|
||||
dict[-292807034] = { return Api.InputChannel.parse_inputChannelEmpty($0) }
|
||||
dict[-212145112] = { return Api.InputChannel.parse_inputChannel($0) }
|
||||
dict[1536380829] = { return Api.InputChannel.parse_inputChannelFromMessage($0) }
|
||||
@ -318,6 +319,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-376962181] = { return Api.KeyboardButton.parse_inputKeyboardButtonUserProfile($0) }
|
||||
dict[814112961] = { return Api.KeyboardButton.parse_keyboardButtonUserProfile($0) }
|
||||
dict[383348795] = { return Api.ContactStatus.parse_contactStatus($0) }
|
||||
dict[997004590] = { return Api.users.UserFull.parse_userFull($0) }
|
||||
dict[1679398724] = { return Api.SecureFile.parse_secureFileEmpty($0) }
|
||||
dict[-534283678] = { return Api.SecureFile.parse_secureFile($0) }
|
||||
dict[-199313886] = { return Api.account.Themes.parse_themesNotModified($0) }
|
||||
@ -529,6 +531,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-6249322] = { return Api.InputStickerSetItem.parse_inputStickerSetItem($0) }
|
||||
dict[-1728664459] = { return Api.help.PromoData.parse_promoDataEmpty($0) }
|
||||
dict[-1942390465] = { return Api.help.PromoData.parse_promoData($0) }
|
||||
dict[1753266509] = { return Api.messages.PeerSettings.parse_peerSettings($0) }
|
||||
dict[-1613493288] = { return Api.NotifyPeer.parse_notifyPeer($0) }
|
||||
dict[-1261946036] = { return Api.NotifyPeer.parse_notifyUsers($0) }
|
||||
dict[-1073230141] = { return Api.NotifyPeer.parse_notifyChats($0) }
|
||||
@ -617,7 +620,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1682413576] = { return Api.messages.Messages.parse_channelMessages($0) }
|
||||
dict[1951620897] = { return Api.messages.Messages.parse_messagesNotModified($0) }
|
||||
dict[215516896] = { return Api.Invoice.parse_invoice($0) }
|
||||
dict[1933519201] = { return Api.PeerSettings.parse_peerSettings($0) }
|
||||
dict[-1474130642] = { return Api.PeerSettings.parse_peerSettings($0) }
|
||||
dict[1577067778] = { return Api.auth.SentCode.parse_sentCode($0) }
|
||||
dict[480546647] = { return Api.InputChatPhoto.parse_inputChatPhotoEmpty($0) }
|
||||
dict[-968723890] = { return Api.InputChatPhoto.parse_inputChatUploadedPhoto($0) }
|
||||
@ -1137,6 +1140,8 @@ public struct Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.ContactStatus:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.users.UserFull:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SecureFile:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.account.Themes:
|
||||
@ -1303,6 +1308,8 @@ public struct Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.help.PromoData:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.PeerSettings:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.NotifyPeer:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputPrivacyKey:
|
||||
|
@ -2,6 +2,7 @@ public extension Api {
|
||||
public struct messages {
|
||||
public enum StickerSet: TypeConstructorDescription {
|
||||
case stickerSet(set: Api.StickerSet, packs: [Api.StickerPack], documents: [Api.Document])
|
||||
case stickerSetNotModified
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -20,6 +21,12 @@ public struct messages {
|
||||
for item in documents {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .stickerSetNotModified:
|
||||
if boxed {
|
||||
buffer.appendInt32(-738646805)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -28,6 +35,8 @@ public struct messages {
|
||||
switch self {
|
||||
case .stickerSet(let set, let packs, let documents):
|
||||
return ("stickerSet", [("set", set), ("packs", packs), ("documents", documents)])
|
||||
case .stickerSetNotModified:
|
||||
return ("stickerSetNotModified", [])
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +63,9 @@ public struct messages {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_stickerSetNotModified(_ reader: BufferReader) -> StickerSet? {
|
||||
return Api.messages.StickerSet.stickerSetNotModified
|
||||
}
|
||||
|
||||
}
|
||||
public enum ArchivedStickers: TypeConstructorDescription {
|
||||
@ -1199,6 +1211,62 @@ public struct messages {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum PeerSettings: TypeConstructorDescription {
|
||||
case peerSettings(settings: Api.PeerSettings, chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .peerSettings(let settings, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(1753266509)
|
||||
}
|
||||
settings.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .peerSettings(let settings, let chats, let users):
|
||||
return ("peerSettings", [("settings", settings), ("chats", chats), ("users", users)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_peerSettings(_ reader: BufferReader) -> PeerSettings? {
|
||||
var _1: Api.PeerSettings?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.PeerSettings
|
||||
}
|
||||
var _2: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _3: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.messages.PeerSettings.peerSettings(settings: _1!, chats: _2!, users: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum SearchCounter: TypeConstructorDescription {
|
||||
case searchCounter(flags: Int32, filter: Api.MessagesFilter, count: Int32)
|
||||
|
@ -2924,16 +2924,16 @@ public extension Api {
|
||||
|
||||
}
|
||||
public enum UserFull: TypeConstructorDescription {
|
||||
case userFull(flags: Int32, user: Api.User, about: String?, settings: Api.PeerSettings, profilePhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?)
|
||||
case userFull(flags: Int32, id: Int64, about: String?, settings: Api.PeerSettings, profilePhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .userFull(let flags, let user, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon):
|
||||
case .userFull(let flags, let id, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon):
|
||||
if boxed {
|
||||
buffer.appendInt32(-694681851)
|
||||
buffer.appendInt32(-123513441)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
user.serialize(buffer, true)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(about!, buffer: buffer, boxed: false)}
|
||||
settings.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 2) != 0 {profilePhoto!.serialize(buffer, true)}
|
||||
@ -2950,18 +2950,16 @@ public extension Api {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .userFull(let flags, let user, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon):
|
||||
return ("userFull", [("flags", flags), ("user", user), ("about", about), ("settings", settings), ("profilePhoto", profilePhoto), ("notifySettings", notifySettings), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("commonChatsCount", commonChatsCount), ("folderId", folderId), ("ttlPeriod", ttlPeriod), ("themeEmoticon", themeEmoticon)])
|
||||
case .userFull(let flags, let id, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon):
|
||||
return ("userFull", [("flags", flags), ("id", id), ("about", about), ("settings", settings), ("profilePhoto", profilePhoto), ("notifySettings", notifySettings), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("commonChatsCount", commonChatsCount), ("folderId", folderId), ("ttlPeriod", ttlPeriod), ("themeEmoticon", themeEmoticon)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_userFull(_ reader: BufferReader) -> UserFull? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.User?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.User
|
||||
}
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) }
|
||||
var _4: Api.PeerSettings?
|
||||
@ -3003,7 +3001,7 @@ public extension Api {
|
||||
let _c11 = (Int(_1!) & Int(1 << 14) == 0) || _11 != nil
|
||||
let _c12 = (Int(_1!) & Int(1 << 15) == 0) || _12 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 {
|
||||
return Api.UserFull.userFull(flags: _1!, user: _2!, about: _3, settings: _4!, profilePhoto: _5, notifySettings: _6!, botInfo: _7, pinnedMsgId: _8, commonChatsCount: _9!, folderId: _10, ttlPeriod: _11, themeEmoticon: _12)
|
||||
return Api.UserFull.userFull(flags: _1!, id: _2!, about: _3, settings: _4!, profilePhoto: _5, notifySettings: _6!, botInfo: _7, pinnedMsgId: _8, commonChatsCount: _9!, folderId: _10, ttlPeriod: _11, themeEmoticon: _12)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -15758,24 +15756,26 @@ public extension Api {
|
||||
|
||||
}
|
||||
public enum PeerSettings: TypeConstructorDescription {
|
||||
case peerSettings(flags: Int32, geoDistance: Int32?)
|
||||
case peerSettings(flags: Int32, geoDistance: Int32?, requestChat: Api.Peer?, requestChatDate: Int32?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .peerSettings(let flags, let geoDistance):
|
||||
case .peerSettings(let flags, let geoDistance, let requestChat, let requestChatDate):
|
||||
if boxed {
|
||||
buffer.appendInt32(1933519201)
|
||||
buffer.appendInt32(-1474130642)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 6) != 0 {serializeInt32(geoDistance!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 9) != 0 {requestChat!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 9) != 0 {serializeInt32(requestChatDate!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .peerSettings(let flags, let geoDistance):
|
||||
return ("peerSettings", [("flags", flags), ("geoDistance", geoDistance)])
|
||||
case .peerSettings(let flags, let geoDistance, let requestChat, let requestChatDate):
|
||||
return ("peerSettings", [("flags", flags), ("geoDistance", geoDistance), ("requestChat", requestChat), ("requestChatDate", requestChatDate)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -15784,10 +15784,18 @@ public extension Api {
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
if Int(_1!) & Int(1 << 6) != 0 {_2 = reader.readInt32() }
|
||||
var _3: Api.Peer?
|
||||
if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
} }
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 9) != 0 {_4 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 6) == 0) || _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.PeerSettings.peerSettings(flags: _1!, geoDistance: _2)
|
||||
let _c3 = (Int(_1!) & Int(1 << 9) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 9) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.PeerSettings.peerSettings(flags: _1!, geoDistance: _2, requestChat: _3, requestChatDate: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -1379,6 +1379,66 @@ public struct auth {
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
public struct users {
|
||||
public enum UserFull: TypeConstructorDescription {
|
||||
case userFull(fullUser: Api.UserFull, chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .userFull(let fullUser, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(997004590)
|
||||
}
|
||||
fullUser.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .userFull(let fullUser, let chats, let users):
|
||||
return ("userFull", [("fullUser", fullUser), ("chats", chats), ("users", users)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_userFull(_ reader: BufferReader) -> UserFull? {
|
||||
var _1: Api.UserFull?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.UserFull
|
||||
}
|
||||
var _2: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _3: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.users.UserFull.userFull(fullUser: _1!, chats: _2!, users: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
public struct contacts {
|
||||
public enum Blocked: TypeConstructorDescription {
|
||||
case blocked(blocked: [Api.PeerBlocked], chats: [Api.Chat], users: [Api.User])
|
||||
|
@ -2245,15 +2245,15 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func getPeerSettings(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.PeerSettings>) {
|
||||
public static func getPeerSettings(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.PeerSettings>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(913498268)
|
||||
buffer.appendInt32(-270948702)
|
||||
peer.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "messages.getPeerSettings", parameters: [("peer", peer)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.PeerSettings? in
|
||||
return (FunctionDescription(name: "messages.getPeerSettings", parameters: [("peer", peer)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.PeerSettings? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.PeerSettings?
|
||||
var result: Api.messages.PeerSettings?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.PeerSettings
|
||||
result = Api.parse(reader, signature: signature) as? Api.messages.PeerSettings
|
||||
}
|
||||
return result
|
||||
})
|
||||
@ -2659,11 +2659,12 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func getStickerSet(stickerset: Api.InputStickerSet) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.StickerSet>) {
|
||||
public static func getStickerSet(stickerset: Api.InputStickerSet, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.StickerSet>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(639215886)
|
||||
buffer.appendInt32(-928977804)
|
||||
stickerset.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "messages.getStickerSet", parameters: [("stickerset", stickerset)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in
|
||||
serializeInt32(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getStickerSet", parameters: [("stickerset", stickerset), ("hash", hash)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.StickerSet?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -5732,15 +5733,15 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func getFullUser(id: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.UserFull>) {
|
||||
public static func getFullUser(id: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.users.UserFull>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-902781519)
|
||||
buffer.appendInt32(-1240508136)
|
||||
id.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "users.getFullUser", parameters: [("id", id)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UserFull? in
|
||||
return (FunctionDescription(name: "users.getFullUser", parameters: [("id", id)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.users.UserFull? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.UserFull?
|
||||
var result: Api.users.UserFull?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.UserFull
|
||||
result = Api.parse(reader, signature: signature) as? Api.users.UserFull
|
||||
}
|
||||
return result
|
||||
})
|
||||
|
@ -6,7 +6,7 @@ import SwiftSignalKit
|
||||
extension PeerStatusSettings {
|
||||
init(apiSettings: Api.PeerSettings) {
|
||||
switch apiSettings {
|
||||
case let .peerSettings(flags, geoDistance):
|
||||
case let .peerSettings(flags, geoDistance, requestChat, requestChatDate):
|
||||
var result = PeerStatusSettings.Flags()
|
||||
if (flags & (1 << 1)) != 0 {
|
||||
result.insert(.canAddContact)
|
||||
@ -32,7 +32,7 @@ extension PeerStatusSettings {
|
||||
if (flags & (1 << 8)) != 0 {
|
||||
result.insert(.suggestAddMembers)
|
||||
}
|
||||
self = PeerStatusSettings(flags: result, geoDistance: geoDistance)
|
||||
self = PeerStatusSettings(flags: result, geoDistance: geoDistance, requestChatPeerId: requestChat?.peerId, requestChatDate: requestChatDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3302,65 +3302,63 @@ func replayFinalState(
|
||||
let namespace: ItemCollectionId.Namespace
|
||||
var items: [ItemCollectionItem] = []
|
||||
let info: StickerPackCollectionInfo
|
||||
switch apiSet {
|
||||
case let .stickerSet(set, packs, documents):
|
||||
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||
for pack in packs {
|
||||
switch pack {
|
||||
case let .stickerPack(text, fileIds):
|
||||
let key = ValueBoxKey(text).toMemoryBuffer()
|
||||
for fileId in fileIds {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if indexKeysByFile[mediaId] == nil {
|
||||
indexKeysByFile[mediaId] = [key]
|
||||
} else {
|
||||
indexKeysByFile[mediaId]!.append(key)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for apiDocument in documents {
|
||||
if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id {
|
||||
let fileIndexKeys: [MemoryBuffer]
|
||||
if let indexKeys = indexKeysByFile[id] {
|
||||
fileIndexKeys = indexKeys
|
||||
if case let .stickerSet(set, packs, documents) = apiSet {
|
||||
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||
for pack in packs {
|
||||
switch pack {
|
||||
case let .stickerPack(text, fileIds):
|
||||
let key = ValueBoxKey(text).toMemoryBuffer()
|
||||
for fileId in fileIds {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if indexKeysByFile[mediaId] == nil {
|
||||
indexKeysByFile[mediaId] = [key]
|
||||
} else {
|
||||
fileIndexKeys = []
|
||||
indexKeysByFile[mediaId]!.append(key)
|
||||
}
|
||||
items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: fileIndexKeys))
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
switch set {
|
||||
case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _):
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
namespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||
} else {
|
||||
namespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info = StickerPackCollectionInfo(apiSet: set, namespace: namespace)
|
||||
}
|
||||
for apiDocument in documents {
|
||||
if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id {
|
||||
let fileIndexKeys: [MemoryBuffer]
|
||||
if let indexKeys = indexKeysByFile[id] {
|
||||
fileIndexKeys = indexKeys
|
||||
} else {
|
||||
fileIndexKeys = []
|
||||
}
|
||||
items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: fileIndexKeys))
|
||||
}
|
||||
}
|
||||
switch set {
|
||||
case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _):
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
namespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||
} else {
|
||||
namespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||
}
|
||||
}
|
||||
|
||||
info = StickerPackCollectionInfo(apiSet: set, namespace: namespace)
|
||||
|
||||
if namespace == Namespaces.ItemCollection.CloudMaskPacks && syncMasks {
|
||||
continue loop
|
||||
} else if namespace == Namespaces.ItemCollection.CloudStickerPacks && syncStickers {
|
||||
continue loop
|
||||
if namespace == Namespaces.ItemCollection.CloudMaskPacks && syncMasks {
|
||||
continue loop
|
||||
} else if namespace == Namespaces.ItemCollection.CloudStickerPacks && syncStickers {
|
||||
continue loop
|
||||
}
|
||||
|
||||
var updatedInfos = transaction.getItemCollectionsInfos(namespace: info.id.namespace).map { $0.1 as! StickerPackCollectionInfo }
|
||||
if let index = updatedInfos.firstIndex(where: { $0.id == info.id }) {
|
||||
let currentInfo = updatedInfos[index]
|
||||
updatedInfos.remove(at: index)
|
||||
updatedInfos.insert(currentInfo, at: 0)
|
||||
} else {
|
||||
updatedInfos.insert(info, at: 0)
|
||||
transaction.replaceItemCollectionItems(collectionId: info.id, items: items)
|
||||
}
|
||||
transaction.replaceItemCollectionInfos(namespace: info.id.namespace, itemCollectionInfos: updatedInfos.map { ($0.id, $0) })
|
||||
}
|
||||
|
||||
var updatedInfos = transaction.getItemCollectionsInfos(namespace: info.id.namespace).map { $0.1 as! StickerPackCollectionInfo }
|
||||
if let index = updatedInfos.firstIndex(where: { $0.id == info.id }) {
|
||||
let currentInfo = updatedInfos[index]
|
||||
updatedInfos.remove(at: index)
|
||||
updatedInfos.insert(currentInfo, at: 0)
|
||||
} else {
|
||||
updatedInfos.insert(info, at: 0)
|
||||
transaction.replaceItemCollectionItems(collectionId: info.id, items: items)
|
||||
}
|
||||
transaction.replaceItemCollectionInfos(namespace: info.id.namespace, itemCollectionInfos: updatedInfos.map { ($0.id, $0) })
|
||||
case let .reorder(namespace, ids):
|
||||
let collectionNamespace: ItemCollectionId.Namespace
|
||||
switch namespace {
|
||||
|
@ -1110,7 +1110,7 @@ public final class AccountViewTracker {
|
||||
var requests: [Signal<Api.messages.StickerSet?, NoError>] = []
|
||||
for reference in stickerPacks {
|
||||
if case let .id(id, accessHash) = reference {
|
||||
requests.append(account.network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(id: id, accessHash: accessHash)))
|
||||
requests.append(account.network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(id: id, accessHash: accessHash), hash: 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.StickerSet?, NoError> in
|
||||
return .single(nil)
|
||||
@ -1235,7 +1235,7 @@ public final class AccountViewTracker {
|
||||
return
|
||||
}
|
||||
let queue = self.queue
|
||||
context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox), _internal_fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in
|
||||
context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, accountPeerId: account.peerId, network: account.network, postbox: account.postbox), _internal_fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in
|
||||
queue.async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -1250,7 +1250,7 @@ public final class AccountViewTracker {
|
||||
}
|
||||
}
|
||||
|
||||
private func updateCachedPeerData(peerId: PeerId, viewId: Int32, hasCachedData: Bool) {
|
||||
private func updateCachedPeerData(peerId: PeerId, accountPeerId: PeerId, viewId: Int32, hasCachedData: Bool) {
|
||||
self.queue.async {
|
||||
let context: PeerCachedDataContext
|
||||
var dataUpdated = false
|
||||
@ -1277,7 +1277,7 @@ public final class AccountViewTracker {
|
||||
return
|
||||
}
|
||||
let queue = self.queue
|
||||
context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox), _internal_fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in
|
||||
context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, accountPeerId: accountPeerId, network: account.network, postbox: account.postbox), _internal_fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in
|
||||
queue.async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -1551,6 +1551,7 @@ public final class AccountViewTracker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return withState(signal, { [weak self] () -> Int32 in
|
||||
if let strongSelf = self {
|
||||
return OSAtomicIncrement32(&strongSelf.nextViewId)
|
||||
@ -1558,8 +1559,8 @@ public final class AccountViewTracker {
|
||||
return -1
|
||||
}
|
||||
}, next: { [weak self] next, viewId in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateCachedPeerData(peerId: peerId, viewId: viewId, hasCachedData: next.cachedData != nil)
|
||||
if let strongSelf = self, let account = strongSelf.account {
|
||||
strongSelf.updateCachedPeerData(peerId: peerId, accountPeerId: account.peerId, viewId: viewId, hasCachedData: next.cachedData != nil)
|
||||
}
|
||||
}, disposed: { [weak self] viewId in
|
||||
if let strongSelf = self {
|
||||
|
@ -139,11 +139,13 @@ private enum SynchronizeInstalledStickerPacksError {
|
||||
}
|
||||
|
||||
private func fetchStickerPack(network: Network, info: StickerPackCollectionInfo) -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem]), NoError> {
|
||||
return network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash)))
|
||||
return network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash), hash: 0))
|
||||
|> map { result -> (StickerPackCollectionInfo, [ItemCollectionItem]) in
|
||||
var items: [ItemCollectionItem] = []
|
||||
var updatedInfo = info
|
||||
switch result {
|
||||
case .stickerSetNotModified:
|
||||
break
|
||||
case let .stickerSet(stickerSet, packs, documents):
|
||||
updatedInfo = StickerPackCollectionInfo(apiSet: stickerSet, namespace: info.id.namespace)
|
||||
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||
|
@ -65,13 +65,15 @@ public func addSavedSticker(postbox: Postbox, network: Network, file: TelegramMe
|
||||
break
|
||||
}
|
||||
if let fetchReference = fetchReference {
|
||||
return network.request(Api.functions.messages.getStickerSet(stickerset: fetchReference.apiInputStickerSet))
|
||||
return network.request(Api.functions.messages.getStickerSet(stickerset: fetchReference.apiInputStickerSet, hash: 0))
|
||||
|> mapError { _ -> AddSavedStickerError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Void, AddSavedStickerError> in
|
||||
var stickerStringRepresentations: [String]?
|
||||
switch result {
|
||||
case .stickerSetNotModified:
|
||||
break
|
||||
case let .stickerSet(_, packs, _):
|
||||
var stringRepresentationsByFile: [MediaId: [String]] = [:]
|
||||
for pack in packs {
|
||||
|
@ -64,7 +64,7 @@ public final class CachedUserData: CachedPeerData {
|
||||
public let autoremoveTimeout: CachedPeerAutoremoveTimeout
|
||||
public let themeEmoticon: String?
|
||||
|
||||
public let peerIds = Set<PeerId>()
|
||||
public let peerIds: Set<PeerId>
|
||||
public let messageIds: Set<MessageId>
|
||||
public let associatedHistoryMessageId: MessageId? = nil
|
||||
|
||||
@ -82,6 +82,7 @@ public final class CachedUserData: CachedPeerData {
|
||||
self.hasScheduledMessages = false
|
||||
self.autoremoveTimeout = .unknown
|
||||
self.themeEmoticon = nil
|
||||
self.peerIds = Set()
|
||||
self.messageIds = Set()
|
||||
}
|
||||
|
||||
@ -100,6 +101,12 @@ public final class CachedUserData: CachedPeerData {
|
||||
self.autoremoveTimeout = autoremoveTimeout
|
||||
self.themeEmoticon = themeEmoticon
|
||||
|
||||
var peerIds = Set<PeerId>()
|
||||
if let requestChatPeerId = peerStatusSettings?.requestChatPeerId {
|
||||
peerIds.insert(requestChatPeerId)
|
||||
}
|
||||
self.peerIds = peerIds
|
||||
|
||||
var messageIds = Set<MessageId>()
|
||||
if let pinnedMessageId = self.pinnedMessageId {
|
||||
messageIds.insert(pinnedMessageId)
|
||||
@ -132,6 +139,12 @@ public final class CachedUserData: CachedPeerData {
|
||||
self.autoremoveTimeout = decoder.decodeObjectForKey("artv", decoder: CachedPeerAutoremoveTimeout.init(decoder:)) as? CachedPeerAutoremoveTimeout ?? .unknown
|
||||
self.themeEmoticon = decoder.decodeOptionalStringForKey("te")
|
||||
|
||||
var peerIds = Set<PeerId>()
|
||||
if let requestChatPeerId = self.peerStatusSettings?.requestChatPeerId {
|
||||
peerIds.insert(requestChatPeerId)
|
||||
}
|
||||
self.peerIds = peerIds
|
||||
|
||||
var messageIds = Set<MessageId>()
|
||||
if let pinnedMessageId = self.pinnedMessageId {
|
||||
messageIds.insert(pinnedMessageId)
|
||||
|
@ -21,20 +21,28 @@ public struct PeerStatusSettings: PostboxCoding, Equatable {
|
||||
|
||||
public var flags: PeerStatusSettings.Flags
|
||||
public var geoDistance: Int32?
|
||||
public var requestChatPeerId: PeerId?
|
||||
public var requestChatDate: Int32?
|
||||
|
||||
public init() {
|
||||
self.flags = PeerStatusSettings.Flags()
|
||||
self.geoDistance = nil
|
||||
self.requestChatPeerId = nil
|
||||
self.requestChatDate = nil
|
||||
}
|
||||
|
||||
public init(flags: PeerStatusSettings.Flags, geoDistance: Int32? = nil) {
|
||||
public init(flags: PeerStatusSettings.Flags, geoDistance: Int32? = nil, requestChatPeerId: PeerId? = nil, requestChatDate: Int32? = nil) {
|
||||
self.flags = flags
|
||||
self.geoDistance = geoDistance
|
||||
self.requestChatPeerId = requestChatPeerId
|
||||
self.requestChatDate = requestChatDate
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.flags = Flags(rawValue: decoder.decodeInt32ForKey("flags", orElse: 0))
|
||||
self.geoDistance = decoder.decodeOptionalInt32ForKey("geoDistance")
|
||||
self.requestChatPeerId = decoder.decodeOptionalInt64ForKey("requestChatPeerId").map { PeerId($0) }
|
||||
self.requestChatDate = decoder.decodeOptionalInt32ForKey("requestChatDate")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
@ -44,6 +52,16 @@ public struct PeerStatusSettings: PostboxCoding, Equatable {
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "geoDistance")
|
||||
}
|
||||
if let requestChatPeerId = self.requestChatPeerId {
|
||||
encoder.encodeInt64(requestChatPeerId.toInt64(), forKey: "requestChatPeerId")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "requestPeerId")
|
||||
}
|
||||
if let requestChatDate = self.requestChatDate {
|
||||
encoder.encodeInt32(requestChatDate, forKey: "requestChatDate")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "requestChatDate")
|
||||
}
|
||||
}
|
||||
|
||||
public func contains(_ member: PeerStatusSettings.Flags) -> Bool {
|
||||
|
@ -3,7 +3,7 @@ import Postbox
|
||||
import TelegramApi
|
||||
import SwiftSignalKit
|
||||
|
||||
func fetchAndUpdateSupplementalCachedPeerData(peerId rawPeerId: PeerId, network: Network, postbox: Postbox) -> Signal<Bool, NoError> {
|
||||
func fetchAndUpdateSupplementalCachedPeerData(peerId rawPeerId: PeerId, accountPeerId: PeerId, network: Network, postbox: Postbox) -> Signal<Bool, NoError> {
|
||||
return postbox.combinedView(keys: [.basicPeer(rawPeerId)])
|
||||
|> mapToSignal { views -> Signal<Peer, NoError> in
|
||||
guard let view = views.views[.basicPeer(rawPeerId)] as? BasicPeerView else {
|
||||
@ -78,9 +78,33 @@ func fetchAndUpdateSupplementalCachedPeerData(peerId rawPeerId: PeerId, network:
|
||||
return network.request(Api.functions.messages.getPeerSettings(peer: inputPeer))
|
||||
|> retryRequest
|
||||
|> mapToSignal { peerSettings -> Signal<Bool, NoError> in
|
||||
let peerStatusSettings = PeerStatusSettings(apiSettings: peerSettings)
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
|
||||
let peerStatusSettings: PeerStatusSettings
|
||||
switch peerSettings {
|
||||
case let .peerSettings(settings, chats, users):
|
||||
peerStatusSettings = PeerStatusSettings(apiSettings: settings)
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Bool in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
|
||||
transaction.updatePeerCachedData(peerIds: Set([peer.id]), update: { _, current in
|
||||
switch peer.id.namespace {
|
||||
case Namespaces.Peer.CloudUser:
|
||||
@ -171,46 +195,67 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
|> mapToSignal { result -> Signal<Bool, NoError> in
|
||||
return postbox.transaction { transaction -> Bool in
|
||||
switch result {
|
||||
case let .userFull(_, userFullUser, _, _, _, userFullNotifySettings, _, _, _, _, _, _):
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(userFullUser.peerId) as? TelegramUser, rhs: userFullUser) {
|
||||
updatePeers(transaction: transaction, peers: [telegramUser], update: { _, updated -> Peer in
|
||||
case let .userFull(fullUser, chats, users):
|
||||
var accountUser: Api.User?
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
}
|
||||
if telegramUser.id == accountPeerId {
|
||||
accountUser = user
|
||||
}
|
||||
}
|
||||
|
||||
switch fullUser {
|
||||
case let .userFull(_, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _):
|
||||
updatePeers(transaction: transaction, peers: peers, update: { previous, updated -> Peer in
|
||||
if previous?.id == accountPeerId, let accountUser = accountUser, let user = TelegramUser.merge(previous as? TelegramUser, rhs: accountUser) {
|
||||
return user
|
||||
}
|
||||
return updated
|
||||
})
|
||||
transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: userFullNotifySettings)])
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
}
|
||||
transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: userFullNotifySettings)])
|
||||
if let presence = TelegramUserPresence(apiUser: userFullUser) {
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: [userFullUser.peerId: presence])
|
||||
}
|
||||
}
|
||||
transaction.updatePeerCachedData(peerIds: [peerId], update: { peerId, current in
|
||||
let previous: CachedUserData
|
||||
if let current = current as? CachedUserData {
|
||||
previous = current
|
||||
} else {
|
||||
previous = CachedUserData()
|
||||
}
|
||||
switch result {
|
||||
case let .userFull(userFullFlags, _, userFullAbout, userFullSettings, _, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon):
|
||||
let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:))
|
||||
let isBlocked = (userFullFlags & (1 << 0)) != 0
|
||||
let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0
|
||||
let videoCallsAvailable = (userFullFlags & (1 << 13)) != 0
|
||||
transaction.updatePeerCachedData(peerIds: [peerId], update: { peerId, current in
|
||||
let previous: CachedUserData
|
||||
if let current = current as? CachedUserData {
|
||||
previous = current
|
||||
} else {
|
||||
previous = CachedUserData()
|
||||
}
|
||||
switch fullUser {
|
||||
case let .userFull(userFullFlags, _, userFullAbout, userFullSettings, _, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon):
|
||||
let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:))
|
||||
let isBlocked = (userFullFlags & (1 << 0)) != 0
|
||||
let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0
|
||||
let videoCallsAvailable = (userFullFlags & (1 << 13)) != 0
|
||||
|
||||
let callsPrivate = (userFullFlags & (1 << 5)) != 0
|
||||
let canPinMessages = (userFullFlags & (1 << 7)) != 0
|
||||
let pinnedMessageId = userFullPinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
|
||||
let callsPrivate = (userFullFlags & (1 << 5)) != 0
|
||||
let canPinMessages = (userFullFlags & (1 << 7)) != 0
|
||||
let pinnedMessageId = userFullPinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
|
||||
|
||||
let peerStatusSettings = PeerStatusSettings(apiSettings: userFullSettings)
|
||||
|
||||
let hasScheduledMessages = (userFullFlags & 1 << 12) != 0
|
||||
|
||||
let autoremoveTimeout: CachedPeerAutoremoveTimeout = .known(CachedPeerAutoremoveTimeout.Value(userFullTtlPeriod))
|
||||
|
||||
let peerStatusSettings = PeerStatusSettings(apiSettings: userFullSettings)
|
||||
|
||||
let hasScheduledMessages = (userFullFlags & 1 << 12) != 0
|
||||
|
||||
let autoremoveTimeout: CachedPeerAutoremoveTimeout = .known(CachedPeerAutoremoveTimeout.Value(userFullTtlPeriod))
|
||||
|
||||
return previous.withUpdatedAbout(userFullAbout).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(userFullCommonChatsCount).withUpdatedIsBlocked(isBlocked).withUpdatedVoiceCallsAvailable(voiceCallsAvailable).withUpdatedVideoCallsAvailable(videoCallsAvailable).withUpdatedCallsPrivate(callsPrivate).withUpdatedCanPinMessages(canPinMessages).withUpdatedPeerStatusSettings(peerStatusSettings).withUpdatedPinnedMessageId(pinnedMessageId).withUpdatedHasScheduledMessages(hasScheduledMessages)
|
||||
.withUpdatedAutoremoveTimeout(autoremoveTimeout)
|
||||
.withUpdatedThemeEmoticon(userFullThemeEmoticon)
|
||||
}
|
||||
})
|
||||
return previous.withUpdatedAbout(userFullAbout).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(userFullCommonChatsCount).withUpdatedIsBlocked(isBlocked).withUpdatedVoiceCallsAvailable(voiceCallsAvailable).withUpdatedVideoCallsAvailable(videoCallsAvailable).withUpdatedCallsPrivate(callsPrivate).withUpdatedCanPinMessages(canPinMessages).withUpdatedPeerStatusSettings(peerStatusSettings).withUpdatedPinnedMessageId(pinnedMessageId).withUpdatedHasScheduledMessages(hasScheduledMessages)
|
||||
.withUpdatedAutoremoveTimeout(autoremoveTimeout)
|
||||
.withUpdatedThemeEmoticon(userFullThemeEmoticon)
|
||||
}
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -153,6 +153,8 @@ func _internal_createStickerSet(account: Account, title: String, shortName: Stri
|
||||
var items: [StickerPackItem] = []
|
||||
|
||||
switch result {
|
||||
case .stickerSetNotModified:
|
||||
return .complete()
|
||||
case let .stickerSet(set, packs, documents):
|
||||
let namespace: ItemCollectionId.Namespace
|
||||
switch set {
|
||||
|
@ -3,7 +3,6 @@ import Postbox
|
||||
import TelegramApi
|
||||
import SwiftSignalKit
|
||||
|
||||
|
||||
extension StickerPackReference {
|
||||
init(_ stickerPackInfo: StickerPackCollectionInfo) {
|
||||
self = .id(id: stickerPackInfo.id.id, accessHash: stickerPackInfo.accessHash)
|
||||
@ -32,7 +31,7 @@ public enum LoadedStickerPack {
|
||||
}
|
||||
|
||||
func updatedRemoteStickerPack(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal<(StickerPackCollectionInfo, [StickerPackItem])?, NoError> {
|
||||
return network.request(Api.functions.messages.getStickerSet(stickerset: reference.apiInputStickerSet))
|
||||
return network.request(Api.functions.messages.getStickerSet(stickerset: reference.apiInputStickerSet, hash: 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.StickerSet?, NoError> in
|
||||
return .single(nil)
|
||||
@ -45,6 +44,8 @@ func updatedRemoteStickerPack(postbox: Postbox, network: Network, reference: Sti
|
||||
let info: StickerPackCollectionInfo
|
||||
var items: [StickerPackItem] = []
|
||||
switch result {
|
||||
case .stickerSetNotModified:
|
||||
return .complete()
|
||||
case let .stickerSet(set, packs, documents):
|
||||
let namespace: ItemCollectionId.Namespace
|
||||
switch set {
|
||||
|
@ -51,53 +51,55 @@ func _internal_requestStickerSet(postbox: Postbox, network: Network, reference:
|
||||
}
|
||||
}
|
||||
|
||||
let remoteSignal = network.request(Api.functions.messages.getStickerSet(stickerset: input))
|
||||
|> mapError { _ -> RequestStickerSetError in
|
||||
return .invalid
|
||||
}
|
||||
|> map { result -> RequestStickerSetResult in
|
||||
var items: [ItemCollectionItem] = []
|
||||
let info: ItemCollectionInfo
|
||||
let installed: Bool
|
||||
switch result {
|
||||
case let .stickerSet(set, packs, documents):
|
||||
info = StickerPackCollectionInfo(apiSet: set, namespace: Namespaces.ItemCollection.CloudStickerPacks)
|
||||
|
||||
switch set {
|
||||
case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _):
|
||||
installed = (flags & (1 << 0) != 0)
|
||||
}
|
||||
|
||||
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||
for pack in packs {
|
||||
switch pack {
|
||||
case let .stickerPack(text, fileIds):
|
||||
let key = ValueBoxKey(text).toMemoryBuffer()
|
||||
for fileId in fileIds {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if indexKeysByFile[mediaId] == nil {
|
||||
indexKeysByFile[mediaId] = [key]
|
||||
} else {
|
||||
indexKeysByFile[mediaId]!.append(key)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for apiDocument in documents {
|
||||
if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id {
|
||||
let fileIndexKeys: [MemoryBuffer]
|
||||
if let indexKeys = indexKeysByFile[id] {
|
||||
fileIndexKeys = indexKeys
|
||||
let remoteSignal = network.request(Api.functions.messages.getStickerSet(stickerset: input, hash: 0))
|
||||
|> mapError { _ -> RequestStickerSetError in
|
||||
return .invalid
|
||||
}
|
||||
|> mapToSignal { result -> Signal<RequestStickerSetResult, RequestStickerSetError> in
|
||||
var items: [ItemCollectionItem] = []
|
||||
let info: ItemCollectionInfo
|
||||
let installed: Bool
|
||||
switch result {
|
||||
case .stickerSetNotModified:
|
||||
return .complete()
|
||||
case let .stickerSet(set, packs, documents):
|
||||
info = StickerPackCollectionInfo(apiSet: set, namespace: Namespaces.ItemCollection.CloudStickerPacks)
|
||||
|
||||
switch set {
|
||||
case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _):
|
||||
installed = (flags & (1 << 0) != 0)
|
||||
}
|
||||
|
||||
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||
for pack in packs {
|
||||
switch pack {
|
||||
case let .stickerPack(text, fileIds):
|
||||
let key = ValueBoxKey(text).toMemoryBuffer()
|
||||
for fileId in fileIds {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if indexKeysByFile[mediaId] == nil {
|
||||
indexKeysByFile[mediaId] = [key]
|
||||
} else {
|
||||
fileIndexKeys = []
|
||||
indexKeysByFile[mediaId]!.append(key)
|
||||
}
|
||||
items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: fileIndexKeys))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return .remote(info: info, items: items, installed: installed)
|
||||
}
|
||||
|
||||
for apiDocument in documents {
|
||||
if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id {
|
||||
let fileIndexKeys: [MemoryBuffer]
|
||||
if let indexKeys = indexKeysByFile[id] {
|
||||
fileIndexKeys = indexKeys
|
||||
} else {
|
||||
fileIndexKeys = []
|
||||
}
|
||||
items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: fileIndexKeys))
|
||||
}
|
||||
}
|
||||
}
|
||||
return .single(.remote(info: info, items: items, installed: installed))
|
||||
}
|
||||
|
||||
if let collectionId = collectionId {
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"v":"5.7.4","fr":60,"ip":0,"op":180,"w":30,"h":30,"nm":"safari_30","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Com 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[185]},{"t":150,"s":[180]}],"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.15,0.205],[-0.233,0.543],[0,0],[0.142,0.444],[0.385,0.123],[1.435,-0.615],[0,0],[0.231,-0.17],[0.15,-0.205],[0.233,-0.543],[0,0],[-0.142,-0.444],[-0.385,-0.123],[-1.435,0.615],[0,0],[-0.231,0.17]],"o":[[0.17,-0.231],[0,0],[0.615,-1.435],[-0.123,-0.385],[-0.444,-0.142],[0,0],[-0.543,0.233],[-0.205,0.15],[-0.17,0.231],[0,0],[-0.615,1.435],[0.123,0.385],[0.444,0.142],[0,0],[0.543,-0.233],[0.205,-0.15]],"v":[[2.611,2.075],[3.13,1.029],[4.28,-1.654],[5.061,-4.251],[4.251,-5.061],[1.654,-4.28],[-1.029,-3.13],[-2.075,-2.611],[-2.611,-2.075],[-3.13,-1.029],[-4.28,1.654],[-5.061,4.251],[-4.251,5.061],[-1.654,4.28],[1.029,3.13],[2.075,2.611]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"d":1,"ty":"el","s":{"a":0,"k":[2.5,2.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Контур эллипса 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"mm","mm":3,"nm":"Объединить контуры 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.478431373835,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Com 2","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":290,"st":110,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Com 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Контур эллипса 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Com 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":290,"st":110,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Block","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.671,-1.317],[0,-3.92],[0,0],[-0.763,-1.497],[-1.317,-0.671],[-3.92,0],[0,0],[-1.497,0.763],[-0.671,1.317],[0,3.92],[0,0],[0.763,1.497],[1.317,0.671],[3.92,0],[0,0],[1.497,-0.763]],"o":[[-0.763,1.497],[0,0],[0,3.92],[0.671,1.317],[1.497,0.763],[0,0],[3.92,0],[1.317,-0.671],[0.763,-1.497],[0,0],[0,-3.92],[-0.671,-1.317],[-1.497,-0.763],[0,0],[-3.92,0],[-1.317,0.671]],"v":[[-14.237,-11.178],[-15,-3.8],[-15,3.8],[-14.237,11.178],[-11.178,14.237],[-3.8,15],[3.8,15],[11.178,14.237],[14.237,11.178],[15,3.8],[15,-3.8],[14.237,-11.178],[11.178,-14.237],[3.8,-15],[-3.8,-15],[-11.178,-14.237]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.478431373835,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Block","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":290,"st":110,"bm":0}],"markers":[]}
|
||||
{"v":"5.7.4","fr":60,"ip":0,"op":120,"w":30,"h":30,"nm":"safari_30","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Com 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[185]},{"t":30,"s":[180]}],"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.15,0.205],[-0.233,0.543],[0,0],[0.142,0.444],[0.385,0.123],[1.435,-0.615],[0,0],[0.231,-0.17],[0.15,-0.205],[0.233,-0.543],[0,0],[-0.142,-0.444],[-0.385,-0.123],[-1.435,0.615],[0,0],[-0.231,0.17]],"o":[[0.17,-0.231],[0,0],[0.615,-1.435],[-0.123,-0.385],[-0.444,-0.142],[0,0],[-0.543,0.233],[-0.205,0.15],[-0.17,0.231],[0,0],[-0.615,1.435],[0.123,0.385],[0.444,0.142],[0,0],[0.543,-0.233],[0.205,-0.15]],"v":[[2.611,2.075],[3.13,1.029],[4.28,-1.654],[5.061,-4.251],[4.251,-5.061],[1.654,-4.28],[-1.029,-3.13],[-2.075,-2.611],[-2.611,-2.075],[-3.13,-1.029],[-4.28,1.654],[-5.061,4.251],[-4.251,5.061],[-1.654,4.28],[1.029,3.13],[2.075,2.611]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"d":1,"ty":"el","s":{"a":0,"k":[2.5,2.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Контур эллипса 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"mm","mm":3,"nm":"Объединить контуры 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Com 2","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":-10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Com 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Контур эллипса 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Com 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":-10,"bm":0}],"markers":[]}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
{"v":"5.7.4","fr":60,"ip":0,"op":120,"w":30,"h":30,"nm":"windows_30","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Union","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[15]},{"i":{"x":[0.833],"y":[0.889]},"o":{"x":[0.333],"y":[0]},"t":25,"s":[12.5]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.222]},"t":35,"s":[15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":55,"s":[17.5]},{"t":70,"s":[15]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[15]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":25,"s":[15]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":35,"s":[15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":55,"s":[15]},{"t":70,"s":[15]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-1,11],[-1,1],[-12.667,1],[-12.667,-1],[-1,-1],[-1,-11],[1,-11],[1,-1],[12.667,-1],[12.667,1],[1,1],[1,11]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Union","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":-60,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Rectangle 23","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[9,-9],[9,9],[-9,9],[-9,-9]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[9,-10.667],[9,10.667],[-10.667,5.667],[-10.667,-5.667]],"c":true}]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[9,-9],[9,9],[-9,9],[-9,-9]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[10.667,-5.667],[10.667,5.667],[-9,10.667],[-9,-10.667]],"c":true}]},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[9,-9],[9,9],[-9,9],[-9,-9]],"c":true}]}],"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Rectangle 23","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":-60,"bm":0}],"markers":[]}
|
@ -3367,7 +3367,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
var contactStatus: ChatContactStatus?
|
||||
if let peer = peerView.peers[peerView.peerId] {
|
||||
if let cachedData = peerView.cachedData as? CachedUserData {
|
||||
contactStatus = ChatContactStatus(canAddContact: !peerView.peerIsContact, canReportIrrelevantLocation: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: nil)
|
||||
var requestChatPeer: Peer?
|
||||
if let requestChatPeerId = cachedData.peerStatusSettings?.requestChatPeerId {
|
||||
if let peer = peerView.peers[requestChatPeerId] {
|
||||
requestChatPeer = peer
|
||||
}
|
||||
}
|
||||
contactStatus = ChatContactStatus(canAddContact: !peerView.peerIsContact, canReportIrrelevantLocation: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: nil, requestChatPeer: requestChatPeer)
|
||||
} else if let cachedData = peerView.cachedData as? CachedGroupData {
|
||||
var invitedBy: Peer?
|
||||
if let invitedByPeerId = cachedData.invitedBy {
|
||||
@ -3375,7 +3381,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
invitedBy = peer
|
||||
}
|
||||
}
|
||||
contactStatus = ChatContactStatus(canAddContact: false, canReportIrrelevantLocation: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: invitedBy)
|
||||
contactStatus = ChatContactStatus(canAddContact: false, canReportIrrelevantLocation: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: invitedBy, requestChatPeer: nil)
|
||||
} else if let cachedData = peerView.cachedData as? CachedChannelData {
|
||||
var canReportIrrelevantLocation = true
|
||||
if let peer = peerView.peers[peerView.peerId] as? TelegramChannel, peer.participationStatus == .member {
|
||||
@ -3390,7 +3396,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
invitedBy = peer
|
||||
}
|
||||
}
|
||||
contactStatus = ChatContactStatus(canAddContact: false, canReportIrrelevantLocation: canReportIrrelevantLocation, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: invitedBy)
|
||||
contactStatus = ChatContactStatus(canAddContact: false, canReportIrrelevantLocation: canReportIrrelevantLocation, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: invitedBy, requestChatPeer: nil)
|
||||
}
|
||||
|
||||
var peers = SimpleDictionary<PeerId, Peer>()
|
||||
@ -13864,6 +13870,29 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.push(controller)
|
||||
}
|
||||
|
||||
private func presentChatRequestAdminInfo() {
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
|
||||
let text = ""
|
||||
|
||||
items.append(ActionSheetTextItem(title: text))
|
||||
items.append(ActionSheetButtonItem(title: self.presentationData.strings.Conversation_InviteRequestInfoConfirm, color: .accent, action: { [weak self, weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
self?.interfaceInteraction?.dismissReportPeer()
|
||||
}))
|
||||
controller.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
})
|
||||
])])
|
||||
controller.setItemGroups([])
|
||||
self.chatDisplayNode.dismissInput()
|
||||
self.push(controller)
|
||||
}
|
||||
|
||||
private var crossfading = false
|
||||
private func presentCrossfadeSnapshot() {
|
||||
guard !self.crossfading, let snapshotView = self.view.snapshotView(afterScreenUpdates: false) else {
|
||||
|
@ -198,6 +198,7 @@ struct ChatContactStatus: Equatable {
|
||||
var canReportIrrelevantLocation: Bool
|
||||
var peerStatusSettings: PeerStatusSettings?
|
||||
var invitedBy: Peer?
|
||||
var requestChatPeer: Peer?
|
||||
|
||||
var isEmpty: Bool {
|
||||
guard var peerStatusSettings = self.peerStatusSettings else {
|
||||
@ -225,6 +226,9 @@ struct ChatContactStatus: Equatable {
|
||||
if !arePeersEqual(lhs.invitedBy, rhs.invitedBy) {
|
||||
return false
|
||||
}
|
||||
if !arePeersEqual(lhs.requestChatPeer, rhs.requestChatPeer) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import LocalizedPeerData
|
||||
import TelegramStringFormatting
|
||||
import TextFormat
|
||||
import Markdown
|
||||
|
||||
private enum ChatReportPeerTitleButton: Equatable {
|
||||
case block
|
||||
@ -302,6 +304,7 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
|
||||
private let closeButton: HighlightableButtonNode
|
||||
private var buttons: [(ChatReportPeerTitleButton, UIButton)] = []
|
||||
private let textNode: ImmediateTextNode
|
||||
|
||||
private var theme: PresentationTheme?
|
||||
|
||||
@ -316,9 +319,12 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
self.closeButton.hitTestSlop = UIEdgeInsets(top: -8.0, left: -8.0, bottom: -8.0, right: -8.0)
|
||||
self.closeButton.displaysAsynchronously = false
|
||||
|
||||
self.textNode = ImmediateTextNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.separatorNode)
|
||||
self.addSubnode(self.textNode)
|
||||
|
||||
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: [.touchUpInside])
|
||||
self.addSubnode(self.closeButton)
|
||||
@ -425,6 +431,33 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let requestChatPeer = interfaceState.contactStatus?.requestChatPeer, let renderedPeer = interfaceState.renderedPeer, let peer = renderedPeer.chatMainPeer {
|
||||
let text: NSAttributedString
|
||||
let regular = MarkdownAttributeSet(font: Font.regular(14.0), textColor: interfaceState.theme.rootController.navigationBar.primaryTextColor)
|
||||
let bold = MarkdownAttributeSet(font: Font.bold(14.0), textColor: interfaceState.theme.rootController.navigationBar.primaryTextColor)
|
||||
if let requestChatPeer = requestChatPeer as? TelegramChannel, case .broadcast = requestChatPeer.info {
|
||||
text = addAttributesToStringWithRanges(interfaceState.strings.Conversation_InviteRequestAdminChannel(EnginePeer(peer).compactDisplayTitle, EnginePeer(requestChatPeer).displayTitle(strings: interfaceState.strings, displayOrder: interfaceState.nameDisplayOrder))._tuple, body: regular, argumentAttributes: [0: bold, 1: bold])
|
||||
} else {
|
||||
text = addAttributesToStringWithRanges(interfaceState.strings.Conversation_InviteRequestAdminGroup(EnginePeer(peer).compactDisplayTitle, EnginePeer(requestChatPeer).displayTitle(strings: interfaceState.strings, displayOrder: interfaceState.nameDisplayOrder))._tuple, body: regular, argumentAttributes: [0: bold, 1: bold])
|
||||
}
|
||||
self.textNode.attributedText = text
|
||||
|
||||
transition.updateAlpha(node: self.textNode, alpha: 1.0)
|
||||
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: width - leftInset - rightInset - 40.0, height: 40.0))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - textSize.width) / 2.0), y: 4.0), size: textSize)
|
||||
|
||||
for (_, view) in self.buttons {
|
||||
transition.updateAlpha(layer: view.layer, alpha: 0.0)
|
||||
}
|
||||
} else {
|
||||
transition.updateAlpha(node: self.textNode, alpha: 0.0)
|
||||
|
||||
for (_, view) in self.buttons {
|
||||
transition.updateAlpha(layer: view.layer, alpha: 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
let initialPanelHeight = panelHeight
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user