Skip to content

Commit f943cce

Browse files
committed
fix: address review feedback for widget extension
- Replace hand-written pbxproj IDs with proper 24-char hex UUIDs - Restore main app signing config (Manual, Usage4Claude-CodeSigning, sandbox enabled) - Switch from file-based storage (~/.Usage4Claude/) to App Group UserDefaults - Add App Group entitlements to both main app and widget extension - Align MACOSX_DEPLOYMENT_TARGET to 14.0 for both targets (required by WidgetKit) - Match widget signing config to main app style
1 parent 0d6eac8 commit f943cce

File tree

5 files changed

+85
-104
lines changed

5 files changed

+85
-104
lines changed

Usage4Claude.xcodeproj/project.pbxproj

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,29 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
WIDGET001 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = WIDGET000 /* WidgetKit.framework */; };
11-
WIDGET002 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = WIDGET003 /* SwiftUI.framework */; };
12-
WIDGET004 /* Usage4ClaudeWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = WIDGETPROD /* Usage4ClaudeWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
10+
851F88B1F6CCE36B8296DBF6 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 334DEEC8C0AF87D7AE76764D /* WidgetKit.framework */; };
11+
554B23CF9491AD6219F536A2 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A87739911B7B81D7B91F6F3 /* SwiftUI.framework */; };
12+
E22FCD122AD18CF56501A4A2 /* Usage4ClaudeWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 068039FD2F82B5A332FAC8C7 /* Usage4ClaudeWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
1313
/* End PBXBuildFile section */
1414

1515
/* Begin PBXContainerItemProxy section */
16-
WIDGETPROXY /* PBXContainerItemProxy */ = {
16+
776710D32DDD1B75B1513839 /* PBXContainerItemProxy */ = {
1717
isa = PBXContainerItemProxy;
1818
containerPortal = 8873E4C72E9F61C700ACFF5C /* Project object */;
1919
proxyType = 1;
20-
remoteGlobalIDString = WIDGETTARGET;
20+
remoteGlobalIDString = AC785F8C97E63874BBA3DA5A;
2121
remoteInfo = Usage4ClaudeWidgetExtension;
2222
};
2323
/* End PBXContainerItemProxy section */
2424

2525
/* Begin PBXCopyFilesBuildPhase section */
26-
WIDGETEMBED /* Embed Foundation Extensions */ = {
26+
EDF27352ADEFCA2E8F4DD6F3 /* Embed Foundation Extensions */ = {
2727
isa = PBXCopyFilesBuildPhase;
2828
buildActionMask = 2147483647;
2929
dstPath = "";
3030
dstSubfolderSpec = 13;
3131
files = (
32-
WIDGET004 /* Usage4ClaudeWidgetExtension.appex in Embed Foundation Extensions */,
32+
E22FCD122AD18CF56501A4A2 /* Usage4ClaudeWidgetExtension.appex in Embed Foundation Extensions */,
3333
);
3434
name = "Embed Foundation Extensions";
3535
runOnlyForDeploymentPostprocessing = 0;
@@ -38,9 +38,9 @@
3838

3939
/* Begin PBXFileReference section */
4040
8873E4CF2E9F61C700ACFF5C /* Usage4Claude.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Usage4Claude.app; sourceTree = BUILT_PRODUCTS_DIR; };
41-
WIDGET000 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
42-
WIDGET003 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
43-
WIDGETPROD /* Usage4ClaudeWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Usage4ClaudeWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
41+
334DEEC8C0AF87D7AE76764D /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
42+
7A87739911B7B81D7B91F6F3 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
43+
068039FD2F82B5A332FAC8C7 /* Usage4ClaudeWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Usage4ClaudeWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
4444
/* End PBXFileReference section */
4545

4646
/* Begin PBXFileSystemSynchronizedRootGroup section */
@@ -49,7 +49,7 @@
4949
path = Usage4Claude;
5050
sourceTree = "<group>";
5151
};
52-
WIDGETGRP /* Usage4ClaudeWidget */ = {
52+
E13350EACE2EC0906F5703CB /* Usage4ClaudeWidget */ = {
5353
isa = PBXFileSystemSynchronizedRootGroup;
5454
path = Usage4ClaudeWidget;
5555
sourceTree = "<group>";
@@ -64,12 +64,12 @@
6464
);
6565
runOnlyForDeploymentPostprocessing = 0;
6666
};
67-
WIDGETFWK /* Frameworks */ = {
67+
C7DFE2691DD0776179DE5342 /* Frameworks */ = {
6868
isa = PBXFrameworksBuildPhase;
6969
buildActionMask = 2147483647;
7070
files = (
71-
WIDGET002 /* SwiftUI.framework in Frameworks */,
72-
WIDGET001 /* WidgetKit.framework in Frameworks */,
71+
554B23CF9491AD6219F536A2 /* SwiftUI.framework in Frameworks */,
72+
851F88B1F6CCE36B8296DBF6 /* WidgetKit.framework in Frameworks */,
7373
);
7474
runOnlyForDeploymentPostprocessing = 0;
7575
};
@@ -80,8 +80,8 @@
8080
isa = PBXGroup;
8181
children = (
8282
8873E4D12E9F61C700ACFF5C /* Usage4Claude */,
83-
WIDGETGRP /* Usage4ClaudeWidget */,
84-
FWKGROUP /* Frameworks */,
83+
E13350EACE2EC0906F5703CB /* Usage4ClaudeWidget */,
84+
857E8F82DC96DD5A2D5BF4DC /* Frameworks */,
8585
8873E4D02E9F61C700ACFF5C /* Products */,
8686
);
8787
sourceTree = "<group>";
@@ -90,16 +90,16 @@
9090
isa = PBXGroup;
9191
children = (
9292
8873E4CF2E9F61C700ACFF5C /* Usage4Claude.app */,
93-
WIDGETPROD /* Usage4ClaudeWidgetExtension.appex */,
93+
068039FD2F82B5A332FAC8C7 /* Usage4ClaudeWidgetExtension.appex */,
9494
);
9595
name = Products;
9696
sourceTree = "<group>";
9797
};
98-
FWKGROUP /* Frameworks */ = {
98+
857E8F82DC96DD5A2D5BF4DC /* Frameworks */ = {
9999
isa = PBXGroup;
100100
children = (
101-
WIDGET000 /* WidgetKit.framework */,
102-
WIDGET003 /* SwiftUI.framework */,
101+
334DEEC8C0AF87D7AE76764D /* WidgetKit.framework */,
102+
7A87739911B7B81D7B91F6F3 /* SwiftUI.framework */,
103103
);
104104
name = Frameworks;
105105
sourceTree = "<group>";
@@ -114,12 +114,12 @@
114114
8873E4CB2E9F61C700ACFF5C /* Sources */,
115115
8873E4CC2E9F61C700ACFF5C /* Frameworks */,
116116
8873E4CD2E9F61C700ACFF5C /* Resources */,
117-
WIDGETEMBED /* Embed Foundation Extensions */,
117+
EDF27352ADEFCA2E8F4DD6F3 /* Embed Foundation Extensions */,
118118
);
119119
buildRules = (
120120
);
121121
dependencies = (
122-
WIDGETDEP /* PBXTargetDependency */,
122+
7B5534E8B7E893AFDAAC2865 /* PBXTargetDependency */,
123123
);
124124
fileSystemSynchronizedGroups = (
125125
8873E4D12E9F61C700ACFF5C /* Usage4Claude */,
@@ -131,26 +131,26 @@
131131
productReference = 8873E4CF2E9F61C700ACFF5C /* Usage4Claude.app */;
132132
productType = "com.apple.product-type.application";
133133
};
134-
WIDGETTARGET /* Usage4ClaudeWidgetExtension */ = {
134+
AC785F8C97E63874BBA3DA5A /* Usage4ClaudeWidgetExtension */ = {
135135
isa = PBXNativeTarget;
136-
buildConfigurationList = WIDGETCFGLIST /* Build configuration list for PBXNativeTarget "Usage4ClaudeWidgetExtension" */;
136+
buildConfigurationList = 33E59AEB0BA46DD3E4735F70 /* Build configuration list for PBXNativeTarget "Usage4ClaudeWidgetExtension" */;
137137
buildPhases = (
138-
WIDGETSRC /* Sources */,
139-
WIDGETFWK /* Frameworks */,
140-
WIDGETRES /* Resources */,
138+
17F20B7601A9B790253FDF5D /* Sources */,
139+
C7DFE2691DD0776179DE5342 /* Frameworks */,
140+
B4698622C34BA37D25D24614 /* Resources */,
141141
);
142142
buildRules = (
143143
);
144144
dependencies = (
145145
);
146146
fileSystemSynchronizedGroups = (
147-
WIDGETGRP /* Usage4ClaudeWidget */,
147+
E13350EACE2EC0906F5703CB /* Usage4ClaudeWidget */,
148148
);
149149
name = Usage4ClaudeWidgetExtension;
150150
packageProductDependencies = (
151151
);
152152
productName = Usage4ClaudeWidgetExtension;
153-
productReference = WIDGETPROD /* Usage4ClaudeWidgetExtension.appex */;
153+
productReference = 068039FD2F82B5A332FAC8C7 /* Usage4ClaudeWidgetExtension.appex */;
154154
productType = "com.apple.product-type.app-extension";
155155
};
156156
/* End PBXNativeTarget section */
@@ -167,7 +167,7 @@
167167
CreatedOnToolsVersion = 26.0.1;
168168
LastSwiftMigration = 2600;
169169
};
170-
WIDGETTARGET = {
170+
AC785F8C97E63874BBA3DA5A = {
171171
CreatedOnToolsVersion = 26.0.1;
172172
};
173173
};
@@ -191,7 +191,7 @@
191191
projectRoot = "";
192192
targets = (
193193
8873E4CE2E9F61C700ACFF5C /* Usage4Claude */,
194-
WIDGETTARGET /* Usage4ClaudeWidgetExtension */,
194+
AC785F8C97E63874BBA3DA5A /* Usage4ClaudeWidgetExtension */,
195195
);
196196
};
197197
/* End PBXProject section */
@@ -204,7 +204,7 @@
204204
);
205205
runOnlyForDeploymentPostprocessing = 0;
206206
};
207-
WIDGETRES /* Resources */ = {
207+
B4698622C34BA37D25D24614 /* Resources */ = {
208208
isa = PBXResourcesBuildPhase;
209209
buildActionMask = 2147483647;
210210
files = (
@@ -221,7 +221,7 @@
221221
);
222222
runOnlyForDeploymentPostprocessing = 0;
223223
};
224-
WIDGETSRC /* Sources */ = {
224+
17F20B7601A9B790253FDF5D /* Sources */ = {
225225
isa = PBXSourcesBuildPhase;
226226
buildActionMask = 2147483647;
227227
files = (
@@ -231,10 +231,10 @@
231231
/* End PBXSourcesBuildPhase section */
232232

233233
/* Begin PBXTargetDependency section */
234-
WIDGETDEP /* PBXTargetDependency */ = {
234+
7B5534E8B7E893AFDAAC2865 /* PBXTargetDependency */ = {
235235
isa = PBXTargetDependency;
236-
target = WIDGETTARGET /* Usage4ClaudeWidgetExtension */;
237-
targetProxy = WIDGETPROXY /* PBXContainerItemProxy */;
236+
target = AC785F8C97E63874BBA3DA5A /* Usage4ClaudeWidgetExtension */;
237+
targetProxy = 776710D32DDD1B75B1513839 /* PBXContainerItemProxy */;
238238
};
239239
/* End PBXTargetDependency section */
240240

@@ -372,14 +372,14 @@
372372
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
373373
CLANG_ENABLE_MODULES = YES;
374374
CODE_SIGN_ENTITLEMENTS = Usage4Claude/Usage4Claude.entitlements;
375-
CODE_SIGN_IDENTITY = "-";
376-
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
377-
CODE_SIGN_STYLE = Automatic;
375+
CODE_SIGN_IDENTITY = "Usage4Claude-CodeSigning";
376+
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Usage4Claude-CodeSigning";
377+
CODE_SIGN_STYLE = Manual;
378378
COMBINE_HIDPI_IMAGES = YES;
379379
CURRENT_PROJECT_VERSION = 1;
380380
DEAD_CODE_STRIPPING = YES;
381381
DEVELOPMENT_TEAM = "";
382-
ENABLE_APP_SANDBOX = NO;
382+
ENABLE_APP_SANDBOX = YES;
383383
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
384384
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
385385
ENABLE_PREVIEWS = YES;
@@ -400,7 +400,7 @@
400400
"$(inherited)",
401401
"@executable_path/../Frameworks",
402402
);
403-
MACOSX_DEPLOYMENT_TARGET = 13.0;
403+
MACOSX_DEPLOYMENT_TARGET = 14.0;
404404
MARKETING_VERSION = 2.6.0;
405405
PRODUCT_BUNDLE_IDENTIFIER = xyz.fi5h.Usage4Claude;
406406
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -424,14 +424,14 @@
424424
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
425425
CLANG_ENABLE_MODULES = YES;
426426
CODE_SIGN_ENTITLEMENTS = Usage4Claude/Usage4Claude.entitlements;
427-
CODE_SIGN_IDENTITY = "-";
428-
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
429-
CODE_SIGN_STYLE = Automatic;
427+
CODE_SIGN_IDENTITY = "Usage4Claude-CodeSigning";
428+
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Usage4Claude-CodeSigning";
429+
CODE_SIGN_STYLE = Manual;
430430
COMBINE_HIDPI_IMAGES = YES;
431431
CURRENT_PROJECT_VERSION = 1;
432432
DEAD_CODE_STRIPPING = YES;
433433
DEVELOPMENT_TEAM = "";
434-
ENABLE_APP_SANDBOX = NO;
434+
ENABLE_APP_SANDBOX = YES;
435435
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
436436
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
437437
ENABLE_PREVIEWS = YES;
@@ -452,7 +452,7 @@
452452
"$(inherited)",
453453
"@executable_path/../Frameworks",
454454
);
455-
MACOSX_DEPLOYMENT_TARGET = 13.0;
455+
MACOSX_DEPLOYMENT_TARGET = 14.0;
456456
MARKETING_VERSION = 2.6.0;
457457
PRODUCT_BUNDLE_IDENTIFIER = xyz.fi5h.Usage4Claude;
458458
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -468,20 +468,20 @@
468468
};
469469
name = Release;
470470
};
471-
WIDGETCFGDEBUG /* Debug */ = {
471+
41C5C227479EA406FC751007 /* Debug */ = {
472472
isa = XCBuildConfiguration;
473473
buildSettings = {
474474
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
475475
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
476476
CLANG_ENABLE_MODULES = YES;
477477
CODE_SIGN_ENTITLEMENTS = Usage4ClaudeWidget/Usage4ClaudeWidget.entitlements;
478-
CODE_SIGN_IDENTITY = "-";
479-
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
480-
CODE_SIGN_STYLE = Automatic;
478+
CODE_SIGN_IDENTITY = "Usage4Claude-CodeSigning";
479+
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Usage4Claude-CodeSigning";
480+
CODE_SIGN_STYLE = Manual;
481481
CURRENT_PROJECT_VERSION = 1;
482482
DEAD_CODE_STRIPPING = YES;
483483
DEVELOPMENT_TEAM = "";
484-
ENABLE_APP_SANDBOX = NO;
484+
ENABLE_APP_SANDBOX = YES;
485485
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
486486
GENERATE_INFOPLIST_FILE = YES;
487487
INFOPLIST_FILE = "";
@@ -508,20 +508,20 @@
508508
};
509509
name = Debug;
510510
};
511-
WIDGETCFGRELEASE /* Release */ = {
511+
EEFAEB934F1F424994C35C21 /* Release */ = {
512512
isa = XCBuildConfiguration;
513513
buildSettings = {
514514
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
515515
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
516516
CLANG_ENABLE_MODULES = YES;
517517
CODE_SIGN_ENTITLEMENTS = Usage4ClaudeWidget/Usage4ClaudeWidget.entitlements;
518-
CODE_SIGN_IDENTITY = "-";
519-
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
520-
CODE_SIGN_STYLE = Automatic;
518+
CODE_SIGN_IDENTITY = "Usage4Claude-CodeSigning";
519+
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Usage4Claude-CodeSigning";
520+
CODE_SIGN_STYLE = Manual;
521521
CURRENT_PROJECT_VERSION = 1;
522522
DEAD_CODE_STRIPPING = YES;
523523
DEVELOPMENT_TEAM = "";
524-
ENABLE_APP_SANDBOX = NO;
524+
ENABLE_APP_SANDBOX = YES;
525525
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
526526
GENERATE_INFOPLIST_FILE = YES;
527527
INFOPLIST_FILE = "";
@@ -568,11 +568,11 @@
568568
defaultConfigurationIsVisible = 0;
569569
defaultConfigurationName = Release;
570570
};
571-
WIDGETCFGLIST /* Build configuration list for PBXNativeTarget "Usage4ClaudeWidgetExtension" */ = {
571+
33E59AEB0BA46DD3E4735F70 /* Build configuration list for PBXNativeTarget "Usage4ClaudeWidgetExtension" */ = {
572572
isa = XCConfigurationList;
573573
buildConfigurations = (
574-
WIDGETCFGDEBUG /* Debug */,
575-
WIDGETCFGRELEASE /* Release */,
574+
41C5C227479EA406FC751007 /* Debug */,
575+
EEFAEB934F1F424994C35C21 /* Release */,
576576
);
577577
defaultConfigurationIsVisible = 0;
578578
defaultConfigurationName = Release;

Usage4Claude/Shared/SharedUsageData.swift

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -197,36 +197,23 @@ extension SharedUsageData {
197197
}
198198
}
199199

200-
// MARK: - File-based Storage (Local Development without App Groups)
200+
// MARK: - App Group Storage
201201

202202
extension SharedUsageData {
203-
private static let fileName = "SharedUsageData.json"
203+
private static let userDefaultsKey = "SharedUsageData"
204204

205-
/// Get shared storage URL accessible by both app and widget
206-
/// Uses a file in the user's Application Support directory
207-
private static var storageURL: URL? {
208-
// Use a shared location in user's home directory
209-
let homeDir = FileManager.default.homeDirectoryForCurrentUser
210-
let sharedDir = homeDir.appendingPathComponent(".Usage4Claude")
211-
212-
// Create directory if needed
213-
try? FileManager.default.createDirectory(at: sharedDir, withIntermediateDirectories: true)
214-
215-
return sharedDir.appendingPathComponent(fileName)
216-
}
217-
218-
/// Save to shared file
205+
/// Save to App Group UserDefaults
219206
func save() {
220-
guard let url = Self.storageURL else { return }
207+
guard let defaults = UserDefaults(suiteName: appGroupIdentifier) else { return }
221208
if let encoded = try? JSONEncoder().encode(self) {
222-
try? encoded.write(to: url)
209+
defaults.set(encoded, forKey: Self.userDefaultsKey)
223210
}
224211
}
225212

226-
/// Load from shared file
213+
/// Load from App Group UserDefaults
227214
static func load() -> SharedUsageData? {
228-
guard let url = storageURL,
229-
let data = try? Data(contentsOf: url),
215+
guard let defaults = UserDefaults(suiteName: appGroupIdentifier),
216+
let data = defaults.data(forKey: userDefaultsKey),
230217
let decoded = try? JSONDecoder().decode(SharedUsageData.self, from: data) else {
231218
return nil
232219
}

Usage4Claude/Usage4Claude.entitlements

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5-
<key>com.apple.security.files.user-selected.read-write</key>
6-
<true/>
5+
<key>com.apple.security.application-groups</key>
6+
<array>
7+
<string>group.xyz.fi5h.Usage4Claude</string>
8+
</array>
79
</dict>
810
</plist>

0 commit comments

Comments
 (0)