no message

This commit is contained in:
Peter Iakovlev 2018-03-20 16:08:15 +04:00
parent 3426ba2972
commit 5eeaed40c2
14 changed files with 190 additions and 132 deletions

View File

@ -101,7 +101,7 @@ public func ==(lhs: AuthorizedAccountState.State, rhs: AuthorizedAccountState.St
public class UnauthorizedAccount {
public let networkArguments: NetworkInitializationArguments
public let id: AccountRecordId
public let appGroupPath: String
public let rootPath: String
public let basePath: String
public let testingEnvironment: Bool
public let postbox: Postbox
@ -113,10 +113,10 @@ public class UnauthorizedAccount {
public let shouldBeServiceTaskMaster = Promise<AccountServiceTaskMasterMode>()
init(networkArguments: NetworkInitializationArguments, id: AccountRecordId, appGroupPath: String, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network, shouldKeepAutoConnection: Bool = true) {
init(networkArguments: NetworkInitializationArguments, id: AccountRecordId, rootPath: String, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network, shouldKeepAutoConnection: Bool = true) {
self.networkArguments = networkArguments
self.id = id
self.appGroupPath = appGroupPath
self.rootPath = rootPath
self.basePath = basePath
self.testingEnvironment = testingEnvironment
self.postbox = postbox
@ -150,7 +150,7 @@ public class UnauthorizedAccount {
} |> mapToSignal { (localizationSettings, proxySettings) -> Signal<UnauthorizedAccount, NoError> in
return initializedNetwork(arguments: self.networkArguments, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, basePath: self.basePath, testingEnvironment: self.testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings)
|> map { network in
let updated = UnauthorizedAccount(networkArguments: self.networkArguments, id: self.id, appGroupPath: self.appGroupPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
let updated = UnauthorizedAccount(networkArguments: self.networkArguments, id: self.id, rootPath: self.rootPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
updated.shouldBeServiceTaskMaster.set(self.shouldBeServiceTaskMaster.get())
return updated
}
@ -273,10 +273,10 @@ public enum AccountResult {
case authorized(Account)
}
public func accountWithId(networkArguments: NetworkInitializationArguments, id: AccountRecordId, supplementary: Bool, appGroupPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> {
public func accountWithId(networkArguments: NetworkInitializationArguments, id: AccountRecordId, supplementary: Bool, rootPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> {
let _ = declaredEncodables
let path = "\(appGroupPath)/\(accountRecordIdPathName(id))"
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
var initializeMessageNamespacesWithHoles: [(PeerId.Namespace, MessageId.Namespace)] = []
for peerNamespace in peerIdNamespacesWithInitialCloudMessageHoles {
@ -313,7 +313,7 @@ public func accountWithId(networkArguments: NetworkInitializationArguments, id:
case let unauthorizedState as UnauthorizedAccountState:
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings)
|> map { network -> AccountResult in
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
}
case let authorizedState as AuthorizedAccountState:
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings)
@ -327,7 +327,7 @@ public func accountWithId(networkArguments: NetworkInitializationArguments, id:
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings)
|> map { network -> AccountResult in
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
}
}
}

View File

@ -14,7 +14,34 @@ private enum AccountKind {
case unauthorized
}
public func currentAccount(networkArguments: NetworkInitializationArguments, supplementary: Bool, manager: AccountManager, appGroupPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<AccountResult?, NoError> {
public func rootPathForBasePath(_ appGroupPath: String) -> String {
return appGroupPath + "/telegram-data"
}
public func performAppGroupUpgrades(appGroupPath: String, rootPath: String) {
let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: rootPath), withIntermediateDirectories: true, attributes: nil)
do {
var resourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true
var mutableUrl = URL(fileURLWithPath: rootPath)
try mutableUrl.setResourceValues(resourceValues)
} catch let e {
print("\(e)")
}
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: appGroupPath), includingPropertiesForKeys: [], options: []) {
for url in files {
if url.lastPathComponent == "accounts-metadata" ||
url.lastPathComponent.hasSuffix("logs") ||
url.lastPathComponent.hasPrefix("account-") {
let _ = try? FileManager.default.moveItem(at: url, to: URL(fileURLWithPath: rootPath + "/" + url.lastPathComponent))
}
}
}
}
public func currentAccount(networkArguments: NetworkInitializationArguments, supplementary: Bool, manager: AccountManager, rootPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<AccountResult?, NoError> {
return manager.allocatedCurrentAccountId()
|> distinctUntilChanged(isEqual: { lhs, rhs in
return lhs == rhs
@ -23,7 +50,7 @@ public func currentAccount(networkArguments: NetworkInitializationArguments, sup
if let id = id {
let reload = ValuePromise<Bool>(true, ignoreRepeated: false)
return reload.get() |> mapToSignal { _ -> Signal<AccountResult?, NoError> in
return accountWithId(networkArguments: networkArguments, id: id, supplementary: supplementary, appGroupPath: appGroupPath, testingEnvironment: testingEnvironment, auxiliaryMethods: auxiliaryMethods)
return accountWithId(networkArguments: networkArguments, id: id, supplementary: supplementary, rootPath: rootPath, testingEnvironment: testingEnvironment, auxiliaryMethods: auxiliaryMethods)
|> mapToSignal { accountResult -> Signal<AccountResult?, NoError> in
let postbox: Postbox
let initialKind: AccountKind
@ -98,7 +125,7 @@ public func logoutFromAccount(id: AccountRecordId, accountManager: AccountManage
}
}
public func managedCleanupAccounts(networkArguments: NetworkInitializationArguments, accountManager: AccountManager, appGroupPath: String, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<Void, NoError> {
public func managedCleanupAccounts(networkArguments: NetworkInitializationArguments, accountManager: AccountManager, rootPath: String, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<Void, NoError> {
return Signal { subscriber in
let loggedOutAccounts = Atomic<[AccountRecordId: MetaDisposable]>(value: [:])
let disposable = accountManager.accountRecords().start(next: { view in
@ -114,7 +141,6 @@ public func managedCleanupAccounts(networkArguments: NetworkInitializationArgume
return false
}.map { $0.id })
var disposables = disposables
for id in disposables.keys {
@ -141,7 +167,22 @@ public func managedCleanupAccounts(networkArguments: NetworkInitializationArgume
disposable.dispose()
}
for (id, disposable) in beginList {
disposable.set(cleanupAccount(networkArguments: networkArguments, accountManager: accountManager, id: id, appGroupPath: appGroupPath, auxiliaryMethods: auxiliaryMethods).start())
disposable.set(cleanupAccount(networkArguments: networkArguments, accountManager: accountManager, id: id, rootPath: rootPath, auxiliaryMethods: auxiliaryMethods).start())
}
var validPaths = Set<String>()
for record in view.records {
validPaths.insert("\(accountRecordIdPathName(record.id))")
}
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: rootPath), includingPropertiesForKeys: [], options: []) {
for url in files {
if url.lastPathComponent.hasPrefix("account-") {
if !validPaths.contains(url.lastPathComponent) {
try? FileManager.default.removeItem(at: url)
}
}
}
}
})
@ -151,9 +192,8 @@ public func managedCleanupAccounts(networkArguments: NetworkInitializationArgume
}
}
private func cleanupAccount(networkArguments: NetworkInitializationArguments, accountManager: AccountManager, id: AccountRecordId, appGroupPath: String, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<Void, NoError> {
return accountWithId(networkArguments: networkArguments, id: id, supplementary: true, appGroupPath: appGroupPath, testingEnvironment: false, auxiliaryMethods: auxiliaryMethods)
private func cleanupAccount(networkArguments: NetworkInitializationArguments, accountManager: AccountManager, id: AccountRecordId, rootPath: String, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<Void, NoError> {
return accountWithId(networkArguments: networkArguments, id: id, supplementary: true, rootPath: rootPath, testingEnvironment: false, auxiliaryMethods: auxiliaryMethods)
|> mapToSignal { account -> Signal<Void, NoError> in
switch account {
case .upgrading:

View File

@ -7,40 +7,44 @@ import Foundation
import SwiftSignalKit
#endif
public func applyMaxReadIndexInteractively(postbox: Postbox, network: Network, stateManager: AccountStateManager, index: MessageIndex) -> Signal<Void, NoError> {
public func applyMaxReadIndexInteractively(postbox: Postbox, stateManager: AccountStateManager, index: MessageIndex) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Void in
let messageIds = modifier.applyInteractiveReadMaxIndex(index)
if index.id.peerId.namespace == Namespaces.Peer.SecretChat {
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
for id in messageIds {
if let message = modifier.getMessage(id) {
for attribute in message.attributes {
if let attribute = attribute as? AutoremoveTimeoutMessageAttribute {
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && !message.containsSecretMedia {
modifier.updateMessage(message.id, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
applyMaxReadIndexInteractively(modifier: modifier, stateManager: stateManager, index: index)
}
}
func applyMaxReadIndexInteractively(modifier: Modifier, stateManager: AccountStateManager, index: MessageIndex) {
let messageIds = modifier.applyInteractiveReadMaxIndex(index)
if index.id.peerId.namespace == Namespaces.Peer.SecretChat {
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
for id in messageIds {
if let message = modifier.getMessage(id) {
for attribute in message.attributes {
if let attribute = attribute as? AutoremoveTimeoutMessageAttribute {
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && !message.containsSecretMedia {
modifier.updateMessage(message.id, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
}
let updatedAttributes = currentMessage.attributes.map({ currentAttribute -> MessageAttribute in
if let currentAttribute = currentAttribute as? AutoremoveTimeoutMessageAttribute {
return AutoremoveTimeoutMessageAttribute(timeout: currentAttribute.timeout, countdownBeginTime: timestamp)
} else {
return currentAttribute
}
let updatedAttributes = currentMessage.attributes.map({ currentAttribute -> MessageAttribute in
if let currentAttribute = currentAttribute as? AutoremoveTimeoutMessageAttribute {
return AutoremoveTimeoutMessageAttribute(timeout: currentAttribute.timeout, countdownBeginTime: timestamp)
} else {
return currentAttribute
}
})
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: currentMessage.media))
})
modifier.addTimestampBasedMessageAttribute(tag: 0, timestamp: timestamp + attribute.timeout, messageId: id)
}
break
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: currentMessage.media))
})
modifier.addTimestampBasedMessageAttribute(tag: 0, timestamp: timestamp + attribute.timeout, messageId: id)
}
break
}
}
}
} else if index.id.peerId.namespace == Namespaces.Peer.CloudUser || index.id.peerId.namespace == Namespaces.Peer.CloudGroup || index.id.peerId.namespace == Namespaces.Peer.CloudChannel {
stateManager.notifyAppliedIncomingReadMessages([index.id])
}
} else if index.id.peerId.namespace == Namespaces.Peer.CloudUser || index.id.peerId.namespace == Namespaces.Peer.CloudGroup || index.id.peerId.namespace == Namespaces.Peer.CloudChannel {
stateManager.notifyAppliedIncomingReadMessages([index.id])
}
}

View File

@ -44,39 +44,45 @@ final class CachedStickerPack: PostboxCoding {
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200)
public func cachedStickerPack(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, NoError> {
return postbox.modify { modifier -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, NoError> in
public enum CachedStickerPackResult {
case none
case fetching
case result(StickerPackCollectionInfo, [ItemCollectionItem], Bool)
}
public func cachedStickerPack(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal<CachedStickerPackResult, NoError> {
return postbox.modify { modifier -> Signal<CachedStickerPackResult, NoError> in
let namespace = Namespaces.ItemCollection.CloudStickerPacks
if case let .id(id, _) = reference, let currentInfo = modifier.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = modifier.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
return .single((currentInfo, items, true))
return .single(.result(currentInfo, items, true))
} else {
let current: Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, NoError>
let current: Signal<CachedStickerPackResult, NoError>
var loadRemote = false
if case let .id(id, _) = reference, let cached = modifier.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id)))) as? CachedStickerPack, let info = cached.info {
current = .single((info, cached.items, false))
current = .single(.result(info, cached.items, false))
if cached.hash != info.hash {
loadRemote = true
}
} else {
current = .single(nil)
current = .single(.fetching)
loadRemote = true
}
var signal = current
if loadRemote {
let appliedRemote = remoteStickerPack(network: network, reference: reference)
|> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, NoError> in
return postbox.modify { modifier -> (StickerPackCollectionInfo, [ItemCollectionItem], Bool)? in
|> mapToSignal { result -> Signal<CachedStickerPackResult, NoError> in
return postbox.modify { modifier -> CachedStickerPackResult in
if let result = result {
modifier.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(result.0.id)), entry: CachedStickerPack(info: result.0, items: result.1.map { $0 as! StickerPackItem }, hash: result.0.hash), collectionSpec: collectionSpec)
let currentInfo = modifier.getItemCollectionInfo(collectionId: result.0.id) as? StickerPackCollectionInfo
return (result.0, result.1, currentInfo != nil)
return .result(result.0, result.1, currentInfo != nil)
} else {
return nil
return .none
}
}
}

View File

@ -165,6 +165,9 @@ public func collectCacheUsageStats(account: Account) -> Signal<CacheUsageStatsRe
for peerId in finalMedia.keys {
if let peer = modifier.getPeer(peerId) {
peers[peer.id] = peer
if let associatedPeerId = peer.associatedPeerId, let associatedPeer = modifier.getPeer(associatedPeerId) {
peers[associatedPeer.id] = associatedPeer
}
}
}
return CacheUsageStats(media: finalMedia, mediaResourceIds: finalMediaResourceIds, peers: peers, otherSize: otherSize, otherPaths: otherPaths, cacheSize: cacheSize, tempPaths: tempPaths, tempSize: tempSize)

View File

@ -7,10 +7,12 @@ import Foundation
import SwiftSignalKit
#endif
public func installInteractiveReadMessagesAction(postbox: Postbox, peerId: PeerId) -> Disposable {
public func installInteractiveReadMessagesAction(postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Disposable {
return postbox.installStoreMessageAction(peerId: peerId, { messages, modifier in
var consumeMessageIds: [MessageId] = []
var readMessageIndexByNamespace: [MessageId.Namespace: MessageIndex] = [:]
for message in messages {
if case let .Id(id) = message.id {
var hasUnconsumedMention = false
@ -29,6 +31,14 @@ public func installInteractiveReadMessagesAction(postbox: Postbox, peerId: PeerI
if hasUnconsumedMention && !hasUnconsumedContent {
consumeMessageIds.append(id)
}
if message.flags.contains(.Incoming) {
let index = MessageIndex(id: id, timestamp: message.timestamp)
let current = readMessageIndexByNamespace[id.namespace]
if current == nil || current! < index {
readMessageIndexByNamespace[id.namespace] = index
}
}
}
}
@ -46,5 +56,9 @@ public func installInteractiveReadMessagesAction(postbox: Postbox, peerId: PeerI
modifier.setPendingMessageAction(type: .consumeUnseenPersonalMessage, id: id, action: ConsumePersonalMessageAction())
}
for (_, index) in readMessageIndexByNamespace {
applyMaxReadIndexInteractively(modifier: modifier, stateManager: stateManager, index: index)
}
})
}

View File

@ -89,58 +89,13 @@ func remoteStickerPack(network: Network, reference: StickerPackReference) -> Sig
public func loadedStickerPack(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal<LoadedStickerPack, NoError> {
return cachedStickerPack(postbox: postbox, network: network, reference: reference)
|> map { result -> LoadedStickerPack in
if let result = result {
return .result(info: result.0, items: result.1, installed: result.2)
} else {
return .fetching
switch result {
case .none:
return .none
case .fetching:
return .fetching
case let .result(info, items, installed):
return .result(info: info, items: items, installed: installed)
}
}
}
private func loadedStickerPack1(account: Account, reference: StickerPackReference) -> Signal<LoadedStickerPack, NoError> {
return account.postbox.modify { modifier -> Signal<LoadedStickerPack, NoError> in
switch reference {
case let .id(id, _):
if let info = modifier.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: Namespaces.ItemCollection.CloudStickerPacks, id: id)) as? StickerPackCollectionInfo {
let items = modifier.getItemCollectionItems(collectionId: info.id)
return account.postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfo(id: info.id)])
|> map { view in
if let view = view.views[PostboxViewKey.itemCollectionInfo(id: info.id)] as? ItemCollectionInfoView, let info = view.info as? StickerPackCollectionInfo {
return .result(info: info, items: items, installed: true)
} else {
return .result(info: info, items: items, installed: false)
}
}
} else if let info = modifier.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: Namespaces.ItemCollection.CloudMaskPacks, id: id)) as? StickerPackCollectionInfo {
let items = modifier.getItemCollectionItems(collectionId: info.id)
return account.postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfo(id: info.id)])
|> map { view in
if let view = view.views[PostboxViewKey.itemCollectionInfo(id: info.id)] as? ItemCollectionInfoView, let info = view.info as? StickerPackCollectionInfo {
return .result(info: info, items: items, installed: true)
} else {
return .result(info: info, items: items, installed: false)
}
}
}
default:
break
}
let signal = remoteStickerPack(network: account.network, reference: reference) |> mapToSignal { result -> Signal<LoadedStickerPack, NoError> in
if let result = result {
return account.postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfo(id: result.0.id)])
|> map { view in
if let view = view.views[PostboxViewKey.itemCollectionInfo(id: result.0.id)] as? ItemCollectionInfoView, let info = view.info as? StickerPackCollectionInfo {
return .result(info: info, items: result.1, installed: true)
} else {
return .result(info: result.0, items: result.1, installed: false)
}
}
} else {
return .single(.none)
}
}
return .single(.fetching) |> then(signal)
} |> switchToLatest
}

View File

@ -27,8 +27,8 @@ public func peerSpecificStickerPack(postbox: Postbox, network: Network, peerId:
if let info = info.info {
return cachedStickerPack(postbox: postbox, network: network, reference: .id(id: info.id.id, accessHash: info.accessHash))
|> map { result -> (StickerPackCollectionInfo, [ItemCollectionItem])? in
if let result = result {
return (result.0, result.1)
if case let .result(info, items, _) = result {
return (info, items)
} else {
return nil
}

View File

@ -6,6 +6,24 @@ import Foundation
#endif
public extension Peer {
public func displayTitle(or defaultTitle: String) -> String {
switch self {
case let user as TelegramUser:
let name = user.name
if name.isEmpty {
return defaultTitle
} else {
return name
}
case let group as TelegramGroup:
return group.title
case let channel as TelegramChannel:
return channel.title
default:
return ""
}
}
public var displayTitle: String {
switch self {
case let user as TelegramUser:

View File

@ -675,23 +675,30 @@ public final class PendingMessageManager {
if updatedState != state {
modifier.setPeerChatState(message.id.peerId, state: updatedState)
}
modifier.updateMessage(message.id, update: { currentMessage in
var flags = StoreMessageFlags(message.flags)
if !flags.contains(.Failed) {
flags.insert(.Sending)
}
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
}
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: flags, tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: currentMessage.attributes, media: currentMessage.media))
})
} else if case .historyScreenshot = media.action {
sentAsAction = true
let updatedState = addSecretChatOutgoingOperation(modifier: modifier, peerId: message.id.peerId, operation: .screenshotMessages(layer: layer, actionGloballyUniqueId: message.globallyUniqueId!, globallyUniqueIds: []), state: state)
if updatedState != state {
modifier.setPeerChatState(message.id.peerId, state: updatedState)
}
}
break
}
}
if !sentAsAction {
if sentAsAction {
modifier.updateMessage(message.id, update: { currentMessage in
var flags = StoreMessageFlags(message.flags)
if !flags.contains(.Failed) {
flags.insert(.Sending)
}
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
}
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: flags, tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: currentMessage.attributes, media: currentMessage.media))
})
} else {
let updatedState = addSecretChatOutgoingOperation(modifier: modifier, peerId: message.id.peerId, operation: .sendMessage(layer: layer, id: message.id, file: secretFile), state: state)
if updatedState != state {
modifier.setPeerChatState(message.id.peerId, state: updatedState)

View File

@ -396,7 +396,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
} else if let resource = file.resource as? LocalFileReferenceMediaResource, let size = resource.size {
hintSize = Int(size)
}
if file.resource.headerSize != 0 {
if file.resource.headerSize != 0 && !file.isAnimated {
hintFileIsLarge = true
}
let upload = messageMediaPreuploadManager.upload(network: network, postbox: postbox, source: .resource(file.resource), encrypt: peerId.namespace == Namespaces.Peer.SecretChat, tag: TelegramMediaResourceFetchTag(statsCategory: statsCategoryForFileWithAttributes(file.attributes)), hintFileSize: hintSize, hintFileIsLarge: hintFileIsLarge)

View File

@ -97,7 +97,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
remoteSearchResult = account.network.request(Api.functions.messages.searchGlobal(q: query, offsetDate: 0, offsetPeer: Api.InputPeer.inputPeerEmpty, offsetId: 0, limit: 64), automaticFloodWait: false)
|> mapError { _ in } |> map(Optional.init)
}
let processedSearchResult = remoteSearchResult
|> mapToSignal { result -> Signal<[Message], NoError> in
guard let result = result else {

View File

@ -10,16 +10,26 @@ import Foundation
public func setSecretChatMessageAutoremoveTimeoutInteractively(account: Account, peerId: PeerId, timeout: Int32?) -> Signal<Void, NoError> {
return account.postbox.modify { modifier -> Void in
if let peer = modifier.getPeer(peerId) as? TelegramSecretChat, let state = modifier.getPeerChatState(peerId) as? SecretChatState {
let updatedPeer = peer.withUpdatedMessageAutoremoveTimeout(timeout)
let updatedState = state.withUpdatedMessageAutoremoveTimeout(timeout)
if !updatedPeer.isEqual(peer) {
updatePeers(modifier: modifier, peers: [updatedPeer], update: { $1 })
if state.messageAutoremoveTimeout != timeout {
let updatedPeer = peer.withUpdatedMessageAutoremoveTimeout(timeout)
let updatedState = state.withUpdatedMessageAutoremoveTimeout(timeout)
if !updatedPeer.isEqual(peer) {
updatePeers(modifier: modifier, peers: [updatedPeer], update: { $1 })
}
if updatedState != state {
modifier.setPeerChatState(peerId, state: updatedState)
}
let _ = enqueueMessages(modifier: modifier, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(timeout == nil ? 0 : timeout!)), replyToMessageId: nil, localGroupingKey: nil))])
}
if updatedState != state {
modifier.setPeerChatState(peerId, state: updatedState)
}
enqueueMessages(modifier: modifier, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(timeout == nil ? 0 : timeout!)), replyToMessageId: nil, localGroupingKey: nil))])
}
}
}
public func addSecretChatMessageScreenshot(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.modify { modifier -> Void in
if let peer = modifier.getPeer(peerId) as? TelegramSecretChat, let state = modifier.getPeerChatState(peerId) as? SecretChatState {
let _ = enqueueMessages(modifier: modifier, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot), replyToMessageId: nil, localGroupingKey: nil))])
}
}
}

View File

@ -451,7 +451,8 @@ static NSArray *GEO_MOBILE_COUNTRIES;
- (NSDictionary *)DIGIT_MAPPINGS
{
if (!DIGIT_MAPPINGS) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
DIGIT_MAPPINGS = [NSDictionary dictionaryWithObjectsAndKeys:
@"0", @"0", @"1", @"1", @"2", @"2", @"3", @"3", @"4", @"4", @"5", @"5", @"6", @"6", @"7", @"7", @"8", @"8", @"9", @"9",
// Fullwidth digit 0 to 9
@ -460,7 +461,7 @@ static NSArray *GEO_MOBILE_COUNTRIES;
@"0", @"\u0660", @"1", @"\u0661", @"2", @"\u0662", @"3", @"\u0663", @"4", @"\u0664", @"5", @"\u0665", @"6", @"\u0666", @"7", @"\u0667", @"8", @"\u0668", @"9", @"\u0669",
// Eastern-Arabic digit 0 to 9
@"0", @"\u06F0", @"1", @"\u06F1", @"2", @"\u06F2", @"3", @"\u06F3", @"4", @"\u06F4", @"5", @"\u06F5", @"6", @"\u06F6", @"7", @"\u06F7", @"8", @"\u06F8", @"9", @"\u06F9", nil];
}
});
return DIGIT_MAPPINGS;
}