diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a97205..334ac49 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build and Release IPA on: push: branches: - - main + - dev jobs: build: name: Build IPA @@ -24,6 +24,6 @@ jobs: - name: Upload IPA artifact uses: actions/upload-artifact@v4 with: - name: Sora-IPA - path: build/Sora.ipa + name: Sulfur-IPA + path: build/Sulfur.ipa compression-level: 0 diff --git a/Sora/Utils/Extensions/finTopView.swift b/Sora/Utils/Extensions/finTopView.swift new file mode 100644 index 0000000..adcdfd7 --- /dev/null +++ b/Sora/Utils/Extensions/finTopView.swift @@ -0,0 +1,27 @@ +// +// finTopView.swift +// Sulfur +// +// Created by Francesco on 04/03/25. +// + +import UIKit + +class findTopViewController { + static func findViewController(_ viewController: UIViewController) -> UIViewController { + if let presented = viewController.presentedViewController { + return findViewController(presented) + } + + if let navigationController = viewController as? UINavigationController { + return findViewController(navigationController.visibleViewController ?? navigationController) + } + + if let tabBarController = viewController as? UITabBarController, + let selected = tabBarController.selectedViewController { + return findViewController(selected) + } + + return viewController + } +} diff --git a/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift b/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift index 038499e..e3c8713 100644 --- a/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift +++ b/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift @@ -57,6 +57,10 @@ class CustomMediaPlayerViewController: UIViewController { var sliderViewModel = SliderViewModel() var isSliderEditing = false + var watchNextButtonNormalConstraints: [NSLayoutConstraint] = [] + var watchNextButtonControlsConstraints: [NSLayoutConstraint] = [] + var isControlsVisible = false + init(module: ScrapingModule, urlString: String, fullUrl: String, @@ -106,8 +110,9 @@ class CustomMediaPlayerViewController: UIViewController { setupControls() setupSubtitleLabel() setupDismissButton() - setupSpeedButton() setupMenuButton() + setupSpeedButton() + setupWatchNextButton() addTimeObserver() startUpdateTimer() setupAudioSession() @@ -244,17 +249,6 @@ class CustomMediaPlayerViewController: UIViewController { sliderHostView.heightAnchor.constraint(equalToConstant: 30) ]) - watchNextButton = UIButton(type: .system) - watchNextButton.setTitle("Watch Next", for: .normal) - watchNextButton.setImage(UIImage(systemName: "forward.fill"), for: .normal) - watchNextButton.backgroundColor = .white - watchNextButton.layer.cornerRadius = 16 - watchNextButton.setTitleColor(.black, for: .normal) - watchNextButton.addTarget(self, action: #selector(watchNextTapped), for: .touchUpInside) - watchNextButton.isHidden = true - controlsContainerView.addSubview(watchNextButton) - watchNextButton.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ playPauseButton.centerXAnchor.constraint(equalTo: controlsContainerView.centerXAnchor), playPauseButton.centerYAnchor.constraint(equalTo: controlsContainerView.centerYAnchor), @@ -269,12 +263,7 @@ class CustomMediaPlayerViewController: UIViewController { forwardButton.centerYAnchor.constraint(equalTo: playPauseButton.centerYAnchor), forwardButton.leadingAnchor.constraint(equalTo: playPauseButton.trailingAnchor, constant: 30), forwardButton.widthAnchor.constraint(equalToConstant: 40), - forwardButton.heightAnchor.constraint(equalToConstant: 40), - - watchNextButton.trailingAnchor.constraint(equalTo: controlsContainerView.trailingAnchor, constant: -10), - watchNextButton.bottomAnchor.constraint(equalTo: controlsContainerView.bottomAnchor, constant: -80), - watchNextButton.heightAnchor.constraint(equalToConstant: 50), - watchNextButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 120) + forwardButton.heightAnchor.constraint(equalToConstant: 40) ]) } @@ -288,9 +277,9 @@ class CustomMediaPlayerViewController: UIViewController { subtitleLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ subtitleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), - subtitleLabel.bottomAnchor.constraint(equalTo: sliderHostingController?.view.topAnchor ?? view.safeAreaLayoutGuide.bottomAnchor), - subtitleLabel.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 20), - subtitleLabel.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -20) + subtitleLabel.bottomAnchor.constraint(equalTo: sliderHostingController?.view.bottomAnchor ?? view.safeAreaLayoutGuide.bottomAnchor), + subtitleLabel.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 36), + subtitleLabel.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -36) ]) } @@ -323,9 +312,10 @@ class CustomMediaPlayerViewController: UIViewController { controlsContainerView.addSubview(menuButton) menuButton.translatesAutoresizingMaskIntoConstraints = false + guard let sliderView = sliderHostingController?.view else { return } NSLayoutConstraint.activate([ - menuButton.bottomAnchor.constraint(equalTo: controlsContainerView.bottomAnchor, constant: -50), - menuButton.trailingAnchor.constraint(equalTo: speedButton.leadingAnchor), + menuButton.bottomAnchor.constraint(equalTo: sliderView.topAnchor), + menuButton.trailingAnchor.constraint(equalTo: sliderView.trailingAnchor), menuButton.widthAnchor.constraint(equalToConstant: 40), menuButton.heightAnchor.constraint(equalToConstant: 40) ]) @@ -341,15 +331,46 @@ class CustomMediaPlayerViewController: UIViewController { controlsContainerView.addSubview(speedButton) speedButton.translatesAutoresizingMaskIntoConstraints = false - guard let sliderView = sliderHostingController?.view else { return } NSLayoutConstraint.activate([ - speedButton.bottomAnchor.constraint(equalTo: sliderView.topAnchor), - speedButton.trailingAnchor.constraint(equalTo: sliderView.trailingAnchor), + speedButton.bottomAnchor.constraint(equalTo: controlsContainerView.bottomAnchor, constant: -50), + speedButton.trailingAnchor.constraint(equalTo: menuButton.leadingAnchor), speedButton.widthAnchor.constraint(equalToConstant: 40), speedButton.heightAnchor.constraint(equalToConstant: 40) ]) } + func setupWatchNextButton() { + watchNextButton = UIButton(type: .system) + watchNextButton.setTitle("Watch Next", for: .normal) + watchNextButton.setImage(UIImage(systemName: "forward.fill"), for: .normal) + watchNextButton.tintColor = .black + watchNextButton.backgroundColor = .white + watchNextButton.layer.cornerRadius = 25 + watchNextButton.setTitleColor(.black, for: .normal) + watchNextButton.addTarget(self, action: #selector(watchNextTapped), for: .touchUpInside) + watchNextButton.isHidden = true + watchNextButton.alpha = 0.8 + + view.addSubview(watchNextButton) + watchNextButton.translatesAutoresizingMaskIntoConstraints = false + + watchNextButtonNormalConstraints = [ + watchNextButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), + watchNextButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -40), + watchNextButton.heightAnchor.constraint(equalToConstant: 50), + watchNextButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 120) + ] + + watchNextButtonControlsConstraints = [ + watchNextButton.trailingAnchor.constraint(equalTo: speedButton.leadingAnchor), + watchNextButton.bottomAnchor.constraint(equalTo: speedButton.bottomAnchor, constant: -5), + watchNextButton.heightAnchor.constraint(equalToConstant: 50), + watchNextButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 120) + ] + + NSLayoutConstraint.activate(watchNextButtonControlsConstraints) + } + func updateSubtitleLabelAppearance() { subtitleLabel.font = UIFont.systemFont(ofSize: CGFloat(subtitleFontSize)) subtitleLabel.textColor = subtitleUIColor() @@ -405,7 +426,6 @@ class CustomMediaPlayerViewController: UIViewController { && self.duration != 0 { if UserDefaults.standard.bool(forKey: "hideNextButton") { - self.watchNextButton.isHidden = false DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { self.watchNextButton.isHidden = true } @@ -444,8 +464,22 @@ class CustomMediaPlayerViewController: UIViewController { } @objc func toggleControls() { + isControlsVisible.toggle() + UIView.animate(withDuration: 0.2) { - self.controlsContainerView.alpha = self.controlsContainerView.alpha == 0 ? 1 : 0 + self.controlsContainerView.alpha = self.isControlsVisible ? 1 : 0 + + if self.isControlsVisible { + NSLayoutConstraint.deactivate(self.watchNextButtonNormalConstraints) + NSLayoutConstraint.activate(self.watchNextButtonControlsConstraints) + self.watchNextButton.alpha = 1.0 + } else { + NSLayoutConstraint.deactivate(self.watchNextButtonControlsConstraints) + NSLayoutConstraint.activate(self.watchNextButtonNormalConstraints) + self.watchNextButton.alpha = 0.8 + } + + self.view.layoutIfNeeded() } } diff --git a/Sora/Utils/MediaPlayer/VideoPlayer.swift b/Sora/Utils/MediaPlayer/VideoPlayer.swift index aede1b0..77ab5aa 100644 --- a/Sora/Utils/MediaPlayer/VideoPlayer.swift +++ b/Sora/Utils/MediaPlayer/VideoPlayer.swift @@ -148,4 +148,11 @@ class VideoPlayerViewController: UIViewController { override var prefersStatusBarHidden: Bool { return true } + + deinit { + player?.pause() + if let timeObserverToken = timeObserverToken { + player?.removeTimeObserver(timeObserverToken) + } + } } diff --git a/Sora/Views/HomeView.swift b/Sora/Views/HomeView.swift index b3a57eb..d3792d5 100644 --- a/Sora/Views/HomeView.swift +++ b/Sora/Views/HomeView.swift @@ -41,229 +41,231 @@ struct HomeView: View { var body: some View { NavigationView { - ScrollView { - if !continueWatchingItems.isEmpty { - VStack(alignment: .leading) { - Text("Continue Watching") - .font(.headline) - .padding(.horizontal, 8) - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 8) { - ForEach(Array(continueWatchingItems.reversed())) { item in - Button(action: { - if UserDefaults.standard.string(forKey: "externalPlayer") == "Sora" { - let customMediaPlayer = CustomMediaPlayerViewController( - module: item.module, - urlString: item.streamUrl, - fullUrl: item.fullUrl, - title: item.mediaTitle, - episodeNumber: item.episodeNumber, - onWatchNext: { }, - subtitlesURL: item.subtitles, - episodeImageUrl: item.imageUrl - ) - customMediaPlayer.modalPresentationStyle = .fullScreen - - if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, - let rootVC = windowScene.windows.first?.rootViewController { - rootVC.present(customMediaPlayer, animated: true, completion: nil) + VStack { + ScrollView { + if !continueWatchingItems.isEmpty { + LazyVStack(alignment: .leading) { + Text("Continue Watching") + .font(.headline) + .padding(.horizontal, 8) + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 8) { + ForEach(Array(continueWatchingItems.reversed())) { item in + Button(action: { + if UserDefaults.standard.string(forKey: "externalPlayer") == "Sora" { + let customMediaPlayer = CustomMediaPlayerViewController( + module: item.module, + urlString: item.streamUrl, + fullUrl: item.fullUrl, + title: item.mediaTitle, + episodeNumber: item.episodeNumber, + onWatchNext: { }, + subtitlesURL: item.subtitles, + episodeImageUrl: item.imageUrl + ) + customMediaPlayer.modalPresentationStyle = .fullScreen + + 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 { + let videoPlayerViewController = VideoPlayerViewController(module: item.module) + videoPlayerViewController.streamUrl = item.streamUrl + videoPlayerViewController.fullUrl = item.fullUrl + videoPlayerViewController.episodeImageUrl = item.imageUrl + videoPlayerViewController.episodeNumber = item.episodeNumber + videoPlayerViewController.mediaTitle = item.mediaTitle + videoPlayerViewController.subtitles = item.subtitles ?? "" + videoPlayerViewController.modalPresentationStyle = .fullScreen + + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let rootVC = windowScene.windows.first?.rootViewController { + findTopViewController.findViewController(rootVC).present(videoPlayerViewController, animated: true, completion: nil) + } } - } else { - let videoPlayerViewController = VideoPlayerViewController(module: item.module) - videoPlayerViewController.streamUrl = item.streamUrl - videoPlayerViewController.fullUrl = item.fullUrl - videoPlayerViewController.episodeImageUrl = item.imageUrl - videoPlayerViewController.episodeNumber = item.episodeNumber - videoPlayerViewController.mediaTitle = item.mediaTitle - videoPlayerViewController.subtitles = item.subtitles ?? "" - videoPlayerViewController.modalPresentationStyle = .fullScreen - - if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, - let rootVC = windowScene.windows.first?.rootViewController { - rootVC.present(videoPlayerViewController, animated: true, completion: nil) + }) { + VStack(alignment: .leading) { + ZStack { + KFImage(URL(string: item.imageUrl.isEmpty ? "https://raw.githubusercontent.com/cranci1/Sora/refs/heads/main/assets/banner2.png" : item.imageUrl)) + .placeholder { + RoundedRectangle(cornerRadius: 10) + .fill(Color.gray.opacity(0.3)) + .frame(width: 240, height: 135) + .shimmering() + } + .setProcessor(RoundCornerImageProcessor(cornerRadius: 10)) + .resizable() + .aspectRatio(16/9, contentMode: .fill) + .frame(width: 240, height: 135) + .cornerRadius(10) + .clipped() + .overlay( + KFImage(URL(string: item.module.metadata.iconUrl)) + .resizable() + .frame(width: 24, height: 24) + .cornerRadius(4) + .padding(4), + alignment: .topLeading + ) + } + .overlay( + ZStack { + Rectangle() + .fill(Color.black.opacity(0.3)) + .blur(radius: 3) + .frame(height: 30) + + ProgressView(value: item.progress) + .progressViewStyle(LinearProgressViewStyle(tint: .white)) + .padding(.horizontal, 8) + .scaleEffect(x: 1, y: 1.5, anchor: .center) + }, + alignment: .bottom + ) + + VStack(alignment: .leading) { + Text("Episode \(item.episodeNumber)") + .font(.caption) + .lineLimit(1) + .foregroundColor(.secondary) + + Text(item.mediaTitle) + .font(.caption) + .lineLimit(2) + .foregroundColor(.primary) + .multilineTextAlignment(.leading) + } + .padding(.horizontal, 8) + } + .frame(width: 250, height: 190) + } + .contextMenu { + Button(action: { markContinueWatchingItemAsWatched(item: item) }) { + Label("Mark as Watched", systemImage: "checkmark.circle") + } + Button(role: .destructive, action: { removeContinueWatchingItem(item: item) }) { + Label("Remove Item", systemImage: "trash") } } - }) { - VStack(alignment: .leading) { - ZStack { - KFImage(URL(string: item.imageUrl.isEmpty ? "https://raw.githubusercontent.com/cranci1/Sora/refs/heads/main/assets/banner2.png" : item.imageUrl)) + } + } + .padding(.horizontal, 8) + } + .frame(height: 190) + } + } + VStack(alignment: .leading, spacing: 16) { + HStack(alignment: .bottom, spacing: 5) { + Text("Seasonal") + .font(.headline) + Text("of \(currentDeviceSeasonAndYear.season) \(String(format: "%d", currentDeviceSeasonAndYear.year))") + .font(.subheadline) + .foregroundColor(.gray) + } + .padding(.horizontal, 8) + .padding(.top, 8) + + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 8) { + if aniListItems.isEmpty { + ForEach(0..<5, id: \.self) { _ in + HomeSkeletonCell() + } + } else { + ForEach(aniListItems, id: \.id) { item in + NavigationLink(destination: AniListDetailsView(animeID: item.id)) { + VStack { + KFImage(URL(string: item.coverImage.large)) .placeholder { RoundedRectangle(cornerRadius: 10) .fill(Color.gray.opacity(0.3)) - .frame(width: 240, height: 135) + .frame(width: 130, height: 195) .shimmering() } .setProcessor(RoundCornerImageProcessor(cornerRadius: 10)) .resizable() - .aspectRatio(16/9, contentMode: .fill) - .frame(width: 240, height: 135) + .scaledToFill() + .frame(width: 130, height: 195) .cornerRadius(10) .clipped() - .overlay( - KFImage(URL(string: item.module.metadata.iconUrl)) - .resizable() - .frame(width: 24, height: 24) - .cornerRadius(4) - .padding(4), - alignment: .topLeading - ) - } - .overlay( - ZStack { - Rectangle() - .fill(Color.black.opacity(0.3)) - .blur(radius: 3) - .frame(height: 30) - - ProgressView(value: item.progress) - .progressViewStyle(LinearProgressViewStyle(tint: .white)) - .padding(.horizontal, 8) - .scaleEffect(x: 1, y: 1.5, anchor: .center) - }, - alignment: .bottom - ) - - VStack(alignment: .leading) { - Text("Episode \(item.episodeNumber)") - .font(.caption) - .lineLimit(1) - .foregroundColor(.secondary) - Text(item.mediaTitle) + Text(item.title.romaji) .font(.caption) - .lineLimit(2) + .frame(width: 130) + .lineLimit(1) + .multilineTextAlignment(.center) .foregroundColor(.primary) - .multilineTextAlignment(.leading) } - .padding(.horizontal, 8) - } - .frame(width: 250, height: 190) - } - .contextMenu { - Button(action: { markContinueWatchingItemAsWatched(item: item) }) { - Label("Mark as Watched", systemImage: "checkmark.circle") - } - Button(role: .destructive, action: { removeContinueWatchingItem(item: item) }) { - Label("Remove Item", systemImage: "trash") } } } } .padding(.horizontal, 8) } - .frame(height: 190) - } - } - VStack(alignment: .leading, spacing: 16) { - HStack(alignment: .bottom, spacing: 5) { - Text("Seasonal") - .font(.headline) - Text("of \(currentDeviceSeasonAndYear.season) \(String(format: "%d", currentDeviceSeasonAndYear.year))") - .font(.subheadline) - .foregroundColor(.gray) - } - .padding(.horizontal, 8) - .padding(.top, 8) - - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 8) { - if aniListItems.isEmpty { - ForEach(0..<5, id: \.self) { _ in - HomeSkeletonCell() - } - } else { - ForEach(aniListItems, id: \.id) { item in - NavigationLink(destination: AniListDetailsView(animeID: item.id)) { - VStack { - KFImage(URL(string: item.coverImage.large)) - .placeholder { - RoundedRectangle(cornerRadius: 10) - .fill(Color.gray.opacity(0.3)) - .frame(width: 130, height: 195) - .shimmering() - } - .setProcessor(RoundCornerImageProcessor(cornerRadius: 10)) - .resizable() - .scaledToFill() - .frame(width: 130, height: 195) - .cornerRadius(10) - .clipped() - - Text(item.title.romaji) - .font(.caption) - .frame(width: 130) - .lineLimit(1) - .multilineTextAlignment(.center) - .foregroundColor(.primary) + + HStack(alignment: .bottom, spacing: 5) { + Text("Trending") + .font(.headline) + Text("on \(trendingDateString)") + .font(.subheadline) + .foregroundColor(.gray) + } + .padding(.horizontal, 8) + + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 8) { + if trendingItems.isEmpty { + ForEach(0..<5, id: \.self) { _ in + HomeSkeletonCell() + } + } else { + ForEach(trendingItems, id: \.id) { item in + NavigationLink(destination: AniListDetailsView(animeID: item.id)) { + VStack { + KFImage(URL(string: item.coverImage.large)) + .placeholder { + RoundedRectangle(cornerRadius: 10) + .fill(Color.gray.opacity(0.3)) + .frame(width: 130, height: 195) + .shimmering() + } + .setProcessor(RoundCornerImageProcessor(cornerRadius: 10)) + .resizable() + .scaledToFill() + .frame(width: 130, height: 195) + .cornerRadius(10) + .clipped() + + Text(item.title.romaji) + .font(.caption) + .frame(width: 130) + .lineLimit(1) + .multilineTextAlignment(.center) + .foregroundColor(.primary) + } } } } } + .padding(.horizontal, 8) } - .padding(.horizontal, 8) } - - HStack(alignment: .bottom, spacing: 5) { - Text("Trending") - .font(.headline) - Text("on \(trendingDateString)") - .font(.subheadline) - .foregroundColor(.gray) - } - .padding(.horizontal, 8) - - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 8) { - if trendingItems.isEmpty { - ForEach(0..<5, id: \.self) { _ in - HomeSkeletonCell() - } - } else { - ForEach(trendingItems, id: \.id) { item in - NavigationLink(destination: AniListDetailsView(animeID: item.id)) { - VStack { - KFImage(URL(string: item.coverImage.large)) - .placeholder { - RoundedRectangle(cornerRadius: 10) - .fill(Color.gray.opacity(0.3)) - .frame(width: 130, height: 195) - .shimmering() - } - .setProcessor(RoundCornerImageProcessor(cornerRadius: 10)) - .resizable() - .scaledToFill() - .frame(width: 130, height: 195) - .cornerRadius(10) - .clipped() - - Text(item.title.romaji) - .font(.caption) - .frame(width: 130) - .lineLimit(1) - .multilineTextAlignment(.center) - .foregroundColor(.primary) - } - } - } - } - } - .padding(.horizontal, 8) + .padding(.bottom, 16) + } + .navigationTitle("Home") + } + .onAppear { + continueWatchingItems = ContinueWatchingManager.shared.fetchItems() + AnilistServiceSeasonalAnime().fetchSeasonalAnime { items in + if let items = items { + aniListItems = items } } - .padding(.bottom, 16) - } - .navigationTitle("Home") - } - .onAppear { - continueWatchingItems = ContinueWatchingManager.shared.fetchItems() - AnilistServiceSeasonalAnime().fetchSeasonalAnime { items in - if let items = items { - aniListItems = items - } - } - AnilistServiceTrendingAnime().fetchTrendingAnime { items in - if let items = items { - trendingItems = items + AnilistServiceTrendingAnime().fetchTrendingAnime { items in + if let items = items { + trendingItems = items + } } } } diff --git a/Sora/Views/MediaInfoView/MediaInfoView.swift b/Sora/Views/MediaInfoView/MediaInfoView.swift index 646847e..24ac21a 100644 --- a/Sora/Views/MediaInfoView/MediaInfoView.swift +++ b/Sora/Views/MediaInfoView/MediaInfoView.swift @@ -519,7 +519,7 @@ struct MediaInfoView: View { if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let rootVC = windowScene.windows.first?.rootViewController { - rootVC.present(customMediaPlayer, animated: true, completion: nil) + findTopViewController.findViewController(rootVC).present(customMediaPlayer, animated: true, completion: nil) } return default: @@ -541,7 +541,7 @@ struct MediaInfoView: View { if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let rootVC = windowScene.windows.first?.rootViewController { - rootVC.present(videoPlayerViewController, animated: true, completion: nil) + findTopViewController.findViewController(rootVC).present(videoPlayerViewController, animated: true, completion: nil) } } } diff --git a/Sulfur.xcodeproj/project.pbxproj b/Sulfur.xcodeproj/project.pbxproj index d1a9dc8..8cb30fb 100644 --- a/Sulfur.xcodeproj/project.pbxproj +++ b/Sulfur.xcodeproj/project.pbxproj @@ -31,6 +31,8 @@ 133D7C942D2BE2640075467E /* JSController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C8B2D2BE2640075467E /* JSController.swift */; }; 133D7C972D2BE2AF0075467E /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 133D7C962D2BE2AF0075467E /* Kingfisher */; }; 133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133F55BA2D33B55100E08EEA /* LibraryManager.swift */; }; + 1359ED142D76F49900C13034 /* finTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1359ED132D76F49900C13034 /* finTopView.swift */; }; + 1359ED1A2D76FA7D00C13034 /* Drops in Frameworks */ = {isa = PBXBuildFile; productRef = 1359ED192D76FA7D00C13034 /* Drops */; }; 135CCBE22D4D1138008B9C0E /* SettingsViewPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135CCBE12D4D1138008B9C0E /* SettingsViewPlayer.swift */; }; 136F21B92D5B8DD8006409AC /* AniList-MediaInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 136F21B82D5B8DD8006409AC /* AniList-MediaInfo.swift */; }; 136F21BC2D5B8F29006409AC /* AniList-DetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 136F21BB2D5B8F29006409AC /* AniList-DetailsView.swift */; }; @@ -44,7 +46,6 @@ 13C0E5EC2D5F85F800E7F619 /* ContinueWatchingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C0E5EB2D5F85F800E7F619 /* ContinueWatchingItem.swift */; }; 13CBA0882D60F19C00EFE70A /* VTTSubtitlesLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CBA0872D60F19C00EFE70A /* VTTSubtitlesLoader.swift */; }; 13CBEFDA2D5F7D1200D011EE /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CBEFD92D5F7D1200D011EE /* String.swift */; }; - 13D842522D4523B800EBBFA6 /* Drops in Frameworks */ = {isa = PBXBuildFile; productRef = 13D842512D4523B800EBBFA6 /* Drops */; }; 13D842552D45267500EBBFA6 /* DropManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13D842542D45267500EBBFA6 /* DropManager.swift */; }; 13D99CF72D4E73C300250A86 /* ModuleAdditionSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13D99CF62D4E73C300250A86 /* ModuleAdditionSettingsView.swift */; }; 13DC0C462D302C7500D0F966 /* VideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DC0C452D302C7500D0F966 /* VideoPlayer.swift */; }; @@ -81,6 +82,7 @@ 133D7C892D2BE2640075467E /* Modules.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Modules.swift; sourceTree = ""; }; 133D7C8B2D2BE2640075467E /* JSController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSController.swift; sourceTree = ""; }; 133F55BA2D33B55100E08EEA /* LibraryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryManager.swift; sourceTree = ""; }; + 1359ED132D76F49900C13034 /* finTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = finTopView.swift; sourceTree = ""; }; 135CCBE12D4D1138008B9C0E /* SettingsViewPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewPlayer.swift; sourceTree = ""; }; 136F21B82D5B8DD8006409AC /* AniList-MediaInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AniList-MediaInfo.swift"; sourceTree = ""; }; 136F21BB2D5B8F29006409AC /* AniList-DetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AniList-DetailsView.swift"; sourceTree = ""; }; @@ -110,7 +112,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 13D842522D4523B800EBBFA6 /* Drops in Frameworks */, + 1359ED1A2D76FA7D00C13034 /* Drops in Frameworks */, 133D7C972D2BE2AF0075467E /* Kingfisher in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -266,6 +268,7 @@ children = ( 1327FBA82D758DEA00FC6689 /* UIDevice+Model.swift */, 133D7C872D2BE2640075467E /* URLSession.swift */, + 1359ED132D76F49900C13034 /* finTopView.swift */, 13CBEFD92D5F7D1200D011EE /* String.swift */, 13103E8A2D58E028000F0673 /* View.swift */, ); @@ -405,7 +408,7 @@ name = Sulfur; packageProductDependencies = ( 133D7C962D2BE2AF0075467E /* Kingfisher */, - 13D842512D4523B800EBBFA6 /* Drops */, + 1359ED192D76FA7D00C13034 /* Drops */, ); productName = Sora; productReference = 133D7C6A2D2BE2500075467E /* Sulfur.app */; @@ -436,7 +439,7 @@ mainGroup = 133D7C612D2BE2500075467E; packageReferences = ( 133D7C952D2BE2AF0075467E /* XCRemoteSwiftPackageReference "Kingfisher" */, - 13D842502D4523B800EBBFA6 /* XCRemoteSwiftPackageReference "Drops" */, + 1359ED182D76FA7D00C13034 /* XCRemoteSwiftPackageReference "Drops" */, ); productRefGroup = 133D7C6B2D2BE2500075467E /* Products */; projectDirPath = ""; @@ -467,6 +470,7 @@ 135CCBE22D4D1138008B9C0E /* SettingsViewPlayer.swift in Sources */, 1327FBA72D758CEA00FC6689 /* Analytics.swift in Sources */, 13DC0C462D302C7500D0F966 /* VideoPlayer.swift in Sources */, + 1359ED142D76F49900C13034 /* finTopView.swift in Sources */, 1399FAD62D3AB3DB00E97C31 /* Logger.swift in Sources */, 13B7F4C12D58FFDD0045714A /* Shimmer.swift in Sources */, 139935662D468C450065CEFF /* ModuleManager.swift in Sources */, @@ -646,6 +650,7 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Sora/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Sora; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -686,6 +691,7 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Sora/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Sora; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -742,12 +748,12 @@ version = 7.9.1; }; }; - 13D842502D4523B800EBBFA6 /* XCRemoteSwiftPackageReference "Drops" */ = { + 1359ED182D76FA7D00C13034 /* XCRemoteSwiftPackageReference "Drops" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/omaralbeik/Drops.git"; requirement = { - kind = upToNextMajorVersion; - minimumVersion = 1.0.0; + branch = main; + kind = branch; }; }; /* End XCRemoteSwiftPackageReference section */ @@ -758,9 +764,9 @@ package = 133D7C952D2BE2AF0075467E /* XCRemoteSwiftPackageReference "Kingfisher" */; productName = Kingfisher; }; - 13D842512D4523B800EBBFA6 /* Drops */ = { + 1359ED192D76FA7D00C13034 /* Drops */ = { isa = XCSwiftPackageProductDependency; - package = 13D842502D4523B800EBBFA6 /* XCRemoteSwiftPackageReference "Drops" */; + package = 1359ED182D76FA7D00C13034 /* XCRemoteSwiftPackageReference "Drops" */; productName = Drops; }; /* End XCSwiftPackageProductDependency section */ diff --git a/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7c62e6b..48e92a9 100644 --- a/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Sulfur.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -5,9 +5,9 @@ "package": "Drops", "repositoryURL": "https://github.com/omaralbeik/Drops.git", "state": { - "branch": null, - "revision": "a183ee6f79f21c940092a19c2cba756555422371", - "version": "1.7.0" + "branch": "main", + "revision": "5824681795286c36bdc4a493081a63e64e2a064e", + "version": null } }, {