paul is not liable for any issues (#185)
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:
50/50 2025-06-12 22:45:56 +02:00 committed by GitHub
parent 375fe1806b
commit 525771927c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 416 additions and 143 deletions

View file

@ -170,6 +170,7 @@
}
},
"AKA Sulfur" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -226,6 +227,9 @@
}
}
}
},
"Also known as Sulfur" : {
},
"AniList" : {
"extractionState" : "manual",
@ -243,9 +247,6 @@
}
}
}
},
"Also known as Sulfur" : {
},
"AniList ID" : {
@ -541,6 +542,22 @@
}
}
},
"Cellular Quality" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Cellular Quality"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Mobiele Kwaliteit"
}
}
}
},
"Check out some community modules here!" : {
"localizations" : {
"en" : {
@ -557,6 +574,22 @@
}
}
},
"Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality. If the exact quality isn't available, the closest option will be selected automatically.\n\nNote: Not all video sources and players support quality selection. This feature works best with HLS streams using the Sora player." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality. If the exact quality isn't available, the closest option will be selected automatically.\n\nNote: Not all video sources and players support quality selection. This feature works best with HLS streams using the Sora player."
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Kies de gewenste videoresolutie voor WiFi en mobiele verbindingen. Hogere resoluties gebruiken meer data maar bieden betere kwaliteit. Als de exacte kwaliteit niet beschikbaar is, wordt automatisch de dichtstbijzijnde optie geselecteerd.\n\nLet op: Niet alle videobronnen en spelers ondersteunen kwaliteitsselectie. Deze functie werkt het beste met HLS-streams met de Sora-speler."
}
}
}
},
"Clear" : {
"localizations" : {
"en" : {
@ -913,6 +946,7 @@
}
},
"Download Episode" : {
"extractionState" : "stale",
"localizations" : {
"nl" : {
"stringUnit" : {
@ -924,6 +958,9 @@
},
"Download Summary" : {
},
"Download This Episode" : {
},
"Downloaded" : {
"localizations" : {
@ -996,6 +1033,7 @@
}
},
"Enter the AniList ID for this media" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -1010,6 +1048,9 @@
}
}
}
},
"Enter the AniList ID for this series" : {
},
"Episode %lld" : {
"localizations" : {
@ -1129,6 +1170,9 @@
}
}
}
},
"Error Fetching Results" : {
},
"Errors and critical issues." : {
"extractionState" : "manual",
@ -1179,16 +1223,6 @@
}
}
},
"Failed to load contributors" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Failed to load contributors. Please try again later."
}
}
}
},
"Files Downloaded" : {
"localizations" : {
"en" : {
@ -1451,28 +1485,6 @@
}
}
},
"INFOS" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Information"
}
}
}
},
"Join the Discord" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Join Discord Community"
}
}
}
},
"LESS" : {
"extractionState" : "manual",
"localizations" : {
@ -1539,16 +1551,6 @@
}
}
},
"License (GPLv3.0)" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "View License (GPLv3.0)"
}
}
}
},
"Loading Episode %lld..." : {
"localizations" : {
"en" : {
@ -1818,8 +1820,12 @@
}
}
}
},
"MAIN SETTINGS" : {
},
"Mark All Previous Watched" : {
"extractionState" : "stale",
"localizations" : {
"nl" : {
"stringUnit" : {
@ -1838,6 +1844,12 @@
}
}
}
},
"Mark Episode as Watched" : {
},
"Mark Previous Episodes as Watched" : {
},
"Mark watched" : {
"localizations" : {
@ -1849,23 +1861,17 @@
}
}
},
"Mark Previous Episodes as Watched" : {
},
"Mark watched" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mark as Watched"
}
}
}
},
"Match with AniList" : {
},
"Match with TMDB" : {
},
"Matched ID: %lld" : {
},
"Matched with: %@" : {
"extractionState" : "stale",
"localizations" : {
"nl" : {
"stringUnit" : {
@ -1950,6 +1956,7 @@
}
},
"Metadata Provider" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -1964,6 +1971,9 @@
}
}
}
},
"Metadata Providers Order" : {
},
"Module Removed" : {
"extractionState" : "manual",
@ -2103,6 +2113,7 @@
}
},
"No items to continue watching." : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -2167,6 +2178,7 @@
}
},
"No Results Found" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -2181,6 +2193,9 @@
}
}
}
},
"No Search Results Found" : {
},
"Note that the modules will be replaced only if there is a different version string inside the JSON file." : {
"localizations" : {
@ -2197,6 +2212,9 @@
}
}
}
},
"Nothing to Continue Watching" : {
},
"OK" : {
"localizations" : {
@ -2360,6 +2378,9 @@
}
}
}
},
"Provider: %@" : {
},
"Queue" : {
@ -2381,6 +2402,7 @@
}
},
"Recently watched content will appear here." : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -2592,17 +2614,6 @@
}
}
},
"Report an Issue" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Report an Issue on GitHub"
}
}
}
},
"Reset" : {
"localizations" : {
"en" : {
@ -2656,6 +2667,7 @@
}
},
"Reset Progress" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -2688,6 +2700,7 @@
}
},
"Running Sora %@ - cranci1" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -2987,6 +3000,9 @@
},
"Sora" : {
},
"Sora %@ by cranci1" : {
},
"Sora and cranci1 are not affiliated with AniList or Trakt in any way.\n\nAlso note that progress updates may not be 100% accurate." : {
"extractionState" : "manual",
@ -3023,6 +3039,7 @@
}
},
"Sora/Sulfur will always remain free with no ADs!" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -3351,6 +3368,7 @@
}
},
"Thumbnails Width" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -3406,6 +3424,7 @@
},
"Try different keywords" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@ -3420,6 +3439,9 @@
}
}
}
},
"Try different search terms" : {
},
"Two Finger Hold for Pause" : {
"localizations" : {
@ -3436,6 +3458,9 @@
}
}
}
},
"Unable to fetch matches. Please try again later." : {
},
"Use TMDB Poster Image" : {
"localizations" : {
@ -3472,6 +3497,22 @@
}
}
},
"Video Quality Preferences" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Video Quality Preferences"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Video Kwaliteit Voorkeuren"
}
}
}
},
"View All" : {
"localizations" : {
"en" : {
@ -3521,6 +3562,22 @@
}
}
},
"WiFi Quality" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "WiFi Quality"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "WiFi Kwaliteit"
}
}
}
},
"You are not logged in" : {
"extractionState" : "manual",
"localizations" : {
@ -3570,66 +3627,277 @@
}
}
},
"Video Quality Preferences" : {
"Your recently watched content will appear here" : {
},
"Download Settings" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Video Quality Preferences"
"value" : "Download Settings"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Video Kwaliteit Voorkeuren"
"value" : "Download Instellingen"
}
}
}
},
"Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality. If the exact quality isn't available, the closest option will be selected automatically.\n\nNote: Not all video sources and players support quality selection. This feature works best with HLS streams using the Sora player." : {
"Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality. If the exact quality isn't available, the closest option will be selected automatically.\n\nNote: Not all video sources and players support quality selection. This feature works best with HLS streams using the Sora player."
"value" : "Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources."
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Kies de gewenste videoresolutie voor WiFi en mobiele verbindingen. Hogere resoluties gebruiken meer data maar bieden betere kwaliteit. Als de exacte kwaliteit niet beschikbaar is, wordt automatisch de dichtstbijzijnde optie geselecteerd.\n\nLet op: Niet alle videobronnen en spelers ondersteunen kwaliteitsselectie. Deze functie werkt het beste met HLS-streams met de Sora-speler."
"value" : "Maximum gelijktijdige downloads bepaalt hoeveel afleveringen tegelijk kunnen worden gedownload. Hogere waarden kunnen meer bandbreedte en apparaatbronnen gebruiken."
}
}
}
},
"WiFi Quality" : {
"Quality" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "WiFi Quality"
"value" : "Quality"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "WiFi Kwaliteit"
"value" : "Kwaliteit"
}
}
}
},
"Cellular Quality" : {
"Max Concurrent Downloads" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Cellular Quality"
"value" : "Max Concurrent Downloads"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Mobiele Kwaliteit"
"value" : "Maximum Gelijktijdige Downloads"
}
}
}
},
"Allow Cellular Downloads" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Allow Cellular Downloads"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Downloads via Mobiel Netwerk Toestaan"
}
}
}
},
"Quality Information" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Quality Information"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Kwaliteitsinformatie"
}
}
}
},
"Storage Management" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Storage Management"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Opslagbeheer"
}
}
}
},
"Storage Used" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Storage Used"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Gebruikte Opslag"
}
}
}
},
"Files Downloaded" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Files Downloaded"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Gedownloade Bestanden"
}
}
}
},
"Refresh Storage Info" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Refresh Storage Info"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Opslaginformatie Vernieuwen"
}
}
}
},
"Clear All Downloads" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Clear All Downloads"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Alle Downloads Wissen"
}
}
}
},
"Delete All Downloads" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Delete All Downloads"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Alle Downloads Verwijderen"
}
}
}
},
"Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use."
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Weet je zeker dat je alle gedownloade bestanden wilt verwijderen? Je kunt ervoor kiezen om alleen de bibliotheek te wissen terwijl je de gedownloade bestanden voor later gebruik bewaart."
}
}
}
},
"Clear Library Only" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Clear Library Only"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Alleen Bibliotheek Wissen"
}
}
}
},
"Library cleared successfully" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Library cleared successfully"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Bibliotheek succesvol gewist"
}
}
}
},
"All downloads deleted successfully" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "All downloads deleted successfully"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Alle downloads succesvol verwijderd"
}
}
}
},
"Downloads" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Downloads"
}
},
"nl" : {
"stringUnit" : {
"state" : "new",
"value" : "Downloads"
}
}
}

View file

@ -164,12 +164,12 @@ struct SettingsViewDownloads: View {
ScrollView {
VStack(spacing: 24) {
SettingsSection(
title: "Download Settings",
footer: "Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources."
title: String(localized: "Download Settings"),
footer: String(localized: "Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources.")
) {
SettingsPickerRow(
icon: "4k.tv",
title: "Quality",
title: String(localized: "Quality"),
options: DownloadQualityPreference.allCases.map { $0.rawValue },
optionToString: { $0 },
selection: $downloadQuality
@ -181,7 +181,7 @@ struct SettingsViewDownloads: View {
.frame(width: 24, height: 24)
.foregroundStyle(.primary)
Text("Max Concurrent Downloads")
Text(String(localized: "Max Concurrent Downloads"))
.foregroundStyle(.primary)
Spacer()
@ -200,14 +200,14 @@ struct SettingsViewDownloads: View {
SettingsToggleRow(
icon: "antenna.radiowaves.left.and.right",
title: "Allow Cellular Downloads",
title: String(localized: "Allow Cellular Downloads"),
isOn: $allowCellularDownloads,
showDivider: false
)
}
SettingsSection(
title: "Quality Information"
title: String(localized: "Quality Information")
) {
if let preferenceDescription = DownloadQualityPreference(rawValue: downloadQuality)?.description {
HStack {
@ -222,7 +222,7 @@ struct SettingsViewDownloads: View {
}
SettingsSection(
title: "Storage Management"
title: String(localized: "Storage Management")
) {
VStack(spacing: 0) {
HStack {
@ -230,7 +230,7 @@ struct SettingsViewDownloads: View {
.frame(width: 24, height: 24)
.foregroundStyle(.primary)
Text("Storage Used")
Text(String(localized: "Storage Used"))
.foregroundStyle(.primary)
Spacer()
@ -255,7 +255,7 @@ struct SettingsViewDownloads: View {
.frame(width: 24, height: 24)
.foregroundStyle(.primary)
Text("Files Downloaded")
Text(String(localized: "Files Downloaded"))
.foregroundStyle(.primary)
Spacer()
@ -277,7 +277,7 @@ struct SettingsViewDownloads: View {
.frame(width: 24, height: 24)
.foregroundStyle(.primary)
Text("Refresh Storage Info")
Text(String(localized: "Refresh Storage Info"))
.foregroundStyle(.primary)
Spacer()
@ -297,7 +297,7 @@ struct SettingsViewDownloads: View {
.frame(width: 24, height: 24)
.foregroundStyle(.red)
Text("Clear All Downloads")
Text(String(localized: "Clear All Downloads"))
.foregroundStyle(.red)
Spacer()
@ -310,18 +310,18 @@ struct SettingsViewDownloads: View {
}
.padding(.vertical, 20)
}
.navigationTitle("Downloads")
.navigationTitle(String(localized: "Downloads"))
.scrollViewBottomPadding()
.alert("Delete All Downloads", isPresented: $showClearConfirmation) {
Button("Cancel", role: .cancel) { }
Button("Delete All", role: .destructive) {
.alert(String(localized: "Delete All Downloads"), isPresented: $showClearConfirmation) {
Button(String(localized: "Cancel"), role: .cancel) { }
Button(String(localized: "Delete All"), role: .destructive) {
clearAllDownloads(preservePersistentDownloads: false)
}
Button("Clear Library Only", role: .destructive) {
Button(String(localized: "Clear Library Only"), role: .destructive) {
clearAllDownloads(preservePersistentDownloads: true)
}
} message: {
Text("Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use.")
Text(String(localized: "Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use."))
}
.onAppear {
calculateTotalStorage()
@ -370,9 +370,9 @@ struct SettingsViewDownloads: View {
DispatchQueue.main.async {
if preservePersistentDownloads {
DropManager.shared.success("Library cleared successfully")
DropManager.shared.success(String(localized: "Library cleared successfully"))
} else {
DropManager.shared.success("All downloads deleted successfully")
DropManager.shared.success(String(localized: "All downloads deleted successfully"))
}
}
}

View file

@ -160,6 +160,7 @@ struct SettingsViewGeneral: View {
@AppStorage("tmdbImageWidth") private var TMDBimageWidht: String = "original"
@AppStorage("mediaColumnsPortrait") private var mediaColumnsPortrait: Int = 2
@AppStorage("mediaColumnsLandscape") private var mediaColumnsLandscape: Int = 4
@AppStorage("metadataProviders") private var metadataProviders: String = "TMDB"
private var metadataProvidersOrder: [String] {
get { (try? JSONDecoder().decode([String].self, from: metadataProvidersOrderData)) ?? ["AniList","TMDB"] }
@ -167,6 +168,7 @@ struct SettingsViewGeneral: View {
}
private let TMDBimageWidhtList = ["300", "500", "780", "1280", "original"]
private let sortOrderOptions = ["Ascending", "Descending"]
private let metadataProvidersList = ["TMDB", "AniList"]
@EnvironmentObject var settings: Settings
@State private var showRestartAlert = false
@ -227,51 +229,54 @@ struct SettingsViewGeneral: View {
isOn: $fetchEpisodeMetadata
)
List {
ForEach(metadataProvidersOrder, id: \.self) { prov in
Text(prov)
.padding(.vertical, 8)
VStack(spacing: 0) {
HStack {
Image(systemName: "arrow.up.arrow.down")
.frame(width: 24, height: 24)
.foregroundStyle(.primary)
Text(NSLocalizedString("Metadata Providers Order", comment: ""))
.foregroundStyle(.primary)
Spacer()
}
.onMove { idx, dest in
var arr = metadataProvidersOrder
arr.move(fromOffsets: idx, toOffset: dest)
metadataProvidersOrderData = try! JSONEncoder().encode(arr)
.padding(.horizontal, 16)
.padding(.vertical, 12)
Divider()
.padding(.horizontal, 16)
List {
ForEach(Array(metadataProvidersOrder.enumerated()), id: \.element) { index, provider in
HStack {
Text("\(index + 1)")
.frame(width: 24, height: 24)
.foregroundStyle(.gray)
Text(provider)
.foregroundStyle(.primary)
Spacer()
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
.listRowBackground(Color.clear)
.listRowSeparator(.visible)
.listRowSeparatorTint(.gray.opacity(0.3))
.listRowInsets(EdgeInsets())
}
.onMove { from, to in
var arr = metadataProvidersOrder
arr.move(fromOffsets: from, toOffset: to)
metadataProvidersOrderData = try! JSONEncoder().encode(arr)
}
}
.listStyle(.plain)
.frame(height: CGFloat(metadataProvidersOrder.count * 48))
.background(Color.clear)
.padding(.bottom, 8)
}
.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: NSLocalizedString("Metadata Provider", comment: ""),
options: metadataProvidersList,
optionToString: { $0 },
selection: $metadataProviders,
showDivider: true
)
SettingsPickerRow(
icon: "square.stack.3d.down.right",
title: NSLocalizedString("Thumbnails Width", comment: ""),
options: TMDBimageWidhtList,
optionToString: { $0 },
selection: $TMDBimageWidht,
showDivider: false
)
} else {
SettingsPickerRow(
icon: "server.rack",
title: NSLocalizedString("Metadata Provider", comment: ""),
options: metadataProvidersList,
optionToString: { $0 },
selection: $metadataProviders,
showDivider: false
)
}
}
SettingsSection(

View file

@ -944,7 +944,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
DEVELOPMENT_TEAM = 385Y24WAN5;
DEVELOPMENT_TEAM = 399LMK6Q2Y;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@ -986,7 +986,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
DEVELOPMENT_TEAM = 385Y24WAN5;
DEVELOPMENT_TEAM = 399LMK6Q2Y;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;