import Foundation #if os(macOS) import PostboxMac import SwiftSignalKitMac import MtProtoKitMac #else import Postbox import SwiftSignalKit import MtProtoKitDynamic #endif #if os(macOS) private typealias SignalKitTimer = SwiftSignalKitMac.Timer #else private typealias SignalKitTimer = SwiftSignalKit.Timer #endif private final class ManagedAutoremoveMessageOperationsHelper { var entry: (TimestampBasedMessageAttributesEntry, MetaDisposable)? func update(_ head: TimestampBasedMessageAttributesEntry?) -> (disposeOperations: [Disposable], beginOperations: [(TimestampBasedMessageAttributesEntry, MetaDisposable)]) { var disposeOperations: [Disposable] = [] var beginOperations: [(TimestampBasedMessageAttributesEntry, MetaDisposable)] = [] if self.entry?.0.index != head?.index { if let (entry, disposable) = self.entry { self.entry = nil disposeOperations.append(disposable) } if let head = head { let disposable = MetaDisposable() self.entry = (head, disposable) beginOperations.append((head, disposable)) } } return (disposeOperations, beginOperations) } func reset() -> [Disposable] { if let entry = entry { return [entry.1] } else { return [] } } } func managedAutoremoveMessageOperations(postbox: Postbox) -> Signal { return Signal { _ in let helper = Atomic(value: ManagedAutoremoveMessageOperationsHelper()) let disposable = postbox.timestampBasedMessageAttributesView(tag: 0).start(next: { view in let (disposeOperations, beginOperations) = helper.with { helper -> (disposeOperations: [Disposable], beginOperations: [(TimestampBasedMessageAttributesEntry, MetaDisposable)]) in return helper.update(view.head) } for disposable in disposeOperations { disposable.dispose() } for (entry, disposable) in beginOperations { let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 let signal = Signal.complete() |> delay(max(0.0, Double(entry.timestamp) - timestamp), queue: Queue.concurrentDefaultQueue()) |> then(postbox.modify { modifier -> Void in modifier.deleteMessages([entry.messageId]) modifier.removeTimestampBasedMessageAttribute(tag: 0, messageId: entry.messageId) }) disposable.set(signal.start()) } }) return ActionDisposable { let disposables = helper.with { helper -> [Disposable] in return helper.reset() } for disposable in disposables { disposable.dispose() } } } }