diff --git a/apps/macos/Sources/Clawdis/DeviceModelCatalog.swift b/apps/macos/Sources/Clawdis/DeviceModelCatalog.swift index 2e37088d3..d98895a51 100644 --- a/apps/macos/Sources/Clawdis/DeviceModelCatalog.swift +++ b/apps/macos/Sources/Clawdis/DeviceModelCatalog.swift @@ -7,6 +7,8 @@ struct DevicePresentation: Sendable { enum DeviceModelCatalog { private static let modelIdentifierToName: [String: String] = loadModelIdentifierToName() + private static let resourceBundle: Bundle? = locateResourceBundle() + private static let resourceSubdirectory = "DeviceModels" static func presentation(deviceFamily: String?, modelIdentifier: String?) -> DevicePresentation? { let family = (deviceFamily ?? "").trimmingCharacters(in: .whitespacesAndNewlines) @@ -104,13 +106,11 @@ enum DeviceModelCatalog { } private static func loadMapping(resourceName: String) -> [String: String] { - guard let url = Bundle.module.url( + guard let url = self.resourceBundle?.url( forResource: resourceName, withExtension: "json", - subdirectory: "DeviceModels") - else { - return [:] - } + subdirectory: self.resourceSubdirectory) + else { return [:] } do { let data = try Data(contentsOf: url) @@ -121,6 +121,45 @@ enum DeviceModelCatalog { } } + private static func locateResourceBundle() -> Bundle? { + if let bundle = self.bundleIfContainsDeviceModels(Bundle.main) { + return bundle + } + + if let resourceURL = Bundle.main.resourceURL { + if let enumerator = FileManager.default.enumerator( + at: resourceURL, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles]) { + for case let url as URL in enumerator { + guard url.pathExtension == "bundle" else { continue } + if let bundle = Bundle(url: url), + self.bundleIfContainsDeviceModels(bundle) != nil { + return bundle + } + } + } + } + + return nil + } + + private static func bundleIfContainsDeviceModels(_ bundle: Bundle) -> Bundle? { + if bundle.url( + forResource: "ios-device-identifiers", + withExtension: "json", + subdirectory: self.resourceSubdirectory) != nil { + return bundle + } + if bundle.url( + forResource: "mac-device-identifiers", + withExtension: "json", + subdirectory: self.resourceSubdirectory) != nil { + return bundle + } + return nil + } + private enum NameValue: Decodable { case string(String) case stringArray([String]) diff --git a/scripts/package-mac-app.sh b/scripts/package-mac-app.sh index 2ec2f6444..d80c4cd81 100755 --- a/scripts/package-mac-app.sh +++ b/scripts/package-mac-app.sh @@ -147,6 +147,10 @@ fi echo "🖼 Copying app icon" cp "$ROOT_DIR/apps/macos/Sources/Clawdis/Resources/Clawdis.icns" "$APP_ROOT/Contents/Resources/Clawdis.icns" +echo "📦 Copying device model resources" +rm -rf "$APP_ROOT/Contents/Resources/DeviceModels" +cp -R "$ROOT_DIR/apps/macos/Sources/Clawdis/Resources/DeviceModels" "$APP_ROOT/Contents/Resources/DeviceModels" + RELAY_DIR="$APP_ROOT/Contents/Resources/Relay" if [[ "${SKIP_GATEWAY_PACKAGE:-0}" != "1" ]]; then