Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 66 additions & 57 deletions TelegramUI/UniversalVideoContentManager.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import AsyncDisplayKit
import SwiftSignalKit
import Postbox

private final class UniversalVideoContentSubscriber {
let id: Int32
Expand Down Expand Up @@ -135,6 +136,19 @@ private final class UniversalVideoContentHolderCallbacks {
}
}

private struct NativeVideoContentHolderKey: Hashable {
let id: UInt32
let mediaId: MediaId
}

private func getHolderKey(forContentId id: AnyHashable) -> AnyHashable {
if let id = id as? NativeVideoContentId, case let .message(_, stableId, mediaId) = id {
return NativeVideoContentHolderKey(id: stableId, mediaId: mediaId)
} else {
return id
}
}

final class UniversalVideoContentManager {
private var holders: [AnyHashable: UniversalVideoContentHolder] = [:]
private var holderCallbacks: [AnyHashable: UniversalVideoContentHolderCallbacks] = [:]
Expand All @@ -143,49 +157,37 @@ final class UniversalVideoContentManager {
assert(Queue.mainQueue().isCurrent())

var initiatedCreation = false

let holderKey = getHolderKey(forContentId: content.id)
let holder: UniversalVideoContentHolder
if let current = self.holders[content.id] {

if let current = self.holders[holderKey] {
holder = current
} else {
var foundHolder: UniversalVideoContentHolder?
for (_, current) in self.holders {
if current.content.isEqual(to: content) {
//foundHolder = current
break
}
}
if let foundHolder = foundHolder {
holder = foundHolder
} else {
initiatedCreation = true
holder = UniversalVideoContentHolder(content: content, contentNode: create(), statusUpdated: { [weak self] value in
if let strongSelf = self {
if let current = strongSelf.holderCallbacks[content.id] {
for subscriber in current.status.copyItems() {
subscriber(value)
}
}
initiatedCreation = true
holder = UniversalVideoContentHolder(
content: content,
contentNode: create(),
statusUpdated: { [weak self] value in
guard let self = self, let current = self.holderCallbacks[holderKey] else { return }
for subscriber in current.status.copyItems() {
subscriber(value)
}
}, bufferingStatusUpdated: { [weak self] value in
if let strongSelf = self {
if let current = strongSelf.holderCallbacks[content.id] {
for subscriber in current.bufferingStatus.copyItems() {
subscriber(value)
}
}
},
bufferingStatusUpdated: { [weak self] value in
guard let self = self, let current = self.holderCallbacks[holderKey] else { return }
for subscriber in current.bufferingStatus.copyItems() {
subscriber(value)
}
}, playbackCompleted: { [weak self] in
if let strongSelf = self {
if let current = strongSelf.holderCallbacks[content.id] {
for subscriber in current.playbackCompleted.copyItems() {
subscriber()
}
}
},
playbackCompleted: { [weak self] in
guard let self = self, let current = self.holderCallbacks[holderKey] else { return }
for subscriber in current.playbackCompleted.copyItems() {
subscriber()
}
})
self.holders[content.id] = holder
}
}
)

self.holders[holderKey] = holder
}

let id = holder.addSubscriber(priority: priority, update: update)
Expand All @@ -195,13 +197,14 @@ final class UniversalVideoContentManager {

func detachUniversalVideoContent(id: AnyHashable, index: Int32) {
assert(Queue.mainQueue().isCurrent())

if let holder = self.holders[id] {

let holderKey = getHolderKey(forContentId: id)
if let holder = self.holders[holderKey] {
holder.removeSubscriberAndUpdate(id: index)
if holder.isEmpty {
self.holders.removeValue(forKey: id)
self.holders.removeValue(forKey: holderKey)

if let current = self.holderCallbacks[id] {
if let current = self.holderCallbacks[holderKey] {
for subscriber in current.status.copyItems() {
subscriber(nil)
}
Expand All @@ -211,7 +214,8 @@ final class UniversalVideoContentManager {
}

func withUniversalVideoContent(id: AnyHashable, _ f: ((UniversalVideoContentNode & ASDisplayNode)?) -> Void) {
if let holder = self.holders[id] {
let holderKey = getHolderKey(forContentId: id)
if let holder = self.holders[holderKey] {
f(holder.contentNode)
} else {
f(nil)
Expand All @@ -220,51 +224,54 @@ final class UniversalVideoContentManager {

func addPlaybackCompleted(id: AnyHashable, _ f: @escaping () -> Void) -> Int {
assert(Queue.mainQueue().isCurrent())
let holderKey = getHolderKey(forContentId: id)
var callbacks: UniversalVideoContentHolderCallbacks
if let current = self.holderCallbacks[id] {
if let current = self.holderCallbacks[holderKey] {
callbacks = current
} else {
callbacks = UniversalVideoContentHolderCallbacks()
self.holderCallbacks[id] = callbacks
self.holderCallbacks[holderKey] = callbacks
}
return callbacks.playbackCompleted.add(f)
}

func removePlaybackCompleted(id: AnyHashable, index: Int) {
if let current = self.holderCallbacks[id] {
let holderKey = getHolderKey(forContentId: id)
if let current = self.holderCallbacks[holderKey] {
current.playbackCompleted.remove(index)
if current.playbackCompleted.isEmpty {
self.holderCallbacks.removeValue(forKey: id)
self.holderCallbacks.removeValue(forKey: holderKey)
}
}
}

func statusSignal(content: UniversalVideoContent) -> Signal<MediaPlayerStatus?, NoError> {
return Signal { subscriber in
let holderKey = getHolderKey(forContentId: content.id)

var callbacks: UniversalVideoContentHolderCallbacks
if let current = self.holderCallbacks[content.id] {
if let current = self.holderCallbacks[holderKey] {
callbacks = current
} else {
callbacks = UniversalVideoContentHolderCallbacks()
self.holderCallbacks[content.id] = callbacks
self.holderCallbacks[holderKey] = callbacks
}

let index = callbacks.status.add({ value in
subscriber.putNext(value)
})

if let current = self.holders[content.id] {
if let current = self.holders[holderKey] {
subscriber.putNext(current.statusValue)
} else {
subscriber.putNext(nil)
}

return ActionDisposable {
Queue.mainQueue().async {
if let current = self.holderCallbacks[content.id] {
if let current = self.holderCallbacks[holderKey] {
current.status.remove(index)
if current.playbackCompleted.isEmpty {
self.holderCallbacks.removeValue(forKey: content.id)
self.holderCallbacks.removeValue(forKey: holderKey)
}
}
}
Expand All @@ -274,30 +281,32 @@ final class UniversalVideoContentManager {

func bufferingStatusSignal(content: UniversalVideoContent) -> Signal<(IndexSet, Int)?, NoError> {
return Signal { subscriber in
let holderKey = getHolderKey(forContentId: content.id)

var callbacks: UniversalVideoContentHolderCallbacks
if let current = self.holderCallbacks[content.id] {
if let current = self.holderCallbacks[holderKey] {
callbacks = current
} else {
callbacks = UniversalVideoContentHolderCallbacks()
self.holderCallbacks[content.id] = callbacks
self.holderCallbacks[holderKey] = callbacks
}

let index = callbacks.bufferingStatus.add({ value in
subscriber.putNext(value)
})

if let current = self.holders[content.id] {
if let current = self.holders[holderKey] {
subscriber.putNext(current.bufferingStatusValue)
} else {
subscriber.putNext(nil)
}

return ActionDisposable {
Queue.mainQueue().async {
if let current = self.holderCallbacks[content.id] {
if let current = self.holderCallbacks[holderKey] {
current.status.remove(index)
if current.playbackCompleted.isEmpty {
self.holderCallbacks.removeValue(forKey: content.id)
self.holderCallbacks.removeValue(forKey: holderKey)
}
}
}
Expand Down