expo-live-activity 0.1.0 → 0.2.0-alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +84 -19
  3. package/app.plugin.js +2 -0
  4. package/build/ExpoLiveActivityModule.d.ts +1 -8
  5. package/build/ExpoLiveActivityModule.d.ts.map +1 -1
  6. package/build/ExpoLiveActivityModule.js +2 -3
  7. package/build/ExpoLiveActivityModule.js.map +1 -1
  8. package/build/index.d.ts +36 -3
  9. package/build/index.d.ts.map +1 -1
  10. package/build/index.js +37 -5
  11. package/build/index.js.map +1 -1
  12. package/expo-module.config.json +3 -11
  13. package/ios/ExpoLiveActivity.podspec +1 -1
  14. package/ios/ExpoLiveActivityModule.swift +130 -38
  15. package/ios/LiveActivityAttributes.swift +32 -0
  16. package/ios-files/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  17. package/ios-files/Assets.xcassets/AppIcon.appiconset/Contents.json +35 -0
  18. package/ios-files/Assets.xcassets/Contents.json +6 -0
  19. package/ios-files/Assets.xcassets/WidgetBackground.colorset/Contents.json +11 -0
  20. package/ios-files/Color+hex.swift +37 -0
  21. package/ios-files/Info.plist +11 -0
  22. package/ios-files/LiveActivityBundle.swift +16 -0
  23. package/ios-files/LiveActivityLiveActivity.swift +142 -0
  24. package/ios-files/LiveActivityView.swift +73 -0
  25. package/package.json +15 -14
  26. package/plugin/build/index.d.ts +3 -0
  27. package/plugin/build/index.js +35 -0
  28. package/plugin/build/lib/getWidgetExtensionEntitlements.d.ts +3 -0
  29. package/plugin/build/lib/getWidgetExtensionEntitlements.js +16 -0
  30. package/plugin/build/lib/getWidgetFiles.d.ts +10 -0
  31. package/plugin/build/lib/getWidgetFiles.js +157 -0
  32. package/plugin/build/withConfig.d.ts +6 -0
  33. package/plugin/build/withConfig.js +54 -0
  34. package/plugin/build/withPodfile.d.ts +4 -0
  35. package/plugin/build/withPodfile.js +92 -0
  36. package/plugin/build/withWidgetExtensionEntitlements.d.ts +6 -0
  37. package/plugin/build/withWidgetExtensionEntitlements.js +56 -0
  38. package/plugin/build/withXcode.d.ts +6 -0
  39. package/plugin/build/withXcode.js +88 -0
  40. package/plugin/build/xcode/addBuildPhases.d.ts +13 -0
  41. package/plugin/build/xcode/addBuildPhases.js +57 -0
  42. package/plugin/build/xcode/addPbxGroup.d.ts +6 -0
  43. package/plugin/build/xcode/addPbxGroup.js +25 -0
  44. package/plugin/build/xcode/addProductFile.d.ts +5 -0
  45. package/plugin/build/xcode/addProductFile.js +21 -0
  46. package/plugin/build/xcode/addTargetDependency.d.ts +4 -0
  47. package/plugin/build/xcode/addTargetDependency.js +14 -0
  48. package/plugin/build/xcode/addToPbxNativeTargetSection.d.ts +24 -0
  49. package/plugin/build/xcode/addToPbxNativeTargetSection.js +29 -0
  50. package/plugin/build/xcode/addToPbxProjectSection.d.ts +4 -0
  51. package/plugin/build/xcode/addToPbxProjectSection.js +14 -0
  52. package/plugin/build/xcode/addXCConfigurationList.d.ts +8 -0
  53. package/plugin/build/xcode/addXCConfigurationList.js +61 -0
  54. package/plugin/src/index.ts +43 -0
  55. package/plugin/src/lib/getWidgetExtensionEntitlements.ts +26 -0
  56. package/plugin/src/lib/getWidgetFiles.ts +149 -0
  57. package/plugin/src/withConfig.ts +62 -0
  58. package/plugin/src/withPodfile.ts +72 -0
  59. package/plugin/src/withWidgetExtensionEntitlements.ts +25 -0
  60. package/plugin/src/withXcode.ts +76 -0
  61. package/plugin/src/xcode/addBuildPhases.ts +83 -0
  62. package/plugin/src/xcode/addPbxGroup.ts +48 -0
  63. package/plugin/src/xcode/addProductFile.ts +25 -0
  64. package/plugin/src/xcode/addTargetDependency.ts +17 -0
  65. package/plugin/src/xcode/addToPbxNativeTargetSection.ts +46 -0
  66. package/plugin/src/xcode/addToPbxProjectSection.ts +23 -0
  67. package/plugin/src/xcode/addXCConfigurationList.ts +83 -0
  68. package/plugin/tsconfig.json +9 -0
  69. package/plugin/tsconfig.tsbuildinfo +1 -0
  70. package/src/ExpoLiveActivityModule.ts +2 -11
  71. package/src/index.ts +59 -5
  72. package/android/build.gradle +0 -43
  73. package/android/src/main/AndroidManifest.xml +0 -2
  74. package/android/src/main/java/expo/modules/liveactivity/ExpoLiveActivityModule.kt +0 -50
  75. package/android/src/main/java/expo/modules/liveactivity/ExpoLiveActivityView.kt +0 -30
  76. package/build/ExpoLiveActivity.types.d.ts +0 -18
  77. package/build/ExpoLiveActivity.types.d.ts.map +0 -1
  78. package/build/ExpoLiveActivity.types.js +0 -2
  79. package/build/ExpoLiveActivity.types.js.map +0 -1
  80. package/build/ExpoLiveActivityModule.web.d.ts +0 -10
  81. package/build/ExpoLiveActivityModule.web.d.ts.map +0 -1
  82. package/build/ExpoLiveActivityModule.web.js +0 -12
  83. package/build/ExpoLiveActivityModule.web.js.map +0 -1
  84. package/build/ExpoLiveActivityView.d.ts +0 -4
  85. package/build/ExpoLiveActivityView.d.ts.map +0 -1
  86. package/build/ExpoLiveActivityView.js +0 -7
  87. package/build/ExpoLiveActivityView.js.map +0 -1
  88. package/build/ExpoLiveActivityView.web.d.ts +0 -4
  89. package/build/ExpoLiveActivityView.web.d.ts.map +0 -1
  90. package/build/ExpoLiveActivityView.web.js +0 -7
  91. package/build/ExpoLiveActivityView.web.js.map +0 -1
  92. package/ios/ExpoLiveActivityView.swift +0 -38
  93. package/src/ExpoLiveActivity.types.ts +0 -19
  94. package/src/ExpoLiveActivityModule.web.ts +0 -15
  95. package/src/ExpoLiveActivityView.tsx +0 -11
  96. package/src/ExpoLiveActivityView.web.tsx +0 -15
@@ -0,0 +1,149 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+
4
+ export type WidgetFiles = {
5
+ swiftFiles: string[];
6
+ entitlementFiles: string[];
7
+ plistFiles: string[];
8
+ assetDirectories: string[];
9
+ intentFiles: string[];
10
+ otherFiles: string[];
11
+ };
12
+
13
+ export function getWidgetFiles(
14
+ targetPath: string,
15
+ ) {
16
+ let packagePath
17
+ try {
18
+ packagePath = path.dirname(require.resolve("expo-live-activity/package.json"));
19
+ } catch {
20
+ console.log("Building for example app")
21
+ }
22
+ const liveActivityFilesPath = path.join(packagePath ? packagePath : "..", "/ios-files");
23
+ const imageAssetsPath = "./assets/live_activity";
24
+
25
+ const widgetFiles: WidgetFiles = {
26
+ swiftFiles: [],
27
+ entitlementFiles: [],
28
+ plistFiles: [],
29
+ assetDirectories: [],
30
+ intentFiles: [],
31
+ otherFiles: [],
32
+ };
33
+
34
+ if (!fs.existsSync(targetPath)) {
35
+ fs.mkdirSync(targetPath, { recursive: true });
36
+ }
37
+
38
+ if (fs.lstatSync(liveActivityFilesPath).isDirectory()) {
39
+ const files = fs.readdirSync(liveActivityFilesPath);
40
+
41
+ files.forEach((file) => {
42
+ const fileExtension = file.split(".").pop();
43
+
44
+ if (fileExtension === "swift") {
45
+ widgetFiles.swiftFiles.push(file);
46
+ } else if (fileExtension === "entitlements") {
47
+ widgetFiles.entitlementFiles.push(file);
48
+ } else if (fileExtension === "plist") {
49
+ widgetFiles.plistFiles.push(file);
50
+ } else if (fileExtension === "xcassets") {
51
+ widgetFiles.assetDirectories.push(file);
52
+ } else if (fileExtension === "intentdefinition") {
53
+ widgetFiles.intentFiles.push(file);
54
+ } else {
55
+ widgetFiles.otherFiles.push(file);
56
+ }
57
+ });
58
+
59
+ }
60
+
61
+ // Copy files
62
+ [
63
+ ...widgetFiles.swiftFiles,
64
+ ...widgetFiles.entitlementFiles,
65
+ ...widgetFiles.plistFiles,
66
+ ...widgetFiles.intentFiles,
67
+ ...widgetFiles.otherFiles,
68
+ ].forEach((file) => {
69
+ const source = path.join(liveActivityFilesPath, file);
70
+ copyFileSync(source, targetPath);
71
+ });
72
+
73
+ // Copy assets directory
74
+ const imagesXcassetsSource = path.join(liveActivityFilesPath, "Assets.xcassets");
75
+ copyFolderRecursiveSync(imagesXcassetsSource, targetPath);
76
+
77
+ // Move images to assets directory
78
+ if (fs.lstatSync(imageAssetsPath).isDirectory()) {
79
+ const imagesXcassetsTarget = path.join(targetPath, "Assets.xcassets");
80
+
81
+ const files = fs.readdirSync(imageAssetsPath);
82
+
83
+ files.forEach((file) => {
84
+ if (path.extname(file).match(/\.(png|jpg|jpeg)$/)) {
85
+ const source = path.join(imageAssetsPath, file);
86
+ const imageSetDir = path.join(imagesXcassetsTarget, `${path.basename(file, path.extname(file))}.imageset`);
87
+
88
+ // Create the .imageset directory if it doesn't exist
89
+ if (!fs.existsSync(imageSetDir)) {
90
+ fs.mkdirSync(imageSetDir, { recursive: true });
91
+ }
92
+
93
+ // Copy image file to the .imageset directory
94
+ const destPath = path.join(imageSetDir, file);
95
+ fs.copyFileSync(source, destPath);
96
+
97
+ // Create Contents.json file
98
+ const contentsJson = {
99
+ images: [
100
+ {
101
+ filename : file,
102
+ idiom : "universal"
103
+ }
104
+ ],
105
+ info: {
106
+ author : "xcode",
107
+ version : 1
108
+ }
109
+ };
110
+
111
+ fs.writeFileSync(
112
+ path.join(imageSetDir, 'Contents.json'),
113
+ JSON.stringify(contentsJson, null, 2)
114
+ );
115
+ }
116
+ })
117
+ }
118
+
119
+ return widgetFiles;
120
+ }
121
+
122
+ export function copyFileSync(source: string, target: string) {
123
+ let targetFile = target;
124
+
125
+ if (fs.existsSync(target) && fs.lstatSync(target).isDirectory()) {
126
+ targetFile = path.join(target, path.basename(source));
127
+ }
128
+
129
+ fs.writeFileSync(targetFile, fs.readFileSync(source));
130
+ }
131
+
132
+ function copyFolderRecursiveSync(source: string, target: string) {
133
+ const targetPath = path.join(target, path.basename(source));
134
+ if (!fs.existsSync(targetPath)) {
135
+ fs.mkdirSync(targetPath, { recursive: true });
136
+ }
137
+
138
+ if (fs.lstatSync(source).isDirectory()) {
139
+ const files = fs.readdirSync(source);
140
+ files.forEach((file) => {
141
+ const currentPath = path.join(source, file);
142
+ if (fs.lstatSync(currentPath).isDirectory()) {
143
+ copyFolderRecursiveSync(currentPath, targetPath);
144
+ } else {
145
+ copyFileSync(currentPath, targetPath);
146
+ }
147
+ });
148
+ }
149
+ }
@@ -0,0 +1,62 @@
1
+ import { ConfigPlugin } from "@expo/config-plugins";
2
+
3
+ import { addApplicationGroupsEntitlement, getWidgetExtensionEntitlements } from "./lib/getWidgetExtensionEntitlements";
4
+
5
+ export const withConfig: ConfigPlugin<{
6
+ bundleIdentifier: string;
7
+ targetName: string;
8
+ groupIdentifier?: string;
9
+ }> = (config, { bundleIdentifier, targetName, groupIdentifier }) => {
10
+ let configIndex: null | number = null;
11
+ config.extra?.eas?.build?.experimental?.ios?.appExtensions?.forEach((ext: any, index: number) => {
12
+ if (ext.targetName === targetName) {
13
+ configIndex = index;
14
+ }
15
+ });
16
+
17
+ if (!configIndex) {
18
+ config.extra = {
19
+ ...config.extra,
20
+ eas: {
21
+ ...config.extra?.eas,
22
+ build: {
23
+ ...config.extra?.eas?.build,
24
+ experimental: {
25
+ ...config.extra?.eas?.build?.experimental,
26
+ ios: {
27
+ ...config.extra?.eas?.build?.experimental?.ios,
28
+ appExtensions: [
29
+ ...(config.extra?.eas?.build?.experimental?.ios?.appExtensions ?? []),
30
+ {
31
+ targetName,
32
+ bundleIdentifier,
33
+ },
34
+ ],
35
+ },
36
+ },
37
+ },
38
+ },
39
+ };
40
+ configIndex = 0;
41
+ }
42
+
43
+ if (configIndex != null && config.extra) {
44
+ const widgetsExtensionConfig = config.extra.eas.build.experimental.ios.appExtensions[configIndex];
45
+
46
+ widgetsExtensionConfig.entitlements = {
47
+ ...widgetsExtensionConfig.entitlements,
48
+ ...getWidgetExtensionEntitlements(config.ios, {
49
+ groupIdentifier,
50
+ }),
51
+ };
52
+
53
+ config.ios = {
54
+ ...config.ios,
55
+ entitlements: {
56
+ ...addApplicationGroupsEntitlement(config.ios?.entitlements ?? {}, groupIdentifier),
57
+ },
58
+ };
59
+ }
60
+
61
+ return config;
62
+ };
@@ -0,0 +1,72 @@
1
+ import { mergeContents } from "@expo/config-plugins/build/utils/generateCode";
2
+ import { ConfigPlugin, withDangerousMod } from "@expo/config-plugins";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+
6
+ export const withPodfile: ConfigPlugin<{ targetName: string }> = (
7
+ config,
8
+ { targetName }
9
+ ) => {
10
+ return withDangerousMod(config, [
11
+ "ios",
12
+ (config) => {
13
+ const podFilePath = path.join(
14
+ config.modRequest.platformProjectRoot,
15
+ "Podfile"
16
+ );
17
+ let podFileContent = fs.readFileSync(podFilePath).toString();
18
+
19
+ /* podFileContent = mergeContents({
20
+ tag: "withWidgetExtensionPodfile1999999999",
21
+ src: podFileContent,
22
+ newSrc: ` target '${targetName}' do\n \n end`,
23
+ anchor: /post_install/,
24
+ offset: 0,
25
+ comment: "#",
26
+ }).contents; */
27
+
28
+ /* podFileContent = podFileContent.replace(
29
+ /use_expo_modules!/,
30
+ `use_expo_modules!(searchPaths: ["./node_modules", "../../node_modules", "../../../WidgetExtension"])`
31
+ ); */
32
+
33
+ podFileContent = mergeContents({
34
+ tag: "react-native-widget-extension-1",
35
+ src: podFileContent,
36
+ newSrc: `installer.pods_project.targets.each do |target|
37
+ target.build_configurations.each do |config|
38
+ # Sentry has build errors unless configured as 'YES' for the Sentry target: https://github.com/bndkt/react-native-widget-extension/issues/24
39
+ config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = target.name == 'Sentry' ? 'YES' : 'No'
40
+ end
41
+ end`,
42
+ anchor:
43
+ /installer.target_installation_results.pod_target_installation_results/,
44
+ offset: 0,
45
+ comment: "#",
46
+ }).contents;
47
+
48
+ /* podFileContent = mergeContents({
49
+ tag: "react-native-widget-extension-2",
50
+ src: podFileContent,
51
+ newSrc: `pod 'WidgetExtension', :path => '../WidgetExtension/ios'`,
52
+ anchor: /use_react_native/,
53
+ offset: -1,
54
+ comment: "#",
55
+ }).contents; */
56
+
57
+ podFileContent = podFileContent
58
+ .concat(`\n\n# >>> Inserted by react-native-widget-extension\n`)
59
+ .concat(
60
+ `target '${targetName}' do
61
+ use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
62
+ use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
63
+ end`
64
+ )
65
+ .concat(`\n# >>> Inserted by react-native-widget-extension`);
66
+
67
+ fs.writeFileSync(podFilePath, podFileContent);
68
+
69
+ return config;
70
+ },
71
+ ]);
72
+ };
@@ -0,0 +1,25 @@
1
+ import plist from "@expo/plist";
2
+ import { ConfigPlugin, withInfoPlist } from "@expo/config-plugins";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+
6
+ // import { getWidgetExtensionEntitlements } from "./lib/getWidgetExtensionEntitlements";
7
+
8
+ export const withWidgetExtensionEntitlements: ConfigPlugin<{
9
+ targetName: string;
10
+ targetPath: string;
11
+ // groupIdentifier: string;
12
+ appleSignin: boolean;
13
+ }> = (config, { targetName }) => {
14
+ return withInfoPlist(config, (config) => {
15
+ const targetPath = path.join(config.modRequest.platformProjectRoot, targetName);
16
+ const filePath = path.join(targetPath, `${targetName}.entitlements`);
17
+
18
+ // const appClipEntitlements = getWidgetExtensionEntitlements(config.ios, {
19
+ // });
20
+
21
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
22
+ fs.writeFileSync(filePath, plist.build({}));
23
+ return config;
24
+ });
25
+ };
@@ -0,0 +1,76 @@
1
+ import { ConfigPlugin, withXcodeProject } from "@expo/config-plugins";
2
+ import * as path from "path";
3
+
4
+ import { addXCConfigurationList } from "./xcode/addXCConfigurationList";
5
+ import { addProductFile } from "./xcode/addProductFile";
6
+ import { addToPbxNativeTargetSection } from "./xcode/addToPbxNativeTargetSection";
7
+ import { addToPbxProjectSection } from "./xcode/addToPbxProjectSection";
8
+ import { addTargetDependency } from "./xcode/addTargetDependency";
9
+ import { addPbxGroup } from "./xcode/addPbxGroup";
10
+ import { addBuildPhases } from "./xcode/addBuildPhases";
11
+ import { getWidgetFiles } from "./lib/getWidgetFiles";
12
+
13
+ export const withXcode: ConfigPlugin<{
14
+ targetName: string;
15
+ bundleIdentifier: string;
16
+ deploymentTarget: string;
17
+ }> = (
18
+ config,
19
+ {
20
+ targetName,
21
+ bundleIdentifier,
22
+ deploymentTarget,
23
+ }
24
+ ) => {
25
+ return withXcodeProject(config, (config) => {
26
+ const xcodeProject = config.modResults;
27
+ const targetUuid = xcodeProject.generateUuid();
28
+ const groupName = "Embed Foundation Extensions";
29
+ const { platformProjectRoot } = config.modRequest;
30
+ const marketingVersion = config.version;
31
+
32
+ const targetPath = path.join(platformProjectRoot, targetName);
33
+
34
+ const widgetFiles = getWidgetFiles(
35
+ targetPath,
36
+ );
37
+
38
+ const xCConfigurationList = addXCConfigurationList(xcodeProject, {
39
+ targetName,
40
+ currentProjectVersion: config.ios!.buildNumber || "1",
41
+ bundleIdentifier,
42
+ deploymentTarget,
43
+ marketingVersion,
44
+ });
45
+
46
+ const productFile = addProductFile(xcodeProject, {
47
+ targetName,
48
+ groupName,
49
+ });
50
+
51
+ const target = addToPbxNativeTargetSection(xcodeProject, {
52
+ targetName,
53
+ targetUuid,
54
+ productFile,
55
+ xCConfigurationList,
56
+ });
57
+
58
+ addToPbxProjectSection(xcodeProject, target);
59
+
60
+ addTargetDependency(xcodeProject, target);
61
+
62
+ addBuildPhases(xcodeProject, {
63
+ targetUuid,
64
+ groupName,
65
+ productFile,
66
+ widgetFiles,
67
+ });
68
+
69
+ addPbxGroup(xcodeProject, {
70
+ targetName,
71
+ widgetFiles,
72
+ });
73
+
74
+ return config;
75
+ });
76
+ };
@@ -0,0 +1,83 @@
1
+ import { XcodeProject } from "@expo/config-plugins";
2
+ import * as util from "util";
3
+
4
+ import { WidgetFiles } from "../lib/getWidgetFiles";
5
+
6
+ export function addBuildPhases(
7
+ xcodeProject: XcodeProject,
8
+ {
9
+ targetUuid,
10
+ groupName,
11
+ productFile,
12
+ widgetFiles,
13
+ }: {
14
+ targetUuid: string;
15
+ groupName: string;
16
+ productFile: {
17
+ uuid: string;
18
+ target: string;
19
+ basename: string;
20
+ group: string;
21
+ };
22
+ widgetFiles: WidgetFiles;
23
+ }
24
+ ) {
25
+ const buildPath = `""`;
26
+ const folderType = "app_extension";
27
+
28
+ const {
29
+ swiftFiles,
30
+ intentFiles,
31
+ assetDirectories,
32
+ entitlementFiles,
33
+ plistFiles,
34
+ } = widgetFiles;
35
+
36
+ // Sources build phase
37
+ xcodeProject.addBuildPhase(
38
+ [...swiftFiles, ...intentFiles],
39
+ "PBXSourcesBuildPhase",
40
+ groupName,
41
+ targetUuid,
42
+ folderType,
43
+ buildPath
44
+ );
45
+
46
+ // Copy files build phase
47
+ xcodeProject.addBuildPhase(
48
+ [],
49
+ "PBXCopyFilesBuildPhase",
50
+ groupName,
51
+ xcodeProject.getFirstTarget().uuid,
52
+ folderType,
53
+ buildPath
54
+ );
55
+
56
+ xcodeProject
57
+ .buildPhaseObject("PBXCopyFilesBuildPhase", groupName, productFile.target)
58
+ .files.push({
59
+ value: productFile.uuid,
60
+ comment: util.format("%s in %s", productFile.basename, productFile.group), // longComment(file);
61
+ });
62
+ xcodeProject.addToPbxBuildFileSection(productFile);
63
+
64
+ // Frameworks build phase
65
+ xcodeProject.addBuildPhase(
66
+ [],
67
+ "PBXFrameworksBuildPhase",
68
+ groupName,
69
+ targetUuid,
70
+ folderType,
71
+ buildPath
72
+ );
73
+
74
+ // Resources build phase
75
+ xcodeProject.addBuildPhase(
76
+ [...assetDirectories],
77
+ "PBXResourcesBuildPhase",
78
+ groupName,
79
+ targetUuid,
80
+ folderType,
81
+ buildPath
82
+ );
83
+ }
@@ -0,0 +1,48 @@
1
+ import { XcodeProject } from "@expo/config-plugins";
2
+
3
+ import { WidgetFiles } from "../lib/getWidgetFiles";
4
+
5
+ export function addPbxGroup(
6
+ xcodeProject: XcodeProject,
7
+ {
8
+ targetName,
9
+ widgetFiles,
10
+ }: {
11
+ targetName: string;
12
+ widgetFiles: WidgetFiles;
13
+ }
14
+ ) {
15
+ const {
16
+ swiftFiles,
17
+ intentFiles,
18
+ otherFiles,
19
+ assetDirectories,
20
+ entitlementFiles,
21
+ plistFiles,
22
+ } = widgetFiles;
23
+
24
+ // Add PBX group
25
+ const { uuid: pbxGroupUuid } = xcodeProject.addPbxGroup(
26
+ [
27
+ ...swiftFiles,
28
+ ...intentFiles,
29
+ ...otherFiles,
30
+ ...entitlementFiles,
31
+ ...plistFiles,
32
+ ...assetDirectories,
33
+ `${targetName}.entitlements`,
34
+ ],
35
+ targetName,
36
+ targetName
37
+ );
38
+
39
+ // Add PBXGroup to top level group
40
+ const groups = xcodeProject.hash.project.objects["PBXGroup"];
41
+ if (pbxGroupUuid) {
42
+ Object.keys(groups).forEach(function (key) {
43
+ if (groups[key].name === undefined && groups[key].path === undefined) {
44
+ xcodeProject.addToPbxGroup(pbxGroupUuid, key);
45
+ }
46
+ });
47
+ }
48
+ }
@@ -0,0 +1,25 @@
1
+ import { XcodeProject } from "@expo/config-plugins";
2
+
3
+ export function addProductFile(
4
+ xcodeProject: XcodeProject,
5
+ { targetName, groupName }: { targetName: string; groupName: string }
6
+ ) {
7
+ const options = {
8
+ basename: `${targetName}.appex`,
9
+ // fileRef: xcodeProject.generateUuid(),
10
+ // uuid: xcodeProject.generateUuid(),
11
+ group: groupName,
12
+ explicitFileType: "wrapper.app-extension",
13
+ /* fileEncoding: 4, */
14
+ settings: {
15
+ ATTRIBUTES: ["RemoveHeadersOnCopy"],
16
+ },
17
+ includeInIndex: 0,
18
+ path: `${targetName}.appex`,
19
+ sourceTree: "BUILT_PRODUCTS_DIR",
20
+ };
21
+
22
+ const productFile = xcodeProject.addProductFile(targetName, options);
23
+
24
+ return productFile;
25
+ }
@@ -0,0 +1,17 @@
1
+ import { XcodeProject } from "@expo/config-plugins";
2
+
3
+ export function addTargetDependency(
4
+ xcodeProject: XcodeProject,
5
+ target: { uuid: string }
6
+ ) {
7
+ if (!xcodeProject.hash.project.objects["PBXTargetDependency"]) {
8
+ xcodeProject.hash.project.objects["PBXTargetDependency"] = {};
9
+ }
10
+ if (!xcodeProject.hash.project.objects["PBXContainerItemProxy"]) {
11
+ xcodeProject.hash.project.objects["PBXContainerItemProxy"] = {};
12
+ }
13
+
14
+ xcodeProject.addTargetDependency(xcodeProject.getFirstTarget().uuid, [
15
+ target.uuid,
16
+ ]);
17
+ }
@@ -0,0 +1,46 @@
1
+ import { XcodeProject } from "@expo/config-plugins";
2
+
3
+ export function addToPbxNativeTargetSection(
4
+ xcodeProject: XcodeProject,
5
+ {
6
+ targetName,
7
+ targetUuid,
8
+ productFile,
9
+ xCConfigurationList,
10
+ }: {
11
+ targetName: string;
12
+ targetUuid: string;
13
+ productFile: { fileRef: string };
14
+ xCConfigurationList: { uuid: string };
15
+ }
16
+ ) {
17
+ const target = {
18
+ uuid: targetUuid,
19
+ pbxNativeTarget: {
20
+ isa: "PBXNativeTarget",
21
+ name: targetName,
22
+ productName: targetName,
23
+ productReference: productFile.fileRef,
24
+ productType: `"com.apple.product-type.app-extension"`,
25
+ buildConfigurationList: xCConfigurationList.uuid,
26
+ buildPhases: [],
27
+ buildRules: [],
28
+ dependencies: [],
29
+ },
30
+ };
31
+
32
+ xcodeProject.addToPbxNativeTargetSection(target);
33
+
34
+ const frameworksGroup = xcodeProject.findPBXGroupKey({ name: "Frameworks" });
35
+ const file1 = xcodeProject.addFile("WidgetKit.framework", frameworksGroup);
36
+ const file2 = xcodeProject.addFile("SwiftUI.framework", frameworksGroup);
37
+ const frameworksBuildPhaseObj = xcodeProject.pbxFrameworksBuildPhaseObj(
38
+ target.uuid
39
+ );
40
+ /* console.log(
41
+ { file1, file2, frameworksBuildPhaseObj },
42
+ frameworksBuildPhaseObj.files
43
+ ); */
44
+
45
+ return target;
46
+ }
@@ -0,0 +1,23 @@
1
+ import { XcodeProject } from "@expo/config-plugins";
2
+
3
+ export function addToPbxProjectSection(
4
+ xcodeProject: XcodeProject,
5
+ target: { uuid: string }
6
+ ) {
7
+ xcodeProject.addToPbxProjectSection(target);
8
+
9
+ // Add target attributes to project section
10
+ if (
11
+ !xcodeProject.pbxProjectSection()[xcodeProject.getFirstProject().uuid]
12
+ .attributes.TargetAttributes
13
+ ) {
14
+ xcodeProject.pbxProjectSection()[
15
+ xcodeProject.getFirstProject().uuid
16
+ ].attributes.TargetAttributes = {};
17
+ }
18
+ xcodeProject.pbxProjectSection()[
19
+ xcodeProject.getFirstProject().uuid
20
+ ].attributes.TargetAttributes[target.uuid] = {
21
+ LastSwiftMigration: 1250,
22
+ };
23
+ }