From 7c5cec2285d36e0f2b23782553868b43a2ba59e3 Mon Sep 17 00:00:00 2001 From: cranci1 <100066266+cranci1@users.noreply.github.com> Date: Tue, 10 Jun 2025 21:15:16 +0200 Subject: [PATCH] opsi my fault --- Sora/Utils/MediaPlayer/SubtitleManager.swift | 81 ----------------- Sora/Utils/MediaPlayer/VideoPlayer.swift | 87 ++++++++++++------- .../xcshareddata/swiftpm/Package.resolved | 3 +- 3 files changed, 55 insertions(+), 116 deletions(-) delete mode 100644 Sora/Utils/MediaPlayer/SubtitleManager.swift diff --git a/Sora/Utils/MediaPlayer/SubtitleManager.swift b/Sora/Utils/MediaPlayer/SubtitleManager.swift deleted file mode 100644 index d0cdc7b..0000000 --- a/Sora/Utils/MediaPlayer/SubtitleManager.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// SubtitleManager.swift -// Sora -// -// Created by Francesco on 10/06/25. -// - -import UIKit -import Foundation -import AVFoundation - -class SubtitleManager { - static let shared = SubtitleManager() - private let subtitleLoader = VTTSubtitlesLoader() - - private init() {} - - func loadSubtitles(from url: URL) async throws -> [SubtitleCue] { - return await withCheckedContinuation { continuation in - subtitleLoader.load(from: url.absoluteString) - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - continuation.resume(returning: self.subtitleLoader.cues) - } - } - } - - func createSubtitleOverlay(for cues: [SubtitleCue], player: AVPlayer) -> SubtitleOverlayView { - let overlay = SubtitleOverlayView() - let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)) - - player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { time in - let currentTime = time.seconds - let currentCue = cues.first { cue in - currentTime >= cue.startTime && currentTime <= cue.endTime - } - overlay.update(with: currentCue?.text ?? "") - } - - return overlay - } -} - -class SubtitleOverlayView: UIView { - private let label: UILabel = { - let label = UILabel() - label.numberOfLines = 0 - label.textAlignment = .center - label.textColor = .white - label.font = .systemFont(ofSize: 16, weight: .medium) - label.layer.shadowColor = UIColor.black.cgColor - label.layer.shadowOffset = CGSize(width: 1, height: 1) - label.layer.shadowOpacity = 0.8 - label.layer.shadowRadius = 2 - return label - }() - - override init(frame: CGRect) { - super.init(frame: frame) - setupView() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - setupView() - } - - private func setupView() { - backgroundColor = .clear - addSubview(label) - label.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20), - label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20), - label.centerYAnchor.constraint(equalTo: centerYAnchor) - ]) - } - - func update(with text: String) { - label.text = text - } -} diff --git a/Sora/Utils/MediaPlayer/VideoPlayer.swift b/Sora/Utils/MediaPlayer/VideoPlayer.swift index 384153c..8da1cd0 100644 --- a/Sora/Utils/MediaPlayer/VideoPlayer.swift +++ b/Sora/Utils/MediaPlayer/VideoPlayer.swift @@ -24,7 +24,8 @@ class VideoPlayerViewController: UIViewController { var episodeNumber: Int = 0 var episodeImageUrl: String = "" var mediaTitle: String = "" - var subtitleOverlay: SubtitleOverlayView? + var subtitlesLoader: VTTSubtitlesLoader? + var subtitleLabel: UILabel? init(module: ScrapingModule) { self.module = module @@ -35,6 +36,54 @@ class VideoPlayerViewController: UIViewController { fatalError("init(coder:) has not been implemented") } + private func setupSubtitles() { + guard !subtitles.isEmpty && UserDefaults.standard.bool(forKey: "subtitlesEnabled"), + let subtitleURL = URL(string: subtitles) else { + return + } + + subtitlesLoader = VTTSubtitlesLoader() + setupSubtitleLabel() + + subtitlesLoader?.load(from: subtitles) + + let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)) + player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in + self?.updateSubtitles(at: time.seconds) + } + } + + private func setupSubtitleLabel() { + let label = UILabel() + label.numberOfLines = 0 + label.textAlignment = .center + label.textColor = .white + label.font = .systemFont(ofSize: 16, weight: .medium) + label.layer.shadowColor = UIColor.black.cgColor + label.layer.shadowOffset = CGSize(width: 1, height: 1) + label.layer.shadowOpacity = 0.8 + label.layer.shadowRadius = 2 + + guard let playerView = playerViewController?.view else { return } + playerView.addSubview(label) + label.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + label.leadingAnchor.constraint(equalTo: playerView.leadingAnchor, constant: 16), + label.trailingAnchor.constraint(equalTo: playerView.trailingAnchor, constant: -16), + label.bottomAnchor.constraint(equalTo: playerView.bottomAnchor, constant: -32) + ]) + + self.subtitleLabel = label + } + + private func updateSubtitles(at time: Double) { + let currentSubtitle = subtitlesLoader?.cues.first { cue in + time >= cue.startTime && time <= cue.endTime + } + subtitleLabel?.text = currentSubtitle?.text ?? "" + } + override func viewDidLoad() { super.viewDidLoad() @@ -69,21 +118,7 @@ class VideoPlayerViewController: UIViewController { playerViewController.didMove(toParent: self) if !subtitles.isEmpty && UserDefaults.standard.bool(forKey: "subtitlesEnabled") { - if let subtitleURL = URL(string: subtitles) { - Task { - do { - let subtitleCues = try await SubtitleManager.shared.loadSubtitles(from: subtitleURL) - await MainActor.run { - if let player = self.player { - let overlay = SubtitleManager.shared.createSubtitleOverlay(for: subtitleCues, player: player) - self.addSubtitleOverlay(overlay) - } - } - } catch { - Logger.shared.log("Failed to load subtitles: \(error.localizedDescription)", type: "Error") - } - } - } + setupSubtitles() } } @@ -177,22 +212,6 @@ class VideoPlayerViewController: UIViewController { } } - private func addSubtitleOverlay(_ overlay: SubtitleOverlayView) { - subtitleOverlay?.removeFromSuperview() - subtitleOverlay = overlay - - guard let playerView = playerViewController?.view else { return } - playerView.addSubview(overlay) - overlay.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate([ - overlay.leadingAnchor.constraint(equalTo: playerView.leadingAnchor), - overlay.trailingAnchor.constraint(equalTo: playerView.trailingAnchor), - overlay.bottomAnchor.constraint(equalTo: playerView.bottomAnchor), - overlay.heightAnchor.constraint(equalToConstant: 100) - ]) - } - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UserDefaults.standard.bool(forKey: "alwaysLandscape") { return .landscape @@ -214,6 +233,8 @@ class VideoPlayerViewController: UIViewController { if let timeObserverToken = timeObserverToken { player?.removeTimeObserver(timeObserverToken) } - subtitleOverlay?.removeFromSuperview() + subtitleLabel?.removeFromSuperview() + subtitleLabel = nil + subtitlesLoader = nil } } diff --git a/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d8a331d..0b5a161 100644 --- a/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,4 @@ { - "originHash" : "e12f82ce5205016ea66a114308acd41450cfe950ccb1aacfe0e26181d2036fa4", "pins" : [ { "identity" : "drops", @@ -29,5 +28,5 @@ } } ], - "version" : 3 + "version" : 2 }