Merge commit '5114a1d068cebdaf441df153e07d4f4b02e502fe'

This commit is contained in:
Ali 2021-10-08 23:03:25 +04:00
commit 40e56e0bb1
25 changed files with 275 additions and 139 deletions

Binary file not shown.

View File

@ -6783,13 +6783,7 @@ Sorry for the inconvenience.";
"SponsoredMessageMenu.Info" = "What are sponsored\nmessages?"; "SponsoredMessageMenu.Info" = "What are sponsored\nmessages?";
"SponsoredMessageInfoScreen.Title" = "What are sponsored messages?"; "SponsoredMessageInfoScreen.Title" = "What are sponsored messages?";
"SponsoredMessageInfoScreen.Text" = "Unlike other apps, Telegram never uses your private data to target ads. You are seeing this message only because someone chose this public one-to many channel as a space to promote their messages. This means that no user data is mined or analyzed to display ads, and every user viewing a channel on Telegram sees the same sponsored message. "SponsoredMessageInfoScreen.Text" = "Unlike other apps, Telegram never uses your private data to target ads. You are seeing this message only because someone chose this public one-to many channel as a space to promote their messages. This means that no user data is mined or analyzed to display ads, and every user viewing a channel on Telegram sees the same sponsored message.\n\nUnline other apps, Telegram doesn't track whether you tapped on a sponsored message and doesn't profile you based on your activity. We also prevent external links in sponsored messages to ensure that third parties can't spy on our users. We believe that everyone has the right to privacy, and technological platforms should respect that.\n\nTelegram offers free and unlimited service to hundreds of millions of users, which involves significant server and traffic costs. In order to remain independent and stay true to its values, Telegram developed a paid tool to promote messages with user privacy in mind. We welcome responsible adverticers at:\n[url]\nAds should no longer be synonymous with abuse of user privacy. Let us redefine how a tech compony should operate — together.";
Unline other apps, Telegram doesn't track whether you tapped on a sponsored message and doesn't profile you based on your activity. We also prevent external links in sponsored messages to ensure that third parties can't spy on our users. We believe that everyone has the right to privacy, and technological platforms should respect that.
Telegram offers free and unlimited service to hundreds of millions of users, which involves significant server and traffic costs. In order to remain independent and stay true to its values, Telegram developed a paid tool to promote messages with user privacy in mind. We welcome responsible adverticers at:
[url]
Ads should no longer be synonymous with abuse of user privacy. Let us redefine how a tech compony should operate — together.";
"SponsoredMessageInfo.Action" = "Learn More"; "SponsoredMessageInfo.Action" = "Learn More";
"SponsoredMessageInfo.Url" = "https://telegram.org/ads"; "SponsoredMessageInfo.Url" = "https://telegram.org/ads";

View File

@ -1,5 +1,6 @@
import UIKit import UIKit
import AsyncDisplayKit import AsyncDisplayKit
import SwiftSignalKit
private var backArrowImageCache: [Int32: UIImage] = [:] private var backArrowImageCache: [Int32: UIImage] = [:]
@ -146,7 +147,23 @@ public final class NavigationBackgroundNode: ASDisplayNode {
self.updateColor(color: color, transition: .immediate) self.updateColor(color: color, transition: .immediate)
} }
public override func didLoad() {
super.didLoad()
if self.scheduledUpdate {
self.scheduledUpdate = false
self.updateBackgroundBlur(forceKeepBlur: false)
}
}
private var scheduledUpdate = false
private func updateBackgroundBlur(forceKeepBlur: Bool) { private func updateBackgroundBlur(forceKeepBlur: Bool) {
guard self.isNodeLoaded else {
self.scheduledUpdate = true
return
}
if self.enableBlur && !sharedIsReduceTransparencyEnabled && ((self._color.alpha > .ulpOfOne && self._color.alpha < 0.95) || forceKeepBlur) { if self.enableBlur && !sharedIsReduceTransparencyEnabled && ((self._color.alpha > .ulpOfOne && self._color.alpha < 0.95) || forceKeepBlur) {
if self.effectView == nil { if self.effectView == nil {
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))

View File

@ -18,12 +18,15 @@ private class LeftAlignedIconButton: UIButton {
override func titleRect(forContentRect contentRect: CGRect) -> CGRect { override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
var titleRect = super.titleRect(forContentRect: contentRect) var titleRect = super.titleRect(forContentRect: contentRect)
let imageSize = currentImage?.size ?? .zero let imageSize = currentImage?.size ?? .zero
titleRect.origin.x = imageSize.width + 2.0 titleRect.origin.x = imageSize.width
//
// let availableWidth = contentRect.width - imageEdgeInsets.right - imageSize.width - titleRect.width
// return titleRect.offsetBy(dx: round(availableWidth / 2) - imageEdgeInsets.left, dy: 0)
return titleRect return titleRect
} }
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
var imageRect = super.imageRect(forContentRect: contentRect)
imageRect.origin.x = 0.0
return imageRect
}
} }
class ChartStackSection: UIView, ChartThemeContainer { class ChartStackSection: UIView, ChartThemeContainer {
@ -72,6 +75,7 @@ class ChartStackSection: UIView, ChartThemeContainer {
backButton.setImage(UIImage(bundleImageName: "Chart/arrow_left"), for: .normal) backButton.setImage(UIImage(bundleImageName: "Chart/arrow_left"), for: .normal)
backButton.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 3.0) backButton.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 3.0)
backButton.imageView?.tintColor = UIColor(rgb: 0x007aff) backButton.imageView?.tintColor = UIColor(rgb: 0x007aff)
backButton.adjustsImageWhenHighlighted = false
backButton.setVisible(false, animated: false) backButton.setVisible(false, animated: false)
} }
@ -172,7 +176,7 @@ class ChartStackSection: UIView, ChartThemeContainer {
self.rangeView.frame = CGRect(origin: CGPoint(x: 0.0, y: 310.0), size: CGSize(width: bounds.width, height: 42.0)) self.rangeView.frame = CGRect(origin: CGPoint(x: 0.0, y: 310.0), size: CGSize(width: bounds.width, height: 42.0))
self.visibilityView.frame = CGRect(origin: CGPoint(x: 0.0, y: self.displayRange ? 368.0 : 326.0), size: CGSize(width: bounds.width, height: 350.0)) self.visibilityView.frame = CGRect(origin: CGPoint(x: 0.0, y: self.displayRange ? 368.0 : 326.0), size: CGSize(width: bounds.width, height: 350.0))
self.backButton.frame = CGRect(x: 0.0, y: 0.0, width: 96.0, height: 38.0) self.backButton.frame = CGRect(x: 8.0, y: 0.0, width: 96.0, height: 38.0)
self.chartView.setNeedsDisplay() self.chartView.setNeedsDisplay()
} }

View File

@ -16,13 +16,15 @@ class InviteLinkHeaderItem: ListViewItem, ItemListItem {
let context: AccountContext let context: AccountContext
let theme: PresentationTheme let theme: PresentationTheme
let text: String let text: String
let animationName: String
let sectionId: ItemListSectionId let sectionId: ItemListSectionId
let linkAction: ((ItemListTextItemLinkAction) -> Void)? let linkAction: ((ItemListTextItemLinkAction) -> Void)?
init(context: AccountContext, theme: PresentationTheme, text: String, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) { init(context: AccountContext, theme: PresentationTheme, text: String, animationName: String, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) {
self.context = context self.context = context
self.theme = theme self.theme = theme
self.text = text self.text = text
self.animationName = animationName
self.sectionId = sectionId self.sectionId = sectionId
self.linkAction = linkAction self.linkAction = linkAction
} }
@ -117,7 +119,7 @@ class InviteLinkHeaderItemNode: ListViewItemNode {
return (layout, { [weak self] in return (layout, { [weak self] in
if let strongSelf = self { if let strongSelf = self {
if strongSelf.item == nil { if strongSelf.item == nil {
strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Invite"), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: item.animationName), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
strongSelf.animationNode.visibility = true strongSelf.animationNode.visibility = true
} }
strongSelf.item = item strongSelf.item = item

View File

@ -210,7 +210,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
let arguments = arguments as! InviteLinkListControllerArguments let arguments = arguments as! InviteLinkListControllerArguments
switch self { switch self {
case let .header(theme, text): case let .header(theme, text):
return InviteLinkHeaderItem(context: arguments.context, theme: theme, text: text, sectionId: self.section) return InviteLinkHeaderItem(context: arguments.context, theme: theme, text: text, animationName: "Invite", sectionId: self.section)
case let .mainLinkHeader(_, text): case let .mainLinkHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .mainLink(_, invite, peers, importersCount, isPublic): case let .mainLink(_, invite, peers, importersCount, isPublic):
@ -283,7 +283,7 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
let mainInvite: ExportedInvitation? let mainInvite: ExportedInvitation?
var isPublic = false var isPublic = false
if let peer = peer, let address = peer.addressName, !address.isEmpty && admin == nil { if let peer = peer, let address = peer.addressName, !address.isEmpty && admin == nil {
mainInvite = ExportedInvitation(link: "t.me/\(address)", isPermanent: true, requestApproval: false, isRevoked: false, adminId: EnginePeer.Id(0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil, approvedDate: nil) mainInvite = ExportedInvitation(link: "t.me/\(address)", isPermanent: true, requestApproval: false, isRevoked: false, adminId: EnginePeer.Id(0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil, requestedCount: nil)
isPublic = true isPublic = true
} else if let invites = invites, let invite = invites.first(where: { $0.isPermanent && !$0.isRevoked }) { } else if let invites = invites, let invite = invites.first(where: { $0.isPermanent && !$0.isRevoked }) {
mainInvite = invite mainInvite = invite
@ -756,7 +756,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio
|> distinctUntilChanged |> distinctUntilChanged
|> deliverOnMainQueue |> deliverOnMainQueue
|> map { invite -> PeerInvitationImportersContext? in |> map { invite -> PeerInvitationImportersContext? in
return invite.flatMap { context.engine.peers.peerInvitationImporters(peerId: peerId, invite: $0) } return invite.flatMap { context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: $0, requested: false)) }
} |> afterNext { context in } |> afterNext { context in
if let context = context { if let context = context {
importersState.set(context.state |> map(Optional.init)) importersState.set(context.state |> map(Optional.init))

View File

@ -341,6 +341,7 @@ public final class InviteLinkViewController: ViewController {
private let invite: ExportedInvitation private let invite: ExportedInvitation
private let importersContext: PeerInvitationImportersContext private let importersContext: PeerInvitationImportersContext
private let requestsContext: PeerInvitationImportersContext?
private var interaction: InviteLinkViewInteraction? private var interaction: InviteLinkViewInteraction?
@ -376,7 +377,12 @@ public final class InviteLinkViewController: ViewController {
self.presentationDataPromise = Promise(self.presentationData) self.presentationDataPromise = Promise(self.presentationData)
self.controller = controller self.controller = controller
self.importersContext = importersContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, invite: invite) self.importersContext = importersContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: false))
if invite.requestApproval {
self.requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: true))
} else {
self.requestsContext = nil
}
self.dimNode = ASDisplayNode() self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5) self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
@ -572,9 +578,16 @@ public final class InviteLinkViewController: ViewController {
let previousCount = Atomic<Int32?>(value: nil) let previousCount = Atomic<Int32?>(value: nil)
let previousLoading = Atomic<Bool?>(value: nil) let previousLoading = Atomic<Bool?>(value: nil)
let requestsState: Signal<PeerInvitationImportersState, NoError>
if let requestsContext = self.requestsContext {
requestsState = requestsContext.state
} else {
requestsState = .single(PeerInvitationImportersState.Empty)
}
let creatorPeer = context.account.postbox.loadedPeerWithId(invite.adminId) let creatorPeer = context.account.postbox.loadedPeerWithId(invite.adminId)
self.disposable = (combineLatest(self.presentationDataPromise.get(), self.importersContext.state, creatorPeer) self.disposable = (combineLatest(self.presentationDataPromise.get(), self.importersContext.state, requestsState, creatorPeer)
|> deliverOnMainQueue).start(next: { [weak self] presentationData, state, creatorPeer in |> deliverOnMainQueue).start(next: { [weak self] presentationData, state, requestsState, creatorPeer in
if let strongSelf = self { if let strongSelf = self {
var entries: [InviteLinkViewEntry] = [] var entries: [InviteLinkViewEntry] = []
@ -582,26 +595,15 @@ public final class InviteLinkViewController: ViewController {
entries.append(.creatorHeader(presentationData.theme, presentationData.strings.InviteLink_CreatedBy.uppercased())) entries.append(.creatorHeader(presentationData.theme, presentationData.strings.InviteLink_CreatedBy.uppercased()))
entries.append(.creator(presentationData.theme, presentationData.dateTimeFormat, EnginePeer(creatorPeer), invite.date)) entries.append(.creator(presentationData.theme, presentationData.dateTimeFormat, EnginePeer(creatorPeer), invite.date))
if !state.importers.isEmpty || (state.isLoadingMore && state.count > 0) { if !requestsState.importers.isEmpty || (state.isLoadingMore && requestsState.count > 0) {
let subtitle: String entries.append(.importerHeader(presentationData.theme, presentationData.strings.MemberRequests_PeopleRequested(Int32(requestsState.count)).uppercased(), "", false))
let subtitleExpired: Bool
if let usageLimit = invite.usageLimit {
let remaining = max(0, usageLimit - state.count)
subtitle = presentationData.strings.InviteLink_PeopleRemaining(remaining).uppercased()
subtitleExpired = remaining <= 0
} else {
subtitle = ""
subtitleExpired = false
}
entries.append(.importerHeader(presentationData.theme, presentationData.strings.InviteLink_PeopleJoined(Int32(state.count)).uppercased(), subtitle, subtitleExpired))
} }
let count: Int32 let count: Int32
let loading: Bool let loading: Bool
var index: Int32 = 0 var index: Int32 = 0
if state.importers.isEmpty && state.isLoadingMore { if requestsState.importers.isEmpty && requestsState.isLoadingMore {
count = min(4, state.count) count = min(4, state.count)
loading = true loading = true
let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])
@ -609,9 +611,9 @@ public final class InviteLinkViewController: ViewController {
entries.append(.importer(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, true)) entries.append(.importer(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, true))
} }
} else { } else {
count = min(4, Int32(state.importers.count)) count = min(4, Int32(requestsState.importers.count))
loading = false loading = false
for importer in state.importers { for importer in requestsState.importers {
if let peer = importer.peer.peer { if let peer = importer.peer.peer {
entries.append(.importer(index, presentationData.theme, presentationData.dateTimeFormat, EnginePeer(peer), importer.date, false)) entries.append(.importer(index, presentationData.theme, presentationData.dateTimeFormat, EnginePeer(peer), importer.date, false))
} }
@ -619,6 +621,43 @@ public final class InviteLinkViewController: ViewController {
} }
} }
// if !state.importers.isEmpty || (state.isLoadingMore && state.count > 0) {
// let subtitle: String
// let subtitleExpired: Bool
// if let usageLimit = invite.usageLimit {
// let remaining = max(0, usageLimit - state.count)
// subtitle = presentationData.strings.InviteLink_PeopleRemaining(remaining).uppercased()
// subtitleExpired = remaining <= 0
// } else {
// subtitle = ""
// subtitleExpired = false
// }
//
// entries.append(.importerHeader(presentationData.theme, presentationData.strings.InviteLink_PeopleJoined(Int32(state.count)).uppercased(), subtitle, subtitleExpired))
// }
// let count: Int32
// let loading: Bool
//
// var index: Int32 = 0
// if state.importers.isEmpty && state.isLoadingMore {
// count = min(4, state.count)
// loading = true
// let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])
// for i in 0 ..< count {
// entries.append(.importer(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, true))
// }
// } else {
// count = min(4, Int32(state.importers.count))
// loading = false
// for importer in state.importers {
// if let peer = importer.peer.peer {
// entries.append(.importer(index, presentationData.theme, presentationData.dateTimeFormat, EnginePeer(peer), importer.date, false))
// }
// index += 1
// }
// }
let previousCount = previousCount.swap(count) let previousCount = previousCount.swap(count)
let previousLoading = previousLoading.swap(loading) let previousLoading = previousLoading.swap(loading)

View File

@ -100,7 +100,7 @@ private enum InviteRequestsEntry: ItemListNodeEntry {
let arguments = arguments as! InviteRequestsControllerArguments let arguments = arguments as! InviteRequestsControllerArguments
switch self { switch self {
case let .header(theme, text): case let .header(theme, text):
return InviteLinkHeaderItem(context: arguments.context, theme: theme, text: text, sectionId: self.section, linkAction: { _ in return InviteLinkHeaderItem(context: arguments.context, theme: theme, text: text, animationName: "Requests", sectionId: self.section, linkAction: { _ in
arguments.openLinks() arguments.openLinks()
}) })
case let .requestsHeader(_, text): case let .requestsHeader(_, text):
@ -166,7 +166,7 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio
var getControllerImpl: (() -> ViewController?)? var getControllerImpl: (() -> ViewController?)?
let importersContext = existingContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, invite: nil) let importersContext = existingContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: nil))
let arguments = InviteRequestsControllerArguments(context: context, openLinks: { let arguments = InviteRequestsControllerArguments(context: context, openLinks: {
let controller = inviteLinkListController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, admin: nil) let controller = inviteLinkListController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, admin: nil)

View File

@ -343,20 +343,29 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
var timerValue: TimerNode.Value? var timerValue: TimerNode.Value?
if let invite = item.invite { if let invite = item.invite {
let count = invite.count ?? 0 let count = invite.count ?? 0
let requestedCount = invite.requestedCount ?? 0
if count > 0 { if count > 0 {
if invite.requestApproval { subtitleText = item.presentationData.strings.InviteLink_PeopleJoinedShort(count)
subtitleText = item.presentationData.strings.MemberRequests_PeopleRequestedShort(count)
} else {
subtitleText = item.presentationData.strings.InviteLink_PeopleJoinedShort(count)
}
} else { } else {
if let usageLimit = invite.usageLimit, count == 0 && !availability.isZero { if let usageLimit = invite.usageLimit, count == 0 && !availability.isZero {
subtitleText = item.presentationData.strings.InviteLink_PeopleCanJoin(usageLimit) subtitleText = item.presentationData.strings.InviteLink_PeopleCanJoin(usageLimit)
} else { } else {
subtitleText = availability.isZero ? item.presentationData.strings.InviteLink_PeopleJoinedShortNoneExpired : item.presentationData.strings.InviteLink_PeopleJoinedShortNone if availability.isZero {
subtitleText = item.presentationData.strings.InviteLink_PeopleJoinedShortNoneExpired
} else if requestedCount == 0 {
subtitleText = item.presentationData.strings.InviteLink_PeopleJoinedShortNone
}
} }
} }
if requestedCount > 0 {
if !subtitleText.isEmpty {
subtitleText += ", "
}
subtitleText += item.presentationData.strings.MemberRequests_PeopleRequestedShort(requestedCount)
}
if invite.isRevoked { if invite.isRevoked {
if !subtitleText.isEmpty { if !subtitleText.isEmpty {
subtitleText += "" subtitleText += ""

View File

@ -277,11 +277,7 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
if let importer = item.importer, let peer = importer.peer.peer.flatMap({ EnginePeer($0) }) { if let importer = item.importer, let peer = importer.peer.peer.flatMap({ EnginePeer($0) }) {
titleText = peer.displayTitle(strings: item.presentationData.strings, displayOrder: item.nameDisplayOrder) titleText = peer.displayTitle(strings: item.presentationData.strings, displayOrder: item.nameDisplayOrder)
if case .user = peer { subtitleText = importer.about ?? ""
subtitleText = " "
} else {
subtitleText = ""
}
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
dateText = stringForRelativeTimestamp(strings: item.presentationData.strings, relativeTimestamp: importer.date, relativeTo: timestamp, dateTimeFormat: item.dateTimeFormat) dateText = stringForRelativeTimestamp(strings: item.presentationData.strings, relativeTimestamp: importer.date, relativeTo: timestamp, dateTimeFormat: item.dateTimeFormat)
} else { } else {
@ -305,8 +301,10 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
let titleSpacing: CGFloat = 1.0 let titleSpacing: CGFloat = 1.0
let minHeight: CGFloat = titleLayout.size.height + verticalInset * 2.0 let minHeight: CGFloat = titleLayout.size.height + verticalInset * 2.0
let rawHeight: CGFloat = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + subtitleLayout.size.height + 24.0 var rawHeight: CGFloat = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + 41.0
if !subtitleLayout.size.height.isZero {
rawHeight += subtitleLayout.size.height + 5.0
}
var insets: UIEdgeInsets var insets: UIEdgeInsets
let itemBackgroundColor: UIColor let itemBackgroundColor: UIColor
let itemSeparatorColor: UIColor let itemSeparatorColor: UIColor
@ -452,10 +450,10 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.dismissButton.setTitle(item.presentationData.strings.MemberRequests_Dismiss, with: Font.bold(15.0), with: item.presentationData.theme.list.itemAccentColor, for: .normal) strongSelf.dismissButton.setTitle(item.presentationData.strings.MemberRequests_Dismiss, with: Font.bold(15.0), with: item.presentationData.theme.list.itemAccentColor, for: .normal)
let addHeight = strongSelf.addButton.updateLayout(width: 138.0, transition: .immediate) let addHeight = strongSelf.addButton.updateLayout(width: 138.0, transition: .immediate)
strongSelf.addButton.frame = CGRect(x: leftInset, y: verticalInset + titleLayout.size.height + 7.0, width: 138.0, height: addHeight) strongSelf.addButton.frame = CGRect(x: leftInset, y: contentSize.height - addHeight - 12.0, width: 138.0, height: addHeight)
let dismissSize = strongSelf.dismissButton.measure(layout.size) let dismissSize = strongSelf.dismissButton.measure(layout.size)
strongSelf.dismissButton.frame = CGRect(origin: CGPoint(x: leftInset + 138.0 + 24.0, y: verticalInset + titleLayout.size.height + 14.0), size: dismissSize) strongSelf.dismissButton.frame = CGRect(origin: CGPoint(x: leftInset + 138.0 + 24.0, y: verticalInset + contentSize.height - addHeight - 14.0), size: dismissSize)
if item.importer == nil { if item.importer == nil {
let shimmerNode: ShimmerEffectNode let shimmerNode: ShimmerEffectNode

View File

@ -157,6 +157,8 @@ public final class JoinLinkPreviewController: ViewController {
} }
case .tooMuchUsers: case .tooMuchUsers:
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_UsersTooMuchError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_UsersTooMuchError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
case .requestSent:
break
case .generic: case .generic:
break break
} }

View File

@ -745,7 +745,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1625153079] = { return Api.InputWebFileLocation.parse_inputWebFileGeoPointLocation($0) } dict[-1625153079] = { return Api.InputWebFileLocation.parse_inputWebFileGeoPointLocation($0) }
dict[-1275374751] = { return Api.EmojiLanguage.parse_emojiLanguage($0) } dict[-1275374751] = { return Api.EmojiLanguage.parse_emojiLanguage($0) }
dict[1601666510] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) } dict[1601666510] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
dict[708589599] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) } dict[-783162982] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
dict[-1012849566] = { return Api.BaseTheme.parse_baseThemeClassic($0) } dict[-1012849566] = { return Api.BaseTheme.parse_baseThemeClassic($0) }
dict[-69724536] = { return Api.BaseTheme.parse_baseThemeDay($0) } dict[-69724536] = { return Api.BaseTheme.parse_baseThemeDay($0) }
dict[-1212997976] = { return Api.BaseTheme.parse_baseThemeNight($0) } dict[-1212997976] = { return Api.BaseTheme.parse_baseThemeNight($0) }
@ -787,7 +787,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) } dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) } dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) }
dict[750063767] = { return Api.messages.FavedStickers.parse_favedStickers($0) } dict[750063767] = { return Api.messages.FavedStickers.parse_favedStickers($0) }
dict[19682803] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) } dict[-1283792928] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[-1389486888] = { return Api.account.AuthorizationForm.parse_authorizationForm($0) } dict[-1389486888] = { return Api.account.AuthorizationForm.parse_authorizationForm($0) }
dict[-1392388579] = { return Api.Authorization.parse_authorization($0) } dict[-1392388579] = { return Api.Authorization.parse_authorization($0) }
dict[-1361650766] = { return Api.MaskCoords.parse_maskCoords($0) } dict[-1361650766] = { return Api.MaskCoords.parse_maskCoords($0) }
@ -838,6 +838,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1781355374] = { return Api.MessageAction.parse_messageActionChannelCreate($0) } dict[-1781355374] = { return Api.MessageAction.parse_messageActionChannelCreate($0) }
dict[-519864430] = { return Api.MessageAction.parse_messageActionChatMigrateTo($0) } dict[-519864430] = { return Api.MessageAction.parse_messageActionChatMigrateTo($0) }
dict[-365344535] = { return Api.MessageAction.parse_messageActionChannelMigrateFrom($0) } dict[-365344535] = { return Api.MessageAction.parse_messageActionChannelMigrateFrom($0) }
dict[-339958837] = { return Api.MessageAction.parse_messageActionChatJoinedByRequest($0) }
dict[-1799538451] = { return Api.MessageAction.parse_messageActionPinMessage($0) } dict[-1799538451] = { return Api.MessageAction.parse_messageActionPinMessage($0) }
dict[-1615153660] = { return Api.MessageAction.parse_messageActionHistoryClear($0) } dict[-1615153660] = { return Api.MessageAction.parse_messageActionHistoryClear($0) }
dict[-1834538890] = { return Api.MessageAction.parse_messageActionGameScore($0) } dict[-1834538890] = { return Api.MessageAction.parse_messageActionGameScore($0) }
@ -856,7 +857,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1441072131] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) } dict[-1441072131] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) } dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) }
dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) } dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) }
dict[-339958837] = { return Api.MessageAction.parse_messageActionChatJoinedByRequest($0) }
dict[1399245077] = { return Api.PhoneCall.parse_phoneCallEmpty($0) } dict[1399245077] = { return Api.PhoneCall.parse_phoneCallEmpty($0) }
dict[-987599081] = { return Api.PhoneCall.parse_phoneCallWaiting($0) } dict[-987599081] = { return Api.PhoneCall.parse_phoneCallWaiting($0) }
dict[347139340] = { return Api.PhoneCall.parse_phoneCallRequested($0) } dict[347139340] = { return Api.PhoneCall.parse_phoneCallRequested($0) }

View File

@ -19396,17 +19396,18 @@ public extension Api {
} }
public enum SponsoredMessage: TypeConstructorDescription { public enum SponsoredMessage: TypeConstructorDescription {
case sponsoredMessage(flags: Int32, randomId: Buffer, fromId: Api.Peer, startParam: String?, message: String, entities: [Api.MessageEntity]?) case sponsoredMessage(flags: Int32, randomId: Buffer, fromId: Api.Peer, channelPost: Int32?, startParam: String?, message: String, entities: [Api.MessageEntity]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .sponsoredMessage(let flags, let randomId, let fromId, let startParam, let message, let entities): case .sponsoredMessage(let flags, let randomId, let fromId, let channelPost, let startParam, let message, let entities):
if boxed { if boxed {
buffer.appendInt32(708589599) buffer.appendInt32(-783162982)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeBytes(randomId, buffer: buffer, boxed: false) serializeBytes(randomId, buffer: buffer, boxed: false)
fromId.serialize(buffer, true) fromId.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(channelPost!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 0) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 0) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
serializeString(message, buffer: buffer, boxed: false) serializeString(message, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
@ -19420,8 +19421,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .sponsoredMessage(let flags, let randomId, let fromId, let startParam, let message, let entities): case .sponsoredMessage(let flags, let randomId, let fromId, let channelPost, let startParam, let message, let entities):
return ("sponsoredMessage", [("flags", flags), ("randomId", randomId), ("fromId", fromId), ("startParam", startParam), ("message", message), ("entities", entities)]) return ("sponsoredMessage", [("flags", flags), ("randomId", randomId), ("fromId", fromId), ("channelPost", channelPost), ("startParam", startParam), ("message", message), ("entities", entities)])
} }
} }
@ -19434,22 +19435,25 @@ public extension Api {
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Peer _3 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _4: String? var _4: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
var _5: String? var _5: String?
_5 = parseString(reader) if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) }
var _6: [Api.MessageEntity]? var _6: String?
_6 = parseString(reader)
var _7: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} } } }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
let _c5 = _5 != nil let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, fromId: _3!, startParam: _4, message: _5!, entities: _6) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, fromId: _3!, channelPost: _4, startParam: _5, message: _6!, entities: _7)
} }
else { else {
return nil return nil
@ -20166,13 +20170,13 @@ public extension Api {
} }
public enum ExportedChatInvite: TypeConstructorDescription { public enum ExportedChatInvite: TypeConstructorDescription {
case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, approved: Int32?) case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, requested: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let approved): case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested):
if boxed { if boxed {
buffer.appendInt32(19682803) buffer.appendInt32(-1283792928)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(link, buffer: buffer, boxed: false) serializeString(link, buffer: buffer, boxed: false)
@ -20182,15 +20186,15 @@ public extension Api {
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 2) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(approved!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 7) != 0 {serializeInt32(requested!, buffer: buffer, boxed: false)}
break break
} }
} }
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let approved): case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested):
return ("chatInviteExported", [("flags", flags), ("link", link), ("adminId", adminId), ("date", date), ("startDate", startDate), ("expireDate", expireDate), ("usageLimit", usageLimit), ("usage", usage), ("approved", approved)]) return ("chatInviteExported", [("flags", flags), ("link", link), ("adminId", adminId), ("date", date), ("startDate", startDate), ("expireDate", expireDate), ("usageLimit", usageLimit), ("usage", usage), ("requested", requested)])
} }
} }
@ -20223,7 +20227,7 @@ public extension Api {
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, approved: _9) return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, requested: _9)
} }
else { else {
return nil return nil
@ -21079,6 +21083,7 @@ public extension Api {
case messageActionChannelCreate(title: String) case messageActionChannelCreate(title: String)
case messageActionChatMigrateTo(channelId: Int64) case messageActionChatMigrateTo(channelId: Int64)
case messageActionChannelMigrateFrom(title: String, chatId: Int64) case messageActionChannelMigrateFrom(title: String, chatId: Int64)
case messageActionChatJoinedByRequest
case messageActionPinMessage case messageActionPinMessage
case messageActionHistoryClear case messageActionHistoryClear
case messageActionGameScore(gameId: Int64, score: Int32) case messageActionGameScore(gameId: Int64, score: Int32)
@ -21097,7 +21102,6 @@ public extension Api {
case messageActionSetMessagesTTL(period: Int32) case messageActionSetMessagesTTL(period: Int32)
case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32) case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32)
case messageActionSetChatTheme(emoticon: String) case messageActionSetChatTheme(emoticon: String)
case messageActionChatJoinedByRequest
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
@ -21176,6 +21180,12 @@ public extension Api {
} }
serializeString(title, buffer: buffer, boxed: false) serializeString(title, buffer: buffer, boxed: false)
serializeInt64(chatId, buffer: buffer, boxed: false) serializeInt64(chatId, buffer: buffer, boxed: false)
break
case .messageActionChatJoinedByRequest:
if boxed {
buffer.appendInt32(-339958837)
}
break break
case .messageActionPinMessage: case .messageActionPinMessage:
if boxed { if boxed {
@ -21314,12 +21324,6 @@ public extension Api {
buffer.appendInt32(-1434950843) buffer.appendInt32(-1434950843)
} }
serializeString(emoticon, buffer: buffer, boxed: false) serializeString(emoticon, buffer: buffer, boxed: false)
break
case .messageActionChatJoinedByRequest:
if boxed {
buffer.appendInt32(-339958837)
}
break break
} }
} }
@ -21348,6 +21352,8 @@ public extension Api {
return ("messageActionChatMigrateTo", [("channelId", channelId)]) return ("messageActionChatMigrateTo", [("channelId", channelId)])
case .messageActionChannelMigrateFrom(let title, let chatId): case .messageActionChannelMigrateFrom(let title, let chatId):
return ("messageActionChannelMigrateFrom", [("title", title), ("chatId", chatId)]) return ("messageActionChannelMigrateFrom", [("title", title), ("chatId", chatId)])
case .messageActionChatJoinedByRequest:
return ("messageActionChatJoinedByRequest", [])
case .messageActionPinMessage: case .messageActionPinMessage:
return ("messageActionPinMessage", []) return ("messageActionPinMessage", [])
case .messageActionHistoryClear: case .messageActionHistoryClear:
@ -21384,8 +21390,6 @@ public extension Api {
return ("messageActionGroupCallScheduled", [("call", call), ("scheduleDate", scheduleDate)]) return ("messageActionGroupCallScheduled", [("call", call), ("scheduleDate", scheduleDate)])
case .messageActionSetChatTheme(let emoticon): case .messageActionSetChatTheme(let emoticon):
return ("messageActionSetChatTheme", [("emoticon", emoticon)]) return ("messageActionSetChatTheme", [("emoticon", emoticon)])
case .messageActionChatJoinedByRequest:
return ("messageActionChatJoinedByRequest", [])
} }
} }
@ -21506,6 +21510,9 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_messageActionChatJoinedByRequest(_ reader: BufferReader) -> MessageAction? {
return Api.MessageAction.messageActionChatJoinedByRequest
}
public static func parse_messageActionPinMessage(_ reader: BufferReader) -> MessageAction? { public static func parse_messageActionPinMessage(_ reader: BufferReader) -> MessageAction? {
return Api.MessageAction.messageActionPinMessage return Api.MessageAction.messageActionPinMessage
} }
@ -21750,9 +21757,6 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_messageActionChatJoinedByRequest(_ reader: BufferReader) -> MessageAction? {
return Api.MessageAction.messageActionChatJoinedByRequest
}
} }
public enum PhoneCall: TypeConstructorDescription { public enum PhoneCall: TypeConstructorDescription {

View File

@ -4371,16 +4371,17 @@ public extension Api {
}) })
} }
public static func getChatInviteImporters(flags: Int32, peer: Api.InputPeer, link: String?, offsetDate: Int32, offsetUser: Api.InputUser, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ChatInviteImporters>) { public static func getChatInviteImporters(flags: Int32, peer: Api.InputPeer, link: String?, q: String?, offsetDate: Int32, offsetUser: Api.InputUser, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ChatInviteImporters>) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(-1742901790) buffer.appendInt32(-553329330)
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {serializeString(link!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeString(link!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeString(q!, buffer: buffer, boxed: false)}
serializeInt32(offsetDate, buffer: buffer, boxed: false) serializeInt32(offsetDate, buffer: buffer, boxed: false)
offsetUser.serialize(buffer, true) offsetUser.serialize(buffer, true)
serializeInt32(limit, buffer: buffer, boxed: false) serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.getChatInviteImporters", parameters: [("flags", flags), ("peer", peer), ("link", link), ("offsetDate", offsetDate), ("offsetUser", offsetUser), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatInviteImporters? in return (FunctionDescription(name: "messages.getChatInviteImporters", parameters: [("flags", flags), ("peer", peer), ("link", link), ("q", q), ("offsetDate", offsetDate), ("offsetUser", offsetUser), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatInviteImporters? in
let reader = BufferReader(buffer) let reader = BufferReader(buffer)
var result: Api.messages.ChatInviteImporters? var result: Api.messages.ChatInviteImporters?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
@ -4484,6 +4485,22 @@ public extension Api {
}) })
} }
public static func hideChatJoinRequest(flags: Int32, peer: Api.InputPeer, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(2145904661)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
userId.serialize(buffer, true)
return (FunctionDescription(name: "messages.hideChatJoinRequest", parameters: [("flags", flags), ("peer", peer), ("userId", userId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
public static func getSearchResultsPositions(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SearchResultsPositions>) { public static func getSearchResultsPositions(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SearchResultsPositions>) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(1855292323) buffer.appendInt32(1855292323)
@ -4500,22 +4517,6 @@ public extension Api {
return result return result
}) })
} }
public static func hideChatJoinRequest(flags: Int32, peer: Api.InputPeer, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(2145904661)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
userId.serialize(buffer, true)
return (FunctionDescription(name: "messages.hideChatJoinRequest", parameters: [("flags", flags), ("peer", peer), ("userId", userId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
} }
public struct channels { public struct channels {
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) { public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {

View File

@ -6,8 +6,8 @@ import TelegramApi
extension ExportedInvitation { extension ExportedInvitation {
init(apiExportedInvite: Api.ExportedChatInvite) { init(apiExportedInvite: Api.ExportedChatInvite) {
switch apiExportedInvite { switch apiExportedInvite {
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, approved): case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested):
self = ExportedInvitation(link: link, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, approvedDate: approved) self = ExportedInvitation(link: link, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, requestedCount: requested)
} }
} }
} }

View File

@ -11,9 +11,9 @@ public struct ExportedInvitation: Codable, Equatable {
public let expireDate: Int32? public let expireDate: Int32?
public let usageLimit: Int32? public let usageLimit: Int32?
public let count: Int32? public let count: Int32?
public let approvedDate: Int32? public let requestedCount: Int32?
public init(link: String, isPermanent: Bool, requestApproval: Bool, isRevoked: Bool, adminId: PeerId, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, count: Int32?, approvedDate: Int32?) { public init(link: String, isPermanent: Bool, requestApproval: Bool, isRevoked: Bool, adminId: PeerId, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, count: Int32?, requestedCount: Int32?) {
self.link = link self.link = link
self.isPermanent = isPermanent self.isPermanent = isPermanent
self.requestApproval = requestApproval self.requestApproval = requestApproval
@ -24,7 +24,7 @@ public struct ExportedInvitation: Codable, Equatable {
self.expireDate = expireDate self.expireDate = expireDate
self.usageLimit = usageLimit self.usageLimit = usageLimit
self.count = count self.count = count
self.approvedDate = approvedDate self.requestedCount = requestedCount
} }
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
@ -40,7 +40,7 @@ public struct ExportedInvitation: Codable, Equatable {
self.expireDate = try container.decodeIfPresent(Int32.self, forKey: "expireDate") self.expireDate = try container.decodeIfPresent(Int32.self, forKey: "expireDate")
self.usageLimit = try container.decodeIfPresent(Int32.self, forKey: "usageLimit") self.usageLimit = try container.decodeIfPresent(Int32.self, forKey: "usageLimit")
self.count = try container.decodeIfPresent(Int32.self, forKey: "count") self.count = try container.decodeIfPresent(Int32.self, forKey: "count")
self.approvedDate = try? container.decodeIfPresent(Int32.self, forKey: "approvedDate") self.requestedCount = try? container.decodeIfPresent(Int32.self, forKey: "requestedCount")
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -56,14 +56,14 @@ public struct ExportedInvitation: Codable, Equatable {
try container.encodeIfPresent(self.expireDate, forKey: "expireDate") try container.encodeIfPresent(self.expireDate, forKey: "expireDate")
try container.encodeIfPresent(self.usageLimit, forKey: "usageLimit") try container.encodeIfPresent(self.usageLimit, forKey: "usageLimit")
try container.encodeIfPresent(self.count, forKey: "count") try container.encodeIfPresent(self.count, forKey: "count")
try container.encodeIfPresent(self.approvedDate, forKey: "approvedDate") try container.encodeIfPresent(self.requestedCount, forKey: "requestedCount")
} }
public static func ==(lhs: ExportedInvitation, rhs: ExportedInvitation) -> Bool { public static func ==(lhs: ExportedInvitation, rhs: ExportedInvitation) -> Bool {
return lhs.link == rhs.link && lhs.isPermanent == rhs.isPermanent && lhs.requestApproval == rhs.requestApproval && lhs.isRevoked == rhs.isRevoked && lhs.adminId == rhs.adminId && lhs.date == rhs.date && lhs.startDate == rhs.startDate && lhs.expireDate == rhs.expireDate && lhs.usageLimit == rhs.usageLimit && lhs.count == rhs.count && lhs.approvedDate == rhs.approvedDate return lhs.link == rhs.link && lhs.isPermanent == rhs.isPermanent && lhs.requestApproval == rhs.requestApproval && lhs.isRevoked == rhs.isRevoked && lhs.adminId == rhs.adminId && lhs.date == rhs.date && lhs.startDate == rhs.startDate && lhs.expireDate == rhs.expireDate && lhs.usageLimit == rhs.usageLimit && lhs.count == rhs.count && lhs.requestedCount == rhs.requestedCount
} }
public func withUpdated(isRevoked: Bool) -> ExportedInvitation { public func withUpdated(isRevoked: Bool) -> ExportedInvitation {
return ExportedInvitation(link: self.link, isPermanent: self.isPermanent, requestApproval: self.requestApproval, isRevoked: isRevoked, adminId: self.adminId, date: self.date, startDate: self.startDate, expireDate: self.expireDate, usageLimit: self.usageLimit, count: self.count, approvedDate: self.approvedDate) return ExportedInvitation(link: self.link, isPermanent: self.isPermanent, requestApproval: self.requestApproval, isRevoked: isRevoked, adminId: self.adminId, date: self.date, startDate: self.startDate, expireDate: self.expireDate, usageLimit: self.usageLimit, count: self.count, requestedCount: self.requestedCount)
} }
} }

View File

@ -11,6 +11,7 @@ private class AdMessagesHistoryContextImpl {
case textEntities case textEntities
case media case media
case authorId case authorId
case messageId
case startParam case startParam
} }
@ -19,6 +20,7 @@ private class AdMessagesHistoryContextImpl {
public let textEntities: [MessageTextEntity] public let textEntities: [MessageTextEntity]
public let media: [Media] public let media: [Media]
public let authorId: PeerId public let authorId: PeerId
public let messageId: MessageId?
public let startParam: String? public let startParam: String?
public init( public init(
@ -27,6 +29,7 @@ private class AdMessagesHistoryContextImpl {
textEntities: [MessageTextEntity], textEntities: [MessageTextEntity],
media: [Media], media: [Media],
authorId: PeerId, authorId: PeerId,
messageId: MessageId?,
startParam: String? startParam: String?
) { ) {
self.opaqueId = opaqueId self.opaqueId = opaqueId
@ -34,6 +37,7 @@ private class AdMessagesHistoryContextImpl {
self.textEntities = textEntities self.textEntities = textEntities
self.media = media self.media = media
self.authorId = authorId self.authorId = authorId
self.messageId = messageId
self.startParam = startParam self.startParam = startParam
} }
@ -51,7 +55,7 @@ private class AdMessagesHistoryContextImpl {
} }
self.authorId = try container.decode(PeerId.self, forKey: .authorId) self.authorId = try container.decode(PeerId.self, forKey: .authorId)
self.messageId = try container.decodeIfPresent(MessageId.self, forKey: .messageId)
self.startParam = try container.decodeIfPresent(String.self, forKey: .startParam) self.startParam = try container.decodeIfPresent(String.self, forKey: .startParam)
} }
@ -70,6 +74,7 @@ private class AdMessagesHistoryContextImpl {
try container.encode(mediaData, forKey: .media) try container.encode(mediaData, forKey: .media)
try container.encode(self.authorId, forKey: .authorId) try container.encode(self.authorId, forKey: .authorId)
try container.encodeIfPresent(self.messageId, forKey: .messageId)
try container.encodeIfPresent(self.startParam, forKey: .startParam) try container.encodeIfPresent(self.startParam, forKey: .startParam)
} }
@ -94,6 +99,9 @@ private class AdMessagesHistoryContextImpl {
if lhs.authorId != rhs.authorId { if lhs.authorId != rhs.authorId {
return false return false
} }
if lhs.messageId != rhs.messageId {
return false
}
if lhs.startParam != rhs.startParam { if lhs.startParam != rhs.startParam {
return false return false
} }
@ -317,7 +325,7 @@ private class AdMessagesHistoryContextImpl {
for message in messages { for message in messages {
switch message { switch message {
case let .sponsoredMessage(_, randomId, fromId, startParam, message, entities): case let .sponsoredMessage(_, randomId, fromId, channelPost, startParam, message, entities):
var parsedEntities: [MessageTextEntity] = [] var parsedEntities: [MessageTextEntity] = []
if let entities = entities { if let entities = entities {
parsedEntities = messageTextEntitiesFromApiEntities(entities) parsedEntities = messageTextEntitiesFromApiEntities(entities)
@ -337,6 +345,7 @@ private class AdMessagesHistoryContextImpl {
textEntities: parsedEntities, textEntities: parsedEntities,
media: parsedMedia, media: parsedMedia,
authorId: fromId.peerId, authorId: fromId.peerId,
messageId: channelPost.flatMap { MessageId(peerId: fromId.peerId, namespace: Namespaces.Message.Cloud, id: $0) },
startParam: startParam startParam: startParam
)) ))
} }

View File

@ -655,6 +655,8 @@ public struct PeerInvitationImportersState: Equatable {
public var waitingCount: Int { public var waitingCount: Int {
return importers.filter { $0.approvedBy == nil }.count return importers.filter { $0.approvedBy == nil }.count
} }
public static var Empty = PeerInvitationImportersState(importers: [], isLoadingMore: false, hasLoadedOnce: true, canLoadMore: false, count: 0)
} }
final class CachedPeerInvitationImporters: Codable { final class CachedPeerInvitationImporters: Codable {
@ -662,10 +664,10 @@ final class CachedPeerInvitationImporters: Codable {
let dates: [PeerId: Int32] let dates: [PeerId: Int32]
let count: Int32 let count: Int32
static func key(peerId: PeerId, link: String) -> ValueBoxKey { static func key(peerId: PeerId, link: String, requested: Bool) -> ValueBoxKey {
let key = ValueBoxKey(length: 8 + 4) let key = ValueBoxKey(length: 8 + 4)
key.setInt64(0, value: peerId.toInt64()) key.setInt64(0, value: peerId.toInt64())
key.setInt32(8, value: Int32(HashFunctions.murMurHash32(link))) key.setInt32(8, value: Int32(HashFunctions.murMurHash32(link + (requested ? "_requested" : ""))))
return key return key
} }
@ -722,6 +724,8 @@ private final class PeerInvitationImportersContextImpl {
private let account: Account private let account: Account
private let peerId: PeerId private let peerId: PeerId
private let link: String? private let link: String?
private let requested: Bool
private let query: String?
private let disposable = MetaDisposable() private let disposable = MetaDisposable()
private let updateDisposable = MetaDisposable() private let updateDisposable = MetaDisposable()
private let actionDisposables = DisposableSet() private let actionDisposables = DisposableSet()
@ -735,18 +739,34 @@ private final class PeerInvitationImportersContextImpl {
let state = Promise<PeerInvitationImportersState>() let state = Promise<PeerInvitationImportersState>()
init(queue: Queue, account: Account, peerId: PeerId, invite: ExportedInvitation?) { init(queue: Queue, account: Account, peerId: PeerId, subject: PeerInvitationImportersContext.Subject) {
self.queue = queue self.queue = queue
self.account = account self.account = account
self.peerId = peerId self.peerId = peerId
var invite: ExportedInvitation?
var requested = false
var query: String?
switch subject {
case let .invite(subjectInvite, subjectRequested):
invite = subjectInvite
requested = subjectRequested
case let .requests(maybeQuery):
query = maybeQuery
}
self.link = invite?.link self.link = invite?.link
self.requested = requested
self.query = query
let count = invite?.count ?? 0 let count = invite?.count ?? 0
self.count = count self.count = count
self.isLoadingMore = true self.isLoadingMore = true
self.disposable.set((account.postbox.transaction { transaction -> (peers: [PeerInvitationImportersState.Importer], count: Int32, canLoadMore: Bool)? in self.disposable.set((account.postbox.transaction { transaction -> (peers: [PeerInvitationImportersState.Importer], count: Int32, canLoadMore: Bool)? in
let cachedResult = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: invite?.link ?? "requests")))?.get(CachedPeerInvitationImporters.self) guard query == nil else {
return nil
}
let cachedResult = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: invite?.link ?? "requests", requested: self.requested)))?.get(CachedPeerInvitationImporters.self)
if let cachedResult = cachedResult, (Int(cachedResult.count) == count || invite == nil) { if let cachedResult = cachedResult, (Int(cachedResult.count) == count || invite == nil) {
var result: [PeerInvitationImportersState.Importer] = [] var result: [PeerInvitationImportersState.Importer] = []
for peerId in cachedResult.peerIds { for peerId in cachedResult.peerIds {
@ -794,6 +814,7 @@ private final class PeerInvitationImportersContextImpl {
let peerId = self.peerId let peerId = self.peerId
let link = self.link let link = self.link
let populateCache = self.populateCache let populateCache = self.populateCache
let query = self.query
var lastResult = self.results.last var lastResult = self.results.last
if self.loadedFromCache { if self.loadedFromCache {
@ -811,12 +832,19 @@ private final class PeerInvitationImportersContextImpl {
var flags: Int32 = 0 var flags: Int32 = 0
if let _ = link { if let _ = link {
if self.requested {
flags |= (1 << 0)
}
flags |= (1 << 1) flags |= (1 << 1)
} else { } else {
flags |= (1 << 0) flags |= (1 << 0)
} }
let signal = account.network.request(Api.functions.messages.getChatInviteImporters(flags: flags, peer: inputPeer, link: link, offsetDate: offsetDate, offsetUser: offsetUser, limit: lastResult == nil ? 10 : 50)) if let _ = query {
flags |= (1 << 2)
}
let signal = account.network.request(Api.functions.messages.getChatInviteImporters(flags: flags, peer: inputPeer, link: link, q: query, offsetDate: offsetDate, offsetUser: offsetUser, limit: lastResult == nil ? 10 : 50))
|> map(Optional.init) |> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.ChatInviteImporters?, NoError> in |> `catch` { _ -> Signal<Api.messages.ChatInviteImporters?, NoError> in
return .single(nil) return .single(nil)
@ -852,9 +880,9 @@ private final class PeerInvitationImportersContextImpl {
resultImporters.append(PeerInvitationImportersState.Importer(peer: RenderedPeer(peer: peer), date: date, about: about, approvedBy: approvedBy)) resultImporters.append(PeerInvitationImportersState.Importer(peer: RenderedPeer(peer: peer), date: date, about: about, approvedBy: approvedBy))
} }
} }
if populateCache { if populateCache && query == nil {
if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) { if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) {
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests")), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec) transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec)
} }
} }
return (resultImporters, count) return (resultImporters, count)
@ -906,7 +934,7 @@ private final class PeerInvitationImportersContextImpl {
} }
private func updateCache() { private func updateCache() {
guard self.hasLoadedOnce && !self.isLoadingMore else { guard self.hasLoadedOnce && !self.isLoadingMore && self.query == nil else {
return return
} }
@ -916,7 +944,7 @@ private final class PeerInvitationImportersContextImpl {
let link = self.link let link = self.link
self.updateDisposable.set(self.account.postbox.transaction({ transaction in self.updateDisposable.set(self.account.postbox.transaction({ transaction in
if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) { if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) {
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests")), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec) transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec)
} }
}).start()) }).start())
} }
@ -927,6 +955,11 @@ private final class PeerInvitationImportersContextImpl {
} }
public final class PeerInvitationImportersContext { public final class PeerInvitationImportersContext {
public enum Subject {
case invite(invite: ExportedInvitation, requested: Bool)
case requests(query: String?)
}
public enum UpdateAction { public enum UpdateAction {
case approve case approve
case deny case deny
@ -947,10 +980,10 @@ public final class PeerInvitationImportersContext {
} }
} }
init(account: Account, peerId: PeerId, invite: ExportedInvitation?) { init(account: Account, peerId: PeerId, subject: Subject) {
let queue = self.queue let queue = self.queue
self.impl = QueueLocalObject(queue: queue, generate: { self.impl = QueueLocalObject(queue: queue, generate: {
return PeerInvitationImportersContextImpl(queue: queue, account: account, peerId: peerId, invite: invite) return PeerInvitationImportersContextImpl(queue: queue, account: account, peerId: peerId, subject: subject)
}) })
} }

View File

@ -8,6 +8,7 @@ public enum JoinLinkError {
case generic case generic
case tooMuchJoined case tooMuchJoined
case tooMuchUsers case tooMuchUsers
case requestSent
} }
func apiUpdatesGroups(_ updates: Api.Updates) -> [Api.Chat] { func apiUpdatesGroups(_ updates: Api.Updates) -> [Api.Chat] {
@ -44,6 +45,8 @@ func _internal_joinChatInteractively(with hash: String, account: Account) -> Sig
return .tooMuchJoined return .tooMuchJoined
case "USERS_TOO_MUCH": case "USERS_TOO_MUCH":
return .tooMuchUsers return .tooMuchUsers
case "INVITE_REQUEST_SENT":
return .requestSent
default: default:
return .generic return .generic
} }

View File

@ -454,8 +454,8 @@ public extension TelegramEngine {
return _internal_revokePersistentPeerExportedInvitation(account: self.account, peerId: peerId) return _internal_revokePersistentPeerExportedInvitation(account: self.account, peerId: peerId)
} }
public func peerInvitationImporters(peerId: PeerId, invite: ExportedInvitation?) -> PeerInvitationImportersContext { public func peerInvitationImporters(peerId: PeerId, subject: PeerInvitationImportersContext.Subject) -> PeerInvitationImportersContext {
return PeerInvitationImportersContext(account: self.account, peerId: peerId, invite: invite) return PeerInvitationImportersContext(account: self.account, peerId: peerId, subject: subject)
} }
public func notificationExceptionsList() -> Signal<NotificationExceptionsList, NoError> { public func notificationExceptionsList() -> Signal<NotificationExceptionsList, NoError> {

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Requests@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -4802,7 +4802,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if canManageInvitations, let inviteRequestsPending = inviteRequestsPending, inviteRequestsPending >= 0, strongSelf.inviteRequestsContext == nil { if canManageInvitations, let inviteRequestsPending = inviteRequestsPending, inviteRequestsPending >= 0, strongSelf.inviteRequestsContext == nil {
let inviteRequestsContext = strongSelf.context.engine.peers.peerInvitationImporters(peerId: peerId, invite: nil) let inviteRequestsContext = strongSelf.context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: nil))
strongSelf.inviteRequestsContext = inviteRequestsContext strongSelf.inviteRequestsContext = inviteRequestsContext
strongSelf.inviteRequestsDisposable.set((inviteRequestsContext.state strongSelf.inviteRequestsDisposable.set((inviteRequestsContext.state

View File

@ -666,7 +666,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
if currentRequestsContext == nil { if currentRequestsContext == nil {
if canManageInvitations { if canManageInvitations {
let requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, invite: nil) let requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: nil))
requestsContextPromise.set(.single(requestsContext)) requestsContextPromise.set(.single(requestsContext))
requestsStatePromise.set(requestsContext.state |> map(Optional.init)) requestsStatePromise.set(requestsContext.state |> map(Optional.init))
} }
@ -843,7 +843,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
if currentRequestsContext == nil { if currentRequestsContext == nil {
if canManageInvitations { if canManageInvitations {
let requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, invite: nil) let requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: nil))
requestsContextPromise.set(.single(requestsContext)) requestsContextPromise.set(.single(requestsContext))
requestsStatePromise.set(requestsContext.state |> map(Optional.init)) requestsStatePromise.set(requestsContext.state |> map(Optional.init))
} }

View File

@ -1112,7 +1112,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
})) }))
if let count = data.requests?.count, count > 0 { if let count = data.requests?.count, count > 0 {
items[.peerInfo]!.append(PeerInfoScreenDisclosureItem(id: ItemMemberRequests, label: .badge(presentationStringsFormattedNumber(count, presentationData.dateTimeFormat.groupingSeparator), presentationData.theme.list.itemAccentColor), text: presentationData.strings.GroupInfo_MemberRequests, icon: UIImage(bundleImageName: "Chat/Info/GroupMembersIcon"), action: { items[.peerInfo]!.append(PeerInfoScreenDisclosureItem(id: ItemMemberRequests, label: .badge(presentationStringsFormattedNumber(count, presentationData.dateTimeFormat.groupingSeparator), presentationData.theme.list.itemAccentColor), text: presentationData.strings.GroupInfo_MemberRequests, icon: UIImage(bundleImageName: "Chat/Info/GroupRequestsIcon"), action: {
interaction.openParticipantsSection(.memberRequests) interaction.openParticipantsSection(.memberRequests)
})) }))
} }