Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2023-04-06 17:06:39 +04:00
commit f2225fad71
6 changed files with 120 additions and 28 deletions

View File

@ -1394,29 +1394,32 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
let context = strongSelf.context let context = strongSelf.context
let filterPeersAreMuted: Signal<Bool, NoError> = strongSelf.context.engine.peers.currentChatListFilters() let filterPeersAreMuted: Signal<(areMuted: Bool, peerIds: [EnginePeer.Id])?, NoError> = strongSelf.context.engine.peers.currentChatListFilters()
|> take(1) |> take(1)
|> mapToSignal { filters -> Signal<Bool, NoError> in |> mapToSignal { filters -> Signal<(areMuted: Bool, peerIds: [EnginePeer.Id])?, NoError> in
guard let filter = filters.first(where: { $0.id == id }) else { guard let filter = filters.first(where: { $0.id == id }) else {
return .single(false) return .single(nil)
} }
guard case let .filter(_, _, _, data) = filter else { guard case let .filter(_, _, _, data) = filter else {
return .single(false) return .single(nil)
} }
let filterPredicate: ChatListFilterPredicate = chatListFilterPredicate(filter: data)
return context.engine.peers.getChatListPeers(filterPredicate: filterPredicate)
|> mapToSignal { peers -> Signal<(areMuted: Bool, peerIds: [EnginePeer.Id])?, NoError> in
let peerIds = peers.map(\.id)
return context.engine.data.get( return context.engine.data.get(
EngineDataMap(data.includePeers.peers.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:))), EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init(id:))),
EngineDataMap(data.includePeers.peers.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init(id:))),
TelegramEngine.EngineData.Item.NotificationSettings.Global() TelegramEngine.EngineData.Item.NotificationSettings.Global()
) )
|> map { peers, list, globalSettings -> Bool in |> map { list, globalSettings -> (areMuted: Bool, peerIds: [EnginePeer.Id])? in
for peerId in data.includePeers.peers { for peer in peers {
switch list[peerId]?.muteState { switch list[peer.id]?.muteState {
case .unmuted: case .unmuted:
return false return (false, peerIds)
case .default: case .default:
if let peer = peers[peerId], let peerValue = peer {
let globalValue: EngineGlobalNotificationSettings.CategorySettings let globalValue: EngineGlobalNotificationSettings.CategorySettings
switch peerValue { switch peer {
case .user, .secretChat: case .user, .secretChat:
globalValue = globalSettings.privateChats globalValue = globalSettings.privateChats
case .legacyGroup: case .legacyGroup:
@ -1429,14 +1432,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
} }
if globalValue.enabled { if globalValue.enabled {
return false return (false, peerIds)
}
} }
default: default:
break break
} }
} }
return true return (true, peerIds)
}
} }
} }
@ -1600,9 +1603,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
for filter in filters { for filter in filters {
if filter.id == filterId, case let .filter(_, title, _, data) = filter { if filter.id == filterId, case let .filter(_, title, _, data) = filter {
if data.categories.isEmpty && !data.excludeRead && !data.excludeMuted && !data.excludeArchived && data.excludePeers.isEmpty && !data.includePeers.peers.isEmpty { if let filterPeersAreMuted {
items.append(.action(ContextMenuActionItem(text: filterPeersAreMuted ? "Unmute All" : "Mute All", textColor: .primary, badge: nil, icon: { theme in items.append(.action(ContextMenuActionItem(text: filterPeersAreMuted.areMuted ? "Unmute All" : "Mute All", textColor: .primary, badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: filterPeersAreMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor) return generateTintedImage(image: UIImage(bundleImageName: filterPeersAreMuted.areMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor)
}, action: { c, f in }, action: { c, f in
c.dismiss(completion: { c.dismiss(completion: {
}) })
@ -1611,7 +1614,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return return
} }
let _ = (strongSelf.context.engine.peers.updateMultiplePeerMuteSettings(peerIds: data.includePeers.peers, muted: !filterPeersAreMuted) let _ = (strongSelf.context.engine.peers.updateMultiplePeerMuteSettings(peerIds: filterPeersAreMuted.peerIds, muted: !filterPeersAreMuted.areMuted)
|> deliverOnMainQueue).start(completed: { |> deliverOnMainQueue).start(completed: {
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@ -1619,7 +1622,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let iconColor: UIColor = .white let iconColor: UIColor = .white
let overlayController: UndoOverlayController let overlayController: UndoOverlayController
if !filterPeersAreMuted { if !filterPeersAreMuted.areMuted {
overlayController = UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_profilemute", scale: 0.075, colors: [ overlayController = UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_profilemute", scale: 0.075, colors: [
"Middle.Group 1.Fill 1": iconColor, "Middle.Group 1.Fill 1": iconColor,
"Top.Group 1.Fill 1": iconColor, "Top.Group 1.Fill 1": iconColor,
@ -2827,6 +2830,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self?.push(c) self?.push(c)
}, presentController: { [weak self] c in }, presentController: { [weak self] c in
self?.present(c, in: .window(.root)) self?.present(c, in: .window(.root))
}, pushPremiumController: { [weak self] c in
self?.push(c)
}, completed: { }, completed: {
}, linkUpdated: { _ in }, linkUpdated: { _ in
}) })

View File

@ -1155,6 +1155,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
var applyImpl: ((Bool, @escaping () -> Void) -> Void)? var applyImpl: ((Bool, @escaping () -> Void) -> Void)?
var getControllerImpl: (() -> ViewController?)? var getControllerImpl: (() -> ViewController?)?
var presentInGlobalOverlayImpl: ((ViewController) -> Void)? var presentInGlobalOverlayImpl: ((ViewController) -> Void)?
var pushPremiumController: ((ViewController) -> Void)?
let sharedLinks = Promise<[ExportedChatFolderLink]?>(nil) let sharedLinks = Promise<[ExportedChatFolderLink]?>(nil)
if let initialPreset { if let initialPreset {
@ -1385,7 +1386,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
let state = stateValue.with({ $0 }) let state = stateValue.with({ $0 })
if state.additionallyIncludePeers.isEmpty { if state.additionallyIncludePeers.isEmpty {
//TODO:localize //TODO:localize
let text = "Please add chats to this folder to share it." let text = "You cant share folders which have chat types or excluded chats."
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
return return
@ -1424,6 +1425,8 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
pushControllerImpl?(c) pushControllerImpl?(c)
}, presentController: { c in }, presentController: { c in
presentControllerImpl?(c, nil) presentControllerImpl?(c, nil)
}, pushPremiumController: { c in
pushPremiumController?(c)
}, completed: { }, completed: {
statusController?.dismiss() statusController?.dismiss()
statusController = nil statusController = nil
@ -1769,6 +1772,11 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
controller.presentInGlobalOverlay(c) controller.presentInGlobalOverlay(c)
} }
} }
pushPremiumController = { [weak controller] c in
if let controller = controller {
controller.replace(with: c)
}
}
attemptNavigationImpl = { f in attemptNavigationImpl = { f in
let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in let _ = (updatedCurrentPreset |> take(1) |> deliverOnMainQueue).start(next: { currentPreset in
let state = stateValue.with { $0 } let state = stateValue.with { $0 }
@ -1803,7 +1811,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
return controller return controller
} }
func openCreateChatListFolderLink(context: AccountContext, folderId: Int32, checkIfExists: Bool, title: String, peerIds: [EnginePeer.Id], pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController) -> Void, completed: @escaping () -> Void, linkUpdated: @escaping (ExportedChatFolderLink?) -> Void) { func openCreateChatListFolderLink(context: AccountContext, folderId: Int32, checkIfExists: Bool, title: String, peerIds: [EnginePeer.Id], pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController) -> Void, pushPremiumController: @escaping (ViewController) -> Void, completed: @escaping () -> Void, linkUpdated: @escaping (ExportedChatFolderLink?) -> Void) {
if peerIds.isEmpty { if peerIds.isEmpty {
completed() completed()
return return
@ -1898,24 +1906,28 @@ func openCreateChatListFolderLink(context: AccountContext, folderId: Int32, chec
text = "An error occurred" text = "An error occurred"
case let .sharedFolderLimitExceeded(limit, _): case let .sharedFolderLimitExceeded(limit, _):
let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .membershipInSharedFolders, count: limit, action: { let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .membershipInSharedFolders, count: limit, action: {
pushPremiumController(PremiumIntroScreen(context: context, source: .membershipInSharedFolders))
}) })
pushController(limitController) pushController(limitController)
return return
case let .limitExceeded(limit, _): case let .limitExceeded(limit, _):
let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .linksPerSharedFolder, count: limit, action: { let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .linksPerSharedFolder, count: limit, action: {
pushPremiumController(PremiumIntroScreen(context: context, source: .linksPerSharedFolder))
}) })
pushController(limitController) pushController(limitController)
return return
case let .tooManyChannels(limit, _): case let .tooManyChannels(limit, _):
let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .linksPerSharedFolder, count: limit, action: { let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .linksPerSharedFolder, count: limit, action: {
pushPremiumController(PremiumIntroScreen(context: context, source: .groupsAndChannels))
}) })
pushController(limitController) pushController(limitController)
return return
case let .tooManyChannelsInAccount(limit, _): case let .tooManyChannelsInAccount(limit, _):
let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .channels, count: limit, action: { let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .channels, count: limit, action: {
pushPremiumController(PremiumIntroScreen(context: context, source: .groupsAndChannels))
}) })
pushController(limitController) pushController(limitController)

View File

@ -265,6 +265,50 @@ final class ChatListTable: Table {
} }
} }
func getChatListPeers(postbox: PostboxImpl, currentTransaction: Transaction, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?) -> [Peer] {
let globalNotificationSettings = postbox.getGlobalNotificationSettings(transaction: currentTransaction)
var result: [Peer] = []
self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), keys: { key in
let (_, _, messageIndex, _) = extractKey(key)
if let peer = postbox.peerTable.get(messageIndex.id.peerId) {
//let state = postbox.readStateTable.getCombinedState(messageIndex.id.peerId), state.isUnread
var passFilter: Bool
if let filterPredicate = filterPredicate {
let isUnread = postbox.readStateTable.getCombinedState(messageIndex.id.peerId)?.isUnread ?? false
let isContact = postbox.contactsTable.isContact(peerId: messageIndex.id.peerId)
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(messageIndex.id.peerId))
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, threadId: nil, calculation: filterPredicate.messageTagSummary)
if filterPredicate.pinnedPeerIds.contains(peer.id) {
passFilter = true
} else if filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: messageTagSummaryResult) {
passFilter = true
} else {
passFilter = false
}
} else {
passFilter = true
}
if passFilter, let additionalFilter = additionalFilter {
if !additionalFilter(peer) {
passFilter = false
}
}
if passFilter {
result.append(peer)
}
}
return true
}, limit: 0)
return result
}
func getUnreadChatListPeerIds(postbox: PostboxImpl, currentTransaction: Transaction, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?, stopOnFirstMatch: Bool) -> [PeerId] { func getUnreadChatListPeerIds(postbox: PostboxImpl, currentTransaction: Transaction, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?, stopOnFirstMatch: Bool) -> [PeerId] {
let globalNotificationSettings = postbox.getGlobalNotificationSettings(transaction: currentTransaction) let globalNotificationSettings = postbox.getGlobalNotificationSettings(transaction: currentTransaction)

View File

@ -389,6 +389,15 @@ public final class Transaction {
return self.postbox?.chatListTable.getPeerChatListIndex(peerId: peerId) return self.postbox?.chatListTable.getPeerChatListIndex(peerId: peerId)
} }
public func getChatListPeers(groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?) -> [Peer] {
assert(!self.disposed)
if let postbox = self.postbox {
return postbox.chatListTable.getChatListPeers(postbox: postbox, currentTransaction: self, groupId: groupId, filterPredicate: filterPredicate, additionalFilter: additionalFilter)
} else {
return []
}
}
public func getUnreadChatListPeerIds(groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?, stopOnFirstMatch: Bool) -> [PeerId] { public func getUnreadChatListPeerIds(groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?, stopOnFirstMatch: Bool) -> [PeerId] {
assert(!self.disposed) assert(!self.disposed)
if let postbox = self.postbox { if let postbox = self.postbox {

View File

@ -3405,6 +3405,22 @@ func replayFinalState(
for (space, _) in holesAtHistoryStart { for (space, _) in holesAtHistoryStart {
transaction.removeHole(peerId: chatPeerId, threadId: nil, namespace: Namespaces.Message.Cloud, space: space, range: 1 ... id.id) transaction.removeHole(peerId: chatPeerId, threadId: nil, namespace: Namespaces.Message.Cloud, space: space, range: 1 ... id.id)
} }
case let .setChatWallpaper(wallpaper):
if chatPeerId == accountPeerId {
transaction.updatePeerCachedData(peerIds: [message.id.peerId], update: { peerId, current in
var current = current
if current == nil {
if peerId.namespace == Namespaces.Peer.CloudUser {
current = CachedUserData()
}
}
if let cachedData = current as? CachedUserData {
return cachedData.withUpdatedWallpaper(wallpaper)
} else {
return current
}
})
}
default: default:
break break
} }

View File

@ -650,6 +650,12 @@ public extension TelegramEngine {
return _internal_updateBotAbout(account: self.account, peerId: peerId, about: about) return _internal_updateBotAbout(account: self.account, peerId: peerId, about: about)
} }
public func getChatListPeers(filterPredicate: ChatListFilterPredicate) -> Signal<[EnginePeer], NoError> {
return self.account.postbox.transaction { transaction -> [EnginePeer] in
return transaction.getChatListPeers(groupId: .root, filterPredicate: filterPredicate, additionalFilter: nil).map(EnginePeer.init)
}
}
public func getNextUnreadChannel(peerId: PeerId, chatListFilterId: Int32?, getFilterPredicate: @escaping (ChatListFilterData) -> ChatListFilterPredicate) -> Signal<(peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)?, NoError> { public func getNextUnreadChannel(peerId: PeerId, chatListFilterId: Int32?, getFilterPredicate: @escaping (ChatListFilterData) -> ChatListFilterPredicate) -> Signal<(peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)?, NoError> {
return self.account.postbox.transaction { transaction -> (peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)? in return self.account.postbox.transaction { transaction -> (peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)? in
func getForFilter(predicate: ChatListFilterPredicate?, isArchived: Bool) -> (peer: EnginePeer, unreadCount: Int)? { func getForFilter(predicate: ChatListFilterPredicate?, isArchived: Bool) -> (peer: EnginePeer, unreadCount: Int)? {