Folder updates

This commit is contained in:
Ali
2023-03-28 23:41:04 +04:00
parent 8ca477e686
commit 4ccd0bd804
23 changed files with 606 additions and 237 deletions

View File

@@ -60,7 +60,7 @@ func _internal_exportChatFolder(account: Account, filterId: Int32, title: String
|> mapToSignal { inputPeers -> Signal<ExportedChatFolderLink, ExportChatFolderError> in
return account.network.request(Api.functions.communities.exportCommunityInvite(community: .inputCommunityDialogFilter(filterId: filterId), title: title, peers: inputPeers))
|> `catch` { error -> Signal<Api.communities.ExportedCommunityInvite, ExportChatFolderError> in
if error.errorDescription == "INVITES_TOO_MUCH" {
if error.errorDescription == "INVITES_TOO_MUCH" || error.errorDescription == "FILTERS_TOO_MUCH" {
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
}
@@ -69,10 +69,18 @@ func _internal_exportChatFolder(account: Account, filterId: Int32, title: String
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
if isPremium {
return .fail(.limitExceeded(limit: userPremiumLimits.maxSharedFolderInviteLinks, premiumLimit: userPremiumLimits.maxSharedFolderInviteLinks))
if error.errorDescription == "FILTERS_TOO_MUCH" {
if isPremium {
return .fail(.limitExceeded(limit: userPremiumLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
} else {
return .fail(.limitExceeded(limit: userDefaultLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
}
} else {
return .fail(.limitExceeded(limit: userDefaultLimits.maxSharedFolderInviteLinks, premiumLimit: userPremiumLimits.maxSharedFolderInviteLinks))
if isPremium {
return .fail(.limitExceeded(limit: userPremiumLimits.maxSharedFolderInviteLinks, premiumLimit: userPremiumLimits.maxSharedFolderInviteLinks))
} else {
return .fail(.limitExceeded(limit: userDefaultLimits.maxSharedFolderInviteLinks, premiumLimit: userPremiumLimits.maxSharedFolderInviteLinks))
}
}
}
} else {
@@ -246,7 +254,9 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
|> mapToSignal { result -> Signal<ChatFolderLinkContents, CheckChatFolderLinkError> in
return account.postbox.transaction { transaction -> ChatFolderLinkContents in
switch result {
case let .communityInvite(title, peers, chats, users):
case let .communityInvite(_, title, emoticon, peers, chats, users):
let _ = emoticon
var allPeers: [Peer] = []
var peerPresences: [PeerId: Api.User] = [:]
@@ -321,7 +331,7 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
if let peerValue = transaction.getPeer(peer.peerId) {
resultPeers.append(EnginePeer(peerValue))
if transaction.getPeerChatListIndex(peer.peerId) != nil {
if currentFilterPeers.contains(where: { $0 == peer.peerId }) && transaction.getPeerChatListIndex(peer.peerId) != nil {
alreadyMemberPeerIds.insert(peer.peerId)
}
}
@@ -407,74 +417,148 @@ func _internal_joinChatFolderLink(account: Account, slug: String, peerIds: [Engi
public final class ChatFolderUpdates: Equatable {
fileprivate let folderId: Int32
fileprivate let title: String
fileprivate let missingPeers: [Api.Peer]
fileprivate let chats: [Api.Chat]
fileprivate let users: [Api.User]
fileprivate let missingPeers: [EnginePeer]
public var availableChatsToJoin: Int {
return self.missingPeers.count
}
public var chatFolderLinkContents: ChatFolderLinkContents {
var peers: [EnginePeer] = []
for missingPeer in self.missingPeers {
for chat in chats {
if chat.peerId == missingPeer.peerId {
if let peer = parseTelegramGroupOrChannel(chat: chat) {
peers.append(EnginePeer(peer))
}
}
}
}
return ChatFolderLinkContents(localFilterId: self.folderId, title: self.title, peers: peers, alreadyMemberPeerIds: Set())
return ChatFolderLinkContents(localFilterId: self.folderId, title: self.title, peers: self.missingPeers, alreadyMemberPeerIds: Set())
}
fileprivate init(
folderId: Int32,
title: String,
missingPeers: [Api.Peer],
chats: [Api.Chat],
users: [Api.User]
missingPeers: [EnginePeer]
) {
self.folderId = folderId
self.title = title
self.missingPeers = missingPeers
self.chats = chats
self.users = users
}
public static func ==(lhs: ChatFolderUpdates, rhs: ChatFolderUpdates) -> Bool {
if lhs.folderId != rhs.folderId {
return false
}
if lhs.missingPeers.map(\.peerId) != rhs.missingPeers.map(\.peerId) {
if lhs.missingPeers.map(\.id) != rhs.missingPeers.map(\.id) {
return false
}
return true
}
}
func _internal_getChatFolderUpdates(account: Account, folderId: Int32) -> Signal<ChatFolderUpdates?, NoError> {
return account.network.request(Api.functions.communities.getCommunityUpdates(community: .inputCommunityDialogFilter(filterId: folderId)))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.communities.CommunityUpdates?, NoError> in
return .single(nil)
func _internal_pollChatFolderUpdatesOnce(account: Account, folderId: Int32) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> ChatListFiltersState in
return _internal_currentChatListFiltersState(transaction: transaction)
}
|> mapToSignal { result -> Signal<ChatFolderUpdates?, NoError> in
guard let result = result else {
|> mapToSignal { state -> Signal<Never, NoError> in
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
if let current = state.updates.first(where: { $0.folderId == folderId }) {
let updateInterval: Int32
#if DEBUG
updateInterval = 5
#else
updateInterval = 60 * 60
#endif
if current.timestamp + updateInterval >= timestamp {
return .complete()
}
}
return account.network.request(Api.functions.communities.getCommunityUpdates(community: .inputCommunityDialogFilter(filterId: folderId)))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.communities.CommunityUpdates?, NoError> in
return .single(nil)
}
switch result {
case let .communityUpdates(missingPeers, chats, users):
return account.postbox.transaction { transaction -> ChatFolderUpdates? in
for filter in _internal_currentChatListFilters(transaction: transaction) {
if case let .filter(id, title, _, _) = filter, id == folderId {
return ChatFolderUpdates(folderId: folderId, title: title, missingPeers: missingPeers, chats: chats, users: users)
}
|> mapToSignal { result -> Signal<Never, NoError> in
guard let result = result else {
return account.postbox.transaction { transaction -> Void in
let _ = updateChatListFiltersState(transaction: transaction, { state in
var state = state
state.updates.removeAll(where: { $0.folderId == folderId })
state.updates.append(ChatListFiltersState.ChatListFilterUpdates(folderId: folderId, timestamp: Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970), peerIds: []))
return state
})
}
return nil
|> ignoreValues
}
switch result {
case let .communityUpdates(missingPeers, chats, users):
return account.postbox.transaction { transaction -> Void in
var peers: [Peer] = []
var peerPresences: [PeerId: Api.User] = [:]
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
peerPresences[telegramUser.id] = user
}
for chat in chats {
if let peer = parseTelegramGroupOrChannel(chat: chat) {
peers.append(peer)
}
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated
})
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
let _ = updateChatListFiltersState(transaction: transaction, { state in
var state = state
state.updates.removeAll(where: { $0.folderId == folderId })
state.updates.append(ChatListFiltersState.ChatListFilterUpdates(folderId: folderId, timestamp: Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970), peerIds: missingPeers.map(\.peerId)))
return state
})
}
|> ignoreValues
}
}
}
}
func _internal_subscribedChatFolderUpdates(account: Account, folderId: Int32) -> Signal<ChatFolderUpdates?, NoError> {
struct InternalData: Equatable {
var title: String
var peerIds: [EnginePeer.Id]
}
return _internal_updatedChatListFiltersState(postbox: account.postbox)
|> map { state -> InternalData? in
guard let update = state.updates.first(where: { $0.folderId == folderId }) else {
return nil
}
guard let folder = state.filters.first(where: { $0.id == folderId }) else {
return nil
}
guard case let .filter(_, title, _, data) = folder, data.isShared else {
return nil
}
let filteredPeerIds: [PeerId] = update.peerIds.filter { !data.includePeers.peers.contains($0) }
return InternalData(title: title, peerIds: filteredPeerIds)
}
|> distinctUntilChanged
|> mapToSignal { internalData -> Signal<ChatFolderUpdates?, NoError> in
guard let internalData = internalData else {
return .single(nil)
}
if internalData.peerIds.isEmpty {
return .single(nil)
}
return account.postbox.transaction { transaction -> ChatFolderUpdates? in
var peers: [EnginePeer] = []
for peerId in internalData.peerIds {
if let peer = transaction.getPeer(peerId) {
peers.append(EnginePeer(peer))
}
}
return ChatFolderUpdates(folderId: folderId, title: internalData.title, missingPeers: peers)
}
}
}
@@ -530,11 +614,22 @@ func _internal_joinAvailableChatsInFolder(account: Account, updates: ChatFolderU
}
func _internal_hideChatFolderUpdates(account: Account, folderId: Int32) -> Signal<Never, NoError> {
return account.network.request(Api.functions.communities.hideCommunityUpdates(community: .inputCommunityDialogFilter(filterId: folderId)))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
return account.postbox.transaction { transaction -> Void in
let _ = updateChatListFiltersState(transaction: transaction, { state in
var state = state
state.updates.removeAll(where: { $0.folderId == folderId })
return state
})
}
|> mapToSignal { _ -> Signal<Never, NoError> in
return account.network.request(Api.functions.communities.hideCommunityUpdates(community: .inputCommunityDialogFilter(filterId: folderId)))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> ignoreValues
}
|> ignoreValues
}
func _internal_leaveChatFolder(account: Account, folderId: Int32, removePeerIds: [EnginePeer.Id]) -> Signal<Never, NoError> {