Merge branch 'dev'

This commit is contained in:
cranci1 2025-06-18 17:59:18 +02:00
commit cf5451599b
12 changed files with 43 additions and 49 deletions

View file

@ -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() {

View file

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

View file

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

View file

@ -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")

View file

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

View file

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

View file

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

View file

@ -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()

View file

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

View file

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

View file

@ -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 */,