Update API

This commit is contained in:
Ilya Laktyushin 2025-08-12 16:10:08 +04:00
parent 8405cd5a19
commit cc7fc32ab1
5 changed files with 84 additions and 28 deletions

View File

@ -14911,3 +14911,8 @@ Sorry for the inconvenience.";
"Notification.StarsGift.UpgradePrepaid" = "%@ unpacked the gift that you helped upgrade"; "Notification.StarsGift.UpgradePrepaid" = "%@ unpacked the gift that you helped upgrade";
"Gift.View.Unknown.Title" = "Gift"; "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";

View File

@ -8,14 +8,34 @@ public enum AddSavedMusicError {
case generic case generic
} }
func _internal_addSavedMusic(account: Account, file: TelegramMediaFile) -> Signal<Never, AddSavedMusicError> { private func revalidatedMusic<T>(account: Account, file: FileMediaReference, signal: @escaping (CloudDocumentMediaResource) -> Signal<T, MTRpcError>) -> Signal<T, MTRpcError> {
guard let resource = file.resource as? CloudDocumentMediaResource else { guard let resource = file.media.resource as? CloudDocumentMediaResource else {
return .complete() return .fail(MTRpcError(errorCode: 500, errorDescription: "Internal"))
} }
return signal(resource)
|> `catch` { error -> Signal<T, MTRpcError> 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<T, MTRpcError> 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<Never, AddSavedMusicError> {
return account.postbox.transaction { transaction in return account.postbox.transaction { transaction in
if let cachedSavedMusic = transaction.retrieveItemCacheEntry(id: entryId(peerId: account.peerId))?.get(CachedProfileSavedMusic.self) { if let cachedSavedMusic = transaction.retrieveItemCacheEntry(id: entryId(peerId: account.peerId))?.get(CachedProfileSavedMusic.self) {
var updatedFiles = cachedSavedMusic.files var updatedFiles = cachedSavedMusic.files
updatedFiles.insert(file, at: 0) updatedFiles.insert(file.media, at: 0)
let updatedCount = max(0, cachedSavedMusic.count + 1) let updatedCount = max(0, cachedSavedMusic.count + 1)
if let entry = CodableEntry(CachedProfileSavedMusic(files: updatedFiles, count: updatedCount)) { if let entry = CodableEntry(CachedProfileSavedMusic(files: updatedFiles, count: updatedCount)) {
transaction.putItemCacheEntry(id: entryId(peerId: account.peerId), entry: entry) 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 transaction.updatePeerCachedData(peerIds: Set([account.peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedUserData { if let cachedData = cachedData as? CachedUserData {
var updatedData = cachedData var updatedData = cachedData
updatedData = updatedData.withUpdatedSavedMusic(file) updatedData = updatedData.withUpdatedSavedMusic(file.media)
return updatedData return updatedData
} else { } else {
return cachedData 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 |> mapError { _ -> AddSavedMusicError in
return .generic return .generic
} }
@ -43,13 +65,10 @@ func _internal_addSavedMusic(account: Account, file: TelegramMediaFile) -> Signa
|> switchToLatest |> switchToLatest
} }
func _internal_removeSavedMusic(account: Account, file: TelegramMediaFile) -> Signal<Never, NoError> { func _internal_removeSavedMusic(account: Account, file: FileMediaReference) -> Signal<Never, NoError> {
guard let resource = file.resource as? CloudDocumentMediaResource else {
return .complete()
}
return account.postbox.transaction { transaction in return account.postbox.transaction { transaction in
if let cachedSavedMusic = transaction.retrieveItemCacheEntry(id: entryId(peerId: account.peerId))?.get(CachedProfileSavedMusic.self) { 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) let updatedCount = max(0, cachedSavedMusic.count - 1)
if let entry = CodableEntry(CachedProfileSavedMusic(files: updatedFiles, count: updatedCount)) { if let entry = CodableEntry(CachedProfileSavedMusic(files: updatedFiles, count: updatedCount)) {
transaction.putItemCacheEntry(id: entryId(peerId: account.peerId), entry: entry) 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 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<Api.Bool, NoError> in |> `catch` { _ -> Signal<Api.Bool, NoError> in
return .complete() return .complete()
} }
@ -127,7 +148,7 @@ public final class ProfileSavedMusicContext {
private let queue: Queue = .mainQueue() private let queue: Queue = .mainQueue()
private let account: Account private let account: Account
private let peerId: EnginePeer.Id public let peerId: EnginePeer.Id
private let disposable = MetaDisposable() private let disposable = MetaDisposable()
private let cacheDisposable = MetaDisposable() private let cacheDisposable = MetaDisposable()
@ -229,17 +250,17 @@ public final class ProfileSavedMusicContext {
})) }))
} }
public func reorderMusic(file: TelegramMediaFile, after: TelegramMediaFile?) -> Signal<Never, NoError> { public func reorderMusic(file: FileMediaReference, file: FileMediaReference?) -> Signal<Never, NoError> {
return .complete() return .complete()
} }
public func addMusic(file: TelegramMediaFile) -> Signal<Never, AddSavedMusicError> { public func addMusic(file: FileMediaReference) -> Signal<Never, AddSavedMusicError> {
return _internal_addSavedMusic(account: self.account, file: file) return _internal_addSavedMusic(account: self.account, file: file)
|> afterCompleted { [weak self] in |> afterCompleted { [weak self] in
guard let self else { guard let self else {
return return
} }
self.files.insert(file, at: 0) self.files.insert(file.media, at: 0)
if let count = self.count { if let count = self.count {
self.count = count + 1 self.count = count + 1
} }
@ -247,13 +268,13 @@ public final class ProfileSavedMusicContext {
} }
} }
public func deleteMusic(file: TelegramMediaFile) -> Signal<Never, NoError> { public func deleteMusic(file: FileMediaReference) -> Signal<Never, NoError> {
return _internal_removeSavedMusic(account: self.account, file: file) return _internal_removeSavedMusic(account: self.account, file: file)
|> afterCompleted { [weak self] in |> afterCompleted { [weak self] in
guard let self else { guard let self else {
return return
} }
self.files.removeAll(where: { $0.fileId == file.id }) self.files.removeAll(where: { $0.fileId == file.media.id })
if let count = self.count { if let count = self.count {
self.count = max(0, count - 1) self.count = max(0, count - 1)
} }

View File

@ -912,11 +912,11 @@ public extension TelegramEngine {
return _internal_reorderProfileTabs(account: self.account, peerId: peerId, order: order) return _internal_reorderProfileTabs(account: self.account, peerId: peerId, order: order)
} }
public func addSavedMusic(file: TelegramMediaFile) -> Signal<Never, AddSavedMusicError> { public func addSavedMusic(file: FileMediaReference) -> Signal<Never, AddSavedMusicError> {
return _internal_addSavedMusic(account: self.account, file: file) return _internal_addSavedMusic(account: self.account, file: file)
} }
public func removeSavedMusic(file: TelegramMediaFile) -> Signal<Never, NoError> { public func removeSavedMusic(file: FileMediaReference) -> Signal<Never, NoError> {
return _internal_removeSavedMusic(account: self.account, file: file) return _internal_removeSavedMusic(account: self.account, file: file)
} }

View File

@ -3999,9 +3999,8 @@ public class GiftViewScreen: ViewControllerComponentContainer {
if let peerId, let savedId { if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId) reference = .peer(peerId: peerId, id: savedId)
} else { } 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) 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): case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _, _, peerId, senderId, savedId, _, canTransferDate, canResaleDate):
var reference: StarGiftReference var reference: StarGiftReference

View File

@ -9801,12 +9801,43 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let _ = self.presentationInterfaceState.inputTextPanelState.mediaRecordingState { if let _ = self.presentationInterfaceState.inputTextPanelState.mediaRecordingState {
alertAction?() alertAction?()
Queue.mainQueue().after(delay ? 0.2 : 0.0) { 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 let alertController = textAlertController(
self?.stopMediaRecorder() context: self.context,
Queue.mainQueue().after(0.1) { updatedPresentationData: self.updatedPresentationData,
action() title: nil,
} text: self.presentationData.strings.Conversation_StopVoiceMessageDescription,
})]), in: .window(.root)) 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 return true