mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +00:00
Merge branch 'dev'
This commit is contained in:
commit
cf5451599b
12 changed files with 43 additions and 49 deletions
|
|
@ -183,7 +183,8 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
watchNextButton,
|
||||
volumeSliderHostingView,
|
||||
pipButton,
|
||||
airplayButton
|
||||
airplayButton,
|
||||
timeBatteryContainer
|
||||
].compactMap { $0 }
|
||||
|
||||
private var originalHiddenStates: [UIView: Bool] = [:]
|
||||
|
|
@ -237,13 +238,9 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
}
|
||||
|
||||
let asset: AVURLAsset
|
||||
|
||||
// Check if this is a local file URL
|
||||
if url.scheme == "file" {
|
||||
// For local files, don't add HTTP headers
|
||||
Logger.shared.log("Loading local file: \(url.absoluteString)", type: "Debug")
|
||||
|
||||
// Check if file exists
|
||||
if FileManager.default.fileExists(atPath: url.path) {
|
||||
Logger.shared.log("Local file exists at path: \(url.path)", type: "Debug")
|
||||
} else {
|
||||
|
|
@ -252,7 +249,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
|
||||
asset = AVURLAsset(url: url)
|
||||
} else {
|
||||
// For remote URLs, add HTTP headers
|
||||
Logger.shared.log("Loading remote URL: \(url.absoluteString)", type: "Debug")
|
||||
var request = URLRequest(url: url)
|
||||
if let mydict = headers, !mydict.isEmpty {
|
||||
|
|
@ -271,8 +267,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
|
||||
let playerItem = AVPlayerItem(asset: asset)
|
||||
self.player = AVPlayer(playerItem: playerItem)
|
||||
|
||||
// Add error observation
|
||||
playerItem.addObserver(self, forKeyPath: "status", options: [.new], context: &playerItemKVOContext)
|
||||
|
||||
Logger.shared.log("Created AVPlayerItem with status: \(playerItem.status.rawValue)", type: "Debug")
|
||||
|
|
@ -1357,6 +1351,12 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
airplayButton.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
controlsContainerView.addSubview(airplayButton)
|
||||
|
||||
airplayButton.layer.shadowColor = UIColor.black.cgColor
|
||||
airplayButton.layer.shadowOffset = CGSize(width: 0, height: 2)
|
||||
airplayButton.layer.shadowOpacity = 0.6
|
||||
airplayButton.layer.shadowRadius = 4
|
||||
airplayButton.layer.masksToBounds = false
|
||||
|
||||
guard AVPictureInPictureController.isPictureInPictureSupported() else {
|
||||
return
|
||||
}
|
||||
|
|
@ -1368,7 +1368,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
pipController = AVPictureInPictureController(playerLayer: pipPlayerLayer)
|
||||
pipController?.delegate = self
|
||||
|
||||
|
||||
let config = UIImage.SymbolConfiguration(pointSize: 15, weight: .medium)
|
||||
let Image = UIImage(systemName: "pip", withConfiguration: config)
|
||||
pipButton = UIButton(type: .system)
|
||||
|
|
@ -1391,7 +1390,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
pipButton.widthAnchor.constraint(equalToConstant: 44),
|
||||
pipButton.heightAnchor.constraint(equalToConstant: 44),
|
||||
airplayButton.centerYAnchor.constraint(equalTo: pipButton.centerYAnchor),
|
||||
airplayButton.trailingAnchor.constraint(equalTo: pipButton.leadingAnchor, constant: -6),
|
||||
airplayButton.trailingAnchor.constraint(equalTo: pipButton.leadingAnchor, constant: -4),
|
||||
airplayButton.widthAnchor.constraint(equalToConstant: 44),
|
||||
airplayButton.heightAnchor.constraint(equalToConstant: 44)
|
||||
])
|
||||
|
|
@ -1416,11 +1415,11 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
menuButton.isHidden = true
|
||||
}
|
||||
|
||||
dismissButton.layer.shadowColor = UIColor.black.cgColor
|
||||
dismissButton.layer.shadowOffset = CGSize(width: 0, height: 2)
|
||||
dismissButton.layer.shadowOpacity = 0.6
|
||||
dismissButton.layer.shadowRadius = 4
|
||||
dismissButton.layer.masksToBounds = false
|
||||
menuButton.layer.shadowColor = UIColor.black.cgColor
|
||||
menuButton.layer.shadowOffset = CGSize(width: 0, height: 2)
|
||||
menuButton.layer.shadowOpacity = 0.6
|
||||
menuButton.layer.shadowRadius = 4
|
||||
menuButton.layer.masksToBounds = false
|
||||
|
||||
controlsContainerView.addSubview(menuButton)
|
||||
menuButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
|
@ -2831,7 +2830,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
}
|
||||
|
||||
private func setupTimeBatteryIndicator() {
|
||||
// Create container
|
||||
let container = UIView()
|
||||
container.translatesAutoresizingMaskIntoConstraints = false
|
||||
container.backgroundColor = .clear
|
||||
|
|
@ -2839,7 +2837,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
controlsContainerView.addSubview(container)
|
||||
self.timeBatteryContainer = container
|
||||
|
||||
// Create time label
|
||||
let timeLabel = UILabel()
|
||||
timeLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
timeLabel.textColor = .white
|
||||
|
|
@ -2848,13 +2845,11 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
container.addSubview(timeLabel)
|
||||
self.timeLabel = timeLabel
|
||||
|
||||
// Create separator
|
||||
let separator = UIView()
|
||||
separator.translatesAutoresizingMaskIntoConstraints = false
|
||||
separator.backgroundColor = .white.withAlphaComponent(0.5)
|
||||
container.addSubview(separator)
|
||||
|
||||
// Create battery label
|
||||
let batteryLabel = UILabel()
|
||||
batteryLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
batteryLabel.textColor = .white
|
||||
|
|
@ -2863,7 +2858,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
container.addSubview(batteryLabel)
|
||||
self.batteryLabel = batteryLabel
|
||||
|
||||
// Setup constraints
|
||||
NSLayoutConstraint.activate([
|
||||
container.centerXAnchor.constraint(equalTo: controlsContainerView.centerXAnchor),
|
||||
container.topAnchor.constraint(equalTo: sliderHostingController?.view.bottomAnchor ?? controlsContainerView.bottomAnchor, constant: 2),
|
||||
|
|
@ -2884,19 +2878,14 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
batteryLabel.widthAnchor.constraint(equalToConstant: 50)
|
||||
])
|
||||
|
||||
// Start time updates
|
||||
updateTime()
|
||||
timeUpdateTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
||||
self?.updateTime()
|
||||
}
|
||||
|
||||
// Setup battery monitoring
|
||||
UIDevice.current.isBatteryMonitoringEnabled = true
|
||||
updateBatteryLevel()
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector: #selector(batteryLevelDidChange),
|
||||
name: UIDevice.batteryLevelDidChangeNotification,
|
||||
object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(batteryLevelDidChange), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
|
||||
}
|
||||
|
||||
private func updateTime() {
|
||||
|
|
|
|||
|
|
@ -208,7 +208,6 @@ class VideoPlayerViewController: UIViewController {
|
|||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// Only start normal playback if not launched from SharePlay
|
||||
if !isLaunchedFromSharePlay {
|
||||
player?.play()
|
||||
setInitialPlayerRate()
|
||||
|
|
@ -217,7 +216,6 @@ class VideoPlayerViewController: UIViewController {
|
|||
await checkForFaceTimeAndPromptSharePlay()
|
||||
}
|
||||
} else {
|
||||
// For SharePlay launches, the playback will be coordinated
|
||||
setInitialPlayerRate()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
// Created by Francesco on 05/01/25.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
import Foundation
|
||||
|
||||
class FetchDelegate: NSObject, URLSessionTaskDelegate {
|
||||
private let allowRedirects: Bool
|
||||
|
|
|
|||
|
|
@ -18,6 +18,13 @@ struct ModuleAdditionSettingsView: View {
|
|||
@State private var errorMessage: String?
|
||||
var moduleUrl: String
|
||||
|
||||
private var moduleAlreadyExists: Bool {
|
||||
if let metadata = moduleMetadata {
|
||||
return moduleManager.modules.contains(where: { $0.metadata.sourceName == metadata.sourceName })
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
LinearGradient(
|
||||
|
|
@ -87,7 +94,7 @@ struct ModuleAdditionSettingsView: View {
|
|||
.fill(Color(.systemGray5))
|
||||
}
|
||||
}
|
||||
.frame(width: 32, height: 32)
|
||||
.frame(width: 40, height: 40)
|
||||
.clipShape(Circle())
|
||||
.shadow(
|
||||
color: colorScheme == .dark
|
||||
|
|
@ -194,10 +201,11 @@ struct ModuleAdditionSettingsView: View {
|
|||
Button(action: addModule) {
|
||||
HStack {
|
||||
Image(systemName: "plus.circle.fill")
|
||||
Text("Add Module")
|
||||
.foregroundColor(colorScheme == .dark ? .black : .white)
|
||||
Text(moduleAlreadyExists ? "Module already added" : "Add Module")
|
||||
}
|
||||
.font(.headline)
|
||||
.foregroundColor(Color.accentColor)
|
||||
.foregroundColor(colorScheme == .dark ? .black : .white)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 14)
|
||||
.background(
|
||||
|
|
@ -219,8 +227,8 @@ struct ModuleAdditionSettingsView: View {
|
|||
)
|
||||
.padding(.horizontal, 20)
|
||||
}
|
||||
.disabled(isLoading || moduleMetadata == nil)
|
||||
.opacity(isLoading ? 0.6 : 1)
|
||||
.disabled(isLoading || moduleMetadata == nil || moduleAlreadyExists)
|
||||
.opacity(isLoading || moduleAlreadyExists ? 0.6 : 1)
|
||||
|
||||
Button(action: { presentationMode.wrappedValue.dismiss() }) {
|
||||
Text("Cancel")
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ struct AllBookmarks: View {
|
|||
}
|
||||
Button(action: {
|
||||
if isSelecting {
|
||||
// If trash icon tapped
|
||||
if !selectedBookmarks.isEmpty {
|
||||
for id in selectedBookmarks {
|
||||
if let item = libraryManager.bookmarks.first(where: { $0.id == id }) {
|
||||
|
|
|
|||
|
|
@ -266,12 +266,17 @@ struct AllWatchingView: View {
|
|||
UserDefaults.standard.set(99999999.0, forKey: key)
|
||||
UserDefaults.standard.set(99999999.0, forKey: totalKey)
|
||||
ContinueWatchingManager.shared.remove(item: item)
|
||||
loadContinueWatchingItems()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
loadContinueWatchingItems()
|
||||
}
|
||||
}
|
||||
|
||||
private func removeItem(item: ContinueWatchingItem) {
|
||||
ContinueWatchingManager.shared.remove(item: item)
|
||||
loadContinueWatchingItems()
|
||||
DispatchQueue.main.async {
|
||||
loadContinueWatchingItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1508,7 +1508,7 @@ struct MediaInfoView: View {
|
|||
|
||||
alert.addAction(UIAlertAction(title: title, style: .default) { _ in
|
||||
guard self.activeFetchID == fetchID else { return }
|
||||
self.playStream(url: streamUrl, fullURL: href, subtitles: subtitles, headers: headers, fetchID: fetchID)
|
||||
self.playStream(url: streamUrl, fullURL: fullURL, subtitles: subtitles, headers: headers, fetchID: fetchID)
|
||||
})
|
||||
|
||||
streamIndex += 1
|
||||
|
|
|
|||
|
|
@ -275,9 +275,6 @@ struct SettingsViewGeneral: View {
|
|||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 12)
|
||||
|
||||
Divider()
|
||||
.padding(.horizontal, 16)
|
||||
|
||||
List {
|
||||
ForEach(Array(metadataProvidersOrder.enumerated()), id: \.element) { index, provider in
|
||||
HStack {
|
||||
|
|
@ -358,8 +355,6 @@ struct SettingsViewGeneral: View {
|
|||
}
|
||||
}
|
||||
.padding(.vertical, 20)
|
||||
.scrollViewBottomPadding()
|
||||
.navigationTitle("General")
|
||||
}
|
||||
.navigationTitle(NSLocalizedString("General", comment: ""))
|
||||
.scrollViewBottomPadding()
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ struct SubtitleSettingsSection: View {
|
|||
icon: "captions.bubble",
|
||||
title: NSLocalizedString("Enable Subtitles", comment: ""),
|
||||
isOn: $subtitlesEnabled,
|
||||
showDivider: false
|
||||
showDivider: true
|
||||
)
|
||||
.onChange(of: subtitlesEnabled) { newValue in
|
||||
SubtitleSettingsManager.shared.update { settings in
|
||||
|
|
@ -454,4 +454,4 @@ struct SubtitleSettingsSection: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ struct SplashScreenView: View {
|
|||
isAnimating = true
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
withAnimation(.easeOut(duration: 0.5)) {
|
||||
showMainApp = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,12 +247,12 @@
|
|||
path = SearchView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0409FE832DFF0870000DB00C /* cz.lproj */ = {
|
||||
0409FE832DFF0870000DB00C /* cs.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0409FE822DFF0870000DB00C /* Localizable.strings */,
|
||||
);
|
||||
path = cz.lproj;
|
||||
path = cs.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0409FE862DFF0870000DB00C /* es.lproj */ = {
|
||||
|
|
@ -632,7 +632,7 @@
|
|||
0410697D2E00ABE900A157BB /* sk.lproj */,
|
||||
04A1B73B2DFF39EB0064688A /* nn.lproj */,
|
||||
0409FE8B2DFF2886000DB00C /* ru.lproj */,
|
||||
0409FE832DFF0870000DB00C /* cz.lproj */,
|
||||
0409FE832DFF0870000DB00C /* cs.lproj */,
|
||||
0409FE862DFF0870000DB00C /* es.lproj */,
|
||||
0488FA9B2DFDF385007575E1 /* ar.lproj */,
|
||||
0488FA972DFDF334007575E1 /* fr.lproj */,
|
||||
|
|
|
|||
Loading…
Reference in a new issue