diff --git a/Telegram/BUILD b/Telegram/BUILD index 66da047e93..d6a0ff812d 100644 --- a/Telegram/BUILD +++ b/Telegram/BUILD @@ -1338,7 +1338,7 @@ ios_extension( ], minimum_os_version = "9.0", # maintain the same minimum OS version across extensions ipa_post_processor = ":SetMinOsVersionWidgetExtension", - provides_main = True, + #provides_main = True, provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:Widget.mobileprovision", diff --git a/build-system/bazel-rules/rules_apple b/build-system/bazel-rules/rules_apple index c337e9318d..fcbfcfad2d 160000 --- a/build-system/bazel-rules/rules_apple +++ b/build-system/bazel-rules/rules_apple @@ -1 +1 @@ -Subproject commit c337e9318d17a004dc06c966bab02a8c7929ce87 +Subproject commit fcbfcfad2d633b6c8be85954975db88bee3fa26c diff --git a/build-system/bazel-rules/rules_swift b/build-system/bazel-rules/rules_swift index 81aa39ed9f..8c8f4661db 160000 --- a/build-system/bazel-rules/rules_swift +++ b/build-system/bazel-rules/rules_swift @@ -1 +1 @@ -Subproject commit 81aa39ed9f58c416e7255adc0c8a6ba50c081030 +Subproject commit 8c8f4661dba2bbe8578ae42b8ab7001d27357575 diff --git a/build-system/tulsi b/build-system/tulsi index 0bddcf7522..00a73c99ba 160000 --- a/build-system/tulsi +++ b/build-system/tulsi @@ -1 +1 @@ -Subproject commit 0bddcf7522cd4f3bcad4e1502e5189156a2eb615 +Subproject commit 00a73c99bac2d96c0e168fb6397089dc39e8eb9a diff --git a/submodules/AccountContext/BUILD b/submodules/AccountContext/BUILD index b5558e05f4..c0b7228501 100644 --- a/submodules/AccountContext/BUILD +++ b/submodules/AccountContext/BUILD @@ -19,6 +19,7 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", + "//submodules/MusicAlbumArtResources:MusicAlbumArtResources", ], visibility = [ "//visibility:public", diff --git a/submodules/AccountContext/Sources/SharedMediaPlayer.swift b/submodules/AccountContext/Sources/SharedMediaPlayer.swift index fee597a187..6217d6f815 100644 --- a/submodules/AccountContext/Sources/SharedMediaPlayer.swift +++ b/submodules/AccountContext/Sources/SharedMediaPlayer.swift @@ -4,6 +4,7 @@ import Postbox import TelegramUIPreferences import SwiftSignalKit import UniversalMediaPlayer +import MusicAlbumArtResources public enum SharedMediaPlaybackDataType { case music @@ -44,25 +45,13 @@ public struct SharedMediaPlaybackData: Equatable { } public struct SharedMediaPlaybackAlbumArt: Equatable { - public let thumbnailResource: TelegramMediaResource - public let fullSizeResource: TelegramMediaResource + public let thumbnailResource: ExternalMusicAlbumArtResource + public let fullSizeResource: ExternalMusicAlbumArtResource - public init(thumbnailResource: TelegramMediaResource, fullSizeResource: TelegramMediaResource) { + public init(thumbnailResource: ExternalMusicAlbumArtResource, fullSizeResource: ExternalMusicAlbumArtResource) { self.thumbnailResource = thumbnailResource self.fullSizeResource = fullSizeResource } - - public static func ==(lhs: SharedMediaPlaybackAlbumArt, rhs: SharedMediaPlaybackAlbumArt) -> Bool { - if !lhs.thumbnailResource.isEqual(to: rhs.thumbnailResource) { - return false - } - - if !lhs.fullSizeResource.isEqual(to: rhs.fullSizeResource) { - return false - } - - return true - } } public enum SharedMediaPlaybackDisplayData: Equatable { diff --git a/submodules/AppLock/BUILD b/submodules/AppLock/BUILD index a4e95c2e8b..90ad4bed73 100644 --- a/submodules/AppLock/BUILD +++ b/submodules/AppLock/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/MonotonicTime:MonotonicTime", diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 2c1a10eca8..5b4b00a598 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -865,7 +865,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } let foundRemotePeers: Signal<([FoundPeer], [FoundPeer], Bool), NoError> - let currentRemotePeersValue = currentRemotePeers.with { $0 } ?? ([], []) + let currentRemotePeersValue: ([FoundPeer], [FoundPeer]) = currentRemotePeers.with { $0 } ?? ([], []) if let query = query { foundRemotePeers = ( .single((currentRemotePeersValue.0, currentRemotePeersValue.1, true)) diff --git a/submodules/ListMessageItem/BUILD b/submodules/ListMessageItem/BUILD index a7dd3fd0d5..c69c49042e 100644 --- a/submodules/ListMessageItem/BUILD +++ b/submodules/ListMessageItem/BUILD @@ -35,6 +35,7 @@ swift_library( "//submodules/FileMediaResourceStatus:FileMediaResourceStatus", "//submodules/ManagedAnimationNode:ManagedAnimationNode", "//submodules/WallpaperResources:WallpaperResources", + "//submodules/Postbox:Postbox", ], visibility = [ "//visibility:public", diff --git a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift index 9a8308574b..556de36fe5 100644 --- a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift @@ -682,7 +682,7 @@ public final class ListMessageFileItemNode: ListMessageNode { case let .imageRepresentation(file, representation): updateIconImageSignal = chatWebpageSnippetFile(account: item.context.account, fileReference: .message(message: MessageReference(message), media: file), representation: representation) case let .albumArt(file, albumArt): - updateIconImageSignal = playerAlbumArt(postbox: item.context.account.postbox, fileReference: .message(message: MessageReference(message), media: file), albumArt: albumArt, thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), emptyColor: item.presentationData.theme.theme.list.itemAccentColor) + updateIconImageSignal = playerAlbumArt(postbox: item.context.account.postbox, engine: item.context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: albumArt, thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), emptyColor: item.presentationData.theme.theme.list.itemAccentColor) case let .roundVideo(file): updateIconImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, videoReference: FileMediaReference.message(message: MessageReference(message), media: file), autoFetchFullSizeThumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3)) } diff --git a/submodules/MediaPlayer/Sources/MediaPlayer.swift b/submodules/MediaPlayer/Sources/MediaPlayer.swift index c3a4693eb0..e1ab42f53f 100644 --- a/submodules/MediaPlayer/Sources/MediaPlayer.swift +++ b/submodules/MediaPlayer/Sources/MediaPlayer.swift @@ -397,7 +397,7 @@ private final class MediaPlayerContext { self.audioRenderer = nil var timebase: CMTimebase? - CMTimebaseCreateWithMasterClock(allocator: nil, masterClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) + CMTimebaseCreateWithSourceClock(allocator: nil, sourceClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) controlTimebase = MediaPlayerControlTimebase(timebase: timebase!, isAudio: false) CMTimebaseSetTime(timebase!, time: seekResult.timestamp) } diff --git a/submodules/MediaPlayer/Sources/MediaPlayerAudioRenderer.swift b/submodules/MediaPlayer/Sources/MediaPlayerAudioRenderer.swift index 9e6774bc75..f9114dc378 100644 --- a/submodules/MediaPlayer/Sources/MediaPlayerAudioRenderer.swift +++ b/submodules/MediaPlayer/Sources/MediaPlayerAudioRenderer.swift @@ -95,13 +95,8 @@ private func rendererInputProc(refCon: UnsafeMutableRawPointer, ioActionFlags: U if !didSetRate { context.state = .playing(rate: rate, didSetRate: true) - let masterClock: CMClockOrTimebase - if #available(iOS 9.0, *) { - masterClock = CMTimebaseCopyMaster(context.timebase) - } else { - masterClock = CMTimebaseGetMaster(context.timebase)! - } - CMTimebaseSetRateAndAnchorTime(context.timebase, rate: rate, anchorTime: CMTimeMake(value: sampleIndex, timescale: 44100), immediateMasterTime: CMSyncGetTime(masterClock)) + let masterClock = CMTimebaseCopySource(context.timebase) + CMTimebaseSetRateAndAnchorTime(context.timebase, rate: rate, anchorTime: CMTimeMake(value: sampleIndex, timescale: 44100), immediateSourceTime: CMSyncGetTime(masterClock)) updatedRate = context.updatedRate } else { context.renderTimestampTick += 1 @@ -802,7 +797,7 @@ public final class MediaPlayerAudioRenderer { self.audioClock = audioClock! var audioTimebase: CMTimebase? - CMTimebaseCreateWithMasterClock(allocator: nil, masterClock: audioClock!, timebaseOut: &audioTimebase) + CMTimebaseCreateWithSourceClock(allocator: nil, sourceClock: audioClock!, timebaseOut: &audioTimebase) self.audioTimebase = audioTimebase! audioPlayerRendererQueue.async { diff --git a/submodules/MusicAlbumArtResources/BUILD b/submodules/MusicAlbumArtResources/BUILD index a975f21fff..617143cfc7 100644 --- a/submodules/MusicAlbumArtResources/BUILD +++ b/submodules/MusicAlbumArtResources/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/TelegramCore:TelegramCore", - "//submodules/Postbox:Postbox", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/UrlEscaping:UrlEscaping", ], diff --git a/submodules/MusicAlbumArtResources/Sources/ExternalMusicAlbumArtResources.swift b/submodules/MusicAlbumArtResources/Sources/ExternalMusicAlbumArtResources.swift index 79c7528d51..4848c7b623 100644 --- a/submodules/MusicAlbumArtResources/Sources/ExternalMusicAlbumArtResources.swift +++ b/submodules/MusicAlbumArtResources/Sources/ExternalMusicAlbumArtResources.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import TelegramCore import SwiftSignalKit -import Postbox import UrlEscaping public struct ExternalMusicAlbumArtResourceId { @@ -25,7 +24,7 @@ public struct ExternalMusicAlbumArtResourceId { } } -public class ExternalMusicAlbumArtResource: TelegramMediaResource { +public class ExternalMusicAlbumArtResource: Equatable { public let title: String public let performer: String public let isThumbnail: Bool @@ -36,38 +35,28 @@ public class ExternalMusicAlbumArtResource: TelegramMediaResource { self.isThumbnail = isThumbnail } - public required init(decoder: PostboxDecoder) { - self.title = decoder.decodeStringForKey("t", orElse: "") - self.performer = decoder.decodeStringForKey("p", orElse: "") - self.isThumbnail = decoder.decodeInt32ForKey("th", orElse: 1) != 0 + public var id: EngineMediaResource.Id { + return EngineMediaResource.Id(ExternalMusicAlbumArtResourceId(title: self.title, performer: self.performer, isThumbnail: self.isThumbnail).uniqueId) } - - public func encode(_ encoder: PostboxEncoder) { - encoder.encodeString(self.title, forKey: "t") - encoder.encodeString(self.performer, forKey: "p") - encoder.encodeInt32(self.isThumbnail ? 1 : 0, forKey: "th") - } - - public var id: MediaResourceId { - return MediaResourceId(ExternalMusicAlbumArtResourceId(title: self.title, performer: self.performer, isThumbnail: self.isThumbnail).uniqueId) - } - - public func isEqual(to: MediaResource) -> Bool { - if let to = to as? ExternalMusicAlbumArtResource { - return self.title == to.title && self.performer == to.performer && self.isThumbnail == to.isThumbnail - } else { + + public static func ==(lhs: ExternalMusicAlbumArtResource, rhs: ExternalMusicAlbumArtResource) -> Bool { + if lhs.title != rhs.title { return false } + if lhs.performer != rhs.performer { + return false + } + if lhs.isThumbnail != rhs.isThumbnail { + return false + } + return true } } -public func fetchExternalMusicAlbumArtResource(account: Account, resource: ExternalMusicAlbumArtResource) -> Signal { +public func fetchExternalMusicAlbumArtResource(engine: TelegramEngine, resource: ExternalMusicAlbumArtResource) -> Signal { return Signal { subscriber in - subscriber.putNext(.reset) - if resource.performer.isEmpty || resource.performer.lowercased().trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) == "unknown artist" || resource.title.isEmpty { - subscriber.putNext(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: true)) - subscriber.putCompletion() + subscriber.putError(.generic) return EmptyDisposable } else { let excludeWords: [String] = [ @@ -103,14 +92,12 @@ public func fetchExternalMusicAlbumArtResource(account: Account, resource: Exter let disposable = fetchHttpResource(url: metaUrl).start(next: { result in if case let .dataPart(_, data, _, complete) = result, complete { guard let dict = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: Any] else { - subscriber.putNext(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: true)) - subscriber.putCompletion() + subscriber.putError(.generic) return } guard let results = dict["results"] as? [Any] else { - subscriber.putNext(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: true)) - subscriber.putCompletion() + subscriber.putError(.generic) return } @@ -131,14 +118,12 @@ public func fetchExternalMusicAlbumArtResource(account: Account, resource: Exter } guard let result = matchingResult as? [String: Any] else { - subscriber.putNext(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: true)) - subscriber.putCompletion() + subscriber.putError(.generic) return } guard var artworkUrl = result["artworkUrl100"] as? String else { - subscriber.putNext(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: true)) - subscriber.putCompletion() + subscriber.putError(.generic) return } @@ -147,12 +132,13 @@ public func fetchExternalMusicAlbumArtResource(account: Account, resource: Exter } if artworkUrl.isEmpty { - subscriber.putNext(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: true)) - subscriber.putCompletion() + subscriber.putError(.generic) return } else { - fetchDisposable.set(fetchHttpResource(url: artworkUrl).start(next: { next in - subscriber.putNext(next) + fetchDisposable.set(engine.resources.httpData(url: artworkUrl).start(next: { next in + let file = EngineTempBox.shared.tempFile(fileName: "image.jpg") + let _ = try? next.write(to: URL(fileURLWithPath: file.path)) + subscriber.putNext(.moveTempFile(file: file)) }, completed: { subscriber.putCompletion() })) diff --git a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift b/submodules/PeerInfoUI/Sources/ChannelInfoController.swift index 3d4acfa6ca..1ec3c93b88 100644 --- a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelInfoController.swift @@ -756,7 +756,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: true)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(context: context, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { result in + let controller = WebSearchController(context: context, peer: peer.flatMap(EnginePeer.init), chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { result in assetsController?.dismiss() completedImpl(result) })) diff --git a/submodules/PhotoResources/BUILD b/submodules/PhotoResources/BUILD index 2a02b1e577..5b84550a66 100644 --- a/submodules/PhotoResources/BUILD +++ b/submodules/PhotoResources/BUILD @@ -23,6 +23,7 @@ swift_library( "//submodules/TelegramUIPreferences:TelegramUIPreferences", "//submodules/WebPBinding:WebPBinding", "//submodules/AppBundle:AppBundle", + "//submodules/MusicAlbumArtResources:MusicAlbumArtResources", ], visibility = [ "//visibility:public", diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index 8c42c66f37..14c832524b 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -16,6 +16,7 @@ import FastBlur import TinyThumbnail import ImageTransparency import AppBundle +import MusicAlbumArtResources private enum ResourceFileData { case data(Data) @@ -2476,102 +2477,80 @@ public func chatWebFileImage(account: Account, file: TelegramMediaWebFile) -> Si private let precomposedSmallAlbumArt = Atomic(value: nil) -private func albumArtThumbnailData(postbox: Postbox, thumbnail: MediaResource, attemptSynchronously: Bool = false) -> Signal { - let thumbnailResource = postbox.mediaBox.resourceData(thumbnail, attemptSynchronously: attemptSynchronously) - - let signal = thumbnailResource |> take(1) |> mapToSignal { maybeData -> Signal in - if maybeData.complete { - let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: []) - return .single((loadedData)) +public func albumArtThumbnailData(engine: TelegramEngine, thumbnail: ExternalMusicAlbumArtResource, attemptSynchronously: Bool = false) -> Signal { + return engine.resources.custom( + id: thumbnail.id.stringRepresentation, + fetch: EngineMediaResource.Fetch { + return fetchExternalMusicAlbumArtResource(engine: engine, resource: thumbnail) + }, + attemptSynchronously: attemptSynchronously + ) + |> mapToSignal { data in + if data.isComplete { + let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: []) + return .single(loadedData) } else { - let fetchedThumbnail = postbox.mediaBox.fetchedResource(thumbnail, parameters: nil) - - let thumbnail = Signal { subscriber in - let fetchedDisposable = fetchedThumbnail.start() - let thumbnailDisposable = thumbnailResource.start(next: { next in - subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: [])) - }, error: subscriber.putError, completed: subscriber.putCompletion) - - return ActionDisposable { - fetchedDisposable.dispose() - thumbnailDisposable.dispose() - } - } - - return thumbnail + return .single(nil) } - } |> distinctUntilChanged(isEqual: { lhs, rhs in + } + |> distinctUntilChanged(isEqual: { lhs, rhs in if lhs == nil && rhs == nil { return true } else { return false } }) - - return signal } -private func albumArtFullSizeDatas(postbox: Postbox, thumbnail: MediaResource, fullSize: MediaResource, autoFetchFullSize: Bool = true) -> Signal, NoError> { - let fullSizeResource = postbox.mediaBox.resourceData(fullSize) - let thumbnailResource = postbox.mediaBox.resourceData(thumbnail) - - let signal = fullSizeResource |> take(1) |> mapToSignal { maybeData -> Signal, NoError> in - if maybeData.complete { - let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: []) +private func albumArtFullSizeDatas(engine: TelegramEngine, thumbnail: ExternalMusicAlbumArtResource, fullSize: ExternalMusicAlbumArtResource, autoFetchFullSize: Bool = true) -> Signal, NoError> { + return engine.resources.custom( + id: thumbnail.id.stringRepresentation, + fetch: nil, + attemptSynchronously: false + ) + |> take(1) + |> mapToSignal { data in + if data.isComplete { + let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: []) return .single(Tuple(nil, loadedData, true)) } else { - let fetchedThumbnail = postbox.mediaBox.fetchedResource(thumbnail, parameters: nil) - let fetchedFullSize = postbox.mediaBox.fetchedResource(fullSize, parameters: nil) - - let thumbnail = Signal { subscriber in - let fetchedDisposable = fetchedThumbnail.start() - let thumbnailDisposable = thumbnailResource.start(next: { next in - subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: [])) - }, error: subscriber.putError, completed: subscriber.putCompletion) - - return ActionDisposable { - fetchedDisposable.dispose() - thumbnailDisposable.dispose() - } - } - - let fullSizeData: Signal, NoError> - - if autoFetchFullSize { - fullSizeData = Signal, NoError> { subscriber in - let fetchedFullSizeDisposable = fetchedFullSize.start() - let fullSizeDisposable = fullSizeResource.start(next: { next in - subscriber.putNext(Tuple(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete)) - }, error: subscriber.putError, completed: subscriber.putCompletion) - - return ActionDisposable { - fetchedFullSizeDisposable.dispose() - fullSizeDisposable.dispose() - } - } - } else { - fullSizeData = fullSizeResource - |> map { next -> Tuple2 in - return Tuple(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete) - } - } - - - return thumbnail |> mapToSignal { thumbnailData in - return fullSizeData |> map { value in - return Tuple(thumbnailData, value._0, value._1) + return combineLatest( + engine.resources.custom( + id: thumbnail.id.stringRepresentation, + fetch: EngineMediaResource.Fetch { + return fetchExternalMusicAlbumArtResource(engine: engine, resource: thumbnail) + }, + attemptSynchronously: false + ), + engine.resources.custom( + id: fullSize.id.stringRepresentation, + fetch: autoFetchFullSize ? EngineMediaResource.Fetch { + return fetchExternalMusicAlbumArtResource(engine: engine, resource: fullSize) + } : nil, + attemptSynchronously: false + ) + ) + |> mapToSignal { thumbnail, fullSize in + if fullSize.isComplete { + let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: fullSize.path), options: []) + return .single(Tuple(nil, loadedData, true)) + } else if thumbnail.isComplete { + let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: thumbnail.path), options: []) + return .single(Tuple(loadedData, nil, false)) + } else { + return .single(Tuple(nil, nil, false)) } } + } - } |> distinctUntilChanged(isEqual: { lhs, rhs in - if (lhs._0 == nil && lhs._1 == nil) && (rhs._0 == nil && rhs._1 == nil) { - return true - } else { - return false - } - }) - - return signal + } + |> distinctUntilChanged(isEqual: { lhs, rhs in + if (lhs._0 == nil && lhs._1 == nil) && (rhs._0 == nil && rhs._1 == nil) { + return true + } else { + return false + } + }) } private func drawAlbumArtPlaceholder(into c: CGContext, arguments: TransformImageArguments, thumbnail: Bool) { @@ -2613,7 +2592,7 @@ private func drawAlbumArtPlaceholder(into c: CGContext, arguments: TransformImag } } -public func playerAlbumArt(postbox: Postbox, fileReference: FileMediaReference?, albumArt: SharedMediaPlaybackAlbumArt?, thumbnail: Bool, overlayColor: UIColor? = nil, emptyColor: UIColor? = nil, drawPlaceholderWhenEmpty: Bool = true, attemptSynchronously: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { +public func playerAlbumArt(postbox: Postbox, engine: TelegramEngine, fileReference: FileMediaReference?, albumArt: SharedMediaPlaybackAlbumArt?, thumbnail: Bool, overlayColor: UIColor? = nil, emptyColor: UIColor? = nil, drawPlaceholderWhenEmpty: Bool = true, attemptSynchronously: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { var fileArtworkData: Signal = .single(nil) if let fileReference = fileReference { let size = thumbnail ? CGSize(width: 48.0, height: 48.0) : CGSize(width: 320.0, height: 320.0) @@ -2654,12 +2633,12 @@ public func playerAlbumArt(postbox: Postbox, fileReference: FileMediaReference?, } } else if let albumArt = albumArt { if thumbnail { - immediateArtworkData = albumArtThumbnailData(postbox: postbox, thumbnail: albumArt.thumbnailResource, attemptSynchronously: attemptSynchronously) + immediateArtworkData = albumArtThumbnailData(engine: engine, thumbnail: albumArt.thumbnailResource, attemptSynchronously: attemptSynchronously) |> map { thumbnailData in return Tuple(thumbnailData, nil, false) } } else { - immediateArtworkData = albumArtFullSizeDatas(postbox: postbox, thumbnail: albumArt.thumbnailResource, fullSize: albumArt.fullSizeResource) + immediateArtworkData = albumArtFullSizeDatas(engine: engine, thumbnail: albumArt.thumbnailResource, fullSize: albumArt.fullSizeResource) } } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index d52b2519ac..4c04c71229 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -6138,7 +6138,7 @@ public final class VoiceChatController: ViewController { guard let strongSelf = self else { return } - let controller = WebSearchController(context: strongSelf.context, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer.id.namespace == Namespaces.Peer.CloudUser ? nil : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { [weak self] result in + let controller = WebSearchController(context: strongSelf.context, peer: EnginePeer(peer), chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer.id.namespace == Namespaces.Peer.CloudUser ? nil : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { [weak self] result in assetsController?.dismiss() self?.updateProfilePhoto(result) })) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/OrderedLists/TelegramEngineOrderedLists.swift b/submodules/TelegramCore/Sources/TelegramEngine/OrderedLists/TelegramEngineOrderedLists.swift new file mode 100644 index 0000000000..87a04bf2ff --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/OrderedLists/TelegramEngineOrderedLists.swift @@ -0,0 +1,15 @@ +import Foundation +import SwiftSignalKit +import Postbox + +public extension TelegramEngine { + final class OrderedLists { + private let account: Account + + init(account: Account) { + self.account = account + } + + + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift b/submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift index 6f4e4cd817..bc2765aa26 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift @@ -59,6 +59,12 @@ public final class EngineMediaResource: Equatable { } } + public enum FetchStatus: Equatable { + case Remote + case Local + case Fetching(isActive: Bool, progress: Float) + } + public struct Id: Equatable, Hashable { public var stringRepresentation: String @@ -96,6 +102,30 @@ public extension EngineMediaResource.ResourceData { } } +public extension EngineMediaResource.FetchStatus { + init(_ status: MediaResourceStatus) { + switch status { + case .Remote: + self = .Remote + case .Local: + self = .Local + case let .Fetching(isActive, progress): + self = .Fetching(isActive: isActive, progress: progress) + } + } + + func _asStatus() -> MediaResourceStatus { + switch self { + case .Remote: + return .Remote + case .Local: + return .Local + case let .Fetching(isActive, progress): + return .Fetching(isActive: isActive, progress: progress) + } + } +} + public extension TelegramEngine { final class Resources { private let account: Account @@ -128,7 +158,12 @@ public extension TelegramEngine { } } - public func custom(id: String, fetch: EngineMediaResource.Fetch, cacheTimeout: EngineMediaResource.CacheTimeout = .default, attemptSynchronously: Bool = false) -> Signal { + public func custom( + id: String, + fetch: EngineMediaResource.Fetch?, + cacheTimeout: EngineMediaResource.CacheTimeout = .default, + attemptSynchronously: Bool = false + ) -> Signal { let mappedKeepDuration: CachedMediaRepresentationKeepDuration switch cacheTimeout { case .default: @@ -141,18 +176,20 @@ public extension TelegramEngine { baseResourceId: nil, pathExtension: nil, complete: true, - fetch: { - return Signal { subscriber in - return fetch.signal().start(next: { result in - let mappedResult: CachedMediaResourceRepresentationResult - switch result { - case let .moveTempFile(file): - mappedResult = .tempFile(file) - } - subscriber.putNext(mappedResult) - }, completed: { - subscriber.putCompletion() - }) + fetch: fetch.flatMap { fetch in + return { + return Signal { subscriber in + return fetch.signal().start(next: { result in + let mappedResult: CachedMediaResourceRepresentationResult + switch result { + case let .moveTempFile(file): + mappedResult = .tempFile(file) + } + subscriber.putNext(mappedResult) + }, completed: { + subscriber.putCompletion() + }) + } } }, keepDuration: mappedKeepDuration, diff --git a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift index 45302b053f..fe567190d2 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift @@ -75,6 +75,10 @@ public final class TelegramEngine { public lazy var data: EngineData = { return EngineData(account: self.account) }() + + public lazy var orderedLists: OrderedLists = { + return OrderedLists(account: self.account) + }() } public final class TelegramEngineUnauthorized { diff --git a/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift b/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift index daa7eb2496..d863811fcb 100644 --- a/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift @@ -123,7 +123,7 @@ private final class ChatContextResultPeekNode: ASDisplayNode, PeekControllerCont self.imageNode.displaysAsynchronously = false var timebase: CMTimebase? - CMTimebaseCreateWithMasterClock(allocator: nil, masterClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) + CMTimebaseCreateWithSourceClock(allocator: nil, sourceClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) CMTimebaseSetRate(timebase!, rate: 0.0) self.timebase = timebase! diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index bd0788dfe1..bfecafca5c 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -9610,7 +9610,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G configureLegacyAssetPicker(controller, context: strongSelf.context, peer: peer, chatLocation: strongSelf.chatLocation, initialCaption: inputText.string, hasSchedule: strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, presentWebSearch: editingMedia ? nil : { [weak self, weak legacyController] in if let strongSelf = self { - let controller = WebSearchController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, chatLocation: strongSelf.chatLocation, configuration: searchBotsConfiguration, mode: .media(completion: { results, selectionState, editingState, silentPosting in + let controller = WebSearchController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: EnginePeer(peer), chatLocation: strongSelf.chatLocation, configuration: searchBotsConfiguration, mode: .media(completion: { results, selectionState, editingState, silentPosting in if let legacyController = legacyController { legacyController.dismiss() } @@ -9717,7 +9717,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } |> deliverOnMainQueue).start(next: { [weak self] configuration in if let strongSelf = self { - let controller = WebSearchController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, chatLocation: strongSelf.chatLocation, configuration: configuration, mode: .media(completion: { [weak self] results, selectionState, editingState, silentPosting in + let controller = WebSearchController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: EnginePeer(peer), chatLocation: strongSelf.chatLocation, configuration: configuration, mode: .media(completion: { [weak self] results, selectionState, editingState, silentPosting in legacyEnqueueWebSearchMessages(selectionState, editingState, enqueueChatContextResult: { [weak self] result in if let strongSelf = self { strongSelf.enqueueChatContextResult(results, result, hideVia: true) diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift index f85158968f..ad52f59483 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift @@ -926,7 +926,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { } } - image = playerAlbumArt(postbox: context.account.postbox, 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(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) } } let statusNode = SemanticStatusNode(backgroundNodeColor: backgroundNodeColor, foregroundNodeColor: foregroundNodeColor, image: image, overlayForegroundNodeColor: presentationData.theme.theme.chat.message.mediaOverlayControlColors.foregroundColor) diff --git a/submodules/TelegramUI/Sources/CreateChannelController.swift b/submodules/TelegramUI/Sources/CreateChannelController.swift index a0f6c1327a..b86093731e 100644 --- a/submodules/TelegramUI/Sources/CreateChannelController.swift +++ b/submodules/TelegramUI/Sources/CreateChannelController.swift @@ -455,7 +455,7 @@ public func createChannelController(context: AccountContext) -> ViewController { let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(context: context, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in + let controller = WebSearchController(context: context, peer: peer.flatMap(EnginePeer.init), chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in assetsController?.dismiss() completedChannelPhotoImpl(result) })) diff --git a/submodules/TelegramUI/Sources/CreateGroupController.swift b/submodules/TelegramUI/Sources/CreateGroupController.swift index c783592849..b284e650d0 100644 --- a/submodules/TelegramUI/Sources/CreateGroupController.swift +++ b/submodules/TelegramUI/Sources/CreateGroupController.swift @@ -701,7 +701,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(context: context, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in + let controller = WebSearchController(context: context, peer: peer.flatMap(EnginePeer.init), chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in assetsController?.dismiss() completedGroupPhotoImpl(result) })) diff --git a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift index 471042e3b9..30b75a0e3b 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift @@ -165,7 +165,7 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode self.imageNode.displaysAsynchronously = false var timebase: CMTimebase? - CMTimebaseCreateWithMasterClock(allocator: nil, masterClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) + CMTimebaseCreateWithSourceClock(allocator: nil, sourceClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) CMTimebaseSetRate(timebase!, rate: 0.0) self.timebase = timebase! diff --git a/submodules/TelegramUI/Sources/MediaManager.swift b/submodules/TelegramUI/Sources/MediaManager.swift index f4abb6e120..428b2d411f 100644 --- a/submodules/TelegramUI/Sources/MediaManager.swift +++ b/submodules/TelegramUI/Sources/MediaManager.swift @@ -13,6 +13,7 @@ import AccountContext import TelegramUniversalVideoContent import DeviceProximity import MediaResources +import PhotoResources enum SharedMediaPlayerGroup: Int { case music = 0 @@ -324,7 +325,11 @@ public final class MediaManagerImpl: NSObject, MediaManager { |> distinctUntilChanged(isEqual: { $0?.0 === $1?.0 && $0?.1 == $1?.1 }) |> mapToSignal { value -> Signal in if let (account, value) = value { - return Signal { subscriber in + return albumArtThumbnailData(engine: TelegramEngine(account: account), thumbnail: value.fullSizeResource) + |> map { data -> UIImage? in + return data.flatMap(UIImage.init(data:)) + } + /*return Signal { subscriber in let fetched = account.postbox.mediaBox.fetchedResource(value.fullSizeResource, parameters: nil).start() let data = account.postbox.mediaBox.resourceData(value.fullSizeResource, pathExtension: nil, option: .complete(waitUntilFetchStatus: false)).start(next: { data in if data.complete, let value = try? Data(contentsOf: URL(fileURLWithPath: data.path)) { @@ -336,7 +341,7 @@ public final class MediaManagerImpl: NSObject, MediaManager { fetched.dispose() data.dispose() } - } + }*/ } else { return .single(nil) } diff --git a/submodules/TelegramUI/Sources/MultiplexedVideoNode.swift b/submodules/TelegramUI/Sources/MultiplexedVideoNode.swift index ae35bcee76..70084b7a3f 100644 --- a/submodules/TelegramUI/Sources/MultiplexedVideoNode.swift +++ b/submodules/TelegramUI/Sources/MultiplexedVideoNode.swift @@ -168,7 +168,7 @@ final class MultiplexedVideoNode: ASDisplayNode, UIScrollViewDelegate { self.trackingNode.isLayerBacked = true var timebase: CMTimebase? - CMTimebaseCreateWithMasterClock(allocator: nil, masterClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) + CMTimebaseCreateWithSourceClock(allocator: nil, sourceClock: CMClockGetHostTimeClock(), timebaseOut: &timebase) CMTimebaseSetRate(timebase!, rate: 0.0) self.timebase = timebase! diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index a7f50a0d69..0218b233e2 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -154,7 +154,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu self.contentNode = ASDisplayNode() - self.controlsNode = OverlayPlayerControlsNode(account: context.account, accountManager: context.sharedContext.accountManager, presentationData: self.presentationData, status: context.sharedContext.mediaManager.musicMediaPlayerState) + self.controlsNode = OverlayPlayerControlsNode(account: context.account, engine: context.engine, accountManager: context.sharedContext.accountManager, presentationData: self.presentationData, status: context.sharedContext.mediaManager.musicMediaPlayerState) self.historyBackgroundNode = ASDisplayNode() self.historyBackgroundNode.isLayerBacked = true diff --git a/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift b/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift index e17807d601..9c1a301fc8 100644 --- a/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift +++ b/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift @@ -88,6 +88,7 @@ private func stringsForDisplayData(_ data: SharedMediaPlaybackDisplayData?, pres final class OverlayPlayerControlsNode: ASDisplayNode { private let accountManager: AccountManager private let postbox: Postbox + private let engine: TelegramEngine private var presentationData: PresentationData private let backgroundNode: ASImageNode @@ -153,9 +154,10 @@ final class OverlayPlayerControlsNode: ASDisplayNode { private var validLayout: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat)? - init(account: Account, accountManager: AccountManager, presentationData: PresentationData, status: Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError>) { + init(account: Account, engine: TelegramEngine, accountManager: AccountManager, presentationData: PresentationData, status: Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError>) { self.accountManager = accountManager self.postbox = account.postbox + self.engine = engine self.presentationData = presentationData self.backgroundNode = ASImageNode() @@ -610,9 +612,9 @@ final class OverlayPlayerControlsNode: ASDisplayNode { if self.currentAlbumArt != albumArt || !self.currentAlbumArtInitialized { self.currentAlbumArtInitialized = true self.currentAlbumArt = albumArt - self.albumArtNode.setSignal(playerAlbumArt(postbox: self.postbox, fileReference: self.currentFileReference, albumArt: albumArt, thumbnail: true)) + self.albumArtNode.setSignal(playerAlbumArt(postbox: self.postbox, engine: self.engine, fileReference: self.currentFileReference, albumArt: albumArt, thumbnail: true)) if let largeAlbumArtNode = self.largeAlbumArtNode { - largeAlbumArtNode.setSignal(playerAlbumArt(postbox: self.postbox, fileReference: self.currentFileReference, albumArt: albumArt, thumbnail: false)) + largeAlbumArtNode.setSignal(playerAlbumArt(postbox: self.postbox, engine: self.engine, fileReference: self.currentFileReference, albumArt: albumArt, thumbnail: false)) } } } @@ -710,7 +712,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode { self.largeAlbumArtNode = largeAlbumArtNode self.addSubnode(largeAlbumArtNode) if self.currentAlbumArtInitialized { - largeAlbumArtNode.setSignal(playerAlbumArt(postbox: self.postbox, fileReference: self.currentFileReference, albumArt: self.currentAlbumArt, thumbnail: false)) + largeAlbumArtNode.setSignal(playerAlbumArt(postbox: self.postbox, engine: self.engine, fileReference: self.currentFileReference, albumArt: self.currentAlbumArt, thumbnail: false)) } } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index f53dd49829..a59737ef9e 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -5280,7 +5280,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self else { return } - let controller = WebSearchController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: strongSelf.isSettings ? nil : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { [weak self] result in + let controller = WebSearchController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, peer: EnginePeer(peer), chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: strongSelf.isSettings ? nil : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { [weak self] result in assetsController?.dismiss() self?.updateProfilePhoto(result) })) diff --git a/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift b/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift index ca367a21e8..6be621e137 100644 --- a/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift +++ b/submodules/TelegramUI/Sources/TelegramAccountAuxiliaryMethods.swift @@ -21,8 +21,6 @@ public let telegramAccountAuxiliaryMethods = AccountAuxiliaryMethods(fetchResour return fetchLocalFileGifMediaResource(resource: resource) } else if let photoLibraryResource = resource as? PhotoLibraryMediaResource { return fetchPhotoLibraryResource(localIdentifier: photoLibraryResource.localIdentifier) - } else if let resource = resource as? ExternalMusicAlbumArtResource { - return fetchExternalMusicAlbumArtResource(account: account, resource: resource) } else if let resource = resource as? ICloudFileResource { return fetchICloudFileResource(resource: resource) } else if let resource = resource as? SecureIdLocalImageResource { diff --git a/submodules/UndoUI/BUILD b/submodules/UndoUI/BUILD index c3a6d09fe4..3887213ddc 100644 --- a/submodules/UndoUI/BUILD +++ b/submodules/UndoUI/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/TextFormat:TextFormat", diff --git a/submodules/WebSearchUI/Sources/LegacyWebSearchEditor.swift b/submodules/WebSearchUI/Sources/LegacyWebSearchEditor.swift index a27dea3ff7..52bff87dd4 100644 --- a/submodules/WebSearchUI/Sources/LegacyWebSearchEditor.swift +++ b/submodules/WebSearchUI/Sources/LegacyWebSearchEditor.swift @@ -3,7 +3,6 @@ import UIKit import LegacyComponents import SwiftSignalKit import TelegramCore -import Postbox import SSignalKit import Display import TelegramPresentationData diff --git a/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift b/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift index 15f33aea6d..d41f41da01 100644 --- a/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift +++ b/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift @@ -3,7 +3,6 @@ import UIKit import LegacyComponents import SwiftSignalKit import TelegramCore -import Postbox import SSignalKit import UIKit import Display @@ -12,6 +11,7 @@ import AccountContext import PhotoResources import LegacyUI import LegacyMediaPickerUI +import Postbox class LegacyWebSearchItem: NSObject, TGMediaEditableItem, TGMediaSelectableItem { var isVideo: Bool { @@ -263,7 +263,7 @@ func legacyWebSearchItem(account: Account, result: ChatContextResult) -> LegacyW representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailDimensions), resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)) } representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(imageDimensions), resource: imageResource, progressiveSizes: [], immediateThumbnailData: nil)) - let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) + let tmpImage = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) thumbnailSignal = chatMessagePhotoDatas(postbox: account.postbox, photoReference: .standalone(media: tmpImage), autoFetchFullSize: false) |> mapToSignal { value -> Signal in let thumbnailData = value._0 @@ -312,7 +312,7 @@ private func galleryItems(account: Account, results: [ChatContextResult], curren return (galleryItems, focusItem) } -func presentLegacyWebSearchGallery(context: AccountContext, peer: Peer?, chatLocation: ChatLocation?, presentationData: PresentationData, results: [ChatContextResult], current: ChatContextResult, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (ChatContextResult) -> UIView?, completed: @escaping (ChatContextResult) -> Void, presentStickers: ((@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?)?, present: (ViewController, Any?) -> Void) { +func presentLegacyWebSearchGallery(context: AccountContext, peer: EnginePeer?, chatLocation: ChatLocation?, presentationData: PresentationData, results: [ChatContextResult], current: ChatContextResult, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (ChatContextResult) -> UIView?, completed: @escaping (ChatContextResult) -> Void, presentStickers: ((@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?)?, present: (ViewController, Any?) -> Void) { let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil) legacyController.statusBar.statusBarStyle = presentationData.theme.rootController.statusBarStyle.style @@ -335,7 +335,7 @@ func presentLegacyWebSearchGallery(context: AccountContext, peer: Peer?, chatLoc let (items, focusItem) = galleryItems(account: context.account, results: results, current: current, selectionContext: selectionContext, editingContext: editingContext) - let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: false, allowCaptionEntities: true, hasTimer: false, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: false, hasCamera: false, recipientName: peer.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))! + let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: false, allowCaptionEntities: true, hasTimer: false, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: false, hasCamera: false, recipientName: peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))! model.stickersContext = paintStickersContext if let peer = peer, let chatLocation = chatLocation { model.suggestionContext = legacySuggestionContext(context: context, peerId: peer.id, chatLocation: chatLocation) diff --git a/submodules/WebSearchUI/Sources/WebSearchController.swift b/submodules/WebSearchUI/Sources/WebSearchController.swift index a3569188ed..776dd46a4a 100644 --- a/submodules/WebSearchUI/Sources/WebSearchController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchController.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import SwiftSignalKit import Display import AsyncDisplayKit @@ -10,7 +9,7 @@ import TelegramUIPreferences import TelegramPresentationData import AccountContext -public func requestContextResults(context: AccountContext, botId: PeerId, query: String, peerId: PeerId, offset: String = "", existingResults: ChatContextResultCollection? = nil, incompleteResults: Bool = false, staleCachedResults: Bool = false, limit: Int = 60) -> Signal { +public func requestContextResults(context: AccountContext, botId: EnginePeer.Id, query: String, peerId: EnginePeer.Id, offset: String = "", existingResults: ChatContextResultCollection? = nil, incompleteResults: Bool = false, staleCachedResults: Bool = false, limit: Int = 60) -> Signal { return context.engine.messages.requestChatContextResults(botId: botId, peerId: peerId, query: query, offset: offset, incompleteResults: incompleteResults, staleCachedResults: staleCachedResults) |> `catch` { error -> Signal in return .single(nil) @@ -125,7 +124,7 @@ public final class WebSearchController: ViewController { private let context: AccountContext private let mode: WebSearchControllerMode - private let peer: Peer? + private let peer: EnginePeer? private let chatLocation: ChatLocation? private let configuration: SearchBotsConfiguration @@ -156,7 +155,7 @@ public final class WebSearchController: ViewController { } } - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: Peer?, chatLocation: ChatLocation?, configuration: SearchBotsConfiguration, mode: WebSearchControllerMode) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: EnginePeer?, chatLocation: ChatLocation?, configuration: SearchBotsConfiguration, mode: WebSearchControllerMode) { self.context = context self.mode = mode self.peer = peer @@ -446,11 +445,11 @@ public final class WebSearchController: ViewController { let context = self.context let contextBot = self.context.engine.peers.resolvePeerByName(name: name) - |> mapToSignal { peer -> Signal in - return .single(peer?._asPeer()) + |> mapToSignal { peer -> Signal in + return .single(peer) } |> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError> in - if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder { + if case let .user(user) = peer, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder { let results = requestContextResults(context: context, botId: user.id, query: query, peerId: peerId, limit: 64) |> map { results -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in return { _ in diff --git a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift index 16043dee6f..176e6c63fe 100644 --- a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift +++ b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import SwiftSignalKit import Display import TelegramCore @@ -118,7 +117,7 @@ private func preparedWebSearchRecentTransition(from fromEntries: [WebSearchRecen class WebSearchControllerNode: ASDisplayNode { private let context: AccountContext - private let peer: Peer? + private let peer: EnginePeer? private let chatLocation: ChatLocation? private var theme: PresentationTheme private var strings: PresentationStrings @@ -172,7 +171,7 @@ class WebSearchControllerNode: ASDisplayNode { var presentStickers: ((@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?)? - init(context: AccountContext, presentationData: PresentationData, controllerInteraction: WebSearchControllerInteraction, peer: Peer?, chatLocation: ChatLocation?, mode: WebSearchMode) { + init(context: AccountContext, presentationData: PresentationData, controllerInteraction: WebSearchControllerInteraction, peer: EnginePeer?, chatLocation: ChatLocation?, mode: WebSearchMode) { self.context = context self.theme = presentationData.theme self.strings = presentationData.strings diff --git a/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift b/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift index 2b6a4024e5..5d9fe64993 100644 --- a/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import QuickLook -import Postbox import SwiftSignalKit import AsyncDisplayKit import TelegramCore @@ -38,7 +37,7 @@ struct WebSearchGalleryEntry: Equatable { switch self.result { case let .externalReference(externalReference): if let content = externalReference.content, externalReference.type == "gif", let thumbnailResource = externalReference.thumbnail?.resource, let dimensions = content.dimensions { - let fileReference = FileMediaReference.standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: content.resource, previewRepresentations: [TelegramMediaImageRepresentation(dimensions: dimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: dimensions, flags: [])])) + let fileReference = FileMediaReference.standalone(media: TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: content.resource, previewRepresentations: [TelegramMediaImageRepresentation(dimensions: dimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: dimensions, flags: [])])) return WebSearchVideoGalleryItem(context: context, presentationData: presentationData, index: self.index, result: self.result, content: NativeVideoContent(id: .contextResult(self.result.queryId, self.result.id), fileReference: fileReference, loopVideo: true, enableSound: false, fetchAutomatically: true), controllerInteraction: controllerInteraction) } case let .internalReference(internalReference): @@ -99,7 +98,7 @@ class WebSearchGalleryController: ViewController { private let replaceRootController: (ViewController, Promise?) -> Void private let baseNavigationController: NavigationController? - init(context: AccountContext, peer: Peer?, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext, entries: [WebSearchGalleryEntry], centralIndex: Int, replaceRootController: @escaping (ViewController, Promise?) -> Void, baseNavigationController: NavigationController?, sendCurrent: @escaping (ChatContextResult) -> Void) { + init(context: AccountContext, peer: EnginePeer?, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext, entries: [WebSearchGalleryEntry], centralIndex: Int, replaceRootController: @escaping (ViewController, Promise?) -> Void, baseNavigationController: NavigationController?, sendCurrent: @escaping (ChatContextResult) -> Void) { self.context = context self.replaceRootController = replaceRootController self.baseNavigationController = baseNavigationController @@ -115,7 +114,7 @@ class WebSearchGalleryController: ViewController { self?.dismiss(forceAway: true) }, selectionState: selectionState, editingState: editingState) - if let title = peer.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) { + if let title = peer?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) { let recipientNode = GalleryNavigationRecipientNode(color: .white, title: title) let leftItem = UIBarButtonItem(customDisplayNode: recipientNode) self.navigationItem.leftBarButtonItem = leftItem diff --git a/submodules/WebSearchUI/Sources/WebSearchGalleryFooterContentNode.swift b/submodules/WebSearchUI/Sources/WebSearchGalleryFooterContentNode.swift index 7ae115385e..8fab4b0895 100644 --- a/submodules/WebSearchUI/Sources/WebSearchGalleryFooterContentNode.swift +++ b/submodules/WebSearchUI/Sources/WebSearchGalleryFooterContentNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import SwiftSignalKit import LegacyComponents diff --git a/submodules/WebSearchUI/Sources/WebSearchItem.swift b/submodules/WebSearchUI/Sources/WebSearchItem.swift index 41f0592efc..433e9cbb81 100644 --- a/submodules/WebSearchUI/Sources/WebSearchItem.swift +++ b/submodules/WebSearchUI/Sources/WebSearchItem.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import Display import TelegramCore import SwiftSignalKit -import Postbox import TelegramPresentationData import CheckNode import PhotoResources @@ -51,7 +50,7 @@ final class WebSearchItemNode: GridItemNode { private let fetchStatusDisposable = MetaDisposable() private let fetchDisposable = MetaDisposable() - private var resourceStatus: MediaResourceStatus? + private var resourceStatus: EngineMediaResource.FetchStatus? override init() { self.imageNodeBackground = ASDisplayNode() @@ -137,7 +136,7 @@ final class WebSearchItemNode: GridItemNode { representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(imageDimensions), resource: imageResource, progressiveSizes: [], immediateThumbnailData: nil)) } if !representations.isEmpty { - let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) + let tmpImage = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) updateImageSignal = mediaGridMessagePhoto(account: item.account, photoReference: .standalone(media: tmpImage)) } else { updateImageSignal = .complete() diff --git a/submodules/WebSearchUI/Sources/WebSearchNavigationContentNode.swift b/submodules/WebSearchUI/Sources/WebSearchNavigationContentNode.swift index dbc045ef04..0b75b15ef1 100644 --- a/submodules/WebSearchUI/Sources/WebSearchNavigationContentNode.swift +++ b/submodules/WebSearchUI/Sources/WebSearchNavigationContentNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import TelegramPresentationData import SearchBarNode diff --git a/submodules/WebSearchUI/Sources/WebSearchRecentQueryItem.swift b/submodules/WebSearchUI/Sources/WebSearchRecentQueryItem.swift index 135bac146c..864e29696b 100644 --- a/submodules/WebSearchUI/Sources/WebSearchRecentQueryItem.swift +++ b/submodules/WebSearchUI/Sources/WebSearchRecentQueryItem.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import Display import SwiftSignalKit import TelegramCore diff --git a/submodules/WebSearchUI/Sources/WebSearchVideoGalleryItem.swift b/submodules/WebSearchUI/Sources/WebSearchVideoGalleryItem.swift index 92ba12146b..b271a88669 100644 --- a/submodules/WebSearchUI/Sources/WebSearchVideoGalleryItem.swift +++ b/submodules/WebSearchUI/Sources/WebSearchVideoGalleryItem.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import SwiftSignalKit import TelegramCore import Display -import Postbox import TelegramPresentationData import AccountContext import RadialStatusNode @@ -81,7 +80,7 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode { private let statusDisposable = MetaDisposable() private let fetchDisposable = MetaDisposable() - private var fetchStatus: MediaResourceStatus? + private var fetchStatus: EngineMediaResource.FetchStatus? private var fetchControls: FetchControls? var playbackCompleted: (() -> Void)? @@ -153,10 +152,10 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode { func setupItem(_ item: WebSearchVideoGalleryItem) { if self.item?.content.id != item.content.id { var isAnimated = false - var mediaResource: MediaResource? + var mediaResource: EngineMediaResource? if let content = item.content as? NativeVideoContent { isAnimated = content.fileReference.media.isAnimated - mediaResource = content.fileReference.media.resource + mediaResource = EngineMediaResource(content.fileReference.media.resource) } if let videoNode = self.videoNode { @@ -175,9 +174,12 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode { videoNode.canAttachContent = true self.requiresDownload = true - var mediaFileStatus: Signal = .single(nil) + var mediaFileStatus: Signal = .single(nil) if let mediaResource = mediaResource { - mediaFileStatus = item.context.account.postbox.mediaBox.resourceStatus(mediaResource) + mediaFileStatus = item.context.account.postbox.mediaBox.resourceStatus(mediaResource._asResource()) + |> map { status in + return EngineMediaResource.FetchStatus(status) + } |> map(Optional.init) }