From 2a49a5db68f3170216d499d1ce650835fce5ea38 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Fri, 23 Oct 2026 21:47:34 +0200 Subject: [PATCH] Use production CloudKit environment for Xcode builds Development-signed builds now opt into the Production CloudKit environment via com.apple.developer.icloud-container-environment, driven by a CLOUDKIT_ENV build setting. A new Debug-CKDev configuration and "Yattee (CloudKit Dev)" scheme switch to the Development environment for schema work. The DEV badge and banner in iCloud settings now reflect the actual environment (YatteeCloudKitEnvironment Info.plist key) instead of #if DEBUG, and the sync engine logs the environment at startup. --- Yattee.xcodeproj/project.pbxproj | 254 +++++++++++++++++- .../xcschemes/Yattee (CloudKit Dev).xcscheme | 91 +++++++ Yattee/Core/AppIdentifiers.swift | 11 + Yattee/Info-tvOS.plist | 2 + Yattee/Info.plist | 2 + Yattee/Localizable.xcstrings | 3 - .../CloudKit/CloudKitSyncEngine.swift | 1 + Yattee/Views/Settings/SettingsView.swift | 36 +-- .../Views/Settings/iCloudSettingsView.swift | 12 +- Yattee/Yattee-macOS.entitlements | 2 + Yattee/Yattee.entitlements | 2 + 11 files changed, 388 insertions(+), 28 deletions(-) create mode 100644 Yattee.xcodeproj/xcshareddata/xcschemes/Yattee (CloudKit Dev).xcscheme diff --git a/Yattee.xcodeproj/project.pbxproj b/Yattee.xcodeproj/project.pbxproj index 4d3f1a62..2a63368c 100644 --- a/Yattee.xcodeproj/project.pbxproj +++ b/Yattee.xcodeproj/project.pbxproj @@ -384,7 +384,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ \"${CONFIGURATION}\" = \"Release-DeveloperID\" ] || [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n echo \"Skipping Sparkle strip (config=${CONFIGURATION})\"\n exit 0\nfi\nFW=\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework\"\nif [ -d \"$FW\" ]; then\n echo \"Stripping Sparkle.framework (config=${CONFIGURATION})\"\n chflags -R nouchg \"$FW\" 2>/dev/null || true\n chmod -R u+w \"$FW\" 2>/dev/null || true\n TMP=\"${FW}.stripping.$$\"\n if mv \"$FW\" \"$TMP\" 2>/dev/null; then\n TARGET=\"$TMP\"\n else\n TARGET=\"$FW\"\n fi\n for i in 1 2 3 4 5; do\n rm -rf \"$TARGET\" && break\n sleep 0.2\n done\n if [ -e \"$TARGET\" ]; then\n echo \"warning: failed to fully remove $TARGET\" >&2\n exit 1\n fi\nfi\n"; + shellScript = "if [ \"${CONFIGURATION}\" = \"Release-DeveloperID\" ] || [ \"${CONFIGURATION}\" = \"Debug\" ] || [ \"${CONFIGURATION}\" = \"Debug-CKDev\" ]; then\n echo \"Skipping Sparkle strip (config=${CONFIGURATION})\"\n exit 0\nfi\nFW=\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework\"\nif [ -d \"$FW\" ]; then\n echo \"Stripping Sparkle.framework (config=${CONFIGURATION})\"\n chflags -R nouchg \"$FW\" 2>/dev/null || true\n chmod -R u+w \"$FW\" 2>/dev/null || true\n TMP=\"${FW}.stripping.$$\"\n if mv \"$FW\" \"$TMP\" 2>/dev/null; then\n TARGET=\"$TMP\"\n else\n TARGET=\"$FW\"\n fi\n for i in 1 2 3 4 5; do\n rm -rf \"$TARGET\" && break\n sleep 0.2\n done\n if [ -e \"$TARGET\" ]; then\n echo \"warning: failed to fully remove $TARGET\" >&2\n exit 1\n fi\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -445,6 +445,7 @@ 372D1A302EDB163900F58F7A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLOUDKIT_ENV = Production; ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; @@ -506,9 +507,75 @@ }; name = Debug; }; + 37CCD0E00000000000000001 /* Debug-CKDev */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLOUDKIT_ENV = Development; + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 78Z5H3M6RJ; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = "Debug-CKDev"; + }; 372D1A312EDB163900F58F7A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLOUDKIT_ENV = Production; ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; @@ -647,6 +714,91 @@ }; name = Debug; }; + 37CCD0E00000000000000002 /* Debug-CKDev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = Yattee2; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + AUTOMATION_APPLE_EVENTS = NO; + CODE_SIGN_ENTITLEMENTS = Yattee/Yattee.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 275; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = 78Z5H3M6RJ; + ENABLE_APP_SANDBOX = YES; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; + ENABLE_PREVIEWS = YES; + ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = YES; + ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; + ENABLE_RESOURCE_ACCESS_CALENDARS = NO; + ENABLE_RESOURCE_ACCESS_CAMERA = NO; + ENABLE_RESOURCE_ACCESS_CONTACTS = NO; + ENABLE_RESOURCE_ACCESS_LOCATION = NO; + ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO; + ENABLE_RESOURCE_ACCESS_PRINTING = NO; + ENABLE_RESOURCE_ACCESS_USB = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + ENABLE_USER_SELECTED_FILES = readwrite; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + "GLES_SILENCE_DEPRECATION=1", + "GL_SILENCE_DEPRECATION=1", + ); + GENERATE_INFOPLIST_FILE = YES; + HEADER_SEARCH_PATHS = ( + "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Libsmbclient.framework/Headers/samba-4.0", + "$(BUILT_PRODUCTS_DIR)/Libsmbclient.framework/Headers/samba-4.0", + ); + INFOPLIST_FILE = Yattee/Info.plist; + "INFOPLIST_FILE[sdk=appletvos*]" = "Yattee/Info-tvOS.plist"; + "INFOPLIST_FILE[sdk=appletvsimulator*]" = "Yattee/Info-tvOS.plist"; + INFOPLIST_KEY_CFBundleDisplayName = Yattee; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.video"; + INFOPLIST_KEY_NSHumanReadableCopyright = "© 2026 Arkadiusz Fal"; + INFOPLIST_KEY_NSLocalNetworkUsageDescription = "Yattee uses local network to discover and control playback on other Yattee devices."; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 2.0.0; + PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO; + RUNTIME_EXCEPTION_ALLOW_JIT = NO; + RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = YES; + RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO; + RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Yattee/Yattee-Bridging-Header.h"; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,3"; + TVOS_DEPLOYMENT_TARGET = 18.0; + XROS_DEPLOYMENT_TARGET = 26.1; + }; + name = "Debug-CKDev"; + }; 372D1A342EDB163900F58F7A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -738,6 +890,7 @@ 376D70452F996E0700255B09 /* Release-DeveloperID */ = { isa = XCBuildConfiguration; buildSettings = { + CLOUDKIT_ENV = Production; ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; @@ -1003,6 +1156,37 @@ }; name = Debug; }; + 37CCD0E00000000000000003 /* Debug-CKDev */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = YatteeShareExtension/YatteeShareExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 275; + DEVELOPMENT_TEAM = 78Z5H3M6RJ; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = YatteeShareExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Yattee Share Extension"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 18; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 2.0.0; + PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app.ShareExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Debug-CKDev"; + }; 37BA19B82EE4EB7F001D7B0F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1069,6 +1253,40 @@ }; name = Debug; }; + 37CCD0E00000000000000004 /* Debug-CKDev */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = YatteeTopShelf/YatteeTopShelf.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 275; + DEVELOPMENT_TEAM = 78Z5H3M6RJ; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = YatteeTopShelf/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Yattee Top Shelf"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_ENTRY_POINT = _NSExtensionMain; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 2.0.0; + PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app.TopShelf; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "appletvos appletvsimulator"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 18.0; + }; + name = "Debug-CKDev"; + }; 37C0AAAA00000000AAAA000B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1133,6 +1351,35 @@ }; name = Debug; }; + 37CCD0E00000000000000005 /* Debug-CKDev */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 275; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = 78Z5H3M6RJ; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + MACOSX_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app.YatteeTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,3"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Yattee.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Yattee"; + TVOS_DEPLOYMENT_TARGET = 18.0; + XROS_DEPLOYMENT_TARGET = 26.1; + }; + name = "Debug-CKDev"; + }; 37D0B29C2EDB23BD00B9C4ED /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1169,6 +1416,7 @@ isa = XCConfigurationList; buildConfigurations = ( 372D1A302EDB163900F58F7A /* Debug */, + 37CCD0E00000000000000001 /* Debug-CKDev */, 372D1A312EDB163900F58F7A /* Release */, 376D70452F996E0700255B09 /* Release-DeveloperID */, ); @@ -1179,6 +1427,7 @@ isa = XCConfigurationList; buildConfigurations = ( 372D1A332EDB163900F58F7A /* Debug */, + 37CCD0E00000000000000002 /* Debug-CKDev */, 372D1A342EDB163900F58F7A /* Release */, 376D70462F996E0700255B09 /* Release-DeveloperID */, ); @@ -1189,6 +1438,7 @@ isa = XCConfigurationList; buildConfigurations = ( 37BA19B72EE4EB7F001D7B0F /* Debug */, + 37CCD0E00000000000000003 /* Debug-CKDev */, 37BA19B82EE4EB7F001D7B0F /* Release */, 376D70482F996E0700255B09 /* Release-DeveloperID */, ); @@ -1199,6 +1449,7 @@ isa = XCConfigurationList; buildConfigurations = ( 37C0AAAA00000000AAAA000A /* Debug */, + 37CCD0E00000000000000004 /* Debug-CKDev */, 37C0AAAA00000000AAAA000B /* Release */, 376D70492F996E0700255B09 /* Release-DeveloperID */, ); @@ -1209,6 +1460,7 @@ isa = XCConfigurationList; buildConfigurations = ( 37D0B29B2EDB23BD00B9C4ED /* Debug */, + 37CCD0E00000000000000005 /* Debug-CKDev */, 37D0B29C2EDB23BD00B9C4ED /* Release */, 376D70472F996E0700255B09 /* Release-DeveloperID */, ); diff --git a/Yattee.xcodeproj/xcshareddata/xcschemes/Yattee (CloudKit Dev).xcscheme b/Yattee.xcodeproj/xcshareddata/xcschemes/Yattee (CloudKit Dev).xcscheme new file mode 100644 index 00000000..4d13e9fc --- /dev/null +++ b/Yattee.xcodeproj/xcshareddata/xcschemes/Yattee (CloudKit Dev).xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Yattee/Core/AppIdentifiers.swift b/Yattee/Core/AppIdentifiers.swift index b6b80075..f29e74ac 100644 --- a/Yattee/Core/AppIdentifiers.swift +++ b/Yattee/Core/AppIdentifiers.swift @@ -12,6 +12,17 @@ enum AppIdentifiers { "iCloud.\(bundleIdentifier)" } + /// CloudKit environment this build is signed for ("Development" or "Production"), + /// from the `CLOUDKIT_ENV` build setting. Debug builds use Production unless + /// built with the Debug-CKDev configuration ("Yattee (CloudKit Dev)" scheme). + static var iCloudEnvironment: String { + Bundle.main.object(forInfoDictionaryKey: "YatteeCloudKitEnvironment") as? String ?? "Production" + } + + static var isCloudKitDevelopmentEnvironment: Bool { + iCloudEnvironment == "Development" + } + // MARK: - Background Tasks static var backgroundFeedRefresh: String { diff --git a/Yattee/Info-tvOS.plist b/Yattee/Info-tvOS.plist index 5e13c828..db68b72e 100644 --- a/Yattee/Info-tvOS.plist +++ b/Yattee/Info-tvOS.plist @@ -37,6 +37,8 @@ stream.yattee.app.activity + YatteeCloudKitEnvironment + $(CLOUDKIT_ENV) UIBackgroundModes audio diff --git a/Yattee/Info.plist b/Yattee/Info.plist index 63f8983a..619ecd06 100644 --- a/Yattee/Info.plist +++ b/Yattee/Info.plist @@ -46,6 +46,8 @@ stream.yattee.app.activity + YatteeCloudKitEnvironment + $(CLOUDKIT_ENV) UIBackgroundModes audio diff --git a/Yattee/Localizable.xcstrings b/Yattee/Localizable.xcstrings index 359ab86a..cdd602fc 100644 --- a/Yattee/Localizable.xcstrings +++ b/Yattee/Localizable.xcstrings @@ -13673,7 +13673,6 @@ } }, "settings.icloud.dev.badge" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -13684,7 +13683,6 @@ } }, "settings.icloud.dev.footer" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -13695,7 +13693,6 @@ } }, "settings.icloud.dev.title" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { diff --git a/Yattee/Services/CloudKit/CloudKitSyncEngine.swift b/Yattee/Services/CloudKit/CloudKitSyncEngine.swift index 35763f67..d514f189 100644 --- a/Yattee/Services/CloudKit/CloudKitSyncEngine.swift +++ b/Yattee/Services/CloudKit/CloudKitSyncEngine.swift @@ -311,6 +311,7 @@ final class CloudKitSyncEngine: @unchecked Sendable { self.container = container self.database = database self.zoneManager = CloudKitZoneManager(database: database) + LoggingService.shared.logCloudKit("CloudKit environment: \(AppIdentifiers.iCloudEnvironment)") } else { LoggingService.shared.logCloudKit("iCloud container entitlement missing (re-signed build) - CloudKit sync unavailable") self.container = nil diff --git a/Yattee/Views/Settings/SettingsView.swift b/Yattee/Views/Settings/SettingsView.swift index 5e34a685..7fb8699b 100644 --- a/Yattee/Views/Settings/SettingsView.swift +++ b/Yattee/Views/Settings/SettingsView.swift @@ -167,15 +167,15 @@ struct SettingsView: View { } label: { HStack { Label(String(localized: "settings.icloud.title"), systemImage: "icloud") - #if DEBUG - Spacer() - Text(String(localized: "settings.icloud.dev.badge")) - .font(.caption2.bold()) - .foregroundStyle(.white) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background(.orange, in: Capsule()) - #endif + if AppIdentifiers.isCloudKitDevelopmentEnvironment { + Spacer() + Text(String(localized: "settings.icloud.dev.badge")) + .font(.caption2.bold()) + .foregroundStyle(.white) + .padding(.horizontal, 6) + .padding(.vertical, 2) + .background(.orange, in: Capsule()) + } } } @@ -287,15 +287,15 @@ struct SettingsView: View { } label: { HStack { Label(String(localized: "settings.icloud.title"), systemImage: "icloud") - #if DEBUG - Spacer() - Text(String(localized: "settings.icloud.dev.badge")) - .font(.caption2.bold()) - .foregroundStyle(.white) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background(.orange, in: Capsule()) - #endif + if AppIdentifiers.isCloudKitDevelopmentEnvironment { + Spacer() + Text(String(localized: "settings.icloud.dev.badge")) + .font(.caption2.bold()) + .foregroundStyle(.white) + .padding(.horizontal, 6) + .padding(.vertical, 2) + .background(.orange, in: Capsule()) + } } } diff --git a/Yattee/Views/Settings/iCloudSettingsView.swift b/Yattee/Views/Settings/iCloudSettingsView.swift index a62c0ef3..19033e87 100644 --- a/Yattee/Views/Settings/iCloudSettingsView.swift +++ b/Yattee/Views/Settings/iCloudSettingsView.swift @@ -50,13 +50,13 @@ struct iCloudSettingsView: View { var body: some View { SettingsFormContainer { - #if DEBUG - SettingsFormSection(footer: "settings.icloud.dev.footer") { - Label(String(localized: "settings.icloud.dev.title"), systemImage: "hammer.fill") - .foregroundStyle(.orange) - .font(.subheadline) + if AppIdentifiers.isCloudKitDevelopmentEnvironment { + SettingsFormSection(footer: "settings.icloud.dev.footer") { + Label(String(localized: "settings.icloud.dev.title"), systemImage: "hammer.fill") + .foregroundStyle(.orange) + .font(.subheadline) + } } - #endif if cloudKitSync?.isCloudKitAvailable == false { SettingsFormSection(footer: "settings.icloud.unavailable.footer") { diff --git a/Yattee/Yattee-macOS.entitlements b/Yattee/Yattee-macOS.entitlements index 63983a82..b88ec4bf 100644 --- a/Yattee/Yattee-macOS.entitlements +++ b/Yattee/Yattee-macOS.entitlements @@ -4,6 +4,8 @@ com.apple.developer.aps-environment production + com.apple.developer.icloud-container-environment + $(CLOUDKIT_ENV) com.apple.developer.icloud-container-identifiers iCloud.$(CFBundleIdentifier) diff --git a/Yattee/Yattee.entitlements b/Yattee/Yattee.entitlements index 0f1cea8c..b74d8171 100644 --- a/Yattee/Yattee.entitlements +++ b/Yattee/Yattee.entitlements @@ -4,6 +4,8 @@ aps-environment development + com.apple.developer.icloud-container-environment + $(CLOUDKIT_ENV) com.apple.developer.icloud-container-identifiers iCloud.$(CFBundleIdentifier)