From cc7fc32ab14f62e8407f770b1663155be2da3329 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 12 Aug 2025 16:10:08 +0400 Subject: [PATCH] Update API --- .../Telegram-iOS/en.lproj/Localizable.strings | 5 ++ .../TelegramEngine/Peers/SavedMusic.swift | 57 +++++++++++++------ .../Peers/TelegramEnginePeers.swift | 4 +- .../Sources/GiftViewScreen.swift | 3 +- .../TelegramUI/Sources/ChatController.swift | 43 ++++++++++++-- 5 files changed, 84 insertions(+), 28 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 1a2573c803..4fe03ded5e 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -14911,3 +14911,8 @@ Sorry for the inconvenience."; "Notification.StarsGift.UpgradePrepaid" = "%@ unpacked the gift that you helped upgrade"; "Gift.View.Unknown.Title" = "Gift"; + +"Conversation.StopVoiceMessageTitle" = "Audio Recording"; +"Conversation.StopVoiceMessageDescription" = "Are you sure you want to stop recording?"; +"Conversation.StopVoiceMessageDiscardAction" = "Discard"; +"Conversation.StopVoiceMessagePauseAction" = "Pause"; diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/SavedMusic.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/SavedMusic.swift index b86fd49e3e..ad7cfafa7e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/SavedMusic.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/SavedMusic.swift @@ -8,14 +8,34 @@ public enum AddSavedMusicError { case generic } -func _internal_addSavedMusic(account: Account, file: TelegramMediaFile) -> Signal { - guard let resource = file.resource as? CloudDocumentMediaResource else { - return .complete() +private func revalidatedMusic(account: Account, file: FileMediaReference, signal: @escaping (CloudDocumentMediaResource) -> Signal) -> Signal { + guard let resource = file.media.resource as? CloudDocumentMediaResource else { + return .fail(MTRpcError(errorCode: 500, errorDescription: "Internal")) } + return signal(resource) + |> `catch` { error -> Signal in + if error.errorDescription == "FILE_REFERENCE_EXPIRED" { + return revalidateMediaResourceReference(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, revalidationContext: account.mediaReferenceRevalidationContext, info: TelegramCloudMediaResourceFetchInfo(reference: file.resourceReference(resource), preferBackgroundReferenceRevalidation: false, continueInBackground: false), resource: resource) + |> mapError { _ -> MTRpcError in + return MTRpcError(errorCode: 500, errorDescription: "Internal") + } + |> mapToSignal { result -> Signal in + guard let resource = result.updatedResource as? CloudDocumentMediaResource else { + return .fail(MTRpcError(errorCode: 500, errorDescription: "Internal")) + } + return signal(resource) + } + } else { + return .fail(error) + } + } +} + +func _internal_addSavedMusic(account: Account, file: FileMediaReference) -> Signal { return account.postbox.transaction { transaction in if let cachedSavedMusic = transaction.retrieveItemCacheEntry(id: entryId(peerId: account.peerId))?.get(CachedProfileSavedMusic.self) { var updatedFiles = cachedSavedMusic.files - updatedFiles.insert(file, at: 0) + updatedFiles.insert(file.media, at: 0) let updatedCount = max(0, cachedSavedMusic.count + 1) if let entry = CodableEntry(CachedProfileSavedMusic(files: updatedFiles, count: updatedCount)) { transaction.putItemCacheEntry(id: entryId(peerId: account.peerId), entry: entry) @@ -24,14 +44,16 @@ func _internal_addSavedMusic(account: Account, file: TelegramMediaFile) -> Signa transaction.updatePeerCachedData(peerIds: Set([account.peerId]), update: { _, cachedData -> CachedPeerData? in if let cachedData = cachedData as? CachedUserData { var updatedData = cachedData - updatedData = updatedData.withUpdatedSavedMusic(file) + updatedData = updatedData.withUpdatedSavedMusic(file.media) return updatedData } else { return cachedData } }) } - return account.network.request(Api.functions.account.saveMusic(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), afterId: nil)) + return revalidatedMusic(account: account, file: file, signal: { resource in + return account.network.request(Api.functions.account.saveMusic(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), afterId: nil)) + }) |> mapError { _ -> AddSavedMusicError in return .generic } @@ -43,13 +65,10 @@ func _internal_addSavedMusic(account: Account, file: TelegramMediaFile) -> Signa |> switchToLatest } -func _internal_removeSavedMusic(account: Account, file: TelegramMediaFile) -> Signal { - guard let resource = file.resource as? CloudDocumentMediaResource else { - return .complete() - } +func _internal_removeSavedMusic(account: Account, file: FileMediaReference) -> Signal { return account.postbox.transaction { transaction in if let cachedSavedMusic = transaction.retrieveItemCacheEntry(id: entryId(peerId: account.peerId))?.get(CachedProfileSavedMusic.self) { - let updatedFiles = cachedSavedMusic.files.filter { $0.fileId != file.id } + let updatedFiles = cachedSavedMusic.files.filter { $0.fileId != file.media.id } let updatedCount = max(0, cachedSavedMusic.count - 1) if let entry = CodableEntry(CachedProfileSavedMusic(files: updatedFiles, count: updatedCount)) { transaction.putItemCacheEntry(id: entryId(peerId: account.peerId), entry: entry) @@ -67,7 +86,9 @@ func _internal_removeSavedMusic(account: Account, file: TelegramMediaFile) -> Si } } let flags: Int32 = 1 << 0 - return account.network.request(Api.functions.account.saveMusic(flags: flags, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), afterId: nil)) + return revalidatedMusic(account: account, file: file, signal: { resource in + return account.network.request(Api.functions.account.saveMusic(flags: flags, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), afterId: nil)) + }) |> `catch` { _ -> Signal in return .complete() } @@ -127,7 +148,7 @@ public final class ProfileSavedMusicContext { private let queue: Queue = .mainQueue() private let account: Account - private let peerId: EnginePeer.Id + public let peerId: EnginePeer.Id private let disposable = MetaDisposable() private let cacheDisposable = MetaDisposable() @@ -229,17 +250,17 @@ public final class ProfileSavedMusicContext { })) } - public func reorderMusic(file: TelegramMediaFile, after: TelegramMediaFile?) -> Signal { + public func reorderMusic(file: FileMediaReference, file: FileMediaReference?) -> Signal { return .complete() } - public func addMusic(file: TelegramMediaFile) -> Signal { + public func addMusic(file: FileMediaReference) -> Signal { return _internal_addSavedMusic(account: self.account, file: file) |> afterCompleted { [weak self] in guard let self else { return } - self.files.insert(file, at: 0) + self.files.insert(file.media, at: 0) if let count = self.count { self.count = count + 1 } @@ -247,13 +268,13 @@ public final class ProfileSavedMusicContext { } } - public func deleteMusic(file: TelegramMediaFile) -> Signal { + public func deleteMusic(file: FileMediaReference) -> Signal { return _internal_removeSavedMusic(account: self.account, file: file) |> afterCompleted { [weak self] in guard let self else { return } - self.files.removeAll(where: { $0.fileId == file.id }) + self.files.removeAll(where: { $0.fileId == file.media.id }) if let count = self.count { self.count = max(0, count - 1) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index dc8cc44916..7ece264f0e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -912,11 +912,11 @@ public extension TelegramEngine { return _internal_reorderProfileTabs(account: self.account, peerId: peerId, order: order) } - public func addSavedMusic(file: TelegramMediaFile) -> Signal { + public func addSavedMusic(file: FileMediaReference) -> Signal { return _internal_addSavedMusic(account: self.account, file: file) } - public func removeSavedMusic(file: TelegramMediaFile) -> Signal { + public func removeSavedMusic(file: FileMediaReference) -> Signal { return _internal_removeSavedMusic(account: self.account, file: file) } diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 117960ad8d..e4f736ae1a 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -3999,9 +3999,8 @@ public class GiftViewScreen: ViewControllerComponentContainer { if let peerId, let savedId { reference = .peer(peerId: peerId, id: savedId) } else { - reference = .message(messageId: message.id) + reference = .message(messageId: giftMessageId.flatMap { EngineMessage.Id(peerId: message.id.peerId, namespace: message.id.namespace, id: $0) } ?? message.id) } - let _ = giftMessageId return (message.id.peerId, senderId ?? message.author?.id, message.author?.compactDisplayTitle, message.id, reference, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, nil, converted, upgraded, isRefunded, canUpgrade, upgradeStars, nil, nil, nil, upgradeMessageId, nil, nil, prepaidUpgradeHash) case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _, _, peerId, senderId, savedId, _, canTransferDate, canResaleDate): var reference: StarGiftReference diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 06afa6c5e5..3b6c8a1f36 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -9801,12 +9801,43 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let _ = self.presentationInterfaceState.inputTextPanelState.mediaRecordingState { alertAction?() Queue.mainQueue().after(delay ? 0.2 : 0.0) { - self.present(textAlertController(context: self.context, updatedPresentationData: self.updatedPresentationData, title: nil, text: self.presentationData.strings.Conversation_DiscardVoiceMessageDescription, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Conversation_DiscardVoiceMessageAction, action: { [weak self] in - self?.stopMediaRecorder() - Queue.mainQueue().after(0.1) { - action() - } - })]), in: .window(.root)) + let alertController = textAlertController( + context: self.context, + updatedPresentationData: self.updatedPresentationData, + title: nil, + text: self.presentationData.strings.Conversation_StopVoiceMessageDescription, + actions: [ + TextAlertAction( + type: .defaultAction, + title: self.presentationData.strings.Conversation_StopVoiceMessagePauseAction, + action: { [weak self] in + self?.stopMediaRecorder(pause: true) + Queue.mainQueue().after(0.1) { + action() + } + } + ), + TextAlertAction( + type: .destructiveAction, + title: self.presentationData.strings.Conversation_StopVoiceMessageDiscardAction, + action: { [weak self] in + self?.stopMediaRecorder() + Queue.mainQueue().after(0.1) { + action() + } + } + ), + TextAlertAction( + type: .genericAction, + title: self.presentationData.strings.Common_Cancel, + action: { + } + ), + ], + actionLayout: .vertical + ) + + self.present(alertController, in: .window(.root)) } return true