no message

This commit is contained in:
Peter
2017-03-28 21:45:26 +03:00
parent c55a138e0b
commit 71ff550bcc
12 changed files with 216 additions and 264 deletions

View File

@@ -243,6 +243,8 @@
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */; };
D0561DEA1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */; };
D0561DEB1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */; };
D058E0D11E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */; };
D058E0D21E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */; };
D05A32E11E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */; };
D05A32E21E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */; };
D05A32E41E6F0B2E002760B4 /* RecentAccountSessions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E31E6F0B2E002760B4 /* RecentAccountSessions.swift */; };
@@ -624,6 +626,7 @@
D05452061E7B5093006EEF19 /* LoadedStickerPack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedStickerPack.swift; sourceTree = "<group>"; };
D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatePeerInfo.swift; sourceTree = "<group>"; };
D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelAdmins.swift; sourceTree = "<group>"; };
D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StandaloneSendMessage.swift; sourceTree = "<group>"; };
D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatedAccountPrivacySettings.swift; sourceTree = "<group>"; };
D05A32E31E6F0B2E002760B4 /* RecentAccountSessions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentAccountSessions.swift; sourceTree = "<group>"; };
D05A32E61E6F0B5C002760B4 /* RecentAccountSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentAccountSession.swift; sourceTree = "<group>"; };
@@ -1013,6 +1016,7 @@
D0E23DD91E806F7700B9B6D2 /* ManagedSynchronizeMarkFeaturedStickerPacksAsSeenOperations.swift */,
D0F3A89E1E82C65400B4C64C /* SynchronizeChatInputStateOperation.swift */,
D0F3A8A11E82C65E00B4C64C /* ManagedSynchronizeChatInputStateOperations.swift */,
D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */,
);
name = State;
sourceTree = "<group>";
@@ -1642,6 +1646,7 @@
D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */,
D049EAF51E44DF3300A2CD3A /* AccountState.swift in Sources */,
D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */,
D058E0D11E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */,
D0BC38751E40A7F70044D6FE /* RemovePeerChat.swift in Sources */,
D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */,
D05A32E41E6F0B2E002760B4 /* RecentAccountSessions.swift in Sources */,
@@ -1881,6 +1886,7 @@
D0F7B1E41E045C7B007EB8A5 /* InstantPage.swift in Sources */,
D03E5E0D1E55E02D0029569A /* LoggedOutAccountAttribute.swift in Sources */,
D0B418AD1D7E0597004562A4 /* Serialization.swift in Sources */,
D058E0D21E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */,
D03C536F1DAD5CA9004C17B3 /* BotInfo.swift in Sources */,
D0FA8BBA1E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
D033FEB41E61F3C000644997 /* ReportPeer.swift in Sources */,

View File

@@ -145,7 +145,7 @@ public class UnauthorizedAccount {
postbox.removeKeychainEntryForKey(key)
})
return initializedNetwork(apiId: self.apiId, datacenterId: Int(masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: self.basePath), testingEnvironment: self.testingEnvironment)
return initializedNetwork(apiId: self.apiId, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: self.basePath), testingEnvironment: self.testingEnvironment)
|> map { network in
let updated = UnauthorizedAccount(apiId: self.apiId, id: self.id, appGroupPath: self.appGroupPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
updated.shouldBeServiceTaskMaster.set(self.shouldBeServiceTaskMaster.get())
@@ -183,7 +183,6 @@ private var declaredEncodables: Void = {
declareEncodable(CachedChannelData.self, f: { CachedChannelData(decoder: $0) })
declareEncodable(TelegramUserPresence.self, f: { TelegramUserPresence(decoder: $0) })
declareEncodable(LocalFileMediaResource.self, f: { LocalFileMediaResource(decoder: $0) })
declareEncodable(PhotoLibraryMediaResource.self, f: { PhotoLibraryMediaResource(decoder: $0) })
declareEncodable(StickerPackCollectionInfo.self, f: { StickerPackCollectionInfo(decoder: $0) })
declareEncodable(StickerPackItem.self, f: { StickerPackItem(decoder: $0) })
declareEncodable(LocalFileReferenceMediaResource.self, f: { LocalFileReferenceMediaResource(decoder: $0) })
@@ -231,7 +230,7 @@ private func accountRecordIdPathName(_ id: AccountRecordId) -> String {
return "account-\(UInt64(bitPattern: id.int64))"
}
public func accountWithId(apiId: Int32, id: AccountRecordId, appGroupPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<Either<UnauthorizedAccount, Account>, NoError> {
public func accountWithId(apiId: Int32, id: AccountRecordId, supplementary: Bool, appGroupPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<Either<UnauthorizedAccount, Account>, NoError> {
return Signal<(String, Postbox, Coding?), NoError> { subscriber in
let _ = declaredEncodables
@@ -265,12 +264,12 @@ public func accountWithId(apiId: Int32, id: AccountRecordId, appGroupPath: Strin
if let accountState = accountState {
switch accountState {
case let unauthorizedState as UnauthorizedAccountState:
return initializedNetwork(apiId: apiId, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
|> map { network -> Either<UnauthorizedAccount, Account> in
.left(value: UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
}
case let authorizedState as AuthorizedAccountState:
return initializedNetwork(apiId: apiId, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
|> map { network -> Either<UnauthorizedAccount, Account> in
return .right(value: Account(id: id, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods))
}
@@ -279,7 +278,7 @@ public func accountWithId(apiId: Int32, id: AccountRecordId, appGroupPath: Strin
}
}
return initializedNetwork(apiId: apiId, datacenterId: 2, keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: 2, keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
|> map { network -> Either<UnauthorizedAccount, Account> in
return .left(value: UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
}

View File

@@ -14,7 +14,7 @@ private enum AccountKind {
case unauthorized
}
public func currentAccount(apiId: Int32, manager: AccountManager, appGroupPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<Either<UnauthorizedAccount, Account>?, NoError> {
public func currentAccount(apiId: Int32, supplementary: Bool, manager: AccountManager, appGroupPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<Either<UnauthorizedAccount, Account>?, NoError> {
return manager.allocatedCurrentAccountId()
|> distinctUntilChanged(isEqual: { lhs, rhs in
return lhs == rhs
@@ -23,7 +23,7 @@ public func currentAccount(apiId: Int32, manager: AccountManager, appGroupPath:
if let id = id {
let reload = ValuePromise<Bool>(true, ignoreRepeated: false)
return reload.get() |> mapToSignal { _ -> Signal<Either<UnauthorizedAccount, Account>?, NoError> in
return accountWithId(apiId: apiId, id: id, appGroupPath: appGroupPath, testingEnvironment: testingEnvironment, auxiliaryMethods: auxiliaryMethods)
return accountWithId(apiId: apiId, id: id, supplementary: supplementary, appGroupPath: appGroupPath, testingEnvironment: testingEnvironment, auxiliaryMethods: auxiliaryMethods)
|> mapToSignal { account -> Signal<Either<UnauthorizedAccount, Account>?, NoError> in
let postbox: Postbox
let initialKind: AccountKind
@@ -151,7 +151,7 @@ public func managedCleanupAccounts(apiId: Int32, accountManager: AccountManager,
private func cleanupAccount(apiId: Int32, accountManager: AccountManager, id: AccountRecordId, appGroupPath: String, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal<Void, NoError> {
return accountWithId(apiId: apiId, id: id, appGroupPath: appGroupPath, testingEnvironment: false, auxiliaryMethods: auxiliaryMethods)
return accountWithId(apiId: apiId, id: id, supplementary: true, appGroupPath: appGroupPath, testingEnvironment: false, auxiliaryMethods: auxiliaryMethods)
|> mapToSignal { account -> Signal<Void, NoError> in
switch account {
case .left:

View File

@@ -228,54 +228,6 @@ public class LocalFileMediaResource: TelegramMediaResource {
}
}
public struct PhotoLibraryMediaResourceId: MediaResourceId {
public let localIdentifier: String
public var uniqueId: String {
return "ph-\(self.localIdentifier.replacingOccurrences(of: "/", with: "_"))"
}
public var hashValue: Int {
return self.localIdentifier.hashValue
}
public func isEqual(to: MediaResourceId) -> Bool {
if let to = to as? PhotoLibraryMediaResourceId {
return self.localIdentifier == to.localIdentifier
} else {
return false
}
}
}
public class PhotoLibraryMediaResource: TelegramMediaResource {
let localIdentifier: String
public init(localIdentifier: String) {
self.localIdentifier = localIdentifier
}
public required init(decoder: Decoder) {
self.localIdentifier = decoder.decodeStringForKey("i")
}
public func encode(_ encoder: Encoder) {
encoder.encodeString(self.localIdentifier, forKey: "i")
}
public var id: MediaResourceId {
return PhotoLibraryMediaResourceId(localIdentifier: self.localIdentifier)
}
public func isEqual(to: TelegramMediaResource) -> Bool {
if let to = to as? PhotoLibraryMediaResource {
return self.localIdentifier == to.localIdentifier
} else {
return false
}
}
}
public struct LocalFileReferenceMediaResourceId: MediaResourceId {
public let randomId: Int64

View File

@@ -190,6 +190,12 @@ func enqueueMessages(modifier: Modifier, account: Account, peerId: PeerId, messa
mediaList.append(media)
}
if let file = media as? TelegramMediaFile, file.isVoice {
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
attributes.append(ConsumableContentMessageAttribute(consumed: false))
}
}
var entitiesAttribute: TextEntitiesMessageAttribute?
for attribute in attributes {
if let attribute = attribute as? TextEntitiesMessageAttribute {

View File

@@ -13,50 +13,6 @@ private func fetchCloudMediaLocation(account: Account, resource: TelegramCloudMe
return multipartFetch(account: account, resource: resource, size: size, range: range)
}
#if os(iOS)
private func fetchPhotoLibraryResource(localIdentifier: String) -> Signal<MediaResourceDataFetchResult, NoError> {
return Signal { subscriber in
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil)
var requestId: PHImageRequestID?
if fetchResult.count != 0 {
let asset = fetchResult.object(at: 0)
let option = PHImageRequestOptions()
option.deliveryMode = .highQualityFormat
let size = CGSize(width: 1280.0, height: 1280.0)
requestId = PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFit, options: option, resultHandler: { (image, info) -> Void in
Queue.concurrentDefaultQueue().async {
requestId = nil
if let image = image {
let scale = min(1.0, min(size.width / max(1.0, image.size.width), size.height / max(1.0, image.size.height)))
let scaledSize = CGSize(width: floor(image.size.width * scale), height: floor(image.size.height * scale))
UIGraphicsBeginImageContextWithOptions(scaledSize, true, image.scale)
image.draw(in: CGRect(origin: CGPoint(), size: scaledSize))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
if let scaledImage = scaledImage, let data = UIImageJPEGRepresentation(scaledImage, 0.6) {
subscriber.putNext(.dataPart(data: data, range: 0 ..< data.count, complete: true))
subscriber.putCompletion()
} else {
subscriber.putCompletion()
}
} else {
subscriber.putCompletion()
}
}
})
}
return ActionDisposable {
if let requestId = requestId {
PHImageManager.default().cancelImageRequest(requestId)
}
}
}
}
#endif
private func fetchLocalFileResource(path: String, move: Bool) -> Signal<MediaResourceDataFetchResult, NoError> {
return Signal { subscriber in
if move {
@@ -81,12 +37,6 @@ func fetchResource(account: Account, resource: MediaResource, range: Range<Int>)
return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchSecretFileResource(account: account, resource: secretFileResource, range: range))
} else if let cloudResource = resource as? TelegramCloudMediaResource {
return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchCloudMediaLocation(account: account, resource: cloudResource, size: resource.size, range: range))
} else if let photoLibraryResource = resource as? PhotoLibraryMediaResource {
#if os(iOS)
return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchPhotoLibraryResource(localIdentifier: photoLibraryResource.localIdentifier))
#else
return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false))
#endif
} else if let localFileResource = resource as? LocalFileReferenceMediaResource {
if false {
//return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchLocalFileResource(path: localFileResource.localFilePath) |> delay(10.0, queue: Queue.concurrentDefaultQueue()))

View File

@@ -7,7 +7,7 @@ import Foundation
import SwiftSignalKit
#endif
public func markMessageContentAsConsumedInteractively(postbox: Postbox, network: Network, messageId: MessageId) -> Signal<Void, NoError> {
public func markMessageContentAsConsumedInteractively(postbox: Postbox, messageId: MessageId) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Void in
if let message = modifier.getMessage(messageId), message.flags.contains(.Incoming) {
var updateMessage = false

View File

@@ -94,7 +94,7 @@ private var registeredLoggingFunctions: Void = {
registerLoggingFunctions()
}()
func initializedNetwork(apiId: Int32, datacenterId: Int, keychain: Keychain, networkUsageInfoPath: String?, testingEnvironment: Bool) -> Signal<Network, NoError> {
func initializedNetwork(apiId: Int32, supplementary: Bool, datacenterId: Int, keychain: Keychain, networkUsageInfoPath: String?, testingEnvironment: Bool) -> Signal<Network, NoError> {
return Signal { subscriber in
Queue.concurrentDefaultQueue().async {
let _ = registeredLoggingFunctions
@@ -105,6 +105,7 @@ func initializedNetwork(apiId: Int32, datacenterId: Int, keychain: Keychain, net
apiEnvironment.apiId = apiId
apiEnvironment.layer = NSNumber(value: Int(serialization.currentLayer()))
apiEnvironment.disableUpdates = supplementary
let context = MTContext(serialization: serialization, apiEnvironment: apiEnvironment)!

View File

@@ -207,8 +207,8 @@ public final class PendingMessageManager {
let contentToUpload = messageContentToUpload(network: strongSelf.network, postbox: strongSelf.postbox, transformOutgoingMessageMedia: strongSelf.transformOutgoingMessageMedia, message: message)
switch contentToUpload {
case let .ready(message, content):
strongSelf.beginSendingMessage(messageContext: messageContext, message: message, content: content)
case let .ready(content):
strongSelf.beginSendingMessage(messageContext: messageContext, messageId: message.id, content: content)
case let .upload(uploadSignal):
if strongSelf.canBeginUploadingMessage(id: message.id) {
strongSelf.beginUploadingMessage(messageContext: messageContext, id: message.id, uploadSignal: uploadSignal)
@@ -216,75 +216,27 @@ public final class PendingMessageManager {
messageContext.state = .waitingForUploadToStart(uploadSignal)
}
}
/*let uploadedContent = uploadedMessageContent(network: strongSelf.network, postbox: strongSelf.postbox, transformOutgoingMessageMedia: strongSelf.transformOutgoingMessageMedia, message: message)
let sendMessage = uploadedContent
|> mapToSignal { contentResult -> Signal<PendingMessageResult, NoError> in
if let strongSelf = self {
switch contentResult {
case let .progress(progress):
return .single(.progress(progress))
case let .content(message, content):
return strongSelf.sendMessageContent(network: strongSelf.network, postbox: strongSelf.postbox, stateManager: strongSelf.stateManager, message: message, content: content)
|> map { next -> PendingMessageResult in
return .progress(1.0)
}
}
} else {
return .complete()
}
}
messageContext.disposable.set((sendMessage |> deliverOn(strongSelf.queue) |> afterDisposed {
if let strongSelf = self {
assert(strongSelf.queue.isCurrent())
if let current = strongSelf.messageContexts[message.id] {
for subscriber in current.statusSubscribers.copyItems() {
subscriber(nil)
}
if current.statusSubscribers.isEmpty {
strongSelf.messageContexts.removeValue(forKey: message.id)
}
}
}
}).start(next: { next in
if let strongSelf = self {
assert(strongSelf.queue.isCurrent())
switch next {
case let .progress(progress):
if let current = strongSelf.messageContexts[message.id] {
let status = PendingMessageStatus(progress: progress)
current.status = status
for subscriber in current.statusSubscribers.copyItems() {
subscriber(status)
}
}
}
}
}))*/
}
}
}))
}
private func beginSendingMessage(messageContext: PendingMessageContext, message: Message, content: PendingMessageUploadedContent) {
private func beginSendingMessage(messageContext: PendingMessageContext, messageId: MessageId, content: PendingMessageUploadedContent) {
messageContext.state = .sending
let sendMessage: Signal<PendingMessageResult, NoError> = self.sendMessageContent(network: self.network, postbox: self.postbox, stateManager: self.stateManager, message: message, content: content)
let sendMessage: Signal<PendingMessageResult, NoError> = self.sendMessageContent(network: self.network, postbox: self.postbox, stateManager: self.stateManager, messageId: messageId, content: content)
|> map { next -> PendingMessageResult in
return .progress(1.0)
}
messageContext.disposable.set((sendMessage |> deliverOn(self.queue) |> afterDisposed { [weak self] in
if let strongSelf = self {
assert(strongSelf.queue.isCurrent())
if let current = strongSelf.messageContexts[message.id] {
if let current = strongSelf.messageContexts[messageId] {
current.status = .none
for subscriber in current.statusSubscribers.copyItems() {
subscriber(nil)
}
if current.statusSubscribers.isEmpty {
strongSelf.messageContexts.removeValue(forKey: message.id)
strongSelf.messageContexts.removeValue(forKey: messageId)
}
}
}
@@ -294,7 +246,7 @@ public final class PendingMessageManager {
switch next {
case let .progress(progress):
if let current = strongSelf.messageContexts[message.id] {
if let current = strongSelf.messageContexts[messageId] {
let status = PendingMessageStatus(progress: progress)
current.status = status
for subscriber in current.statusSubscribers.copyItems() {
@@ -322,9 +274,9 @@ public final class PendingMessageManager {
subscriber(status)
}
}
case let .content(message, content):
case let .content(content):
if let current = strongSelf.messageContexts[id] {
strongSelf.beginSendingMessage(messageContext: current, message: message, content: content)
strongSelf.beginSendingMessage(messageContext: current, messageId: id, content: content)
strongSelf.updateWaitingUploads(peerId: id.peerId)
}
}
@@ -354,11 +306,11 @@ public final class PendingMessageManager {
subscriber(status)
}
}
case let .content(message, content):
if let current = strongSelf.messageContexts[message.id] {
case let .content(content):
if let current = strongSelf.messageContexts[contextId] {
current.state = .sending
current.disposable.set((strongSelf.sendMessageContent(network: strongSelf.network, postbox: strongSelf.postbox, stateManager: strongSelf.stateManager, message: message, content: content)
current.disposable.set((strongSelf.sendMessageContent(network: strongSelf.network, postbox: strongSelf.postbox, stateManager: strongSelf.stateManager, messageId: contextId, content: content)
|> map { next -> PendingMessageResult in
return .progress(1.0)
} |> deliverOn(strongSelf.queue)).start(next: { next in
@@ -367,7 +319,7 @@ public final class PendingMessageManager {
switch next {
case let .progress(progress):
if let current = strongSelf.messageContexts[message.id] {
if let current = strongSelf.messageContexts[contextId] {
let status = PendingMessageStatus(progress: progress)
current.status = status
for subscriber in current.statusSubscribers.copyItems() {
@@ -387,9 +339,13 @@ public final class PendingMessageManager {
}
}
private func sendMessageContent(network: Network, postbox: Postbox, stateManager: AccountStateManager, message: Message, content: PendingMessageUploadedContent) -> Signal<Void, NoError> {
private func sendMessageContent(network: Network, postbox: Postbox, stateManager: AccountStateManager, messageId: MessageId, content: PendingMessageUploadedContent) -> Signal<Void, NoError> {
return postbox.modify { [weak self] modifier -> Signal<Void, NoError> in
if message.id.peerId.namespace == Namespaces.Peer.SecretChat {
guard let message = modifier.getMessage(messageId) else {
return .complete()
}
if messageId.peerId.namespace == Namespaces.Peer.SecretChat {
var secretFile: SecretChatOutgoingFile?
switch content {
case let .secretMedia(file, size, key):
@@ -401,7 +357,7 @@ public final class PendingMessageManager {
}
var layer: SecretChatLayer?
let state = modifier.getPeerChatState(message.id.peerId) as? SecretChatState
let state = modifier.getPeerChatState(messageId.peerId) as? SecretChatState
if let state = state {
switch state.embeddedState {
case .terminated, .handshake:
@@ -440,11 +396,11 @@ public final class PendingMessageManager {
}
if !sentAsAction {
let updatedState = addSecretChatOutgoingOperation(modifier: modifier, peerId: message.id.peerId, operation: .sendMessage(layer: layer, id: message.id, file: secretFile), state: state)
let updatedState = addSecretChatOutgoingOperation(modifier: modifier, peerId: messageId.peerId, operation: .sendMessage(layer: layer, id: messageId, file: secretFile), state: state)
if updatedState != state {
modifier.setPeerChatState(message.id.peerId, state: updatedState)
modifier.setPeerChatState(messageId.peerId, state: updatedState)
}
modifier.updateMessage(message.id, update: { currentMessage in
modifier.updateMessage(messageId, update: { currentMessage in
var flags = StoreMessageFlags(message.flags)
if !flags.contains(.Failed) {
flags.insert(.Sending)
@@ -457,7 +413,7 @@ public final class PendingMessageManager {
})
}
} else {
modifier.updateMessage(message.id, update: { currentMessage in
modifier.updateMessage(messageId, 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)
@@ -466,7 +422,7 @@ public final class PendingMessageManager {
})
}
return .complete()
} else if let peer = modifier.getPeer(message.id.peerId), let inputPeer = apiInputPeer(peer) {
} else if let peer = modifier.getPeer(messageId.peerId), let inputPeer = apiInputPeer(peer) {
var uniqueId: Int64 = 0
var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var messageEntities: [Api.MessageEntity]?
@@ -499,7 +455,7 @@ public final class PendingMessageManager {
flags |= Int32(1 << 3)
}
let dependencyTag = PendingMessageRequestDependencyTag(messageId: message.id)
let dependencyTag = PendingMessageRequestDependencyTag(messageId: messageId)
let sendMessageRequest: Signal<Api.Updates, NoError>
switch content {

View File

@@ -17,115 +17,76 @@ enum PendingMessageUploadedContent {
enum PendingMessageUploadedContentResult {
case progress(Float)
case content(Message, PendingMessageUploadedContent)
case content(PendingMessageUploadedContent)
}
enum PendingMessageUploadContent {
case ready(Message, PendingMessageUploadedContent)
case ready(PendingMessageUploadedContent)
case upload(Signal<PendingMessageUploadedContentResult, NoError>)
}
func messageContentToUpload(network: Network, postbox: Postbox, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, message: Message) -> PendingMessageUploadContent {
var outgoingChatContextResultAttribute: OutgoingChatContextResultMessageAttribute?
for attribute in message.attributes {
return messageContentToUpload(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, peerId: message.id.peerId, messageId: message.id, attributes: message.attributes, text: message.text, media: message.media)
}
func messageContentToUpload(network: Network, postbox: Postbox, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, peerId: PeerId, messageId: MessageId?, attributes: [MessageAttribute], text: String, media: [Media]) -> PendingMessageUploadContent {
var contextResult: OutgoingChatContextResultMessageAttribute?
for attribute in attributes {
if let attribute = attribute as? OutgoingChatContextResultMessageAttribute {
outgoingChatContextResultAttribute = attribute
contextResult = attribute
}
}
if let _ = message.forwardInfo {
var forwardSourceInfo: ForwardSourceInfoAttribute?
for attribute in message.attributes {
if let attribute = attribute as? ForwardSourceInfoAttribute {
forwardSourceInfo = attribute
}
}
if let forwardSourceInfo = forwardSourceInfo {
return .ready(message, .forward(forwardSourceInfo))
} else {
assertionFailure()
return .ready(message, .text(message.text))
}
} else if let outgoingChatContextResultAttribute = outgoingChatContextResultAttribute {
return .ready(message, .chatContextResult(outgoingChatContextResultAttribute))
} else if let media = message.media.first {
if let image = media as? TelegramMediaImage, let _ = largestImageRepresentation(image.representations) {
return .upload(uploadedMediaImageContent(network: network, postbox: postbox, image: image, message: message))
} else if let file = media as? TelegramMediaFile {
if let resource = file.resource as? CloudDocumentMediaResource {
return .ready(message, .media(Api.InputMedia.inputMediaDocument(id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash), caption: message.text)))
} else {
return .upload(uploadedMediaFileContent(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, file: file, message: message))
}
} else if let contact = media as? TelegramMediaContact {
let input = Api.InputMedia.inputMediaContact(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName)
return .ready(message, .media(input))
} else {
return .ready(message, .text(message.text))
}
} else {
return .ready(message, .text(message.text))
}
}
func uploadedMessageContent(network: Network, postbox: Postbox, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, message: Message) -> Signal<PendingMessageUploadedContentResult, NoError> {
var outgoingChatContextResultAttribute: OutgoingChatContextResultMessageAttribute?
for attribute in message.attributes {
if let attribute = attribute as? OutgoingChatContextResultMessageAttribute {
outgoingChatContextResultAttribute = attribute
var forwardInfo: ForwardSourceInfoAttribute?
for attribute in attributes {
if let attribute = attribute as? ForwardSourceInfoAttribute {
forwardInfo = attribute
}
}
if let _ = message.forwardInfo {
var forwardSourceInfo: ForwardSourceInfoAttribute?
for attribute in message.attributes {
if let attribute = attribute as? ForwardSourceInfoAttribute {
forwardSourceInfo = attribute
}
}
if let forwardSourceInfo = forwardSourceInfo {
return .single(.content(message, .forward(forwardSourceInfo)))
} else {
assertionFailure()
return .never()
}
} else if let outgoingChatContextResultAttribute = outgoingChatContextResultAttribute {
return .single(.content(message, .chatContextResult(outgoingChatContextResultAttribute)))
} else if let media = message.media.first {
if let forwardInfo = forwardInfo {
return .ready(.forward(forwardInfo))
}
if let forwardInfo = forwardInfo {
return .ready(.forward(forwardInfo))
} else if let contextResult = contextResult {
return .ready(.chatContextResult(contextResult))
} else if let media = media.first {
if let image = media as? TelegramMediaImage, let _ = largestImageRepresentation(image.representations) {
return uploadedMediaImageContent(network: network, postbox: postbox, image: image, message: message)
return .upload(uploadedMediaImageContent(network: network, postbox: postbox, peerId: peerId, image: image, text: text))
} else if let file = media as? TelegramMediaFile {
if let resource = file.resource as? CloudDocumentMediaResource {
return .single(.content(message, .media(Api.InputMedia.inputMediaDocument(id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash), caption: message.text))))
return .ready(.media(Api.InputMedia.inputMediaDocument(id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash), caption: text)))
} else {
return uploadedMediaFileContent(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, file: file, message: message)
return .upload(uploadedMediaFileContent(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, peerId: peerId, messageId: messageId, text: text, attributes: attributes, file: file))
}
} else if let contact = media as? TelegramMediaContact {
let input = Api.InputMedia.inputMediaContact(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName)
return .single(.content(message, .media(input)))
return .ready(.media(input))
} else {
return .single(.content(message, .text(message.text)))
return .ready(.text(text))
}
} else {
return .single(.content(message, .text(message.text)))
return .ready(.text(text))
}
}
private func uploadedMediaImageContent(network: Network, postbox: Postbox, image: TelegramMediaImage, message: Message) -> Signal<PendingMessageUploadedContentResult, NoError> {
private func uploadedMediaImageContent(network: Network, postbox: Postbox, peerId: PeerId, image: TelegramMediaImage, text: String) -> Signal<PendingMessageUploadedContentResult, NoError> {
if let largestRepresentation = largestImageRepresentation(image.representations) {
return multipartUpload(network: network, postbox: postbox, resource: largestRepresentation.resource, encrypt: message.id.peerId.namespace == Namespaces.Peer.SecretChat)
return multipartUpload(network: network, postbox: postbox, resource: largestRepresentation.resource, encrypt: peerId.namespace == Namespaces.Peer.SecretChat)
|> map { next -> PendingMessageUploadedContentResult in
switch next {
case let .progress(progress):
return .progress(progress)
case let .inputFile(file):
return .content(message, .media(Api.InputMedia.inputMediaUploadedPhoto(flags: 0, file: file, caption: message.text, stickers: nil)))
return .content(.media(Api.InputMedia.inputMediaUploadedPhoto(flags: 0, file: file, caption: text, stickers: nil)))
case let .inputSecretFile(file, size, key):
return .content(message, .secretMedia(file, size, key))
return .content(.secretMedia(file, size, key))
}
}
} else {
return .single(.content(message, .text(message.text)))
return .single(.content(.text(text)))
}
}
@@ -201,14 +162,14 @@ private func uploadedThumbnail(network: Network, postbox: Postbox, image: Telegr
}
}
private func uploadedMediaFileContent(network: Network, postbox: Postbox, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, file: TelegramMediaFile, message: Message) -> Signal<PendingMessageUploadedContentResult, NoError> {
private func uploadedMediaFileContent(network: Network, postbox: Postbox, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, peerId: PeerId, messageId: MessageId?, text: String, attributes: [MessageAttribute], file: TelegramMediaFile) -> Signal<PendingMessageUploadedContentResult, NoError> {
var hintSize: Int?
if let size = file.size {
hintSize = size
} else if let resource = file.resource as? LocalFileReferenceMediaResource, let size = resource.size {
hintSize = Int(size)
}
let upload = multipartUpload(network: network, postbox: postbox, resource: file.resource, encrypt: message.id.peerId.namespace == Namespaces.Peer.SecretChat, hintFileSize: hintSize)
let upload = multipartUpload(network: network, postbox: postbox, resource: file.resource, encrypt: peerId.namespace == Namespaces.Peer.SecretChat, hintFileSize: hintSize)
/*|> map { next -> UploadedMediaFileContent in
switch next {
case let .progress(progress):
@@ -220,7 +181,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, transf
}
}*/
var alreadyTransformed = false
for attribute in message.attributes {
for attribute in attributes {
if let attribute = attribute as? OutgoingMessageInfoAttribute {
if attribute.flags.contains(.transformedMedia) {
alreadyTransformed = true
@@ -230,14 +191,14 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, transf
}
let transform: Signal<UploadedMediaTransform, Void>
if let transformOutgoingMessageMedia = transformOutgoingMessageMedia, !alreadyTransformed {
if let transformOutgoingMessageMedia = transformOutgoingMessageMedia, let messageId = messageId, !alreadyTransformed {
transform = .single(.pending) |> then(transformOutgoingMessageMedia(postbox, network, file, false)
|> mapToSignal { media -> Signal<UploadedMediaTransform, NoError> in
return postbox.modify { modifier -> UploadedMediaTransform in
if let media = media {
if let id = media.id {
modifier.updateMedia(id, update: media)
modifier.updateMessage(message.id, update: { currentMessage in
modifier.updateMessage(messageId, 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)
@@ -288,17 +249,17 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, transf
if case let .done(thumbnail) = media {
let inputMedia: Api.InputMedia
if let thumbnail = thumbnail {
inputMedia = Api.InputMedia.inputMediaUploadedThumbDocument(flags: 0, file: inputFile, thumb: thumbnail, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFile(file), caption: message.text, stickers: nil)
inputMedia = Api.InputMedia.inputMediaUploadedThumbDocument(flags: 0, file: inputFile, thumb: thumbnail, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFile(file), caption: text, stickers: nil)
} else {
inputMedia = Api.InputMedia.inputMediaUploadedDocument(flags: 0, file: inputFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFile(file), caption: message.text, stickers: nil)
inputMedia = Api.InputMedia.inputMediaUploadedDocument(flags: 0, file: inputFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFile(file), caption: text, stickers: nil)
}
return .single(.content(message, .media(inputMedia)))
return .single(.content(.media(inputMedia)))
} else {
return .complete()
}
case let .inputSecretFile(file, size, key):
if case .done = media {
return .single(.content(message, .secretMedia(file, size, key)))
return .single(.content(.secretMedia(file, size, key)))
} else {
return .complete()
}

View File

@@ -12,10 +12,14 @@ final class CachedResolvedByNamePeer: Coding {
let timestamp: Int32
static func key(name: String) -> ValueBoxKey {
let nameData = name.data(using: .utf8)!
let key = ValueBoxKey(length: nameData.count)
nameData.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Void in
memcpy(key.memory, bytes, nameData.count)
let key: ValueBoxKey
if let nameData = name.data(using: .utf8) {
key = ValueBoxKey(length: nameData.count)
nameData.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Void in
memcpy(key.memory, bytes, nameData.count)
}
} else {
key = ValueBoxKey(length: 0)
}
return key
}

View File

@@ -0,0 +1,117 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
import MtProtoKitMac
#else
import Postbox
import SwiftSignalKit
import MtProtoKitDynamic
#endif
public enum StandaloneMedia {
case image(Data)
case file(Data)
}
public func standaloneSendMessage(account: Account, peerId: PeerId, text: String, attributes: [MessageAttribute], replyToMessageId: MessageId?) -> Signal<Void, NoError> {
let contentToUpload = messageContentToUpload(network: account.network, postbox: account.postbox, transformOutgoingMessageMedia: nil, peerId: peerId, messageId: nil, attributes: attributes, text: text, media: [])
switch contentToUpload {
case let .ready(content):
return sendMessageContent(account: account, peerId: peerId, attributes: attributes, content: content)
case let .upload(uploadSignal):
return .complete()
/*if strongSelf.canBeginUploadingMessage(id: message.id) {
strongSelf.beginUploadingMessage(messageContext: messageContext, id: message.id, uploadSignal: uploadSignal)
} else {
messageContext.state = .waitingForUploadToStart(uploadSignal)
}*/
}
}
private func sendMessageContent(account: Account, peerId: PeerId, attributes: [MessageAttribute], content: PendingMessageUploadedContent) -> Signal<Void, NoError> {
return account.postbox.modify { modifier -> Signal<Void, NoError> in
if peerId.namespace == Namespaces.Peer.SecretChat {
return .complete()
} else if let peer = modifier.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var uniqueId: Int64 = 0
var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var messageEntities: [Api.MessageEntity]?
var replyMessageId: Int32?
var flags: Int32 = 0
flags |= (1 << 7)
for attribute in attributes {
if let replyAttribute = attribute as? ReplyMessageAttribute {
replyMessageId = replyAttribute.messageId.id
} else if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute {
uniqueId = outgoingInfo.uniqueId
} else if let attribute = attribute as? ForwardSourceInfoAttribute {
forwardSourceInfoAttribute = attribute
} else if let attribute = attribute as? TextEntitiesMessageAttribute {
messageEntities = apiTextAttributeEntities(attribute, associatedPeers: SimpleDictionary())
} else if let attribute = attribute as? OutgoingContentInfoMessageAttribute {
if attribute.flags.contains(.disableLinkPreviews) {
flags |= Int32(1 << 1)
}
}
}
if let _ = replyMessageId {
flags |= Int32(1 << 0)
}
if let _ = messageEntities {
flags |= Int32(1 << 3)
}
let sendMessageRequest: Signal<Api.Updates, NoError>
switch content {
case let .text(text):
sendMessageRequest = account.network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities))
|> mapError { _ -> NoError in
return NoError()
}
case let .media(inputMedia):
sendMessageRequest = account.network.request(Api.functions.messages.sendMedia(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, media: inputMedia, randomId: uniqueId, replyMarkup: nil))
|> mapError { _ -> NoError in
return NoError()
}
case let .forward(sourceInfo):
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = modifier.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
sendMessageRequest = account.network.request(Api.functions.messages.forwardMessages(flags: 0, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer))
|> mapError { _ -> NoError in
return NoError()
}
} else {
sendMessageRequest = .fail(NoError())
}
case let .chatContextResult(chatContextResult):
sendMessageRequest = account.network.request(Api.functions.messages.sendInlineBotResult(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, randomId: uniqueId, queryId: chatContextResult.queryId, id: chatContextResult.id))
|> mapError { _ -> NoError in
return NoError()
}
case .secretMedia:
assertionFailure()
sendMessageRequest = .fail(NoError())
}
return sendMessageRequest
|> mapToSignal { result -> Signal<Void, NoError> in
return .complete()
/*if let strongSelf = self {
return strongSelf.applySentMessage(postbox: postbox, stateManager: stateManager, message: message, result: result)
} else {
return .never()
}*/
}
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()
}
} else {
return .complete()
}
} |> switchToLatest
}