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)