Compare commits
2 Commits
c9bd42aae5
...
0d2ad6e021
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d2ad6e021 | ||
|
|
7fa8dbdbdf |
@@ -393,6 +393,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -411,10 +412,9 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
MARKETING_VERSION = 3.5;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 3.5;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@@ -459,6 +459,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -471,10 +472,9 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
MARKETING_VERSION = 3.5;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 3.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -490,10 +490,12 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "Calendarr iOS/Calendarr iOS.entitlements";
|
||||
"CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "Calendarr iOS/Calendarr iOS-Catalyst.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = PP34X97WS3;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Calendarr;
|
||||
INFOPLIST_KEY_CFBundleName = Calendarr;
|
||||
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
|
||||
@@ -515,7 +517,7 @@
|
||||
PRODUCT_NAME = "Calendarr iOS";
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
@@ -523,7 +525,7 @@
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -533,10 +535,12 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "Calendarr iOS/Calendarr iOS.entitlements";
|
||||
"CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "Calendarr iOS/Calendarr iOS-Catalyst.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = PP34X97WS3;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Calendarr;
|
||||
INFOPLIST_KEY_CFBundleName = Calendarr;
|
||||
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
|
||||
@@ -558,7 +562,7 @@
|
||||
PRODUCT_NAME = "Calendarr iOS";
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
@@ -566,7 +570,7 @@
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -575,6 +579,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = CalendarrWidgets/CalendarrWidgets.entitlements;
|
||||
"CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "CalendarrWidgets/CalendarrWidgets-Catalyst.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = PP34X97WS3;
|
||||
GENERATE_INFOPLIST_FILE = NO;
|
||||
@@ -592,14 +597,14 @@
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -608,6 +613,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = CalendarrWidgets/CalendarrWidgets.entitlements;
|
||||
"CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "CalendarrWidgets/CalendarrWidgets-Catalyst.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = PP34X97WS3;
|
||||
GENERATE_INFOPLIST_FILE = NO;
|
||||
@@ -625,13 +631,13 @@
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
46
Calendarr iOS/Calendarr iOS-Catalyst.entitlements
Normal file
46
Calendarr iOS/Calendarr iOS-Catalyst.entitlements
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!--
|
||||
Mac Catalyst entitlements. A separate file is required because the App
|
||||
Group value differs per platform: macOS demands the Team ID prefix, iOS
|
||||
forbids it, and listing both in one file breaks iOS provisioning.
|
||||
Selected via CODE_SIGN_ENTITLEMENTS[sdk=macosx*].
|
||||
|
||||
This one file serves both distribution paths. app-sandbox is required by
|
||||
the Mac App Store and desirable for Developer ID; ENABLE_HARDENED_RUNTIME
|
||||
is required for notarization and ignored by the App Store. Only the
|
||||
signing identity differs, and that is chosen at export time.
|
||||
-->
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
|
||||
<!-- Talks to the user's own Calendarr server. -->
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
|
||||
<!-- BirthdaysImporter reads Contacts to sync birthdays. -->
|
||||
<key>com.apple.security.personal-information.addressbook</key>
|
||||
<true/>
|
||||
|
||||
<!-- .ics import (fileImporter) and calendar export (fileExporter). -->
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
|
||||
<!-- Must match CalendarrAppGroup.current on this platform, byte for byte. -->
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>PP34X97WS3.group.com.scarriffleservices.calendarr</string>
|
||||
</array>
|
||||
|
||||
<!-- Own group first: it stays the default access group, so tokens written
|
||||
before this entitlement existed keep resolving. The .shared group is
|
||||
what a second app from this team reads the auth token from. -->
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.scarriffleservices.calendarr.ios</string>
|
||||
<string>$(AppIdentifierPrefix)com.scarriffleservices.calendarr.shared</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -32,11 +32,16 @@ struct CalendarEntityQuery: EntityQuery {
|
||||
}
|
||||
|
||||
/// Widget configuration intent: lets the user pick which calendars to show.
|
||||
/// An empty selection means "show all calendars" (the default).
|
||||
/// No selection means "show all calendars" (the default).
|
||||
///
|
||||
/// The parameter must be optional: WidgetConfigurationIntent requires every
|
||||
/// parameter type to be optional, and the macOS/Mac Catalyst SDK enforces that
|
||||
/// where the iOS one lets a bare array through. `nil` and `[]` are treated
|
||||
/// alike downstream, so this is behaviour-preserving.
|
||||
struct CalendarSelectionIntent: WidgetConfigurationIntent {
|
||||
static var title: LocalizedStringResource = "Kalender auswählen"
|
||||
static var description = IntentDescription("Wähle welche Kalender im Widget angezeigt werden. Leer = alle Kalender.")
|
||||
|
||||
@Parameter(title: "Kalender")
|
||||
var selectedCalendars: [CalendarAppEntity]
|
||||
var selectedCalendars: [CalendarAppEntity]?
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ struct CalendarrTimelineProvider: AppIntentTimelineProvider {
|
||||
|
||||
private func filtered(_ snapshot: WidgetSnapshot?, by config: CalendarSelectionIntent) -> WidgetSnapshot? {
|
||||
guard let snapshot else { return nil }
|
||||
let ids = config.selectedCalendars.map { $0.id }
|
||||
guard !ids.isEmpty else { return snapshot } // empty = show all
|
||||
let ids = (config.selectedCalendars ?? []).map { $0.id }
|
||||
guard !ids.isEmpty else { return snapshot } // nothing selected = show all
|
||||
let keep = Set(ids)
|
||||
return WidgetSnapshot(
|
||||
writtenAt: snapshot.writtenAt,
|
||||
|
||||
19
CalendarrWidgets/CalendarrWidgets-Catalyst.entitlements
Normal file
19
CalendarrWidgets/CalendarrWidgets-Catalyst.entitlements
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!--
|
||||
Mac Catalyst entitlements for the widget extension. Deliberately minimal:
|
||||
the widget only ever reads the snapshot from the App Group container. It
|
||||
does no networking, touches no Contacts, and needs no keychain access.
|
||||
-->
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
|
||||
<!-- Must match CalendarrAppGroup.current on this platform, byte for byte. -->
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>PP34X97WS3.group.com.scarriffleservices.calendarr</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -4,9 +4,30 @@ import WidgetKit
|
||||
#endif
|
||||
|
||||
/// App-Group identifier shared between the main app and the widget extension.
|
||||
/// IMPORTANT: This must match the App Group capability in BOTH targets
|
||||
/// and the App Group ID registered in the Apple Developer Portal.
|
||||
let widgetAppGroupID = "group.com.scarriffleservices.calendarr"
|
||||
///
|
||||
/// IMPORTANT: this must stay byte-identical to `com.apple.security.application-groups`
|
||||
/// in the matching .entitlements file for the platform being built, and match the
|
||||
/// App Group registered in the Apple Developer portal.
|
||||
///
|
||||
/// The identifier registered in the portal never changes — only the string the
|
||||
/// *runtime* expects does. macOS (including Mac Catalyst) requires the Team ID
|
||||
/// prefix; iOS forbids it. Get this wrong and `containerURL(forSecurityApplication‑
|
||||
/// GroupIdentifier:)` returns nil, every read and write below quietly no-ops, and
|
||||
/// the widgets show placeholder content forever with no error anywhere.
|
||||
enum CalendarrAppGroup {
|
||||
/// As registered in the Apple Developer portal.
|
||||
static let unprefixed = "group.com.scarriffleservices.calendarr"
|
||||
/// Team ID — the value `$(AppIdentifierPrefix)` expands to at build time.
|
||||
static let teamID = "PP34X97WS3"
|
||||
|
||||
#if os(macOS) || targetEnvironment(macCatalyst)
|
||||
static let current = "\(teamID).\(unprefixed)"
|
||||
#else
|
||||
static let current = unprefixed
|
||||
#endif
|
||||
}
|
||||
|
||||
let widgetAppGroupID = CalendarrAppGroup.current
|
||||
|
||||
/// Lightweight calendar descriptor stored alongside the event cache so the
|
||||
/// widget configuration intent can offer calendar options without a network call.
|
||||
@@ -108,7 +129,18 @@ enum WidgetStore {
|
||||
private static let calendarsFilename = "widget-calendars.json"
|
||||
|
||||
private static var containerURL: URL? {
|
||||
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: widgetAppGroupID)
|
||||
let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: widgetAppGroupID)
|
||||
#if DEBUG
|
||||
if url == nil {
|
||||
// A nil container is always a build-configuration bug: the entitlement
|
||||
// is missing, or its value does not match widgetAppGroupID. It is
|
||||
// otherwise completely silent, so make it loud while developing.
|
||||
assertionFailure("App Group container unavailable for \(widgetAppGroupID) — "
|
||||
+ "check com.apple.security.application-groups in the "
|
||||
+ "entitlements for this platform.")
|
||||
}
|
||||
#endif
|
||||
return url
|
||||
}
|
||||
|
||||
private static var cacheURL: URL? {
|
||||
|
||||
Reference in New Issue
Block a user