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.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";

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 {
var queue: Queue { get }

View File

@ -56,7 +56,7 @@ public func messageMediaImageInteractiveFetched(fetchManager: FetchManager, mess
if let range = range {
ranges = IndexSet(integersIn: Int(range.lowerBound) ..< Int(range.upperBound))
} 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)
}

View File

@ -186,6 +186,9 @@ private final class FetchManagerCategoryContext {
if self.topEntryIdAndPriority?.0 == id {
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)
removedEntries = true
}
@ -232,6 +235,7 @@ private final class FetchManagerCategoryContext {
}
activeContext.disposable?.dispose()
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)
|> mapToSignal { type -> Signal<FetchResourceSourceType, FetchResourceError> in
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)
}
|> deliverOnMainQueue).start(next: { _ in
Logger.shared.log("FetchManager", "Completed fetching \(entry.resourceReference.resource.id.stringRepresentation)")
entryCompleted(id)
})
} else {
@ -356,6 +361,7 @@ private final class FetchManagerCategoryContext {
} else if ranges.isEmpty {
} else {
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)
|> mapToSignal { type -> Signal<FetchResourceSourceType, FetchResourceError> in
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)
}
|> deliverOnMainQueue).start(next: { _ in
Logger.shared.log("FetchManager", "Completed fetching \(entry.resourceReference.resource.id.stringRepresentation)")
entryCompleted(topEntryId)
})
}
@ -411,7 +418,8 @@ private final class FetchManagerCategoryContext {
var entriesRemoved = false
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)
entriesRemoved = true

View File

@ -1016,9 +1016,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
@objc func deleteButtonPressed() {
if let currentMessage = self.currentMessage {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in
return transaction.getMessageGroup(currentMessage.id) ?? []
} |> deliverOnMainQueue).start(next: { [weak self] messages in
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.MessageGroup(id: currentMessage.id))
|> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self, !messages.isEmpty {
if messages.count == 1 {
strongSelf.commitDeleteMessages(messages, ask: true)
@ -1032,7 +1031,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
var generalMessageContentKind: MessageContentKind?
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 {
generalMessageContentKind = currentKind
} 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 {
strongSelf.commitDeleteMessages(messages, ask: false)
}
@ -1070,7 +1069,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
deleteAction([currentMessage])
deleteAction([EngineMessage(currentMessage)])
}),
ActionSheetButtonItem(title: multipleText, color: .destructive, action: { [weak actionSheet] in
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
if let strongSelf = self, let controllerInteration = strongSelf.controllerInteraction, !actions.options.isEmpty {
var presentationData = strongSelf.presentationData
@ -1166,9 +1165,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
self.interacting?(true)
if let currentMessage = self.currentMessage {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in
return transaction.getMessageGroup(currentMessage.id) ?? []
} |> deliverOnMainQueue).start(next: { [weak self] messages in
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.MessageGroup(id: currentMessage.id))
|> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self, !messages.isEmpty {
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
var forceTheme: PresentationTheme?
@ -1181,7 +1179,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
var messageContentKinds = Set<MessageContentKindKey>()
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 {
generalMessageContentKind = nil
} else if !beganContentKindScanning || currentKind == generalMessageContentKind {
@ -1210,10 +1208,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
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 {
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 {
if content.embedType == "iframe" {
let item = OpenInItem.url(url: content.url)
@ -1246,12 +1244,12 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
} 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 {
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Preview_SaveGif, action: { [weak self] in
if let strongSelf = self {
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)
}
@ -1397,7 +1395,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}),
ActionSheetButtonItem(title: multipleText, color: .accent, action: { [weak actionSheet] in
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 range = representationFetchRangeForDisplayAtSize(representation: largestRepresentation, dimension: displayAtSize) {
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 deletedMessages(peerId: PeerId)
case notice(key: NoticeEntryKey)
case messageGroup(id: MessageId)
case isContact(id: PeerId)
public func hash(into hasher: inout Hasher) {
switch self {
@ -112,6 +114,10 @@ public enum PostboxViewKey: Hashable {
hasher.combine(peerId)
case let .notice(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 {
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)
case let .notice(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)
}
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
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
}
public func messageStatsController(context: AccountContext, messageId: MessageId, cachedPeerData: CachedPeerData) -> ViewController {
public func messageStatsController(context: AccountContext, messageId: MessageId, statsDatacenterId: Int32?) -> ViewController {
var navigateToMessageImpl: ((MessageId) -> Void)?
let actionsDisposable = DisposableSet()
let dataPromise = Promise<MessageStats?>(nil)
let messagesPromise = Promise<(SearchMessagesResult, SearchMessagesState)?>(nil)
var datacenterId: Int32 = 0
if let cachedData = cachedPeerData as? CachedChannelData {
datacenterId = cachedData.statsDatacenterId
}
let datacenterId: Int32 = statsDatacenterId ?? 0
let statsContext = MessageStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, messageId: messageId)
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) {
let _ = (context.account.postbox.transaction { transaction -> EngineMessage? in
return transaction.getMessage(id).flatMap(EngineMessage.init)
} |> deliverOnMainQueue).start(next: presentImpl)
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: id))
|> deliverOnMainQueue).start(next: presentImpl)
} else if let liveLocationManager = context.liveLocationManager {
let _ = (liveLocationManager.summaryManager.peersBroadcastingTo(peerId: peerId)
|> take(1)

View File

@ -325,18 +325,7 @@ private enum MultipartFetchSource {
return .fail(.revalidateMediaReference)
case .revalidate:
return .fail(.revalidateMediaReference)
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
case let .location(parsedLocation):
return download.request(Api.functions.upload.getFile(flags: 0, location: parsedLocation, offset: offset, limit: Int32(limit)), tag: tag, continueInBackground: continueInBackground)
|> mapError { error -> MultipartFetchDownloadError in
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)
}
}
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 typealias Result = [EngineMessage.Id: EngineMessage]

View File

@ -4,6 +4,29 @@ import Postbox
public typealias EngineExportedPeerInvitation = ExportedInvitation
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 {
public struct Peer: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = Optional<EnginePeer>
@ -101,7 +124,7 @@ public extension TelegramEngine.EngineData.Item {
}
public struct NotificationSettings: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = Optional<EnginePeer.NotificationSettings>
public typealias Result = EnginePeer.NotificationSettings
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
@ -121,7 +144,7 @@ public extension TelegramEngine.EngineData.Item {
preconditionFailure()
}
guard let notificationSettings = view.notificationSettings as? TelegramPeerNotificationSettings else {
return nil
return EnginePeer.NotificationSettings(TelegramPeerNotificationSettings.defaultSettings)
}
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 {
final class EngineData {
public struct Item {

View File

@ -366,5 +366,17 @@ public extension TelegramEngine {
}
}).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 {
init(_ muteState: PeerMuteState) {
switch muteState {
@ -495,3 +526,32 @@ public extension EngineRenderedPeer {
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)
|> map { peer in
return peer.flatMap(EnginePeer.init)
}
}
public func supportPeerId() -> Signal<PeerId?, NoError> {
@ -724,6 +727,31 @@ public extension TelegramEngine {
public func ensurePeerIsLocallyAvailable(peer: EnginePeer) -> Signal<EnginePeer.Id, NoError> {
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
}
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
} |> deliverOnMainQueue).start(next: { [weak self] message in
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else {
return
}
@ -1641,9 +1640,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
}
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { message in
guard let strongSelf = self, let message = message else {
return
@ -1690,7 +1687,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
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?
@ -1702,7 +1699,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
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
} else if let peer = message.peers[message.id.peerId] as? TelegramUser, peer.botInfo != nil {
botPeer = peer
@ -2525,9 +2522,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
strongSelf.commitPurposefulAction()
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
}
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { message in
guard let strongSelf = self, let message = message else {
return
@ -2608,9 +2603,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
if id.namespace == Namespaces.Message.ScheduledCloud {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in
return transaction.getMessageGroup(id) ?? []
} |> deliverOnMainQueue).start(next: { messages in
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.MessageGroup(id: id))
|> deliverOnMainQueue).start(next: { messages in
guard let strongSelf = self, let message = messages.filter({ $0.id == id }).first else {
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)
}, action: { [weak self] controller, f in
if let strongSelf = self {
strongSelf.interfaceInteraction?.deleteMessages(messages, controller, f)
strongSelf.interfaceInteraction?.deleteMessages(messages.map { $0._asMessage() }, controller, f)
}
})))
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.forEachController({ controller in
if let controller = controller as? TooltipScreen {
@ -2653,9 +2647,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.window?.presentInGlobalOverlay(controller)
})
} else {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in
return transaction.getMessageFailedGroup(id) ?? []
} |> deliverOnMainQueue).start(next: { messages in
let _ = (strongSelf.context.engine.messages.failedMessageGroup(id: id)
|> deliverOnMainQueue).start(next: { messages in
guard let strongSelf = self else {
return
}
@ -2666,9 +2659,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if groups[groupInfo.stableId] == nil {
groups[groupInfo.stableId] = []
}
groups[groupInfo.stableId]?.append(message)
groups[groupInfo.stableId]?.append(message._asMessage())
} else {
notGrouped.append(message)
notGrouped.append(message._asMessage())
}
}
@ -2856,9 +2849,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
}
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { message in
guard let message = message else {
return
@ -2957,9 +2948,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}, editScheduledMessagesTime: { [weak self] messageIds in
if let strongSelf = self, let messageId = messageIds.first {
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
} |> deliverOnMainQueue).start(next: { [weak self] message in
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else {
return
}
@ -3085,9 +3075,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
}
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { message in
guard let message = message else {
return
@ -3140,21 +3128,35 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.dismissAllTooltips()
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
guard let strongSelf = self, let peer = peer, peer.smallProfileImage != nil else {
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)
galleryController.setHintWillBePresentedInPreviewingContext(true)
let items: Signal<[ContextMenuItem], NoError> = context.account.postbox.transaction { transaction -> [ContextMenuItem] in
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
}
var items: [ContextMenuItem] = [
@ -3187,7 +3189,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if inputMode == .none {
inputMode = .text
}
return (chatTextInputAddMentionAttribute(current, peer: peer), inputMode)
return (chatTextInputAddMentionAttribute(current, peer: peer._asPeer()), inputMode)
}
}, delay: true)
})))
@ -3235,17 +3237,25 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
let _ = (context.account.postbox.transaction { transaction -> (MessageId, CachedPeerData?)? in
if let message = transaction.getMessage(id), let sourceMessageId = message.forwardInfo?.sourceMessageId {
return (sourceMessageId, transaction.getPeerCachedData(peerId: sourceMessageId.peerId))
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: id))
|> mapToSignal { message -> Signal<(EngineMessage.Id, Int32?)?, NoError> in
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 {
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
}
strongSelf.push(messageStatsController(context: context, messageId: id, cachedPeerData: cachedPeerData))
strongSelf.push(messageStatsController(context: context, messageId: id, statsDatacenterId: statsDatacenterId))
})
}, delay: true)
}, editMessageMedia: { [weak self] messageId, draw in
@ -3256,9 +3266,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.dismissInput()
if draw {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
} |> deliverOnMainQueue).start(next: { [weak self] message in
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else {
return
}
@ -6114,9 +6123,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
if let messageId = strongSelf.presentationInterfaceState.interfaceState.editMessage?.messageId {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
} |> deliverOnMainQueue).start(next: { message in
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { message in
guard let strongSelf = self, let editMessageState = strongSelf.presentationInterfaceState.editMessageState, case let .media(options) = editMessageState.content else {
return
}
@ -6124,10 +6132,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let message = message {
for media in message.media {
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 {
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
if let strongSelf = self, let selectedIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !selectedIds.isEmpty {
strongSelf.commitPurposefulAction()
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in
var messages: [Message] = []
for id in selectedIds {
if let message = transaction.getMessage(id) {
messages.append(message)
}
}
return messages
} |> deliverOnMainQueue).start(next: { messages in
let _ = (strongSelf.context.engine.data.get(EngineDataMap(
selectedIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
))
|> map { messages -> [EngineMessage] in
return messages.values.compactMap { $0 }
}
|> deliverOnMainQueue).start(next: { messages in
if let strongSelf = self, !messages.isEmpty {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) })
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in
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.present(shareController, in: .window(.root))
}
@ -8469,14 +8475,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self?.presentChatRequestAdminInfo()
}, displayCopyProtectionTip: { [weak self] node, save in
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
var messages: [EngineMessage] = []
for id in messageIds {
if let message = transaction.getMessage(id) {
messages.append(EngineMessage(message))
}
}
return messages
let _ = (strongSelf.context.engine.data.get(EngineDataMap(
messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
))
|> map { messages -> [EngineMessage] in
return messages.values.compactMap { $0 }
}
|> deliverOnMainQueue).start(next: { [weak self] messages in
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) {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in
return messageIds.compactMap(transaction.getMessage)
}
let _ = (self.context.engine.data.get(EngineDataMap(
messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
))
|> 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 {
let appLocale = presentationData.strings.baseLanguageCode
let signal: Signal<String?, NoError> = context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(message.id)
}
let signal: Signal<String?, NoError> = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: message.id))
|> mapToSignal { message -> Signal<String?, NoError> in
guard let message = message else {
return .single(nil)

View File

@ -842,7 +842,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
}
}
} 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
return (resourceStatus, nil)
}

View File

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

View File

@ -129,13 +129,16 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection
switch self.mode {
case let .chatSelection(_, selectedChats, additionalCategories, _):
let _ = (self.context.account.postbox.transaction { transaction -> [Peer] in
return selectedChats.compactMap(transaction.getPeer)
}
|> deliverOnMainQueue).start(next: { [weak self] peers in
let _ = (self.context.engine.data.get(
EngineDataList(
selectedChats.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 }
if let additionalCategories = additionalCategories {
for i in 0 ..< additionalCategories.categories.count {
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
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))
if strongSelf.isNodeLoaded {

View File

@ -58,11 +58,10 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer
self?.dismiss()
}, requestShare: { [weak self] messageId in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
} |> deliverOnMainQueue).start(next: { message in
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { message in
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 {
strongSelf.context.sharedContext.navigateToChat(accountId: strongSelf.context.account.id, peerId: message.id.peerId, messageId: message.id)
strongSelf.dismiss()
@ -70,16 +69,14 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer
}, externalShare: true)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
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
let _ = (strongSelf.context.engine.data.get(
EngineDataList(
peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
)
)
|> deliverOnMainQueue).start(next: { [weak self] peerList in
if let strongSelf = self {
let peers = peerList.compactMap { $0 }
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
@ -89,14 +86,14 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer
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)
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
} 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)
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.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
} 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
} else {
text = ""

View File

@ -1928,16 +1928,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let presentationData = strongSelf.presentationData
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
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] = []
let messageIds = [message.id]
if let peer = transaction.getPeer(message.id.peerId) {
if let peer = peer {
var personalPeerName: String?
var isChannel = false
if let user = peer as? TelegramUser {
if case let .user(user) = peer {
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
}
@ -2066,16 +2067,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
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
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] = []
let messageIds = [message.id]
if let peer = transaction.getPeer(message.id.peerId) {
if let peer = peer {
var personalPeerName: String?
var isChannel = false
if let user = peer as? TelegramUser {
if case let .user(user) = peer {
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
}
@ -2724,9 +2726,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
let context = strongSelf.context
let _ = (getUserPeer(postbox: strongSelf.context.account.postbox, peerId: peer.id)
|> mapToSignal { peer, _ -> Signal<Void, NoError> in
guard let peer = peer as? TelegramUser, let phone = peer.phone, !phone.isEmpty else {
let _ = (getUserPeer(engine: strongSelf.context.engine, peerId: peer.id)
|> mapToSignal { peer -> Signal<Void, NoError> in
guard case let .user(peer) = peer, let phone = peer.phone, !phone.isEmpty else {
return .complete()
}
return (context.sharedContext.contactDataManager?.basicDataForNormalizedPhoneNumber(DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phone))) ?? .single([]))
@ -3279,9 +3281,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
} |> deliverOnMainQueue).start(next: { [weak self] message in
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else {
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)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
var peers: [Peer] = []
for peerId in peerIds {
if let peer = transaction.getPeer(peerId) {
peers.append(peer)
}
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
}
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_ContactForwardTooltip_SavedMessages_One
savedMessages = true
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_ContactForwardTooltip_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_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 {
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_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 = ""
}
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() {
let peerId = self.peerId
let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, PeerId?) in
let peer = transaction.getPeer(peerId)
let filteredPeerIds = Array(transaction.getAssociatedPeerIds(peerId)).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 (peer, index.messageIndex.id.peerId)
} else {
return (peer, nil)
}
}
let _ = (combineLatest(
self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId)),
self.context.engine.peers.mostRecentSecretChat(id: self.peerId)
)
|> deliverOnMainQueue).start(next: { [weak self] peer, currentPeerId in
guard let strongSelf = self else {
return
}
if let controller = strongSelf.controller {
let displayTitle = peer.flatMap(EnginePeer.init)?.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 controller = strongSelf.controller else {
return
}
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 {
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
}
if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId)))
}
|> runOn(Queue.mainQueue())
|> delay(0.15, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start()
createSignal = createSignal
|> afterDisposed {
Queue.mainQueue().async {
progressDisposable.dispose()
}
}, error: { error in
guard let strongSelf = self else {
return
}
let createSecretChatDisposable = MetaDisposable()
cancelImpl = {
createSecretChatDisposable.set(nil)
let text: String
switch error {
case .limitExceeded:
text = strongSelf.presentationData.strings.TwoStepAuth_FloodError
default:
text = strongSelf.presentationData.strings.Login_UnknownError
}
createSecretChatDisposable.set((createSignal
|> deliverOnMainQueue).start(next: { peerId in
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))
}
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) {
let shareController = ShareController(context: self.context, subject: .url("https://t.me/\(value)"), updatedPresentationData: self.controller?.updatedPresentationData)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
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)
}
})
guard let strongSelf = self else {
return
}
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
if let strongSelf = self {
@ -4668,12 +4654,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func openPhone(value: String) {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in
let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self else {
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 dismissAction: () -> Void = { [weak actionSheet] in
actionSheet?.dismissAnimated()
@ -4704,12 +4690,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func editingOpenNotificationSettings() {
let peerId = self.peerId
let _ = (combineLatest(self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in
let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings
let globalSettings: GlobalNotificationSettings = transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications)?.get(GlobalNotificationSettings.self) ?? GlobalNotificationSettings.defaultSettings
return (peerSettings, globalSettings)
}, self.context.engine.peers.notificationSoundList())
let _ = (combineLatest(
self.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: self.peerId),
TelegramEngine.EngineData.Item.NotificationSettings.Global()
),
self.context.engine.peers.notificationSoundList()
)
|> deliverOnMainQueue).start(next: { [weak self] settings, notificationSoundList in
guard let strongSelf = self else {
return
@ -4717,11 +4704,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
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 {
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 {
return
}
@ -4741,18 +4728,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func editingOpenSoundSettings() {
let peerId = self.peerId
let _ = (self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in
let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings
let globalSettings: GlobalNotificationSettings = transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications)?.get(GlobalNotificationSettings.self) ?? GlobalNotificationSettings.defaultSettings
return (peerSettings, globalSettings)
}
let _ = (self.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: self.peerId),
TelegramEngine.EngineData.Item.NotificationSettings.Global()
)
|> deliverOnMainQueue).start(next: { [weak self] peerSettings, globalSettings in
guard let strongSelf = self else {
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 {
return
}
@ -4763,8 +4748,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func editingToggleShowMessageText(value: Bool) {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in
let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else {
return
}
@ -4784,8 +4769,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
guard let strongSelf = self else {
return
}
let _ = (getUserPeer(postbox: strongSelf.context.account.postbox, peerId: strongSelf.peerId)
|> deliverOnMainQueue).start(next: { peer, _ in
let _ = (getUserPeer(engine: strongSelf.context.engine, peerId: strongSelf.peerId)
|> deliverOnMainQueue).start(next: { peer in
guard let peer = peer, let strongSelf = self else {
return
}
@ -4885,8 +4870,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func openAddContact() {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in
let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else {
return
}
@ -4899,15 +4884,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
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)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else {
return
}
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())
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()
@ -4926,8 +4911,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let deleteChat = false
actionSheet.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.UserInfo_BlockConfirmationTitle(EnginePeer(peer).compactDisplayTitle).string),
ActionSheetButtonItem(title: presentationData.strings.UserInfo_BlockActionTitle(EnginePeer(peer).compactDisplayTitle).string, color: .destructive, action: {
ActionSheetTextItem(title: presentationData.strings.UserInfo_BlockConfirmationTitle(peer.compactDisplayTitle).string),
ActionSheetButtonItem(title: presentationData.strings.UserInfo_BlockActionTitle(peer.compactDisplayTitle).string, color: .destructive, action: {
dismissAction()
guard let strongSelf = self else {
return
@ -4951,9 +4936,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} else {
let text: String
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 {
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: {
guard let strongSelf = self else {
@ -5228,52 +5213,53 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func openShareBot() {
let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer, _ in
let _ = (getUserPeer(engine: self.context.engine, peerId: self.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self else {
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)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
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)
}
})
guard let strongSelf = self else {
return
}
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
if let strongSelf = self {
@ -5646,20 +5632,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func openDeletePeer() {
let peerId = self.peerId
let _ = (self.context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId))
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else {
return
}
var isGroup = false
if let channel = peer as? TelegramChannel {
if case let .channel(channel) = peer {
if case .group = channel.info {
isGroup = true
}
} else if peer is TelegramGroup {
} else if case .legacyGroup = peer {
isGroup = true
}
let presentationData = strongSelf.presentationData
@ -5683,7 +5666,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
ActionSheetTextItem(title: title),
ActionSheetButtonItem(title: text, color: .destructive, action: {
dismissAction()
self?.deletePeerChat(peer: peer, globally: true)
self?.deletePeerChat(peer: peer._asPeer(), globally: true)
}),
]),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
@ -5694,21 +5677,18 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func openLeavePeer(delete: Bool) {
let peerId = self.peerId
let _ = (self.context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId))
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else {
return
}
var isGroup = false
if let channel = peer as? TelegramChannel {
if case let .channel(channel) = peer {
if case .group = channel.info {
isGroup = true
}
} else if peer is TelegramGroup {
} else if case .legacyGroup = peer {
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: [
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: {
})
@ -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 {
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in
var messages: [Message] = []
for id in messageIds {
if let message = transaction.getMessage(id) {
messages.append(message)
}
}
return messages
}
|> deliverOnMainQueue).start(next: { messages in
let _ = (strongSelf.context.engine.data.get(EngineDataMap(
messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
))
|> deliverOnMainQueue).start(next: { messageMap in
let messages = messageMap.values.compactMap { $0 }
if let strongSelf = self, !messages.isEmpty {
strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil)
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in
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.controller?.present(shareController, in: .window(.root))
}
@ -7261,19 +7237,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}, completion: { _, _ in }), in: .window(.root))
}, displayCopyProtectionTip: { [weak self] node, save in
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
var messages: [EngineMessage] = []
for id in messageIds {
if let message = transaction.getMessage(id) {
messages.append(EngineMessage(message))
}
}
return messages
}
|> deliverOnMainQueue).start(next: { [weak self] messages in
let _ = (strongSelf.context.engine.data.get(EngineDataMap(
messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
))
|> deliverOnMainQueue).start(next: { [weak self] messageMap in
guard let strongSelf = self else {
return
}
let messages = messageMap.values.compactMap { $0 }
enum PeerType {
case group
case channel
@ -8104,19 +8075,20 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
return chatNavigationStack.compactMap(transaction.getPeer)
}
|> deliverOnMainQueue).start(next: { peers in
let _ = (strongSelf.context.engine.data.get(EngineDataList(
chatNavigationStack.map(TelegramEngine.EngineData.Item.Peer.Peer.init)
))
|> deliverOnMainQueue).start(next: { peerList in
guard let strongSelf = self, let backButtonNode = strongSelf.navigationBar?.backButtonNode else {
return
}
let peers = peerList.compactMap { $0 }
let avatarSize = CGSize(width: 28.0, height: 28.0)
var items: [ContextMenuItem] = []
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)
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> {
return postbox.transaction { transaction -> (Peer?, CachedPeerData?) in
guard let peer = transaction.getPeer(peerId) else {
return (nil, nil)
private func getUserPeer(engine: TelegramEngine, peerId: EnginePeer.Id) -> Signal<EnginePeer?, NoError> {
return engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> mapToSignal { peer -> Signal<EnginePeer?, NoError> in
guard let peer = peer else {
return .single(nil)
}
var resultPeer: Peer?
if let peer = peer as? TelegramSecretChat {
resultPeer = transaction.getPeer(peer.regularPeerId)
if case let .secretChat(secretChat) = peer {
return engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: secretChat.regularPeerId))
} 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):
switch self.messagesLocation {
case let .messages(chatLocation, tagMask, _):
let inputIndex: Signal<MessageIndex?, NoError>
var inputIndex: Signal<MessageIndex?, NoError>?
let looping = self.looping
switch self.order {
case .regular, .reversed:
inputIndex = .single(index)
case .random:
var playbackStack = self.playbackStack
inputIndex = self.context.account.postbox.transaction { transaction -> MessageIndex? in
if case let .random(previous) = navigation, previous {
let _ = playbackStack.pop()
while true {
if let id = playbackStack.pop() {
if let message = transaction.getMessage(id) {
return message.index
}
} else {
break
if case let .random(previous) = navigation, previous {
let _ = playbackStack.pop()
inner: while true {
if let id = playbackStack.pop() {
inputIndex = self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: id))
|> map { message in
return message?.index
}
break inner
} else {
break
}
}
}
if inputIndex == nil {
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 {
return nil
inputIndex = .single(nil)
}
}
}
let historySignal = inputIndex
let historySignal = (inputIndex ?? .single(nil))
|> mapToSignal { inputIndex -> Signal<(Message, [Message])?, NoError> in
guard let inputIndex = inputIndex else {
return .single(nil)

View File

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

View File

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

View File

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

View File

@ -517,9 +517,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
}
}
case let .peerId(peerId):
return context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in
if let peer = peer {
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):
return context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(messageId.peerId)
}
return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId))
|> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in
let foundPeer: Signal<Peer?, NoError>
let foundPeer: Signal<EnginePeer?, NoError>
if let peer = peer {
foundPeer = .single(peer)
} else {

View File

@ -388,18 +388,17 @@ final class WatchMediaHandler: WatchRequestHandler {
|> take(1)
|> mapToSignal({ context -> Signal<UIImage?, NoError> in
if let context = context {
return context.account.postbox.transaction { transaction -> Peer? in
guard let peer = transaction.getPeer(peerId) else {
return nil
}
if let peer = peer as? TelegramSecretChat {
return transaction.getPeer(peer.regularPeerId)
return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> mapToSignal { peer -> Signal<EnginePeer?, NoError> in
if let peer = peer, case let .secretChat(secretChat) = peer {
return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: secretChat.regularPeerId))
} 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 {
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 {
return imageData
|> map { data -> UIImage? in
@ -457,14 +456,12 @@ final class WatchMediaHandler: WatchRequestHandler {
}
}
} else if args.stickerPeerId != 0, let peerId = makePeerIdFromBridgeIdentifier(args.stickerPeerId) {
mediaSignal = context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.stickerMessageId))
}
mediaSignal = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.stickerMessageId)))
|> map { message -> (TelegramMediaFile, FileMediaReference)? in
if let message = message {
for media in message.media {
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
if let context = context, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) {
var roundVideo = false
return context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId))
}
return context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId)))
|> 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 updatedMediaReference: AnyMediaReference?
var candidateMediaReference: AnyMediaReference?
var imageDimensions: CGSize?
for media in message.media {
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())
candidateMediaReference = .message(message: MessageReference(message), media: media)
self.disposable.add(messageMediaImageInteractiveFetched(context: context, message: message._asMessage(), image: image, resource: resource, storeToDownloadsPeerType: nil).start())
candidateMediaReference = .message(message: MessageReference(message._asMessage()), media: media)
break
} else if let _ = media as? TelegramMediaFile {
candidateMediaReference = .message(message: MessageReference(message), media: media)
candidateMediaReference = .message(message: MessageReference(message._asMessage()), media: media)
break
} 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)
break
}
@ -664,14 +659,12 @@ final class WatchAudioHandler: WatchRequestHandler {
|> take(1)
|> mapToSignal({ context -> Signal<String, NoError> in
if let context = context, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) {
return context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId))
}
return context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId)))
|> mapToSignal { message -> Signal<String, NoError> in
if let message = message {
for media in message.media {
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)
|> mapToSignal({ data -> Signal<String, NoError> in
if let tempPath = manager.watchTemporaryStorePath, data.complete {