Update API

This commit is contained in:
Ilya Laktyushin 2021-11-19 18:32:05 +04:00
parent 5bbc508c1a
commit 15b708791d
35 changed files with 751 additions and 223 deletions

View File

@ -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";

View File

@ -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 {

View File

@ -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)

View File

@ -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
}
}
}

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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])

View File

@ -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
})

View File

@ -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)
}
}
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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]] = [:]

View File

@ -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 {

View File

@ -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)

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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":[]}

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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)))