mirror of
https://github.com/cranci1/Sora.git
synced 2026-04-21 00:22:12 +00:00
Yeah idk what i am even doing at this point
This commit is contained in:
parent
22685e688f
commit
d94daaf177
3 changed files with 83 additions and 120 deletions
|
|
@ -41,7 +41,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
||||||
var currentTimeVal: Double = 0.0
|
var currentTimeVal: Double = 0.0
|
||||||
var duration: Double = 0.0
|
var duration: Double = 0.0
|
||||||
var isVideoLoaded = false
|
var isVideoLoaded = false
|
||||||
var detachedWindow: UIWindow?
|
|
||||||
|
|
||||||
private var isHoldPauseEnabled: Bool {
|
private var isHoldPauseEnabled: Bool {
|
||||||
UserDefaults.standard.bool(forKey: "holdForPauseEnabled")
|
UserDefaults.standard.bool(forKey: "holdForPauseEnabled")
|
||||||
|
|
@ -1816,15 +1815,12 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func dismissTapped() {
|
@objc func dismissTapped() {
|
||||||
dismiss(animated: true) { [weak self] in
|
dismiss(animated: true, completion: nil)
|
||||||
self?.detachedWindow = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func watchNextTapped() {
|
@objc func watchNextTapped() {
|
||||||
player.pause()
|
player.pause()
|
||||||
dismiss(animated: true) { [weak self] in
|
dismiss(animated: true) { [weak self] in
|
||||||
self?.detachedWindow = nil
|
|
||||||
self?.onWatchNext()
|
self?.onWatchNext()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2487,9 +2483,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
||||||
switch gesture.state {
|
switch gesture.state {
|
||||||
case .ended:
|
case .ended:
|
||||||
if translation.y > 100 {
|
if translation.y > 100 {
|
||||||
dismiss(animated: true) { [weak self] in
|
dismiss(animated: true, completion: nil)
|
||||||
self?.detachedWindow = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ class VideoPlayerViewController: UIViewController {
|
||||||
var episodeNumber: Int = 0
|
var episodeNumber: Int = 0
|
||||||
var episodeImageUrl: String = ""
|
var episodeImageUrl: String = ""
|
||||||
var mediaTitle: String = ""
|
var mediaTitle: String = ""
|
||||||
var detachedWindow: UIWindow?
|
|
||||||
|
|
||||||
init(module: ScrapingModule) {
|
init(module: ScrapingModule) {
|
||||||
self.module = module
|
self.module = module
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@ struct MediaInfoView: View {
|
||||||
@State private var isBulkDownloading: Bool = false
|
@State private var isBulkDownloading: Bool = false
|
||||||
@State private var bulkDownloadProgress: String = ""
|
@State private var bulkDownloadProgress: String = ""
|
||||||
@State private var tmdbType: TMDBFetcher.MediaType? = nil
|
@State private var tmdbType: TMDBFetcher.MediaType? = nil
|
||||||
@State private var latestProgress: Double = 0.0
|
|
||||||
|
|
||||||
private var isGroupedBySeasons: Bool {
|
private var isGroupedBySeasons: Bool {
|
||||||
return groupedEpisodes().count > 1
|
return groupedEpisodes().count > 1
|
||||||
|
|
@ -244,24 +243,20 @@ struct MediaInfoView: View {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.overlay(
|
.overlay(
|
||||||
VStack(spacing: 0) {
|
LinearGradient(
|
||||||
Spacer()
|
gradient: Gradient(stops: [
|
||||||
LinearGradient(
|
.init(color: .clear, location: 0.0),
|
||||||
gradient: Gradient(stops: [
|
.init(color: .clear, location: 0.7),
|
||||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.0), location: 0.0),
|
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.9), location: 1.0)
|
||||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.5), location: 0.5),
|
]),
|
||||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(1.0), location: 1.0)
|
startPoint: .top,
|
||||||
]),
|
endPoint: .bottom
|
||||||
startPoint: .top,
|
)
|
||||||
endPoint: .bottom
|
|
||||||
)
|
|
||||||
.frame(height: 150)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(Color.clear)
|
.fill(Color.clear)
|
||||||
.frame(height: 450)
|
.frame(height: 400)
|
||||||
VStack(alignment: .leading, spacing: 16) {
|
VStack(alignment: .leading, spacing: 16) {
|
||||||
headerSection
|
headerSection
|
||||||
if !episodeLinks.isEmpty {
|
if !episodeLinks.isEmpty {
|
||||||
|
|
@ -275,15 +270,15 @@ struct MediaInfoView: View {
|
||||||
LinearGradient(
|
LinearGradient(
|
||||||
gradient: Gradient(stops: [
|
gradient: Gradient(stops: [
|
||||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.0), location: 0.0),
|
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.0), location: 0.0),
|
||||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.3), location: 0.1),
|
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.5), location: 0.2),
|
||||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.6), location: 0.3),
|
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.8), location: 0.5),
|
||||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.9), location: 0.7),
|
.init(color: (colorScheme == .dark ? Color.black : Color.white), location: 1.0)
|
||||||
]),
|
]),
|
||||||
startPoint: .top,
|
startPoint: .top,
|
||||||
endPoint: .bottom
|
endPoint: .bottom
|
||||||
)
|
)
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 0))
|
.clipShape(RoundedRectangle(cornerRadius: 0))
|
||||||
.shadow(color: (colorScheme == .dark ? Color.black : Color.white).opacity(1), radius: 15, x: 0, y: 15)
|
.shadow(color: (colorScheme == .dark ? Color.black : Color.white).opacity(1), radius: 10, x: 0, y: 10)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.deviceScaled()
|
.deviceScaled()
|
||||||
|
|
@ -359,12 +354,10 @@ struct MediaInfoView: View {
|
||||||
UserDefaults.standard.set(99999999.0, forKey: "lastPlayedTime_\(ep.href)")
|
UserDefaults.standard.set(99999999.0, forKey: "lastPlayedTime_\(ep.href)")
|
||||||
UserDefaults.standard.set(99999999.0, forKey: "totalTime_\(ep.href)")
|
UserDefaults.standard.set(99999999.0, forKey: "totalTime_\(ep.href)")
|
||||||
DropManager.shared.showDrop(title: "Marked as Watched", subtitle: "", duration: 1.0, icon: UIImage(systemName: "checkmark.circle.fill"))
|
DropManager.shared.showDrop(title: "Marked as Watched", subtitle: "", duration: 1.0, icon: UIImage(systemName: "checkmark.circle.fill"))
|
||||||
updateLatestProgress()
|
|
||||||
} else {
|
} else {
|
||||||
UserDefaults.standard.set(0.0, forKey: "lastPlayedTime_\(ep.href)")
|
UserDefaults.standard.set(0.0, forKey: "lastPlayedTime_\(ep.href)")
|
||||||
UserDefaults.standard.set(0.0, forKey: "totalTime_\(ep.href)")
|
UserDefaults.standard.set(0.0, forKey: "totalTime_\(ep.href)")
|
||||||
DropManager.shared.showDrop(title: "Progress Reset", subtitle: "", duration: 1.0, icon: UIImage(systemName: "arrow.counterclockwise"))
|
DropManager.shared.showDrop(title: "Progress Reset", subtitle: "", duration: 1.0, icon: UIImage(systemName: "arrow.counterclockwise"))
|
||||||
updateLatestProgress()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -587,34 +580,25 @@ struct MediaInfoView: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var playAndBookmarkSection: some View {
|
private var playAndBookmarkSection: some View {
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
ZStack(alignment: .leading) {
|
Button(action: {
|
||||||
RoundedRectangle(cornerRadius: 25)
|
playFirstUnwatchedEpisode()
|
||||||
.fill(Color.accentColor)
|
}) {
|
||||||
.frame(height: 48)
|
HStack(spacing: 8) {
|
||||||
|
Image(systemName: "play.fill")
|
||||||
Button(action: {
|
.foregroundColor(colorScheme == .dark ? .black : .white)
|
||||||
playFirstUnwatchedEpisode()
|
Text(startWatchingText)
|
||||||
}) {
|
.font(.system(size: 16, weight: .medium))
|
||||||
HStack(spacing: 8) {
|
.foregroundColor(colorScheme == .dark ? .black : .white)
|
||||||
Image(systemName: "play.fill")
|
|
||||||
.foregroundColor(colorScheme == .dark ? .black : .white)
|
|
||||||
Text(continueWatchingText)
|
|
||||||
.font(.system(size: 16, weight: .medium))
|
|
||||||
.foregroundColor(colorScheme == .dark ? .black : .white)
|
|
||||||
}
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.padding(.vertical, 12)
|
|
||||||
.padding(.horizontal, 20)
|
|
||||||
.background(Color.clear)
|
|
||||||
.contentShape(RoundedRectangle(cornerRadius: 25))
|
|
||||||
}
|
}
|
||||||
.disabled(isFetchingEpisode)
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding(.vertical, 12)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 25)
|
||||||
|
.fill(Color.accentColor)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 25))
|
.disabled(isFetchingEpisode)
|
||||||
.overlay(
|
|
||||||
RoundedRectangle(cornerRadius: 25)
|
|
||||||
.stroke(Color.accentColor, lineWidth: 0)
|
|
||||||
)
|
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
libraryManager.toggleBookmark(
|
libraryManager.toggleBookmark(
|
||||||
|
|
@ -1000,46 +984,53 @@ struct MediaInfoView: View {
|
||||||
.padding(.vertical, 50)
|
.padding(.vertical, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var continueWatchingText: String {
|
private var startWatchingText: String {
|
||||||
for ep in episodeLinks {
|
let indices = finishedAndUnfinishedIndices()
|
||||||
let last = UserDefaults.standard.double(forKey: "lastPlayedTime_\(ep.href)")
|
let finished = indices.finished
|
||||||
let total = UserDefaults.standard.double(forKey: "totalTime_\(ep.href)")
|
let unfinished = indices.unfinished
|
||||||
let progress = total > 0 ? last / total : 0
|
|
||||||
|
if episodeLinks.count == 1 {
|
||||||
if progress > 0 && progress < 0.9 {
|
if let unfinishedIndex = unfinished {
|
||||||
return "Continue Watching Episode \(ep.number)"
|
return "Continue Watching"
|
||||||
}
|
}
|
||||||
|
return "Start Watching"
|
||||||
}
|
}
|
||||||
|
|
||||||
for ep in episodeLinks {
|
if let finishedIndex = finished, finishedIndex < episodeLinks.count - 1 {
|
||||||
let last = UserDefaults.standard.double(forKey: "lastPlayedTime_\(ep.href)")
|
let nextEp = episodeLinks[finishedIndex + 1]
|
||||||
let total = UserDefaults.standard.double(forKey: "totalTime_\(ep.href)")
|
return "Start Watching Episode \(nextEp.number)"
|
||||||
let progress = total > 0 ? last / total : 0
|
}
|
||||||
|
|
||||||
if progress < 0.9 {
|
if let unfinishedIndex = unfinished {
|
||||||
return "Start Watching Episode \(ep.number)"
|
let currentEp = episodeLinks[unfinishedIndex]
|
||||||
}
|
return "Continue Watching Episode \(currentEp.number)"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Start Watching"
|
return "Start Watching"
|
||||||
}
|
}
|
||||||
|
|
||||||
private func playFirstUnwatchedEpisode() {
|
private func playFirstUnwatchedEpisode() {
|
||||||
for ep in episodeLinks {
|
let indices = finishedAndUnfinishedIndices()
|
||||||
let last = UserDefaults.standard.double(forKey: "lastPlayedTime_\(ep.href)")
|
let finished = indices.finished
|
||||||
let total = UserDefaults.standard.double(forKey: "totalTime_\(ep.href)")
|
let unfinished = indices.unfinished
|
||||||
let progress = total > 0 ? last / total : 0
|
|
||||||
|
if let finishedIndex = finished, finishedIndex < episodeLinks.count - 1 {
|
||||||
if progress < 0.9 {
|
let nextEp = episodeLinks[finishedIndex + 1]
|
||||||
selectedEpisodeNumber = ep.number
|
selectedEpisodeNumber = nextEp.number
|
||||||
fetchStream(href: ep.href)
|
fetchStream(href: nextEp.href)
|
||||||
return
|
return
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let first = episodeLinks.first {
|
if let unfinishedIndex = unfinished {
|
||||||
selectedEpisodeNumber = first.number
|
let ep = episodeLinks[unfinishedIndex]
|
||||||
fetchStream(href: first.href)
|
selectedEpisodeNumber = ep.number
|
||||||
|
fetchStream(href: ep.href)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let firstEpisode = episodeLinks.first {
|
||||||
|
selectedEpisodeNumber = firstEpisode.number
|
||||||
|
fetchStream(href: firstEpisode.href)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1347,9 +1338,12 @@ struct MediaInfoView: View {
|
||||||
videoPlayerViewController.mediaTitle = title
|
videoPlayerViewController.mediaTitle = title
|
||||||
videoPlayerViewController.subtitles = subtitles ?? ""
|
videoPlayerViewController.subtitles = subtitles ?? ""
|
||||||
videoPlayerViewController.aniListID = itemID ?? 0
|
videoPlayerViewController.aniListID = itemID ?? 0
|
||||||
videoPlayerViewController.modalPresentationStyle = .fullScreen
|
videoPlayerViewController.modalPresentationStyle = .overFullScreen
|
||||||
|
|
||||||
presentPlayerWithDetachedContext(videoPlayerViewController: videoPlayerViewController)
|
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||||
|
let rootVC = windowScene.windows.first?.rootViewController {
|
||||||
|
findTopViewController.findViewController(rootVC).present(videoPlayerViewController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|
@ -1384,10 +1378,16 @@ struct MediaInfoView: View {
|
||||||
episodeImageUrl: selectedEpisodeImage,
|
episodeImageUrl: selectedEpisodeImage,
|
||||||
headers: headers ?? nil
|
headers: headers ?? nil
|
||||||
)
|
)
|
||||||
customMediaPlayer.modalPresentationStyle = .fullScreen
|
customMediaPlayer.modalPresentationStyle = .overFullScreen
|
||||||
Logger.shared.log("Opening custom media player with stream URL: \(url), and subtitles URL: \(String(describing: subtitles))", type: "Stream")
|
Logger.shared.log("Opening custom media player with url: \(url)")
|
||||||
|
|
||||||
presentPlayerWithDetachedContext(customMediaPlayer: customMediaPlayer)
|
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||||
|
let rootVC = windowScene.windows.first?.rootViewController {
|
||||||
|
findTopViewController.findViewController(rootVC).present(customMediaPlayer, animated: true, completion: nil)
|
||||||
|
} else {
|
||||||
|
Logger.shared.log("Failed to find root view controller", type: "Error")
|
||||||
|
DropManager.shared.showDrop(title: "Error", subtitle: "Failed to present player", duration: 2.0, icon: UIImage(systemName: "xmark.circle"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1936,34 +1936,4 @@ struct MediaInfoView: View {
|
||||||
}
|
}
|
||||||
}.resume()
|
}.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentPlayerWithDetachedContext(videoPlayerViewController: VideoPlayerViewController) {
|
|
||||||
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
|
|
||||||
|
|
||||||
let detachedWindow = UIWindow(windowScene: windowScene)
|
|
||||||
let hostingController = UIViewController()
|
|
||||||
hostingController.view.backgroundColor = .clear
|
|
||||||
detachedWindow.rootViewController = hostingController
|
|
||||||
detachedWindow.backgroundColor = .clear
|
|
||||||
detachedWindow.windowLevel = .normal + 1
|
|
||||||
detachedWindow.makeKeyAndVisible()
|
|
||||||
|
|
||||||
videoPlayerViewController.detachedWindow = detachedWindow
|
|
||||||
hostingController.present(videoPlayerViewController, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func presentPlayerWithDetachedContext(customMediaPlayer: CustomMediaPlayerViewController) {
|
|
||||||
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
|
|
||||||
|
|
||||||
let detachedWindow = UIWindow(windowScene: windowScene)
|
|
||||||
let hostingController = UIViewController()
|
|
||||||
hostingController.view.backgroundColor = .clear
|
|
||||||
detachedWindow.rootViewController = hostingController
|
|
||||||
detachedWindow.backgroundColor = .clear
|
|
||||||
detachedWindow.windowLevel = .normal + 1
|
|
||||||
detachedWindow.makeKeyAndVisible()
|
|
||||||
|
|
||||||
customMediaPlayer.detachedWindow = detachedWindow
|
|
||||||
hostingController.present(customMediaPlayer, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue