import Foundation import UIKit import AsyncDisplayKit import SwiftSignalKit class SharedVideoContext { func dispose() { } } private final class SharedVideoContextSubscriber { let id: Int32 let priority: Int32 let update: (SharedVideoContext?) -> Void var active: Bool = false init(id: Int32, priority: Int32, update: @escaping (SharedVideoContext?) -> Void) { self.id = id self.priority = priority self.update = update } } private final class SharedVideoContextHolder { private var nextId: Int32 = 0 private var subscribers: [SharedVideoContextSubscriber] = [] let context: SharedVideoContext init(context: SharedVideoContext) { self.context = context } var isEmpty: Bool { return self.subscribers.isEmpty } func addSubscriber(priority: Int32, update: @escaping (SharedVideoContext?) -> Void) -> Int32 { let id = self.nextId self.nextId += 1 self.subscribers.append(SharedVideoContextSubscriber(id: id, priority: priority, update: update)) self.subscribers.sort(by: { lhs, rhs in if lhs.priority != rhs.priority { return lhs.priority < rhs.priority } return lhs.id < rhs.id }) return id } func removeSubscriberAndUpdate(id: Int32) { for i in 0 ..< self.subscribers.count { if self.subscribers[i].id == id { let subscriber = self.subscribers[i] self.subscribers.remove(at: i) if subscriber.active { subscriber.update(nil) self.update() } break } } } func update() { for i in (0 ..< self.subscribers.count) { if i == self.subscribers.count - 1 { if !self.subscribers[i].active { self.subscribers[i].active = true self.subscribers[i].update(self.context) } } else { if self.subscribers[i].active { self.subscribers[i].active = false self.subscribers[i].update(nil) } } } } } final class SharedVideoContextManager { private var holders: [AnyHashable: SharedVideoContextHolder] = [:] func attachSharedVideoContext(id: AnyHashable, priority: Int32, create: () -> SharedVideoContext, update: @escaping (SharedVideoContext?) -> Void) -> Int32 { assert(Queue.mainQueue().isCurrent()) let holder: SharedVideoContextHolder if let current = self.holders[id] { holder = current } else { holder = SharedVideoContextHolder(context: create()) self.holders[id] = holder } let id = holder.addSubscriber(priority: priority, update: update) holder.update() return id } func detachSharedVideoContext(id: AnyHashable, index: Int32) { assert(Queue.mainQueue().isCurrent()) if let holder = self.holders[id] { holder.removeSubscriberAndUpdate(id: index) if holder.isEmpty { holder.context.dispose() self.holders.removeValue(forKey: id) } } } func withSharedVideoContext(id: AnyHashable, _ f: (SharedVideoContext?) -> Void) { if let holder = self.holders[id] { f(holder.context) } else { f(nil) } } }