mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-02 04:38:33 +00:00
Merge branch 'master' of https://github.com/peter-iakovlev/TelegramCore
This commit is contained in:
commit
5ca27728d7
@ -93,6 +93,10 @@
|
||||
D01D6BFA1E42A718006151C6 /* SearchStickers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01D6BF81E42A713006151C6 /* SearchStickers.swift */; };
|
||||
D021E0DF1DB539FC00C6B04F /* StickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0DE1DB539FC00C6B04F /* StickerPack.swift */; };
|
||||
D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0E11DB5401A00C6B04F /* StickerManagement.swift */; };
|
||||
D0223A981EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0223A971EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift */; };
|
||||
D0223A991EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0223A971EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift */; };
|
||||
D0223A9B1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0223A9A1EA5654D00211D94 /* TelegramMediaResource.swift */; };
|
||||
D0223A9C1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0223A9A1EA5654D00211D94 /* TelegramMediaResource.swift */; };
|
||||
D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */; };
|
||||
D02ABC7C1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */; };
|
||||
D02ABC7E1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC7D1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift */; };
|
||||
@ -474,6 +478,10 @@
|
||||
D0F7B1EB1E045C87007EB8A5 /* ResolvePeerByName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */; };
|
||||
D0F7B1EC1E045C87007EB8A5 /* SearchPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827BA1E00451F00071108 /* SearchPeers.swift */; };
|
||||
D0FA0ABD1E76C908005BB9B7 /* TwoStepVerification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA0ABC1E76C908005BB9B7 /* TwoStepVerification.swift */; };
|
||||
D0FA35051EA6135D00E56FFA /* CacheStorageSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA35041EA6135D00E56FFA /* CacheStorageSettings.swift */; };
|
||||
D0FA35061EA6135D00E56FFA /* CacheStorageSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA35041EA6135D00E56FFA /* CacheStorageSettings.swift */; };
|
||||
D0FA35081EA632E400E56FFA /* CollectCacheUsageStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA35071EA632E400E56FFA /* CollectCacheUsageStats.swift */; };
|
||||
D0FA35091EA632E400E56FFA /* CollectCacheUsageStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA35071EA632E400E56FFA /* CollectCacheUsageStats.swift */; };
|
||||
D0FA8B981E1E955C001E855B /* SecretChatOutgoingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA8B971E1E955C001E855B /* SecretChatOutgoingOperation.swift */; };
|
||||
D0FA8B991E1E955C001E855B /* SecretChatOutgoingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA8B971E1E955C001E855B /* SecretChatOutgoingOperation.swift */; };
|
||||
D0FA8B9E1E1F973B001E855B /* SecretChatIncomingEncryptedOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA8B9D1E1F973B001E855B /* SecretChatIncomingEncryptedOperation.swift */; };
|
||||
@ -549,6 +557,8 @@
|
||||
D01D6BF81E42A713006151C6 /* SearchStickers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchStickers.swift; sourceTree = "<group>"; };
|
||||
D021E0DE1DB539FC00C6B04F /* StickerPack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerPack.swift; sourceTree = "<group>"; };
|
||||
D021E0E11DB5401A00C6B04F /* StickerManagement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerManagement.swift; sourceTree = "<group>"; };
|
||||
D0223A971EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaResourceNetworkStatsTag.swift; sourceTree = "<group>"; };
|
||||
D0223A9A1EA5654D00211D94 /* TelegramMediaResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelegramMediaResource.swift; sourceTree = "<group>"; };
|
||||
D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteMessagesInteractively.swift; sourceTree = "<group>"; };
|
||||
D02ABC7D1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudChatRemoveMessagesOperation.swift; sourceTree = "<group>"; };
|
||||
D02ABC801E310E5D00CAE539 /* ManagedCloudChatRemoveMessagesOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedCloudChatRemoveMessagesOperations.swift; sourceTree = "<group>"; };
|
||||
@ -767,6 +777,8 @@
|
||||
D0F7AB2B1DCE889D009AD9A1 /* EditedMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditedMessageAttribute.swift; sourceTree = "<group>"; };
|
||||
D0F7AB2E1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyMarkupMessageAttribute.swift; sourceTree = "<group>"; };
|
||||
D0FA0ABC1E76C908005BB9B7 /* TwoStepVerification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoStepVerification.swift; sourceTree = "<group>"; };
|
||||
D0FA35041EA6135D00E56FFA /* CacheStorageSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacheStorageSettings.swift; sourceTree = "<group>"; };
|
||||
D0FA35071EA632E400E56FFA /* CollectCacheUsageStats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectCacheUsageStats.swift; sourceTree = "<group>"; };
|
||||
D0FA8B971E1E955C001E855B /* SecretChatOutgoingOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretChatOutgoingOperation.swift; sourceTree = "<group>"; };
|
||||
D0FA8B9D1E1F973B001E855B /* SecretChatIncomingEncryptedOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretChatIncomingEncryptedOperation.swift; sourceTree = "<group>"; };
|
||||
D0FA8BA01E1F99E1001E855B /* SecretChatFileReference.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretChatFileReference.swift; sourceTree = "<group>"; };
|
||||
@ -826,6 +838,7 @@
|
||||
D01B27A11E394D8B0022A4C0 /* PrivacySettings.swift */,
|
||||
D08774FD1E3E3A3500A97350 /* GlobalNotificationSettings.swift */,
|
||||
D05A32E61E6F0B5C002760B4 /* RecentAccountSession.swift */,
|
||||
D0FA35041EA6135D00E56FFA /* CacheStorageSettings.swift */,
|
||||
);
|
||||
name = Settings;
|
||||
sourceTree = "<group>";
|
||||
@ -1057,7 +1070,9 @@
|
||||
D03B0D121D62257600955575 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0223A9A1EA5654D00211D94 /* TelegramMediaResource.swift */,
|
||||
D03B0D431D6319F900955575 /* CloudFileMediaResource.swift */,
|
||||
D0223A971EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift */,
|
||||
D03B0D391D6319E200955575 /* Fetch.swift */,
|
||||
D0E35A0D1DE4953E00BC6096 /* FetchHttpResource.swift */,
|
||||
D0448CA11E291B14005A61A7 /* FetchSecretFileResource.swift */,
|
||||
@ -1130,6 +1145,7 @@
|
||||
C239BE961E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift */,
|
||||
D0528E5F1E65B94E00E2FEF5 /* SingleMessageView.swift */,
|
||||
D0528E691E65DD2100E2FEF5 /* WebpagePreview.swift */,
|
||||
D0FA35071EA632E400E56FFA /* CollectCacheUsageStats.swift */,
|
||||
);
|
||||
name = Messages;
|
||||
sourceTree = "<group>";
|
||||
@ -1628,6 +1644,7 @@
|
||||
D019B1CC1E2E3B6A00F80DB3 /* SecretChatRekeySession.swift in Sources */,
|
||||
D03B0CD91D62245B00955575 /* PeerUtils.swift in Sources */,
|
||||
D03B0CE41D62249F00955575 /* TextEntitiesMessageAttribute.swift in Sources */,
|
||||
D0FA35081EA632E400E56FFA /* CollectCacheUsageStats.swift in Sources */,
|
||||
D049EAEB1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift in Sources */,
|
||||
D03B0CD31D62244300955575 /* Namespaces.swift in Sources */,
|
||||
D01D6BF91E42A713006151C6 /* SearchStickers.swift in Sources */,
|
||||
@ -1649,6 +1666,7 @@
|
||||
D0448C8E1E22993C005A61A7 /* ProcessSecretChatIncomingDecryptedOperations.swift in Sources */,
|
||||
D0448C911E251F96005A61A7 /* SecretChatEncryption.swift in Sources */,
|
||||
D0FA8BA11E1F99E1001E855B /* SecretChatFileReference.swift in Sources */,
|
||||
D0223A981EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift in Sources */,
|
||||
D07827BB1E00451F00071108 /* SearchPeers.swift in Sources */,
|
||||
D0DC354E1DE368F7000195EB /* RequestChatContextResults.swift in Sources */,
|
||||
D0BC38771E40BAAA0044D6FE /* ManagedSynchronizePinnedChatsOperations.swift in Sources */,
|
||||
@ -1667,6 +1685,7 @@
|
||||
D03B0D0F1D62255C00955575 /* UpdateMessageService.swift in Sources */,
|
||||
D03B0CF61D62250800955575 /* TelegramMediaFile.swift in Sources */,
|
||||
D03B0CE81D6224AD00955575 /* ViewCountMessageAttribute.swift in Sources */,
|
||||
D0FA35051EA6135D00E56FFA /* CacheStorageSettings.swift in Sources */,
|
||||
D03B0D0C1D62255C00955575 /* AccountStateManagementUtils.swift in Sources */,
|
||||
D073CE5D1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
||||
D0FA8B9E1E1F973B001E855B /* SecretChatIncomingEncryptedOperation.swift in Sources */,
|
||||
@ -1682,6 +1701,7 @@
|
||||
D03B0D5C1D631A6900955575 /* Download.swift in Sources */,
|
||||
D01749591E1092BC0057C89A /* RequestStartBot.swift in Sources */,
|
||||
D01B27A21E394D8B0022A4C0 /* PrivacySettings.swift in Sources */,
|
||||
D0223A9B1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */,
|
||||
D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */,
|
||||
D0FA8BB61E223C16001E855B /* SecretApiLayer8.swift in Sources */,
|
||||
D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */,
|
||||
@ -1794,6 +1814,7 @@
|
||||
D03C53711DAD5CA9004C17B3 /* CachedGroupParticipants.swift in Sources */,
|
||||
C2366C841E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */,
|
||||
D03C53671DAD5CA9004C17B3 /* ApiUtils.swift in Sources */,
|
||||
D0223A9C1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */,
|
||||
D0AAD1B91E326FE200D5B9DE /* ManagedAutoremoveMessageOperations.swift in Sources */,
|
||||
D001F3F21E128A1C007A8C60 /* UpdateGroup.swift in Sources */,
|
||||
D0F7B1EB1E045C87007EB8A5 /* ResolvePeerByName.swift in Sources */,
|
||||
@ -1834,6 +1855,7 @@
|
||||
D0F3A8A61E82C94C00B4C64C /* SynchronizeableChatInputState.swift in Sources */,
|
||||
D00D34431E6EDD2E0057B307 /* ManagedSynchronizeConsumeMessageContentsOperations.swift in Sources */,
|
||||
D049EAE91E44B67100A2CD3A /* RecentPeerItem.swift in Sources */,
|
||||
D0FA35091EA632E400E56FFA /* CollectCacheUsageStats.swift in Sources */,
|
||||
D001F3F31E128A1C007A8C60 /* UpdateMessageService.swift in Sources */,
|
||||
D0C50E351E93A86600F62E39 /* CallSessionManager.swift in Sources */,
|
||||
D0B8442D1DAB91E0005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
||||
@ -1891,6 +1913,7 @@
|
||||
D0DC35511DE36908000195EB /* RequestChatContextResults.swift in Sources */,
|
||||
D0F7B1EC1E045C87007EB8A5 /* SearchPeers.swift in Sources */,
|
||||
D001F3EF1E128A1C007A8C60 /* AccountIntermediateState.swift in Sources */,
|
||||
D0223A991EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift in Sources */,
|
||||
D00C7CCD1E3620C30080C3D5 /* CachedChannelParticipants.swift in Sources */,
|
||||
D03C536E1DAD5CA9004C17B3 /* PhoneNumber.swift in Sources */,
|
||||
D0BC387C1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */,
|
||||
@ -1900,6 +1923,7 @@
|
||||
D0BEAF5E1E54941B00BD963D /* Authorization.swift in Sources */,
|
||||
D073CEA41DCBF3EA007511FD /* MultipartUpload.swift in Sources */,
|
||||
D03C53701DAD5CA9004C17B3 /* ExportedInvitation.swift in Sources */,
|
||||
D0FA35061EA6135D00E56FFA /* CacheStorageSettings.swift in Sources */,
|
||||
D08F4A671E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */,
|
||||
D05A32E81E6F0B5C002760B4 /* RecentAccountSession.swift in Sources */,
|
||||
D0F7B1E31E045C7B007EB8A5 /* RichText.swift in Sources */,
|
||||
|
||||
@ -145,7 +145,7 @@ public class UnauthorizedAccount {
|
||||
postbox.removeKeychainEntryForKey(key)
|
||||
})
|
||||
|
||||
return initializedNetwork(apiId: self.apiId, supplementary: false, 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, 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())
|
||||
@ -219,6 +219,7 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(ArchivedStickerPacksInfo.self, f: { ArchivedStickerPacksInfo(decoder: $0) })
|
||||
declareEncodable(SynchronizeChatInputStateOperation.self, f: { SynchronizeChatInputStateOperation(decoder: $0) })
|
||||
declareEncodable(SynchronizeSavedGifsOperation.self, f: { SynchronizeSavedGifsOperation(decoder: $0) })
|
||||
declareEncodable(CacheStorageSettings.self, f: { CacheStorageSettings(decoder: $0) })
|
||||
|
||||
return
|
||||
}()
|
||||
@ -272,12 +273,12 @@ public func accountWithId(apiId: Int32, id: AccountRecordId, supplementary: Bool
|
||||
if let accountState = accountState {
|
||||
switch accountState {
|
||||
case let unauthorizedState as UnauthorizedAccountState:
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: path), testingEnvironment: testingEnvironment)
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
}
|
||||
case let authorizedState as AuthorizedAccountState:
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: path), testingEnvironment: testingEnvironment)
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment)
|
||||
|> map { network -> AccountResult in
|
||||
return .authorized(Account(id: id, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods))
|
||||
}
|
||||
@ -286,7 +287,7 @@ public func accountWithId(apiId: Int32, id: AccountRecordId, supplementary: Bool
|
||||
}
|
||||
}
|
||||
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: 2, keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: path), testingEnvironment: testingEnvironment)
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: testingEnvironment)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
}
|
||||
@ -365,9 +366,9 @@ public enum AccountNetworkState {
|
||||
|
||||
public final class AccountAuxiliaryMethods {
|
||||
public let updatePeerChatInputState: (PeerChatInterfaceState?, SynchronizeableChatInputState?) -> PeerChatInterfaceState?
|
||||
public let fetchResource: (Account, MediaResource, Range<Int>) -> Signal<MediaResourceDataFetchResult, NoError>?
|
||||
public let fetchResource: (Account, MediaResource, Range<Int>, MediaResourceFetchTag?) -> Signal<MediaResourceDataFetchResult, NoError>?
|
||||
|
||||
public init(updatePeerChatInputState: @escaping (PeerChatInterfaceState?, SynchronizeableChatInputState?) -> PeerChatInterfaceState?, fetchResource: @escaping (Account, MediaResource, Range<Int>) -> Signal<MediaResourceDataFetchResult, NoError>?) {
|
||||
public init(updatePeerChatInputState: @escaping (PeerChatInterfaceState?, SynchronizeableChatInputState?) -> PeerChatInterfaceState?, fetchResource: @escaping (Account, MediaResource, Range<Int>, MediaResourceFetchTag?) -> Signal<MediaResourceDataFetchResult, NoError>?) {
|
||||
self.updatePeerChatInputState = updatePeerChatInputState
|
||||
self.fetchResource = fetchResource
|
||||
}
|
||||
@ -624,20 +625,6 @@ public class Account {
|
||||
self.managedOperationsDisposable.dispose()
|
||||
}
|
||||
|
||||
/*public func currentNetworkStats() -> Signal<MTNetworkUsageManagerStats, NoError> {
|
||||
return Signal { subscriber in
|
||||
let manager = MTNetworkUsageManager(info: MTNetworkUsageCalculationInfo(filePath: accountNetworkUsageInfoPath(basePath: self.basePath)))!
|
||||
manager.currentStats().start(next: { next in
|
||||
if let stats = next as? MTNetworkUsageManagerStats {
|
||||
subscriber.putNext(stats)
|
||||
}
|
||||
subscriber.putCompletion()
|
||||
}, error: nil, completed: nil)
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
}*/
|
||||
|
||||
public func peerInputActivities(peerId: PeerId) -> Signal<[(PeerId, PeerInputActivity)], NoError> {
|
||||
return self.peerInputActivityManager.activities(peerId: peerId)
|
||||
}
|
||||
@ -653,15 +640,19 @@ public class Account {
|
||||
}
|
||||
}
|
||||
|
||||
public func accountNetworkUsageStats(account: Account, reset: ResetNetworkUsageStats) -> Signal<NetworkUsageStats, NoError> {
|
||||
return networkUsageStats(basePath: account.basePath, reset: reset)
|
||||
}
|
||||
|
||||
public typealias FetchCachedResourceRepresentation = (_ account: Account, _ resource: MediaResource, _ resourceData: MediaResourceData, _ representation: CachedMediaResourceRepresentation) -> Signal<CachedMediaResourceRepresentationResult, NoError>
|
||||
public typealias TransformOutgoingMessageMedia = (_ postbox: Postbox, _ network: Network, _ media: Media, _ userInteractive: Bool) -> Signal<Media?, NoError>
|
||||
|
||||
public func setupAccount(_ account: Account, fetchCachedResourceRepresentation: FetchCachedResourceRepresentation? = nil, transformOutgoingMessageMedia: TransformOutgoingMessageMedia? = nil) {
|
||||
account.postbox.mediaBox.fetchResource = { [weak account] resource, range -> Signal<MediaResourceDataFetchResult, NoError> in
|
||||
account.postbox.mediaBox.fetchResource = { [weak account] resource, range, tag -> Signal<MediaResourceDataFetchResult, NoError> in
|
||||
if let strongAccount = account {
|
||||
if let result = fetchResource(account: strongAccount, resource: resource, range: range) {
|
||||
if let result = fetchResource(account: strongAccount, resource: resource, range: range, tag: tag) {
|
||||
return result
|
||||
} else if let result = strongAccount.auxiliaryMethods.fetchResource(strongAccount, resource, range) {
|
||||
} else if let result = strongAccount.auxiliaryMethods.fetchResource(strongAccount, resource, range, tag) {
|
||||
return result
|
||||
} else {
|
||||
return .never()
|
||||
|
||||
@ -130,6 +130,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[393186209] = { return Api.SendMessageAction.parse_sendMessageGeoLocationAction($0) }
|
||||
dict[1653390447] = { return Api.SendMessageAction.parse_sendMessageChooseContactAction($0) }
|
||||
dict[-580219064] = { return Api.SendMessageAction.parse_sendMessageGamePlayAction($0) }
|
||||
dict[-1997373508] = { return Api.SendMessageAction.parse_sendMessageRecordRoundAction($0) }
|
||||
dict[-1150187996] = { return Api.SendMessageAction.parse_sendMessageUploadRoundAction($0) }
|
||||
dict[-1137792208] = { return Api.PrivacyKey.parse_privacyKeyStatusTimestamp($0) }
|
||||
dict[1343122938] = { return Api.PrivacyKey.parse_privacyKeyChatInvite($0) }
|
||||
dict[1030105979] = { return Api.PrivacyKey.parse_privacyKeyPhoneCall($0) }
|
||||
@ -4875,6 +4877,8 @@ public struct Api {
|
||||
case sendMessageGeoLocationAction
|
||||
case sendMessageChooseContactAction
|
||||
case sendMessageGamePlayAction
|
||||
case sendMessageRecordRoundAction
|
||||
case sendMessageUploadRoundAction
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool {
|
||||
switch self {
|
||||
@ -4943,6 +4947,18 @@ public struct Api {
|
||||
buffer.appendInt32(-580219064)
|
||||
}
|
||||
|
||||
break
|
||||
case .sendMessageRecordRoundAction:
|
||||
if boxed {
|
||||
buffer.appendInt32(-1997373508)
|
||||
}
|
||||
|
||||
break
|
||||
case .sendMessageUploadRoundAction:
|
||||
if boxed {
|
||||
buffer.appendInt32(-1150187996)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
return true
|
||||
@ -5013,6 +5029,12 @@ public struct Api {
|
||||
fileprivate static func parse_sendMessageGamePlayAction(_ reader: BufferReader) -> SendMessageAction? {
|
||||
return Api.SendMessageAction.sendMessageGamePlayAction
|
||||
}
|
||||
fileprivate static func parse_sendMessageRecordRoundAction(_ reader: BufferReader) -> SendMessageAction? {
|
||||
return Api.SendMessageAction.sendMessageRecordRoundAction
|
||||
}
|
||||
fileprivate static func parse_sendMessageUploadRoundAction(_ reader: BufferReader) -> SendMessageAction? {
|
||||
return Api.SendMessageAction.sendMessageUploadRoundAction
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
get {
|
||||
@ -5039,6 +5061,10 @@ public struct Api {
|
||||
return "(sendMessageChooseContactAction)"
|
||||
case .sendMessageGamePlayAction:
|
||||
return "(sendMessageGamePlayAction)"
|
||||
case .sendMessageRecordRoundAction:
|
||||
return "(sendMessageRecordRoundAction)"
|
||||
case .sendMessageUploadRoundAction:
|
||||
return "(sendMessageUploadRoundAction)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
TelegramCore/CacheStorageSettings.swift
Normal file
58
TelegramCore/CacheStorageSettings.swift
Normal file
@ -0,0 +1,58 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public struct CacheStorageSettings: PreferencesEntry, Equatable {
|
||||
public let defaultCacheStorageTimeout: Int32
|
||||
|
||||
public static var defaultSettings: CacheStorageSettings {
|
||||
return CacheStorageSettings(defaultCacheStorageTimeout: Int32.max)
|
||||
}
|
||||
|
||||
init(defaultCacheStorageTimeout: Int32) {
|
||||
self.defaultCacheStorageTimeout = defaultCacheStorageTimeout
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.defaultCacheStorageTimeout = decoder.decodeInt32ForKey("dt") as Int32
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
encoder.encodeInt32(self.defaultCacheStorageTimeout, forKey: "dt")
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
if let to = to as? CacheStorageSettings {
|
||||
return self == to
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: CacheStorageSettings, rhs: CacheStorageSettings) -> Bool {
|
||||
return lhs.defaultCacheStorageTimeout == rhs.defaultCacheStorageTimeout
|
||||
}
|
||||
|
||||
public func withUpdatedDefaultCacheStorageTimeout(_ defaultCacheStorageTimeout: Int32) -> CacheStorageSettings {
|
||||
return CacheStorageSettings(defaultCacheStorageTimeout: defaultCacheStorageTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
public func updateCacheStorageSettingsInteractively(postbox: Postbox, _ f: @escaping (CacheStorageSettings) -> CacheStorageSettings) -> Signal<Void, NoError> {
|
||||
return postbox.modify { modifier -> Void in
|
||||
modifier.updatePreferencesEntry(key: PreferencesKeys.cacheStorageSettings, { entry in
|
||||
let currentSettings: CacheStorageSettings
|
||||
if let entry = entry as? CacheStorageSettings {
|
||||
currentSettings = entry
|
||||
} else {
|
||||
currentSettings = CacheStorageSettings.defaultSettings
|
||||
}
|
||||
return f(currentSettings)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -5,10 +5,6 @@ import Foundation
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public protocol TelegramMediaResource: MediaResource, Coding {
|
||||
func isEqual(to: TelegramMediaResource) -> Bool
|
||||
}
|
||||
|
||||
protocol TelegramCloudMediaResource: TelegramMediaResource {
|
||||
var datacenterId: Int { get }
|
||||
var apiInputLocation: Api.InputFileLocation { get }
|
||||
|
||||
159
TelegramCore/CollectCacheUsageStats.swift
Normal file
159
TelegramCore/CollectCacheUsageStats.swift
Normal file
@ -0,0 +1,159 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public enum PeerCacheUsageCategory: Int32 {
|
||||
case image = 0
|
||||
case video
|
||||
case audio
|
||||
case file
|
||||
}
|
||||
|
||||
public struct CacheUsageStats {
|
||||
public let media: [PeerId: [PeerCacheUsageCategory: [MediaId: Int64]]]
|
||||
public let mediaResourceIds: [MediaId: [MediaResourceId]]
|
||||
public let peers: [PeerId: Peer]
|
||||
|
||||
public init(media: [PeerId: [PeerCacheUsageCategory: [MediaId: Int64]]], mediaResourceIds: [MediaId: [MediaResourceId]], peers: [PeerId: Peer]) {
|
||||
self.media = media
|
||||
self.mediaResourceIds = mediaResourceIds
|
||||
self.peers = peers
|
||||
}
|
||||
}
|
||||
|
||||
public enum CacheUsageStatsResult {
|
||||
case progress(Float)
|
||||
case result(CacheUsageStats)
|
||||
}
|
||||
|
||||
private enum CollectCacheUsageStatsError {
|
||||
case done(CacheUsageStats)
|
||||
}
|
||||
|
||||
private final class CacheUsageStatsState {
|
||||
var media: [PeerId: [PeerCacheUsageCategory: [MediaId: Int64]]] = [:]
|
||||
var mediaResourceIds: [MediaId: [MediaResourceId]] = [:]
|
||||
var lowerBound: MessageIndex?
|
||||
}
|
||||
|
||||
public func collectCacheUsageStats(account: Account) -> Signal<CacheUsageStatsResult, NoError> {
|
||||
let state = Atomic<CacheUsageStatsState>(value: CacheUsageStatsState())
|
||||
|
||||
let fetch = account.postbox.modify { modifier -> ([PeerId : Set<MediaId>], [MediaId : Media], MessageIndex?) in
|
||||
return modifier.enumerateMedia(lowerBound: state.with { $0.lowerBound }, limit: 1000)
|
||||
} |> mapError { _ -> CollectCacheUsageStatsError in preconditionFailure() }
|
||||
|
||||
let process: ([PeerId : Set<MediaId>], [MediaId : Media], MessageIndex?) -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> = { mediaByPeer, mediaRefs, updatedLowerBound in
|
||||
var mediaIdToPeerId: [MediaId: PeerId] = [:]
|
||||
for (peerId, mediaIds) in mediaByPeer {
|
||||
for id in mediaIds {
|
||||
mediaIdToPeerId[id] = peerId
|
||||
}
|
||||
}
|
||||
|
||||
var resourceIdToMediaId: [WrappedMediaResourceId: (MediaId, PeerCacheUsageCategory)] = [:]
|
||||
var mediaResourceIds: [MediaId: [MediaResourceId]] = [:]
|
||||
var resourceIds: [MediaResourceId] = []
|
||||
for (id, media) in mediaRefs {
|
||||
mediaResourceIds[id] = []
|
||||
switch media {
|
||||
case let image as TelegramMediaImage:
|
||||
for representation in image.representations {
|
||||
resourceIds.append(representation.resource.id)
|
||||
resourceIdToMediaId[WrappedMediaResourceId(representation.resource.id)] = (id, .image)
|
||||
mediaResourceIds[id]!.append(representation.resource.id)
|
||||
}
|
||||
case let file as TelegramMediaFile:
|
||||
var category: PeerCacheUsageCategory = .file
|
||||
loop: for attribute in file.attributes {
|
||||
switch attribute {
|
||||
case .Video:
|
||||
category = .video
|
||||
break loop
|
||||
case .Audio:
|
||||
category = .audio
|
||||
break loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
for representation in file.previewRepresentations {
|
||||
resourceIds.append(representation.resource.id)
|
||||
resourceIdToMediaId[WrappedMediaResourceId(representation.resource.id)] = (id, category)
|
||||
mediaResourceIds[id]!.append(representation.resource.id)
|
||||
}
|
||||
resourceIds.append(file.resource.id)
|
||||
resourceIdToMediaId[WrappedMediaResourceId(file.resource.id)] = (id, category)
|
||||
mediaResourceIds[id]!.append(file.resource.id)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
return account.postbox.mediaBox.collectResourceCacheUsage(resourceIds)
|
||||
|> mapError { _ -> CollectCacheUsageStatsError in preconditionFailure() }
|
||||
|> mapToSignal { result -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
state.with { state -> Void in
|
||||
state.lowerBound = updatedLowerBound
|
||||
for (wrappedId, size) in result {
|
||||
if let (id, category) = resourceIdToMediaId[wrappedId] {
|
||||
if let peerId = mediaIdToPeerId[id] {
|
||||
if state.media[peerId] == nil {
|
||||
state.media[peerId] = [:]
|
||||
}
|
||||
if state.media[peerId]![category] == nil {
|
||||
state.media[peerId]![category] = [:]
|
||||
}
|
||||
var currentSize: Int64 = 0
|
||||
if let current = state.media[peerId]![category]![id] {
|
||||
currentSize = current
|
||||
}
|
||||
state.media[peerId]![category]![id] = currentSize + size
|
||||
}
|
||||
}
|
||||
}
|
||||
for (id, ids) in mediaResourceIds {
|
||||
state.mediaResourceIds[id] = ids
|
||||
}
|
||||
}
|
||||
if updatedLowerBound == nil {
|
||||
let (finalMedia, finalMediaResourceIds) = state.with { state -> ([PeerId: [PeerCacheUsageCategory: [MediaId: Int64]]], [MediaId: [MediaResourceId]]) in
|
||||
return (state.media, state.mediaResourceIds)
|
||||
}
|
||||
return account.postbox.modify { modifier -> CacheUsageStats in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for peerId in finalMedia.keys {
|
||||
if let peer = modifier.getPeer(peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
return CacheUsageStats(media: finalMedia, mediaResourceIds: finalMediaResourceIds, peers: peers)
|
||||
} |> mapError { _ -> CollectCacheUsageStatsError in preconditionFailure() }
|
||||
|> mapToSignal { stats -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
return .fail(.done(stats))
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let signal = (fetch |> mapToSignal { mediaByPeer, mediaRefs, updatedLowerBound -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
return process(mediaByPeer, mediaRefs, updatedLowerBound)
|
||||
}) |> restart
|
||||
|
||||
return signal |> `catch` { error in
|
||||
switch error {
|
||||
case let .done(result):
|
||||
return .single(.result(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func clearCachedMediaResources(account: Account, mediaResourceIds: Set<WrappedMediaResourceId>) -> Signal<Void, NoError> {
|
||||
return account.postbox.mediaBox.removeCachedResources(mediaResourceIds)
|
||||
}
|
||||
@ -28,11 +28,11 @@ class Download: NSObject, MTRequestMessageServiceDelegate {
|
||||
let mtProto: MTProto
|
||||
let requestService: MTRequestMessageService
|
||||
|
||||
init(datacenterId: Int, context: MTContext, masterDatacenterId: Int) {
|
||||
init(datacenterId: Int, context: MTContext, masterDatacenterId: Int, usageInfo: MTNetworkUsageCalculationInfo?) {
|
||||
self.datacenterId = datacenterId
|
||||
self.context = context
|
||||
|
||||
self.mtProto = MTProto(context: self.context, datacenterId: datacenterId, usageCalculationInfo: nil)
|
||||
self.mtProto = MTProto(context: self.context, datacenterId: datacenterId, usageCalculationInfo: usageInfo)
|
||||
if datacenterId != masterDatacenterId {
|
||||
self.mtProto.authTokenMasterDatacenterId = masterDatacenterId
|
||||
self.mtProto.requiredAuthToken = Int(datacenterId) as NSNumber
|
||||
|
||||
@ -9,8 +9,8 @@ import SwiftSignalKit
|
||||
import Photos
|
||||
#endif
|
||||
|
||||
private func fetchCloudMediaLocation(account: Account, resource: TelegramCloudMediaResource, size: Int?, range: Range<Int>) -> Signal<MediaResourceDataFetchResult, NoError> {
|
||||
return multipartFetch(account: account, resource: resource, size: size, range: range)
|
||||
private func fetchCloudMediaLocation(account: Account, resource: TelegramCloudMediaResource, size: Int?, range: Range<Int>, tag: MediaResourceFetchTag?) -> Signal<MediaResourceDataFetchResult, NoError> {
|
||||
return multipartFetch(account: account, resource: resource, size: size, range: range, tag: tag)
|
||||
}
|
||||
|
||||
private func fetchLocalFileResource(path: String, move: Bool) -> Signal<MediaResourceDataFetchResult, NoError> {
|
||||
@ -30,13 +30,13 @@ private func fetchLocalFileResource(path: String, move: Bool) -> Signal<MediaRes
|
||||
}
|
||||
}
|
||||
|
||||
func fetchResource(account: Account, resource: MediaResource, range: Range<Int>) -> Signal<MediaResourceDataFetchResult, NoError>? {
|
||||
func fetchResource(account: Account, resource: MediaResource, range: Range<Int>, tag: MediaResourceFetchTag?) -> Signal<MediaResourceDataFetchResult, NoError>? {
|
||||
if let _ = resource as? EmptyMediaResource {
|
||||
return .never()
|
||||
} else if let secretFileResource = resource as? SecretFileMediaResource {
|
||||
return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchSecretFileResource(account: account, resource: secretFileResource, range: range))
|
||||
return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchSecretFileResource(account: account, resource: secretFileResource, range: range, tag: tag))
|
||||
} 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))
|
||||
return .single(.dataPart(data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchCloudMediaLocation(account: account, resource: cloudResource, size: resource.size, range: range, tag: tag))
|
||||
} 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()))
|
||||
|
||||
@ -9,6 +9,6 @@ import Foundation
|
||||
import MtProtoKitDynamic
|
||||
#endif
|
||||
|
||||
func fetchSecretFileResource(account: Account, resource: SecretFileMediaResource, range: Range<Int>) -> Signal<MediaResourceDataFetchResult, NoError> {
|
||||
return multipartFetch(account: account, resource: resource, size: resource.size, range: range, encryptionKey: resource.key, decryptedSize: resource.decryptedSize)
|
||||
func fetchSecretFileResource(account: Account, resource: SecretFileMediaResource, range: Range<Int>, tag: MediaResourceFetchTag?) -> Signal<MediaResourceDataFetchResult, NoError> {
|
||||
return multipartFetch(account: account, resource: resource, size: resource.size, range: range, tag: tag, encryptionKey: resource.key, decryptedSize: resource.decryptedSize)
|
||||
}
|
||||
|
||||
@ -95,6 +95,10 @@ private func actionFromActivity(_ activity: PeerInputActivity?) -> Api.SendMessa
|
||||
return .sendMessageGamePlayAction
|
||||
case let .uploadingFile(progress):
|
||||
return .sendMessageUploadDocumentAction(progress: progress)
|
||||
case .recordingInstantVideo:
|
||||
return .sendMessageRecordRoundAction
|
||||
case .uploadingInstantVideo:
|
||||
return .sendMessageUploadRoundAction
|
||||
}
|
||||
} else {
|
||||
return .sendMessageCancelAction
|
||||
|
||||
21
TelegramCore/MediaResourceNetworkStatsTag.swift
Normal file
21
TelegramCore/MediaResourceNetworkStatsTag.swift
Normal file
@ -0,0 +1,21 @@
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
#else
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public enum MediaResourceStatsCategory {
|
||||
case generic
|
||||
case image
|
||||
case video
|
||||
case audio
|
||||
case file
|
||||
}
|
||||
|
||||
public final class TelegramMediaResourceFetchTag: MediaResourceFetchTag {
|
||||
public let statsCategory: MediaResourceStatsCategory
|
||||
|
||||
public init(statsCategory: MediaResourceStatsCategory) {
|
||||
self.statsCategory = statsCategory
|
||||
}
|
||||
}
|
||||
@ -192,8 +192,8 @@ private final class MultipartFetchManager {
|
||||
}
|
||||
}
|
||||
|
||||
func multipartFetch(account: Account, resource: TelegramCloudMediaResource, size: Int?, range: Range<Int>, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int32? = nil) -> Signal<MediaResourceDataFetchResult, NoError> {
|
||||
return account.network.download(datacenterId: resource.datacenterId)
|
||||
func multipartFetch(account: Account, resource: TelegramCloudMediaResource, size: Int?, range: Range<Int>, tag: MediaResourceFetchTag?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int32? = nil) -> Signal<MediaResourceDataFetchResult, NoError> {
|
||||
return account.network.download(datacenterId: resource.datacenterId, tag: tag)
|
||||
|> mapToSignal { download -> Signal<MediaResourceDataFetchResult, NoError> in
|
||||
return Signal { subscriber in
|
||||
let inputLocation = resource.apiInputLocation
|
||||
|
||||
@ -322,8 +322,8 @@ enum MultipartUploadSource {
|
||||
case data(Data)
|
||||
}
|
||||
|
||||
func multipartUpload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, hintFileSize: Int? = nil) -> Signal<MultipartUploadResult, NoError> {
|
||||
return network.download(datacenterId: network.datacenterId)
|
||||
func multipartUpload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, tag: MediaResourceFetchTag?, hintFileSize: Int? = nil) -> Signal<MultipartUploadResult, NoError> {
|
||||
return network.download(datacenterId: network.datacenterId, tag: tag)
|
||||
|> mapToSignal { download -> Signal<MultipartUploadResult, NoError> in
|
||||
return Signal { subscriber in
|
||||
var encryptionKey: SecretFileEncryptionKey?
|
||||
@ -348,7 +348,7 @@ func multipartUpload(network: Network, postbox: Postbox, source: MultipartUpload
|
||||
case let .resource(resource):
|
||||
dataSignal = postbox.mediaBox.resourceData(resource, option: .incremental(waitUntilFetchStatus: true)) |> map { MultipartUploadData.resourceData($0) }
|
||||
headerSize = resource.headerSize
|
||||
fetchedResource = postbox.mediaBox.fetchedResource(resource) |> map {_ in}
|
||||
fetchedResource = postbox.mediaBox.fetchedResource(resource, tag: tag) |> map {_ in}
|
||||
case let .data(data):
|
||||
dataSignal = .single(.data(data))
|
||||
headerSize = 0
|
||||
|
||||
@ -84,6 +84,7 @@ struct OperationLogTags {
|
||||
|
||||
private enum PreferencesKeyValues: Int32 {
|
||||
case globalNotifications = 0
|
||||
case cacheStorageSettings = 1
|
||||
}
|
||||
|
||||
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
||||
@ -98,4 +99,10 @@ public struct PreferencesKeys {
|
||||
key.setInt32(0, value: PreferencesKeyValues.globalNotifications.rawValue)
|
||||
return key
|
||||
}()
|
||||
|
||||
public static let cacheStorageSettings: ValueBoxKey = {
|
||||
let key = ValueBoxKey(length: 4)
|
||||
key.setInt32(0, value: PreferencesKeyValues.cacheStorageSettings.rawValue)
|
||||
return key
|
||||
}()
|
||||
}
|
||||
|
||||
@ -94,7 +94,206 @@ private var registeredLoggingFunctions: Void = {
|
||||
registerLoggingFunctions()
|
||||
}()
|
||||
|
||||
func initializedNetwork(apiId: Int32, supplementary: Bool, datacenterId: Int, keychain: Keychain, networkUsageInfoPath: String?, testingEnvironment: Bool) -> Signal<Network, NoError> {
|
||||
private enum UsageCalculationConnection: Int32 {
|
||||
case cellular = 0
|
||||
case wifi = 1
|
||||
}
|
||||
|
||||
private enum UsageCalculationDirection: Int32 {
|
||||
case incoming = 0
|
||||
case outgoing = 1
|
||||
}
|
||||
|
||||
private struct UsageCalculationTag {
|
||||
let connection: UsageCalculationConnection
|
||||
let direction: UsageCalculationDirection
|
||||
let category: MediaResourceStatsCategory
|
||||
|
||||
var key: Int32 {
|
||||
switch category {
|
||||
case .generic:
|
||||
return 0 * 4 + self.connection.rawValue * 2 + self.direction.rawValue * 1
|
||||
case .image:
|
||||
return 1 * 4 + self.connection.rawValue * 2 + self.direction.rawValue * 1
|
||||
case .video:
|
||||
return 2 * 4 + self.connection.rawValue * 2 + self.direction.rawValue * 1
|
||||
case .audio:
|
||||
return 3 * 4 + self.connection.rawValue * 2 + self.direction.rawValue * 1
|
||||
case .file:
|
||||
return 4 * 4 + self.connection.rawValue * 2 + self.direction.rawValue * 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum UsageCalculationResetKey: Int32 {
|
||||
case wifi = 80 //20 * 4 + 0
|
||||
case cellular = 81 //20 * 4 + 2
|
||||
}
|
||||
|
||||
private func usageCalculationInfo(basePath: String, category: MediaResourceStatsCategory?) -> MTNetworkUsageCalculationInfo {
|
||||
let categoryValue: MediaResourceStatsCategory
|
||||
if let category = category {
|
||||
categoryValue = category
|
||||
} else {
|
||||
categoryValue = .generic
|
||||
}
|
||||
return MTNetworkUsageCalculationInfo(filePath: basePath + "/network-stats", incomingWWANKey: UsageCalculationTag(connection: .cellular, direction: .incoming, category: categoryValue).key, outgoingWWANKey: UsageCalculationTag(connection: .cellular, direction: .outgoing, category: categoryValue).key, incomingOtherKey: UsageCalculationTag(connection: .wifi, direction: .incoming, category: categoryValue).key, outgoingOtherKey: UsageCalculationTag(connection: .wifi, direction: .outgoing, category: categoryValue).key)
|
||||
}
|
||||
|
||||
public struct NetworkUsageStatsDirectionsEntry: Equatable {
|
||||
public let incoming: Int64
|
||||
public let outgoing: Int64
|
||||
|
||||
public static func ==(lhs: NetworkUsageStatsDirectionsEntry, rhs: NetworkUsageStatsDirectionsEntry) -> Bool {
|
||||
return lhs.incoming == rhs.incoming && lhs.outgoing == rhs.outgoing
|
||||
}
|
||||
}
|
||||
|
||||
public struct NetworkUsageStatsConnectionsEntry: Equatable {
|
||||
public let cellular: NetworkUsageStatsDirectionsEntry
|
||||
public let wifi: NetworkUsageStatsDirectionsEntry
|
||||
|
||||
public static func ==(lhs: NetworkUsageStatsConnectionsEntry, rhs: NetworkUsageStatsConnectionsEntry) -> Bool {
|
||||
return lhs.cellular == rhs.cellular && lhs.wifi == rhs.wifi
|
||||
}
|
||||
}
|
||||
|
||||
public struct NetworkUsageStats: Equatable {
|
||||
public let generic: NetworkUsageStatsConnectionsEntry
|
||||
public let image: NetworkUsageStatsConnectionsEntry
|
||||
public let video: NetworkUsageStatsConnectionsEntry
|
||||
public let audio: NetworkUsageStatsConnectionsEntry
|
||||
public let file: NetworkUsageStatsConnectionsEntry
|
||||
|
||||
public let resetWifiTimestamp: Int32
|
||||
public let resetCellularTimestamp: Int32
|
||||
|
||||
public static func ==(lhs: NetworkUsageStats, rhs: NetworkUsageStats) -> Bool {
|
||||
return lhs.generic == rhs.generic && lhs.image == rhs.image && lhs.video == rhs.video && lhs.audio == rhs.audio && lhs.file == rhs.file && lhs.resetWifiTimestamp == rhs.resetWifiTimestamp && lhs.resetCellularTimestamp == rhs.resetCellularTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
public struct ResetNetworkUsageStats: OptionSet {
|
||||
public var rawValue: Int32
|
||||
|
||||
public init(rawValue: Int32) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
public init() {
|
||||
self.rawValue = 0
|
||||
}
|
||||
|
||||
public static let wifi = ResetNetworkUsageStats(rawValue: 1 << 0)
|
||||
public static let cellular = ResetNetworkUsageStats(rawValue: 1 << 1)
|
||||
}
|
||||
|
||||
func networkUsageStats(basePath: String, reset: ResetNetworkUsageStats) -> Signal<NetworkUsageStats, NoError> {
|
||||
return ((Signal<NetworkUsageStats, NoError> { subscriber in
|
||||
let info = usageCalculationInfo(basePath: basePath, category: nil)
|
||||
let manager = MTNetworkUsageManager(info: info)!
|
||||
|
||||
let rawKeys: [UsageCalculationTag] = [
|
||||
UsageCalculationTag(connection: .cellular, direction: .incoming, category: .generic),
|
||||
UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .generic),
|
||||
UsageCalculationTag(connection: .wifi, direction: .incoming, category: .generic),
|
||||
UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .generic),
|
||||
|
||||
UsageCalculationTag(connection: .cellular, direction: .incoming, category: .image),
|
||||
UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .image),
|
||||
UsageCalculationTag(connection: .wifi, direction: .incoming, category: .image),
|
||||
UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .image),
|
||||
|
||||
UsageCalculationTag(connection: .cellular, direction: .incoming, category: .video),
|
||||
UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .video),
|
||||
UsageCalculationTag(connection: .wifi, direction: .incoming, category: .video),
|
||||
UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .video),
|
||||
|
||||
UsageCalculationTag(connection: .cellular, direction: .incoming, category: .audio),
|
||||
UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .audio),
|
||||
UsageCalculationTag(connection: .wifi, direction: .incoming, category: .audio),
|
||||
UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .audio),
|
||||
|
||||
UsageCalculationTag(connection: .cellular, direction: .incoming, category: .file),
|
||||
UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .file),
|
||||
UsageCalculationTag(connection: .wifi, direction: .incoming, category: .file),
|
||||
UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .file)
|
||||
]
|
||||
|
||||
var keys: [NSNumber] = rawKeys.map { $0.key as NSNumber }
|
||||
|
||||
var resetKeys: [NSNumber] = []
|
||||
var resetAddKeys: [NSNumber: NSNumber] = [:]
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
if reset.contains(.wifi) {
|
||||
resetKeys = rawKeys.filter({ $0.connection == .wifi }).map({ $0.key as NSNumber })
|
||||
resetAddKeys[UsageCalculationResetKey.wifi.rawValue as NSNumber] = Int64(timestamp) as NSNumber
|
||||
}
|
||||
if reset.contains(.cellular) {
|
||||
resetKeys = rawKeys.filter({ $0.connection == .cellular }).map({ $0.key as NSNumber })
|
||||
resetAddKeys[UsageCalculationResetKey.cellular.rawValue as NSNumber] = Int64(timestamp) as NSNumber
|
||||
}
|
||||
if !resetKeys.isEmpty {
|
||||
manager.resetKeys(resetKeys, setKeys: resetAddKeys, completion: {})
|
||||
}
|
||||
keys.append(UsageCalculationResetKey.cellular.rawValue as NSNumber)
|
||||
keys.append(UsageCalculationResetKey.wifi.rawValue as NSNumber)
|
||||
|
||||
let disposable = manager.currentStats(forKeys: keys).start(next: { next in
|
||||
var dict: [Int32: Int64] = [:]
|
||||
for key in keys {
|
||||
dict[key.int32Value] = 0
|
||||
}
|
||||
(next as! NSDictionary).enumerateKeysAndObjects({ key, value, _ in
|
||||
dict[(key as AnyObject).int32Value] = (value as AnyObject).int64Value!
|
||||
})
|
||||
subscriber.putNext(NetworkUsageStats(
|
||||
generic: NetworkUsageStatsConnectionsEntry(
|
||||
cellular: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .cellular, direction: .incoming, category: .generic).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .generic).key]!),
|
||||
wifi: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .wifi, direction: .incoming, category: .generic).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .generic).key]!)),
|
||||
image: NetworkUsageStatsConnectionsEntry(
|
||||
cellular: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .cellular, direction: .incoming, category: .image).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .image).key]!),
|
||||
wifi: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .wifi, direction: .incoming, category: .image).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .image).key]!)),
|
||||
video: NetworkUsageStatsConnectionsEntry(
|
||||
cellular: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .cellular, direction: .incoming, category: .video).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .video).key]!),
|
||||
wifi: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .wifi, direction: .incoming, category: .video).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .video).key]!)),
|
||||
audio: NetworkUsageStatsConnectionsEntry(
|
||||
cellular: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .cellular, direction: .incoming, category: .audio).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .audio).key]!),
|
||||
wifi: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .wifi, direction: .incoming, category: .audio).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .audio).key]!)),
|
||||
file: NetworkUsageStatsConnectionsEntry(
|
||||
cellular: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .cellular, direction: .incoming, category: .file).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .cellular, direction: .outgoing, category: .file).key]!),
|
||||
wifi: NetworkUsageStatsDirectionsEntry(
|
||||
incoming: dict[UsageCalculationTag(connection: .wifi, direction: .incoming, category: .file).key]!,
|
||||
outgoing: dict[UsageCalculationTag(connection: .wifi, direction: .outgoing, category: .file).key]!)),
|
||||
resetWifiTimestamp: Int32(dict[UsageCalculationResetKey.wifi.rawValue]!),
|
||||
resetCellularTimestamp: Int32(dict[UsageCalculationResetKey.cellular.rawValue]!)
|
||||
))
|
||||
})!
|
||||
return ActionDisposable {
|
||||
disposable.dispose()
|
||||
}
|
||||
}) |> then(Signal<NetworkUsageStats, NoError>.complete() |> delay(5.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
||||
}
|
||||
|
||||
func initializedNetwork(apiId: Int32, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool) -> Signal<Network, NoError> {
|
||||
return Signal { subscriber in
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
let _ = registeredLoggingFunctions
|
||||
@ -131,7 +330,7 @@ func initializedNetwork(apiId: Int32, supplementary: Bool, datacenterId: Int, ke
|
||||
}
|
||||
|
||||
context.keychain = keychain
|
||||
let mtProto = MTProto(context: context, datacenterId: datacenterId, usageCalculationInfo: nil)!
|
||||
let mtProto = MTProto(context: context, datacenterId: datacenterId, usageCalculationInfo: usageCalculationInfo(basePath: basePath, category: nil))!
|
||||
|
||||
let connectionStatus = Promise<ConnectionStatus>(.WaitingForNetwork)
|
||||
|
||||
@ -159,7 +358,7 @@ func initializedNetwork(apiId: Int32, supplementary: Bool, datacenterId: Int, ke
|
||||
mtProto.delegate = connectionStatusDelegate
|
||||
mtProto.add(requestService)
|
||||
|
||||
subscriber.putNext(Network(datacenterId: datacenterId, context: context, mtProto: mtProto, requestService: requestService, connectionStatusDelegate: connectionStatusDelegate, _connectionStatus: connectionStatus))
|
||||
subscriber.putNext(Network(datacenterId: datacenterId, context: context, mtProto: mtProto, requestService: requestService, connectionStatusDelegate: connectionStatusDelegate, _connectionStatus: connectionStatus, basePath: basePath))
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
|
||||
@ -172,6 +371,7 @@ public class Network: NSObject, MTRequestMessageServiceDelegate {
|
||||
let context: MTContext
|
||||
let mtProto: MTProto
|
||||
let requestService: MTRequestMessageService
|
||||
let basePath: String
|
||||
private let connectionStatusDelegate: MTProtoConnectionStatusDelegate
|
||||
|
||||
private let _connectionStatus: Promise<ConnectionStatus>
|
||||
@ -184,13 +384,14 @@ public class Network: NSObject, MTRequestMessageServiceDelegate {
|
||||
|
||||
var loggedOut: (() -> Void)?
|
||||
|
||||
fileprivate init(datacenterId: Int, context: MTContext, mtProto: MTProto, requestService: MTRequestMessageService, connectionStatusDelegate: MTProtoConnectionStatusDelegate, _connectionStatus: Promise<ConnectionStatus>) {
|
||||
fileprivate init(datacenterId: Int, context: MTContext, mtProto: MTProto, requestService: MTRequestMessageService, connectionStatusDelegate: MTProtoConnectionStatusDelegate, _connectionStatus: Promise<ConnectionStatus>, basePath: String) {
|
||||
self.datacenterId = datacenterId
|
||||
self.context = context
|
||||
self.mtProto = mtProto
|
||||
self.requestService = requestService
|
||||
self.connectionStatusDelegate = connectionStatusDelegate
|
||||
self._connectionStatus = _connectionStatus
|
||||
self.basePath = basePath
|
||||
|
||||
super.init()
|
||||
|
||||
@ -219,10 +420,10 @@ public class Network: NSObject, MTRequestMessageServiceDelegate {
|
||||
self.loggedOut?()
|
||||
}
|
||||
|
||||
func download(datacenterId: Int) -> Signal<Download, NoError> {
|
||||
func download(datacenterId: Int, tag: MediaResourceFetchTag?) -> Signal<Download, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
if let strongSelf = self {
|
||||
subscriber.putNext(Download(datacenterId: datacenterId, context: strongSelf.context, masterDatacenterId: strongSelf.datacenterId))
|
||||
subscriber.putNext(Download(datacenterId: datacenterId, context: strongSelf.context, masterDatacenterId: strongSelf.datacenterId, usageInfo: usageCalculationInfo(basePath: strongSelf.basePath, category: (tag as? TelegramMediaResourceFetchTag)?.statsCategory)))
|
||||
}
|
||||
subscriber.putCompletion()
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@ public enum PeerInputActivity: Comparable {
|
||||
case uploadingFile(progress: Int32)
|
||||
case recordingVoice
|
||||
case playingGame
|
||||
case recordingInstantVideo
|
||||
case uploadingInstantVideo
|
||||
|
||||
public static func ==(lhs: PeerInputActivity, rhs: PeerInputActivity) -> Bool {
|
||||
switch lhs {
|
||||
@ -32,6 +34,18 @@ public enum PeerInputActivity: Comparable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .recordingInstantVideo:
|
||||
if case .recordingInstantVideo = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .uploadingInstantVideo:
|
||||
if case .uploadingInstantVideo = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,8 +57,12 @@ public enum PeerInputActivity: Comparable {
|
||||
return 1
|
||||
case .recordingVoice:
|
||||
return 2
|
||||
case .playingGame:
|
||||
case .recordingInstantVideo:
|
||||
return 3
|
||||
case .uploadingInstantVideo:
|
||||
return 4
|
||||
case .playingGame:
|
||||
return 5
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +88,10 @@ extension PeerInputActivity {
|
||||
self = .uploadingFile(progress: progress)
|
||||
case let .sendMessageUploadVideoAction(progress):
|
||||
self = .uploadingFile(progress: progress)
|
||||
case .sendMessageRecordRoundAction:
|
||||
self = .recordingInstantVideo
|
||||
case .sendMessageUploadRoundAction:
|
||||
self = .uploadingInstantVideo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ public func updateAccountPhoto(account:Account, resource:MediaResource) -> Signa
|
||||
|
||||
public func updatePeerPhoto(account:Account, peerId:PeerId, resource:MediaResource) -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> {
|
||||
return account.postbox.loadedPeerWithId(peerId) |> mapError {_ in return .generic} |> mapToSignal { peer in
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .resource(resource), encrypt: false)
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .resource(resource), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image))
|
||||
|> mapError {_ in return .generic}
|
||||
|> mapToSignal { result -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
|
||||
switch result {
|
||||
@ -89,7 +89,12 @@ public func updatePeerPhoto(account:Account, peerId:PeerId, resource:MediaResour
|
||||
for chat in updates.chats {
|
||||
if chat.peerId == peerId {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
return .single(.complete(groupOrChannel.profileImageRepresentations))
|
||||
return account.postbox.modify { modifier -> UpdatePeerPhotoStatus in
|
||||
updatePeers(modifier: modifier, peers: [groupOrChannel], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return .complete(groupOrChannel.profileImageRepresentations)
|
||||
} |> mapError { _ in return .generic }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ func messageContentToUpload(network: Network, postbox: Postbox, transformOutgoin
|
||||
|
||||
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, source: .resource(largestRepresentation.resource), encrypt: peerId.namespace == Namespaces.Peer.SecretChat)
|
||||
return multipartUpload(network: network, postbox: postbox, source: .resource(largestRepresentation.resource), encrypt: peerId.namespace == Namespaces.Peer.SecretChat, tag: TelegramMediaResourceFetchTag(statsCategory: .image))
|
||||
|> map { next -> PendingMessageUploadedContentResult in
|
||||
switch next {
|
||||
case let .progress(progress):
|
||||
@ -153,7 +153,7 @@ private enum UploadedMediaThumbnail {
|
||||
}
|
||||
|
||||
private func uploadedThumbnail(network: Network, postbox: Postbox, image: TelegramMediaImageRepresentation) -> Signal<Api.InputFile?, NoError> {
|
||||
return multipartUpload(network: network, postbox: postbox, source: .resource(image.resource), encrypt: false)
|
||||
return multipartUpload(network: network, postbox: postbox, source: .resource(image.resource), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image))
|
||||
|> mapToSignal { result -> Signal<Api.InputFile?, NoError> in
|
||||
switch result {
|
||||
case .progress:
|
||||
@ -166,6 +166,20 @@ private func uploadedThumbnail(network: Network, postbox: Postbox, image: Telegr
|
||||
}
|
||||
}
|
||||
|
||||
public func statsCategoryForFileWithAttributes(_ attributes: [TelegramMediaFileAttribute]) -> MediaResourceStatsCategory {
|
||||
for attribute in attributes {
|
||||
switch attribute {
|
||||
case .Audio:
|
||||
return .audio
|
||||
case .Video:
|
||||
return .video
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
return .file
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -173,7 +187,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, transf
|
||||
} else if let resource = file.resource as? LocalFileReferenceMediaResource, let size = resource.size {
|
||||
hintSize = Int(size)
|
||||
}
|
||||
let upload = multipartUpload(network: network, postbox: postbox, source: .resource(file.resource), encrypt: peerId.namespace == Namespaces.Peer.SecretChat, hintFileSize: hintSize)
|
||||
let upload = multipartUpload(network: network, postbox: postbox, source: .resource(file.resource), encrypt: peerId.namespace == Namespaces.Peer.SecretChat, tag: TelegramMediaResourceFetchTag(statsCategory: statsCategoryForFileWithAttributes(file.attributes)), hintFileSize: hintSize)
|
||||
/*|> map { next -> UploadedMediaFileContent in
|
||||
switch next {
|
||||
case let .progress(progress):
|
||||
|
||||
@ -140,7 +140,7 @@ private enum UploadMediaEvent {
|
||||
}
|
||||
|
||||
private func uploadedImage(account: Account, text: String, data: Data) -> Signal<UploadMediaEvent, NoError> {
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false)
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image))
|
||||
|> map { next -> UploadMediaEvent in
|
||||
switch next {
|
||||
case let .inputFile(inputFile):
|
||||
@ -154,7 +154,7 @@ private func uploadedImage(account: Account, text: String, data: Data) -> Signal
|
||||
}
|
||||
|
||||
private func uploadedFile(account: Account, text: String, data: Data, mimeType: String, attributes: [TelegramMediaFileAttribute]) -> Signal<UploadMediaEvent, NoError> {
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false)
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: statsCategoryForFileWithAttributes(attributes)))
|
||||
|> map { next -> UploadMediaEvent in
|
||||
switch next {
|
||||
case let .inputFile(inputFile):
|
||||
|
||||
@ -1,9 +1,26 @@
|
||||
|
||||
public func dataSizeString(_ size: Int) -> String {
|
||||
if size >= 1024 * 1024 {
|
||||
if size >= 1024 * 1024 * 1024 {
|
||||
let remainder = (size % (1024 * 1024 * 1024)) / (1024 * 1024 * 102)
|
||||
if remainder != 0 {
|
||||
return "\(size / (1024 * 1024 * 1024)),\(remainder) GB"
|
||||
} else {
|
||||
return "\(size / (1024 * 1024 * 1024)) GB"
|
||||
}
|
||||
} else if size >= 1024 * 1024 {
|
||||
let remainder = (size % (1024 * 1024)) / (1024 * 102)
|
||||
if remainder != 0 {
|
||||
return "\(size / (1024 * 1024)),\(remainder) MB"
|
||||
} else {
|
||||
return "\(size / (1024 * 1024)) MB"
|
||||
}
|
||||
} else if size >= 1024 {
|
||||
let remainder = (size % (1024)) / (102)
|
||||
if remainder != 0 {
|
||||
return "\(size / 1024),\(remainder) KB"
|
||||
} else {
|
||||
return "\(size / 1024) KB"
|
||||
}
|
||||
} else {
|
||||
return "\(size) B"
|
||||
}
|
||||
|
||||
11
TelegramCore/TelegramMediaResource.swift
Normal file
11
TelegramCore/TelegramMediaResource.swift
Normal file
@ -0,0 +1,11 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
#else
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public protocol TelegramMediaResource: MediaResource, Coding {
|
||||
func isEqual(to: TelegramMediaResource) -> Bool
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user