From 471eb18ba1bf3855687cbc6bb56dc6489e15a21b Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 1 Jul 2023 19:22:09 +0200 Subject: [PATCH] Improve preload --- .../Sources/ChatListController.swift | 20 +-- .../Messages/TelegramEngineMessages.swift | 60 +++---- .../Sources/StoryChatContent.swift | 150 ++++++++---------- .../Sources/StoryPeerListComponent.swift | 4 +- 4 files changed, 101 insertions(+), 133 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index e071e7d4c1..652f25fffd 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -187,7 +187,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController private var storyProgressDisposable: Disposable? private var storySubscriptionsDisposable: Disposable? private var preloadStorySubscriptionsDisposable: Disposable? - private var preloadStoryResourceDisposables: [MediaResourceId: Disposable] = [:] + private var preloadStoryResourceDisposables: [MediaId: Disposable] = [:] private var fullScreenEffectView: RippleEffectView? @@ -1821,23 +1821,17 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController resources.removeAll() } - var validIds: [MediaResourceId] = [] + var validIds: [MediaId] = [] for (_, info) in resources.sorted(by: { $0.value.priority < $1.value.priority }) { - let resource = info.resource - validIds.append(resource.resource.id) - if self.preloadStoryResourceDisposables[resource.resource.id] == nil { - var fetchRange: (Range, MediaBoxFetchPriority)? - if let size = info.size { - fetchRange = (0 ..< Int64(size), .default) + if let mediaId = info.media.id { + validIds.append(mediaId) + if self.preloadStoryResourceDisposables[mediaId] == nil { + self.preloadStoryResourceDisposables[mediaId] = preloadStoryMedia(context: self.context, peer: info.peer, storyId: info.storyId, media: info.media).start() } - #if DEBUG - fetchRange = nil - #endif - self.preloadStoryResourceDisposables[resource.resource.id] = fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: resource, range: fetchRange).start() } } - var removeIds: [MediaResourceId] = [] + var removeIds: [MediaId] = [] for (id, disposable) in self.preloadStoryResourceDisposables { if !validIds.contains(id) { removeIds.append(id) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index b6212cfba0..968df7dc17 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -14,17 +14,20 @@ public final class StoryPreloadInfo { case next(position: Int) } - public let resource: MediaResourceReference - public let size: Int32? + public let peer: PeerReference + public let storyId: Int32 + public let media: EngineMedia public let priority: Priority public init( - resource: MediaResourceReference, - size: Int32?, + peer: PeerReference, + storyId: Int32, + media: EngineMedia, priority: Priority ) { - self.resource = resource - self.size = size + self.peer = peer + self.storyId = storyId + self.media = media self.priority = priority } } @@ -822,7 +825,7 @@ public extension TelegramEngine { } } - public func preloadStorySubscriptions(isHidden: Bool) -> Signal<[EngineMediaResource.Id: StoryPreloadInfo], NoError> { + public func preloadStorySubscriptions(isHidden: Bool) -> Signal<[EngineMedia.Id: StoryPreloadInfo], NoError> { let basicPeerKey = PostboxViewKey.basicPeer(self.account.peerId) let subscriptionsKey: PostboxStorySubscriptionsKey = isHidden ? .hidden : .filtered let storySubscriptionsKey = PostboxViewKey.storySubscriptions(key: subscriptionsKey) @@ -831,7 +834,7 @@ public extension TelegramEngine { storySubscriptionsKey, PostboxViewKey.storiesState(key: .subscriptions(subscriptionsKey)) ]) - |> mapToSignal { views -> Signal<[EngineMediaResource.Id: StoryPreloadInfo], NoError> in + |> mapToSignal { views -> Signal<[EngineMedia.Id: StoryPreloadInfo], NoError> in guard let basicPeerView = views.views[basicPeerKey] as? BasicPeerView, let accountPeer = basicPeerView.peer else { return .single([:]) } @@ -854,7 +857,7 @@ public extension TelegramEngine { }) return self.account.postbox.combinedView(keys: additionalDataKeys) - |> map { views -> [EngineMediaResource.Id: StoryPreloadInfo] in + |> map { views -> [EngineMedia.Id: StoryPreloadInfo] in let _ = accountPeer let _ = storiesStateView @@ -893,42 +896,23 @@ public extension TelegramEngine { }) var nextPriority: Int = 0 - var resultResources: [EngineMediaResource.Id: StoryPreloadInfo] = [:] + var resultResources: [EngineMedia.Id: StoryPreloadInfo] = [:] for itemAndPeer in sortedItems.prefix(10) { guard let peerReference = PeerReference(itemAndPeer.peer) else { continue } - guard let media = itemAndPeer.item.media else { + guard let media = itemAndPeer.item.media, let mediaId = media.id else { continue } - if let image = media as? TelegramMediaImage, let resource = image.representations.last?.resource { - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: itemAndPeer.item.id, media: media), resource: resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: nil, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } else if let file = media as? TelegramMediaFile { - if let preview = file.previewRepresentations.last { - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: itemAndPeer.item.id, media: file), resource: preview.resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: nil, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } - - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: itemAndPeer.item.id, media: file), resource: file.resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: file.preloadSize, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } + + resultResources[mediaId] = StoryPreloadInfo( + peer: peerReference, + storyId: itemAndPeer.item.id, + media: EngineMedia(media), + priority: .top(position: nextPriority) + ) + nextPriority += 1 } return resultResources diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift index 3e5cd25fa8..da21e1214b 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift @@ -6,6 +6,7 @@ import SwiftSignalKit import AccountContext import TelegramCore import Postbox +import MediaResources private struct StoryKey: Hashable { var peerId: EnginePeer.Id @@ -396,7 +397,7 @@ public final class StoryContentContextImpl: StoryContentContext { private var requestedStoryKeys = Set() private var requestStoryDisposables = DisposableSet() - private var preloadStoryResourceDisposables: [MediaResourceId: Disposable] = [:] + private var preloadStoryResourceDisposables: [MediaId: Disposable] = [:] private var pollStoryMetadataDisposables = DisposableSet() private var singlePeerListContext: PeerExpiringStoryListContext? @@ -761,55 +762,30 @@ public final class StoryContentContextImpl: StoryContentContext { } var nextPriority = 0 - var resultResources: [EngineMediaResource.Id: StoryPreloadInfo] = [:] + var resultResources: [EngineMedia.Id: StoryPreloadInfo] = [:] for i in 0 ..< min(possibleItems.count, 3) { let peer = possibleItems[i].0 let item = possibleItems[i].1 - if let peerReference = PeerReference(peer._asPeer()) { - if let image = item.media._asMedia() as? TelegramMediaImage, let resource = image.representations.last?.resource { - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: item.id, media: image), resource: resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: nil, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } else if let file = item.media._asMedia() as? TelegramMediaFile { - if let preview = file.previewRepresentations.last { - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: item.id, media: file), resource: preview.resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: nil, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } - - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: item.id, media: file), resource: file.resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: file.preloadSize, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } + if let peerReference = PeerReference(peer._asPeer()), let mediaId = item.media.id { + resultResources[mediaId] = StoryPreloadInfo( + peer: peerReference, + storyId: item.id, + media: item.media, + priority: .top(position: nextPriority) + ) + nextPriority += 1 } } - var validIds: [MediaResourceId] = [] - for (_, info) in resultResources.sorted(by: { $0.value.priority < $1.value.priority }) { - let resource = info.resource - validIds.append(resource.resource.id) - if self.preloadStoryResourceDisposables[resource.resource.id] == nil { - var fetchRange: (Range, MediaBoxFetchPriority)? - if let size = info.size { - fetchRange = (0 ..< Int64(size), .default) - } - self.preloadStoryResourceDisposables[resource.resource.id] = fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: resource, range: fetchRange).start() + var validIds: [EngineMedia.Id] = [] + for (id, info) in resultResources.sorted(by: { $0.value.priority < $1.value.priority }) { + validIds.append(id) + if self.preloadStoryResourceDisposables[id] == nil { + self.preloadStoryResourceDisposables[id] = preloadStoryMedia(context: context, peer: info.peer, storyId: info.storyId, media: info.media).start() } } - var removeIds: [MediaResourceId] = [] + var removeIds: [EngineMedia.Id] = [] for (id, disposable) in self.preloadStoryResourceDisposables { if !validIds.contains(id) { removeIds.append(id) @@ -1075,7 +1051,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { private var focusedId: Int32? private var focusedIdUpdated = Promise(Void()) - private var preloadStoryResourceDisposables: [MediaResourceId: Disposable] = [:] + private var preloadStoryResourceDisposables: [EngineMedia.Id: Disposable] = [:] private var pollStoryMetadataDisposables = DisposableSet() public init(context: AccountContext, peerId: EnginePeer.Id, listContext: PeerStoryListContext, initialId: Int32?) { @@ -1184,7 +1160,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { self.statePromise.set(.single(stateValue)) self.updatedPromise.set(.single(Void())) - var resultResources: [EngineMediaResource.Id: StoryPreloadInfo] = [:] + var resultResources: [EngineMedia.Id: StoryPreloadInfo] = [:] var pollItems: [StoryKey] = [] if let focusedIndex, let slice = stateValue.slice { @@ -1207,52 +1183,29 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { for i in 0 ..< min(possibleItems.count, 3) { let peer = possibleItems[i].0 let item = possibleItems[i].1 - if let peerReference = PeerReference(peer._asPeer()) { - if let image = item.media._asMedia() as? TelegramMediaImage, let resource = image.representations.last?.resource { - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: item.id, media: image), resource: resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: nil, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } else if let file = item.media._asMedia() as? TelegramMediaFile { - if let preview = file.previewRepresentations.last { - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: item.id, media: file), resource: preview.resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: nil, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } - - let resource = MediaResourceReference.media(media: .story(peer: peerReference, id: item.id, media: file), resource: file.resource) - resultResources[EngineMediaResource.Id(resource.resource.id)] = StoryPreloadInfo( - resource: resource, - size: file.preloadSize, - priority: .top(position: nextPriority) - ) - nextPriority += 1 - } + if let peerReference = PeerReference(peer._asPeer()), let mediaId = item.media.id { + resultResources[mediaId] = StoryPreloadInfo( + peer: peerReference, + storyId: item.id, + media: item.media, + priority: .top(position: nextPriority) + ) + nextPriority += 1 } } } - var validIds: [MediaResourceId] = [] + var validIds: [EngineMedia.Id] = [] for (_, info) in resultResources.sorted(by: { $0.value.priority < $1.value.priority }) { - let resource = info.resource - validIds.append(resource.resource.id) - if self.preloadStoryResourceDisposables[resource.resource.id] == nil { - var fetchRange: (Range, MediaBoxFetchPriority)? - if let size = info.size { - fetchRange = (0 ..< Int64(size), .default) + if let mediaId = info.media.id { + validIds.append(mediaId) + if self.preloadStoryResourceDisposables[mediaId] == nil { + self.preloadStoryResourceDisposables[mediaId] = preloadStoryMedia(context: context, peer: info.peer, storyId: info.storyId, media: info.media).start() } - self.preloadStoryResourceDisposables[resource.resource.id] = fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: resource, range: fetchRange).start() } } - var removeIds: [MediaResourceId] = [] + var removeIds: [EngineMedia.Id] = [] for (id, disposable) in self.preloadStoryResourceDisposables { if !validIds.contains(id) { removeIds.append(id) @@ -1330,3 +1283,40 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { let _ = self.context.engine.messages.markStoryAsSeen(peerId: id.peerId, id: id.id, asPinned: true).start() } } + +public func preloadStoryMedia(context: AccountContext, peer: PeerReference, storyId: Int32, media: EngineMedia) -> Signal { + var signals: [Signal] = [] + + switch media { + case let .image(image): + if let representation = largestImageRepresentation(image.representations) { + signals.append(fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .peer(peer.id), userContentType: .other, reference: .media(media: .story(peer: peer, id: storyId, media: media._asMedia()), resource: representation.resource), range: nil) + |> ignoreValues + |> `catch` { _ -> Signal in + return .complete() + }) + } + case let .file(file): + var fetchRange: (Range, MediaBoxFetchPriority)? + for attribute in file.attributes { + if case let .Video(_, _, _, preloadSize) = attribute { + if let preloadSize { + fetchRange = (0 ..< Int64(preloadSize), .default) + } + break + } + } + + signals.append(fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .peer(peer.id), userContentType: .other, reference: .media(media: .story(peer: peer, id: storyId, media: media._asMedia()), resource: file.resource), range: fetchRange) + |> ignoreValues + |> `catch` { _ -> Signal in + return .complete() + }) + signals.append(context.account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedVideoFirstFrameRepresentation(), complete: true, fetch: true, attemptSynchronously: false) + |> ignoreValues) + default: + break + } + + return combineLatest(signals) |> ignoreValues +} diff --git a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift index 7a5ba263b8..7b0e2699bc 100644 --- a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift @@ -693,7 +693,7 @@ public final class StoryPeerListComponent: Component { expandBoundsFraction = 0.0 } - let blurRadius: CGFloat = collapsedState.sideAlphaFraction * 0.0 + (1.0 - collapsedState.sideAlphaFraction) * 14.0 + /*let blurRadius: CGFloat = collapsedState.sideAlphaFraction * 0.0 + (1.0 - collapsedState.sideAlphaFraction) * 14.0 if blurRadius == 0.0 { self.sharedBlurEffect = nil } else { @@ -706,7 +706,7 @@ public final class StoryPeerListComponent: Component { self.sharedBlurEffect = nil } } - } + }*/ var targetCollapsedContentWidth: CGFloat = 0.0 if collapsedItemCount > 0 {