Refactoring

This commit is contained in:
Ali 2022-05-29 21:09:11 +04:00
parent 5eb4bbeaae
commit dfad27f9e8
24 changed files with 344 additions and 258 deletions

View File

@ -78,7 +78,7 @@ private enum ChannelAdminEntryStableId: Hashable {
} }
private enum ChannelAdminEntry: ItemListNodeEntry { private enum ChannelAdminEntry: ItemListNodeEntry {
case info(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, TelegramUserPresence?) case info(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, EnginePeer, EnginePeer.Presence?)
case rankTitle(PresentationTheme, String, Int32?, Int32) case rankTitle(PresentationTheme, String, Int32?, Int32)
case rank(PresentationTheme, PresentationStrings, String, String, Bool) case rank(PresentationTheme, PresentationStrings, String, String, Bool)
case rankInfo(PresentationTheme, String, Bool) case rankInfo(PresentationTheme, String, Bool)
@ -144,7 +144,7 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
if lhsDateTimeFormat != rhsDateTimeFormat { if lhsDateTimeFormat != rhsDateTimeFormat {
return false return false
} }
if !arePeersEqual(lhsPeer, rhsPeer) { if lhsPeer != rhsPeer {
return false return false
} }
if lhsPresence != rhsPresence { if lhsPresence != rhsPresence {
@ -309,7 +309,7 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
let arguments = arguments as! ChannelAdminControllerArguments let arguments = arguments as! ChannelAdminControllerArguments
switch self { switch self {
case let .info(_, _, dateTimeFormat, peer, presence): case let .info(_, _, dateTimeFormat, peer, presence):
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: EnginePeer(peer), presence: presence.flatMap(EnginePeer.Presence.init), memberCount: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, memberCount: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
}, avatarTapped: { }, avatarTapped: {
}) })
case let .rankTitle(_, text, count, limit): case let .rankTitle(_, text, count, limit):
@ -534,11 +534,11 @@ private func areAllAdminRightsEnabled(_ flags: TelegramChatAdminRightsFlags, gro
} }
} }
private func channelAdminControllerEntries(presentationData: PresentationData, state: ChannelAdminControllerState, accountPeerId: PeerId, channelView: PeerView, adminView: PeerView, initialParticipant: ChannelParticipant?, invite: Bool, canEdit: Bool) -> [ChannelAdminEntry] { private func channelAdminControllerEntries(presentationData: PresentationData, state: ChannelAdminControllerState, accountPeerId: PeerId, channelPeer: EnginePeer?, adminPeer: EnginePeer?, adminPresence: EnginePeer.Presence?, initialParticipant: ChannelParticipant?, invite: Bool, canEdit: Bool) -> [ChannelAdminEntry] {
var entries: [ChannelAdminEntry] = [] var entries: [ChannelAdminEntry] = []
if let channel = channelView.peers[channelView.peerId] as? TelegramChannel, let admin = adminView.peers[adminView.peerId] { if case let .channel(channel) = channelPeer, let admin = adminPeer {
entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, admin, adminView.peerPresences[admin.id] as? TelegramUserPresence)) entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, admin, adminPresence))
var isChannel = false var isChannel = false
if case .broadcast = channel.info { if case .broadcast = channel.info {
@ -618,7 +618,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
} }
} }
} else { } else {
if let adminPeer = adminView.peers[adminView.peerId] as? TelegramUser, adminPeer.botInfo != nil, case .group = channel.info, invite, let channelPeer = channelView.peers[channelView.peerId], canEditAdminRights(accountPeerId: accountPeerId, channelPeer: channelPeer, initialParticipant: initialParticipant) { if case let .user(adminPeer) = adminPeer, adminPeer.botInfo != nil, case .group = channel.info, invite, let channelPeer = channelPeer, canEditAdminRights(accountPeerId: accountPeerId, channelPeer: channelPeer._asPeer(), initialParticipant: initialParticipant) {
if let initialParticipant = initialParticipant, case let .member(_, _, adminInfo, _, _) = initialParticipant, adminInfo != nil { if let initialParticipant = initialParticipant, case let .member(_, _, adminInfo, _, _) = initialParticipant, adminInfo != nil {
} else { } else {
@ -629,7 +629,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
if !invite || state.adminRights { if !invite || state.adminRights {
entries.append(.rightsTitle(presentationData.theme, presentationData.strings.Channel_EditAdmin_PermissionsHeader)) entries.append(.rightsTitle(presentationData.theme, presentationData.strings.Channel_EditAdmin_PermissionsHeader))
if let channelPeer = channelView.peers[channelView.peerId], canEditAdminRights(accountPeerId: accountPeerId, channelPeer: channelPeer, initialParticipant: initialParticipant) { if let channelPeer = channelPeer, canEditAdminRights(accountPeerId: accountPeerId, channelPeer: channelPeer._asPeer(), initialParticipant: initialParticipant) {
let accountUserRightsFlags: TelegramChatAdminRightsFlags let accountUserRightsFlags: TelegramChatAdminRightsFlags
if channel.flags.contains(.isCreator) { if channel.flags.contains(.isCreator) {
accountUserRightsFlags = maskRightsFlags accountUserRightsFlags = maskRightsFlags
@ -660,7 +660,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
entries.append(.addAdminsInfo(presentationData.theme, currentRightsFlags.contains(.canAddAdmins) ? presentationData.strings.Channel_EditAdmin_PermissinAddAdminOn : presentationData.strings.Channel_EditAdmin_PermissinAddAdminOff)) entries.append(.addAdminsInfo(presentationData.theme, currentRightsFlags.contains(.canAddAdmins) ? presentationData.strings.Channel_EditAdmin_PermissinAddAdminOn : presentationData.strings.Channel_EditAdmin_PermissinAddAdminOff))
} }
if let admin = admin as? TelegramUser, admin.botInfo == nil && !admin.isDeleted && channel.flags.contains(.isCreator) && areAllAdminRightsEnabled(currentRightsFlags, group: isGroup, except: .canBeAnonymous) { if case let .user(admin) = admin, admin.botInfo == nil && !admin.isDeleted && channel.flags.contains(.isCreator) && areAllAdminRightsEnabled(currentRightsFlags, group: isGroup, except: .canBeAnonymous) {
canTransfer = true canTransfer = true
} }
@ -717,8 +717,8 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
if canDismiss { if canDismiss {
entries.append(.dismiss(presentationData.theme, presentationData.strings.Channel_Moderator_AccessLevelRevoke)) entries.append(.dismiss(presentationData.theme, presentationData.strings.Channel_Moderator_AccessLevelRevoke))
} }
} else if let group = channelView.peers[channelView.peerId] as? TelegramGroup, let admin = adminView.peers[adminView.peerId] { } else if case let .legacyGroup(group) = channelPeer, let admin = adminPeer {
entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, admin, adminView.peerPresences[admin.id] as? TelegramUserPresence)) entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, admin, adminPresence))
var isCreator = false var isCreator = false
if let initialParticipant = initialParticipant, case .creator = initialParticipant { if let initialParticipant = initialParticipant, case .creator = initialParticipant {
@ -738,7 +738,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
entries.append(.rankTitle(presentationData.theme, presentationData.strings.Group_EditAdmin_RankTitle.uppercased(), rankEnabled && state.focusedOnRank ? Int32(currentRank?.count ?? 0) : nil, rankMaxLength)) entries.append(.rankTitle(presentationData.theme, presentationData.strings.Group_EditAdmin_RankTitle.uppercased(), rankEnabled && state.focusedOnRank ? Int32(currentRank?.count ?? 0) : nil, rankMaxLength))
entries.append(.rank(presentationData.theme, presentationData.strings, isCreator ? presentationData.strings.Group_EditAdmin_RankOwnerPlaceholder : presentationData.strings.Group_EditAdmin_RankAdminPlaceholder, currentRank ?? "", rankEnabled)) entries.append(.rank(presentationData.theme, presentationData.strings, isCreator ? presentationData.strings.Group_EditAdmin_RankOwnerPlaceholder : presentationData.strings.Group_EditAdmin_RankAdminPlaceholder, currentRank ?? "", rankEnabled))
} else { } else {
if let adminPeer = adminView.peers[adminView.peerId] as? TelegramUser, adminPeer.botInfo != nil, invite { if case let .user(adminPeer) = adminPeer, adminPeer.botInfo != nil, invite {
if let initialParticipant = initialParticipant, case let .member(_, _, adminRights, _, _) = initialParticipant, adminRights != nil { if let initialParticipant = initialParticipant, case let .member(_, _, adminRights, _, _) = initialParticipant, adminRights != nil {
} else { } else {
@ -791,7 +791,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
entries.append(.addAdminsInfo(presentationData.theme, currentRightsFlags.contains(.canAddAdmins) ? presentationData.strings.Channel_EditAdmin_PermissinAddAdminOn : presentationData.strings.Channel_EditAdmin_PermissinAddAdminOff)) entries.append(.addAdminsInfo(presentationData.theme, currentRightsFlags.contains(.canAddAdmins) ? presentationData.strings.Channel_EditAdmin_PermissinAddAdminOn : presentationData.strings.Channel_EditAdmin_PermissinAddAdminOff))
} }
if let admin = admin as? TelegramUser, case .creator = group.role, admin.botInfo == nil && !admin.isDeleted && areAllAdminRightsEnabled(currentRightsFlags, group: true, except: .canBeAnonymous) { if case let .user(admin) = admin, case .creator = group.role, admin.botInfo == nil && !admin.isDeleted && areAllAdminRightsEnabled(currentRightsFlags, group: true, except: .canBeAnonymous) {
entries.append(.transfer(presentationData.theme, presentationData.strings.Group_EditAdmin_TransferOwnership)) entries.append(.transfer(presentationData.theme, presentationData.strings.Group_EditAdmin_TransferOwnership))
} }
@ -955,15 +955,23 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
errorImpl?() errorImpl?()
}) })
let combinedView = context.account.postbox.combinedView(keys: [.peer(peerId: peerId, components: .all), .peer(peerId: adminId, components: .all)])
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
let signal = combineLatest(presentationData, statePromise.get(), combinedView) let signal = combineLatest(
queue: .mainQueue(),
presentationData,
statePromise.get(),
context.engine.data.subscribe(
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId),
TelegramEngine.EngineData.Item.Peer.Peer(id: adminId),
TelegramEngine.EngineData.Item.Peer.Presence(id: adminId)
)
)
|> deliverOnMainQueue |> deliverOnMainQueue
|> map { presentationData, state, combinedView -> (ItemListControllerState, (ItemListNodeState, Any)) in |> map { presentationData, state, peerInfoData -> (ItemListControllerState, (ItemListNodeState, Any)) in
let channelView = combinedView.views[.peer(peerId: peerId, components: .all)] as! PeerView let channelPeer = peerInfoData.0.flatMap { $0 }
let adminView = combinedView.views[.peer(peerId: adminId, components: .all)] as! PeerView let adminPeer = peerInfoData.1.flatMap { $0 }
let canEdit = canEditAdminRights(accountPeerId: context.account.peerId, channelPeer: channelView.peers[channelView.peerId]!, initialParticipant: initialParticipant) let adminPresence = peerInfoData.2
let canEdit = canEditAdminRights(accountPeerId: context.account.peerId, channelPeer: channelPeer!._asPeer(), initialParticipant: initialParticipant)
let leftNavigationButton: ItemListNavigationButton let leftNavigationButton: ItemListNavigationButton
if canEdit { if canEdit {
@ -986,8 +994,9 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
updateState { current in updateState { current in
return current.withUpdatedUpdating(true) return current.withUpdatedUpdating(true)
} }
if let channel = channelView.peers[channelView.peerId] as? TelegramChannel { if case let .channel(channel) = channelPeer {
updateRightsDisposable.set((context.engine.peers.addChannelMember(peerId: peerId, memberId: adminId) |> deliverOnMainQueue).start(error: { error in updateRightsDisposable.set((context.engine.peers.addChannelMember(peerId: peerId, memberId: adminId)
|> deliverOnMainQueue).start(error: { error in
updateState { current in updateState { current in
return current.withUpdatedUpdating(false) return current.withUpdatedUpdating(false)
} }
@ -998,12 +1007,12 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
case .tooMuchJoined: case .tooMuchJoined:
text = presentationData.strings.Group_ErrorSupergroupConversionNotPossible text = presentationData.strings.Group_ErrorSupergroupConversionNotPossible
case .restricted: case .restricted:
if let admin = adminView.peers[adminView.peerId] { if let admin = adminPeer {
switch channel.info { switch channel.info {
case .broadcast: case .broadcast:
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
case .group: case .group:
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
} }
} }
case .notMutualContact: case .notMutualContact:
@ -1020,20 +1029,20 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
updated(nil) updated(nil)
dismissImpl?() dismissImpl?()
})) }))
} else if let _ = channelView.peers[channelView.peerId] as? TelegramGroup { } else if case .legacyGroup = channelPeer {
updateRightsDisposable.set((context.engine.peers.addGroupMember(peerId: peerId, memberId: adminId) |> deliverOnMainQueue).start(error: { error in updateRightsDisposable.set((context.engine.peers.addGroupMember(peerId: peerId, memberId: adminId) |> deliverOnMainQueue).start(error: { error in
updateState { current in updateState { current in
return current.withUpdatedUpdating(false) return current.withUpdatedUpdating(false)
} }
if case .privacy = error, let admin = adminView.peers[adminView.peerId] { if case .privacy = error, let admin = adminPeer {
presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
} }
}, completed: { }, completed: {
updated(nil) updated(nil)
dismissImpl?() dismissImpl?()
})) }))
} }
} else if let channel = channelView.peers[channelView.peerId] as? TelegramChannel { } else if case let .channel(channel) = channelPeer {
if let initialParticipant = initialParticipant { if let initialParticipant = initialParticipant {
var updateFlags: TelegramChatAdminRightsFlags? var updateFlags: TelegramChatAdminRightsFlags?
var updateRank: String? var updateRank: String?
@ -1105,12 +1114,12 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
case .tooMuchJoined: case .tooMuchJoined:
text = presentationData.strings.Group_ErrorSupergroupConversionNotPossible text = presentationData.strings.Group_ErrorSupergroupConversionNotPossible
case .restricted: case .restricted:
if let admin = adminView.peers[adminView.peerId] { if let admin = adminPeer {
switch channel.info { switch channel.info {
case .broadcast: case .broadcast:
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
case .group: case .group:
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
} }
} }
case .notMutualContact: case .notMutualContact:
@ -1184,7 +1193,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
return current.withUpdatedUpdating(true) return current.withUpdatedUpdating(true)
} }
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { error in updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { error in
if case let .addMemberError(addMemberError) = error, let admin = adminView.peers[adminView.peerId] { if case let .addMemberError(addMemberError) = error, let admin = adminPeer {
var text = presentationData.strings.Login_UnknownError var text = presentationData.strings.Login_UnknownError
switch addMemberError { switch addMemberError {
case .tooMuchJoined: case .tooMuchJoined:
@ -1192,9 +1201,9 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
case .restricted: case .restricted:
switch channel.info { switch channel.info {
case .broadcast: case .broadcast:
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
case .group: case .group:
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
} }
case .notMutualContact: case .notMutualContact:
if case .broadcast = channel.info { if case .broadcast = channel.info {
@ -1222,7 +1231,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
})) }))
} }
} }
} else if let _ = channelView.peers[channelView.peerId] as? TelegramGroup { } else if case .legacyGroup = channelPeer {
var updateFlags: TelegramChatAdminRightsFlags? var updateFlags: TelegramChatAdminRightsFlags?
var updateRank: String? var updateRank: String?
updateState { current in updateState { current in
@ -1252,8 +1261,8 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
} }
updateRightsDisposable.set((context.engine.peers.addGroupAdmin(peerId: peerId, adminId: adminId) updateRightsDisposable.set((context.engine.peers.addGroupAdmin(peerId: peerId, adminId: adminId)
|> deliverOnMainQueue).start(error: { error in |> deliverOnMainQueue).start(error: { error in
if case let .addMemberError(error) = error, case .privacy = error, let admin = adminView.peers[adminView.peerId] { if case let .addMemberError(error) = error, case .privacy = error, let admin = adminPeer {
presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
} else if case .adminsTooMuch = error { } else if case .adminsTooMuch = error {
presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Group_ErrorAdminsTooMuch, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Group_ErrorAdminsTooMuch, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
} }
@ -1312,8 +1321,8 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
case let .direct(error): case let .direct(error):
if case let .addMemberError(error) = error { if case let .addMemberError(error) = error {
var text = presentationData.strings.Login_UnknownError var text = presentationData.strings.Login_UnknownError
if case .restricted = error, let admin = adminView.peers[adminView.peerId] { if case .restricted = error, let admin = adminPeer {
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(admin).compactDisplayTitle, EnginePeer(admin).compactDisplayTitle).string text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
} else if case .tooMuchJoined = error { } else if case .tooMuchJoined = error {
text = presentationData.strings.Invite_ChannelsTooMuch text = presentationData.strings.Invite_ChannelsTooMuch
} else if case .kicked = error { } else if case .kicked = error {
@ -1353,17 +1362,17 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
if initialParticipant?.adminInfo == nil { if initialParticipant?.adminInfo == nil {
var isGroup: Bool = false var isGroup: Bool = false
var peerTitle: String = "" var peerTitle: String = ""
if let peer = channelView.peers[channelView.peerId] as? TelegramGroup { if case let .legacyGroup(peer) = channelPeer {
isGroup = true isGroup = true
peerTitle = peer.title peerTitle = peer.title
} else if let peer = channelView.peers[channelView.peerId] as? TelegramChannel { } else if case let .channel(peer) = channelPeer {
if case .group = peer.info { if case .group = peer.info {
isGroup = true isGroup = true
} }
peerTitle = peer.title peerTitle = peer.title
} }
if let admin = adminView.peers[adminView.peerId] as? TelegramUser, admin.botInfo != nil && invite { if case let .user(admin) = adminPeer, admin.botInfo != nil && invite {
title = presentationData.strings.Bot_AddToChat_Add_Title title = presentationData.strings.Bot_AddToChat_Add_Title
rightNavigationButton = nil rightNavigationButton = nil
footerItem = ChannelAdminAddBotFooterItem(theme: presentationData.theme, title: state.adminRights ? presentationData.strings.Bot_AddToChat_Add_AddAsAdmin : presentationData.strings.Bot_AddToChat_Add_AddAsMember, action: { footerItem = ChannelAdminAddBotFooterItem(theme: presentationData.theme, title: state.adminRights ? presentationData.strings.Bot_AddToChat_Add_AddAsAdmin : presentationData.strings.Bot_AddToChat_Add_AddAsMember, action: {
@ -1395,7 +1404,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelAdminControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, adminView: adminView, initialParticipant: initialParticipant, invite: invite, canEdit: canEdit), style: .blocks, focusItemTag: focusItemTag, ensureVisibleItemTag: nil, emptyStateItem: nil, footerItem: footerItem, animateChanges: true) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelAdminControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelPeer: channelPeer, adminPeer: adminPeer, adminPresence: adminPresence, initialParticipant: initialParticipant, invite: invite, canEdit: canEdit), style: .blocks, focusItemTag: focusItemTag, ensureVisibleItemTag: nil, emptyStateItem: nil, footerItem: footerItem, animateChanges: true)
return (controllerState, (listState, arguments)) return (controllerState, (listState, arguments))
} }

View File

@ -417,10 +417,17 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
}) })
} }
let preferencesKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.localizationListState]))
let previousState = Atomic<LocalizationListState?>(value: nil) let previousState = Atomic<LocalizationListState?>(value: nil)
let previousEntriesHolder = Atomic<([LanguageListEntry], PresentationTheme, PresentationStrings)?>(value: nil) let previousEntriesHolder = Atomic<([LanguageListEntry], PresentationTheme, PresentationStrings)?>(value: nil)
self.listDisposable = combineLatest(queue: .mainQueue(), context.account.postbox.combinedView(keys: [preferencesKey]), context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.localizationSettings, ApplicationSpecificSharedDataKeys.translationSettings]), self.presentationDataValue.get(), self.applyingCode.get(), revealedCode.get(), self.isEditing.get()).start(next: { [weak self] view, sharedData, presentationData, applyingCode, revealedCode, isEditing in self.listDisposable = combineLatest(
queue: .mainQueue(),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.LocalizationList()),
context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.localizationSettings, ApplicationSpecificSharedDataKeys.translationSettings]),
self.presentationDataValue.get(),
self.applyingCode.get(),
revealedCode.get(),
self.isEditing.get()
).start(next: { [weak self] localizationListState, sharedData, presentationData, applyingCode, revealedCode, isEditing in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -449,8 +456,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
} }
} }
let localizationListState = (view.views[preferencesKey] as? PreferencesView)?.values[PreferencesKeys.localizationListState]?.get(LocalizationListState.self) if !localizationListState.availableOfficialLocalizations.isEmpty {
if let localizationListState = localizationListState, !localizationListState.availableOfficialLocalizations.isEmpty {
strongSelf.currentListState = localizationListState strongSelf.currentListState = localizationListState
if #available(iOS 12.0, *) { if #available(iOS 12.0, *) {
@ -520,7 +526,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
if let strongSelf = self { if let strongSelf = self {
strongSelf.push(translationSettingsController(context: strongSelf.context)) strongSelf.push(translationSettingsController(context: strongSelf.context))
} }
}, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, firstTime: previousEntriesAndPresentationData == nil, isLoading: entries.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: (previousEntriesAndPresentationData?.0.count ?? 0) != entries.count, crossfade: (previousState == nil) != (localizationListState == nil)) }, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, firstTime: previousEntriesAndPresentationData == nil, isLoading: entries.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: (previousEntriesAndPresentationData?.0.count ?? 0) != entries.count, crossfade: (previousState == nil || previousState!.availableOfficialLocalizations.isEmpty) != localizationListState.availableOfficialLocalizations.isEmpty)
strongSelf.enqueueTransition(transition) strongSelf.enqueueTransition(transition)
}) })
self.updatedDisposable = context.engine.localization.synchronizedLocalizationListState().start() self.updatedDisposable = context.engine.localization.synchronizedLocalizationListState().start()

View File

@ -1170,20 +1170,19 @@ private final class NotificationExceptionsSearchContainerNode: SearchDisplayCont
let updateNotificationsDisposable = self.updateNotificationsDisposable let updateNotificationsDisposable = self.updateNotificationsDisposable
let updateNotificationsView: (@escaping () -> Void) -> Void = { completion in let updateNotificationsView: (@escaping () -> Void) -> Void = { completion in
let key: PostboxViewKey = .peerNotificationSettings(peerIds: Set(mode.peerIds)) updateNotificationsDisposable.set(context.engine.data.subscribe(EngineDataMap(
mode.peerIds.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init)
updateNotificationsDisposable.set(context.account.postbox.combinedView(keys: [key]).start(next: { view in )).start(next: { notificationSettingsMap in
if let view = view.views[key] as? PeerNotificationSettingsView {
let _ = (context.engine.data.get( let _ = (context.engine.data.get(
EngineDataMap(view.notificationSettings.keys.map(TelegramEngine.EngineData.Item.Peer.Peer.init)), EngineDataMap(notificationSettingsMap.keys.map(TelegramEngine.EngineData.Item.Peer.Peer.init)),
EngineDataMap(view.notificationSettings.keys.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init)) EngineDataMap(notificationSettingsMap.keys.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init))
) )
|> deliverOnMainQueue).start(next: { peerMap, notificationSettingsMap in |> deliverOnMainQueue).start(next: { peerMap, notificationSettingsMap in
updateState { current in updateState { current in
var current = current var current = current
for (key, value) in view.notificationSettings { for (key, value) in notificationSettingsMap {
if let value = value as? TelegramPeerNotificationSettings,let local = current.mode.settings[key] { if let local = current.mode.settings[key] {
if !value.isEqual(to: local.settings), let maybePeer = peerMap[key], let peer = maybePeer, let settings = notificationSettingsMap[key], !settings._asNotificationSettings().isEqual(to: local.settings) { if !value._asNotificationSettings().isEqual(to: local.settings), let maybePeer = peerMap[key], let peer = maybePeer, let settings = notificationSettingsMap[key], !settings._asNotificationSettings().isEqual(to: local.settings) {
current = current.withUpdatedPeerSound(peer._asPeer(), settings.messageSound._asMessageSound()).withUpdatedPeerMuteInterval(peer._asPeer(), settings.muteState.timeInterval) current = current.withUpdatedPeerSound(peer._asPeer(), settings.messageSound._asMessageSound()).withUpdatedPeerMuteInterval(peer._asPeer(), settings.muteState.timeInterval)
} }
} }
@ -1193,9 +1192,6 @@ private final class NotificationExceptionsSearchContainerNode: SearchDisplayCont
completion() completion()
}) })
} else {
completion()
}
})) }))
} }

View File

@ -775,11 +775,12 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
return settings.servers return settings.servers
} }
let localizationPreferencesKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.localizationListState])) let localizations = combineLatest(
let localizations = combineLatest(context.account.postbox.combinedView(keys: [localizationPreferencesKey]), context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.localizationSettings])) context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.LocalizationList()),
|> map { view, sharedData -> [LocalizationInfo] in context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.localizationSettings])
if let localizationListState = (view.views[localizationPreferencesKey] as? PreferencesView)?.values[PreferencesKeys.localizationListState]?.get(LocalizationListState.self), !localizationListState.availableOfficialLocalizations.isEmpty { )
|> map { localizationListState, sharedData -> [LocalizationInfo] in
if !localizationListState.availableOfficialLocalizations.isEmpty {
var existingIds = Set<String>() var existingIds = Set<String>()
let availableSavedLocalizations = localizationListState.availableSavedLocalizations.filter({ info in !localizationListState.availableOfficialLocalizations.contains(where: { $0.languageCode == info.languageCode }) }) let availableSavedLocalizations = localizationListState.availableSavedLocalizations.filter({ info in !localizationListState.availableOfficialLocalizations.contains(where: { $0.languageCode == info.languageCode }) })

View File

@ -313,7 +313,7 @@ public final class ShareController: ViewController {
private let segmentedValues: [ShareControllerSegmentedValue]? private let segmentedValues: [ShareControllerSegmentedValue]?
private let fromForeignApp: Bool private let fromForeignApp: Bool
private let peers = Promise<([(EngineRenderedPeer, PeerPresence?)], EnginePeer)>() private let peers = Promise<([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer)>()
private let peersDisposable = MetaDisposable() private let peersDisposable = MetaDisposable()
private let readyDisposable = MetaDisposable() private let readyDisposable = MetaDisposable()
private let accountActiveDisposable = MetaDisposable() private let accountActiveDisposable = MetaDisposable()
@ -966,7 +966,7 @@ public final class ShareController: ViewController {
self.currentAccount.viewTracker.tailChatListView(groupId: .root, count: 150) self.currentAccount.viewTracker.tailChatListView(groupId: .root, count: 150)
|> take(1) |> take(1)
) )
|> mapToSignal { maybeAccountPeer, view -> Signal<([(EngineRenderedPeer, PeerPresence?)], EnginePeer), NoError> in |> mapToSignal { maybeAccountPeer, view -> Signal<([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer), NoError> in
let accountPeer = maybeAccountPeer! let accountPeer = maybeAccountPeer!
var peers: [EngineRenderedPeer] = [] var peers: [EngineRenderedPeer] = []
@ -980,14 +980,14 @@ public final class ShareController: ViewController {
break break
} }
} }
let key = PostboxViewKey.peerPresences(peerIds: Set(peers.map { $0.peerId }))
return account.postbox.combinedView(keys: [key]) return TelegramEngine(account: account).data.subscribe(EngineDataMap(
|> map { views -> ([(EngineRenderedPeer, PeerPresence?)], EnginePeer) in peers.map { TelegramEngine.EngineData.Item.Peer.Presence(id: $0.peerId) }
var resultPeers: [(EngineRenderedPeer, PeerPresence?)] = [] ))
if let presencesView = views.views[key] as? PeerPresencesView { |> map { presenceMap -> ([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer) in
var resultPeers: [(EngineRenderedPeer, EnginePeer.Presence?)] = []
for peer in peers { for peer in peers {
resultPeers.append((peer, presencesView.presences[peer.peerId])) resultPeers.append((peer, presenceMap[peer.peerId].flatMap { $0 }))
}
} }
return (resultPeers, accountPeer) return (resultPeers, accountPeer)
} }

View File

@ -804,7 +804,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
} }
func updatePeers(context: AccountContext, switchableAccounts: [AccountWithInfo], peers: [(EngineRenderedPeer, PeerPresence?)], accountPeer: EnginePeer, defaultAction: ShareControllerAction?) { func updatePeers(context: AccountContext, switchableAccounts: [AccountWithInfo], peers: [(EngineRenderedPeer, EnginePeer.Presence?)], accountPeer: EnginePeer, defaultAction: ShareControllerAction?) {
self.context = context self.context = context
if let peersContentNode = self.peersContentNode, peersContentNode.accountPeer.id == accountPeer.id { if let peersContentNode = self.peersContentNode, peersContentNode.accountPeer.id == accountPeer.id {

View File

@ -91,13 +91,13 @@ final class ShareControllerPeerGridItem: GridItem {
let theme: PresentationTheme let theme: PresentationTheme
let strings: PresentationStrings let strings: PresentationStrings
let peer: EngineRenderedPeer? let peer: EngineRenderedPeer?
let presence: PeerPresence? let presence: EnginePeer.Presence?
let controllerInteraction: ShareControllerInteraction let controllerInteraction: ShareControllerInteraction
let search: Bool let search: Bool
let section: GridSection? let section: GridSection?
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer?, presence: PeerPresence?, controllerInteraction: ShareControllerInteraction, sectionTitle: String? = nil, search: Bool = false) { init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer?, presence: EnginePeer.Presence?, controllerInteraction: ShareControllerInteraction, sectionTitle: String? = nil, search: Bool = false) {
self.context = context self.context = context
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
@ -131,7 +131,7 @@ final class ShareControllerPeerGridItem: GridItem {
} }
final class ShareControllerPeerGridItemNode: GridItemNode { final class ShareControllerPeerGridItemNode: GridItemNode {
private var currentState: (AccountContext, PresentationTheme, PresentationStrings, EngineRenderedPeer?, Bool, PeerPresence?)? private var currentState: (AccountContext, PresentationTheme, PresentationStrings, EngineRenderedPeer?, Bool, EnginePeer.Presence?)?
private let peerNode: SelectablePeerNode private let peerNode: SelectablePeerNode
private var presenceManager: PeerPresenceStatusManager? private var presenceManager: PeerPresenceStatusManager?
@ -171,14 +171,14 @@ final class ShareControllerPeerGridItemNode: GridItemNode {
} }
} }
func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer?, presence: PeerPresence?, search: Bool, synchronousLoad: Bool, force: Bool) { func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer?, presence: EnginePeer.Presence?, search: Bool, synchronousLoad: Bool, force: Bool) {
if force || self.currentState == nil || self.currentState!.0 !== context || self.currentState!.3 != peer || !arePeerPresencesEqual(self.currentState!.5, presence) { if force || self.currentState == nil || self.currentState!.0 !== context || self.currentState!.3 != peer || self.currentState!.5 != presence {
let itemTheme = SelectablePeerNodeTheme(textColor: theme.actionSheet.primaryTextColor, secretTextColor: theme.chatList.secretTitleColor, selectedTextColor: theme.actionSheet.controlAccentColor, checkBackgroundColor: theme.actionSheet.opaqueItemBackgroundColor, checkFillColor: theme.actionSheet.controlAccentColor, checkColor: theme.actionSheet.checkContentColor, avatarPlaceholderColor: theme.list.mediaPlaceholderColor) let itemTheme = SelectablePeerNodeTheme(textColor: theme.actionSheet.primaryTextColor, secretTextColor: theme.chatList.secretTitleColor, selectedTextColor: theme.actionSheet.controlAccentColor, checkBackgroundColor: theme.actionSheet.opaqueItemBackgroundColor, checkFillColor: theme.actionSheet.controlAccentColor, checkColor: theme.actionSheet.checkContentColor, avatarPlaceholderColor: theme.list.mediaPlaceholderColor)
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
var online = false var online = false
if case let .user(peer) = peer?.peer, let presence = presence as? TelegramUserPresence, !isServicePeer(peer) && !peer.flags.contains(.isSupport) && peer.id != context.account.peerId { if case let .user(peer) = peer?.peer, let presence = presence, !isServicePeer(peer) && !peer.flags.contains(.isSupport) && peer.id != context.account.peerId {
let relativeStatus = relativeUserPresenceStatus(EnginePeer.Presence(presence), relativeTo: timestamp) let relativeStatus = relativeUserPresenceStatus(presence, relativeTo: timestamp)
if case .online = relativeStatus { if case .online = relativeStatus {
online = true online = true
} }
@ -220,8 +220,8 @@ final class ShareControllerPeerGridItemNode: GridItemNode {
} }
self.currentState = (context, theme, strings, peer, search, presence) self.currentState = (context, theme, strings, peer, search, presence)
self.setNeedsLayout() self.setNeedsLayout()
if let presence = presence as? TelegramUserPresence { if let presence = presence {
self.presenceManager?.reset(presence: EnginePeer.Presence(presence)) self.presenceManager?.reset(presence: presence)
} }
} }
self.updateSelection(animated: false) self.updateSelection(animated: false)

View File

@ -20,7 +20,7 @@ private let subtitleFont = Font.regular(12.0)
private struct SharePeerEntry: Comparable, Identifiable { private struct SharePeerEntry: Comparable, Identifiable {
let index: Int32 let index: Int32
let peer: EngineRenderedPeer let peer: EngineRenderedPeer
let presence: PeerPresence? let presence: EnginePeer.Presence?
let theme: PresentationTheme let theme: PresentationTheme
let strings: PresentationStrings let strings: PresentationStrings
@ -35,13 +35,10 @@ private struct SharePeerEntry: Comparable, Identifiable {
if lhs.peer != rhs.peer { if lhs.peer != rhs.peer {
return false return false
} }
if let lhsPresence = lhs.presence, let rhsPresence = rhs.presence { if lhs.presence != rhs.presence {
if !lhsPresence.isEqual(to: rhsPresence) {
return false
}
} else if (lhs.presence != nil) != (rhs.presence != nil) {
return false return false
} }
return true return true
} }
@ -115,9 +112,9 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
private var validLayout: (CGSize, CGFloat)? private var validLayout: (CGSize, CGFloat)?
private var overrideGridOffsetTransition: ContainedViewLayoutTransition? private var overrideGridOffsetTransition: ContainedViewLayoutTransition?
let peersValue = Promise<[(EngineRenderedPeer, PeerPresence?)]>() let peersValue = Promise<[(EngineRenderedPeer, EnginePeer.Presence?)]>()
init(sharedContext: SharedAccountContext, context: AccountContext, switchableAccounts: [AccountWithInfo], theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, peers: [(EngineRenderedPeer, PeerPresence?)], accountPeer: EnginePeer, controllerInteraction: ShareControllerInteraction, externalShare: Bool, switchToAnotherAccount: @escaping () -> Void, debugAction: @escaping () -> Void, extendedInitialReveal: Bool, segmentedValues: [ShareControllerSegmentedValue]?) { init(sharedContext: SharedAccountContext, context: AccountContext, switchableAccounts: [AccountWithInfo], theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, peers: [(EngineRenderedPeer, EnginePeer.Presence?)], accountPeer: EnginePeer, controllerInteraction: ShareControllerInteraction, externalShare: Bool, switchToAnotherAccount: @escaping () -> Void, debugAction: @escaping () -> Void, extendedInitialReveal: Bool, segmentedValues: [ShareControllerSegmentedValue]?) {
self.sharedContext = sharedContext self.sharedContext = sharedContext
self.context = context self.context = context
self.theme = theme self.theme = theme

View File

@ -36,7 +36,7 @@ private enum ShareSearchRecentEntryStableId: Hashable {
private enum ShareSearchRecentEntry: Comparable, Identifiable { private enum ShareSearchRecentEntry: Comparable, Identifiable {
case topPeers(PresentationTheme, PresentationStrings) case topPeers(PresentationTheme, PresentationStrings)
case peer(index: Int, theme: PresentationTheme, peer: Peer, associatedPeer: Peer?, presence: PeerPresence?, PresentationStrings) case peer(index: Int, theme: PresentationTheme, peer: Peer, associatedPeer: Peer?, presence: EnginePeer.Presence?, PresentationStrings)
var stableId: ShareSearchRecentEntryStableId { var stableId: ShareSearchRecentEntryStableId {
switch self { switch self {
@ -62,7 +62,7 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable {
return false return false
} }
case let .peer(lhsIndex, lhsTheme, lhsPeer, lhsAssociatedPeer, lhsPresence, lhsStrings): case let .peer(lhsIndex, lhsTheme, lhsPeer, lhsAssociatedPeer, lhsPresence, lhsStrings):
if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsStrings) = rhs, lhsPeer.isEqual(rhsPeer) && arePeersEqual(lhsAssociatedPeer, rhsAssociatedPeer) && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme && arePeerPresencesEqual(lhsPresence, rhsPresence) { if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsStrings) = rhs, lhsPeer.isEqual(rhsPeer) && arePeersEqual(lhsAssociatedPeer, rhsAssociatedPeer) && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme && lhsPresence == rhsPresence {
return true return true
} else { } else {
return false return false
@ -102,7 +102,7 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable {
private struct ShareSearchPeerEntry: Comparable, Identifiable { private struct ShareSearchPeerEntry: Comparable, Identifiable {
let index: Int32 let index: Int32
let peer: EngineRenderedPeer? let peer: EngineRenderedPeer?
let presence: PeerPresence? let presence: EnginePeer.Presence?
let theme: PresentationTheme let theme: PresentationTheme
let strings: PresentationStrings let strings: PresentationStrings

View File

@ -464,17 +464,16 @@ public func sentShareItems(account: Account, to peerIds: [PeerId], items: [Prepa
return enqueueMessagesToMultiplePeers(account: account, peerIds: peerIds, messages: messages) return enqueueMessagesToMultiplePeers(account: account, peerIds: peerIds, messages: messages)
|> castError(Void.self) |> castError(Void.self)
|> mapToSignal { messageIds -> Signal<Float, Void> in |> mapToSignal { messageIds -> Signal<Float, Void> in
let key: PostboxViewKey = .messages(Set(messageIds)) return TelegramEngine(account: account).data.subscribe(EngineDataMap(
return account.postbox.combinedView(keys: [key]) messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
))
|> castError(Void.self) |> castError(Void.self)
|> mapToSignal { view -> Signal<Float, Void> in |> mapToSignal { messages -> Signal<Float, Void> in
if let messagesView = view.views[key] as? MessagesView { for (_, message) in messages {
for (_, message) in messagesView.messages { if let message = message, message.flags.contains(.Unsent) {
if message.flags.contains(.Unsent) {
return .complete() return .complete()
} }
} }
}
return .single(1.0) return .single(1.0)
} }
|> take(1) |> take(1)

View File

@ -1968,15 +1968,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|> distinctUntilChanged |> distinctUntilChanged
|> runOn(.mainQueue()) |> runOn(.mainQueue())
} else { } else {
rawAdminIds = accountContext.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peerId)]) rawAdminIds = accountContext.engine.data.subscribe(
|> map { views -> Set<PeerId> in TelegramEngine.EngineData.Item.Peer.LegacyGroupParticipants(id: peerId)
guard let view = views.views[.cachedPeerData(peerId: peerId)] as? CachedPeerDataView else { )
|> map { participants -> Set<PeerId> in
guard case let .known(participants) = participants else {
return Set() return Set()
} }
guard let cachedData = view.cachedPeerData as? CachedGroupData, let participants = cachedData.participants else { return Set(participants.compactMap { item -> PeerId? in
return Set()
}
return Set(participants.participants.compactMap { item -> PeerId? in
switch item { switch item {
case .creator, .admin: case .creator, .admin:
return item.peerId return item.peerId

View File

@ -2,7 +2,7 @@ import SwiftSignalKit
import Postbox import Postbox
public final class EngineTotalReadCounters { public final class EngineTotalReadCounters {
private let state: ChatListTotalUnreadState fileprivate let state: ChatListTotalUnreadState
public init(state: ChatListTotalUnreadState) { public init(state: ChatListTotalUnreadState) {
self.state = state self.state = state
@ -13,8 +13,14 @@ public final class EngineTotalReadCounters {
} }
} }
public extension EngineTotalReadCounters {
func _asCounters() -> ChatListTotalUnreadState {
return self.state
}
}
public struct EnginePeerReadCounters: Equatable { public struct EnginePeerReadCounters: Equatable {
private let state: CombinedPeerReadState? fileprivate let state: CombinedPeerReadState?
public init(state: CombinedPeerReadState?) { public init(state: CombinedPeerReadState?) {
self.state = state self.state = state
@ -64,6 +70,10 @@ public extension EnginePeerReadCounters {
init(incomingReadId: EngineMessage.Id.Id, outgoingReadId: EngineMessage.Id.Id, count: Int32, markedUnread: Bool) { init(incomingReadId: EngineMessage.Id.Id, outgoingReadId: EngineMessage.Id.Id, count: Int32, markedUnread: Bool) {
self.init(state: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, .idBased(maxIncomingReadId: incomingReadId, maxOutgoingReadId: outgoingReadId, maxKnownId: max(incomingReadId, outgoingReadId), count: count, markedUnread: markedUnread))])) self.init(state: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, .idBased(maxIncomingReadId: incomingReadId, maxOutgoingReadId: outgoingReadId, maxKnownId: max(incomingReadId, outgoingReadId), count: count, markedUnread: markedUnread))]))
} }
func _asReadCounters() -> CombinedPeerReadState? {
return self.state
}
} }
public extension TelegramEngine.EngineData.Item { public extension TelegramEngine.EngineData.Item {
@ -260,5 +270,63 @@ public extension TelegramEngine.EngineData.Item {
return view.inclusion.groupId.flatMap(EngineChatList.Group.init) return view.inclusion.groupId.flatMap(EngineChatList.Group.init)
} }
} }
public struct MessageCount: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public struct ItemKey: Hashable {
public var peerId: EnginePeer.Id
public var tag: MessageTags
}
public typealias Result = Int?
fileprivate var peerId: EnginePeer.Id
fileprivate var tag: MessageTags
public var mapKey: ItemKey {
return ItemKey(peerId: self.peerId, tag: self.tag)
}
public init(peerId: EnginePeer.Id, tag: MessageTags) {
self.peerId = peerId
self.tag = tag
}
var key: PostboxViewKey {
return .historyTagSummaryView(tag: tag, peerId: peerId, namespace: Namespaces.Message.Cloud)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? MessageHistoryTagSummaryView else {
preconditionFailure()
}
return view.count.flatMap(Int.init)
}
}
public struct TopMessage: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = EngineMessage?
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
return self.id
}
public init(id: EnginePeer.Id) {
self.id = id
}
var key: PostboxViewKey {
return .topChatMessage(peerIds: [self.id])
}
func extract(view: PostboxView) -> Result {
guard let view = view as? TopChatMessageView else {
preconditionFailure()
}
guard let message = view.messages[self.id] else {
return nil
}
return EngineMessage(message)
}
}
} }
} }

View File

@ -2,6 +2,7 @@ import SwiftSignalKit
import Postbox import Postbox
public typealias EngineExportedPeerInvitation = ExportedInvitation public typealias EngineExportedPeerInvitation = ExportedInvitation
public typealias EngineSecretChatKeyFingerprint = SecretChatKeyFingerprint
public enum EnginePeerCachedInfoItem<T> { public enum EnginePeerCachedInfoItem<T> {
case known(T) case known(T)
@ -782,5 +783,34 @@ public extension TelegramEngine.EngineData.Item {
} }
} }
} }
public struct SecretChatKeyFingerprint: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = EngineSecretChatKeyFingerprint?
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
return self.id
}
public init(id: EnginePeer.Id) {
self.id = id
}
var key: PostboxViewKey {
return .peerChatState(peerId: self.id)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? PeerChatStateView else {
preconditionFailure()
}
if let peerChatState = view.chatState?.getLegacy() as? SecretChatState {
return peerChatState.keyFingerprint
} else {
return nil
}
}
}
} }
} }

View File

@ -95,6 +95,37 @@ public final class EngineDataList<Item: TelegramEngineDataItem & TelegramEngineM
} }
} }
public final class EngineDataOptional<Item: TelegramEngineDataItem>: TelegramEngineDataItem, AnyPostboxViewDataItem {
public typealias Result = Item.Result?
private let item: Item?
public init(_ item: Item?) {
self.item = item
}
var keys: [PostboxViewKey] {
var keys = Set<PostboxViewKey>()
if let item = self.item {
for key in (item as! AnyPostboxViewDataItem).keys {
keys.insert(key)
}
}
return Array(keys)
}
func _extract(views: [PostboxViewKey: PostboxView]) -> Any {
var result: [Item.Result] = []
if let item = self.item {
let itemResult = (item as! AnyPostboxViewDataItem)._extract(views: views)
result.append(itemResult as! Item.Result)
}
return result
}
}
public extension TelegramEngine { public extension TelegramEngine {
final class EngineData { final class EngineData {
public struct Item { public struct Item {

View File

@ -59,10 +59,9 @@ private final class DeviceSpecificContactImportContexts {
if context.reference != reference { if context.reference != reference {
context.reference = reference context.reference = reference
let key: PostboxViewKey = .basicPeer(peerId) let signal = TelegramEngine(account: account).data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
let signal = account.postbox.combinedView(keys: [key]) |> map { peer -> String? in
|> map { view -> String? in if case let .user(user) = peer {
if let user = (view.views[key] as? BasicPeerView)?.peer as? TelegramUser {
return user.phone return user.phone
} else { } else {
return nil return nil

View File

@ -8567,28 +8567,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}) })
if case let .peer(peerId) = self.chatLocation { if case let .peer(peerId) = self.chatLocation {
let unreadCountsKey: PostboxViewKey = .unreadCounts(items: [.peer(peerId), .total(nil)]) self.chatUnreadCountDisposable = (self.context.engine.data.subscribe(
let notificationSettingsKey: PostboxViewKey = .peerNotificationSettings(peerIds: Set([peerId])) TelegramEngine.EngineData.Item.Messages.PeerUnreadCount(id: peerId),
self.chatUnreadCountDisposable = (self.context.account.postbox.combinedView(keys: [unreadCountsKey, notificationSettingsKey]) TelegramEngine.EngineData.Item.Messages.TotalReadCounters(),
|> deliverOnMainQueue).start(next: { [weak self] views in TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peerId)
if let strongSelf = self { )
var unreadCount: Int32 = 0 |> deliverOnMainQueue).start(next: { [weak self] peerUnreadCount, totalReadCounters, notificationSettings in
var totalChatCount: Int32 = 0 guard let strongSelf = self else {
return
}
let unreadCount: Int32 = Int32(peerUnreadCount)
let inAppSettings = strongSelf.context.sharedContext.currentInAppNotificationSettings.with { $0 } let inAppSettings = strongSelf.context.sharedContext.currentInAppNotificationSettings.with { $0 }
if let view = views.views[unreadCountsKey] as? UnreadMessageCountsView { let totalChatCount: Int32 = renderedTotalUnreadCount(inAppSettings: inAppSettings, totalUnreadState: totalReadCounters._asCounters()).0
if let count = view.count(for: .peer(peerId)) {
unreadCount = count
}
if let (_, state) = view.total() {
let (count, _) = renderedTotalUnreadCount(inAppSettings: inAppSettings, totalUnreadState: state)
totalChatCount = count
}
}
if let view = views.views[notificationSettingsKey] as? PeerNotificationSettingsView, let notificationSettings = view.notificationSettings[peerId] {
var globalRemainingUnreadChatCount = totalChatCount var globalRemainingUnreadChatCount = totalChatCount
if !notificationSettings.isRemovedFromTotalUnreadCount(default: false) && unreadCount > 0 { if !notificationSettings._asNotificationSettings().isRemovedFromTotalUnreadCount(default: false) && unreadCount > 0 {
if case .messages = inAppSettings.totalUnreadCountDisplayCategory { if case .messages = inAppSettings.totalUnreadCountDisplayCategory {
globalRemainingUnreadChatCount -= unreadCount globalRemainingUnreadChatCount -= unreadCount
} else { } else {
@ -8601,8 +8595,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} else { } else {
strongSelf.navigationItem.badge = "" strongSelf.navigationItem.badge = ""
} }
}
}
}) })
self.chatUnreadMentionCountDisposable = (self.context.account.viewTracker.unseenPersonalMessagesAndReactionCount(peerId: peerId) |> deliverOnMainQueue).start(next: { [weak self] mentionCount, reactionCount in self.chatUnreadMentionCountDisposable = (self.context.account.viewTracker.unseenPersonalMessagesAndReactionCount(peerId: peerId) |> deliverOnMainQueue).start(next: { [weak self] mentionCount, reactionCount in

View File

@ -931,20 +931,15 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
let customChannelDiscussionReadState: Signal<MessageId?, NoError> let customChannelDiscussionReadState: Signal<MessageId?, NoError>
if case let .peer(peerId) = chatLocation, peerId.namespace == Namespaces.Peer.CloudChannel { if case let .peer(peerId) = chatLocation, peerId.namespace == Namespaces.Peer.CloudChannel {
let cachedDataKey = PostboxViewKey.cachedPeerData(peerId: peerId) customChannelDiscussionReadState = context.engine.data.subscribe(
let peerKey = PostboxViewKey.basicPeer(peerId) TelegramEngine.EngineData.Item.Peer.LinkedDiscussionPeerId(id: peerId),
customChannelDiscussionReadState = context.account.postbox.combinedView(keys: [cachedDataKey, peerKey]) TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
|> mapToSignal { views -> Signal<PeerId?, NoError> in )
guard let view = views.views[cachedDataKey] as? CachedPeerDataView else { |> mapToSignal { linkedDiscussionPeerId, peer -> Signal<PeerId?, NoError> in
guard case let .channel(peer) = peer, case .broadcast = peer.info else {
return .single(nil) return .single(nil)
} }
guard let peer = (views.views[peerKey] as? BasicPeerView)?.peer as? TelegramChannel, case .broadcast = peer.info else { guard case let .known(value) = linkedDiscussionPeerId else {
return .single(nil)
}
guard let cachedData = view.cachedPeerData as? CachedChannelData else {
return .single(nil)
}
guard case let .known(value) = cachedData.linkedDiscussionPeerId else {
return .single(nil) return .single(nil)
} }
return .single(value) return .single(value)
@ -954,13 +949,10 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
guard let discussionPeerId = discussionPeerId else { guard let discussionPeerId = discussionPeerId else {
return .single(nil) return .single(nil)
} }
let key = PostboxViewKey.combinedReadState(peerId: discussionPeerId)
return context.account.postbox.combinedView(keys: [key]) return context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.PeerReadCounters(id: discussionPeerId))
|> map { views -> MessageId? in |> map { readCounters -> MessageId? in
guard let view = views.views[key] as? CombinedReadStateView else { guard let state = readCounters._asReadCounters() else {
return nil
}
guard let state = view.state else {
return nil return nil
} }
for (namespace, namespaceState) in state.states { for (namespace, namespaceState) in state.states {

View File

@ -1071,16 +1071,10 @@ final class ChatMediaInputNode: ChatInputNode {
}) })
self.trendingInteraction = trendingInteraction self.trendingInteraction = trendingInteraction
let preferencesViewKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration])) let reactions: Signal<[String], NoError> = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App())
let reactions: Signal<[String], NoError> = context.account.postbox.combinedView(keys: [preferencesViewKey]) |> map { appConfiguration -> [String] in
|> map { views -> [String] in
let defaultReactions: [String] = ["👍", "👎", "😍", "😂", "😯", "😕", "😢", "😡", "💪", "👏", "🙈", "😒"] let defaultReactions: [String] = ["👍", "👎", "😍", "😂", "😯", "😕", "😢", "😡", "💪", "👏", "🙈", "😒"]
guard let view = views.views[preferencesViewKey] as? PreferencesView else {
return defaultReactions
}
guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else {
return defaultReactions
}
guard let data = appConfiguration.data, let emojis = data["gif_search_emojies"] as? [String] else { guard let data = appConfiguration.data, let emojis = data["gif_search_emojies"] as? [String] else {
return defaultReactions return defaultReactions
} }

View File

@ -142,9 +142,11 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
}) })
} }
self.statusPromise.set(context.account.postbox.combinedView(keys: [PostboxViewKey.historyTagSummaryView(tag: tagMask, peerId: peerId, namespace: Namespaces.Message.Cloud)]) self.statusPromise.set(context.engine.data.subscribe(
|> map { views -> PeerInfoStatusData? in TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, tag: tagMask)
let count: Int32 = (views.views[PostboxViewKey.historyTagSummaryView(tag: tagMask, peerId: peerId, namespace: Namespaces.Message.Cloud)] as? MessageHistoryTagSummaryView)?.count ?? 0 )
|> map { count -> PeerInfoStatusData? in
let count: Int = count ?? 0
if count == 0 { if count == 0 {
return nil return nil
} }

View File

@ -2015,34 +2015,14 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
case .music: case .music:
summaries.append(.music) summaries.append(.music)
} }
return context.account.postbox.combinedView(keys: summaries.map { tag in
return PostboxViewKey.historyTagSummaryView(tag: tag, peerId: peerId, namespace: Namespaces.Message.Cloud) return context.engine.data.subscribe(EngineDataMap(
}) summaries.map { TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, tag: $0) }
|> map { views -> (ContentType, [MessageTags: Int32]) in ))
switch contentType { |> map { summaries -> (ContentType, [MessageTags: Int32]) in
case .photoOrVideo:
summaries.append(.photo)
summaries.append(.video)
case .photo:
summaries.append(.photo)
case .video:
summaries.append(.video)
case .gifs:
summaries.append(.gif)
case .files:
summaries.append(.file)
case .voiceAndVideoMessages:
summaries.append(.voiceOrInstantVideo)
case .music:
summaries.append(.music)
}
var result: [MessageTags: Int32] = [:] var result: [MessageTags: Int32] = [:]
for tag in summaries { for (key, count) in summaries {
if let view = views.views[PostboxViewKey.historyTagSummaryView(tag: tag, peerId: peerId, namespace: Namespaces.Message.Cloud)] as? MessageHistoryTagSummaryView { result[key.tag] = count.flatMap(Int32.init) ?? 0
result[tag] = view.count ?? 0
} else {
result[tag] = 0
}
} }
return (contentType, result) return (contentType, result)
} }

View File

@ -565,25 +565,20 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
return disposable return disposable
} }
|> distinctUntilChanged |> distinctUntilChanged
var combinedKeys: [PostboxViewKey] = []
var secretChatKeyFingerprint: Signal<EngineSecretChatKeyFingerprint?, NoError> = .single(nil)
if let secretChatId = secretChatId { if let secretChatId = secretChatId {
combinedKeys.append(.peerChatState(peerId: secretChatId)) secretChatKeyFingerprint = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.SecretChatKeyFingerprint(id: secretChatId))
} }
return combineLatest( return combineLatest(
context.account.viewTracker.peerView(peerId, updateData: true), context.account.viewTracker.peerView(peerId, updateData: true),
peerInfoAvailableMediaPanes(context: context, peerId: peerId), peerInfoAvailableMediaPanes(context: context, peerId: peerId),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()), context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()),
context.account.postbox.combinedView(keys: combinedKeys), secretChatKeyFingerprint,
status status
) )
|> map { peerView, availablePanes, globalNotificationSettings, combinedView, status -> PeerInfoScreenData in |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status -> PeerInfoScreenData in
var encryptionKeyFingerprint: SecretChatKeyFingerprint?
if let secretChatId = secretChatId, let peerChatStateView = combinedView.views[.peerChatState(peerId: secretChatId)] as? PeerChatStateView {
if let peerChatState = peerChatStateView.chatState?.getLegacy() as? SecretChatState {
encryptionKeyFingerprint = peerChatState.keyFingerprint
}
}
var availablePanes = availablePanes var availablePanes = availablePanes
if availablePanes != nil, groupsInCommon != nil, let cachedData = peerView.cachedData as? CachedUserData { if availablePanes != nil, groupsInCommon != nil, let cachedData = peerView.cachedData as? CachedUserData {
if cachedData.commonGroupCount != 0 { if cachedData.commonGroupCount != 0 {

View File

@ -6766,24 +6766,20 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func displayMediaGalleryContextMenu(source: ContextReferenceContentNode, gesture: ContextGesture?) { private func displayMediaGalleryContextMenu(source: ContextReferenceContentNode, gesture: ContextGesture?) {
let summaryTags: [MessageTags] = [.photo, .video]
let peerId = self.peerId let peerId = self.peerId
let _ = (context.account.postbox.combinedView(keys: summaryTags.map { tag in
return PostboxViewKey.historyTagSummaryView(tag: tag, peerId: peerId, namespace: Namespaces.Message.Cloud) let _ = (self.context.engine.data.get(EngineDataMap([
}) TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, tag: .photo),
|> take(1) TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, tag: .video)
|> deliverOnMainQueue).start(next: { [weak self] views in ]))
|> deliverOnMainQueue).start(next: { [weak self] messageCounts in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
var mediaCount: [MessageTags: Int32] = [:] var mediaCount: [MessageTags: Int32] = [:]
for tag in summaryTags { for (key, count) in messageCounts {
if let view = views.views[PostboxViewKey.historyTagSummaryView(tag: tag, peerId: peerId, namespace: Namespaces.Message.Cloud)] as? MessageHistoryTagSummaryView { mediaCount[key.tag] = count.flatMap(Int32.init) ?? 0
mediaCount[tag] = view.count ?? 0
} else {
mediaCount[tag] = 0
}
} }
let photoCount: Int32 = mediaCount[.photo] ?? 0 let photoCount: Int32 = mediaCount[.photo] ?? 0

View File

@ -875,12 +875,11 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDe
self.animationTimer = animationTimer self.animationTimer = animationTimer
animationTimer.start() animationTimer.start()
self.statusPromise.set(context.account.postbox.combinedView(keys: [PostboxViewKey.historyTagSummaryView(tag: tagMaskForType(self.contentType), peerId: peerId, namespace: Namespaces.Message.Cloud)]) self.statusPromise.set(context.engine.data.subscribe(
|> map { [weak self] views -> PeerInfoStatusData? in TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, tag: tagMaskForType(self.contentType))
guard let strongSelf = self else { )
return nil |> map { count -> PeerInfoStatusData? in
} let count: Int = count ?? 0
let count: Int32 = (views.views[PostboxViewKey.historyTagSummaryView(tag: tagMaskForType(strongSelf.contentType), peerId: peerId, namespace: Namespaces.Message.Cloud)] as? MessageHistoryTagSummaryView)?.count ?? 0
if count == 0 { if count == 0 {
return nil return nil
} }

View File

@ -198,15 +198,16 @@ final class WidgetDataContext {
if peerIds.isEmpty { if peerIds.isEmpty {
continue continue
} }
let topMessagesKey: PostboxViewKey = .topChatMessage(peerIds: Array(peerIds))
accountSignals.append(account.postbox.combinedView(keys: [topMessagesKey]) accountSignals.append(TelegramEngine(account: account).data.subscribe(EngineDataMap(
|> map { combinedView -> [WidgetDataPeer] in peerIds.map(TelegramEngine.EngineData.Item.Messages.TopMessage.init)
guard let topMessages = combinedView.views[topMessagesKey] as? TopChatMessageView else { ))
return [] |> map { topMessages -> [WidgetDataPeer] in
}
var result: [WidgetDataPeer] = [] var result: [WidgetDataPeer] = []
for (peerId, message) in topMessages.messages { for (peerId, message) in topMessages {
guard let message = message else {
continue
}
guard let peer = message.peers[message.id.peerId] else { guard let peer = message.peers[message.id.peerId] else {
continue continue
} }
@ -227,7 +228,7 @@ final class WidgetDataContext {
name = peer.debugDisplayTitle name = peer.debugDisplayTitle
} }
result.append(WidgetDataPeer(id: peerId.toInt64(), name: name, lastName: lastName, letters: [], avatarPath: nil, badge: nil, message: WidgetDataPeer.Message(accountPeerId: account.peerId, message: EngineMessage(message)))) result.append(WidgetDataPeer(id: peerId.toInt64(), name: name, lastName: lastName, letters: [], avatarPath: nil, badge: nil, message: WidgetDataPeer.Message(accountPeerId: account.peerId, message: message)))
} }
result.sort(by: { lhs, rhs in result.sort(by: { lhs, rhs in
return lhs.id < rhs.id return lhs.id < rhs.id