mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Emoji improvents
This commit is contained in:
parent
489c410aca
commit
cd6d2a3b9d
@ -91,7 +91,7 @@ final class InstantPageMediaPlaylistItem: SharedMediaPlaylistItem {
|
||||
if file.fileName?.lowercased().hasSuffix(".ogg") == true {
|
||||
albumArt = nil
|
||||
} else {
|
||||
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
||||
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .standalone(media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .standalone(media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
||||
}
|
||||
|
||||
return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: false)
|
||||
|
@ -473,9 +473,9 @@ public final class ListMessageFileItemNode: ListMessageNode {
|
||||
|
||||
if !voice {
|
||||
if file.fileName?.lowercased().hasSuffix(".ogg") == true {
|
||||
iconImage = .albumArt(file, SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(title: "", performer: "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(title: "", performer: "", isThumbnail: false)))
|
||||
iconImage = .albumArt(file, SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: "", performer: "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: "", performer: "", isThumbnail: false)))
|
||||
} else {
|
||||
iconImage = .albumArt(file, SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(title: title ?? "", performer: performer ?? "", isThumbnail: false)))
|
||||
iconImage = .albumArt(file, SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: false)))
|
||||
}
|
||||
} else {
|
||||
titleText = NSAttributedString(string: " ", font: audioTitleFont, textColor: item.presentationData.theme.theme.list.itemPrimaryTextColor)
|
||||
|
@ -25,11 +25,13 @@ public struct ExternalMusicAlbumArtResourceId {
|
||||
}
|
||||
|
||||
public class ExternalMusicAlbumArtResource: Equatable {
|
||||
public let file: FileMediaReference?
|
||||
public let title: String
|
||||
public let performer: String
|
||||
public let isThumbnail: Bool
|
||||
|
||||
public init(title: String, performer: String, isThumbnail: Bool) {
|
||||
public init(file: FileMediaReference?, title: String, performer: String, isThumbnail: Bool) {
|
||||
self.file = file
|
||||
self.title = title
|
||||
self.performer = performer
|
||||
self.isThumbnail = isThumbnail
|
||||
@ -40,6 +42,9 @@ public class ExternalMusicAlbumArtResource: Equatable {
|
||||
}
|
||||
|
||||
public static func ==(lhs: ExternalMusicAlbumArtResource, rhs: ExternalMusicAlbumArtResource) -> Bool {
|
||||
if lhs.file?.media.fileId != rhs.file?.media.fileId {
|
||||
return false
|
||||
}
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
@ -53,8 +58,10 @@ public class ExternalMusicAlbumArtResource: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public func fetchExternalMusicAlbumArtResource(engine: TelegramEngine, resource: ExternalMusicAlbumArtResource) -> Signal<EngineMediaResource.Fetch.Result, EngineMediaResource.Fetch.Error> {
|
||||
return Signal { subscriber in
|
||||
public func fetchExternalMusicAlbumArtResource(engine: TelegramEngine, file: FileMediaReference?, resource: ExternalMusicAlbumArtResource) -> Signal<EngineMediaResource.Fetch.Result, EngineMediaResource.Fetch.Error> {
|
||||
return engine.resources.fetchAlbumCover(file: file, title: resource.title, performer: resource.performer)
|
||||
|
||||
/*return Signal { subscriber in
|
||||
if resource.performer.isEmpty || resource.performer.lowercased().trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) == "unknown artist" || resource.title.isEmpty {
|
||||
subscriber.putError(.generic)
|
||||
return EmptyDisposable
|
||||
@ -151,5 +158,5 @@ public func fetchExternalMusicAlbumArtResource(engine: TelegramEngine, resource:
|
||||
fetchDisposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -2592,7 +2592,7 @@ public func albumArtThumbnailData(engine: TelegramEngine, thumbnail: ExternalMus
|
||||
return engine.resources.custom(
|
||||
id: thumbnail.id.stringRepresentation,
|
||||
fetch: EngineMediaResource.Fetch {
|
||||
return fetchExternalMusicAlbumArtResource(engine: engine, resource: thumbnail)
|
||||
return fetchExternalMusicAlbumArtResource(engine: engine, file: thumbnail.file, resource: thumbnail)
|
||||
},
|
||||
attemptSynchronously: attemptSynchronously
|
||||
)
|
||||
@ -2613,7 +2613,7 @@ public func albumArtThumbnailData(engine: TelegramEngine, thumbnail: ExternalMus
|
||||
})
|
||||
}
|
||||
|
||||
private func albumArtFullSizeDatas(engine: TelegramEngine, thumbnail: ExternalMusicAlbumArtResource, fullSize: ExternalMusicAlbumArtResource, autoFetchFullSize: Bool = true) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
|
||||
private func albumArtFullSizeDatas(engine: TelegramEngine, file: FileMediaReference?, thumbnail: ExternalMusicAlbumArtResource, fullSize: ExternalMusicAlbumArtResource, autoFetchFullSize: Bool = true) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
|
||||
return engine.resources.custom(
|
||||
id: fullSize.id.stringRepresentation,
|
||||
fetch: nil,
|
||||
@ -2629,14 +2629,14 @@ private func albumArtFullSizeDatas(engine: TelegramEngine, thumbnail: ExternalMu
|
||||
engine.resources.custom(
|
||||
id: thumbnail.id.stringRepresentation,
|
||||
fetch: EngineMediaResource.Fetch {
|
||||
return fetchExternalMusicAlbumArtResource(engine: engine, resource: thumbnail)
|
||||
return fetchExternalMusicAlbumArtResource(engine: engine, file: file, resource: thumbnail)
|
||||
},
|
||||
attemptSynchronously: false
|
||||
),
|
||||
engine.resources.custom(
|
||||
id: fullSize.id.stringRepresentation,
|
||||
fetch: autoFetchFullSize ? EngineMediaResource.Fetch {
|
||||
return fetchExternalMusicAlbumArtResource(engine: engine, resource: fullSize)
|
||||
return fetchExternalMusicAlbumArtResource(engine: engine, file: file, resource: fullSize)
|
||||
} : nil,
|
||||
attemptSynchronously: false
|
||||
)
|
||||
@ -2749,7 +2749,7 @@ public func playerAlbumArt(postbox: Postbox, engine: TelegramEngine, fileReferen
|
||||
return Tuple(thumbnailData, nil, false)
|
||||
}
|
||||
} else {
|
||||
immediateArtworkData = albumArtFullSizeDatas(engine: engine, thumbnail: albumArt.thumbnailResource, fullSize: albumArt.fullSizeResource)
|
||||
immediateArtworkData = albumArtFullSizeDatas(engine: engine, file: fileReference, thumbnail: albumArt.thumbnailResource, fullSize: albumArt.fullSizeResource)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ public struct MediaResourceId: Equatable, Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
public protocol MediaResource {
|
||||
public protocol MediaResource: AnyObject {
|
||||
var id: MediaResourceId { get }
|
||||
var size: Int64? { get }
|
||||
var streamable: Bool { get }
|
||||
|
@ -363,6 +363,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1770371538] = { return Api.InputWallPaper.parse_inputWallPaperNoFile($0) }
|
||||
dict[1913199744] = { return Api.InputWallPaper.parse_inputWallPaperSlug($0) }
|
||||
dict[-1678949555] = { return Api.InputWebDocument.parse_inputWebDocument($0) }
|
||||
dict[-193992412] = { return Api.InputWebFileLocation.parse_inputWebFileAudioAlbumThumbLocation($0) }
|
||||
dict[-1625153079] = { return Api.InputWebFileLocation.parse_inputWebFileGeoPointLocation($0) }
|
||||
dict[-1036396922] = { return Api.InputWebFileLocation.parse_inputWebFileLocation($0) }
|
||||
dict[1048946971] = { return Api.Invoice.parse_invoice($0) }
|
||||
|
@ -54,11 +54,21 @@ public extension Api {
|
||||
}
|
||||
public extension Api {
|
||||
enum InputWebFileLocation: TypeConstructorDescription {
|
||||
case inputWebFileAudioAlbumThumbLocation(flags: Int32, document: Api.InputDocument?, title: String?, performer: String?)
|
||||
case inputWebFileGeoPointLocation(geoPoint: Api.InputGeoPoint, accessHash: Int64, w: Int32, h: Int32, zoom: Int32, scale: Int32)
|
||||
case inputWebFileLocation(url: String, accessHash: Int64)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputWebFileAudioAlbumThumbLocation(let flags, let document, let title, let performer):
|
||||
if boxed {
|
||||
buffer.appendInt32(-193992412)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(performer!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1625153079)
|
||||
@ -82,6 +92,8 @@ public extension Api {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputWebFileAudioAlbumThumbLocation(let flags, let document, let title, let performer):
|
||||
return ("inputWebFileAudioAlbumThumbLocation", [("flags", String(describing: flags)), ("document", String(describing: document)), ("title", String(describing: title)), ("performer", String(describing: performer))])
|
||||
case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale):
|
||||
return ("inputWebFileGeoPointLocation", [("geoPoint", String(describing: geoPoint)), ("accessHash", String(describing: accessHash)), ("w", String(describing: w)), ("h", String(describing: h)), ("zoom", String(describing: zoom)), ("scale", String(describing: scale))])
|
||||
case .inputWebFileLocation(let url, let accessHash):
|
||||
@ -89,6 +101,28 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputWebFileAudioAlbumThumbLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputDocument?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputDocument
|
||||
} }
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputWebFileLocation.inputWebFileAudioAlbumThumbLocation(flags: _1!, document: _2, title: _3, performer: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputWebFileGeoPointLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: Api.InputGeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
|
@ -82,9 +82,3 @@ extension SecretFileMediaResource: TelegramCloudMediaResource, TelegramMultipart
|
||||
return .inputEncryptedFileLocation(id: self.fileId, accessHash: self.accessHash)
|
||||
}
|
||||
}
|
||||
|
||||
extension WebFileReferenceMediaResource {
|
||||
var apiInputLocation: Api.InputWebFileLocation {
|
||||
return .inputWebFileLocation(url: self.url, accessHash: self.accessHash)
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ private enum MultipartFetchDownloadError {
|
||||
case reuploadToCdn(masterDatacenterId: Int32, token: Data)
|
||||
case revalidateMediaReference
|
||||
case hashesMissing
|
||||
case fatal
|
||||
}
|
||||
|
||||
private enum MultipartFetchGenericLocationResult {
|
||||
@ -347,7 +348,7 @@ private enum MultipartFetchSource {
|
||||
case let .web(_, location):
|
||||
return download.request(Api.functions.upload.getWebFile(location: location, offset: Int32(offset), limit: Int32(limit)), tag: tag, continueInBackground: continueInBackground)
|
||||
|> mapError { error -> MultipartFetchDownloadError in
|
||||
return .generic
|
||||
return .fatal
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Data, MultipartFetchDownloadError> in
|
||||
switch result {
|
||||
@ -448,6 +449,7 @@ private final class MultipartFetchManager {
|
||||
let continueInBackground: Bool
|
||||
let partReady: (Int64, Data) -> Void
|
||||
let reportCompleteSize: (Int64) -> Void
|
||||
let finishWithError: (MediaResourceDataFetchError) -> Void
|
||||
|
||||
private let useMainConnection: Bool
|
||||
private var source: MultipartFetchSource
|
||||
@ -472,7 +474,7 @@ private final class MultipartFetchManager {
|
||||
private var fetchSpeedRecords: [FetchSpeedRecord] = []
|
||||
private var totalFetchedByteCount: Int = 0
|
||||
|
||||
init(resource: TelegramMediaResource, parameters: MediaResourceFetchParameters?, size: Int64?, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, encryptionKey: SecretFileEncryptionKey?, decryptedSize: Int64?, location: MultipartFetchMasterLocation, postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext?, partReady: @escaping (Int64, Data) -> Void, reportCompleteSize: @escaping (Int64) -> Void, useMainConnection: Bool) {
|
||||
init(resource: TelegramMediaResource, parameters: MediaResourceFetchParameters?, size: Int64?, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, encryptionKey: SecretFileEncryptionKey?, decryptedSize: Int64?, location: MultipartFetchMasterLocation, postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext?, partReady: @escaping (Int64, Data) -> Void, reportCompleteSize: @escaping (Int64) -> Void, finishWithError: @escaping (MediaResourceDataFetchError) -> Void, useMainConnection: Bool) {
|
||||
self.resource = resource
|
||||
self.parameters = parameters
|
||||
self.consumerId = Int64.random(in: Int64.min ... Int64.max)
|
||||
@ -528,6 +530,7 @@ private final class MultipartFetchManager {
|
||||
self.source = .master(location: location, download: DownloadWrapper(consumerId: self.consumerId, datacenterId: location.datacenterId, isCdn: false, network: network, useMainConnection: self.useMainConnection))
|
||||
self.partReady = partReady
|
||||
self.reportCompleteSize = reportCompleteSize
|
||||
self.finishWithError = finishWithError
|
||||
|
||||
self.rangesDisposable = (intervals
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] intervals in
|
||||
@ -734,6 +737,8 @@ private final class MultipartFetchManager {
|
||||
switch error {
|
||||
case .generic:
|
||||
break
|
||||
case .fatal:
|
||||
strongSelf.finishWithError(.generic)
|
||||
case .revalidateMediaReference:
|
||||
if !strongSelf.revalidatingMediaReference && !strongSelf.revalidatedMediaReference {
|
||||
strongSelf.revalidatingMediaReference = true
|
||||
@ -821,7 +826,7 @@ public func resourceFetchInfo(resource: TelegramMediaResource) -> MediaResourceF
|
||||
func multipartFetch(postbox: Postbox, network: Network, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext?, resource: TelegramMediaResource, datacenterId: Int, size: Int64?, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int64? = nil, continueInBackground: Bool = false, useMainConnection: Bool = false) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
return Signal { subscriber in
|
||||
let location: MultipartFetchMasterLocation
|
||||
if let resource = resource as? WebFileReferenceMediaResource {
|
||||
if let resource = resource as? MediaResourceWithWebFileReference {
|
||||
location = .web(Int32(datacenterId), resource.apiInputLocation)
|
||||
} else {
|
||||
location = .generic(Int32(datacenterId), { resource, resourceReference, fileReference in
|
||||
@ -876,6 +881,8 @@ func multipartFetch(postbox: Postbox, network: Network, mediaReferenceRevalidati
|
||||
}, reportCompleteSize: { size in
|
||||
subscriber.putNext(.resourceSizeUpdated(size))
|
||||
subscriber.putCompletion()
|
||||
}, finishWithError: { error in
|
||||
subscriber.putError(error)
|
||||
}, useMainConnection: useMainConnection)
|
||||
|
||||
manager.start()
|
||||
|
@ -49,7 +49,7 @@ func fetchResource(account: Account, resource: MediaResource, intervals: Signal<
|
||||
} else if let cloudResource = resource as? TelegramMultipartFetchableResource {
|
||||
return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false))
|
||||
|> then(fetchCloudMediaLocation(account: account, resource: cloudResource, datacenterId: cloudResource.datacenterId, size: resource.size == 0 ? nil : resource.size, intervals: intervals, parameters: parameters))
|
||||
} else if let webFileResource = resource as? WebFileReferenceMediaResource {
|
||||
} else if let webFileResource = resource as? MediaResourceWithWebFileReference {
|
||||
return currentWebDocumentsHostDatacenterId(postbox: account.postbox, isTestingEnvironment: account.testingEnvironment)
|
||||
|> castError(MediaResourceDataFetchError.self)
|
||||
|> mapToSignal { datacenterId -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> in
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
import TelegramApi
|
||||
|
||||
public struct CloudFileMediaResourceId: Hashable, Equatable {
|
||||
let datacenterId: Int
|
||||
@ -664,7 +665,11 @@ public struct WebFileReferenceMediaResourceId: Hashable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public final class WebFileReferenceMediaResource: TelegramMediaResource {
|
||||
protocol MediaResourceWithWebFileReference: TelegramMediaResource {
|
||||
var apiInputLocation: Api.InputWebFileLocation { get }
|
||||
}
|
||||
|
||||
public final class WebFileReferenceMediaResource: TelegramMediaResource, MediaResourceWithWebFileReference {
|
||||
public let url: String
|
||||
public let actualSize: Int64
|
||||
public var size: Int64? {
|
||||
@ -705,8 +710,71 @@ public final class WebFileReferenceMediaResource: TelegramMediaResource {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var apiInputLocation: Api.InputWebFileLocation {
|
||||
return .inputWebFileLocation(url: self.url, accessHash: self.accessHash)
|
||||
}
|
||||
}
|
||||
|
||||
final class AlbumCoverResource: TelegramMediaResource, MediaResourceWithWebFileReference {
|
||||
var id: MediaResourceId {
|
||||
return MediaResourceId("AlbumCoverResource-\(self.datacenterId)-\(self.title)-\(self.performer)")
|
||||
}
|
||||
|
||||
let datacenterId: Int
|
||||
let size: Int64? = nil
|
||||
|
||||
func isEqual(to: MediaResource) -> Bool {
|
||||
return self === to
|
||||
}
|
||||
|
||||
var fileReference: Data? {
|
||||
if let file = self.file, let resource = file.media.resource as? CloudDocumentMediaResource {
|
||||
return resource.fileReference
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
let file: FileMediaReference?
|
||||
let title: String
|
||||
let performer: String
|
||||
|
||||
init(datacenterId: Int, file: FileMediaReference?, title: String, performer: String) {
|
||||
self.datacenterId = datacenterId
|
||||
self.file = file
|
||||
self.title = title
|
||||
self.performer = performer
|
||||
}
|
||||
|
||||
init(decoder: PostboxDecoder) {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
func encode(_ encoder: PostboxEncoder) {
|
||||
}
|
||||
|
||||
var apiInputLocation: Api.InputWebFileLocation {
|
||||
var flags: Int32 = 0
|
||||
var document: Api.InputDocument?
|
||||
if let file = self.file, let resource = file.media.resource as? CloudDocumentMediaResource {
|
||||
document = .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data()))
|
||||
flags |= 1 << 0
|
||||
}
|
||||
if !self.title.isEmpty {
|
||||
flags |= 1 << 1
|
||||
}
|
||||
if !self.performer.isEmpty {
|
||||
flags |= 1 << 1
|
||||
}
|
||||
return .inputWebFileAudioAlbumThumbLocation(
|
||||
flags: flags,
|
||||
document: document,
|
||||
title: self.title.isEmpty ? nil : self.title,
|
||||
performer: self.performer.isEmpty ? nil : self.performer
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public struct SecretFileMediaResourceId: Hashable, Equatable {
|
||||
public let fileId: Int64
|
||||
|
@ -1,10 +1,59 @@
|
||||
import Foundation
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramApi
|
||||
|
||||
public typealias EngineTempBox = TempBox
|
||||
public typealias EngineTempBoxFile = TempBoxFile
|
||||
|
||||
func bufferedFetch(_ signal: Signal<EngineMediaResource.Fetch.Result, EngineMediaResource.Fetch.Error>) -> Signal<EngineMediaResource.Fetch.Result, EngineMediaResource.Fetch.Error> {
|
||||
return Signal { subscriber in
|
||||
final class State {
|
||||
var data = Data()
|
||||
var isCompleted: Bool = false
|
||||
|
||||
init() {
|
||||
}
|
||||
}
|
||||
|
||||
let state = Atomic<State>(value: State())
|
||||
return signal.start(next: { value in
|
||||
switch value {
|
||||
case let .dataPart(_, data, _, _):
|
||||
let _ = state.with { state in
|
||||
state.data.append(data)
|
||||
}
|
||||
case let .moveTempFile(file):
|
||||
let _ = state.with { state in
|
||||
state.isCompleted = true
|
||||
}
|
||||
subscriber.putNext(.moveTempFile(file: file))
|
||||
case .resourceSizeUpdated:
|
||||
break
|
||||
default:
|
||||
assert(false)
|
||||
break
|
||||
}
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
let tempFile = state.with { state -> TempBoxFile? in
|
||||
if state.isCompleted {
|
||||
return nil
|
||||
} else {
|
||||
let tempFile = TempBox.shared.tempFile(fileName: "data")
|
||||
let _ = try? state.data.write(to: URL(fileURLWithPath: tempFile.path), options: .atomic)
|
||||
return tempFile
|
||||
}
|
||||
}
|
||||
if let tempFile = tempFile {
|
||||
subscriber.putNext(.moveTempFile(file: tempFile))
|
||||
}
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public final class EngineMediaResource: Equatable {
|
||||
public enum CacheTimeout {
|
||||
case `default`
|
||||
@ -29,7 +78,14 @@ public final class EngineMediaResource: Equatable {
|
||||
|
||||
public final class Fetch {
|
||||
public enum Result {
|
||||
case dataPart(resourceOffset: Int64, data: Data, range: Range<Int64>, complete: Bool)
|
||||
case resourceSizeUpdated(Int64)
|
||||
case progressUpdated(Float)
|
||||
case replaceHeader(data: Data, range: Range<Int64>)
|
||||
case moveLocalFile(path: String)
|
||||
case moveTempFile(file: TempBoxFile)
|
||||
case copyLocalItem(MediaResourceDataFetchCopyLocalItem)
|
||||
case reset
|
||||
}
|
||||
|
||||
public enum Error {
|
||||
@ -189,6 +245,9 @@ public extension TelegramEngine {
|
||||
switch result {
|
||||
case let .moveTempFile(file):
|
||||
mappedResult = .tempFile(file)
|
||||
default:
|
||||
assert(false)
|
||||
return
|
||||
}
|
||||
subscriber.putNext(mappedResult)
|
||||
}, completed: {
|
||||
@ -219,6 +278,53 @@ public extension TelegramEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func fetchAlbumCover(file: FileMediaReference?, title: String, performer: String) -> Signal<EngineMediaResource.Fetch.Result, EngineMediaResource.Fetch.Error> {
|
||||
let datacenterId: Int
|
||||
if let resource = file?.media.resource as? CloudDocumentMediaResource {
|
||||
datacenterId = resource.datacenterId
|
||||
} else {
|
||||
datacenterId = self.account.network.datacenterId
|
||||
}
|
||||
|
||||
let resource = AlbumCoverResource(datacenterId: datacenterId, file: file, title: title, performer: performer)
|
||||
|
||||
return bufferedFetch(multipartFetch(postbox: self.account.postbox, network: self.account.network, mediaReferenceRevalidationContext: self.account.mediaReferenceRevalidationContext, resource: resource, datacenterId: datacenterId, size: nil, intervals: .single([(0 ..< Int64.max, .default)]), parameters: MediaResourceFetchParameters(
|
||||
tag: nil,
|
||||
info: TelegramCloudMediaResourceFetchInfo(
|
||||
reference: MediaResourceReference.standalone(resource: resource),
|
||||
preferBackgroundReferenceRevalidation: false,
|
||||
continueInBackground: false
|
||||
),
|
||||
isRandomAccessAllowed: true
|
||||
))
|
||||
|> map { result -> EngineMediaResource.Fetch.Result in
|
||||
switch result {
|
||||
case let .dataPart(resourceOffset, data, range, complete):
|
||||
return .dataPart(resourceOffset: resourceOffset, data: data, range: range, complete: complete)
|
||||
case let .resourceSizeUpdated(size):
|
||||
return .resourceSizeUpdated(size)
|
||||
case let .progressUpdated(value):
|
||||
return .progressUpdated(value)
|
||||
case let .replaceHeader(data, range):
|
||||
return .replaceHeader(data: data, range: range)
|
||||
case let .moveLocalFile(path):
|
||||
return .moveLocalFile(path: path)
|
||||
case let .moveTempFile(file):
|
||||
return .moveTempFile(file: file)
|
||||
case let .copyLocalItem(item):
|
||||
return .copyLocalItem(item)
|
||||
case .reset:
|
||||
return .reset
|
||||
}
|
||||
}
|
||||
|> mapError { error -> EngineMediaResource.Fetch.Error in
|
||||
switch error {
|
||||
case .generic:
|
||||
return .generic
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public func cancelAllFetches(id: String) {
|
||||
preconditionFailure()
|
||||
|
@ -158,6 +158,7 @@ public final class EmojiSuggestionsComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
private let blurView: BlurredBackgroundView
|
||||
private let backgroundLayer: SimpleShapeLayer
|
||||
private let scrollView: UIScrollView
|
||||
|
||||
@ -168,11 +169,19 @@ public final class EmojiSuggestionsComponent: Component {
|
||||
private var visibleLayers: [MediaId: InlineStickerItemLayer] = [:]
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.blurView = BlurredBackgroundView(color: .clear, enableBlur: true)
|
||||
self.blurView.layer.shadowColor = UIColor(white: 0.0, alpha: 1.0).cgColor
|
||||
self.blurView.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
|
||||
self.blurView.layer.shadowRadius = 15.0
|
||||
self.blurView.layer.shadowOpacity = 0.15
|
||||
|
||||
self.backgroundLayer = SimpleShapeLayer()
|
||||
self.backgroundLayer.shadowColor = UIColor(white: 0.0, alpha: 1.0).cgColor
|
||||
/*self.backgroundLayer.shadowColor = UIColor(white: 0.0, alpha: 1.0).cgColor
|
||||
self.backgroundLayer.shadowOffset = CGSize(width: 0.0, height: 2.0)
|
||||
self.backgroundLayer.shadowRadius = 15.0
|
||||
self.backgroundLayer.shadowOpacity = 0.15
|
||||
self.backgroundLayer.shadowOpacity = 0.15*/
|
||||
|
||||
self.blurView.layer.mask = self.backgroundLayer
|
||||
|
||||
self.scrollView = UIScrollView()
|
||||
|
||||
@ -197,6 +206,7 @@ public final class EmojiSuggestionsComponent: Component {
|
||||
self.scrollView.delegate = self
|
||||
self.scrollView.clipsToBounds = true
|
||||
|
||||
self.addSubview(self.blurView)
|
||||
self.layer.addSublayer(self.backgroundLayer)
|
||||
self.addSubview(self.scrollView)
|
||||
|
||||
@ -317,6 +327,8 @@ public final class EmojiSuggestionsComponent: Component {
|
||||
path.addArc(tangent1End: CGPoint(x: size.width, y: 0.0), tangent2End: CGPoint(x: size.width - radius, y: 0.0), radius: radius)
|
||||
path.addLine(to: CGPoint(x: radius, y: 0.0))
|
||||
|
||||
self.blurView.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.blurView.update(size: size, transition: .immediate)
|
||||
self.backgroundLayer.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.backgroundLayer.path = path
|
||||
self.backgroundLayer.shadowPath = path
|
||||
@ -326,7 +338,9 @@ public final class EmojiSuggestionsComponent: Component {
|
||||
let height: CGFloat = 54.0
|
||||
|
||||
if self.component?.theme !== component.theme {
|
||||
self.backgroundLayer.fillColor = component.theme.list.plainBackgroundColor.cgColor
|
||||
//self.backgroundLayer.fillColor = component.theme.list.plainBackgroundColor.cgColor
|
||||
self.backgroundLayer.fillColor = UIColor.black.cgColor
|
||||
self.blurView.updateColor(color: component.theme.list.plainBackgroundColor.withMultipliedAlpha(0.6), transition: .immediate)
|
||||
}
|
||||
var resetScrollingPosition = false
|
||||
if self.component?.files != component.files {
|
||||
|
@ -1496,7 +1496,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
image = playerAlbumArt(postbox: context.account.postbox, engine: context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: .init(thumbnailResource: ExternalMusicAlbumArtResource(title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(title: title ?? "", performer: performer ?? "", isThumbnail: false)), thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), drawPlaceholderWhenEmpty: false, attemptSynchronously: !animated)
|
||||
image = playerAlbumArt(postbox: context.account.postbox, engine: context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: .init(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: false)), thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), drawPlaceholderWhenEmpty: false, attemptSynchronously: !animated)
|
||||
}
|
||||
}
|
||||
let statusNode = SemanticStatusNode(backgroundNodeColor: backgroundNodeColor, foregroundNodeColor: foregroundNodeColor, image: image, overlayForegroundNodeColor: presentationData.theme.theme.chat.message.mediaOverlayControlColors.foregroundColor)
|
||||
|
@ -111,7 +111,7 @@ final class MessageMediaPlaylistItem: SharedMediaPlaylistItem {
|
||||
if file.fileName?.lowercased().hasSuffix(".ogg") == true {
|
||||
albumArt = nil
|
||||
} else {
|
||||
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
||||
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(self.message), media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(self.message), media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
||||
}
|
||||
|
||||
return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: CGFloat(duration) > 10.0 * 60.0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user