|  |  |  | // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import Foundation | 
					
						
							|  |  |  | import SessionUtilitiesKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// This entity has responsibility for blocking the device from sleeping if certain behaviors (e.g. recording or | 
					
						
							|  |  |  | /// playing voice messages) are in progress. | 
					
						
							|  |  |  | /// | 
					
						
							|  |  |  | /// Sleep blocking is keyed using "block objects" whose lifetime corresponds to the duration of the block.  For | 
					
						
							|  |  |  | /// example, sleep blocking during audio playback can be keyed to the audio player.  This provides a measure | 
					
						
							|  |  |  | /// of robustness. | 
					
						
							|  |  |  | /// | 
					
						
							|  |  |  | /// On the one hand, we can use weak references to track block objects and stop blocking if the block object is | 
					
						
							|  |  |  | /// deallocated even if removeBlock() is not called.  On the other hand, we will also get correct behavior to addBlock() | 
					
						
							|  |  |  | /// being called twice with the same block object. | 
					
						
							|  |  |  | @objc | 
					
						
							|  |  |  | public class DeviceSleepManager: NSObject { | 
					
						
							|  |  |  |     @objc public static let sharedInstance = DeviceSleepManager() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private class SleepBlock: CustomDebugStringConvertible { | 
					
						
							|  |  |  |         weak var blockObject: NSObject? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var debugDescription: String { | 
					
						
							|  |  |  |             return "SleepBlock(\(String(reflecting: blockObject)))" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         init(blockObject: NSObject) { | 
					
						
							|  |  |  |             self.blockObject = blockObject | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     private var blocks: [SleepBlock] = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private override init() { | 
					
						
							|  |  |  |         super.init() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         NotificationCenter.default.addObserver( | 
					
						
							|  |  |  |             self, | 
					
						
							|  |  |  |             selector: #selector(didEnterBackground), | 
					
						
							|  |  |  |             name: NSNotification.Name.OWSApplicationDidEnterBackground, | 
					
						
							|  |  |  |             object: nil | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     deinit { | 
					
						
							|  |  |  |         NotificationCenter.default.removeObserver(self) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @objc | 
					
						
							|  |  |  |     private func didEnterBackground() { | 
					
						
							|  |  |  |         ensureSleepBlocking() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @objc | 
					
						
							|  |  |  |     public func addBlock(blockObject: NSObject) { | 
					
						
							|  |  |  |         blocks.append(SleepBlock(blockObject: blockObject)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ensureSleepBlocking() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @objc | 
					
						
							|  |  |  |     public func removeBlock(blockObject: NSObject) { | 
					
						
							|  |  |  |         blocks = blocks.filter { | 
					
						
							|  |  |  |             $0.blockObject != nil && $0.blockObject != blockObject | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ensureSleepBlocking() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private func ensureSleepBlocking() { | 
					
						
							|  |  |  |         // Cull expired blocks. | 
					
						
							|  |  |  |         blocks = blocks.filter { | 
					
						
							|  |  |  |             $0.blockObject != nil | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         let shouldBlock = blocks.count > 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         CurrentAppContext().ensureSleepBlocking(shouldBlock, blockingObjects: blocks) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |