im even dumber 😭
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-11 21:23:30 +02:00
parent 05c9722142
commit 117639514e
5 changed files with 38 additions and 77 deletions

View file

@ -32,7 +32,7 @@ struct SoraApp: App {
var body: some Scene {
WindowGroup {
Group {
if !UserDefaults.standard.bool(forKey: "hideSplashScreenEnable") {
if !UserDefaults.standard.bool(forKey: "hideSplashScreen") {
SplashScreenView()
} else {
ContentView()
@ -102,26 +102,4 @@ struct SoraApp: App {
break
}
}
}
@objc class AppInfo: NSObject {
@objc static let shared = AppInfo()
@objc func getBundleIdentifier() -> String {
return Bundle.main.bundleIdentifier ?? "me.cranci.sulfur"
}
@objc func getDisplayName() -> String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
}
@objc func isValidApp() -> Bool {
let bundleId = getBundleIdentifier().lowercased()
let displayName = getDisplayName().lowercased()
let hasValidBundleId = bundleId.contains("sulfur")
let hasValidDisplayName = displayName == "sora" || displayName == "sulfur"
return hasValidBundleId && hasValidDisplayName
}
}
}

View file

@ -10,9 +10,6 @@ import JavaScriptCore
extension JSContext {
func setupConsoleLogging() {
let consoleObject = JSValue(newObjectIn: self)
let appInfoBridge = AppInfo.shared
self.setObject(appInfoBridge, forKeyedSubscript: "AppInfo" as NSString)
let consoleLogFunction: @convention(block) (String) -> Void = { message in
Logger.shared.log(message, type: "Debug")
@ -275,10 +272,33 @@ extension JSContext {
self.setObject(atobFunction, forKeyedSubscript: "atob" as NSString)
}
func setupAppInfo() {
let bundle = Bundle.main
let appInfo = JSValue(newObjectIn: self)
appInfo?.setValue(bundle.bundleIdentifier ?? "", forProperty: "bundleId")
appInfo?.setValue(
bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
?? bundle.object(forInfoDictionaryKey: "CFBundleName") as? String
?? "",
forProperty: "displayName"
)
let isValidApp: @convention(block) () -> Bool = {
guard let app = appInfo else { return false }
return !(app.forProperty("bundleId").toString().isEmpty ||
app.forProperty("displayName").toString().isEmpty)
}
appInfo?.setObject(isValidApp, forKeyedSubscript: "isValidApp" as NSString)
self.setObject(appInfo, forKeyedSubscript: "AppInfo" as NSString)
}
func setupJavaScriptEnvironment() {
setupConsoleLogging()
setupNativeFetch()
setupFetchV2()
setupBase64Functions()
setupAppInfo()
}
}

View file

@ -9,10 +9,7 @@ import NukeUI
import SwiftUI
import AVFoundation
struct EpisodeCell: View {
let episodeIndex: Int
let episode: String
let episodeID: Int
@ -26,16 +23,13 @@ struct EpisodeCell: View {
let tmdbID: Int?
let seasonNumber: Int?
let isMultiSelectMode: Bool
let isSelected: Bool
let onSelectionChanged: ((Bool) -> Void)?
let onTap: (String) -> Void
let onMarkAllPrevious: () -> Void
@State private var episodeTitle = ""
@State private var episodeImageUrl = ""
@State private var isLoading = true
@ -45,23 +39,19 @@ struct EpisodeCell: View {
@State private var downloadAnimationScale: CGFloat = 1.0
@State private var activeDownloadTask: AVAssetDownloadTask?
@State private var swipeOffset: CGFloat = 0
@State private var isShowingActions = false
@State private var actionButtonWidth: CGFloat = 60
@State private var retryAttempts = 0
private let maxRetryAttempts = 3
private let initialBackoffDelay: TimeInterval = 1.0
@ObservedObject private var jsController = JSController.shared
@EnvironmentObject var moduleManager: ModuleManager
@Environment(\.colorScheme) private var colorScheme
@AppStorage("selectedAppearance") private var selectedAppearance: Appearance = .system
init(
episodeIndex: Int,
episode: String,
@ -98,7 +88,7 @@ struct EpisodeCell: View {
self.tmdbID = tmdbID
self.seasonNumber = seasonNumber
let isLightMode = (UserDefaults.standard.string(forKey: "selectedAppearance") == "light") ||
((UserDefaults.standard.string(forKey: "selectedAppearance") == "system") &&
UITraitCollection.current.userInterfaceStyle == .light)
@ -110,13 +100,10 @@ struct EpisodeCell: View {
(isLightMode ? defaultLightBanner : defaultDarkBanner) : defaultBannerImage
}
var body: some View {
ZStack {
actionButtonsBackground
episodeCellContent
.offset(x: swipeOffset)
.animation(.spring(response: 0.3, dampingFraction: 0.8), value: swipeOffset)
@ -146,7 +133,6 @@ struct EpisodeCell: View {
}
}
private extension EpisodeCell {
var actionButtonsBackground: some View {
@ -365,7 +351,7 @@ private extension EpisodeCell {
}
func calculateMaxSwipeDistance() -> CGFloat {
var buttonCount = 1
var buttonCount = 1
if progress <= 0.9 { buttonCount += 1 }
if progress != 0 { buttonCount += 1 }
@ -796,7 +782,7 @@ private extension EpisodeCell {
self.retryAttempts = 0
if UserDefaults.standard.object(forKey: "fetchEpisodeMetadata") == nil ||
UserDefaults.standard.bool(forKey: "fetchEpisodeMetadata") {
UserDefaults.standard.bool(forKey: "fetchEpisodeMetadata") {
self.episodeTitle = title["en"] ?? title.values.first ?? ""
if !image.isEmpty {
@ -825,9 +811,9 @@ private extension EpisodeCell {
let stillPath = json["still_path"] as? String
let imageUrl = stillPath.map { path in
tmdbImageWidth == "original"
? "https://image.tmdb.org/t/p/original\(path)"
: "https://image.tmdb.org/t/p/w\(tmdbImageWidth)\(path)"
tmdbImageWidth == "original"
? "https://image.tmdb.org/t/p/original\(path)"
: "https://image.tmdb.org/t/p/w\(tmdbImageWidth)\(path)"
} ?? ""
DispatchQueue.main.async {

View file

@ -9,7 +9,6 @@ import NukeUI
import SwiftUI
import SafariServices
private let tmdbFetcher = TMDBFetcher()
struct MediaItem: Identifiable {
@ -19,9 +18,6 @@ struct MediaItem: Identifiable {
let airdate: String
}
struct MediaInfoView: View {
let title: String
@State var imageUrl: String
@ -183,8 +179,6 @@ struct MediaInfoView: View {
}
}
// MARK: - View Builders
@ViewBuilder
private var navigationOverlay: some View {
VStack {
@ -444,8 +438,6 @@ struct MediaInfoView: View {
}
}
// MARK: - Computed Properties for Single Episode
private var isBookmarked: Bool {
libraryManager.isBookmarked(href: href, moduleName: module.metadata.sourceName)
}
@ -470,8 +462,6 @@ struct MediaInfoView: View {
return "Mark watched"
}
// MARK: - Episodes Section
@ViewBuilder
private var episodesSection: some View {
if episodeLinks.count != 1 {
@ -638,8 +628,6 @@ struct MediaInfoView: View {
.padding(.vertical, 50)
}
// MARK: - Menu and Action Buttons
@ViewBuilder
private var sourceButton: some View {
Button(action: { openSafariViewController(with: href) }) {
@ -737,8 +725,6 @@ struct MediaInfoView: View {
}
}
// MARK: - Setup and Lifecycle Methods
private func setupViewOnAppear() {
buttonRefreshTrigger.toggle()
tabBarController.hideTabBar()
@ -790,8 +776,6 @@ struct MediaInfoView: View {
showLoadingAlert = false
}
// MARK: - Action Methods
private func copyTitleToClipboard() {
UIPasteboard.general.string = title
DropManager.shared.showDrop(
@ -895,8 +879,6 @@ struct MediaInfoView: View {
}
}
// MARK: - Menu Action Methods
private func handleAniListMatch(selectedID: Int) {
self.customAniListID = selectedID
self.itemID = selectedID
@ -951,8 +933,6 @@ struct MediaInfoView: View {
)
}
// MARK: - Utility Methods
private func getBannerImageBasedOnAppearance() -> String {
let isLightMode = selectedAppearance == .light || (selectedAppearance == .system && colorScheme == .light)
return isLightMode
@ -967,7 +947,7 @@ struct MediaInfoView: View {
} else {
selectedRange = generateRanges().first ?? 0..<episodeChunkSize
}
if let savedSeason = UserDefaults.standard.object(forKey: selectedSeasonKey) as? Int {
let maxIndex = max(0, groupedEpisodes().count - 1)
selectedSeason = min(savedSeason, maxIndex)
@ -1017,8 +997,6 @@ struct MediaInfoView: View {
return cleaned.isEmpty ? "Unknown" : cleaned
}
// MARK: - Playback Methods
private func playFirstUnwatchedEpisode() {
let indices = finishedAndUnfinishedIndices()
let finished = indices.finished
@ -1069,9 +1047,9 @@ struct MediaInfoView: View {
private func selectNextEpisode() {
guard let currentIndex = episodeLinks.firstIndex(where: { $0.number == selectedEpisodeNumber }),
currentIndex + 1 < episodeLinks.count else {
Logger.shared.log("No more episodes to play", type: "Info")
return
}
Logger.shared.log("No more episodes to play", type: "Info")
return
}
let nextEpisode = episodeLinks[currentIndex + 1]
selectedEpisodeNumber = nextEpisode.number
@ -1084,8 +1062,6 @@ struct MediaInfoView: View {
)
}
// MARK: - Episode Progress Management
private func markAllPreviousEpisodesAsWatched(ep: EpisodeLink, inSeason: Bool) {
let userDefaults = UserDefaults.standard
var updates = [String: Double]()

View file

@ -153,7 +153,7 @@ struct SettingsViewGeneral: View {
@AppStorage("refreshModulesOnLaunch") private var refreshModulesOnLaunch: Bool = true
@AppStorage("fetchEpisodeMetadata") private var fetchEpisodeMetadata: Bool = true
@AppStorage("analyticsEnabled") private var analyticsEnabled: Bool = false
@AppStorage("hideSplashScreenEnable") private var hideSplashScreenEnable: Bool = false
@AppStorage("hideSplashScreen") private var hideSplashScreenEnable: Bool = false
@AppStorage("metadataProviders") private var metadataProviders: String = "TMDB"
@AppStorage("tmdbImageWidth") private var TMDBimageWidht: String = "original"
@AppStorage("mediaColumnsPortrait") private var mediaColumnsPortrait: Int = 2
@ -185,7 +185,8 @@ struct SettingsViewGeneral: View {
SettingsToggleRow(
icon: "wand.and.rays.inverse",
title: "Hide Splash Screen",
isOn: $hideSplashScreenEnable
isOn: $hideSplashScreenEnable,
showDivider: false
)
}