From 02f8f165a15ce71de48bfe4a85e6d34f166bcc9d Mon Sep 17 00:00:00 2001 From: Seiike <122684677+Seeike@users.noreply.github.com> Date: Thu, 12 Jun 2025 20:06:00 +0200 Subject: [PATCH] i fucking hate merges --- Sora/Localizable.xcstrings | 17 +- .../Tracking Services/TMDB/TMDB-FetchID.swift | 2 +- Sora/Views/MediaInfoView/MediaInfoView.swift | 142 +++++++++----- .../MediaInfoView/TMDBMatchPopupView.swift | 176 ++++++++++++++++++ .../SettingsViewGeneral.swift | 130 ++++++------- Sulfur.xcodeproj/project.pbxproj | 12 +- 6 files changed, 352 insertions(+), 127 deletions(-) create mode 100644 Sora/Views/MediaInfoView/TMDBMatchPopupView.swift diff --git a/Sora/Localizable.xcstrings b/Sora/Localizable.xcstrings index bc0c7de..6beeef3 100644 --- a/Sora/Localizable.xcstrings +++ b/Sora/Localizable.xcstrings @@ -195,6 +195,9 @@ }, "Error" : { + }, + "Error Fetching Results" : { + }, "Failed to load contributors" : { @@ -265,7 +268,10 @@ "Match with AniList" : { }, - "Matched with: %@" : { + "Match with TMDB" : { + + }, + "Matched ID: %lld" : { }, "Max Concurrent Downloads" : { @@ -330,6 +336,9 @@ }, "Please select a module from settings" : { + }, + "Provider: %@" : { + }, "Queued" : { @@ -417,6 +426,9 @@ }, "The module provided only a single episode, this is most likely a movie, so we decided to make separate screens for these cases." : { + }, + "TMDB Match" : { + }, "Trackers" : { @@ -426,6 +438,9 @@ }, "Try different keywords" : { + }, + "Unable to fetch matches. Please try again later." : { + }, "Use TMDB Poster Image" : { diff --git a/Sora/Tracking Services/TMDB/TMDB-FetchID.swift b/Sora/Tracking Services/TMDB/TMDB-FetchID.swift index 818bc96..0112a6d 100644 --- a/Sora/Tracking Services/TMDB/TMDB-FetchID.swift +++ b/Sora/Tracking Services/TMDB/TMDB-FetchID.swift @@ -23,7 +23,7 @@ class TMDBFetcher { let results: [TMDBResult] } - private let apiKey = "738b4edd0a156cc126dc4a4b8aea4aca" + let apiKey = "738b4edd0a156cc126dc4a4b8aea4aca" private let session = URLSession.custom func fetchBestMatchID(for title: String, completion: @escaping (Int?, MediaType?) -> Void) { diff --git a/Sora/Views/MediaInfoView/MediaInfoView.swift b/Sora/Views/MediaInfoView/MediaInfoView.swift index 58073b1..e31e0b3 100644 --- a/Sora/Views/MediaInfoView/MediaInfoView.swift +++ b/Sora/Views/MediaInfoView/MediaInfoView.swift @@ -65,6 +65,8 @@ struct MediaInfoView: View { @State private var showStreamLoadingView: Bool = false @State private var currentStreamTitle: String = "" @State private var activeFetchID: UUID? = nil + @State private var activeProvider: String? + @State private var isTMDBMatchingPresented = false @State private var refreshTrigger: Bool = false @State private var buttonRefreshTrigger: Bool = false @@ -85,6 +87,15 @@ struct MediaInfoView: View { @Environment(\.colorScheme) private var colorScheme @Environment(\.verticalSizeClass) private var verticalSizeClass + @AppStorage("metadataProvidersOrder") private var metadataProvidersOrderData: Data = { + try! JSONEncoder().encode(["AniList","TMDB"]) + }() + + private var metadataProvidersOrder: [String] { + get { (try? JSONDecoder().decode([String].self, from: metadataProvidersOrderData)) ?? ["AniList","TMDB"] } + set { metadataProvidersOrderData = try! JSONEncoder().encode(newValue) } + } + private var isGroupedBySeasons: Bool { return groupedEpisodes().count > 1 } @@ -647,6 +658,13 @@ struct MediaInfoView: View { .sheet(isPresented: $isMatchingPresented) { AnilistMatchPopupView(seriesTitle: title) { selectedID in handleAniListMatch(selectedID: selectedID) + fetchMetadataIDIfNeeded() // ← use your new async re-try loop + } + } + .sheet(isPresented: $isTMDBMatchingPresented) { + TMDBMatchPopupView(seriesTitle: title) { id, type in + tmdbID = id; tmdbType = type + fetchMetadataIDIfNeeded() } } } @@ -654,34 +672,40 @@ struct MediaInfoView: View { @ViewBuilder private var menuContent: some View { Group { - if let id = itemID ?? customAniListID { - let labelText = (matchedTitle?.isEmpty == false ? matchedTitle! : "\(id)") - Text("Matched with: \(labelText)") + // Show which provider “won” + if let active = activeProvider { + Text("Provider: \(active)") .font(.caption) .foregroundColor(.gray) .padding(.vertical, 4) + Divider() } - Divider() - - if let _ = customAniListID { + // AniList branch: match, show ID, reset & open + if activeProvider == "AniList" { + Button("Match with AniList") { + isMatchingPresented = true + } + Text("Matched ID: \(itemID ?? 0)") + .font(.caption2) + .foregroundColor(.secondary) + Button(action: { resetAniListID() }) { Label("Reset AniList ID", systemImage: "arrow.clockwise") } - } - - if let id = itemID ?? customAniListID { - Button(action: { openAniListPage(id: id) }) { + + Button(action: { openAniListPage(id: itemID ?? 0) }) { Label("Open in AniList", systemImage: "link") } } - - if UserDefaults.standard.string(forKey: "metadataProviders") ?? "TMDB" == "AniList" { - Button(action: { isMatchingPresented = true }) { - Label("Match with AniList", systemImage: "magnifyingglass") + // TMDB branch: only match + else if activeProvider == "TMDB" { + Button("Match with TMDB") { + isTMDBMatchingPresented = true } } + // Keep all of your existing poster & debug options posterMenuOptions Divider() @@ -691,6 +715,7 @@ struct MediaInfoView: View { } } } + @ViewBuilder private var posterMenuOptions: some View { @@ -1163,45 +1188,60 @@ struct MediaInfoView: View { } private func fetchMetadataIDIfNeeded() { - let provider = UserDefaults.standard.string(forKey: "metadataProviders") ?? "TMDB" - let cleaned = cleanTitle(title) - - if provider == "TMDB" { - tmdbID = nil - tmdbFetcher.fetchBestMatchID(for: cleaned) { id, type in - DispatchQueue.main.async { - self.tmdbID = id - self.tmdbType = type - Logger.shared.log("Fetched TMDB ID: \(id ?? -1) (\(type?.rawValue ?? "unknown")) for title: \(cleaned)", type: "Debug") - } - } - - itemID = nil - fetchItemID(byTitle: cleaned) { result in - switch result { - case .success(let id): - DispatchQueue.main.async { - self.itemID = id - Logger.shared.log("Fetched AniList ID: \(id) for title: \(cleaned)", type: "Debug") - } - case .failure(let error): - Logger.shared.log("Failed to fetch AniList ID: \(error)", type: "Error") - } - } - } else if provider == "Anilist" { - itemID = nil - fetchItemID(byTitle: cleaned) { result in - switch result { - case .success(let id): - DispatchQueue.main.async { - self.itemID = id - Logger.shared.log("Fetched AniList ID: \(id) for title: \(cleaned)", type: "Debug") - } - case .failure(let error): - Logger.shared.log("Failed to fetch AniList ID: \(error)", type: "Error") - } + let order = metadataProvidersOrder + let cleanedTitle = cleanTitle(title) + + itemID = nil + tmdbID = nil + activeProvider = nil + isError = false + + fetchItemID(byTitle: cleanedTitle) { result in + switch result { + case .success(let id): + DispatchQueue.main.async { self.itemID = id } + case .failure(let error): + Logger.shared.log("Failed to fetch AniList ID for tracking: \(error)", type: "Error") } } + + func tryNext(_ index: Int) { + guard index < order.count else { + isError = true + return + } + let provider = order[index] + if provider == "TMDB" { + tmdbFetcher.fetchBestMatchID(for: cleanedTitle) { id, type in + DispatchQueue.main.async { + if let id = id, let type = type { + self.tmdbID = id + self.tmdbType = type + self.activeProvider = "TMDB" + UserDefaults.standard.set("TMDB", forKey: "metadataProviders") + } else { + tryNext(index + 1) + } + } + } + } else if provider == "AniList" { + fetchItemID(byTitle: cleanedTitle) { result in + switch result { + case .success: + DispatchQueue.main.async { + self.activeProvider = "AniList" + UserDefaults.standard.set("AniList", forKey: "metadataProviders") + } + case .failure: + tryNext(index + 1) + } + } + } else { + tryNext(index + 1) + } + } + + tryNext(0) } private func fetchItemID(byTitle title: String, completion: @escaping (Result) -> Void) { diff --git a/Sora/Views/MediaInfoView/TMDBMatchPopupView.swift b/Sora/Views/MediaInfoView/TMDBMatchPopupView.swift new file mode 100644 index 0000000..3293a2a --- /dev/null +++ b/Sora/Views/MediaInfoView/TMDBMatchPopupView.swift @@ -0,0 +1,176 @@ +// +// TMDBMatchPopupView.swift +// Sulfur +// +// Created by seiike on 12/06/2025. +// + +import SwiftUI +import NukeUI + +struct TMDBMatchPopupView: View { + let seriesTitle: String + let onSelect: (Int, TMDBFetcher.MediaType) -> Void + + @State private var results: [ResultItem] = [] + @State private var isLoading = true + @State private var showingError = false + + @Environment(\.dismiss) private var dismiss + + struct ResultItem: Identifiable { + let id: Int + let title: String + let mediaType: TMDBFetcher.MediaType + let posterURL: String? + } + + private struct TMDBSearchResult: Decodable { + let id: Int + let name: String? + let title: String? + let poster_path: String? + let popularity: Double + } + + private struct TMDBSearchResponse: Decodable { + let results: [TMDBSearchResult] + } + + var body: some View { + NavigationView { + ScrollView { + VStack(spacing: 0) { + if isLoading { + ProgressView() + .frame(maxWidth: .infinity) + .padding() + } else if results.isEmpty { + Text("No matches found") + .font(.subheadline) + .foregroundStyle(.gray) + .frame(maxWidth: .infinity) + .padding() + } else { + LazyVStack(spacing: 15) { + ForEach(results) { item in + Button(action: { + onSelect(item.id, item.mediaType) + dismiss() + }) { + HStack(spacing: 12) { + if let poster = item.posterURL, let url = URL(string: poster) { + LazyImage(url: url) { state in + if let image = state.imageContainer?.image { + Image(uiImage: image) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 50, height: 75) + .cornerRadius(6) + } else { + Rectangle() + .fill(.tertiary) + .frame(width: 50, height: 75) + .cornerRadius(6) + } + } + } + + VStack(alignment: .leading, spacing: 2) { + Text(item.title) + .font(.body) + .foregroundStyle(.primary) + Text(item.mediaType.rawValue.capitalized) + .font(.caption) + .foregroundStyle(.secondary) + } + Spacer() + } + .padding(11) + .frame(maxWidth: .infinity) + .background( + RoundedRectangle(cornerRadius: 15) + .fill(.ultraThinMaterial) + ) + .overlay( + RoundedRectangle(cornerRadius: 15) + .stroke( + Color.accentColor.opacity(0.2), + lineWidth: 0.5 + ) + ) + } + .buttonStyle(.plain) + } + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + } + } + } + .navigationTitle("TMDB Match") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button("Cancel") { + dismiss() + } + } + } + .alert("Error Fetching Results", isPresented: $showingError) { + Button("OK", role: .cancel) { } + } message: { + Text("Unable to fetch matches. Please try again later.") + } + } + .onAppear(perform: fetchMatches) + } + + private func fetchMatches() { + isLoading = true + results = [] + + let fetcher = TMDBFetcher() + let apiKey = fetcher.apiKey + let dispatchGroup = DispatchGroup() + var temp: [ResultItem] = [] + var encounteredError = false + + for type in TMDBFetcher.MediaType.allCases { + dispatchGroup.enter() + let query = seriesTitle.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" + let urlString = "https://api.themoviedb.org/3/search/\(type.rawValue)?api_key=\(apiKey)&query=\(query)" + guard let url = URL(string: urlString) else { + encounteredError = true + dispatchGroup.leave() + continue + } + + URLSession.shared.dataTask(with: url) { data, _, error in + defer { dispatchGroup.leave() } + + guard error == nil, let data = data, + let response = try? JSONDecoder().decode(TMDBSearchResponse.self, from: data) else { + encounteredError = true + return + } + + let items = response.results.prefix(6).map { res -> ResultItem in + let title = (type == .tv ? res.name : res.title) ?? "Unknown" + let poster = res.poster_path.map { "https://image.tmdb.org/t/p/w500\($0)" } + return ResultItem(id: res.id, title: title, mediaType: type, posterURL: poster) + } + temp.append(contentsOf: items) + }.resume() + } + + dispatchGroup.notify(queue: .main) { + if encounteredError { + showingError = true + } + // Keep API order (by popularity), limit to top 6 overall + results = Array(temp.prefix(6)) + isLoading = false + } + } +} diff --git a/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift index 1774a67..e7b6b61 100644 --- a/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift +++ b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift @@ -154,12 +154,17 @@ struct SettingsViewGeneral: View { @AppStorage("fetchEpisodeMetadata") private var fetchEpisodeMetadata: Bool = true @AppStorage("analyticsEnabled") private var analyticsEnabled: Bool = false @AppStorage("hideSplashScreen") private var hideSplashScreenEnable: Bool = false - @AppStorage("metadataProviders") private var metadataProviders: String = "TMDB" + @AppStorage("metadataProvidersOrder") private var metadataProvidersOrderData: Data = { + try! JSONEncoder().encode(["TMDB","AniList"]) + }() @AppStorage("tmdbImageWidth") private var TMDBimageWidht: String = "original" @AppStorage("mediaColumnsPortrait") private var mediaColumnsPortrait: Int = 2 @AppStorage("mediaColumnsLandscape") private var mediaColumnsLandscape: Int = 4 - private let metadataProvidersList = ["AniList", "TMDB"] + private var metadataProvidersOrder: [String] { + get { (try? JSONDecoder().decode([String].self, from: metadataProvidersOrderData)) ?? ["AniList","TMDB"] } + set { metadataProvidersOrderData = try! JSONEncoder().encode(newValue) } + } private let TMDBimageWidhtList = ["300", "500", "780", "1280", "original"] private let sortOrderOptions = ["Ascending", "Descending"] @EnvironmentObject var settings: Settings @@ -208,85 +213,70 @@ struct SettingsViewGeneral: View { isOn: $fetchEpisodeMetadata ) - if metadataProviders == "TMDB" { + List { + ForEach(metadataProvidersOrder, id: \.self) { prov in + Text(prov) + .padding(.vertical, 8) + } + .onMove { idx, dest in + var arr = metadataProvidersOrder + arr.move(fromOffsets: idx, toOffset: dest) + metadataProvidersOrderData = try! JSONEncoder().encode(arr) + } + } + .environment(\.editMode, .constant(.active)) + .frame(height: 140) + + SettingsSection( + title: "Media Grid Layout", + footer: "Adjust the number of media items per row in portrait and landscape modes." + ) { SettingsPickerRow( - icon: "server.rack", - title: "Metadata Provider", - options: metadataProvidersList, - optionToString: { $0 }, - selection: $metadataProviders, - showDivider: true + icon: "rectangle.portrait", + title: "Portrait Columns", + options: UIDevice.current.userInterfaceIdiom == .pad ? Array(1...5) : Array(1...4), + optionToString: { "\($0)" }, + selection: $mediaColumnsPortrait ) SettingsPickerRow( - icon: "square.stack.3d.down.right", - title: "Thumbnails Width", - options: TMDBimageWidhtList, - optionToString: { $0 }, - selection: $TMDBimageWidht, + icon: "rectangle", + title: "Landscape Columns", + options: UIDevice.current.userInterfaceIdiom == .pad ? Array(2...8) : Array(2...5), + optionToString: { "\($0)" }, + selection: $mediaColumnsLandscape, showDivider: false ) - } else { - SettingsPickerRow( - icon: "server.rack", - title: "Metadata Provider", - options: metadataProvidersList, - optionToString: { $0 }, - selection: $metadataProviders, + } + + SettingsSection( + title: "Modules", + footer: "Note that the modules will be replaced only if there is a different version string inside the JSON file." + ) { + SettingsToggleRow( + icon: "arrow.clockwise", + title: "Refresh Modules on Launch", + isOn: $refreshModulesOnLaunch, + showDivider: false + ) + } + + SettingsSection( + title: "Advanced", + footer: "Anonymous data is collected to improve the app. No personal information is collected. This can be disabled at any time." + ) { + SettingsToggleRow( + icon: "chart.bar", + title: "Enable Analytics", + isOn: $analyticsEnabled, showDivider: false ) } } - - SettingsSection( - title: "Media Grid Layout", - footer: "Adjust the number of media items per row in portrait and landscape modes." - ) { - SettingsPickerRow( - icon: "rectangle.portrait", - title: "Portrait Columns", - options: UIDevice.current.userInterfaceIdiom == .pad ? Array(1...5) : Array(1...4), - optionToString: { "\($0)" }, - selection: $mediaColumnsPortrait - ) - - SettingsPickerRow( - icon: "rectangle", - title: "Landscape Columns", - options: UIDevice.current.userInterfaceIdiom == .pad ? Array(2...8) : Array(2...5), - optionToString: { "\($0)" }, - selection: $mediaColumnsLandscape, - showDivider: false - ) - } - - SettingsSection( - title: "Modules", - footer: "Note that the modules will be replaced only if there is a different version string inside the JSON file." - ) { - SettingsToggleRow( - icon: "arrow.clockwise", - title: "Refresh Modules on Launch", - isOn: $refreshModulesOnLaunch, - showDivider: false - ) - } - - SettingsSection( - title: "Advanced", - footer: "Anonymous data is collected to improve the app. No personal information is collected. This can be disabled at any time." - ) { - SettingsToggleRow( - icon: "chart.bar", - title: "Enable Analytics", - isOn: $analyticsEnabled, - showDivider: false - ) - } + .padding(.vertical, 20) } - .padding(.vertical, 20) + .navigationTitle("General") + .scrollViewBottomPadding() } - .navigationTitle("General") - .scrollViewBottomPadding() } } diff --git a/Sulfur.xcodeproj/project.pbxproj b/Sulfur.xcodeproj/project.pbxproj index 46b16e2..281524d 100644 --- a/Sulfur.xcodeproj/project.pbxproj +++ b/Sulfur.xcodeproj/project.pbxproj @@ -87,6 +87,7 @@ 1E47859B2DEBC5960095BF2F /* AnilistMatchPopupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E47859A2DEBC5960095BF2F /* AnilistMatchPopupView.swift */; }; 1E9FF1D32D403E49008AC100 /* SettingsViewLoggerFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9FF1D22D403E42008AC100 /* SettingsViewLoggerFilter.swift */; }; 1EAC7A322D888BC50083984D /* MusicProgressSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EAC7A312D888BC50083984D /* MusicProgressSlider.swift */; }; + 1EDA48F42DFAC374002A4EC3 /* TMDBMatchPopupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EDA48F32DFAC374002A4EC3 /* TMDBMatchPopupView.swift */; }; 1EF5C3A92DB988E40032BF07 /* CommunityLib.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EF5C3A82DB988D70032BF07 /* CommunityLib.swift */; }; 7222485F2DCBAA2C00CABE2D /* DownloadModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7222485D2DCBAA2C00CABE2D /* DownloadModels.swift */; }; 722248602DCBAA2C00CABE2D /* M3U8StreamExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7222485E2DCBAA2C00CABE2D /* M3U8StreamExtractor.swift */; }; @@ -180,6 +181,7 @@ 1E47859A2DEBC5960095BF2F /* AnilistMatchPopupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnilistMatchPopupView.swift; sourceTree = ""; }; 1E9FF1D22D403E42008AC100 /* SettingsViewLoggerFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewLoggerFilter.swift; sourceTree = ""; }; 1EAC7A312D888BC50083984D /* MusicProgressSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicProgressSlider.swift; sourceTree = ""; }; + 1EDA48F32DFAC374002A4EC3 /* TMDBMatchPopupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TMDBMatchPopupView.swift; sourceTree = ""; }; 1EF5C3A82DB988D70032BF07 /* CommunityLib.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunityLib.swift; sourceTree = ""; }; 7222485D2DCBAA2C00CABE2D /* DownloadModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadModels.swift; sourceTree = ""; }; 7222485E2DCBAA2C00CABE2D /* M3U8StreamExtractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = M3U8StreamExtractor.swift; sourceTree = ""; }; @@ -366,6 +368,7 @@ 133D7C7F2D2BE2630075467E /* MediaInfoView */ = { isa = PBXGroup; children = ( + 1EDA48F32DFAC374002A4EC3 /* TMDBMatchPopupView.swift */, 138AA1B52D2D66EC0021F9DF /* EpisodeCell */, 133D7C802D2BE2630075467E /* MediaInfoView.swift */, 1E47859A2DEBC5960095BF2F /* AnilistMatchPopupView.swift */, @@ -700,6 +703,7 @@ files = ( 135CCBE22D4D1138008B9C0E /* SettingsViewPlayer.swift in Sources */, 131270172DC13A010093AA9C /* DownloadManager.swift in Sources */, + 1EDA48F42DFAC374002A4EC3 /* TMDBMatchPopupView.swift in Sources */, 1327FBA72D758CEA00FC6689 /* Analytics.swift in Sources */, 13DC0C462D302C7500D0F966 /* VideoPlayer.swift in Sources */, 1359ED142D76F49900C13034 /* finTopView.swift in Sources */, @@ -935,7 +939,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\""; - DEVELOPMENT_TEAM = 399LMK6Q2Y; + DEVELOPMENT_TEAM = 385Y24WAN5; "ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -953,7 +957,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0.0; - PRODUCT_BUNDLE_IDENTIFIER = me.cranci.sulfur; + PRODUCT_BUNDLE_IDENTIFIER = me.cranci.sulfur1; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -977,7 +981,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\""; - DEVELOPMENT_TEAM = 399LMK6Q2Y; + DEVELOPMENT_TEAM = 385Y24WAN5; "ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -995,7 +999,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0.0; - PRODUCT_BUNDLE_IDENTIFIER = me.cranci.sulfur; + PRODUCT_BUNDLE_IDENTIFIER = me.cranci.sulfur1; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";