this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

lint swift

Hailey 29cf10db bd7b0b5e

+96 -96
+9 -9
ios/AudioManagement.swift
··· 9 9 10 10 class AudioManagement { 11 11 static let shared = AudioManagement() 12 - 12 + 13 13 let audioSession = AVAudioSession.sharedInstance() 14 - var prevAudioCategory: AVAudioSession.Category? = nil 14 + var prevAudioCategory: AVAudioSession.Category? 15 15 var prevAudioActive: Bool = false 16 - 16 + 17 17 func setPlayingVideo(_ playing: Bool) { 18 18 if playing { 19 19 self.setAudioCategory(category: .playback) ··· 23 23 self.setAudioActive(false) 24 24 } 25 25 } 26 - 26 + 27 27 private func setAudioCategory(category: AVAudioSession.Category) { 28 28 if self.audioSession.category == category { 29 29 return 30 30 } 31 - 31 + 32 32 self.prevAudioCategory = self.audioSession.category 33 33 DispatchQueue.global(qos: .background).async { 34 34 try? AVAudioSession.sharedInstance().setCategory(category) 35 35 } 36 36 } 37 - 37 + 38 38 private func setAudioActive(_ active: Bool) { 39 39 if active == self.prevAudioActive { 40 40 return 41 41 } 42 - 42 + 43 43 if active { 44 44 DispatchQueue.global(qos: .background).async { 45 45 do { 46 46 try AVAudioSession.sharedInstance().setActive(true) 47 47 self.prevAudioActive = !self.prevAudioActive 48 48 } catch { } 49 - 50 - let _ = try? AVAudioSession.sharedInstance().setActive(true) 49 + 50 + _ = try? AVAudioSession.sharedInstance().setActive(true) 51 51 } 52 52 } else { 53 53 DispatchQueue.global(qos: .background).async {
+13 -13
ios/BlueskyVideoModule.swift
··· 1 1 import ExpoModulesCore 2 2 3 3 public class BlueskyVideoModule: Module { 4 - private var wasPlayingPlayer: AVPlayer? = nil 5 - 4 + private var wasPlayingPlayer: AVPlayer? 5 + 6 6 public func definition() -> ModuleDefinition { 7 7 Name("BlueskyVideo") 8 - 8 + 9 9 OnAppEntersForeground { 10 10 self.wasPlayingPlayer?.play() 11 11 self.wasPlayingPlayer = nil 12 12 } 13 - 13 + 14 14 OnAppEntersBackground { 15 15 PlayerManager.shared.allPlayers().forEach { player in 16 16 if player.isPlaying { ··· 20 20 } 21 21 } 22 22 } 23 - 23 + 24 24 AsyncFunction("updateActiveVideoViewAsync") { 25 25 ViewManager.shared.updateActiveView() 26 26 } 27 - 27 + 28 28 View(VideoView.self) { 29 29 Events([ 30 30 "onActiveChange", ··· 32 32 "onMutedChange", 33 33 "onStatusChange", 34 34 "onTimeRemainingChange", 35 - "onError", 35 + "onError" 36 36 ]) 37 - 37 + 38 38 Prop("url") { (view: VideoView, prop: URL) in 39 39 view.url = prop 40 40 } 41 - 41 + 42 42 Prop("autoplay") { (view: VideoView, prop: Bool) in 43 43 view.autoplay = prop 44 44 } 45 - 45 + 46 46 Prop("beginMuted") { (view: VideoView, prop: Bool) in 47 47 view.beginMuted = prop 48 48 } 49 - 49 + 50 50 AsyncFunction("togglePlayback") { (view: VideoView) in 51 51 view.togglePlayback() 52 52 } 53 - 53 + 54 54 AsyncFunction("toggleMuted") { (view: VideoView) in 55 55 view.toggleMuted() 56 56 } 57 - 57 + 58 58 AsyncFunction("enterFullscreen") { (view: VideoView) in 59 59 view.enterFullscreen() 60 60 }
+5 -5
ios/Manager.swift
··· 7 7 8 8 class Manager<T: AnyObject> { 9 9 private let objects = NSHashTable<T>.weakObjects() 10 - 10 + 11 11 func add(_ object: T) { 12 12 objects.add(object) 13 13 } 14 - 14 + 15 15 func remove(_ object: T) { 16 16 objects.remove(object) 17 17 } 18 - 18 + 19 19 func count() -> Int { 20 20 return objects.count 21 21 } 22 - 22 + 23 23 func has(_ object: T) -> Bool { 24 24 return objects.contains(object) 25 25 } 26 - 26 + 27 27 func getEnumerator() -> NSEnumerator? { 28 28 return objects.objectEnumerator() 29 29 }
+8 -8
ios/PlayerManager.swift
··· 9 9 10 10 class PlayerManager { 11 11 static let shared = PlayerManager() 12 - 12 + 13 13 private var availalbePlayers: [AVPlayer] = [] 14 14 private var usedPlayers: Set<AVPlayer> = [] 15 - 15 + 16 16 func dequeuePlayer() -> AVPlayer { 17 17 if let player = availalbePlayers.popLast() { 18 18 self.usedPlayers.insert(player) ··· 24 24 return newPlayer 25 25 } 26 26 } 27 - 27 + 28 28 func recyclePlayer(_ player: AVPlayer) { 29 29 self.resetPlayer(player) 30 30 self.usedPlayers.remove(player) 31 31 self.availalbePlayers.append(player) 32 32 } 33 - 33 + 34 34 private func resetPlayer(_ player: AVPlayer) { 35 35 player.replaceCurrentItem(with: nil) 36 36 player.isMuted = true 37 37 player.pause() 38 38 player.seek(to: CMTime.zero) 39 39 } 40 - 40 + 41 41 // MARK: - configuration 42 - 42 + 43 43 private func applyDefaultsToPlayer(_ player: AVPlayer) { 44 44 player.automaticallyWaitsToMinimizeStalling = false 45 45 player.preventsDisplaySleepDuringVideoPlayback = true 46 46 player.isMuted = true 47 - 47 + 48 48 } 49 - 49 + 50 50 func allPlayers() -> [AVPlayer] { 51 51 return Array(self.usedPlayers) + self.availalbePlayers 52 52 }
+52 -52
ios/VideoView.swift
··· 5 5 private var pViewController: AVPlayerViewController? 6 6 private var player: AVPlayer? 7 7 private var periodicTimeObserver: Any? 8 - 8 + 9 9 // props 10 10 var autoplay: Bool = true 11 11 var url: URL? 12 12 var beginMuted = true 13 - 13 + 14 14 // controls 15 15 private var isLoading: Bool = true { 16 16 didSet { ··· 22 22 ]) 23 23 } 24 24 } 25 - 25 + 26 26 private var isPlaying: Bool = false { 27 27 didSet { 28 28 if isPlaying == oldValue { 29 29 return 30 30 } 31 - 31 + 32 32 self.onStatusChange([ 33 33 "status": isPlaying ? "playing" : "paused" 34 34 ]) 35 35 } 36 36 } 37 - 37 + 38 38 private var isViewActive: Bool = false { 39 39 didSet { 40 40 if isViewActive == oldValue { ··· 45 45 ]) 46 46 } 47 47 } 48 - 48 + 49 49 private var isFullscreen: Bool = false { 50 50 didSet { 51 51 if isFullscreen { ··· 56 56 } 57 57 } 58 58 } 59 - 59 + 60 60 // event handlers 61 61 private let onActiveChange = EventDispatcher() 62 62 private let onLoadingChange = EventDispatcher() ··· 64 64 private let onStatusChange = EventDispatcher() 65 65 private let onTimeRemainingChange = EventDispatcher() 66 66 private let onError = EventDispatcher() 67 - 67 + 68 68 private var enteredFullScreenMuted = true 69 - 69 + 70 70 required init(appContext: AppContext? = nil) { 71 71 self.pViewController = AVPlayerViewController() 72 72 super.init(appContext: appContext) 73 73 self.clipsToBounds = true 74 74 } 75 - 75 + 76 76 // MARK: - lifecycle 77 - 77 + 78 78 private func setup() { 79 79 guard let url = url, self.player == nil else { 80 80 return 81 81 } 82 - 82 + 83 83 // Setup the view controller 84 84 let pViewController = AVPlayerViewController() 85 85 pViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] ··· 88 88 pViewController.showsPlaybackControls = false 89 89 pViewController.delegate = self 90 90 pViewController.videoGravity = .resizeAspectFill 91 - 91 + 92 92 // Recycle the current player if there is one 93 93 if let currentPlayer = self.player { 94 94 PlayerManager.shared.recyclePlayer(currentPlayer) 95 95 } 96 - 96 + 97 97 // Get a new player to use 98 98 let player = PlayerManager.shared.dequeuePlayer() 99 - 99 + 100 100 // Add observers to the player 101 101 self.periodicTimeObserver = self.createPeriodicTimeObserver(player) 102 - 102 + 103 103 // Get the player item and add it to the player 104 104 DispatchQueue.global(qos: .background).async { [weak self] in 105 105 let playerItem = AVPlayerItem(url: url) 106 106 playerItem.preferredForwardBufferDuration = 5 107 - 107 + 108 108 DispatchQueue.main.async { 109 109 player.replaceCurrentItem(with: playerItem) 110 110 self?.addObserversToPlayerItem(playerItem) ··· 113 113 114 114 pViewController.player = player 115 115 self.addSubview(pViewController.view) 116 - 116 + 117 117 self.pViewController = pViewController 118 118 self.player = player 119 119 } 120 - 120 + 121 121 private func destroy() { 122 122 guard let player = self.player else { 123 123 return 124 124 } 125 - 125 + 126 126 // Fire final events 127 127 self.mute() 128 128 self.pause() 129 129 self.isLoading = true 130 - 130 + 131 131 // Remove period time observer and nil it 132 132 if let periodicTimeObserver = self.periodicTimeObserver { 133 133 self.player?.removeTimeObserver(periodicTimeObserver) 134 134 self.periodicTimeObserver = nil 135 135 } 136 - 136 + 137 137 // Remove any observers from the player item and nil the item 138 138 if let playerItem = self.player?.currentItem { 139 139 removeObserversFromPlayerItem(playerItem) ··· 142 142 // Recycle the player and nil the player 143 143 PlayerManager.shared.recyclePlayer(player) 144 144 self.player = nil 145 - 145 + 146 146 // Remove the player from the controller 147 147 self.pViewController?.player = nil 148 - 148 + 149 149 // Remove the view controller 150 150 self.pViewController?.view.removeFromSuperview() 151 151 self.pViewController?.removeFromParent() 152 152 self.pViewController = nil 153 153 } 154 - 154 + 155 155 override func willMove(toWindow newWindow: UIWindow?) { 156 156 // Ignore anything that happens whenever we enter fullscreen. It's expected that the view will unmount here 157 157 if self.isFullscreen { 158 158 return 159 159 } 160 - 160 + 161 161 if newWindow == nil { 162 162 ViewManager.shared.remove(self) 163 163 self.destroy() ··· 165 165 ViewManager.shared.add(self) 166 166 } 167 167 } 168 - 168 + 169 169 deinit { 170 170 self.destroy() 171 171 } 172 - 172 + 173 173 // MARK: - observers 174 - 174 + 175 175 @objc func playerDidFinishPlaying(notification: NSNotification) { 176 176 self.player?.seek(to: CMTime.zero) 177 177 self.play() 178 178 } 179 - 179 + 180 180 override func observeValue(forKeyPath keyPath: String?, 181 181 of object: Any?, 182 - change: [NSKeyValueChangeKey : Any]?, 182 + change: [NSKeyValueChangeKey: Any]?, 183 183 context: UnsafeMutableRawPointer?) { 184 - 184 + 185 185 // This shouldn't happen, but just guard nil values 186 186 guard let player = self.player, 187 187 let playerItem = player.currentItem else { 188 188 return 189 189 } 190 - 190 + 191 191 // status changes for the player item, i.e. for loading 192 192 if keyPath == "status" { 193 193 if playerItem.status == AVPlayerItem.Status.readyToPlay { ··· 204 204 } 205 205 } 206 206 } 207 - 207 + 208 208 func createPeriodicTimeObserver(_ player: AVPlayer) -> Any? { 209 209 let interval = CMTime(seconds: 1, 210 210 preferredTimescale: CMTimeScale(NSEC_PER_SEC)) 211 - 211 + 212 212 return player.addPeriodicTimeObserver(forInterval: interval, 213 213 queue: .main) { [weak self] time in 214 214 guard let duration = self?.player?.currentItem?.duration else { ··· 220 220 ]) 221 221 } 222 222 } 223 - 223 + 224 224 func addObserversToPlayerItem(_ playerItem: AVPlayerItem) { 225 225 NotificationCenter.default.addObserver(self, 226 226 selector: #selector(playerDidFinishPlaying), ··· 228 228 object: playerItem) 229 229 playerItem.addObserver(self, forKeyPath: "status", options: [.old, .new], context: nil) 230 230 } 231 - 231 + 232 232 func removeObserversFromPlayerItem(_ playerItem: AVPlayerItem) { 233 233 NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: playerItem) 234 234 playerItem.removeObserver(self, forKeyPath: "status") 235 235 } 236 - 236 + 237 237 // MARK: - AVPlayerViewControllerDelegate 238 - 238 + 239 239 func playerViewController(_ playerViewController: AVPlayerViewController, 240 240 willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { 241 - coordinator.animate(alongsideTransition: nil) { transitionContext in 241 + coordinator.animate(alongsideTransition: nil) { _ in 242 242 self.isFullscreen = false 243 243 self.mute() 244 244 self.play() 245 245 } 246 246 } 247 - 247 + 248 248 // MARK: - visibility 249 - 249 + 250 250 func setIsCurrentlyActive(active: Bool) -> Bool { 251 251 if self.isFullscreen { 252 252 return false ··· 260 260 } 261 261 return true 262 262 } 263 - 263 + 264 264 // MARK: - controls 265 - 265 + 266 266 private func play() { 267 267 self.player?.play() 268 268 self.isPlaying = true 269 269 } 270 - 270 + 271 271 private func pause() { 272 272 self.player?.pause() 273 273 self.isPlaying = false 274 274 } 275 - 275 + 276 276 func togglePlayback() { 277 277 if self.isPlaying { 278 278 self.play() ··· 280 280 self.pause() 281 281 } 282 282 } 283 - 283 + 284 284 private func mute() { 285 285 AudioManagement.shared.setPlayingVideo(false) 286 286 self.player?.isMuted = true ··· 288 288 "isMuted": true 289 289 ]) 290 290 } 291 - 291 + 292 292 private func unmute() { 293 293 AudioManagement.shared.setPlayingVideo(true) 294 294 self.player?.isMuted = false 295 295 onMutedChange([ 296 - "isMuted": false, 296 + "isMuted": false 297 297 ]) 298 298 } 299 - 299 + 300 300 func toggleMuted() { 301 301 if self.player?.isMuted == true { 302 302 self.unmute() ··· 304 304 self.mute() 305 305 } 306 306 } 307 - 307 + 308 308 func enterFullscreen() { 309 309 guard let pViewController = self.pViewController, 310 310 !isFullscreen else { 311 311 return 312 312 } 313 - 313 + 314 314 let selectorName = "enterFullScreenAnimated:completionHandler:" 315 315 let selectorToForceFullScreenMode = NSSelectorFromString(selectorName) 316 316
+9 -9
ios/ViewManager.swift
··· 9 9 10 10 class ViewManager: Manager<VideoView> { 11 11 static let shared = ViewManager() 12 - 12 + 13 13 private var currentlyActiveView: VideoView? 14 14 private var screenHeight = UIScreen.main.bounds.height 15 15 private var prevCount = 0 16 - 16 + 17 17 override func add(_ object: VideoView) { 18 18 super.add(object) 19 - 19 + 20 20 if self.prevCount == 0 { 21 21 self.updateActiveView() 22 22 } ··· 27 27 super.remove(object) 28 28 self.prevCount = self.count() 29 29 } 30 - 30 + 31 31 func updateActiveView() { 32 32 DispatchQueue.main.async { 33 33 var activeView: VideoView? ··· 44 44 guard let views = self.getEnumerator() else { 45 45 return 46 46 } 47 - 47 + 48 48 var mostVisibleView: VideoView? 49 49 var mostVisiblePosition: CGRect? 50 50 ··· 52 52 guard let view = view as? VideoView else { 53 53 return 54 54 } 55 - 55 + 56 56 if !view.isViewableEnough() { 57 57 return 58 58 } ··· 87 87 } 88 88 } 89 89 } 90 - 90 + 91 91 private func clearActiveView() { 92 92 if let currentlyActiveView = self.currentlyActiveView { 93 - let _ = currentlyActiveView.setIsCurrentlyActive(active: false) 93 + _ = currentlyActiveView.setIsCurrentlyActive(active: false) 94 94 self.currentlyActiveView = nil 95 95 } 96 96 } 97 - 97 + 98 98 private func setActiveView(_ view: VideoView) { 99 99 let didUpdate = view.setIsCurrentlyActive(active: true) 100 100 if didUpdate {