opsi my fault
Some checks are pending
Build and Release / Build IPA (push) Waiting to run
Build and Release / Build Mac Catalyst (push) Waiting to run

This commit is contained in:
cranci1 2025-06-10 21:15:16 +02:00
parent cc4c75f88a
commit 7c5cec2285
3 changed files with 55 additions and 116 deletions

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -1,5 +1,4 @@
{
"originHash" : "e12f82ce5205016ea66a114308acd41450cfe950ccb1aacfe0e26181d2036fa4",
"pins" : [
{
"identity" : "drops",
@ -29,5 +28,5 @@
}
}
],
"version" : 3
"version" : 2
}