Refactoring

This commit is contained in:
Ali 2022-05-29 19:11:14 +04:00
parent 70227e7cf1
commit 5eb4bbeaae
42 changed files with 366 additions and 353 deletions

View File

@ -38,7 +38,7 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
self.impl = NotificationViewControllerImpl(initializationData: NotificationViewControllerInitializationData(appBundleId: baseAppBundleId, appGroupPath: appGroupUrl.path, apiId: buildConfig.apiId, apiHash: buildConfig.apiHash, languagesCategory: languagesCategory, encryptionParameters: encryptionParameters, appVersion: appVersion, bundleData: buildConfig.bundleData(withAppToken: nil, signatureDict: nil)), setPreferredContentSize: { [weak self] size in self.impl = NotificationViewControllerImpl(initializationData: NotificationViewControllerInitializationData(appBundleId: baseAppBundleId, appBuildType: buildConfig.isAppStoreBuild ? .public : .internal, appGroupPath: appGroupUrl.path, apiId: buildConfig.apiId, apiHash: buildConfig.apiHash, languagesCategory: languagesCategory, encryptionParameters: encryptionParameters, appVersion: appVersion, bundleData: buildConfig.bundleData(withAppToken: nil, signatureDict: nil)), setPreferredContentSize: { [weak self] size in
self?.preferredContentSize = size self?.preferredContentSize = size
}) })
} }

View File

@ -45,7 +45,7 @@ class ShareRootController: UIViewController {
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
self.impl = ShareRootControllerImpl(initializationData: ShareRootControllerInitializationData(appBundleId: baseAppBundleId, appGroupPath: appGroupUrl.path, apiId: buildConfig.apiId, apiHash: buildConfig.apiHash, languagesCategory: languagesCategory, encryptionParameters: encryptionParameters, appVersion: appVersion, bundleData: buildConfig.bundleData(withAppToken: nil, signatureDict: nil)), getExtensionContext: { [weak self] in self.impl = ShareRootControllerImpl(initializationData: ShareRootControllerInitializationData(appBundleId: baseAppBundleId, appBuildType: buildConfig.isAppStoreBuild ? .public : .internal, appGroupPath: appGroupUrl.path, apiId: buildConfig.apiId, apiHash: buildConfig.apiHash, languagesCategory: languagesCategory, encryptionParameters: encryptionParameters, appVersion: appVersion, bundleData: buildConfig.bundleData(withAppToken: nil, signatureDict: nil)), getExtensionContext: { [weak self] in
return self?.extensionContext return self?.extensionContext
}) })
} }

View File

@ -29,9 +29,15 @@ public enum AccessType {
case unreachable case unreachable
} }
public enum TelegramAppBuildType {
case `internal`
case `public`
}
public final class TelegramApplicationBindings { public final class TelegramApplicationBindings {
public let isMainApp: Bool public let isMainApp: Bool
public let appBundleId: String public let appBundleId: String
public let appBuildType: TelegramAppBuildType
public let containerPath: String public let containerPath: String
public let appSpecificScheme: String public let appSpecificScheme: String
public let openUrl: (String) -> Void public let openUrl: (String) -> Void
@ -56,9 +62,10 @@ public final class TelegramApplicationBindings {
public let requestSetAlternateIconName: (String?, @escaping (Bool) -> Void) -> Void public let requestSetAlternateIconName: (String?, @escaping (Bool) -> Void) -> Void
public let forceOrientation: (UIInterfaceOrientation) -> Void public let forceOrientation: (UIInterfaceOrientation) -> Void
public init(isMainApp: Bool, appBundleId: String, containerPath: String, appSpecificScheme: String, openUrl: @escaping (String) -> Void, openUniversalUrl: @escaping (String, TelegramApplicationOpenUrlCompletion) -> Void, canOpenUrl: @escaping (String) -> Bool, getTopWindow: @escaping () -> UIWindow?, displayNotification: @escaping (String) -> Void, applicationInForeground: Signal<Bool, NoError>, applicationIsActive: Signal<Bool, NoError>, clearMessageNotifications: @escaping ([MessageId]) -> Void, pushIdleTimerExtension: @escaping () -> Disposable, openSettings: @escaping () -> Void, openAppStorePage: @escaping () -> Void, registerForNotifications: @escaping (@escaping (Bool) -> Void) -> Void, requestSiriAuthorization: @escaping (@escaping (Bool) -> Void) -> Void, siriAuthorization: @escaping () -> AccessType, getWindowHost: @escaping () -> WindowHost?, presentNativeController: @escaping (UIViewController) -> Void, dismissNativeController: @escaping () -> Void, getAvailableAlternateIcons: @escaping () -> [PresentationAppIcon], getAlternateIconName: @escaping () -> String?, requestSetAlternateIconName: @escaping (String?, @escaping (Bool) -> Void) -> Void, forceOrientation: @escaping (UIInterfaceOrientation) -> Void) { public init(isMainApp: Bool, appBundleId: String, appBuildType: TelegramAppBuildType, containerPath: String, appSpecificScheme: String, openUrl: @escaping (String) -> Void, openUniversalUrl: @escaping (String, TelegramApplicationOpenUrlCompletion) -> Void, canOpenUrl: @escaping (String) -> Bool, getTopWindow: @escaping () -> UIWindow?, displayNotification: @escaping (String) -> Void, applicationInForeground: Signal<Bool, NoError>, applicationIsActive: Signal<Bool, NoError>, clearMessageNotifications: @escaping ([MessageId]) -> Void, pushIdleTimerExtension: @escaping () -> Disposable, openSettings: @escaping () -> Void, openAppStorePage: @escaping () -> Void, registerForNotifications: @escaping (@escaping (Bool) -> Void) -> Void, requestSiriAuthorization: @escaping (@escaping (Bool) -> Void) -> Void, siriAuthorization: @escaping () -> AccessType, getWindowHost: @escaping () -> WindowHost?, presentNativeController: @escaping (UIViewController) -> Void, dismissNativeController: @escaping () -> Void, getAvailableAlternateIcons: @escaping () -> [PresentationAppIcon], getAlternateIconName: @escaping () -> String?, requestSetAlternateIconName: @escaping (String?, @escaping (Bool) -> Void) -> Void, forceOrientation: @escaping (UIInterfaceOrientation) -> Void) {
self.isMainApp = isMainApp self.isMainApp = isMainApp
self.appBundleId = appBundleId self.appBundleId = appBundleId
self.appBuildType = appBuildType
self.containerPath = containerPath self.containerPath = containerPath
self.appSpecificScheme = appSpecificScheme self.appSpecificScheme = appSpecificScheme
self.openUrl = openUrl self.openUrl = openUrl

View File

@ -94,9 +94,9 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
return context.engine.data.get( return context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.IsContact(id: peer.id), TelegramEngine.EngineData.Item.Peer.IsContact(id: peer.id),
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peer.id), TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peer.id),
TelegramEngine.EngineData.Item.Messages.ReadState(id: peer.id) TelegramEngine.EngineData.Item.Messages.PeerReadCounters(id: peer.id)
) )
|> map { [weak chatListController] isContact, notificationSettings, readState -> [ContextMenuItem] in |> map { [weak chatListController] isContact, notificationSettings, readCounters -> [ContextMenuItem] in
if promoInfo != nil { if promoInfo != nil {
return [] return []
} }
@ -160,7 +160,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
} }
var isUnread = false var isUnread = false
if let readState = readState, readState.isUnread { if readCounters.isUnread {
isUnread = true isUnread = true
} }

View File

@ -1954,29 +1954,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
private var initializedFilters = false private var initializedFilters = false
private func reloadFilters(firstUpdate: (() -> Void)? = nil) { private func reloadFilters(firstUpdate: (() -> Void)? = nil) {
let preferencesKey: PostboxViewKey = .preferences(keys: Set([
ApplicationSpecificPreferencesKeys.chatListFilterSettings
]))
let experimentalUISettingsKey: ValueBoxKey = ApplicationSpecificSharedDataKeys.experimentalUISettings
let displayTabsAtBottom = self.context.sharedContext.accountManager.sharedData(keys: Set([experimentalUISettingsKey]))
|> map { sharedData -> Bool in
let settings: ExperimentalUISettings = sharedData.entries[experimentalUISettingsKey]?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings
return settings.foldersTabAtBottom
}
|> distinctUntilChanged
let filterItems = chatListFilterItems(context: self.context) let filterItems = chatListFilterItems(context: self.context)
var notifiedFirstUpdate = false var notifiedFirstUpdate = false
self.filterDisposable.set((combineLatest(queue: .mainQueue(), self.filterDisposable.set((combineLatest(queue: .mainQueue(),
self.context.account.postbox.combinedView(keys: [
preferencesKey
]),
filterItems, filterItems,
displayTabsAtBottom,
self.context.account.postbox.peerView(id: self.context.account.peerId), self.context.account.postbox.peerView(id: self.context.account.peerId),
self.context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false)) self.context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false))
) )
|> deliverOnMainQueue).start(next: { [weak self] _, countAndFilterItems, displayTabsAtBottom, peerView, limits in |> deliverOnMainQueue).start(next: { [weak self] countAndFilterItems, peerView, limits in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -2044,7 +2029,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
} }
let filtersLimit = isPremium == false ? limits.maxFoldersCount : nil let filtersLimit = isPremium == false ? limits.maxFoldersCount : nil
strongSelf.tabContainerData = (resolvedItems, displayTabsAtBottom, filtersLimit) strongSelf.tabContainerData = (resolvedItems, false, filtersLimit)
var availableFilters: [ChatListContainerNodeFilter] = [] var availableFilters: [ChatListContainerNodeFilter] = []
var hasAllChats = false var hasAllChats = false
for item in items { for item in items {
@ -2080,7 +2065,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.initializedFilters = true strongSelf.initializedFilters = true
} }
let isEmpty = resolvedItems.count <= 1 || displayTabsAtBottom let isEmpty = resolvedItems.count <= 1
let animated = strongSelf.didSetupTabs let animated = strongSelf.didSetupTabs
strongSelf.didSetupTabs = true strongSelf.didSetupTabs = true

View File

@ -29,41 +29,28 @@ func chatListSelectionOptions(context: AccountContext, peerIds: Set<PeerId>, fil
} }
|> distinctUntilChanged |> distinctUntilChanged
} else { } else {
let key = PostboxViewKey.unreadCounts(items: [.total(nil)]) return context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.TotalReadCounters())
return context.account.postbox.combinedView(keys: [key]) |> map { readCounters -> ChatListSelectionOptions in
|> map { view -> ChatListSelectionOptions in
var hasUnread = false var hasUnread = false
if let unreadCounts = view.views[key] as? UnreadMessageCountsView, let total = unreadCounts.total() { if readCounters.count(for: .filtered, in: .chats, with: .all) != 0 {
for (_, counter) in total.1.absoluteCounters {
if counter.messageCount != 0 {
hasUnread = true hasUnread = true
break
}
}
} }
return ChatListSelectionOptions(read: .all(enabled: hasUnread), delete: false) return ChatListSelectionOptions(read: .all(enabled: hasUnread), delete: false)
} }
|> distinctUntilChanged |> distinctUntilChanged
} }
} else { } else {
let items: [UnreadMessageCountsItem] = peerIds.map(UnreadMessageCountsItem.peer) return context.engine.data.subscribe(EngineDataList(
let key = PostboxViewKey.unreadCounts(items: items) peerIds.map(TelegramEngine.EngineData.Item.Messages.PeerReadCounters.init)
return context.account.postbox.combinedView(keys: [key]) ))
|> map { view -> ChatListSelectionOptions in |> map { readCounters -> ChatListSelectionOptions in
var hasUnread = false var hasUnread = false
if let unreadCounts = view.views[key] as? UnreadMessageCountsView { for counters in readCounters {
loop: for entry in unreadCounts.entries { if counters.isUnread {
switch entry {
case let .peer(_, state):
if let state = state, state.isUnread {
hasUnread = true hasUnread = true
break loop
}
default:
break break
} }
} }
}
return ChatListSelectionOptions(read: .selective(enabled: hasUnread), delete: true) return ChatListSelectionOptions(read: .selective(enabled: hasUnread), delete: true)
} }
|> distinctUntilChanged |> distinctUntilChanged

View File

@ -120,7 +120,10 @@ public func debugAccountsController(context: AccountContext, accountManager: Acc
ActionSheetItemGroup(items: [ ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: "Production", color: .accent, action: { ActionSheetButtonItem(title: "Production", color: .accent, action: {
dismissAction() dismissAction()
if case .internal = context.sharedContext.applicationBindings.appBuildType {
context.sharedContext.beginNewAuth(testingEnvironment: false) context.sharedContext.beginNewAuth(testingEnvironment: false)
}
}), }),
ActionSheetButtonItem(title: "Test", color: .accent, action: { ActionSheetButtonItem(title: "Test", color: .accent, action: {
dismissAction() dismissAction()

View File

@ -608,15 +608,14 @@ private final class PictureInPictureContentImpl: NSObject, PictureInPictureConte
} }
if let (messageId, _) = hiddenMedia { if let (messageId, _) = hiddenMedia {
self.messageRemovedDisposable = (context.account.postbox.combinedView(keys: [PostboxViewKey.messages([messageId])]) self.messageRemovedDisposable = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> map { views -> Bool in |> map { message -> Bool in
if let view = views.views[PostboxViewKey.messages([messageId])] as? MessagesView { if let _ = message {
if view.messages[messageId] == nil { return false
} else {
return true return true
} }
} }
return false
}
|> filter { $0 } |> filter { $0 }
|> take(1) |> take(1)
|> deliverOnMainQueue).start(next: { [weak self] _ in |> deliverOnMainQueue).start(next: { [weak self] _ in
@ -2247,16 +2246,12 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
let shouldBeDismissed: Signal<Bool, NoError> let shouldBeDismissed: Signal<Bool, NoError>
if let contentInfo = item.contentInfo, case let .message(message) = contentInfo { if let contentInfo = item.contentInfo, case let .message(message) = contentInfo {
let viewKey = PostboxViewKey.messages(Set([message.id])) shouldBeDismissed = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: message.id))
shouldBeDismissed = context.account.postbox.combinedView(keys: [viewKey]) |> map { message -> Bool in
|> map { views -> Bool in if let _ = message {
guard let view = views.views[viewKey] as? MessagesView else {
return false return false
}
if view.messages.isEmpty {
return true
} else { } else {
return false return true
} }
} }
|> distinctUntilChanged |> distinctUntilChanged

View File

@ -21,13 +21,13 @@ public enum AvatarGalleryEntryId: Hashable {
case resource(String) case resource(String)
} }
public func peerInfoProfilePhotos(context: AccountContext, peerId: PeerId) -> Signal<Any, NoError> { public func peerInfoProfilePhotos(context: AccountContext, peerId: EnginePeer.Id) -> Signal<Any, NoError> {
return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) return context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> mapToSignal { view -> Signal<[AvatarGalleryEntry]?, NoError> in |> mapToSignal { peer -> Signal<[AvatarGalleryEntry]?, NoError> in
guard let peer = (view.views[.basicPeer(peerId)] as? BasicPeerView)?.peer else { guard let peer = peer else {
return .single(nil) return .single(nil)
} }
return initialAvatarGalleryEntries(account: context.account, engine: context.engine, peer: peer) return initialAvatarGalleryEntries(account: context.account, engine: context.engine, peer: peer._asPeer())
} }
|> distinctUntilChanged |> distinctUntilChanged
|> mapToSignal { entries -> Signal<(Bool, [AvatarGalleryEntry])?, NoError> in |> mapToSignal { entries -> Signal<(Bool, [AvatarGalleryEntry])?, NoError> in

View File

@ -47,7 +47,7 @@ private enum ChannelBannedMemberEntryStableId: Hashable {
} }
private enum ChannelBannedMemberEntry: ItemListNodeEntry { private enum ChannelBannedMemberEntry: ItemListNodeEntry {
case info(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, TelegramUserPresence?) case info(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, EnginePeer, EnginePeer.Presence?)
case rightsHeader(PresentationTheme, String) case rightsHeader(PresentationTheme, String)
case rightItem(PresentationTheme, Int, String, TelegramChatBannedRightsFlags, Bool, Bool) case rightItem(PresentationTheme, Int, String, TelegramChatBannedRightsFlags, Bool, Bool)
case timeout(PresentationTheme, String, String) case timeout(PresentationTheme, String, String)
@ -97,7 +97,7 @@ private enum ChannelBannedMemberEntry: 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 {
@ -207,7 +207,7 @@ private enum ChannelBannedMemberEntry: ItemListNodeEntry {
let arguments = arguments as! ChannelBannedMemberControllerArguments let arguments = arguments as! ChannelBannedMemberControllerArguments
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 .rightsHeader(_, text): case let .rightsHeader(_, text):
@ -256,11 +256,11 @@ func completeRights(_ flags: TelegramChatBannedRightsFlags) -> TelegramChatBanne
return result return result
} }
private func channelBannedMemberControllerEntries(presentationData: PresentationData, state: ChannelBannedMemberControllerState, accountPeerId: PeerId, channelView: PeerView, memberView: PeerView, initialParticipant: ChannelParticipant?, initialBannedBy: Peer?) -> [ChannelBannedMemberEntry] { private func channelBannedMemberControllerEntries(presentationData: PresentationData, state: ChannelBannedMemberControllerState, accountPeerId: PeerId, channelPeer: EnginePeer?, memberPeer: EnginePeer?, memberPresence: EnginePeer.Presence?, initialParticipant: ChannelParticipant?, initialBannedBy: EnginePeer?) -> [ChannelBannedMemberEntry] {
var entries: [ChannelBannedMemberEntry] = [] var entries: [ChannelBannedMemberEntry] = []
if let channel = channelView.peers[channelView.peerId] as? TelegramChannel, let _ = channelView.cachedData as? CachedChannelData, let defaultBannedRights = channel.defaultBannedRights, let member = memberView.peers[memberView.peerId] { if case let .channel(channel) = channelPeer, let defaultBannedRights = channel.defaultBannedRights, let member = memberPeer {
entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, member, memberView.peerPresences[member.id] as? TelegramUserPresence)) entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, member, memberPresence))
let currentRightsFlags: TelegramChatBannedRightsFlags let currentRightsFlags: TelegramChatBannedRightsFlags
if let updatedFlags = state.updatedFlags { if let updatedFlags = state.updatedFlags {
@ -300,13 +300,13 @@ private func channelBannedMemberControllerEntries(presentationData: Presentation
entries.append(.timeout(presentationData.theme, presentationData.strings.GroupPermission_Duration, currentTimeoutString)) entries.append(.timeout(presentationData.theme, presentationData.strings.GroupPermission_Duration, currentTimeoutString))
if let initialParticipant = initialParticipant, case let .member(_, _, _, banInfo?, _) = initialParticipant, let initialBannedBy = initialBannedBy { if let initialParticipant = initialParticipant, case let .member(_, _, _, banInfo?, _) = initialParticipant, let initialBannedBy = initialBannedBy {
entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(EnginePeer(initialBannedBy).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).string)) entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(initialBannedBy.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).string))
entries.append(.delete(presentationData.theme, presentationData.strings.GroupPermission_Delete)) entries.append(.delete(presentationData.theme, presentationData.strings.GroupPermission_Delete))
} }
} else if let group = channelView.peers[channelView.peerId] as? TelegramGroup, let member = memberView.peers[memberView.peerId] { } else if case let .legacyGroup(group) = channelPeer, let member = memberPeer {
let defaultBannedRightsFlags = group.defaultBannedRights?.flags ?? [] let defaultBannedRightsFlags = group.defaultBannedRights?.flags ?? []
entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, member, memberView.peerPresences[member.id] as? TelegramUserPresence)) entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, member, memberPresence))
let currentRightsFlags: TelegramChatBannedRightsFlags let currentRightsFlags: TelegramChatBannedRightsFlags
if let updatedFlags = state.updatedFlags { if let updatedFlags = state.updatedFlags {
@ -346,7 +346,7 @@ private func channelBannedMemberControllerEntries(presentationData: Presentation
entries.append(.timeout(presentationData.theme, presentationData.strings.GroupPermission_Duration, currentTimeoutString)) entries.append(.timeout(presentationData.theme, presentationData.strings.GroupPermission_Duration, currentTimeoutString))
if let initialParticipant = initialParticipant, case let .member(_, _, _, banInfo?, _) = initialParticipant, let initialBannedBy = initialBannedBy { if let initialParticipant = initialParticipant, case let .member(_, _, _, banInfo?, _) = initialParticipant, let initialBannedBy = initialBannedBy {
entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(EnginePeer(initialBannedBy).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).string)) entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(initialBannedBy.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).string))
entries.append(.delete(presentationData.theme, presentationData.strings.GroupPermission_Delete)) entries.append(.delete(presentationData.theme, presentationData.strings.GroupPermission_Delete))
} }
} }
@ -504,24 +504,31 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen
presentControllerImpl?(actionSheet, nil) presentControllerImpl?(actionSheet, nil)
}) })
var keys: [PostboxViewKey] = [.peer(peerId: peerId, components: .all), .peer(peerId: memberId, components: .all)] var peerDataItems: [TelegramEngine.EngineData.Item.Peer.Peer] = []
peerDataItems.append(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
peerDataItems.append(TelegramEngine.EngineData.Item.Peer.Peer(id: memberId))
if let banInfo = initialParticipant?.banInfo { if let banInfo = initialParticipant?.banInfo {
keys.append(.peer(peerId: banInfo.restrictedBy, components: [])) peerDataItems.append(TelegramEngine.EngineData.Item.Peer.Peer(id: banInfo.restrictedBy))
} }
let combinedView = context.account.postbox.combinedView(keys: keys)
let peersMap = context.engine.data.subscribe(
EngineDataMap(peerDataItems),
TelegramEngine.EngineData.Item.Peer.Presence(id: memberId)
)
let canEdit = true let canEdit = true
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
let signal = combineLatest(presentationData, statePromise.get(), combinedView) let signal = combineLatest(presentationData, statePromise.get(), peersMap)
|> deliverOnMainQueue |> deliverOnMainQueue
|> map { presentationData, state, combinedView -> (ItemListControllerState, (ItemListNodeState, Any)) in |> map { presentationData, state, peersMap -> (ItemListControllerState, (ItemListNodeState, Any)) in
let channelView = combinedView.views[.peer(peerId: peerId, components: .all)] as! PeerView let channelPeer = peersMap.0[peerId].flatMap { $0 }
let memberView = combinedView.views[.peer(peerId: memberId, components: .all)] as! PeerView let memberPeer = peersMap.0[memberId].flatMap { $0 }
var initialBannedByPeer: Peer? var initialBannedByPeer: EnginePeer?
if let banInfo = initialParticipant?.banInfo { if let banInfo = initialParticipant?.banInfo {
initialBannedByPeer = (combinedView.views[.peer(peerId: banInfo.restrictedBy, components: [])] as? PeerView)?.peers[banInfo.restrictedBy] initialBannedByPeer = peersMap.0[banInfo.restrictedBy].flatMap { $0 }
} }
let memberPresence = peersMap.1
let leftNavigationButton: ItemListNavigationButton let leftNavigationButton: ItemListNavigationButton
leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
@ -590,7 +597,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen
resolvedRights = TelegramChatBannedRights(flags: completeRights(currentRightsFlags), untilDate: currentTimeout) resolvedRights = TelegramChatBannedRights(flags: completeRights(currentRightsFlags), untilDate: currentTimeout)
} }
} else if canEdit, let _ = channelView.peers[channelView.peerId] as? TelegramChannel { } else if canEdit, case .channel = channelPeer {
var updateFlags: TelegramChatBannedRightsFlags? var updateFlags: TelegramChatBannedRightsFlags?
var updateTimeout: Int32? var updateTimeout: Int32?
updateState { state in updateState { state in
@ -723,7 +730,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen
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: channelBannedMemberControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, memberView: memberView, initialParticipant: initialParticipant, initialBannedBy: initialBannedByPeer), style: .blocks, emptyStateItem: nil, animateChanges: true) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelBannedMemberControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelPeer: channelPeer, memberPeer: memberPeer, memberPresence: memberPresence, initialParticipant: initialParticipant, initialBannedBy: initialBannedByPeer), style: .blocks, emptyStateItem: nil, animateChanges: true)
return (controllerState, (listState, arguments)) return (controllerState, (listState, arguments))
} }

View File

@ -740,28 +740,26 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
let updateNotificationsView: (@escaping () -> Void) -> Void = { completion in let updateNotificationsView: (@escaping () -> Void) -> Void = { completion in
updateState { current in updateState { current in
peerIds = peerIds.union(current.mode.peerIds) peerIds = peerIds.union(current.mode.peerIds)
let key: PostboxViewKey = .peerNotificationSettings(peerIds: peerIds) updateNotificationsDisposable.set((context.engine.data.subscribe(EngineDataMap(
updateNotificationsDisposable.set((context.account.postbox.combinedView(keys: [key]) peerIds.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init)
|> deliverOnMainQueue).start(next: { view in ))
if let view = view.views[key] as? PeerNotificationSettingsView { |> deliverOnMainQueue).start(next: { notificationSettingsMap in
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 {
if 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).withUpdatedPeerDisplayPreviews(peer._asPeer(), settings.displayPreviews._asDisplayPreviews()) current = current.withUpdatedPeerSound(peer._asPeer(), settings.messageSound._asMessageSound()).withUpdatedPeerMuteInterval(peer._asPeer(), settings.muteState.timeInterval).withUpdatedPeerDisplayPreviews(peer._asPeer(), settings.displayPreviews._asDisplayPreviews())
} }
} else if let maybePeer = peerMap[key], let peer = maybePeer { } else if let maybePeer = peerMap[key], let peer = maybePeer {
if case .default = value.messageSound, case .unmuted = value.muteState, case .default = value.displayPreviews { if case .default = value.messageSound, case .unmuted = value.muteState, case .default = value.displayPreviews {
} else { } else {
current = current.withUpdatedPeerSound(peer._asPeer(), value.messageSound).withUpdatedPeerMuteInterval(peer._asPeer(), EnginePeer.NotificationSettings.MuteState(value.muteState).timeInterval).withUpdatedPeerDisplayPreviews(peer._asPeer(), value.displayPreviews) current = current.withUpdatedPeerSound(peer._asPeer(), value.messageSound._asMessageSound()).withUpdatedPeerMuteInterval(peer._asPeer(), value.muteState.timeInterval).withUpdatedPeerDisplayPreviews(peer._asPeer(), value.displayPreviews._asDisplayPreviews())
}
} }
} }
} }
@ -770,9 +768,6 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
completion() completion()
}) })
} else {
completion()
}
})) }))
return current return current
} }

View File

@ -455,28 +455,28 @@ public func notificationsPeerCategoryController(context: AccountContext, categor
let updateNotificationsView: (@escaping () -> Void) -> Void = { completion in let updateNotificationsView: (@escaping () -> Void) -> Void = { completion in
updateState { current in updateState { current in
peerIds = peerIds.union(current.mode.peerIds) peerIds = peerIds.union(current.mode.peerIds)
let key: PostboxViewKey = .peerNotificationSettings(peerIds: peerIds) let combinedPeerNotificationSettings = context.engine.data.subscribe(EngineDataMap(
updateNotificationsDisposable.set((context.account.postbox.combinedView(keys: [key]) peerIds.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init)
|> deliverOnMainQueue).start(next: { view in ))
if let view = view.views[key] as? PeerNotificationSettingsView {
updateNotificationsDisposable.set((combinedPeerNotificationSettings
|> deliverOnMainQueue).start(next: { combinedPeerNotificationSettings in
let _ = (context.engine.data.get( let _ = (context.engine.data.get(
EngineDataMap(view.notificationSettings.keys.map(TelegramEngine.EngineData.Item.Peer.Peer.init)), EngineDataMap(combinedPeerNotificationSettings.keys.map(TelegramEngine.EngineData.Item.Peer.Peer.init)),
EngineDataMap(view.notificationSettings.keys.map(TelegramEngine.EngineData.Item.Peer.NotificationSettings.init)) EngineDataMap(combinedPeerNotificationSettings.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 combinedPeerNotificationSettings {
if let value = value as? TelegramPeerNotificationSettings {
if 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).withUpdatedPeerDisplayPreviews(peer._asPeer(), settings.displayPreviews._asDisplayPreviews()) current = current.withUpdatedPeerSound(peer._asPeer(), settings.messageSound._asMessageSound()).withUpdatedPeerMuteInterval(peer._asPeer(), settings.muteState.timeInterval).withUpdatedPeerDisplayPreviews(peer._asPeer(), settings.displayPreviews._asDisplayPreviews())
} }
} else if let maybePeer = peerMap[key], let peer = maybePeer { } else if let maybePeer = peerMap[key], let peer = maybePeer {
if case .default = value.messageSound, case .unmuted = value.muteState, case .default = value.displayPreviews { if case .default = value.messageSound, case .unmuted = value.muteState, case .default = value.displayPreviews {
} else { } else {
current = current.withUpdatedPeerSound(peer._asPeer(), value.messageSound).withUpdatedPeerMuteInterval(peer._asPeer(), EnginePeer.NotificationSettings.MuteState(value.muteState).timeInterval).withUpdatedPeerDisplayPreviews(peer._asPeer(), value.displayPreviews) current = current.withUpdatedPeerSound(peer._asPeer(), value.messageSound._asMessageSound()).withUpdatedPeerMuteInterval(peer._asPeer(), value.muteState.timeInterval).withUpdatedPeerDisplayPreviews(peer._asPeer(), value.displayPreviews._asDisplayPreviews())
}
} }
} }
} }
@ -485,9 +485,6 @@ public func notificationsPeerCategoryController(context: AccountContext, categor
completion() completion()
}) })
} else {
completion()
}
})) }))
return current return current
} }

View File

@ -851,12 +851,23 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
updatedBlockedPeers?(blockedPeersContext) updatedBlockedPeers?(blockedPeersContext)
})) }))
let preferencesKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration])) let signal = combineLatest(
queue: .mainQueue(),
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), privacySettingsPromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), context.engine.peers.recentPeers(), blockedPeersState.get(), webSessionsContext.state, context.sharedContext.accountManager.accessChallengeData(), combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()), context.account.postbox.combinedView(keys: [preferencesKey])) context.sharedContext.presentationData,
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, preferences -> (ItemListControllerState, (ItemListNodeState, Any)) in statePromise.get(),
privacySettingsPromise.get(),
context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()),
context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]),
context.engine.peers.recentPeers(),
blockedPeersState.get(),
webSessionsContext.state,
context.sharedContext.accountManager.accessChallengeData(),
combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App())
)
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration -> (ItemListControllerState, (ItemListNodeState, Any)) in
var canAutoarchive = false var canAutoarchive = false
if let view = preferences.views[preferencesKey] as? PreferencesView, let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self), let data = appConfiguration.data, let hasAutoarchive = data["autoarchive_setting_available"] as? Bool { if let data = appConfiguration.data, let hasAutoarchive = data["autoarchive_setting_available"] as? Bool {
canAutoarchive = hasAutoarchive canAutoarchive = hasAutoarchive
} }

View File

@ -400,7 +400,7 @@ public final class SettingsSearchContainerNode: SearchDisplayControllerContentNo
self.recentListNode.isHidden = false self.recentListNode.isHidden = false
let previousRecentlySearchedItemOrder = Atomic<[SettingsSearchableItemId]>(value: []) let previousRecentlySearchedItemOrder = Atomic<[SettingsSearchableItemId]>(value: [])
let fixedRecentlySearchedItems = settingsSearchRecentItems(postbox: context.account.postbox) let fixedRecentlySearchedItems = settingsSearchRecentItems(engine: context.engine)
|> map { recentIds -> [SettingsSearchableItemId] in |> map { recentIds -> [SettingsSearchableItemId] in
var result: [SettingsSearchableItemId] = [] var result: [SettingsSearchableItemId] = []
let _ = previousRecentlySearchedItemOrder.modify { current in let _ = previousRecentlySearchedItemOrder.modify { current in

View File

@ -52,18 +52,16 @@ func clearRecentSettingsSearchItems(engine: TelegramEngine) {
let _ = engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems).start() let _ = engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems).start()
} }
func settingsSearchRecentItems(postbox: Postbox) -> Signal<[SettingsSearchableItemId], NoError> { func settingsSearchRecentItems(engine: TelegramEngine) -> Signal<[SettingsSearchableItemId], NoError> {
return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)]) return engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems))
|> map { view -> [SettingsSearchableItemId] in |> map { items -> [SettingsSearchableItemId] in
var result: [SettingsSearchableItemId] = [] var result: [SettingsSearchableItemId] = []
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)] as? OrderedItemListView { for item in items {
for item in view.items {
let index = SettingsSearchRecentQueryItemId(item.id).value let index = SettingsSearchRecentQueryItemId(item.id).value
if let itemId = SettingsSearchableItemId(index: index) { if let itemId = SettingsSearchableItemId(index: index) {
result.append(itemId) result.append(itemId)
} }
} }
}
return result return result
} }
} }

View File

@ -569,7 +569,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode {
} }
let previousRecentItems = Atomic<[ThemeGridRecentEntry]?>(value: nil) let previousRecentItems = Atomic<[ThemeGridRecentEntry]?>(value: nil)
self.recentDisposable = (combineLatest(wallpaperSearchRecentQueries(postbox: self.context.account.postbox), self.presentationDataPromise.get()) self.recentDisposable = (combineLatest(wallpaperSearchRecentQueries(engine: self.context.engine), self.presentationDataPromise.get())
|> deliverOnMainQueue).start(next: { [weak self] queries, presentationData in |> deliverOnMainQueue).start(next: { [weak self] queries, presentationData in
if let strongSelf = self { if let strongSelf = self {
var entries: [ThemeGridRecentEntry] = [] var entries: [ThemeGridRecentEntry] = []

View File

@ -55,16 +55,14 @@ func clearRecentWallpaperSearchQueries(engine: TelegramEngine) -> Signal<Never,
return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries) return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)
} }
func wallpaperSearchRecentQueries(postbox: Postbox) -> Signal<[String], NoError> { func wallpaperSearchRecentQueries(engine: TelegramEngine) -> Signal<[String], NoError> {
return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)]) return engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries))
|> map { view -> [String] in |> map { items -> [String] in
var result: [String] = [] var result: [String] = []
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)] as? OrderedItemListView { for item in items {
for item in view.items {
let value = WallpaperSearchRecentQueryItemId(item.id).value let value = WallpaperSearchRecentQueryItemId(item.id).value
result.append(value) result.append(value)
} }
}
return result return result
} }
} }

View File

@ -1391,15 +1391,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
@ -1413,11 +1412,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
let adminIds = combineLatest(queue: .mainQueue(), let adminIds = combineLatest(queue: .mainQueue(),
rawAdminIds, rawAdminIds,
accountContext.account.postbox.combinedView(keys: [.basicPeer(peerId)]) accountContext.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
) )
|> map { rawAdminIds, view -> Set<PeerId> in |> map { rawAdminIds, peer -> Set<PeerId> in
var rawAdminIds = rawAdminIds var rawAdminIds = rawAdminIds
if let peerView = view.views[.basicPeer(peerId)] as? BasicPeerView, let peer = peerView.peer as? TelegramChannel { if case let .channel(peer) = peer {
if peer.hasPermission(.manageCalls) { if peer.hasPermission(.manageCalls) {
rawAdminIds.insert(accountContext.account.peerId) rawAdminIds.insert(accountContext.account.peerId)
} else { } else {
@ -1991,11 +1990,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
let adminIds = combineLatest(queue: .mainQueue(), let adminIds = combineLatest(queue: .mainQueue(),
rawAdminIds, rawAdminIds,
accountContext.account.postbox.combinedView(keys: [.basicPeer(peerId)]) accountContext.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
) )
|> map { rawAdminIds, view -> Set<PeerId> in |> map { rawAdminIds, peer -> Set<PeerId> in
var rawAdminIds = rawAdminIds var rawAdminIds = rawAdminIds
if let peerView = view.views[.basicPeer(peerId)] as? BasicPeerView, let peer = peerView.peer as? TelegramChannel { if case let .channel(peer) = peer {
if peer.hasPermission(.manageCalls) { if peer.hasPermission(.manageCalls) {
rawAdminIds.insert(accountContext.account.peerId) rawAdminIds.insert(accountContext.account.peerId)
} else { } else {

View File

@ -3,6 +3,11 @@ import Postbox
import TelegramApi import TelegramApi
import MtProtoKit import MtProtoKit
public enum TelegramEngineAuthorizationState {
case unauthorized(UnauthorizedAccountState)
case authorized
}
public extension TelegramEngineUnauthorized { public extension TelegramEngineUnauthorized {
final class Auth { final class Auth {
private let account: UnauthorizedAccount private let account: UnauthorizedAccount
@ -43,6 +48,19 @@ public extension TelegramEngineUnauthorized {
return _internal_uploadedPeerVideo(postbox: self.account.postbox, network: self.account.network, messageMediaPreuploadManager: nil, resource: resource) return _internal_uploadedPeerVideo(postbox: self.account.postbox, network: self.account.network, messageMediaPreuploadManager: nil, resource: resource)
} }
public func state() -> Signal<TelegramEngineAuthorizationState?, NoError> {
return self.account.postbox.stateView()
|> map { view -> TelegramEngineAuthorizationState? in
if let state = view.state as? UnauthorizedAccountState {
return .unauthorized(state)
} else if let _ = view.state as? AuthorizedAccountState {
return .authorized
} else {
return nil
}
}
}
public func setState(state: UnauthorizedAccountState) -> Signal<Never, NoError> { public func setState(state: UnauthorizedAccountState) -> Signal<Never, NoError> {
return self.account.postbox.transaction { transaction -> Void in return self.account.postbox.transaction { transaction -> Void in
transaction.setState(state) transaction.setState(state)

View File

@ -0,0 +1,8 @@
import SwiftSignalKit
import Postbox
public extension TelegramEngine.EngineData.Item {
enum ChatList {
}
}

View File

@ -14,9 +14,9 @@ public final class EngineTotalReadCounters {
} }
public struct EnginePeerReadCounters: Equatable { public struct EnginePeerReadCounters: Equatable {
private let state: CombinedPeerReadState private let state: CombinedPeerReadState?
public init(state: CombinedPeerReadState) { public init(state: CombinedPeerReadState?) {
self.state = state self.state = state
} }
@ -25,24 +25,38 @@ public struct EnginePeerReadCounters: Equatable {
} }
public var count: Int32 { public var count: Int32 {
return self.state.count guard let state = self.state else {
return 0
}
return state.count
} }
public var markedUnread: Bool { public var markedUnread: Bool {
return self.state.markedUnread guard let state = self.state else {
return false
}
return state.markedUnread
} }
public var isUnread: Bool { public var isUnread: Bool {
return self.state.isUnread guard let state = self.state else {
return false
}
return state.isUnread
} }
public func isOutgoingMessageIndexRead(_ index: EngineMessage.Index) -> Bool { public func isOutgoingMessageIndexRead(_ index: EngineMessage.Index) -> Bool {
return self.state.isOutgoingMessageIndexRead(index) guard let state = self.state else {
return false
}
return state.isOutgoingMessageIndexRead(index)
} }
public func isIncomingMessageIndexRead(_ index: EngineMessage.Index) -> Bool { public func isIncomingMessageIndexRead(_ index: EngineMessage.Index) -> Bool {
return self.state.isIncomingMessageIndexRead(index) guard let state = self.state else {
return false
}
return state.isIncomingMessageIndexRead(index)
} }
} }
@ -128,8 +142,8 @@ public extension TelegramEngine.EngineData.Item {
} }
} }
public struct ReadState: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { public struct PeerReadCounters: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = CombinedPeerReadState? public typealias Result = EnginePeerReadCounters
fileprivate let id: EnginePeer.Id fileprivate let id: EnginePeer.Id
public var mapKey: EnginePeer.Id { public var mapKey: EnginePeer.Id {
@ -149,7 +163,7 @@ public extension TelegramEngine.EngineData.Item {
preconditionFailure() preconditionFailure()
} }
return view.state return EnginePeerReadCounters(state: view.state)
} }
} }

View File

@ -0,0 +1,27 @@
import SwiftSignalKit
import Postbox
public extension TelegramEngine.EngineData.Item {
enum OrderedLists {
public struct ListItems: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = [OrderedItemListEntry]
private let collectionId: Int32
public init(collectionId: Int32) {
self.collectionId = collectionId
}
var key: PostboxViewKey {
return .orderedItemList(id: self.collectionId)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? OrderedItemListView else {
preconditionFailure()
}
return view.items
}
}
}
}

View File

@ -526,7 +526,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
self.hasActiveAudioSession.set(MediaManagerImpl.globalAudioSession.isActive()) self.hasActiveAudioSession.set(MediaManagerImpl.globalAudioSession.isActive())
let applicationBindings = TelegramApplicationBindings(isMainApp: true, appBundleId: baseAppBundleId, containerPath: appGroupUrl.path, appSpecificScheme: buildConfig.appSpecificUrlScheme, openUrl: { url in let applicationBindings = TelegramApplicationBindings(isMainApp: true, appBundleId: baseAppBundleId, appBuildType: buildConfig.isAppStoreBuild ? .public : .internal, containerPath: appGroupUrl.path, appSpecificScheme: buildConfig.appSpecificUrlScheme, openUrl: { url in
var parsedUrl = URL(string: url) var parsedUrl = URL(string: url)
if let parsed = parsedUrl { if let parsed = parsedUrl {
if parsed.scheme == nil || parsed.scheme!.isEmpty { if parsed.scheme == nil || parsed.scheme!.isEmpty {

View File

@ -69,11 +69,11 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
super.init(mode: .single, theme: NavigationControllerTheme(statusBar: navigationStatusBar, navigationBar: AuthorizationSequenceController.navigationBarTheme(presentationData.theme), emptyAreaColor: .black)) super.init(mode: .single, theme: NavigationControllerTheme(statusBar: navigationStatusBar, navigationBar: AuthorizationSequenceController.navigationBarTheme(presentationData.theme), emptyAreaColor: .black))
self.stateDisposable = (account.postbox.stateView() self.stateDisposable = (TelegramEngineUnauthorized(account: self.account).auth.state()
|> map { view -> InnerState in |> map { state -> InnerState in
if let _ = view.state as? AuthorizedAccountState { if case .authorized = state {
return .authorized return .authorized
} else if let state = view.state as? UnauthorizedAccountState { } else if case let .unauthorized(state) = state {
return .state(state.contents) return .state(state.contents)
} else { } else {
return .state(.empty) return .state(.empty)
@ -489,11 +489,16 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
if let strongSelf = self, let strongController = controller { if let strongSelf = self, let strongController = controller {
strongController.inProgress = false strongController.inProgress = false
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in let _ = (TelegramEngineUnauthorized(account: strongSelf.account).auth.state()
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordEntry(hint, number, code, _, syncContacts) = state.contents { |> take(1)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordRecovery(hint: hint, number: number, code: code, emailPattern: pattern, syncContacts: syncContacts))) |> deliverOnMainQueue).start(next: { state in
guard let strongSelf = self else {
return
} }
}).start() if case let .unauthorized(state) = state, case let .passwordEntry(hint, number, code, _, syncContacts) = state.contents {
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordRecovery(hint: hint, number: number, code: code, emailPattern: pattern, syncContacts: syncContacts))).start()
}
})
} }
}, error: { error in }, error: { error in
guard let strongController = controller else { guard let strongController = controller else {
@ -560,11 +565,16 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
return return
} }
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in let _ = (TelegramEngineUnauthorized(account: strongSelf.account).auth.state()
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordRecovery(hint, number, code, _, syncContacts) = state.contents { |> take(1)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code, suggestReset: true, syncContacts: syncContacts))) |> deliverOnMainQueue).start(next: { state in
guard let strongSelf = self else {
return
} }
}).start() if case let .unauthorized(state) = state, case let .passwordRecovery(hint, number, code, _, syncContacts) = state.contents {
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code, suggestReset: true, syncContacts: syncContacts))).start()
}
})
} }
return controller return controller
} }

View File

@ -547,13 +547,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
locationBroadcastPanelSource = .none locationBroadcastPanelSource = .none
groupCallPanelSource = .none groupCallPanelSource = .none
let promise = Promise<Message?>() let promise = Promise<Message?>()
let key = PostboxViewKey.messages([replyThreadMessage.messageId]) promise.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: replyThreadMessage.messageId))
promise.set(context.account.postbox.combinedView(keys: [key]) |> map { message -> Message? in
|> map { views -> Message? in guard let message = message else {
guard let view = views.views[key] as? MessagesView else {
return nil return nil
} }
return view.messages[replyThreadMessage.messageId] return message._asMessage()
}) })
self.chatLocationInfoData = .replyThread(promise) self.chatLocationInfoData = .replyThread(promise)
case .feed: case .feed:
@ -1075,7 +1074,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: selectAll)), items: .single(actions), recognizer: recognizer, gesture: gesture) let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, engine: strongSelf.context.engine, message: message, selectAll: selectAll)), items: .single(actions), recognizer: recognizer, gesture: gesture)
controller.getOverlayViews = { [weak self] in controller.getOverlayViews = { [weak self] in
guard let strongSelf = self else { guard let strongSelf = self else {
return [] return []
@ -1207,7 +1206,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageReactionContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, contentView: sourceView)), items: .single(items), recognizer: nil, gesture: gesture) let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageReactionContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, engine: strongSelf.context.engine, message: message, contentView: sourceView)), items: .single(items), recognizer: nil, gesture: gesture)
dismissController = { [weak controller] completion in dismissController = { [weak controller] completion in
controller?.dismiss(completion: { controller?.dismiss(completion: {
@ -2642,7 +2641,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message._asMessage(), selectAll: true)), items: .single(ContextController.Items(content: .list(actions))), recognizer: nil) let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, engine: strongSelf.context.engine, message: message._asMessage(), selectAll: true)), items: .single(ContextController.Items(content: .list(actions))), recognizer: nil)
strongSelf.currentContextController = controller strongSelf.currentContextController = controller
strongSelf.forEachController({ controller in strongSelf.forEachController({ controller in
if let controller = controller as? TooltipScreen { if let controller = controller as? TooltipScreen {
@ -2720,7 +2719,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: topMessage, selectAll: true)), items: .single(ContextController.Items(content: .list(actions))), recognizer: nil) let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, engine: strongSelf.context.engine, message: topMessage, selectAll: true)), items: .single(ContextController.Items(content: .list(actions))), recognizer: nil)
strongSelf.currentContextController = controller strongSelf.currentContextController = controller
strongSelf.forEachController({ controller in strongSelf.forEachController({ controller in
if let controller = controller as? TooltipScreen { if let controller = controller as? TooltipScreen {

View File

@ -575,7 +575,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
) )
} }
let readState = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.ReadState(id: messages[0].id.peerId)) let readCounters = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.PeerReadCounters(id: messages[0].id.peerId))
let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?), NoError> = combineLatest( let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?), NoError> = combineLatest(
loadLimits, loadLimits,
@ -585,13 +585,13 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
context.account.pendingUpdateMessageManager.updatingMessageMedia context.account.pendingUpdateMessageManager.updatingMessageMedia
|> take(1), |> take(1),
infoSummaryData, infoSummaryData,
readState, readCounters,
ApplicationSpecificNotice.getMessageViewsPrivacyTips(accountManager: context.sharedContext.accountManager), ApplicationSpecificNotice.getMessageViewsPrivacyTips(accountManager: context.sharedContext.accountManager),
context.engine.stickers.availableReactions(), context.engine.stickers.availableReactions(),
context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings, SharedDataKeys.loggingSettings]), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings, SharedDataKeys.loggingSettings]),
context.engine.peers.notificationSoundList() |> take(1) context.engine.peers.notificationSoundList() |> take(1)
) )
|> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, readState, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?) in |> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, readCounters, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?) in
let (limitsConfiguration, appConfig) = limitsAndAppConfig let (limitsConfiguration, appConfig) = limitsAndAppConfig
var canEdit = false var canEdit = false
if !isAction { if !isAction {
@ -599,10 +599,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
canEdit = canEditMessage(context: context, limitsConfiguration: limitsConfiguration, message: message) canEdit = canEditMessage(context: context, limitsConfiguration: limitsConfiguration, message: message)
} }
var isMessageRead = false let isMessageRead = readCounters.isOutgoingMessageIndexRead(message.index)
if let readState = readState {
isMessageRead = readState.isOutgoingMessageIndexRead(message.index)
}
let translationSettings: TranslationSettings let translationSettings: TranslationSettings
if let current = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) { if let current = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) {

View File

@ -290,23 +290,17 @@ final class ChatMediaInputGifPane: ChatMediaInputPane, UIScrollViewDelegate {
let filesSignal: Signal<(MultiplexedVideoNodeFiles, String?), NoError> let filesSignal: Signal<(MultiplexedVideoNodeFiles, String?), NoError>
switch self.mode { switch self.mode {
case .recent: case .recent:
filesSignal = combineLatest(self.trendingPromise.get(), self.context.account.postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.CloudRecentGifs)])) filesSignal = combineLatest(
|> map { trending, view -> (MultiplexedVideoNodeFiles, String?) in self.trendingPromise.get(),
var recentGifs: OrderedItemListView? self.context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs))
if let orderedView = view.views[.orderedItemList(id: Namespaces.OrderedItemList.CloudRecentGifs)] { )
recentGifs = orderedView as? OrderedItemListView |> map { trending, cloudRecentGifs -> (MultiplexedVideoNodeFiles, String?) in
}
var saved: [MultiplexedVideoNodeFile] = [] var saved: [MultiplexedVideoNodeFile] = []
if let recentGifs = recentGifs { saved = cloudRecentGifs.map { item in
saved = recentGifs.items.map { item in
let file = item.contents.get(RecentMediaItem.self)!.media let file = item.contents.get(RecentMediaItem.self)!.media
return MultiplexedVideoNodeFile(file: .savedGif(media: file), contextResult: nil) return MultiplexedVideoNodeFile(file: .savedGif(media: file), contextResult: nil)
} }
} else {
saved = []
}
return (MultiplexedVideoNodeFiles(saved: saved, trending: trending?.files ?? [], isSearch: false, canLoadMore: false, isStale: false), nil) return (MultiplexedVideoNodeFiles(saved: saved, trending: trending?.files ?? [], isSearch: false, canLoadMore: false, isStale: false), nil)
} }

View File

@ -3,6 +3,7 @@ import UIKit
import Display import Display
import ContextUI import ContextUI
import Postbox import Postbox
import TelegramCore
import SwiftSignalKit import SwiftSignalKit
final class ChatMessageContextExtractedContentSource: ContextExtractedContentSource { final class ChatMessageContextExtractedContentSource: ContextExtractedContentSource {
@ -11,7 +12,7 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou
let blurBackground: Bool = true let blurBackground: Bool = true
private weak var chatNode: ChatControllerNode? private weak var chatNode: ChatControllerNode?
private let postbox: Postbox private let engine: TelegramEngine
private let message: Message private let message: Message
private let selectAll: Bool private let selectAll: Bool
@ -19,24 +20,21 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou
if self.message.adAttribute != nil { if self.message.adAttribute != nil {
return .single(false) return .single(false)
} }
let viewKey = PostboxViewKey.messages(Set([self.message.id]))
return self.postbox.combinedView(keys: [viewKey]) return self.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: self.message.id))
|> map { views -> Bool in |> map { message -> Bool in
guard let view = views.views[viewKey] as? MessagesView else { if let _ = message {
return false return false
}
if view.messages.isEmpty {
return true
} else { } else {
return false return true
} }
} }
|> distinctUntilChanged |> distinctUntilChanged
} }
init(chatNode: ChatControllerNode, postbox: Postbox, message: Message, selectAll: Bool) { init(chatNode: ChatControllerNode, engine: TelegramEngine, message: Message, selectAll: Bool) {
self.chatNode = chatNode self.chatNode = chatNode
self.postbox = postbox self.engine = engine
self.message = message self.message = message
self.selectAll = selectAll self.selectAll = selectAll
} }
@ -89,7 +87,7 @@ final class ChatMessageReactionContextExtractedContentSource: ContextExtractedCo
let centerActionsHorizontally: Bool = true let centerActionsHorizontally: Bool = true
private weak var chatNode: ChatControllerNode? private weak var chatNode: ChatControllerNode?
private let postbox: Postbox private let engine: TelegramEngine
private let message: Message private let message: Message
private let contentView: ContextExtractedContentContainingView private let contentView: ContextExtractedContentContainingView
@ -97,24 +95,21 @@ final class ChatMessageReactionContextExtractedContentSource: ContextExtractedCo
if self.message.adAttribute != nil { if self.message.adAttribute != nil {
return .single(false) return .single(false)
} }
let viewKey = PostboxViewKey.messages(Set([self.message.id]))
return self.postbox.combinedView(keys: [viewKey]) return self.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: self.message.id))
|> map { views -> Bool in |> map { message -> Bool in
guard let view = views.views[viewKey] as? MessagesView else { if let _ = message {
return false return false
}
if view.messages.isEmpty {
return true
} else { } else {
return false return true
} }
} }
|> distinctUntilChanged |> distinctUntilChanged
} }
init(chatNode: ChatControllerNode, postbox: Postbox, message: Message, contentView: ContextExtractedContentContainingView) { init(chatNode: ChatControllerNode, engine: TelegramEngine, message: Message, contentView: ContextExtractedContentContainingView) {
self.chatNode = chatNode self.chatNode = chatNode
self.postbox = postbox self.engine = engine
self.message = message self.message = message
self.contentView = contentView self.contentView = contentView
} }

View File

@ -33,6 +33,7 @@ private func setupSharedLogger(rootPath: String, path: String) {
public struct NotificationViewControllerInitializationData { public struct NotificationViewControllerInitializationData {
public let appBundleId: String public let appBundleId: String
public let appBuildType: TelegramAppBuildType
public let appGroupPath: String public let appGroupPath: String
public let apiId: Int32 public let apiId: Int32
public let apiHash: String public let apiHash: String
@ -41,8 +42,9 @@ public struct NotificationViewControllerInitializationData {
public let appVersion: String public let appVersion: String
public let bundleData: Data? public let bundleData: Data?
public init(appBundleId: String, appGroupPath: String, apiId: Int32, apiHash: String, languagesCategory: String, encryptionParameters: (Data, Data), appVersion: String, bundleData: Data?) { public init(appBundleId: String, appBuildType: TelegramAppBuildType, appGroupPath: String, apiId: Int32, apiHash: String, languagesCategory: String, encryptionParameters: (Data, Data), appVersion: String, bundleData: Data?) {
self.appBundleId = appBundleId self.appBundleId = appBundleId
self.appBuildType = appBuildType
self.appGroupPath = appGroupPath self.appGroupPath = appGroupPath
self.apiId = apiId self.apiId = apiId
self.apiHash = apiHash self.apiHash = apiHash
@ -104,7 +106,7 @@ public final class NotificationViewControllerImpl {
}) })
semaphore.wait() semaphore.wait()
let applicationBindings = TelegramApplicationBindings(isMainApp: false, appBundleId: self.initializationData.appBundleId, containerPath: self.initializationData.appGroupPath, appSpecificScheme: "tgapp", openUrl: { _ in let applicationBindings = TelegramApplicationBindings(isMainApp: false, appBundleId: self.initializationData.appBundleId, appBuildType: self.initializationData.appBuildType, containerPath: self.initializationData.appGroupPath, appSpecificScheme: "tgapp", openUrl: { _ in
}, openUniversalUrl: { _, completion in }, openUniversalUrl: { _, completion in
completion.completion(false) completion.completion(false)
return return

View File

@ -195,16 +195,16 @@ final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
self.disposable = (combineLatest(queue: .mainQueue(), self.disposable = (combineLatest(queue: .mainQueue(),
membersContext.state, membersContext.state,
self.presentationDataPromise.get(), self.presentationDataPromise.get(),
context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
) )
|> deliverOnMainQueue).start(next: { [weak self] state, presentationData, combinedView in |> deliverOnMainQueue).start(next: { [weak self] state, presentationData, enclosingPeer in
guard let strongSelf = self, let basicPeerView = combinedView.views[.basicPeer(peerId)] as? BasicPeerView, let enclosingPeer = basicPeerView.peer else { guard let strongSelf = self, let enclosingPeer = enclosingPeer else {
return return
} }
strongSelf.enclosingPeer = enclosingPeer strongSelf.enclosingPeer = enclosingPeer._asPeer()
strongSelf.currentState = state strongSelf.currentState = state
strongSelf.updateState(enclosingPeer: enclosingPeer, state: state, presentationData: presentationData) strongSelf.updateState(enclosingPeer: enclosingPeer._asPeer(), state: state, presentationData: presentationData)
}) })
self.listNode.visibleBottomContentOffsetChanged = { [weak self] offset in self.listNode.visibleBottomContentOffsetChanged = { [weak self] offset in

View File

@ -173,7 +173,7 @@ final class PeerInfoScreenData {
let cachedData: CachedPeerData? let cachedData: CachedPeerData?
let status: PeerInfoStatusData? let status: PeerInfoStatusData?
let notificationSettings: TelegramPeerNotificationSettings? let notificationSettings: TelegramPeerNotificationSettings?
let globalNotificationSettings: GlobalNotificationSettings? let globalNotificationSettings: EngineGlobalNotificationSettings?
let isContact: Bool let isContact: Bool
let availablePanes: [PeerInfoPaneKey] let availablePanes: [PeerInfoPaneKey]
let groupsInCommon: GroupsInCommonContext? let groupsInCommon: GroupsInCommonContext?
@ -191,7 +191,7 @@ final class PeerInfoScreenData {
cachedData: CachedPeerData?, cachedData: CachedPeerData?,
status: PeerInfoStatusData?, status: PeerInfoStatusData?,
notificationSettings: TelegramPeerNotificationSettings?, notificationSettings: TelegramPeerNotificationSettings?,
globalNotificationSettings: GlobalNotificationSettings?, globalNotificationSettings: EngineGlobalNotificationSettings?,
isContact: Bool, isContact: Bool,
availablePanes: [PeerInfoPaneKey], availablePanes: [PeerInfoPaneKey],
groupsInCommon: GroupsInCommonContext?, groupsInCommon: GroupsInCommonContext?,
@ -313,13 +313,13 @@ enum PeerInfoMembersData: Equatable {
} }
} }
private func peerInfoScreenInputData(context: AccountContext, peerId: PeerId, isSettings: Bool) -> Signal<PeerInfoScreenInputData, NoError> { private func peerInfoScreenInputData(context: AccountContext, peerId: EnginePeer.Id, isSettings: Bool) -> Signal<PeerInfoScreenInputData, NoError> {
return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) return context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> map { view -> PeerInfoScreenInputData in |> map { peer -> PeerInfoScreenInputData in
guard let peer = (view.views[.basicPeer(peerId)] as? BasicPeerView)?.peer else { guard let peer = peer else {
return .none return .none
} }
if let user = peer as? TelegramUser { if case let .user(user) = peer {
if isSettings && user.id == context.account.peerId { if isSettings && user.id == context.account.peerId {
return .settings return .settings
} else { } else {
@ -333,15 +333,15 @@ private func peerInfoScreenInputData(context: AccountContext, peerId: PeerId, is
} }
return .user(userId: user.id, secretChatId: nil, kind: kind) return .user(userId: user.id, secretChatId: nil, kind: kind)
} }
} else if let channel = peer as? TelegramChannel { } else if case let .channel(channel) = peer {
if case .group = channel.info { if case .group = channel.info {
return .group(groupId: channel.id) return .group(groupId: channel.id)
} else { } else {
return .channel return .channel
} }
} else if let group = peer as? TelegramGroup { } else if case let .legacyGroup(group) = peer {
return .group(groupId: group.id) return .group(groupId: group.id)
} else if let secretChat = peer as? TelegramSecretChat { } else if case let .secretChat(secretChat) = peer {
return .user(userId: secretChat.regularPeerId, secretChatId: peer.id, kind: .user) return .user(userId: secretChat.regularPeerId, secretChatId: peer.id, kind: .user)
} else { } else {
return .none return .none
@ -565,26 +565,18 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
return disposable return disposable
} }
|> distinctUntilChanged |> distinctUntilChanged
let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set<ValueBoxKey>([PreferencesKeys.globalNotifications]))
var combinedKeys: [PostboxViewKey] = [] var combinedKeys: [PostboxViewKey] = []
combinedKeys.append(globalNotificationsKey)
if let secretChatId = secretChatId { if let secretChatId = secretChatId {
combinedKeys.append(.peerChatState(peerId: secretChatId)) combinedKeys.append(.peerChatState(peerId: 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.account.postbox.combinedView(keys: combinedKeys), context.account.postbox.combinedView(keys: combinedKeys),
status status
) )
|> map { peerView, availablePanes, combinedView, status -> PeerInfoScreenData in |> map { peerView, availablePanes, globalNotificationSettings, combinedView, status -> PeerInfoScreenData in
var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings
if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView {
if let settings = preferencesView.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) {
globalNotificationSettings = settings
}
}
var encryptionKeyFingerprint: SecretChatKeyFingerprint? var encryptionKeyFingerprint: SecretChatKeyFingerprint?
if let secretChatId = secretChatId, let peerChatStateView = combinedView.views[.peerChatState(peerId: secretChatId)] as? PeerChatStateView { if let secretChatId = secretChatId, let peerChatStateView = combinedView.views[.peerChatState(peerId: secretChatId)] as? PeerChatStateView {
if let peerChatState = peerChatStateView.chatState?.getLegacy() as? SecretChatState { if let peerChatState = peerChatStateView.chatState?.getLegacy() as? SecretChatState {
@ -632,10 +624,6 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
} }
|> distinctUntilChanged |> distinctUntilChanged
let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set<ValueBoxKey>([PreferencesKeys.globalNotifications]))
var combinedKeys: [PostboxViewKey] = []
combinedKeys.append(globalNotificationsKey)
let invitationsContextPromise = Promise<PeerExportedInvitationsContext?>(nil) let invitationsContextPromise = Promise<PeerExportedInvitationsContext?>(nil)
let invitationsStatePromise = Promise<PeerExportedInvitationsState?>(nil) let invitationsStatePromise = Promise<PeerExportedInvitationsState?>(nil)
@ -645,21 +633,14 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
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.account.postbox.combinedView(keys: combinedKeys), context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()),
status, status,
invitationsContextPromise.get(), invitationsContextPromise.get(),
invitationsStatePromise.get(), invitationsStatePromise.get(),
requestsContextPromise.get(), requestsContextPromise.get(),
requestsStatePromise.get() requestsStatePromise.get()
) )
|> map { peerView, availablePanes, combinedView, status, currentInvitationsContext, invitations, currentRequestsContext, requests -> PeerInfoScreenData in |> map { peerView, availablePanes, globalNotificationSettings, status, currentInvitationsContext, invitations, currentRequestsContext, requests -> PeerInfoScreenData in
var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings
if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView {
if let settings = preferencesView.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) {
globalNotificationSettings = settings
}
}
var discussionPeer: Peer? var discussionPeer: Peer?
if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] { if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] {
discussionPeer = peer discussionPeer = peer
@ -795,10 +776,6 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
} }
|> distinctUntilChanged |> distinctUntilChanged
let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set<ValueBoxKey>([PreferencesKeys.globalNotifications]))
var combinedKeys: [PostboxViewKey] = []
combinedKeys.append(globalNotificationsKey)
let invitationsContextPromise = Promise<PeerExportedInvitationsContext?>(nil) let invitationsContextPromise = Promise<PeerExportedInvitationsContext?>(nil)
let invitationsStatePromise = Promise<PeerExportedInvitationsState?>(nil) let invitationsStatePromise = Promise<PeerExportedInvitationsState?>(nil)
@ -808,7 +785,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
return combineLatest(queue: .mainQueue(), return combineLatest(queue: .mainQueue(),
context.account.viewTracker.peerView(groupId, updateData: true), context.account.viewTracker.peerView(groupId, updateData: true),
peerInfoAvailableMediaPanes(context: context, peerId: groupId), peerInfoAvailableMediaPanes(context: context, peerId: groupId),
context.account.postbox.combinedView(keys: combinedKeys), context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()),
status, status,
membersData, membersData,
invitationsContextPromise.get(), invitationsContextPromise.get(),
@ -816,14 +793,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
requestsContextPromise.get(), requestsContextPromise.get(),
requestsStatePromise.get() requestsStatePromise.get()
) )
|> map { peerView, availablePanes, combinedView, status, membersData, currentInvitationsContext, invitations, currentRequestsContext, requests -> PeerInfoScreenData in |> map { peerView, availablePanes, globalNotificationSettings, status, membersData, currentInvitationsContext, invitations, currentRequestsContext, requests -> PeerInfoScreenData in
var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings
if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView {
if let settings = preferencesView.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) {
globalNotificationSettings = settings
}
}
var discussionPeer: Peer? var discussionPeer: Peer?
if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] { if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] {
discussionPeer = peer discussionPeer = peer

View File

@ -444,16 +444,14 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
if item?.message.id != self.currentlyObservedMessageId { if item?.message.id != self.currentlyObservedMessageId {
self.currentlyObservedMessageId = item?.message.id self.currentlyObservedMessageId = item?.message.id
if let id = item?.message.id { if let id = item?.message.id {
let key: PostboxViewKey = .messages(Set([id])) self.currentlyObservedMessageDisposable.set((self.context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: id))
self.currentlyObservedMessageDisposable.set((self.context.account.postbox.combinedView(keys: [key]) |> filter { message in
|> filter { views in if let _ = message {
if let view = views.views[key] as? MessagesView {
if !view.messages.isEmpty {
return false return false
} } else {
}
return true return true
} }
}
|> take(1) |> take(1)
|> deliverOnMainQueue).start(next: { [weak self] _ in |> deliverOnMainQueue).start(next: { [weak self] _ in
self?.currentItemDisappeared?() self?.currentItemDisappeared?()

View File

@ -56,6 +56,7 @@ private enum ShareAuthorizationError {
public struct ShareRootControllerInitializationData { public struct ShareRootControllerInitializationData {
public let appBundleId: String public let appBundleId: String
public let appBuildType: TelegramAppBuildType
public let appGroupPath: String public let appGroupPath: String
public let apiId: Int32 public let apiId: Int32
public let apiHash: String public let apiHash: String
@ -64,8 +65,9 @@ public struct ShareRootControllerInitializationData {
public let appVersion: String public let appVersion: String
public let bundleData: Data? public let bundleData: Data?
public init(appBundleId: String, appGroupPath: String, apiId: Int32, apiHash: String, languagesCategory: String, encryptionParameters: (Data, Data), appVersion: String, bundleData: Data?) { public init(appBundleId: String, appBuildType: TelegramAppBuildType, appGroupPath: String, apiId: Int32, apiHash: String, languagesCategory: String, encryptionParameters: (Data, Data), appVersion: String, bundleData: Data?) {
self.appBundleId = appBundleId self.appBundleId = appBundleId
self.appBuildType = appBuildType
self.appGroupPath = appGroupPath self.appGroupPath = appGroupPath
self.apiId = apiId self.apiId = apiId
self.apiHash = apiHash self.apiHash = apiHash
@ -178,7 +180,7 @@ public class ShareRootControllerImpl {
setupSharedLogger(rootPath: rootPath, path: logsPath) setupSharedLogger(rootPath: rootPath, path: logsPath)
let applicationBindings = TelegramApplicationBindings(isMainApp: false, appBundleId: self.initializationData.appBundleId, containerPath: self.initializationData.appGroupPath, appSpecificScheme: "tg", openUrl: { _ in let applicationBindings = TelegramApplicationBindings(isMainApp: false, appBundleId: self.initializationData.appBundleId, appBuildType: self.initializationData.appBuildType, containerPath: self.initializationData.appGroupPath, appSpecificScheme: "tg", openUrl: { _ in
}, openUniversalUrl: { _, completion in }, openUniversalUrl: { _, completion in
completion.completion(false) completion.completion(false)
return return

View File

@ -575,13 +575,12 @@ public final class SharedAccountContextImpl: SharedAccountContext {
self.activeAccountsWithInfoPromise.set(self.activeAccountContexts self.activeAccountsWithInfoPromise.set(self.activeAccountContexts
|> mapToSignal { primary, accounts, _ -> Signal<(primary: AccountRecordId?, accounts: [AccountWithInfo]), NoError> in |> mapToSignal { primary, accounts, _ -> Signal<(primary: AccountRecordId?, accounts: [AccountWithInfo]), NoError> in
return combineLatest(accounts.map { _, context, _ -> Signal<AccountWithInfo?, NoError> in return combineLatest(accounts.map { _, context, _ -> Signal<AccountWithInfo?, NoError> in
let peerViewKey: PostboxViewKey = .peer(peerId: context.account.peerId, components: []) return context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
return context.account.postbox.combinedView(keys: [peerViewKey]) |> map { peer -> AccountWithInfo? in
|> map { view -> AccountWithInfo? in guard let peer = peer else {
guard let peerView = view.views[peerViewKey] as? PeerView, let peer = peerView.peers[peerView.peerId] else {
return nil return nil
} }
return AccountWithInfo(account: context.account, peer: peer) return AccountWithInfo(account: context.account, peer: peer._asPeer())
} }
|> distinctUntilChanged |> distinctUntilChanged
}) })

View File

@ -511,15 +511,16 @@ public final class PeerChannelMemberCategoriesContextsManager {
let updatedIds = Set(idList) let updatedIds = Set(idList)
if previousIds != updatedIds { if previousIds != updatedIds {
previousIds = updatedIds previousIds = updatedIds
let key: PostboxViewKey = .peerPresences(peerIds: updatedIds)
statusesDisposable.set((postbox.combinedView(keys: [key]) statusesDisposable.set((engine.data.subscribe(EngineDataMap(
|> map { view -> Int32 in updatedIds.map(TelegramEngine.EngineData.Item.Peer.Presence.init)
))
|> map { presenceMap -> Int32 in
var count: Int32 = 0 var count: Int32 = 0
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
if let presences = (view.views[key] as? PeerPresencesView)?.presences { for (_, presence) in presenceMap {
for (_, presence) in presences { if let presence = presence {
if let presence = presence as? TelegramUserPresence { let relativeStatus = relativeUserPresenceStatus(presence, relativeTo: Int32(timestamp))
let relativeStatus = relativeUserPresenceStatus(EnginePeer.Presence(presence), relativeTo: Int32(timestamp))
switch relativeStatus { switch relativeStatus {
case .online: case .online:
count += 1 count += 1
@ -528,7 +529,6 @@ public final class PeerChannelMemberCategoriesContextsManager {
} }
} }
} }
}
return count return count
} }
|> distinctUntilChanged |> distinctUntilChanged

View File

@ -282,7 +282,7 @@ class WebSearchControllerNode: ASDisplayNode {
if !attachment { if !attachment {
let previousRecentItems = Atomic<[WebSearchRecentQueryEntry]?>(value: nil) let previousRecentItems = Atomic<[WebSearchRecentQueryEntry]?>(value: nil)
self.recentDisposable = (combineLatest(webSearchRecentQueries(postbox: self.context.account.postbox), self.webSearchInterfaceStatePromise.get()) self.recentDisposable = (combineLatest(webSearchRecentQueries(engine: self.context.engine), self.webSearchInterfaceStatePromise.get())
|> deliverOnMainQueue).start(next: { [weak self] queries, interfaceState in |> deliverOnMainQueue).start(next: { [weak self] queries, interfaceState in
if let strongSelf = self { if let strongSelf = self {
var entries: [WebSearchRecentQueryEntry] = [] var entries: [WebSearchRecentQueryEntry] = []

View File

@ -56,16 +56,14 @@ func clearRecentWebSearchQueries(engine: TelegramEngine) -> Signal<Never, NoErro
return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries) return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)
} }
func webSearchRecentQueries(postbox: Postbox) -> Signal<[String], NoError> { func webSearchRecentQueries(engine: TelegramEngine) -> Signal<[String], NoError> {
return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)]) return engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries))
|> mapToSignal { view -> Signal<[String], NoError> in |> map { items -> [String] in
var result: [String] = [] var result: [String] = []
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)] as? OrderedItemListView { for item in items {
for item in view.items {
let value = WebSearchRecentQueryItemId(item.id).value let value = WebSearchRecentQueryItemId(item.id).value
result.append(value) result.append(value)
} }
} return result
return .single(result)
} }
} }