Improve preload

This commit is contained in:
Ali 2023-07-01 19:22:09 +02:00
parent d6434fa17f
commit 471eb18ba1
4 changed files with 101 additions and 133 deletions

View File

@ -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<Int64>, 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)

View File

@ -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,43 +896,24 @@ 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,
resultResources[mediaId] = StoryPreloadInfo(
peer: peerReference,
storyId: itemAndPeer.item.id,
media: EngineMedia(media),
priority: .top(position: nextPriority)
)
nextPriority += 1
}
}
return resultResources
}

View File

@ -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<StoryKey>()
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,
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<Int64>, 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>(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,
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
} 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
}
}
}
}
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<Int64>, 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<Never, NoError> {
var signals: [Signal<Never, NoError>] = []
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<Never, NoError> in
return .complete()
})
}
case let .file(file):
var fetchRange: (Range<Int64>, 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<Never, NoError> 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
}

View File

@ -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 {