mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Quick fixes
This commit is contained in:
parent
4f466f0f69
commit
e8ff8c875b
@ -229,7 +229,6 @@ static int32_t fixedTimeDifferenceValue = 0;
|
||||
_useTempAuthKeys = useTempAuthKeys;
|
||||
#if DEBUG
|
||||
_tempKeyExpiration = 1 * 60 * 60;
|
||||
_tempKeyExpiration = 5;
|
||||
#else
|
||||
_tempKeyExpiration = 24 * 60 * 60;
|
||||
#endif
|
||||
|
@ -1105,7 +1105,7 @@ func debugRestoreState(basePath:String, name: String) {
|
||||
|
||||
private let sharedQueue = Queue(name: "org.telegram.postbox.Postbox")
|
||||
|
||||
public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<PostboxResult, NoError> {
|
||||
public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, encryptionParameters: ValueBoxEncryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32) -> Signal<PostboxResult, NoError> {
|
||||
let queue = sharedQueue
|
||||
return Signal { subscriber in
|
||||
queue.async {
|
||||
@ -1177,7 +1177,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
let endTime = CFAbsoluteTimeGetCurrent()
|
||||
print("Postbox load took \((endTime - startTime) * 1000.0) ms")
|
||||
|
||||
subscriber.putNext(.postbox(Postbox(queue: queue, basePath: basePath, seedConfiguration: seedConfiguration, valueBox: valueBox)))
|
||||
subscriber.putNext(.postbox(Postbox(queue: queue, basePath: basePath, seedConfiguration: seedConfiguration, valueBox: valueBox, timestampForAbsoluteTimeBasedOperations: timestampForAbsoluteTimeBasedOperations)))
|
||||
subscriber.putCompletion()
|
||||
break
|
||||
}
|
||||
@ -1330,7 +1330,7 @@ public final class Postbox {
|
||||
|
||||
var installedMessageActionsByPeerId: [PeerId: Bag<([StoreMessage], Transaction) -> Void>] = [:]
|
||||
|
||||
init(queue: Queue, basePath: String, seedConfiguration: SeedConfiguration, valueBox: SqliteValueBox) {
|
||||
init(queue: Queue, basePath: String, seedConfiguration: SeedConfiguration, valueBox: SqliteValueBox, timestampForAbsoluteTimeBasedOperations: Int32) {
|
||||
assert(queue.isCurrent())
|
||||
|
||||
let startTime = CFAbsoluteTimeGetCurrent()
|
||||
@ -1534,6 +1534,9 @@ public final class Postbox {
|
||||
for id in self.messageHistoryUnsentTable.get() {
|
||||
transaction.updateMessage(id, update: { message in
|
||||
if !message.flags.contains(.Failed) {
|
||||
if message.timestamp + 60 * 10 > timestampForAbsoluteTimeBasedOperations {
|
||||
return .skip
|
||||
}
|
||||
var flags = StoreMessageFlags(message.flags)
|
||||
flags.remove(.Unsent)
|
||||
flags.remove(.Sending)
|
||||
|
@ -1,3 +1,4 @@
|
||||
import Foundation
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
|
||||
@ -67,7 +68,7 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
||||
|
||||
public func accountTransaction<T>(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, transaction: @escaping (Transaction) -> T) -> Signal<T, NoError> {
|
||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters)
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970))
|
||||
return postbox
|
||||
|> mapToSignal { value -> Signal<T, NoError> in
|
||||
switch value {
|
||||
|
@ -160,7 +160,7 @@ public enum AccountPreferenceEntriesResult {
|
||||
|
||||
public func accountPreferenceEntries(rootPath: String, id: AccountRecordId, keys: Set<ValueBoxKey>, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountPreferenceEntriesResult, NoError> {
|
||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters)
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970))
|
||||
return postbox
|
||||
|> mapToSignal { value -> Signal<AccountPreferenceEntriesResult, NoError> in
|
||||
switch value {
|
||||
@ -187,7 +187,7 @@ public enum AccountNoticeEntriesResult {
|
||||
|
||||
public func accountNoticeEntries(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountNoticeEntriesResult, NoError> {
|
||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters)
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970))
|
||||
return postbox
|
||||
|> mapToSignal { value -> Signal<AccountNoticeEntriesResult, NoError> in
|
||||
switch value {
|
||||
@ -208,7 +208,7 @@ public enum LegacyAccessChallengeDataResult {
|
||||
|
||||
public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<LegacyAccessChallengeDataResult, NoError> {
|
||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters)
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970))
|
||||
return postbox
|
||||
|> mapToSignal { value -> Signal<LegacyAccessChallengeDataResult, NoError> in
|
||||
switch value {
|
||||
@ -225,7 +225,7 @@ public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecord
|
||||
public func accountWithId(accountManager: AccountManager, networkArguments: NetworkInitializationArguments, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, backupData: AccountBackupData?, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> {
|
||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters)
|
||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970))
|
||||
|
||||
return postbox
|
||||
|> mapToSignal { result -> Signal<AccountResult, NoError> in
|
||||
|
@ -209,7 +209,7 @@ public func temporaryAccount(manager: AccountManager, rootPath: String, encrypti
|
||||
return manager.allocatedTemporaryAccountId()
|
||||
|> mapToSignal { id -> Signal<TemporaryAccount, NoError> in
|
||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||
return openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters)
|
||||
return openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970))
|
||||
|> mapToSignal { result -> Signal<TemporaryAccount, NoError> in
|
||||
switch result {
|
||||
case .upgrading:
|
||||
|
@ -291,6 +291,7 @@ public final class AccountViewTracker {
|
||||
private var seenLiveLocationDisposables = DisposableDict<Int32>()
|
||||
|
||||
private var updatedUnsupportedMediaMessageIdsAndTimestamps: [MessageId: Int32] = [:]
|
||||
private var refreshSecretChatMediaMessageIdsAndTimestamps: [MessageId: Int32] = [:]
|
||||
private var nextUpdatedUnsupportedMediaDisposableId: Int32 = 0
|
||||
private var updatedUnsupportedMediaDisposables = DisposableDict<Int32>()
|
||||
|
||||
@ -631,6 +632,18 @@ public final class AccountViewTracker {
|
||||
|> runOn(self.queue)
|
||||
}
|
||||
|
||||
public func updateReplyInfoForMessageId(_ id: MessageId, info: UpdatedMessageReplyInfo) {
|
||||
self.queue.async { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let current = strongSelf.updatedViewCountMessageIdsAndTimestamps[id] else {
|
||||
return
|
||||
}
|
||||
strongSelf.updatedViewCountMessageIdsAndTimestamps[id] = ViewCountContextState(timestamp: Int32(CFAbsoluteTimeGetCurrent()), clientId: current.clientId, result: ViewCountContextState.ReplyInfo(commentsPeerId: info.commentsPeerId, maxReadIncomingMessageId: info.maxReadIncomingMessageId, maxMessageId: info.maxMessageId))
|
||||
}
|
||||
}
|
||||
|
||||
public func updateViewCountForMessageIds(messageIds: Set<MessageId>, clientId: Int32) {
|
||||
self.queue.async {
|
||||
var addedMessageIds: [MessageId] = []
|
||||
@ -1037,6 +1050,98 @@ public final class AccountViewTracker {
|
||||
}
|
||||
}
|
||||
|
||||
public func refreshSecretMediaMediaForMessageIds(messageIds: Set<MessageId>) {
|
||||
self.queue.async {
|
||||
var addedMessageIds: [MessageId] = []
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent())
|
||||
for messageId in messageIds {
|
||||
let messageTimestamp = self.refreshSecretChatMediaMessageIdsAndTimestamps[messageId]
|
||||
if messageTimestamp == nil {
|
||||
self.refreshSecretChatMediaMessageIdsAndTimestamps[messageId] = timestamp
|
||||
addedMessageIds.append(messageId)
|
||||
}
|
||||
}
|
||||
if !addedMessageIds.isEmpty {
|
||||
for (_, messageIds) in messagesIdsGroupedByPeerId(Set(addedMessageIds)) {
|
||||
let disposableId = self.nextUpdatedUnsupportedMediaDisposableId
|
||||
self.nextUpdatedUnsupportedMediaDisposableId += 1
|
||||
|
||||
if let account = self.account {
|
||||
let signal = account.postbox.transaction { transaction -> [TelegramMediaFile] in
|
||||
var result: [TelegramMediaFile] = []
|
||||
for id in messageIds {
|
||||
if let message = transaction.getMessage(id) {
|
||||
for media in message.media {
|
||||
if let file = media as? TelegramMediaFile, file.isAnimatedSticker {
|
||||
result.append(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|> mapToSignal { files -> Signal<Void, NoError> in
|
||||
guard !files.isEmpty else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var stickerPacks = Set<StickerPackReference>()
|
||||
for file in files {
|
||||
for attribute in file.attributes {
|
||||
if case let .Sticker(_, packReferenceValue, _) = attribute, let packReference = packReferenceValue {
|
||||
if case .id = packReference {
|
||||
stickerPacks.insert(packReference)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var requests: [Signal<Api.messages.StickerSet?, NoError>] = []
|
||||
for reference in stickerPacks {
|
||||
if case let .id(id, accessHash) = reference {
|
||||
requests.append(account.network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(id: id, accessHash: accessHash)))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.StickerSet?, NoError> in
|
||||
return .single(nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
if requests.isEmpty {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
return combineLatest(requests)
|
||||
|> mapToSignal { results -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
for result in results {
|
||||
switch result {
|
||||
case let .stickerSet(_, _, documents):
|
||||
for document in documents {
|
||||
if let file = telegramMediaFileFromApiDocument(document) {
|
||||
if transaction.getMedia(file.fileId) != nil {
|
||||
let _ = transaction.updateMedia(file.fileId, update: file)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|> afterDisposed { [weak self] in
|
||||
self?.queue.async {
|
||||
self?.updatedUnsupportedMediaDisposables.set(nil, forKey: disposableId)
|
||||
}
|
||||
}
|
||||
self.updatedUnsupportedMediaDisposables.set(signal.start(), forKey: disposableId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func updateMarkAllMentionsSeen(peerId: PeerId) {
|
||||
self.queue.async {
|
||||
guard let account = self.account else {
|
||||
|
@ -130,6 +130,21 @@ private func requestActivity(postbox: Postbox, network: Network, accountPeerId:
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
return .complete()
|
||||
}
|
||||
if let _ = peer as? TelegramUser {
|
||||
if let presence = transaction.getPeerPresence(peerId: peerId) as? TelegramUserPresence {
|
||||
switch presence.status {
|
||||
case .none, .recently, .lastWeek, .lastMonth:
|
||||
return .complete()
|
||||
case let .present(statusTimestamp):
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
if statusTimestamp < timestamp {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
if let inputPeer = apiInputPeer(peer) {
|
||||
var flags: Int32 = 0
|
||||
|
@ -145,10 +145,12 @@ private class ReplyThreadHistoryContextImpl {
|
||||
}
|
||||
|
||||
var channelMessageId: MessageId?
|
||||
var replyThreadAttribute: ReplyThreadMessageAttribute?
|
||||
for attribute in topMessage.attributes {
|
||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||
channelMessageId = attribute.messageId
|
||||
break
|
||||
} else if let attribute = attribute as? ReplyThreadMessageAttribute {
|
||||
replyThreadAttribute = attribute
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,14 +197,41 @@ private class ReplyThreadHistoryContextImpl {
|
||||
}
|
||||
}
|
||||
|
||||
let maxReadIncomingMessageId = readInboxMaxId.flatMap { readMaxId in
|
||||
MessageId(peerId: parsedIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId)
|
||||
}
|
||||
|
||||
if let channelMessageId = channelMessageId, let replyThreadAttribute = replyThreadAttribute {
|
||||
account.viewTracker.updateReplyInfoForMessageId(channelMessageId, info: AccountViewTracker.UpdatedMessageReplyInfo(
|
||||
timestamp: Int32(CFAbsoluteTimeGetCurrent()),
|
||||
commentsPeerId: parsedIndex.id.peerId,
|
||||
maxReadIncomingMessageId: maxReadIncomingMessageId,
|
||||
maxMessageId: resolvedMaxMessage
|
||||
))
|
||||
|
||||
transaction.updateMessage(channelMessageId, update: { currentMessage in
|
||||
var attributes = currentMessage.attributes
|
||||
loop: for j in 0 ..< attributes.count {
|
||||
if let attribute = attributes[j] as? ReplyThreadMessageAttribute {
|
||||
attributes[j] = ReplyThreadMessageAttribute(
|
||||
count: replyThreadAttribute.count,
|
||||
latestUsers: attribute.latestUsers,
|
||||
commentsPeerId: attribute.commentsPeerId,
|
||||
maxMessageId: replyThreadAttribute.maxMessageId,
|
||||
maxReadMessageId: replyThreadAttribute.maxReadMessageId
|
||||
)
|
||||
}
|
||||
}
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init), authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
|
||||
})
|
||||
}
|
||||
|
||||
return .single(DiscussionMessage(
|
||||
messageId: parsedIndex.id,
|
||||
channelMessageId: channelMessageId,
|
||||
isChannelPost: isChannelPost,
|
||||
maxMessage: resolvedMaxMessage,
|
||||
maxReadIncomingMessageId: readInboxMaxId.flatMap { readMaxId in
|
||||
MessageId(peerId: parsedIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId)
|
||||
},
|
||||
maxReadIncomingMessageId: maxReadIncomingMessageId,
|
||||
maxReadOutgoingMessageId: readOutboxMaxId.flatMap { readMaxId in
|
||||
MessageId(peerId: parsedIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId)
|
||||
}
|
||||
|
@ -3068,6 +3068,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
})
|
||||
|
||||
var wasInForeground = true
|
||||
self.applicationInForegroundDisposable = (context.sharedContext.applicationBindings.applicationInForeground
|
||||
|> distinctUntilChanged
|
||||
|> deliverOn(Queue.mainQueue())).start(next: { [weak self] value in
|
||||
@ -3077,7 +3078,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.raiseToListen?.applicationResignedActive()
|
||||
|
||||
strongSelf.stopMediaRecorder()
|
||||
} else {
|
||||
if !wasInForeground {
|
||||
strongSelf.chatDisplayNode.recursivelyEnsureDisplaySynchronously(true)
|
||||
}
|
||||
}
|
||||
wasInForeground = value
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -514,6 +514,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
private let messageReactionsProcessingManager = ChatMessageThrottledProcessingManager()
|
||||
private let seenLiveLocationProcessingManager = ChatMessageThrottledProcessingManager()
|
||||
private let unsupportedMessageProcessingManager = ChatMessageThrottledProcessingManager()
|
||||
private let refreshMediaProcessingManager = ChatMessageThrottledProcessingManager()
|
||||
private let messageMentionProcessingManager = ChatMessageThrottledProcessingManager(delay: 0.2)
|
||||
let prefetchManager: InChatPrefetchManager
|
||||
private var currentEarlierPrefetchMessages: [(Message, Media)] = []
|
||||
@ -605,6 +606,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
self.unsupportedMessageProcessingManager.process = { [weak context] messageIds in
|
||||
context?.account.viewTracker.updateUnsupportedMediaForMessageIds(messageIds: messageIds)
|
||||
}
|
||||
self.refreshMediaProcessingManager.process = { [weak context] messageIds in
|
||||
context?.account.viewTracker.refreshSecretMediaMediaForMessageIds(messageIds: messageIds)
|
||||
}
|
||||
self.messageMentionProcessingManager.process = { [weak context] messageIds in
|
||||
context?.account.viewTracker.updateMarkMentionsSeenForMessageIds(messageIds: messageIds)
|
||||
}
|
||||
@ -1174,6 +1178,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
var messageIdsWithUpdateableReactions: [MessageId] = []
|
||||
var messageIdsWithLiveLocation: [MessageId] = []
|
||||
var messageIdsWithUnsupportedMedia: [MessageId] = []
|
||||
var messageIdsWithRefreshMedia: [MessageId] = []
|
||||
var messageIdsWithUnseenPersonalMention: [MessageId] = []
|
||||
var messagesWithPreloadableMediaToEarlier: [(Message, Media)] = []
|
||||
var messagesWithPreloadableMediaToLater: [(Message, Media)] = []
|
||||
@ -1192,6 +1197,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
}
|
||||
}
|
||||
var contentRequiredValidation = false
|
||||
var mediaRequiredValidation = false
|
||||
for attribute in message.attributes {
|
||||
if attribute is ViewCountMessageAttribute {
|
||||
if message.id.namespace == Namespaces.Message.Cloud {
|
||||
@ -1218,6 +1224,24 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
}
|
||||
} else if let _ = media as? TelegramMediaAction {
|
||||
isAction = true
|
||||
} else if let telegramFile = media as? TelegramMediaFile {
|
||||
if telegramFile.isAnimatedSticker, (message.id.peerId.namespace == Namespaces.Peer.SecretChat || !telegramFile.previewRepresentations.isEmpty), let size = telegramFile.size, size > 0 && size <= 128 * 1024 {
|
||||
if message.id.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
if telegramFile.fileId.namespace == Namespaces.Media.CloudFile {
|
||||
var isValidated = false
|
||||
attributes: for attribute in telegramFile.attributes {
|
||||
if case .hintIsValidated = attribute {
|
||||
isValidated = true
|
||||
break attributes
|
||||
}
|
||||
}
|
||||
|
||||
if !isValidated {
|
||||
mediaRequiredValidation = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !isAction && message.id.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
@ -1226,6 +1250,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
if contentRequiredValidation {
|
||||
messageIdsWithUnsupportedMedia.append(message.id)
|
||||
}
|
||||
if mediaRequiredValidation {
|
||||
messageIdsWithRefreshMedia.append(message.id)
|
||||
}
|
||||
if hasUnconsumedMention && !hasUnconsumedContent {
|
||||
messageIdsWithUnseenPersonalMention.append(message.id)
|
||||
}
|
||||
@ -1346,6 +1373,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
if !messageIdsWithUnsupportedMedia.isEmpty {
|
||||
self.unsupportedMessageProcessingManager.add(messageIdsWithUnsupportedMedia)
|
||||
}
|
||||
if !messageIdsWithRefreshMedia.isEmpty {
|
||||
self.refreshMediaProcessingManager.add(messageIdsWithRefreshMedia)
|
||||
}
|
||||
if !messageIdsWithUnseenPersonalMention.isEmpty {
|
||||
self.messageMentionProcessingManager.add(messageIdsWithUnseenPersonalMention)
|
||||
}
|
||||
|
@ -1056,7 +1056,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
||||
} else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty && !isPreview {
|
||||
replyMarkup = attribute
|
||||
} else if let attribute = attribute as? AuthorSignatureMessageAttribute {
|
||||
if firstMessage.author is TelegramChannel, !attribute.signature.isEmpty {
|
||||
if let chatPeer = firstMessage.peers[firstMessage.id.peerId] as? TelegramChannel, case .group = chatPeer.info, firstMessage.author is TelegramChannel, !attribute.signature.isEmpty {
|
||||
authorRank = .custom(attribute.signature)
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import PresentationDataUtils
|
||||
import SearchUI
|
||||
import TelegramPermissionsUI
|
||||
import AppBundle
|
||||
import DeviceAccess
|
||||
|
||||
public class ComposeController: ViewController {
|
||||
private let context: AccountContext
|
||||
@ -183,6 +184,42 @@ public class ComposeController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
self.contactsNode.openCreateContact = { [weak self] in
|
||||
let _ = (DeviceAccess.authorizationStatus(subject: .contacts)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { status in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
switch status {
|
||||
case .allowed:
|
||||
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: "", lastName: "", phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!<Mobile>!$_", value: "+")]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
|
||||
(strongSelf.navigationController as? NavigationController)?.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let peer = peer {
|
||||
DispatchQueue.main.async {
|
||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(strongSelf.navigationController as? NavigationController)?.replaceAllButRootController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil), animated: true)
|
||||
}
|
||||
}), completed: nil, cancelled: nil))
|
||||
case .notDetermined:
|
||||
DeviceAccess.authorizeAccess(to: .contacts)
|
||||
default:
|
||||
let presentationData = strongSelf.presentationData
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.AccessDenied_Title, text: presentationData.strings.Contacts_AccessDeniedError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
self?.context.sharedContext.applicationBindings.openSettings()
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.contactsNode.openCreateNewChannel = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
@ -27,6 +27,7 @@ final class ComposeControllerNode: ASDisplayNode {
|
||||
|
||||
var openCreateNewGroup: (() -> Void)?
|
||||
var openCreateNewSecretChat: (() -> Void)?
|
||||
var openCreateContact: (() -> Void)?
|
||||
var openCreateNewChannel: (() -> Void)?
|
||||
|
||||
private var presentationData: PresentationData
|
||||
@ -39,14 +40,15 @@ final class ComposeControllerNode: ASDisplayNode {
|
||||
|
||||
var openCreateNewGroupImpl: (() -> Void)?
|
||||
var openCreateNewSecretChatImpl: (() -> Void)?
|
||||
var openCreateContactImpl: (() -> Void)?
|
||||
var openCreateNewChannelImpl: (() -> Void)?
|
||||
|
||||
self.contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: [
|
||||
ContactListAdditionalOption(title: self.presentationData.strings.Compose_NewGroup, icon: .generic(UIImage(bundleImageName: "Contact List/CreateGroupActionIcon")!), action: {
|
||||
openCreateNewGroupImpl?()
|
||||
}),
|
||||
ContactListAdditionalOption(title: self.presentationData.strings.Compose_NewEncryptedChat, icon: .generic(UIImage(bundleImageName: "Contact List/CreateSecretChatActionIcon")!), action: {
|
||||
openCreateNewSecretChatImpl?()
|
||||
ContactListAdditionalOption(title: self.presentationData.strings.NewContact_Title, icon: .generic(UIImage(bundleImageName: "Contact List/AddMemberIcon")!), action: {
|
||||
openCreateContactImpl?()
|
||||
}),
|
||||
ContactListAdditionalOption(title: self.presentationData.strings.Compose_NewChannel, icon: .generic(UIImage(bundleImageName: "Contact List/CreateChannelActionIcon")!), action: {
|
||||
openCreateNewChannelImpl?()
|
||||
@ -69,6 +71,10 @@ final class ComposeControllerNode: ASDisplayNode {
|
||||
openCreateNewSecretChatImpl = { [weak self] in
|
||||
self?.openCreateNewSecretChat?()
|
||||
}
|
||||
openCreateContactImpl = { [weak self] in
|
||||
self?.contactListNode.listNode.clearHighlightAnimated(true)
|
||||
self?.openCreateContact?()
|
||||
}
|
||||
openCreateNewChannelImpl = { [weak self] in
|
||||
self?.openCreateNewChannel?()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user