This commit is contained in:
Ali 2023-06-24 01:29:50 +03:00
parent 9110d1912a
commit 805cb5c610
9 changed files with 384 additions and 114 deletions

View File

@ -1978,12 +1978,12 @@ ios_application(
extensions = select({
":disableExtensionsSetting": [],
"//conditions:default": [
":ShareExtension",
":NotificationContentExtension",
#":ShareExtension",
#":NotificationContentExtension",
":NotificationServiceExtension",
":IntentsExtension",
":WidgetExtension",
":BroadcastUploadExtension",
#":IntentsExtension",
#":WidgetExtension",
#":BroadcastUploadExtension",
],
}),
watch_application = select({
@ -2013,9 +2013,9 @@ xcodeproj(
"Debug": {
"//command_line_option:compilation_mode": "dbg",
},
"Release": {
"//command_line_option:compilation_mode": "opt",
},
#"Release": {
# "//command_line_option:compilation_mode": "opt",
#},
},
default_xcode_configuration = "Debug"

View File

@ -847,6 +847,7 @@ private final class NotificationServiceHandler {
var peerId: PeerId?
var messageId: MessageId.Id?
var storyId: Int32?
var mediaAttachment: Media?
var downloadNotificationSound: (file: TelegramMediaFile, path: String, fileName: String)?
@ -868,6 +869,9 @@ private final class NotificationServiceHandler {
if let messageIdString = payloadJson["msg_id"] as? String {
messageId = Int32(messageIdString)
}
if let storyIdString = payloadJson["story_id"] as? String {
storyId = Int32(storyIdString)
}
if let fromIdString = payloadJson["from_id"] as? String {
if let userIdValue = Int64(fromIdString) {
@ -917,6 +921,7 @@ private final class NotificationServiceHandler {
enum Action {
case logout
case poll(peerId: PeerId, content: NotificationContent, messageId: MessageId?)
case pollStories(peerId: PeerId, content: NotificationContent, storyId: Int32)
case deleteMessage([MessageId])
case readReactions([MessageId])
case readMessage(MessageId)
@ -1004,6 +1009,10 @@ private final class NotificationServiceHandler {
messageIdValue = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: messageId)
}
if let storyId = storyId {
interactionAuthorId = peerId
content.userInfo["story_id"] = "\(storyId)"
}
if peerId.namespace == Namespaces.Peer.CloudUser {
content.userInfo["from_id"] = "\(peerId.id._internalGetInt64Value())"
@ -1107,7 +1116,11 @@ private final class NotificationServiceHandler {
}
}*/
action = .poll(peerId: peerId, content: content, messageId: messageIdValue)
if let storyId {
action = .pollStories(peerId: peerId, content: content, storyId: storyId)
} else {
action = .poll(peerId: peerId, content: content, messageId: messageIdValue)
}
updateCurrentContent(content)
}
@ -1549,6 +1562,168 @@ private final class NotificationServiceHandler {
|> map { _ -> NotificationContent in }
}
var updatedContent = initialContent
strongSelf.pollDisposable.set(pollWithUpdatedContent.start(next: { content in
updatedContent = content
}, completed: {
pollCompletion(updatedContent)
}))
} else {
completed()
}
case let .pollStories(peerId, initialContent, _):
Logger.shared.log("NotificationService \(episode)", "Will poll stories for \(peerId)")
if let stateManager = strongSelf.stateManager {
let pollCompletion: (NotificationContent) -> Void = { content in
let content = content
queue.async {
guard let strongSelf = self, let stateManager = strongSelf.stateManager else {
let content = NotificationContent(isLockedMessage: isLockedMessage)
updateCurrentContent(content)
completed()
return
}
var fetchStoriesSignal: Signal<Void, NoError> = .single(Void())
fetchStoriesSignal = _internal_pollPeerStories(postbox: stateManager.postbox, network: stateManager.network, accountPeerId: stateManager.accountPeerId, peerId: peerId)
|> map { _ -> Void in
}
|> then(.single(Void()))
let fetchMediaSignal: Signal<Data?, NoError> = .single(nil)
var fetchNotificationSoundSignal: Signal<Data?, NoError> = .single(nil)
if let (downloadNotificationSound, _, _) = downloadNotificationSound {
var fetchResource: TelegramMultipartFetchableResource?
fetchResource = downloadNotificationSound.resource as? TelegramMultipartFetchableResource
if let resource = fetchResource {
if let path = strongSelf.stateManager?.postbox.mediaBox.completedResourcePath(resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path)) {
fetchNotificationSoundSignal = .single(data)
} else {
let intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError> = .single([(0 ..< Int64.max, MediaBoxFetchPriority.maximum)])
fetchNotificationSoundSignal = Signal { subscriber in
let collectedData = Atomic<Data>(value: Data())
return standaloneMultipartFetch(
accountPeerId: stateManager.accountPeerId,
postbox: stateManager.postbox,
network: stateManager.network,
resource: resource,
datacenterId: resource.datacenterId,
size: nil,
intervals: intervals,
parameters: MediaResourceFetchParameters(
tag: nil,
info: resourceFetchInfo(resource: resource),
location: nil,
contentType: .other,
isRandomAccessAllowed: true
),
encryptionKey: nil,
decryptedSize: nil,
continueInBackground: false,
useMainConnection: true
).start(next: { result in
switch result {
case let .dataPart(_, data, _, _):
let _ = collectedData.modify { current in
var current = current
current.append(data)
return current
}
default:
break
}
}, error: { _ in
subscriber.putNext(nil)
subscriber.putCompletion()
}, completed: {
subscriber.putNext(collectedData.with({ $0 }))
subscriber.putCompletion()
})
}
}
}
}
Logger.shared.log("NotificationService \(episode)", "Will fetch media")
let _ = (combineLatest(queue: queue,
fetchMediaSignal
|> timeout(10.0, queue: queue, alternate: .single(nil)),
fetchNotificationSoundSignal
|> timeout(10.0, queue: queue, alternate: .single(nil)),
fetchStoriesSignal
|> timeout(10.0, queue: queue, alternate: .single(Void()))
)
|> deliverOn(queue)).start(next: { mediaData, notificationSoundData, _ in
guard let strongSelf = self, let _ = strongSelf.stateManager else {
completed()
return
}
Logger.shared.log("NotificationService \(episode)", "Did fetch media \(mediaData == nil ? "Non-empty" : "Empty")")
if let notificationSoundData = notificationSoundData {
Logger.shared.log("NotificationService \(episode)", "Did fetch notificationSoundData")
if let (_, filePath, _) = downloadNotificationSound {
let _ = try? notificationSoundData.write(to: URL(fileURLWithPath: filePath))
}
}
Logger.shared.log("NotificationService \(episode)", "Updating content to \(content)")
updateCurrentContent(content)
completed()
})
}
}
let pollSignal: Signal<Never, NoError>
pollSignal = .complete()
stateManager.network.shouldKeepConnection.set(.single(true))
let pollWithUpdatedContent: Signal<NotificationContent, NoError>
if interactionAuthorId != nil || messageId != nil {
pollWithUpdatedContent = stateManager.postbox.transaction { transaction -> NotificationContent in
var content = initialContent
if let interactionAuthorId = interactionAuthorId {
if inAppNotificationSettings.displayNameOnLockscreen, let peer = transaction.getPeer(interactionAuthorId) {
var foundLocalId: String?
transaction.enumerateDeviceContactImportInfoItems({ _, value in
if let value = value as? TelegramDeviceContactImportedData {
switch value {
case let .imported(data, _, peerId):
if peerId == interactionAuthorId {
foundLocalId = data.localIdentifiers.first
return false
}
default:
break
}
}
return true
})
content.addSenderInfo(mediaBox: stateManager.postbox.mediaBox, accountPeerId: stateManager.accountPeerId, peer: peer, topicTitle: topicTitle, contactIdentifier: foundLocalId)
}
}
return content
}
|> then(
pollSignal
|> map { _ -> NotificationContent in }
)
} else {
pollWithUpdatedContent = pollSignal
|> map { _ -> NotificationContent in }
}
var updatedContent = initialContent
strongSelf.pollDisposable.set(pollWithUpdatedContent.start(next: { content in
updatedContent = content

View File

@ -21,4 +21,6 @@ public protocol ChatListController: ViewController {
func playSignUpCompletedAnimation()
func navigateToFolder(folderId: Int32, completion: @escaping () -> Void)
func openStories(peerId: EnginePeer.Id)
}

View File

@ -2511,62 +2511,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
}
self.shouldFixStorySubscriptionOrder = true
let storyContent = StoryContentContextImpl(context: self.context, isHidden: false, focusedPeerId: peer.id, singlePeer: false, fixedOrder: self.fixedStorySubscriptionOrder)
let _ = (storyContent.state
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
guard let self else {
return
}
if peer.id == self.context.account.peerId, storyContentState.slice == nil {
self.openStoryCamera()
return
}
var transitionIn: StoryContainerScreen.TransitionIn?
if let componentView = self.chatListHeaderView() {
if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peer.id) {
transitionIn = StoryContainerScreen.TransitionIn(
sourceView: transitionView,
sourceRect: transitionView.bounds,
sourceCornerRadius: transitionView.bounds.height * 0.5,
sourceIsAvatar: true
)
}
}
let storyContainerScreen = StoryContainerScreen(
context: self.context,
content: storyContent,
transitionIn: transitionIn,
transitionOut: { [weak self] peerId, _ in
guard let self else {
return nil
}
if let componentView = self.chatListHeaderView() {
if let (transitionView, transitionContentView) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) {
return StoryContainerScreen.TransitionOut(
destinationView: transitionView,
transitionView: transitionContentView,
destinationRect: transitionView.bounds,
destinationCornerRadius: transitionView.bounds.height * 0.5,
destinationIsAvatar: true,
completed: {}
)
}
}
return nil
}
)
if let componentView = self.chatListHeaderView() {
componentView.storyPeerListView()?.setPreviewedItem(signal: storyContainerScreen.focusedItem)
}
self.push(storyContainerScreen)
})
self.openStories(peerId: peer.id)
}
componentView.storyContextPeerAction = { [weak self] sourceNode, gesture, peer in
@ -3342,6 +3287,77 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
})
}
public func openStories(peerId: EnginePeer.Id) {
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View {
if navigationBarView.storiesUnlocked {
self.shouldFixStorySubscriptionOrder = true
}
}
let storyContent = StoryContentContextImpl(context: self.context, isHidden: false, focusedPeerId: peerId, singlePeer: false, fixedOrder: self.fixedStorySubscriptionOrder)
let _ = (storyContent.state
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
guard let self else {
return
}
if peerId == self.context.account.peerId, storyContentState.slice == nil {
self.openStoryCamera()
return
}
var transitionIn: StoryContainerScreen.TransitionIn?
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View {
if navigationBarView.storiesUnlocked {
if let componentView = self.chatListHeaderView() {
if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) {
transitionIn = StoryContainerScreen.TransitionIn(
sourceView: transitionView,
sourceRect: transitionView.bounds,
sourceCornerRadius: transitionView.bounds.height * 0.5,
sourceIsAvatar: true
)
}
}
}
}
let storyContainerScreen = StoryContainerScreen(
context: self.context,
content: storyContent,
transitionIn: transitionIn,
transitionOut: { [weak self] peerId, _ in
guard let self else {
return nil
}
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View {
if navigationBarView.storiesUnlocked {
if let componentView = self.chatListHeaderView() {
if let (transitionView, transitionContentView) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) {
return StoryContainerScreen.TransitionOut(
destinationView: transitionView,
transitionView: transitionContentView,
destinationRect: transitionView.bounds,
destinationCornerRadius: transitionView.bounds.height * 0.5,
destinationIsAvatar: true,
completed: {}
)
}
}
}
}
return nil
}
)
if let componentView = self.chatListHeaderView() {
componentView.storyPeerListView()?.setPreviewedItem(signal: storyContainerScreen.focusedItem)
}
self.push(storyContainerScreen)
})
}
private func askForFilterRemoval(id: Int32) {
let apply: () -> Void = { [weak self] in
guard let strongSelf = self else {

View File

@ -552,7 +552,7 @@ private func notificationsAndSoundsEntries(authorizationStatus: AccessType, warn
entries.append(.groupChats(presentationData.theme, presentationData.strings.Notifications_GroupChats, !exceptions.groups.isEmpty ? presentationData.strings.Notifications_CategoryExceptions(Int32(exceptions.groups.peerIds.count)) : "", globalSettings.groupChats.enabled ? presentationData.strings.Notifications_On : presentationData.strings.Notifications_Off))
entries.append(.channels(presentationData.theme, presentationData.strings.Notifications_Channels, !exceptions.channels.isEmpty ? presentationData.strings.Notifications_CategoryExceptions(Int32(exceptions.channels.peerIds.count)) : "", globalSettings.channels.enabled ? presentationData.strings.Notifications_On : presentationData.strings.Notifications_Off))
//TODO:localize
entries.append(.stories(presentationData.theme, "Stories", !exceptions.stories.isEmpty ? presentationData.strings.Notifications_CategoryExceptions(Int32(exceptions.stories.peerIds.count)) : "", globalSettings.privateChats.storiesMuted != false ? presentationData.strings.Notifications_On : presentationData.strings.Notifications_Off))
entries.append(.stories(presentationData.theme, "Stories", !exceptions.stories.isEmpty ? presentationData.strings.Notifications_CategoryExceptions(Int32(exceptions.stories.peerIds.count)) : "", globalSettings.privateChats.storiesMuted != true ? presentationData.strings.Notifications_On : presentationData.strings.Notifications_Off))
entries.append(.inAppHeader(presentationData.theme, presentationData.strings.Notifications_InAppNotifications.uppercased()))
entries.append(.inAppSounds(presentationData.theme, presentationData.strings.Notifications_InAppNotificationsSounds, inAppSettings.playSounds))

View File

@ -1083,3 +1083,67 @@ public final class PeerExpiringStoryListContext {
})
}
}
public func _internal_pollPeerStories(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Api.InputUser? in
return transaction.getPeer(peerId).flatMap(apiInputUser)
}
|> mapToSignal { inputUser -> Signal<Never, NoError> in
guard let inputUser = inputUser else {
return .complete()
}
return network.request(Api.functions.stories.getUserStories(userId: inputUser))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.stories.UserStories?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<Never, NoError> in
return postbox.transaction { transaction -> Void in
var updatedPeerEntries: [StoryItemsTableEntry] = []
updatedPeerEntries.removeAll()
if let result = result, case let .userStories(stories, users) = result {
var peers: [Peer] = []
var peerPresences: [PeerId: Api.User] = [:]
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
peerPresences[telegramUser.id] = user
}
switch stories {
case let .userStories(_, userId, maxReadId, stories):
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
let previousPeerEntries: [StoryItemsTableEntry] = transaction.getStoryItems(peerId: peerId)
for story in stories {
if let storedItem = Stories.StoredItem(apiStoryItem: story, peerId: peerId, transaction: transaction) {
if case .placeholder = storedItem, let previousEntry = previousPeerEntries.first(where: { $0.id == storedItem.id }) {
updatedPeerEntries.append(previousEntry)
} else {
if let codedEntry = CodableEntry(storedItem) {
updatedPeerEntries.append(StoryItemsTableEntry(value: codedEntry, id: storedItem.id))
}
}
}
}
transaction.setPeerStoryState(peerId: peerId, state: CodableEntry(Stories.PeerState(
maxReadId: maxReadId ?? 0
)))
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated
})
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
}
transaction.setStoryItems(peerId: peerId, items: updatedPeerEntries)
}
|> ignoreValues
}
}
}

View File

@ -670,7 +670,7 @@ private struct NotificationExceptionPeerState : Equatable {
self.mode = .alwaysOn
}
self.displayPreviews = notifications.displayPreviews == .hide ? .alwaysOff : .alwaysOn
self.storyNotifications = notifications.storiesMuted == false ? .alwaysOff : .alwaysOn
self.storyNotifications = notifications.storiesMuted == true ? .alwaysOff : .alwaysOn
} else {
self.selectedSound = .default
self.mode = .alwaysOn

View File

@ -888,7 +888,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
let sharedContext = SharedAccountContextImpl(mainWindow: self.mainWindow, sharedContainerPath: legacyBasePath, basePath: rootPath, encryptionParameters: encryptionParameters, accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings, networkArguments: networkArguments, hasInAppPurchases: buildConfig.isAppStoreBuild && buildConfig.apiId == 1, rootPath: rootPath, legacyBasePath: legacyBasePath, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), firebaseSecretStream: self.firebaseSecretStream.get(), setNotificationCall: { call in
setPresentationCall?(call)
}, navigateToChat: { accountId, peerId, messageId in
self.openChatWhenReady(accountId: accountId, peerId: peerId, threadId: nil, messageId: messageId)
self.openChatWhenReady(accountId: accountId, peerId: peerId, threadId: nil, messageId: messageId, storyId: nil)
}, displayUpgradeProgress: { progress in
if let progress = progress {
if self.dataImportSplash == nil {
@ -2221,7 +2221,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
if let value = Int64(string) {
self.openChatWhenReady(accountId: nil, peerId: PeerId(value), threadId: nil, activateInput: true)
self.openChatWhenReady(accountId: nil, peerId: PeerId(value), threadId: nil, activateInput: true, storyId: nil)
}
}
}
@ -2262,7 +2262,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
if let primary = primary {
for context in contexts {
if let context = context, context.account.id == primary {
self.openChatWhenReady(accountId: nil, peerId: peerId, threadId: nil)
self.openChatWhenReady(accountId: nil, peerId: peerId, threadId: nil, storyId: nil)
return
}
}
@ -2270,7 +2270,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
for context in contexts {
if let context = context {
self.openChatWhenReady(accountId: context.account.id, peerId: peerId, threadId: nil)
self.openChatWhenReady(accountId: context.account.id, peerId: peerId, threadId: nil, storyId: nil)
return
}
}
@ -2303,7 +2303,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
case .camera:
context.openRootCamera()
case .savedMessages:
self.openChatWhenReady(accountId: nil, peerId: context.context.account.peerId, threadId: nil)
self.openChatWhenReady(accountId: nil, peerId: context.context.account.peerId, threadId: nil, storyId: nil)
case .account:
context.switchAccount()
}
@ -2354,7 +2354,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
}))
}
private func openChatWhenReady(accountId: AccountRecordId?, peerId: PeerId, threadId: Int64?, messageId: MessageId? = nil, activateInput: Bool = false) {
private func openChatWhenReady(accountId: AccountRecordId?, peerId: PeerId, threadId: Int64?, messageId: MessageId? = nil, activateInput: Bool = false, storyId: StoryId?) {
let signal = self.sharedContextPromise.get()
|> take(1)
|> deliverOnMainQueue
@ -2373,7 +2373,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
}
self.openChatWhenReadyDisposable.set((signal
|> deliverOnMainQueue).start(next: { context in
context.openChatWithPeerId(peerId: peerId, threadId: threadId, messageId: messageId, activateInput: activateInput)
context.openChatWithPeerId(peerId: peerId, threadId: threadId, messageId: messageId, activateInput: activateInput, storyId: storyId)
}))
}
@ -2402,7 +2402,8 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
if response.notification.request.content.categoryIdentifier == "c" || response.notification.request.content.categoryIdentifier == "t" {
messageId = messageIdFromNotification(peerId: peerId, notification: response.notification)
}
self.openChatWhenReady(accountId: accountId, peerId: peerId, threadId: threadId, messageId: messageId)
let storyId = storyIdFromNotification(peerId: peerId, notification: response.notification)
self.openChatWhenReady(accountId: accountId, peerId: peerId, threadId: threadId, messageId: messageId, storyId: storyId)
}
completionHandler()
} else if response.actionIdentifier == "reply", let (peerId, threadId) = peerIdFromNotification(response.notification), let accountId = accountId {
@ -2793,7 +2794,6 @@ private func peerIdFromNotification(_ notification: UNNotification) -> (peerId:
}
}
@available(iOS 10.0, *)
private func messageIdFromNotification(peerId: PeerId, notification: UNNotification) -> MessageId? {
let payload = notification.request.content.userInfo
if let messageIdNamespace = payload["messageId.namespace"] as? Int32, let messageIdId = payload["messageId.id"] as? Int32 {
@ -2807,6 +2807,15 @@ private func messageIdFromNotification(peerId: PeerId, notification: UNNotificat
return nil
}
private func storyIdFromNotification(peerId: PeerId, notification: UNNotification) -> StoryId? {
let payload = notification.request.content.userInfo
if let storyId = payload["story_id"] {
let storyIdValue = storyId as! NSString
return StoryId(peerId: peerId, id: Int32(storyIdValue.intValue))
}
return nil
}
private enum DownloadFileError {
case network
}

View File

@ -851,47 +851,51 @@ final class AuthorizedApplicationContext {
}))
}
func openChatWithPeerId(peerId: PeerId, threadId: Int64?, messageId: MessageId? = nil, activateInput: Bool = false) {
var visiblePeerId: PeerId?
if let controller = self.rootController.topViewController as? ChatControllerImpl, controller.chatLocation.peerId == peerId, controller.chatLocation.threadId == threadId {
visiblePeerId = peerId
}
if visiblePeerId != peerId || messageId != nil {
let isOutgoingMessage: Signal<Bool, NoError>
if let messageId {
let accountPeerId = self.context.account.peerId
isOutgoingMessage = self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> map { message -> Bool in
if let message {
return !message._asMessage().effectivelyIncoming(accountPeerId)
} else {
return false
}
}
} else {
isOutgoingMessage = .single(false)
func openChatWithPeerId(peerId: PeerId, threadId: Int64?, messageId: MessageId? = nil, activateInput: Bool = false, storyId: StoryId?) {
if let _ = storyId {
self.rootController.chatListController?.openStories(peerId: peerId)
} else {
var visiblePeerId: PeerId?
if let controller = self.rootController.topViewController as? ChatControllerImpl, controller.chatLocation.peerId == peerId, controller.chatLocation.threadId == threadId {
visiblePeerId = peerId
}
let _ = combineLatest(
queue: Queue.mainQueue(),
self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)),
isOutgoingMessage
).start(next: { peer, isOutgoingMessage in
guard let peer = peer else {
return
}
let chatLocation: NavigateToChatControllerParams.Location
if let threadId = threadId {
chatLocation = .replyThread(ChatReplyThreadMessage(
messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
))
if visiblePeerId != peerId || messageId != nil {
let isOutgoingMessage: Signal<Bool, NoError>
if let messageId {
let accountPeerId = self.context.account.peerId
isOutgoingMessage = self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> map { message -> Bool in
if let message {
return !message._asMessage().effectivelyIncoming(accountPeerId)
} else {
return false
}
}
} else {
chatLocation = .peer(peer)
isOutgoingMessage = .single(false)
}
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: chatLocation, subject: isOutgoingMessage ? messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) } : nil, activateInput: activateInput ? .text : nil))
})
let _ = combineLatest(
queue: Queue.mainQueue(),
self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)),
isOutgoingMessage
).start(next: { peer, isOutgoingMessage in
guard let peer = peer else {
return
}
let chatLocation: NavigateToChatControllerParams.Location
if let threadId = threadId {
chatLocation = .replyThread(ChatReplyThreadMessage(
messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
))
} else {
chatLocation = .peer(peer)
}
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: chatLocation, subject: isOutgoingMessage ? messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) } : nil, activateInput: activateInput ? .text : nil))
})
}
}
}