PeerInvitationImportersContext
struct
PeerInvitationImportersState
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public struct Importer: Equatable {
public var peer: RenderedPeer
public var date: Int32
public var about: String?
public var approvedBy: PeerId?
}
public var importers: [Importer]
public var isLoadingMore: Bool
public var hasLoadedOnce: Bool
public var canLoadMore: Bool
public var count: Int32
public static var Empty = PeerInvitationImportersState(importers: [], isLoadingMore: false, hasLoadedOnce: true, canLoadMore: false, count: 0)
// has doubts here for the isLoadingMore
public static var Loading = PeerInvitationImportersState(importers: [], isLoadingMore: false, hasLoadedOnce: false, canLoadMore: false, count: 0)
class
PeerInvitationImportersContextImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
private let queue: Queue
private let account: Account
// associated peerId
private let peerId: PeerId
// associated link
private let link: String?
// requested
private let requested: Bool
// query
private let query: String?
// disposable
private let disposable = MetaDisposable()
// update disposable set
private let updateDisposables = DisposableSet()
// action disposable set
private let actionDisposables = DisposableSet()
// is loading more
private var isLoadingMore: Bool = false
// has loaded more
private var hasLoadedOnce: Bool = false
// can load more
private var canLoadMore: Bool = true
// has loaded from cache
private var loadedFromCache = false
// results
private var results: [PeerInvitationImportersState.Importer] = []
// count
private var count: Int32
// populate cache
private var populateCache: Bool = true
// is main list
private var isMainList: Bool
let state = Promise<PeerExportedInvitationsState>()
init(queue: Queue, account: Account, peerId: PeerId, adminId: PeerId?, revoked: Bool, forceUpdate: Bool) {
self.queue = queue
self.account = account
self.peerId = peerId
self.adminId = adminId ?? account.peerId
self.revoked = revoked
self.forceUpdate = forceUpdate
// is main list
self.isMainList = adminId == nil
self.count = 0
if adminId == nil {
self.isLoadingMore = true
// load from cache
self.disposable.set((account.postbox.transaction { transaction -> CachedPeerExportedInvitations? in
return transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)))?.get(CachedPeerExportedInvitations.self)
}
|> deliverOn(self.queue)).start(next: { [weak self] cachedResult in
guard let strongSelf = self else {
return
}
strongSelf.isLoadingMore = false
if let cachedResult = cachedResult {
strongSelf.results = cachedResult.invitations
strongSelf.count = cachedResult.count
strongSelf.hasLoadedOnce = true
strongSelf.canLoadMore = cachedResult.canLoadMore
strongSelf.loadedFromCache = true
}
// load more
strongSelf.loadMore()
}))
}
// load more
self.loadMore()
}
// load more
func loadMore() {
if self.isLoadingMore {
return
}
self.isLoadingMore = true
let account = self.account
let peerId = self.peerId
let adminId = self.adminId
let revoked = self.revoked
var lastResult = self.results.last
if self.forceUpdate {// force update, load from start
self.populateCache = self.isMainList
self.forceUpdate = false
lastResult = nil // lastResult = nil
} else if self.loadedFromCache {
self.populateCache = false
self.loadedFromCache = false
}
let populateCache = self.populateCache
self.disposable.set((self.account.postbox.transaction { transaction -> (peerId: Api.InputPeer?, adminId: Api.InputUser?) in
return (transaction.getPeer(peerId).flatMap(apiInputPeer), transaction.getPeer(adminId).flatMap(apiInputUser))
}
|> mapToSignal { inputPeer, adminId -> Signal<([ExportedInvitation], Int32), NoError> in
if let inputPeer = inputPeer, let adminId = adminId {
let offsetLink = lastResult?.link
let offsetDate = lastResult?.date
var flags: Int32 = 0
if let _ = offsetLink {
flags |= (1 << 2)
}
if revoked {
flags |= (1 << 3)
}
// Api.functions.messages.getExportedChatInvites
let signal = account.network.request(Api.functions.messages.getExportedChatInvites(flags: flags, peer: inputPeer, adminId: adminId, offsetDate: offsetDate, offsetLink: offsetLink, limit: lastResult == nil ? 50 : 100))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.ExportedChatInvites?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<([ExportedInvitation], Int32), NoError> in
return account.postbox.transaction { transaction -> ([ExportedInvitation], Int32) in
guard let result = result else {
return ([], 0)
}
switch result {
case let .exportedChatInvites(count, invites, users):
var peers: [Peer] = []
for apiUser in users {
peers.append(TelegramUser(user: apiUser))
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
return updated
})
let invitations: [ExportedInvitation] = invites.compactMap { ExportedInvitation(apiExportedInvite: $0) }
if populateCache {// populate cache; put cache
if let entry = CodableEntry(CachedPeerExportedInvitations(invitations: invitations, canLoadMore: count >= 50, count: count)) {
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry, collectionSpec: cachedPeerExportedInvitationsCollectionSpec)
}
}
return (invitations, count)
}
}
}
return signal
} else {
return .single(([], 0))
}
}
|> deliverOn(self.queue)).start(next: { [weak self] invitations, updatedCount in
guard let strongSelf = self else {
return
}
if strongSelf.populateCache {
strongSelf.populateCache = false
strongSelf.results.removeAll()
}
var existingLinks = Set(strongSelf.results.map { $0.link })
for invitation in invitations {
if !existingLinks.contains(invitation.link) {
strongSelf.results.append(invitation)
existingLinks.insert(invitation.link)
}
}
strongSelf.isLoadingMore = false
strongSelf.hasLoadedOnce = true
strongSelf.canLoadMore = !invitations.isEmpty
if strongSelf.canLoadMore {
strongSelf.count = max(updatedCount, Int32(strongSelf.results.count))
} else {
strongSelf.count = Int32(strongSelf.results.count)
}
strongSelf.updateState()
if strongSelf.forceUpdate {
strongSelf.loadMore()
}
}))
self.updateState()
}
struct
ExportedInvitation
1
2
3
4
5
6
7
8
9
10
11
12
public let link: String
public let title: String?
public let isPermanent: Bool
public let requestApproval: Bool
public let isRevoked: Bool
public let adminId: PeerId
public let date: Int32
public let startDate: Int32?
public let expireDate: Int32?
public let usageLimit: Int32?
public let count: Int32?
public let requestedCount: Int32?
class
PeerInvitationImportersContext
1
2
3
4
5
6
7
8
9
10
11
12
public enum Subject {
case invite(invite: ExportedInvitation, requested: Bool)
case requests(query: String?)
}
public enum UpdateAction {
case approve
case deny
}
private let queue: Queue = Queue()
private let impl: QueueLocalObject<PeerInvitationImportersContextImpl>