Refactoring

This commit is contained in:
Ali 2022-05-26 23:11:44 +04:00
parent 1a0bba8e45
commit af1b794332
32 changed files with 839 additions and 501 deletions

View File

@ -388,7 +388,7 @@
"Tour.Text5" = "**Telegram** lets you access your\nmessages from multiple devices."; "Tour.Text5" = "**Telegram** lets you access your\nmessages from multiple devices.";
"Tour.Title6" = "Free"; "Tour.Title6" = "Free";
"Tour.Text6" = "**Telegram** is free forever. No ads.\nNo subscription fees."; "Tour.Text6" = "**Telegram** isprovides free unlimited cloud storage\nfor chats and media.";
"Tour.StartButton" = "Start Messaging"; "Tour.StartButton" = "Start Messaging";

View File

@ -148,8 +148,6 @@ public enum FetchManagerPriority: Comparable {
} }
} }
public let FetchCompleteRange = IndexSet(integersIn: 0 ..< Int(Int32.max) as Range<Int>)
public protocol FetchManager { public protocol FetchManager {
var queue: Queue { get } var queue: Queue { get }

View File

@ -56,7 +56,7 @@ public func messageMediaImageInteractiveFetched(fetchManager: FetchManager, mess
if let range = range { if let range = range {
ranges = IndexSet(integersIn: Int(range.lowerBound) ..< Int(range.upperBound)) ranges = IndexSet(integersIn: Int(range.lowerBound) ..< Int(range.upperBound))
} else { } else {
ranges = FetchCompleteRange ranges = IndexSet(integersIn: Int(0) ..< Int(Int64.max))
} }
return fetchManager.interactivelyFetched(category: .image, location: .chat(messageId.peerId), locationKey: .messageId(messageId), mediaReference: mediaReference, resourceReference: mediaReference.resourceReference(resource), ranges: ranges, statsCategory: .image, elevatedPriority: false, userInitiated: userInitiated, priority: priority, storeToDownloadsPeerType: storeToDownloadsPeerType) return fetchManager.interactivelyFetched(category: .image, location: .chat(messageId.peerId), locationKey: .messageId(messageId), mediaReference: mediaReference, resourceReference: mediaReference.resourceReference(resource), ranges: ranges, statsCategory: .image, elevatedPriority: false, userInitiated: userInitiated, priority: priority, storeToDownloadsPeerType: storeToDownloadsPeerType)
} }

View File

@ -186,6 +186,9 @@ private final class FetchManagerCategoryContext {
if self.topEntryIdAndPriority?.0 == id { if self.topEntryIdAndPriority?.0 == id {
self.topEntryIdAndPriority = nil self.topEntryIdAndPriority = nil
} }
if let entry = self.entries[id] {
Logger.shared.log("FetchManager", "Canceled fetching \(entry.resourceReference.resource.id.stringRepresentation)")
}
self.entries.removeValue(forKey: id) self.entries.removeValue(forKey: id)
removedEntries = true removedEntries = true
} }
@ -232,6 +235,7 @@ private final class FetchManagerCategoryContext {
} }
activeContext.disposable?.dispose() activeContext.disposable?.dispose()
let postbox = self.postbox let postbox = self.postbox
Logger.shared.log("FetchManager", "Begin fetching \(entry.resourceReference.resource.id.stringRepresentation) ranges: \(String(describing: parsedRanges))")
activeContext.disposable = (fetchedMediaResource(mediaBox: postbox.mediaBox, reference: entry.resourceReference, ranges: parsedRanges, statsCategory: entry.statsCategory, reportResultStatus: true, continueInBackground: entry.userInitiated) activeContext.disposable = (fetchedMediaResource(mediaBox: postbox.mediaBox, reference: entry.resourceReference, ranges: parsedRanges, statsCategory: entry.statsCategory, reportResultStatus: true, continueInBackground: entry.userInitiated)
|> mapToSignal { type -> Signal<FetchResourceSourceType, FetchResourceError> in |> mapToSignal { type -> Signal<FetchResourceSourceType, FetchResourceError> in
if filterDownloadStatsEntry(entry: entry), case let .message(message, _) = entry.mediaReference, let messageId = message.id, case .remote = type { if filterDownloadStatsEntry(entry: entry), case let .message(message, _) = entry.mediaReference, let messageId = message.id, case .remote = type {
@ -248,6 +252,7 @@ private final class FetchManagerCategoryContext {
return .single(type) return .single(type)
} }
|> deliverOnMainQueue).start(next: { _ in |> deliverOnMainQueue).start(next: { _ in
Logger.shared.log("FetchManager", "Completed fetching \(entry.resourceReference.resource.id.stringRepresentation)")
entryCompleted(id) entryCompleted(id)
}) })
} else { } else {
@ -356,6 +361,7 @@ private final class FetchManagerCategoryContext {
} else if ranges.isEmpty { } else if ranges.isEmpty {
} else { } else {
let postbox = self.postbox let postbox = self.postbox
Logger.shared.log("FetchManager", "Begin fetching \(entry.resourceReference.resource.id.stringRepresentation) ranges: \(String(describing: parsedRanges))")
activeContext.disposable = (fetchedMediaResource(mediaBox: postbox.mediaBox, reference: entry.resourceReference, ranges: parsedRanges, statsCategory: entry.statsCategory, reportResultStatus: true, continueInBackground: entry.userInitiated) activeContext.disposable = (fetchedMediaResource(mediaBox: postbox.mediaBox, reference: entry.resourceReference, ranges: parsedRanges, statsCategory: entry.statsCategory, reportResultStatus: true, continueInBackground: entry.userInitiated)
|> mapToSignal { type -> Signal<FetchResourceSourceType, FetchResourceError> in |> mapToSignal { type -> Signal<FetchResourceSourceType, FetchResourceError> in
if filterDownloadStatsEntry(entry: entry), case let .message(message, _) = entry.mediaReference, let messageId = message.id, case .remote = type { if filterDownloadStatsEntry(entry: entry), case let .message(message, _) = entry.mediaReference, let messageId = message.id, case .remote = type {
@ -372,6 +378,7 @@ private final class FetchManagerCategoryContext {
return .single(type) return .single(type)
} }
|> deliverOnMainQueue).start(next: { _ in |> deliverOnMainQueue).start(next: { _ in
Logger.shared.log("FetchManager", "Completed fetching \(entry.resourceReference.resource.id.stringRepresentation)")
entryCompleted(topEntryId) entryCompleted(topEntryId)
}) })
} }
@ -411,7 +418,8 @@ private final class FetchManagerCategoryContext {
var entriesRemoved = false var entriesRemoved = false
let _ = entriesRemoved let _ = entriesRemoved
if let _ = self.entries[id] { if let entry = self.entries[id] {
Logger.shared.log("FetchManager", "Cancel fetching \(entry.resourceReference.resource.id.stringRepresentation)")
self.entries.removeValue(forKey: id) self.entries.removeValue(forKey: id)
entriesRemoved = true entriesRemoved = true

View File

@ -1016,9 +1016,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
@objc func deleteButtonPressed() { @objc func deleteButtonPressed() {
if let currentMessage = self.currentMessage { if let currentMessage = self.currentMessage {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.MessageGroup(id: currentMessage.id))
return transaction.getMessageGroup(currentMessage.id) ?? [] |> deliverOnMainQueue).start(next: { [weak self] messages in
} |> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self, !messages.isEmpty { if let strongSelf = self, !messages.isEmpty {
if messages.count == 1 { if messages.count == 1 {
strongSelf.commitDeleteMessages(messages, ask: true) strongSelf.commitDeleteMessages(messages, ask: true)
@ -1032,7 +1031,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
var generalMessageContentKind: MessageContentKind? var generalMessageContentKind: MessageContentKind?
for message in messages { for message in messages {
let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId) let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: message, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId)
if generalMessageContentKind == nil || generalMessageContentKind == currentKind { if generalMessageContentKind == nil || generalMessageContentKind == currentKind {
generalMessageContentKind = currentKind generalMessageContentKind = currentKind
} else { } else {
@ -1057,7 +1056,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
} }
let deleteAction: ([Message]) -> Void = { messages in let deleteAction: ([EngineMessage]) -> Void = { messages in
if let strongSelf = self { if let strongSelf = self {
strongSelf.commitDeleteMessages(messages, ask: false) strongSelf.commitDeleteMessages(messages, ask: false)
} }
@ -1070,7 +1069,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
let items: [ActionSheetItem] = [ let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
deleteAction([currentMessage]) deleteAction([EngineMessage(currentMessage)])
}), }),
ActionSheetButtonItem(title: multipleText, color: .destructive, action: { [weak actionSheet] in ActionSheetButtonItem(title: multipleText, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
@ -1093,7 +1092,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
} }
private func commitDeleteMessages(_ messages: [Message], ask: Bool) { private func commitDeleteMessages(_ messages: [EngineMessage], ask: Bool) {
self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in
if let strongSelf = self, let controllerInteration = strongSelf.controllerInteraction, !actions.options.isEmpty { if let strongSelf = self, let controllerInteration = strongSelf.controllerInteraction, !actions.options.isEmpty {
var presentationData = strongSelf.presentationData var presentationData = strongSelf.presentationData
@ -1166,9 +1165,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
self.interacting?(true) self.interacting?(true)
if let currentMessage = self.currentMessage { if let currentMessage = self.currentMessage {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.MessageGroup(id: currentMessage.id))
return transaction.getMessageGroup(currentMessage.id) ?? [] |> deliverOnMainQueue).start(next: { [weak self] messages in
} |> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self, !messages.isEmpty { if let strongSelf = self, !messages.isEmpty {
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
var forceTheme: PresentationTheme? var forceTheme: PresentationTheme?
@ -1181,7 +1179,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
var messageContentKinds = Set<MessageContentKindKey>() var messageContentKinds = Set<MessageContentKindKey>()
for message in messages { for message in messages {
let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId) let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: message, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId)
if beganContentKindScanning && currentKind != generalMessageContentKind { if beganContentKindScanning && currentKind != generalMessageContentKind {
generalMessageContentKind = nil generalMessageContentKind = nil
} else if !beganContentKindScanning || currentKind == generalMessageContentKind { } else if !beganContentKindScanning || currentKind == generalMessageContentKind {
@ -1210,10 +1208,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
if messages.count == 1 { if messages.count == 1 {
var subject: ShareControllerSubject = ShareControllerSubject.messages(messages) var subject: ShareControllerSubject = ShareControllerSubject.messages(messages.map { $0._asMessage() })
for m in messages[0].media { for m in messages[0].media {
if let image = m as? TelegramMediaImage { if let image = m as? TelegramMediaImage {
subject = .image(image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(messages[0]), media: m), resource: $0.resource)) })) subject = .image(image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(messages[0]._asMessage()), media: m), resource: $0.resource)) }))
} else if let webpage = m as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content { } else if let webpage = m as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
if content.embedType == "iframe" { if content.embedType == "iframe" {
let item = OpenInItem.url(url: content.url) let item = OpenInItem.url(url: content.url)
@ -1246,12 +1244,12 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
} }
} else if let file = m as? TelegramMediaFile { } else if let file = m as? TelegramMediaFile {
subject = .media(.message(message: MessageReference(messages[0]), media: file)) subject = .media(.message(message: MessageReference(messages[0]._asMessage()), media: file))
if file.isAnimated { if file.isAnimated {
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Preview_SaveGif, action: { [weak self] in preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Preview_SaveGif, action: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
let message = messages[0] let message = messages[0]
let _ = addSavedGif(postbox: strongSelf.context.account.postbox, fileReference: .message(message: MessageReference(message), media: file)).start() let _ = addSavedGif(postbox: strongSelf.context.account.postbox, fileReference: .message(message: MessageReference(message._asMessage()), media: file)).start()
strongSelf.controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil) strongSelf.controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil)
} }
@ -1397,7 +1395,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}), }),
ActionSheetButtonItem(title: multipleText, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: multipleText, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
shareAction(messages) shareAction(messages.map { $0._asMessage() })
}) })
] ]

View File

@ -1664,7 +1664,7 @@ public func internalMediaGridMessageVideo(postbox: Postbox, videoReference: File
} }
} }
public func chatMessagePhotoStatus(context: AccountContext, messageId: MessageId, photoReference: ImageMediaReference, displayAtSize: Int = 1000) -> Signal<MediaResourceStatus, NoError> { public func chatMessagePhotoStatus(context: AccountContext, messageId: MessageId, photoReference: ImageMediaReference, displayAtSize: Int? = nil) -> Signal<MediaResourceStatus, NoError> {
if let largestRepresentation = largestRepresentationForPhoto(photoReference.media) { if let largestRepresentation = largestRepresentationForPhoto(photoReference.media) {
if let range = representationFetchRangeForDisplayAtSize(representation: largestRepresentation, dimension: displayAtSize) { if let range = representationFetchRangeForDisplayAtSize(representation: largestRepresentation, dimension: displayAtSize) {
return combineLatest( return combineLatest(

View File

@ -0,0 +1,43 @@
import Foundation
final class MutableIsContactView: MutablePostboxView {
fileprivate let id: PeerId
fileprivate var isContact: Bool
init(postbox: PostboxImpl, id: PeerId) {
self.id = id
self.isContact = postbox.contactsTable.isContact(peerId: self.id)
}
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
var updated = false
if transaction.replaceContactPeerIds != nil {
let isContact = postbox.contactsTable.isContact(peerId: self.id)
if self.isContact != isContact {
self.isContact = isContact
updated = true
}
}
if updated {
return true
} else {
return false
}
}
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
return false
}
func immutableView() -> PostboxView {
return IsContactView(self)
}
}
public final class IsContactView: PostboxView {
public let isContact: Bool
init(_ view: MutableIsContactView) {
self.isContact = view.isContact
}
}

View File

@ -0,0 +1,65 @@
import Foundation
final class MutableMessageGroupView: MutablePostboxView {
fileprivate let id: MessageId
fileprivate let groupingKey: Int64?
fileprivate var messages: [Message] = []
init(postbox: PostboxImpl, id: MessageId) {
self.id = id
self.messages = postbox.getMessageGroup(at: id) ?? []
self.groupingKey = self.messages.first?.groupingKey
}
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
var updated = false
if let operations = transaction.currentOperationsByPeerId[self.id.peerId] {
outer: for operation in operations {
switch operation {
case let .InsertMessage(message):
if let groupingKey = self.groupingKey, message.groupingKey == groupingKey {
updated = true
break outer
} else if message.id == self.id {
updated = true
break outer
}
case let .Remove(indices):
for index in indices {
for message in self.messages {
if index.0.id == message.id {
updated = true
break outer
}
}
}
default:
break
}
}
}
if updated {
self.messages = postbox.getMessageGroup(at: self.id) ?? []
return true
} else {
return false
}
}
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
return false
}
func immutableView() -> PostboxView {
return MessageGroupView(self)
}
}
public final class MessageGroupView: PostboxView {
public let messages: [Message]
init(_ view: MutableMessageGroupView) {
self.messages = view.messages
}
}

View File

@ -34,6 +34,8 @@ public enum PostboxViewKey: Hashable {
case contacts(accountPeerId: PeerId?, includePresences: Bool) case contacts(accountPeerId: PeerId?, includePresences: Bool)
case deletedMessages(peerId: PeerId) case deletedMessages(peerId: PeerId)
case notice(key: NoticeEntryKey) case notice(key: NoticeEntryKey)
case messageGroup(id: MessageId)
case isContact(id: PeerId)
public func hash(into hasher: inout Hasher) { public func hash(into hasher: inout Hasher) {
switch self { switch self {
@ -112,6 +114,10 @@ public enum PostboxViewKey: Hashable {
hasher.combine(peerId) hasher.combine(peerId)
case let .notice(key): case let .notice(key):
hasher.combine(key) hasher.combine(key)
case let .messageGroup(id):
hasher.combine(id)
case let .isContact(id):
hasher.combine(id)
} }
} }
@ -315,6 +321,18 @@ public enum PostboxViewKey: Hashable {
} else { } else {
return false return false
} }
case let .messageGroup(id):
if case .messageGroup(id) = rhs {
return true
} else {
return false
}
case let .isContact(id):
if case .isContact(id) = rhs {
return true
} else {
return false
}
} }
} }
} }
@ -387,5 +405,9 @@ func postboxViewForKey(postbox: PostboxImpl, key: PostboxViewKey) -> MutablePost
return MutableDeletedMessagesView(peerId: peerId) return MutableDeletedMessagesView(peerId: peerId)
case let .notice(key): case let .notice(key):
return MutableLocalNoticeEntryView(postbox: postbox, key: key) return MutableLocalNoticeEntryView(postbox: postbox, key: key)
case let .messageGroup(id):
return MutableMessageGroupView(postbox: postbox, id: id)
case let .isContact(id):
return MutableIsContactView(postbox: postbox, id: id)
} }
} }

View File

@ -505,7 +505,11 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
controller?.clearItemNodesHighlight(animated: true) controller?.clearItemNodesHighlight(animated: true)
} }
openMessageStatsImpl = { [weak controller] messageId in openMessageStatsImpl = { [weak controller] messageId in
controller?.push(messageStatsController(context: context, messageId: messageId, cachedPeerData: cachedPeerData)) var statsDatacenterId: Int32?
if let cachedData = cachedPeerData as? CachedChannelData {
statsDatacenterId = cachedData.statsDatacenterId
}
controller?.push(messageStatsController(context: context, messageId: messageId, statsDatacenterId: statsDatacenterId))
} }
contextActionImpl = { [weak controller] messageId, sourceNode, gesture in contextActionImpl = { [weak controller] messageId, sourceNode, gesture in
guard let controller = controller, let sourceNode = sourceNode as? ContextExtractedContentContainingNode else { guard let controller = controller, let sourceNode = sourceNode as? ContextExtractedContentContainingNode else {

View File

@ -185,17 +185,14 @@ private func messageStatsControllerEntries(data: MessageStats?, messages: Search
return entries return entries
} }
public func messageStatsController(context: AccountContext, messageId: MessageId, cachedPeerData: CachedPeerData) -> ViewController { public func messageStatsController(context: AccountContext, messageId: MessageId, statsDatacenterId: Int32?) -> ViewController {
var navigateToMessageImpl: ((MessageId) -> Void)? var navigateToMessageImpl: ((MessageId) -> Void)?
let actionsDisposable = DisposableSet() let actionsDisposable = DisposableSet()
let dataPromise = Promise<MessageStats?>(nil) let dataPromise = Promise<MessageStats?>(nil)
let messagesPromise = Promise<(SearchMessagesResult, SearchMessagesState)?>(nil) let messagesPromise = Promise<(SearchMessagesResult, SearchMessagesState)?>(nil)
var datacenterId: Int32 = 0 let datacenterId: Int32 = statsDatacenterId ?? 0
if let cachedData = cachedPeerData as? CachedChannelData {
datacenterId = cachedData.statsDatacenterId
}
let statsContext = MessageStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, messageId: messageId) let statsContext = MessageStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, messageId: messageId)
let dataSignal: Signal<MessageStats?, NoError> = statsContext.state let dataSignal: Signal<MessageStats?, NoError> = statsContext.state

View File

@ -48,9 +48,8 @@ private func presentLiveLocationController(context: AccountContext, peerId: Peer
} }
} }
if let id = context.liveLocationManager?.internalMessageForPeerId(peerId) { if let id = context.liveLocationManager?.internalMessageForPeerId(peerId) {
let _ = (context.account.postbox.transaction { transaction -> EngineMessage? in let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: id))
return transaction.getMessage(id).flatMap(EngineMessage.init) |> deliverOnMainQueue).start(next: presentImpl)
} |> deliverOnMainQueue).start(next: presentImpl)
} else if let liveLocationManager = context.liveLocationManager { } else if let liveLocationManager = context.liveLocationManager {
let _ = (liveLocationManager.summaryManager.peersBroadcastingTo(peerId: peerId) let _ = (liveLocationManager.summaryManager.peersBroadcastingTo(peerId: peerId)
|> take(1) |> take(1)

View File

@ -325,18 +325,7 @@ private enum MultipartFetchSource {
return .fail(.revalidateMediaReference) return .fail(.revalidateMediaReference)
case .revalidate: case .revalidate:
return .fail(.revalidateMediaReference) return .fail(.revalidateMediaReference)
case let .location(parsedLocation): case let .location(parsedLocation):
#if DEBUG
switch parsedLocation {
case let .inputDocumentFileLocation(id, _, _, _):
if id == 5467475273110788326 {
return Signal<Data, MultipartFetchDownloadError>.single(Data(count: Int(limit))) |> delay(0.01, queue: .concurrentDefaultQueue())
}
default:
break
}
#endif
return download.request(Api.functions.upload.getFile(flags: 0, location: parsedLocation, offset: offset, limit: Int32(limit)), tag: tag, continueInBackground: continueInBackground) return download.request(Api.functions.upload.getFile(flags: 0, location: parsedLocation, offset: offset, limit: Int32(limit)), tag: tag, continueInBackground: continueInBackground)
|> mapError { error -> MultipartFetchDownloadError in |> mapError { error -> MultipartFetchDownloadError in
if error.errorDescription.hasPrefix("FILEREF_INVALID") || error.errorDescription.hasPrefix("FILE_REFERENCE_") { if error.errorDescription.hasPrefix("FILEREF_INVALID") || error.errorDescription.hasPrefix("FILE_REFERENCE_") {

View File

@ -81,6 +81,27 @@ public extension TelegramEngine.EngineData.Item {
return EngineMessage(message) return EngineMessage(message)
} }
} }
public struct MessageGroup: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = [EngineMessage]
fileprivate var id: EngineMessage.Id
public init(id: EngineMessage.Id) {
self.id = id
}
var key: PostboxViewKey {
return .messageGroup(id: self.id)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? MessageGroupView else {
preconditionFailure()
}
return view.messages.map(EngineMessage.init)
}
}
public struct Messages: TelegramEngineDataItem, PostboxViewDataItem { public struct Messages: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = [EngineMessage.Id: EngineMessage] public typealias Result = [EngineMessage.Id: EngineMessage]

View File

@ -4,6 +4,29 @@ import Postbox
public typealias EngineExportedPeerInvitation = ExportedInvitation public typealias EngineExportedPeerInvitation = ExportedInvitation
public extension TelegramEngine.EngineData.Item { public extension TelegramEngine.EngineData.Item {
enum NotificationSettings {
public struct Global: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = EngineGlobalNotificationSettings
public init() {
}
var key: PostboxViewKey {
return .preferences(keys: Set([PreferencesKeys.globalNotifications]))
}
func extract(view: PostboxView) -> Result {
guard let view = view as? PreferencesView else {
preconditionFailure()
}
guard let notificationSettings = view.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) else {
return EngineGlobalNotificationSettings(GlobalNotificationSettings.defaultSettings.effective)
}
return EngineGlobalNotificationSettings(notificationSettings.effective)
}
}
}
enum Peer { enum Peer {
public struct Peer: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { public struct Peer: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = Optional<EnginePeer> public typealias Result = Optional<EnginePeer>
@ -101,7 +124,7 @@ public extension TelegramEngine.EngineData.Item {
} }
public struct NotificationSettings: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { public struct NotificationSettings: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = Optional<EnginePeer.NotificationSettings> public typealias Result = EnginePeer.NotificationSettings
fileprivate var id: EnginePeer.Id fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id { public var mapKey: EnginePeer.Id {
@ -121,7 +144,7 @@ public extension TelegramEngine.EngineData.Item {
preconditionFailure() preconditionFailure()
} }
guard let notificationSettings = view.notificationSettings as? TelegramPeerNotificationSettings else { guard let notificationSettings = view.notificationSettings as? TelegramPeerNotificationSettings else {
return nil return EnginePeer.NotificationSettings(TelegramPeerNotificationSettings.defaultSettings)
} }
return EnginePeer.NotificationSettings(notificationSettings) return EnginePeer.NotificationSettings(notificationSettings)
} }
@ -228,5 +251,96 @@ public extension TelegramEngine.EngineData.Item {
} }
} }
} }
public struct StatsDatacenterId: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = Optional<Int32>
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
return self.id
}
public init(id: EnginePeer.Id) {
self.id = id
}
var key: PostboxViewKey {
return .cachedPeerData(peerId: self.id)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? CachedPeerDataView else {
preconditionFailure()
}
guard let cachedPeerData = view.cachedPeerData else {
return nil
}
switch cachedPeerData {
case let channel as CachedChannelData:
return channel.statsDatacenterId
default:
return nil
}
}
}
public struct ThemeEmoticon: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = Optional<String>
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
return self.id
}
public init(id: EnginePeer.Id) {
self.id = id
}
var key: PostboxViewKey {
return .cachedPeerData(peerId: self.id)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? CachedPeerDataView else {
preconditionFailure()
}
guard let cachedPeerData = view.cachedPeerData else {
return nil
}
if let cachedData = cachedPeerData as? CachedUserData {
return cachedData.themeEmoticon
} else if let cachedData = cachedPeerData as? CachedGroupData {
return cachedData.themeEmoticon
} else if let cachedData = cachedPeerData as? CachedChannelData {
return cachedData.themeEmoticon
} else {
return nil
}
}
}
public struct IsContact: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = Bool
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
return self.id
}
public init(id: EnginePeer.Id) {
self.id = id
}
var key: PostboxViewKey {
return .isContact(id: self.id)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? IsContactView else {
preconditionFailure()
}
return view.isContact
}
}
} }
} }

View File

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

View File

@ -366,5 +366,17 @@ public extension TelegramEngine {
} }
}).start() }).start()
} }
public func findRandomMessage(peerId: EnginePeer.Id, namespace: EngineMessage.Id.Namespace, tag: EngineMessage.Tags, ignoreIds: ([EngineMessage.Id], Set<EngineMessage.Id>)) -> Signal<EngineMessage.Index?, NoError> {
return self.account.postbox.transaction { transaction -> EngineMessage.Index? in
return transaction.findRandomMessage(peerId: peerId, namespace: namespace, tag: tag, ignoreIds: ignoreIds)
}
}
public func failedMessageGroup(id: EngineMessage.Id) -> Signal<[EngineMessage], NoError> {
return self.account.postbox.transaction { transaction -> [EngineMessage] in
return transaction.getMessageFailedGroup(id)?.map(EngineMessage.init) ?? []
}
}
} }
} }

View File

@ -167,6 +167,37 @@ public enum EnginePeer: Equatable {
} }
} }
public struct EngineGlobalNotificationSettings: Equatable {
public struct CategorySettings: Equatable {
public var enabled: Bool
public var displayPreviews: Bool
public var sound: EnginePeer.NotificationSettings.MessageSound
public init(enabled: Bool, displayPreviews: Bool, sound: EnginePeer.NotificationSettings.MessageSound) {
self.enabled = enabled
self.displayPreviews = displayPreviews
self.sound = sound
}
}
public var privateChats: CategorySettings
public var groupChats: CategorySettings
public var channels: CategorySettings
public var contactsJoined: Bool
public init(
privateChats: CategorySettings,
groupChats: CategorySettings,
channels: CategorySettings,
contactsJoined: Bool
) {
self.privateChats = privateChats
self.groupChats = groupChats
self.channels = channels
self.contactsJoined = contactsJoined
}
}
public extension EnginePeer.NotificationSettings.MuteState { public extension EnginePeer.NotificationSettings.MuteState {
init(_ muteState: PeerMuteState) { init(_ muteState: PeerMuteState) {
switch muteState { switch muteState {
@ -495,3 +526,32 @@ public extension EngineRenderedPeer {
self.init(RenderedPeer(message: message._asMessage())) self.init(RenderedPeer(message: message._asMessage()))
} }
} }
public extension EngineGlobalNotificationSettings.CategorySettings {
init(_ categorySettings: MessageNotificationSettings) {
self.init(
enabled: categorySettings.enabled,
displayPreviews: categorySettings.displayPreviews,
sound: EnginePeer.NotificationSettings.MessageSound(categorySettings.sound)
)
}
func _asMessageNotificationSettings() -> MessageNotificationSettings {
return MessageNotificationSettings(
enabled: self.enabled,
displayPreviews: self.displayPreviews,
sound: self.sound._asMessageSound()
)
}
}
public extension EngineGlobalNotificationSettings {
init(_ globalNotificationSettings: GlobalNotificationSettingsSet) {
self.init(
privateChats: CategorySettings(globalNotificationSettings.privateChats),
groupChats: CategorySettings(globalNotificationSettings.groupChats),
channels: CategorySettings(globalNotificationSettings.channels),
contactsJoined: globalNotificationSettings.contactsJoined
)
}
}

View File

@ -74,8 +74,11 @@ public extension TelegramEngine {
} }
} }
public func findChannelById(channelId: Int64) -> Signal<Peer?, NoError> { public func findChannelById(channelId: Int64) -> Signal<EnginePeer?, NoError> {
return _internal_findChannelById(postbox: self.account.postbox, network: self.account.network, channelId: channelId) return _internal_findChannelById(postbox: self.account.postbox, network: self.account.network, channelId: channelId)
|> map { peer in
return peer.flatMap(EnginePeer.init)
}
} }
public func supportPeerId() -> Signal<PeerId?, NoError> { public func supportPeerId() -> Signal<PeerId?, NoError> {
@ -724,6 +727,31 @@ public extension TelegramEngine {
public func ensurePeerIsLocallyAvailable(peer: EnginePeer) -> Signal<EnginePeer.Id, NoError> { public func ensurePeerIsLocallyAvailable(peer: EnginePeer) -> Signal<EnginePeer.Id, NoError> {
return _internal_storedMessageFromSearchPeer(account: self.account, peer: peer._asPeer()) return _internal_storedMessageFromSearchPeer(account: self.account, peer: peer._asPeer())
} }
public func mostRecentSecretChat(id: EnginePeer.Id) -> Signal<EnginePeer.Id?, NoError> {
return self.account.postbox.transaction { transaction -> EnginePeer.Id? in
let filteredPeerIds = Array(transaction.getAssociatedPeerIds(id)).filter { $0.namespace == Namespaces.Peer.SecretChat }
var activeIndices: [ChatListIndex] = []
for associatedId in filteredPeerIds {
if let state = (transaction.getPeer(associatedId) as? TelegramSecretChat)?.embeddedState {
switch state {
case .active, .handshake:
if let (_, index) = transaction.getPeerChatListIndex(associatedId) {
activeIndices.append(index)
}
default:
break
}
}
}
activeIndices.sort()
if let index = activeIndices.last {
return index.messageIndex.id.peerId
} else {
return nil
}
}
}
} }
} }

View File

@ -899,9 +899,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId) |> deliverOnMainQueue).start(next: { [weak self] message in
} |> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else { guard let strongSelf = self, let message = message else {
return return
} }
@ -1641,9 +1640,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId)
}
|> deliverOnMainQueue).start(next: { message in |> deliverOnMainQueue).start(next: { message in
guard let strongSelf = self, let message = message else { guard let strongSelf = self, let message = message else {
return return
@ -1690,7 +1687,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
strongSelf.chatDisplayNode.dismissInput() strongSelf.chatDisplayNode.dismissInput()
strongSelf.effectiveNavigationController?.pushViewController(GameController(context: strongSelf.context, url: url, message: EngineMessage(message))) strongSelf.effectiveNavigationController?.pushViewController(GameController(context: strongSelf.context, url: url, message: message))
} }
var botPeer: TelegramUser? var botPeer: TelegramUser?
@ -1702,7 +1699,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
if botPeer == nil { if botPeer == nil {
if let peer = message.author as? TelegramUser, peer.botInfo != nil { if case let .user(peer) = message.author, peer.botInfo != nil {
botPeer = peer botPeer = peer
} else if let peer = message.peers[message.id.peerId] as? TelegramUser, peer.botInfo != nil { } else if let peer = message.peers[message.id.peerId] as? TelegramUser, peer.botInfo != nil {
botPeer = peer botPeer = peer
@ -2525,9 +2522,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
strongSelf.commitPurposefulAction() strongSelf.commitPurposefulAction()
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId)
}
|> deliverOnMainQueue).start(next: { message in |> deliverOnMainQueue).start(next: { message in
guard let strongSelf = self, let message = message else { guard let strongSelf = self, let message = message else {
return return
@ -2608,9 +2603,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
if id.namespace == Namespaces.Message.ScheduledCloud { if id.namespace == Namespaces.Message.ScheduledCloud {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.MessageGroup(id: id))
return transaction.getMessageGroup(id) ?? [] |> deliverOnMainQueue).start(next: { messages in
} |> deliverOnMainQueue).start(next: { messages in
guard let strongSelf = self, let message = messages.filter({ $0.id == id }).first else { guard let strongSelf = self, let message = messages.filter({ $0.id == id }).first else {
return return
} }
@ -2636,13 +2630,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor)
}, action: { [weak self] controller, f in }, action: { [weak self] controller, f in
if let strongSelf = self { if let strongSelf = self {
strongSelf.interfaceInteraction?.deleteMessages(messages, controller, f) strongSelf.interfaceInteraction?.deleteMessages(messages.map { $0._asMessage() }, controller, f)
} }
}))) })))
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: 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, postbox: strongSelf.context.account.postbox, 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 {
@ -2653,9 +2647,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.window?.presentInGlobalOverlay(controller) strongSelf.window?.presentInGlobalOverlay(controller)
}) })
} else { } else {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in let _ = (strongSelf.context.engine.messages.failedMessageGroup(id: id)
return transaction.getMessageFailedGroup(id) ?? [] |> deliverOnMainQueue).start(next: { messages in
} |> deliverOnMainQueue).start(next: { messages in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -2666,9 +2659,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if groups[groupInfo.stableId] == nil { if groups[groupInfo.stableId] == nil {
groups[groupInfo.stableId] = [] groups[groupInfo.stableId] = []
} }
groups[groupInfo.stableId]?.append(message) groups[groupInfo.stableId]?.append(message._asMessage())
} else { } else {
notGrouped.append(message) notGrouped.append(message._asMessage())
} }
} }
@ -2856,9 +2849,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: { let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId)
}
|> deliverOnMainQueue).start(next: { message in |> deliverOnMainQueue).start(next: { message in
guard let message = message else { guard let message = message else {
return return
@ -2957,9 +2948,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}, editScheduledMessagesTime: { [weak self] messageIds in }, editScheduledMessagesTime: { [weak self] messageIds in
if let strongSelf = self, let messageId = messageIds.first { if let strongSelf = self, let messageId = messageIds.first {
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: { let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId) |> deliverOnMainQueue).start(next: { [weak self] message in
} |> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else { guard let strongSelf = self, let message = message else {
return return
} }
@ -3085,9 +3075,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: { let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId)
}
|> deliverOnMainQueue).start(next: { message in |> deliverOnMainQueue).start(next: { message in
guard let message = message else { guard let message = message else {
return return
@ -3140,21 +3128,35 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.dismissAllTooltips() strongSelf.dismissAllTooltips()
let context = strongSelf.context let context = strongSelf.context
let _ = (context.account.postbox.transaction { transaction -> (Peer?, Message?) in
return (transaction.getPeer(peer.id), messageId.flatMap { transaction.getMessage($0) }) let dataSignal: Signal<(EnginePeer?, EngineMessage?), NoError>
if let messageId = messageId {
dataSignal = context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: peer.id),
TelegramEngine.EngineData.Item.Messages.Message(id: messageId)
)
} else {
dataSignal = context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: peer.id)
)
|> map { peer -> (EnginePeer?, EngineMessage?) in
return (peer, nil)
}
} }
let _ = (dataSignal
|> deliverOnMainQueue).start(next: { [weak self] peer, message in |> deliverOnMainQueue).start(next: { [weak self] peer, message in
guard let strongSelf = self, let peer = peer, peer.smallProfileImage != nil else { guard let strongSelf = self, let peer = peer, peer.smallProfileImage != nil else {
return return
} }
let galleryController = AvatarGalleryController(context: context, peer: peer, remoteEntries: nil, replaceRootController: { controller, ready in let galleryController = AvatarGalleryController(context: context, peer: peer._asPeer(), remoteEntries: nil, replaceRootController: { controller, ready in
}, synchronousLoad: true) }, synchronousLoad: true)
galleryController.setHintWillBePresentedInPreviewingContext(true) galleryController.setHintWillBePresentedInPreviewingContext(true)
let items: Signal<[ContextMenuItem], NoError> = context.account.postbox.transaction { transaction -> [ContextMenuItem] in let items: Signal<[ContextMenuItem], NoError> = context.account.postbox.transaction { transaction -> [ContextMenuItem] in
var isChannel = false var isChannel = false
if let peer = peer as? TelegramChannel, case .broadcast = peer.info { if case let .channel(peer) = peer, case .broadcast = peer.info {
isChannel = true isChannel = true
} }
var items: [ContextMenuItem] = [ var items: [ContextMenuItem] = [
@ -3187,7 +3189,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if inputMode == .none { if inputMode == .none {
inputMode = .text inputMode = .text
} }
return (chatTextInputAddMentionAttribute(current, peer: peer), inputMode) return (chatTextInputAddMentionAttribute(current, peer: peer._asPeer()), inputMode)
} }
}, delay: true) }, delay: true)
}))) })))
@ -3235,17 +3237,25 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: { let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (context.account.postbox.transaction { transaction -> (MessageId, CachedPeerData?)? in let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: id))
if let message = transaction.getMessage(id), let sourceMessageId = message.forwardInfo?.sourceMessageId { |> mapToSignal { message -> Signal<(EngineMessage.Id, Int32?)?, NoError> in
return (sourceMessageId, transaction.getPeerCachedData(peerId: sourceMessageId.peerId)) if let message = message, let sourceMessageId = message.forwardInfo?.sourceMessageId {
return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.StatsDatacenterId(id: sourceMessageId.peerId))
|> map { statsDatacenterId -> (EngineMessage.Id, Int32?)? in
return (sourceMessageId, statsDatacenterId)
}
} else { } else {
return (id, transaction.getPeerCachedData(peerId: id.peerId)) return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.StatsDatacenterId(id: id.peerId))
|> map { statsDatacenterId -> (EngineMessage.Id, Int32?)? in
return (id, statsDatacenterId)
}
} }
} |> deliverOnMainQueue).start(next: { [weak self] messageIdAndCachedPeerData in }
guard let strongSelf = self, let (id, cachedPeerDataValue) = messageIdAndCachedPeerData, let cachedPeerData = cachedPeerDataValue else { |> deliverOnMainQueue).start(next: { [weak self] messageIdAndStatsDatacenterId in
guard let strongSelf = self, let (id, statsDatacenterId) = messageIdAndStatsDatacenterId, let statsDatacenterId = statsDatacenterId else {
return return
} }
strongSelf.push(messageStatsController(context: context, messageId: id, cachedPeerData: cachedPeerData)) strongSelf.push(messageStatsController(context: context, messageId: id, statsDatacenterId: statsDatacenterId))
}) })
}, delay: true) }, delay: true)
}, editMessageMedia: { [weak self] messageId, draw in }, editMessageMedia: { [weak self] messageId, draw in
@ -3256,9 +3266,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.dismissInput() strongSelf.chatDisplayNode.dismissInput()
if draw { if draw {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId) |> deliverOnMainQueue).start(next: { [weak self] message in
} |> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else { guard let strongSelf = self, let message = message else {
return return
} }
@ -6114,9 +6123,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
if let messageId = strongSelf.presentationInterfaceState.interfaceState.editMessage?.messageId { if let messageId = strongSelf.presentationInterfaceState.interfaceState.editMessage?.messageId {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId) |> deliverOnMainQueue).start(next: { message in
} |> deliverOnMainQueue).start(next: { message in
guard let strongSelf = self, let editMessageState = strongSelf.presentationInterfaceState.editMessageState, case let .media(options) = editMessageState.content else { guard let strongSelf = self, let editMessageState = strongSelf.presentationInterfaceState.editMessageState, case let .media(options) = editMessageState.content else {
return return
} }
@ -6124,10 +6132,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let message = message { if let message = message {
for media in message.media { for media in message.media {
if let image = media as? TelegramMediaImage { if let image = media as? TelegramMediaImage {
originalMediaReference = .message(message: MessageReference(message), media: image) originalMediaReference = .message(message: MessageReference(message._asMessage()), media: image)
} else if let file = media as? TelegramMediaFile { } else if let file = media as? TelegramMediaFile {
if file.isVideo || file.isAnimated { if file.isVideo || file.isAnimated {
originalMediaReference = .message(message: MessageReference(message), media: file) originalMediaReference = .message(message: MessageReference(message._asMessage()), media: file)
} }
} }
} }
@ -6884,21 +6892,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}, shareSelectedMessages: { [weak self] in }, shareSelectedMessages: { [weak self] in
if let strongSelf = self, let selectedIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !selectedIds.isEmpty { if let strongSelf = self, let selectedIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !selectedIds.isEmpty {
strongSelf.commitPurposefulAction() strongSelf.commitPurposefulAction()
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in let _ = (strongSelf.context.engine.data.get(EngineDataMap(
var messages: [Message] = [] selectedIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
for id in selectedIds { ))
if let message = transaction.getMessage(id) { |> map { messages -> [EngineMessage] in
messages.append(message) return messages.values.compactMap { $0 }
} }
} |> deliverOnMainQueue).start(next: { messages in
return messages
} |> deliverOnMainQueue).start(next: { messages in
if let strongSelf = self, !messages.isEmpty { if let strongSelf = self, !messages.isEmpty {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) }) strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) })
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in
return lhs.index < rhs.index return lhs.index < rhs.index
})), externalShare: true, immediateExternalShare: true, updatedPresentationData: strongSelf.updatedPresentationData) }).map { $0._asMessage() }), externalShare: true, immediateExternalShare: true, updatedPresentationData: strongSelf.updatedPresentationData)
strongSelf.chatDisplayNode.dismissInput() strongSelf.chatDisplayNode.dismissInput()
strongSelf.present(shareController, in: .window(.root)) strongSelf.present(shareController, in: .window(.root))
} }
@ -8469,14 +8475,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self?.presentChatRequestAdminInfo() self?.presentChatRequestAdminInfo()
}, displayCopyProtectionTip: { [weak self] node, save in }, displayCopyProtectionTip: { [weak self] node, save in
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, let messageIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds { if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, let messageIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [EngineMessage] in let _ = (strongSelf.context.engine.data.get(EngineDataMap(
var messages: [EngineMessage] = [] messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
for id in messageIds { ))
if let message = transaction.getMessage(id) { |> map { messages -> [EngineMessage] in
messages.append(EngineMessage(message)) return messages.values.compactMap { $0 }
}
}
return messages
} }
|> deliverOnMainQueue).start(next: { [weak self] messages in |> deliverOnMainQueue).start(next: { [weak self] messages in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -13975,11 +13978,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
private func forwardMessages(messageIds: [MessageId], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool = false) { private func forwardMessages(messageIds: [MessageId], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool = false) {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in let _ = (self.context.engine.data.get(EngineDataMap(
return messageIds.compactMap(transaction.getMessage) messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
} ))
|> deliverOnMainQueue).start(next: { [weak self] messages in |> deliverOnMainQueue).start(next: { [weak self] messages in
self?.forwardMessages(messages: messages, options: options, resetCurrent: resetCurrent) self?.forwardMessages(messages: messages.values.compactMap { $0?._asMessage() }, options: options, resetCurrent: resetCurrent)
}) })
} }

View File

@ -324,9 +324,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
if context.sharedContext.immediateExperimentalUISettings.localTranscription { if context.sharedContext.immediateExperimentalUISettings.localTranscription {
let appLocale = presentationData.strings.baseLanguageCode let appLocale = presentationData.strings.baseLanguageCode
let signal: Signal<String?, NoError> = context.account.postbox.transaction { transaction -> Message? in let signal: Signal<String?, NoError> = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: message.id))
return transaction.getMessage(message.id)
}
|> mapToSignal { message -> Signal<String?, NoError> in |> mapToSignal { message -> Signal<String?, NoError> in
guard let message = message else { guard let message = message else {
return .single(nil) return .single(nil)

View File

@ -842,7 +842,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
} }
} }
} else { } else {
updatedStatusSignal = chatMessagePhotoStatus(context: context, messageId: message.id, photoReference: .message(message: MessageReference(message), media: image), displayAtSize: 600) updatedStatusSignal = chatMessagePhotoStatus(context: context, messageId: message.id, photoReference: .message(message: MessageReference(message), media: image), displayAtSize: nil)
|> map { resourceStatus -> (MediaResourceStatus, MediaResourceStatus?) in |> map { resourceStatus -> (MediaResourceStatus, MediaResourceStatus?) in
return (resourceStatus, nil) return (resourceStatus, nil)
} }

View File

@ -995,11 +995,9 @@ private class ChatQrCodeScreenNode: ViewControllerTracingNode, UIScrollViewDeleg
let sharedData = self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings]) let sharedData = self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings])
|> take(1) |> take(1)
if case let .peer(peer) = controller.subject, peer.id != self.context.account.peerId { if case let .peer(peer) = controller.subject, peer.id != self.context.account.peerId {
let cachedData = self.context.account.postbox.transaction { transaction in let themeEmoticon = self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.ThemeEmoticon(id: peer.id))
return transaction.getPeerCachedData(peerId: peer.id) initiallySelectedEmoticon = combineLatest(themeEmoticon, sharedData)
} |> map { themeEmoticon, sharedData -> String in
initiallySelectedEmoticon = combineLatest(cachedData, sharedData)
|> map { cachedData, sharedData -> String in
let themeSettings: PresentationThemeSettings let themeSettings: PresentationThemeSettings
if let current = sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings]?.get(PresentationThemeSettings.self) { if let current = sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings]?.get(PresentationThemeSettings.self) {
themeSettings = current themeSettings = current
@ -1008,15 +1006,7 @@ private class ChatQrCodeScreenNode: ViewControllerTracingNode, UIScrollViewDeleg
} }
let currentDefaultEmoticon = themeSettings.theme.emoticon ?? defaultEmoticon let currentDefaultEmoticon = themeSettings.theme.emoticon ?? defaultEmoticon
if let cachedData = cachedData as? CachedUserData { return themeEmoticon ?? currentDefaultEmoticon
return cachedData.themeEmoticon ?? currentDefaultEmoticon
} else if let cachedData = cachedData as? CachedGroupData {
return cachedData.themeEmoticon ?? currentDefaultEmoticon
} else if let cachedData = cachedData as? CachedChannelData {
return cachedData.themeEmoticon ?? currentDefaultEmoticon
} else {
return currentDefaultEmoticon
}
} }
} else { } else {
initiallySelectedEmoticon = sharedData initiallySelectedEmoticon = sharedData

View File

@ -129,13 +129,16 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection
switch self.mode { switch self.mode {
case let .chatSelection(_, selectedChats, additionalCategories, _): case let .chatSelection(_, selectedChats, additionalCategories, _):
let _ = (self.context.account.postbox.transaction { transaction -> [Peer] in let _ = (self.context.engine.data.get(
return selectedChats.compactMap(transaction.getPeer) EngineDataList(
} selectedChats.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
|> deliverOnMainQueue).start(next: { [weak self] peers in )
)
|> deliverOnMainQueue).start(next: { [weak self] peerList in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let peers = peerList.compactMap { $0 }
if let additionalCategories = additionalCategories { if let additionalCategories = additionalCategories {
for i in 0 ..< additionalCategories.categories.count { for i in 0 ..< additionalCategories.categories.count {
if additionalCategories.selectedCategories.contains(additionalCategories.categories[i].id) { if additionalCategories.selectedCategories.contains(additionalCategories.categories[i].id) {
@ -144,7 +147,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection
} }
} }
strongSelf.contactsNode.editableTokens.append(contentsOf: peers.map { peer -> EditableTokenListToken in strongSelf.contactsNode.editableTokens.append(contentsOf: peers.map { peer -> EditableTokenListToken in
return EditableTokenListToken(id: peer.id, title: peerTokenTitle(accountPeerId: params.context.account.peerId, peer: peer, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder), fixedPosition: nil) return EditableTokenListToken(id: peer.id, title: peerTokenTitle(accountPeerId: params.context.account.peerId, peer: peer._asPeer(), strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder), fixedPosition: nil)
}) })
strongSelf._peersReady.set(.single(true)) strongSelf._peersReady.set(.single(true))
if strongSelf.isNodeLoaded { if strongSelf.isNodeLoaded {

View File

@ -58,11 +58,10 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer
self?.dismiss() self?.dismiss()
}, requestShare: { [weak self] messageId in }, requestShare: { [weak self] messageId in
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId) |> deliverOnMainQueue).start(next: { message in
} |> deliverOnMainQueue).start(next: { message in
if let strongSelf = self, let message = message { if let strongSelf = self, let message = message {
let shareController = ShareController(context: strongSelf.context, subject: .messages([message]), showInChat: { message in let shareController = ShareController(context: strongSelf.context, subject: .messages([message._asMessage()]), showInChat: { message in
if let strongSelf = self { if let strongSelf = self {
strongSelf.context.sharedContext.navigateToChat(accountId: strongSelf.context.account.id, peerId: message.id.peerId, messageId: message.id) strongSelf.context.sharedContext.navigateToChat(accountId: strongSelf.context.account.id, peerId: message.id.peerId, messageId: message.id)
strongSelf.dismiss() strongSelf.dismiss()
@ -70,16 +69,14 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer
}, externalShare: true) }, externalShare: true)
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in let _ = (strongSelf.context.engine.data.get(
var peers: [Peer] = [] EngineDataList(
for peerId in peerIds { peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
if let peer = transaction.getPeer(peerId) { )
peers.append(peer) )
} |> deliverOnMainQueue).start(next: { [weak self] peerList in
}
return peers
} |> deliverOnMainQueue).start(next: { [weak self] peers in
if let strongSelf = self { if let strongSelf = self {
let peers = peerList.compactMap { $0 }
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String let text: String
@ -89,14 +86,14 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer
savedMessages = true savedMessages = true
} else { } else {
if peers.count == 1, let peer = peers.first { if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string text = presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last { } else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(firstPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(secondPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string text = presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} else if let peer = peers.first { } else if let peer = peers.first {
let peerName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string text = presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
} else { } else {
text = "" text = ""

View File

@ -1928,16 +1928,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let presentationData = strongSelf.presentationData let presentationData = strongSelf.presentationData
let peerId = strongSelf.peerId let peerId = strongSelf.peerId
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { c, _ in items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { c, _ in
c.setItems(context.account.postbox.transaction { transaction -> ContextController.Items in c.setItems(context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: message.id.peerId))
|> map { peer -> ContextController.Items in
var items: [ContextMenuItem] = [] var items: [ContextMenuItem] = []
let messageIds = [message.id] let messageIds = [message.id]
if let peer = transaction.getPeer(message.id.peerId) { if let peer = peer {
var personalPeerName: String? var personalPeerName: String?
var isChannel = false var isChannel = false
if let user = peer as? TelegramUser { if case let .user(user) = peer {
personalPeerName = EnginePeer(user).compactDisplayTitle personalPeerName = EnginePeer(user).compactDisplayTitle
} else if let channel = peer as? TelegramChannel, case .broadcast = channel.info { } else if case let .channel(channel) = peer, case .broadcast = channel.info {
isChannel = true isChannel = true
} }
@ -2066,16 +2067,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
if actions.options.contains(.deleteLocally) || actions.options.contains(.deleteGlobally) { if actions.options.contains(.deleteLocally) || actions.options.contains(.deleteGlobally) {
items.append(.action(ContextMenuActionItem(text: strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { c, f in items.append(.action(ContextMenuActionItem(text: strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { c, f in
c.setItems(context.account.postbox.transaction { transaction -> ContextController.Items in c.setItems(context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: message.id.peerId))
|> map { peer -> ContextController.Items in
var items: [ContextMenuItem] = [] var items: [ContextMenuItem] = []
let messageIds = [message.id] let messageIds = [message.id]
if let peer = transaction.getPeer(message.id.peerId) { if let peer = peer {
var personalPeerName: String? var personalPeerName: String?
var isChannel = false var isChannel = false
if let user = peer as? TelegramUser { if case let .user(user) = peer {
personalPeerName = EnginePeer(user).compactDisplayTitle personalPeerName = EnginePeer(user).compactDisplayTitle
} else if let channel = peer as? TelegramChannel, case .broadcast = channel.info { } else if case let .channel(channel) = peer, case .broadcast = channel.info {
isChannel = true isChannel = true
} }
@ -2724,9 +2726,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
let context = strongSelf.context let context = strongSelf.context
let _ = (getUserPeer(postbox: strongSelf.context.account.postbox, peerId: peer.id) let _ = (getUserPeer(engine: strongSelf.context.engine, peerId: peer.id)
|> mapToSignal { peer, _ -> Signal<Void, NoError> in |> mapToSignal { peer -> Signal<Void, NoError> in
guard let peer = peer as? TelegramUser, let phone = peer.phone, !phone.isEmpty else { guard case let .user(peer) = peer, let phone = peer.phone, !phone.isEmpty else {
return .complete() return .complete()
} }
return (context.sharedContext.contactDataManager?.basicDataForNormalizedPhoneNumber(DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phone))) ?? .single([])) return (context.sharedContext.contactDataManager?.basicDataForNormalizedPhoneNumber(DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phone))) ?? .single([]))
@ -3279,9 +3281,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
return return
} }
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId) |> deliverOnMainQueue).start(next: { [weak self] message in
} |> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else { guard let strongSelf = self, let message = message else {
return return
} }
@ -4004,41 +4005,42 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let shareController = ShareController(context: strongSelf.context, subject: .media(.standalone(media: contact)), updatedPresentationData: strongSelf.controller?.updatedPresentationData) let shareController = ShareController(context: strongSelf.context, subject: .media(.standalone(media: contact)), updatedPresentationData: strongSelf.controller?.updatedPresentationData)
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in let _ = (strongSelf.context.engine.data.get(
var peers: [Peer] = [] EngineDataList(
for peerId in peerIds { peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
if let peer = transaction.getPeer(peerId) { )
peers.append(peer) )
} |> deliverOnMainQueue).start(next: { [weak self] peerList in
guard let strongSelf = self else {
return
} }
return peers
} |> deliverOnMainQueue).start(next: { [weak self] peers in let peers = peerList.compactMap { $0 }
if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String let text: String
var savedMessages = false var savedMessages = false
if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId { if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId {
text = presentationData.strings.UserInfo_ContactForwardTooltip_SavedMessages_One text = presentationData.strings.UserInfo_ContactForwardTooltip_SavedMessages_One
savedMessages = true savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_ContactForwardTooltip_Chat_One(peerName).string
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_ContactForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} else if let peer = peers.first {
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_ContactForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
} else { } else {
if peers.count == 1, let peer = peers.first { text = ""
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_ContactForwardTooltip_Chat_One(peerName).string
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(firstPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(secondPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_ContactForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} else if let peer = peers.first {
let peerName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_ContactForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
} else {
text = ""
}
} }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
} }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}) })
} }
} }
@ -4346,94 +4348,77 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
private func openStartSecretChat() { private func openStartSecretChat() {
let peerId = self.peerId let peerId = self.peerId
let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, PeerId?) in
let peer = transaction.getPeer(peerId) let _ = (combineLatest(
let filteredPeerIds = Array(transaction.getAssociatedPeerIds(peerId)).filter { $0.namespace == Namespaces.Peer.SecretChat } self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId)),
var activeIndices: [ChatListIndex] = [] self.context.engine.peers.mostRecentSecretChat(id: self.peerId)
for associatedId in filteredPeerIds { )
if let state = (transaction.getPeer(associatedId) as? TelegramSecretChat)?.embeddedState {
switch state {
case .active, .handshake:
if let (_, index) = transaction.getPeerChatListIndex(associatedId) {
activeIndices.append(index)
}
default:
break
}
}
}
activeIndices.sort()
if let index = activeIndices.last {
return (peer, index.messageIndex.id.peerId)
} else {
return (peer, nil)
}
}
|> deliverOnMainQueue).start(next: { [weak self] peer, currentPeerId in |> deliverOnMainQueue).start(next: { [weak self] peer, currentPeerId in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if let controller = strongSelf.controller { guard let controller = strongSelf.controller else {
let displayTitle = peer.flatMap(EnginePeer.init)?.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder) ?? "" return
controller.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.UserInfo_StartSecretChatConfirmation(displayTitle).string, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.UserInfo_StartSecretChatStart, action: { }
let displayTitle = peer?.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder) ?? ""
controller.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.UserInfo_StartSecretChatConfirmation(displayTitle).string, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.UserInfo_StartSecretChatStart, action: {
guard let strongSelf = self else {
return
}
var createSignal = strongSelf.context.engine.peers.createSecretChat(peerId: peerId)
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
if let strongSelf = self {
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: {
cancelImpl?()
}))
strongSelf.controller?.present(statusController, in: .window(.root))
return ActionDisposable { [weak statusController] in
Queue.mainQueue().async() {
statusController?.dismiss()
}
}
} else {
return EmptyDisposable
}
}
|> runOn(Queue.mainQueue())
|> delay(0.15, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start()
createSignal = createSignal
|> afterDisposed {
Queue.mainQueue().async {
progressDisposable.dispose()
}
}
let createSecretChatDisposable = MetaDisposable()
cancelImpl = {
createSecretChatDisposable.set(nil)
}
createSecretChatDisposable.set((createSignal
|> deliverOnMainQueue).start(next: { peerId in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
var createSignal = strongSelf.context.engine.peers.createSecretChat(peerId: peerId) if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) {
var cancelImpl: (() -> Void)? strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId)))
let progressSignal = Signal<Never, NoError> { subscriber in
if let strongSelf = self {
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: {
cancelImpl?()
}))
strongSelf.controller?.present(statusController, in: .window(.root))
return ActionDisposable { [weak statusController] in
Queue.mainQueue().async() {
statusController?.dismiss()
}
}
} else {
return EmptyDisposable
}
} }
|> runOn(Queue.mainQueue()) }, error: { error in
|> delay(0.15, queue: Queue.mainQueue()) guard let strongSelf = self else {
let progressDisposable = progressSignal.start() return
createSignal = createSignal
|> afterDisposed {
Queue.mainQueue().async {
progressDisposable.dispose()
}
} }
let createSecretChatDisposable = MetaDisposable() let text: String
cancelImpl = { switch error {
createSecretChatDisposable.set(nil) case .limitExceeded:
text = strongSelf.presentationData.strings.TwoStepAuth_FloodError
default:
text = strongSelf.presentationData.strings.Login_UnknownError
} }
strongSelf.controller?.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
createSecretChatDisposable.set((createSignal }))
|> deliverOnMainQueue).start(next: { peerId in })]), in: .window(.root))
guard let strongSelf = self else {
return
}
if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId)))
}
}, error: { error in
guard let strongSelf = self else {
return
}
let text: String
switch error {
case .limitExceeded:
text = strongSelf.presentationData.strings.TwoStepAuth_FloodError
default:
text = strongSelf.presentationData.strings.Login_UnknownError
}
strongSelf.controller?.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}))
})]), in: .window(.root))
}
}) })
} }
@ -4507,44 +4492,45 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
private func openUsername(value: String) { private func openUsername(value: String) {
let shareController = ShareController(context: self.context, subject: .url("https://t.me/\(value)"), updatedPresentationData: self.controller?.updatedPresentationData) let shareController = ShareController(context: self.context, subject: .url("https://t.me/\(value)"), updatedPresentationData: self.controller?.updatedPresentationData)
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { guard let strongSelf = self else {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in return
var peers: [Peer] = []
for peerId in peerIds {
if let peer = transaction.getPeer(peerId) {
peers.append(peer)
}
}
return peers
} |> deliverOnMainQueue).start(next: { [weak self] peers in
if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId {
text = presentationData.strings.UserInfo_LinkForwardTooltip_SavedMessages_One
savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peerName).string
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(firstPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(secondPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} else if let peer = peers.first {
let peerName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
} else {
text = ""
}
}
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}
})
} }
let _ = (strongSelf.context.engine.data.get(
EngineDataList(
peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
)
)
|> deliverOnMainQueue).start(next: { [weak self] peerList in
guard let strongSelf = self else {
return
}
let peers = peerList.compactMap { $0 }
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId {
text = presentationData.strings.UserInfo_LinkForwardTooltip_SavedMessages_One
savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peerName).string
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} else if let peer = peers.first {
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
} else {
text = ""
}
}
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
})
} }
shareController.actionCompleted = { [weak self] in shareController.actionCompleted = { [weak self] in
if let strongSelf = self { if let strongSelf = self {
@ -4668,12 +4654,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func openPhone(value: String) { private func openPhone(value: String) {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: peerId) let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if let peer = peer as? TelegramUser, let peerPhoneNumber = peer.phone, formatPhoneNumber(value) == formatPhoneNumber(peerPhoneNumber) { if case let .user(peer) = peer, let peerPhoneNumber = peer.phone, formatPhoneNumber(value) == formatPhoneNumber(peerPhoneNumber) {
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
let dismissAction: () -> Void = { [weak actionSheet] in let dismissAction: () -> Void = { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
@ -4704,12 +4690,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func editingOpenNotificationSettings() { private func editingOpenNotificationSettings() {
let peerId = self.peerId let _ = (combineLatest(
let _ = (combineLatest(self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in self.context.engine.data.get(
let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: self.peerId),
let globalSettings: GlobalNotificationSettings = transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications)?.get(GlobalNotificationSettings.self) ?? GlobalNotificationSettings.defaultSettings TelegramEngine.EngineData.Item.NotificationSettings.Global()
return (peerSettings, globalSettings) ),
}, self.context.engine.peers.notificationSoundList()) self.context.engine.peers.notificationSoundList()
)
|> deliverOnMainQueue).start(next: { [weak self] settings, notificationSoundList in |> deliverOnMainQueue).start(next: { [weak self] settings, notificationSoundList in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@ -4717,11 +4704,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let (peerSettings, globalSettings) = settings let (peerSettings, globalSettings) = settings
let muteSettingsController = notificationMuteSettingsController(presentationData: strongSelf.presentationData, notificationSoundList: notificationSoundList, notificationSettings: globalSettings.effective.groupChats, soundSettings: nil, openSoundSettings: { let muteSettingsController = notificationMuteSettingsController(presentationData: strongSelf.presentationData, notificationSoundList: notificationSoundList, notificationSettings: globalSettings.groupChats._asMessageNotificationSettings(), soundSettings: nil, openSoundSettings: {
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let soundController = notificationSoundSelectionController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in let soundController = notificationSoundSelectionController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, isModal: true, currentSound: peerSettings.messageSound._asMessageSound(), defaultSound: globalSettings.groupChats.sound._asMessageSound(), completion: { sound in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -4741,18 +4728,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func editingOpenSoundSettings() { private func editingOpenSoundSettings() {
let peerId = self.peerId let _ = (self.context.engine.data.get(
let _ = (self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: self.peerId),
let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings TelegramEngine.EngineData.Item.NotificationSettings.Global()
let globalSettings: GlobalNotificationSettings = transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications)?.get(GlobalNotificationSettings.self) ?? GlobalNotificationSettings.defaultSettings )
return (peerSettings, globalSettings)
}
|> deliverOnMainQueue).start(next: { [weak self] peerSettings, globalSettings in |> deliverOnMainQueue).start(next: { [weak self] peerSettings, globalSettings in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let soundController = notificationSoundSelectionController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in let soundController = notificationSoundSelectionController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, isModal: true, currentSound: peerSettings.messageSound._asMessageSound(), defaultSound: globalSettings.groupChats.sound._asMessageSound(), completion: { sound in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -4763,8 +4748,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func editingToggleShowMessageText(value: Bool) { private func editingToggleShowMessageText(value: Bool) {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else { guard let strongSelf = self, let peer = peer else {
return return
} }
@ -4784,8 +4769,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let _ = (getUserPeer(postbox: strongSelf.context.account.postbox, peerId: strongSelf.peerId) let _ = (getUserPeer(engine: strongSelf.context.engine, peerId: strongSelf.peerId)
|> deliverOnMainQueue).start(next: { peer, _ in |> deliverOnMainQueue).start(next: { peer in
guard let peer = peer, let strongSelf = self else { guard let peer = peer, let strongSelf = self else {
return return
} }
@ -4885,8 +4870,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func openAddContact() { private func openAddContact() {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else { guard let strongSelf = self, let peer = peer else {
return return
} }
@ -4899,15 +4884,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func updateBlocked(block: Bool) { private func updateBlocked(block: Bool) {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> take(1) |> take(1)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else { guard let strongSelf = self, let peer = peer else {
return return
} }
let presentationData = strongSelf.presentationData let presentationData = strongSelf.presentationData
if let peer = peer as? TelegramUser, let _ = peer.botInfo { if case let .user(peer) = peer, let _ = peer.botInfo {
strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: block).start()) strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: block).start())
if !block { if !block {
let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start()
@ -4926,8 +4911,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let deleteChat = false let deleteChat = false
actionSheet.setItemGroups([ actionSheet.setItemGroups([
ActionSheetItemGroup(items: [ ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.UserInfo_BlockConfirmationTitle(EnginePeer(peer).compactDisplayTitle).string), ActionSheetTextItem(title: presentationData.strings.UserInfo_BlockConfirmationTitle(peer.compactDisplayTitle).string),
ActionSheetButtonItem(title: presentationData.strings.UserInfo_BlockActionTitle(EnginePeer(peer).compactDisplayTitle).string, color: .destructive, action: { ActionSheetButtonItem(title: presentationData.strings.UserInfo_BlockActionTitle(peer.compactDisplayTitle).string, color: .destructive, action: {
dismissAction() dismissAction()
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@ -4951,9 +4936,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} else { } else {
let text: String let text: String
if block { if block {
text = presentationData.strings.UserInfo_BlockConfirmation(EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string text = presentationData.strings.UserInfo_BlockConfirmation(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
} else { } else {
text = presentationData.strings.UserInfo_UnblockConfirmation(EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string text = presentationData.strings.UserInfo_UnblockConfirmation(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
} }
strongSelf.controller?.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Yes, action: { strongSelf.controller?.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Yes, action: {
guard let strongSelf = self else { guard let strongSelf = self else {
@ -5228,52 +5213,53 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func openShareBot() { private func openShareBot() {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if let peer = peer as? TelegramUser, let username = peer.username { if case let .user(peer) = peer, let username = peer.username {
let shareController = ShareController(context: strongSelf.context, subject: .url("https://t.me/\(username)"), updatedPresentationData: strongSelf.controller?.updatedPresentationData) let shareController = ShareController(context: strongSelf.context, subject: .url("https://t.me/\(username)"), updatedPresentationData: strongSelf.controller?.updatedPresentationData)
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { guard let strongSelf = self else {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in return
var peers: [Peer] = []
for peerId in peerIds {
if let peer = transaction.getPeer(peerId) {
peers.append(peer)
}
}
return peers
} |> deliverOnMainQueue).start(next: { [weak self] peers in
if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId {
text = presentationData.strings.UserInfo_LinkForwardTooltip_SavedMessages_One
savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peerName).string
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(firstPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(secondPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} else if let peer = peers.first {
let peerName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
} else {
text = ""
}
}
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}
})
} }
let _ = (strongSelf.context.engine.data.get(
EngineDataList(
peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
)
)
|> deliverOnMainQueue).start(next: { [weak self] peerList in
guard let strongSelf = self else {
return
}
let peers = peerList.compactMap { $0 }
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId {
text = presentationData.strings.UserInfo_LinkForwardTooltip_SavedMessages_One
savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peerName).string
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} else if let peer = peers.first {
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = presentationData.strings.UserInfo_LinkForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
} else {
text = ""
}
}
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
})
} }
shareController.actionCompleted = { [weak self] in shareController.actionCompleted = { [weak self] in
if let strongSelf = self { if let strongSelf = self {
@ -5646,20 +5632,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func openDeletePeer() { private func openDeletePeer() {
let peerId = self.peerId let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId))
let _ = (self.context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
|> deliverOnMainQueue).start(next: { [weak self] peer in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else { guard let strongSelf = self, let peer = peer else {
return return
} }
var isGroup = false var isGroup = false
if let channel = peer as? TelegramChannel { if case let .channel(channel) = peer {
if case .group = channel.info { if case .group = channel.info {
isGroup = true isGroup = true
} }
} else if peer is TelegramGroup { } else if case .legacyGroup = peer {
isGroup = true isGroup = true
} }
let presentationData = strongSelf.presentationData let presentationData = strongSelf.presentationData
@ -5683,7 +5666,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
ActionSheetTextItem(title: title), ActionSheetTextItem(title: title),
ActionSheetButtonItem(title: text, color: .destructive, action: { ActionSheetButtonItem(title: text, color: .destructive, action: {
dismissAction() dismissAction()
self?.deletePeerChat(peer: peer, globally: true) self?.deletePeerChat(peer: peer._asPeer(), globally: true)
}), }),
]), ]),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
@ -5694,21 +5677,18 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
private func openLeavePeer(delete: Bool) { private func openLeavePeer(delete: Bool) {
let peerId = self.peerId let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId))
let _ = (self.context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
|> deliverOnMainQueue).start(next: { [weak self] peer in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else { guard let strongSelf = self, let peer = peer else {
return return
} }
var isGroup = false var isGroup = false
if let channel = peer as? TelegramChannel { if case let .channel(channel) = peer {
if case .group = channel.info { if case .group = channel.info {
isGroup = true isGroup = true
} }
} else if peer is TelegramGroup { } else if case .legacyGroup = peer {
isGroup = true isGroup = true
} }
@ -5740,7 +5720,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
strongSelf.controller?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: title, text: text, actions: [ strongSelf.controller?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: title, text: text, actions: [
TextAlertAction(type: .destructiveAction, title: actionText, action: { TextAlertAction(type: .destructiveAction, title: actionText, action: {
self?.deletePeerChat(peer: peer, globally: delete) self?.deletePeerChat(peer: peer._asPeer(), globally: delete)
}), }),
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
}) })
@ -7224,22 +7204,18 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty, strongSelf.peerId.namespace != Namespaces.Peer.SecretChat else { guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty, strongSelf.peerId.namespace != Namespaces.Peer.SecretChat else {
return return
} }
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in let _ = (strongSelf.context.engine.data.get(EngineDataMap(
var messages: [Message] = [] messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
for id in messageIds { ))
if let message = transaction.getMessage(id) { |> deliverOnMainQueue).start(next: { messageMap in
messages.append(message) let messages = messageMap.values.compactMap { $0 }
}
}
return messages
}
|> deliverOnMainQueue).start(next: { messages in
if let strongSelf = self, !messages.isEmpty { if let strongSelf = self, !messages.isEmpty {
strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil) strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil)
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in
return lhs.index < rhs.index return lhs.index < rhs.index
})), externalShare: true, immediateExternalShare: true, updatedPresentationData: strongSelf.controller?.updatedPresentationData) }).map({ $0._asMessage() })), externalShare: true, immediateExternalShare: true, updatedPresentationData: strongSelf.controller?.updatedPresentationData)
strongSelf.view.endEditing(true) strongSelf.view.endEditing(true)
strongSelf.controller?.present(shareController, in: .window(.root)) strongSelf.controller?.present(shareController, in: .window(.root))
} }
@ -7261,19 +7237,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}, completion: { _, _ in }), in: .window(.root)) }, completion: { _, _ in }), in: .window(.root))
}, displayCopyProtectionTip: { [weak self] node, save in }, displayCopyProtectionTip: { [weak self] node, save in
if let strongSelf = self, let peer = strongSelf.data?.peer, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty { if let strongSelf = self, let peer = strongSelf.data?.peer, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [EngineMessage] in let _ = (strongSelf.context.engine.data.get(EngineDataMap(
var messages: [EngineMessage] = [] messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
for id in messageIds { ))
if let message = transaction.getMessage(id) { |> deliverOnMainQueue).start(next: { [weak self] messageMap in
messages.append(EngineMessage(message))
}
}
return messages
}
|> deliverOnMainQueue).start(next: { [weak self] messages in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let messages = messageMap.values.compactMap { $0 }
enum PeerType { enum PeerType {
case group case group
case channel case channel
@ -8104,19 +8075,20 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
return return
} }
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in let _ = (strongSelf.context.engine.data.get(EngineDataList(
return chatNavigationStack.compactMap(transaction.getPeer) chatNavigationStack.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
} ))
|> deliverOnMainQueue).start(next: { peers in |> deliverOnMainQueue).start(next: { peerList in
guard let strongSelf = self, let backButtonNode = strongSelf.navigationBar?.backButtonNode else { guard let strongSelf = self, let backButtonNode = strongSelf.navigationBar?.backButtonNode else {
return return
} }
let peers = peerList.compactMap { $0 }
let avatarSize = CGSize(width: 28.0, height: 28.0) let avatarSize = CGSize(width: 28.0, height: 28.0)
var items: [ContextMenuItem] = [] var items: [ContextMenuItem] = []
for peer in peers { for peer in peers {
items.append(.action(ContextMenuActionItem(text: EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), icon: { _ in return nil }, iconSource: ContextMenuActionItemIconSource(size: avatarSize, signal: peerAvatarCompleteImage(account: strongSelf.context.account, peer: EnginePeer(peer), size: avatarSize)), action: { _, f in items.append(.action(ContextMenuActionItem(text: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), icon: { _ in return nil }, iconSource: ContextMenuActionItemIconSource(size: avatarSize, signal: peerAvatarCompleteImage(account: strongSelf.context.account, peer: peer, size: avatarSize)), action: { _, f in
f(.default) f(.default)
guard let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController else { guard let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController else {
@ -8212,18 +8184,17 @@ private final class SettingsTabBarContextExtractedContentSource: ContextExtracte
} }
} }
private func getUserPeer(postbox: Postbox, peerId: PeerId) -> Signal<(Peer?, CachedPeerData?), NoError> { private func getUserPeer(engine: TelegramEngine, peerId: EnginePeer.Id) -> Signal<EnginePeer?, NoError> {
return postbox.transaction { transaction -> (Peer?, CachedPeerData?) in return engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
guard let peer = transaction.getPeer(peerId) else { |> mapToSignal { peer -> Signal<EnginePeer?, NoError> in
return (nil, nil) guard let peer = peer else {
return .single(nil)
} }
var resultPeer: Peer? if case let .secretChat(secretChat) = peer {
if let peer = peer as? TelegramSecretChat { return engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: secretChat.regularPeerId))
resultPeer = transaction.getPeer(peer.regularPeerId)
} else { } else {
resultPeer = peer return .single(peer)
} }
return (resultPeer, resultPeer.flatMap({ transaction.getPeerCachedData(peerId: $0.id) }))
} }
} }

View File

@ -559,35 +559,41 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
case let .index(index): case let .index(index):
switch self.messagesLocation { switch self.messagesLocation {
case let .messages(chatLocation, tagMask, _): case let .messages(chatLocation, tagMask, _):
let inputIndex: Signal<MessageIndex?, NoError> var inputIndex: Signal<MessageIndex?, NoError>?
let looping = self.looping let looping = self.looping
switch self.order { switch self.order {
case .regular, .reversed: case .regular, .reversed:
inputIndex = .single(index) inputIndex = .single(index)
case .random: case .random:
var playbackStack = self.playbackStack var playbackStack = self.playbackStack
inputIndex = self.context.account.postbox.transaction { transaction -> MessageIndex? in
if case let .random(previous) = navigation, previous { if case let .random(previous) = navigation, previous {
let _ = playbackStack.pop() let _ = playbackStack.pop()
while true { inner: while true {
if let id = playbackStack.pop() { if let id = playbackStack.pop() {
if let message = transaction.getMessage(id) { inputIndex = self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: id))
return message.index |> map { message in
} return message?.index
} else {
break
} }
break inner
} else {
break
} }
} }
}
if inputIndex == nil {
if let peerId = chatLocation.peerId { if let peerId = chatLocation.peerId {
return transaction.findRandomMessage(peerId: peerId, namespace: Namespaces.Message.Cloud, tag: tagMask, ignoreIds: (playbackStack.ids, playbackStack.set)) ?? index inputIndex = self.context.engine.messages.findRandomMessage(peerId: peerId, namespace: Namespaces.Message.Cloud, tag: tagMask, ignoreIds: (playbackStack.ids, playbackStack.set))
|> map { result in
return result ?? index
}
} else { } else {
return nil inputIndex = .single(nil)
} }
} }
} }
let historySignal = inputIndex let historySignal = (inputIndex ?? .single(nil))
|> mapToSignal { inputIndex -> Signal<(Message, [Message])?, NoError> in |> mapToSignal { inputIndex -> Signal<(Message, [Message])?, NoError> in
guard let inputIndex = inputIndex else { guard let inputIndex = inputIndex else {
return .single(nil) return .single(nil)

View File

@ -189,14 +189,8 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self.peerSelectionNode.requestOpenPeerFromSearch = { [weak self] peer in self.peerSelectionNode.requestOpenPeerFromSearch = { [weak self] peer in
if let strongSelf = self { if let strongSelf = self {
let storedPeer = strongSelf.context.account.postbox.transaction { transaction -> Void in strongSelf.openMessageFromSearchDisposable.set((strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: EnginePeer(peer))
if transaction.getPeer(peer.id) == nil { |> deliverOnMainQueue).start(completed: { [weak strongSelf] in
updatePeers(transaction: transaction, peers: [peer], update: { previousPeer, updatedPeer in
return updatedPeer
})
}
}
strongSelf.openMessageFromSearchDisposable.set((storedPeer |> deliverOnMainQueue).start(completed: { [weak strongSelf] in
if let strongSelf = strongSelf, let peerSelected = strongSelf.peerSelected { if let strongSelf = strongSelf, let peerSelected = strongSelf.peerSelected {
peerSelected(peer) peerSelected(peer)
} }

View File

@ -705,11 +705,10 @@ final class PeerSelectionControllerNode: ASDisplayNode {
} else { } else {
switch peer { switch peer {
case let .peer(peer, _, _): case let .peer(peer, _, _):
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Peer? in let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peer.id))
return transaction.getPeer(peer.id) |> deliverOnMainQueue).start(next: { peer in
} |> deliverOnMainQueue).start(next: { peer in
if let strongSelf = self, let peer = peer { if let strongSelf = self, let peer = peer {
strongSelf.requestOpenPeerFromSearch?(peer) strongSelf.requestOpenPeerFromSearch?(peer._asPeer())
} }
}) })
case .deviceContact: case .deviceContact:

View File

@ -1183,13 +1183,12 @@ public final class SharedAccountContextImpl: SharedAccountContext {
// params.openPeer(peer, .info) // params.openPeer(peer, .info)
}) })
let _ = ((context.account.postbox.transaction { transaction -> Message? in let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
return transaction.getMessage(messageId) |> deliverOnMainQueue).start(next: { message in
}) |> deliverOnMainQueue).start(next: { message in
guard let message = message else { guard let message = message else {
return return
} }
let controller = LocationViewController(context: context, subject: message, params: controllerParams) let controller = LocationViewController(context: context, subject: message._asMessage(), params: controllerParams)
controller.navigationPresentation = .modal controller.navigationPresentation = .modal
navigationController.pushViewController(controller) navigationController.pushViewController(controller)
}) })

View File

@ -517,9 +517,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
} }
} }
case let .peerId(peerId): case let .peerId(peerId):
return context.account.postbox.transaction { transaction -> Peer? in return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
return transaction.getPeer(peerId)
}
|> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in |> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in
if let peer = peer { if let peer = peer {
return .single(.peer(peer.id, .chat(textInputState: nil, subject: nil, peekData: nil))) return .single(.peer(peer.id, .chat(textInputState: nil, subject: nil, peekData: nil)))
@ -528,11 +526,9 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
} }
} }
case let .privateMessage(messageId, threadId, timecode): case let .privateMessage(messageId, threadId, timecode):
return context.account.postbox.transaction { transaction -> Peer? in return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId))
return transaction.getPeer(messageId.peerId)
}
|> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in |> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in
let foundPeer: Signal<Peer?, NoError> let foundPeer: Signal<EnginePeer?, NoError>
if let peer = peer { if let peer = peer {
foundPeer = .single(peer) foundPeer = .single(peer)
} else { } else {

View File

@ -388,18 +388,17 @@ final class WatchMediaHandler: WatchRequestHandler {
|> take(1) |> take(1)
|> mapToSignal({ context -> Signal<UIImage?, NoError> in |> mapToSignal({ context -> Signal<UIImage?, NoError> in
if let context = context { if let context = context {
return context.account.postbox.transaction { transaction -> Peer? in return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
guard let peer = transaction.getPeer(peerId) else { |> mapToSignal { peer -> Signal<EnginePeer?, NoError> in
return nil if let peer = peer, case let .secretChat(secretChat) = peer {
} return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: secretChat.regularPeerId))
if let peer = peer as? TelegramSecretChat {
return transaction.getPeer(peer.regularPeerId)
} else { } else {
return peer return .single(peer)
} }
} |> mapToSignal({ peer -> Signal<UIImage?, NoError> in }
|> mapToSignal({ peer -> Signal<UIImage?, NoError> in
if let peer = peer, let representation = peer.smallProfileImage { if let peer = peer, let representation = peer.smallProfileImage {
let imageData = peerAvatarImageData(account: context.account, peerReference: PeerReference(peer), authorOfMessage: nil, representation: representation, synchronousLoad: false) let imageData = peerAvatarImageData(account: context.account, peerReference: PeerReference(peer._asPeer()), authorOfMessage: nil, representation: representation, synchronousLoad: false)
if let imageData = imageData { if let imageData = imageData {
return imageData return imageData
|> map { data -> UIImage? in |> map { data -> UIImage? in
@ -457,14 +456,12 @@ final class WatchMediaHandler: WatchRequestHandler {
} }
} }
} else if args.stickerPeerId != 0, let peerId = makePeerIdFromBridgeIdentifier(args.stickerPeerId) { } else if args.stickerPeerId != 0, let peerId = makePeerIdFromBridgeIdentifier(args.stickerPeerId) {
mediaSignal = context.account.postbox.transaction { transaction -> Message? in mediaSignal = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.stickerMessageId)))
return transaction.getMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.stickerMessageId))
}
|> map { message -> (TelegramMediaFile, FileMediaReference)? in |> map { message -> (TelegramMediaFile, FileMediaReference)? in
if let message = message { if let message = message {
for media in message.media { for media in message.media {
if let media = media as? TelegramMediaFile { if let media = media as? TelegramMediaFile {
return (media, .message(message: MessageReference(message), media: media)) return (media, .message(message: MessageReference(message._asMessage()), media: media))
} }
} }
} }
@ -514,25 +511,23 @@ final class WatchMediaHandler: WatchRequestHandler {
|> mapToSignal({ context -> Signal<UIImage?, NoError> in |> mapToSignal({ context -> Signal<UIImage?, NoError> in
if let context = context, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) { if let context = context, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) {
var roundVideo = false var roundVideo = false
return context.account.postbox.transaction { transaction -> Message? in return context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId)))
return transaction.getMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId))
}
|> mapToSignal { message -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in |> mapToSignal { message -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in
if let message = message, !message.containsSecretMedia { if let message = message, !message._asMessage().containsSecretMedia {
var imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? var imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
var updatedMediaReference: AnyMediaReference? var updatedMediaReference: AnyMediaReference?
var candidateMediaReference: AnyMediaReference? var candidateMediaReference: AnyMediaReference?
var imageDimensions: CGSize? var imageDimensions: CGSize?
for media in message.media { for media in message.media {
if let image = media as? TelegramMediaImage, let resource = largestImageRepresentation(image.representations)?.resource { if let image = media as? TelegramMediaImage, let resource = largestImageRepresentation(image.representations)?.resource {
self.disposable.add(messageMediaImageInteractiveFetched(context: context, message: message, image: image, resource: resource, storeToDownloadsPeerType: nil).start()) self.disposable.add(messageMediaImageInteractiveFetched(context: context, message: message._asMessage(), image: image, resource: resource, storeToDownloadsPeerType: nil).start())
candidateMediaReference = .message(message: MessageReference(message), media: media) candidateMediaReference = .message(message: MessageReference(message._asMessage()), media: media)
break break
} else if let _ = media as? TelegramMediaFile { } else if let _ = media as? TelegramMediaFile {
candidateMediaReference = .message(message: MessageReference(message), media: media) candidateMediaReference = .message(message: MessageReference(message._asMessage()), media: media)
break break
} else if let webPage = media as? TelegramMediaWebpage, case let .Loaded(content) = webPage.content, let image = content.image, let resource = largestImageRepresentation(image.representations)?.resource { } else if let webPage = media as? TelegramMediaWebpage, case let .Loaded(content) = webPage.content, let image = content.image, let resource = largestImageRepresentation(image.representations)?.resource {
self.disposable.add(messageMediaImageInteractiveFetched(context: context, message: message, image: image, resource: resource, storeToDownloadsPeerType: nil).start()) self.disposable.add(messageMediaImageInteractiveFetched(context: context, message: message._asMessage(), image: image, resource: resource, storeToDownloadsPeerType: nil).start())
candidateMediaReference = .webPage(webPage: WebpageReference(webPage), media: image) candidateMediaReference = .webPage(webPage: WebpageReference(webPage), media: image)
break break
} }
@ -664,14 +659,12 @@ final class WatchAudioHandler: WatchRequestHandler {
|> take(1) |> take(1)
|> mapToSignal({ context -> Signal<String, NoError> in |> mapToSignal({ context -> Signal<String, NoError> in
if let context = context, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) { if let context = context, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) {
return context.account.postbox.transaction { transaction -> Message? in return context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId)))
return transaction.getMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId))
}
|> mapToSignal { message -> Signal<String, NoError> in |> mapToSignal { message -> Signal<String, NoError> in
if let message = message { if let message = message {
for media in message.media { for media in message.media {
if let file = media as? TelegramMediaFile { if let file = media as? TelegramMediaFile {
self.disposable.add(messageMediaFileInteractiveFetched(context: context, message: message, file: file, userInitiated: true).start()) self.disposable.add(messageMediaFileInteractiveFetched(context: context, message: message._asMessage(), file: file, userInitiated: true).start())
return context.account.postbox.mediaBox.resourceData(file.resource) return context.account.postbox.mediaBox.resourceData(file.resource)
|> mapToSignal({ data -> Signal<String, NoError> in |> mapToSignal({ data -> Signal<String, NoError> in
if let tempPath = manager.watchTemporaryStorePath, data.complete { if let tempPath = manager.watchTemporaryStorePath, data.complete {