expo-live-activity 0.1.0 → 0.2.0-alpha

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 +13 -14
  26. package/plugin/build/index.d.ts +3 -0
  27. package/plugin/build/index.js +40 -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 +172 -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 +57 -0
  38. package/plugin/build/withXcode.d.ts +8 -0
  39. package/plugin/build/withXcode.js +99 -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 +49 -0
  55. package/plugin/src/lib/getWidgetExtensionEntitlements.ts +26 -0
  56. package/plugin/src/lib/getWidgetFiles.ts +162 -0
  57. package/plugin/src/withConfig.ts +62 -0
  58. package/plugin/src/withPodfile.ts +72 -0
  59. package/plugin/src/withWidgetExtensionEntitlements.ts +26 -0
  60. package/plugin/src/withXcode.ts +93 -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,162 @@
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
+ // widgetsPath: string, // to zmieniamy, bo u nas to będzie "config.modRequest.projectRoot/[tu może coś jeszcze być]/node_modules/nasz-moduł/iosViews"
15
+ targetPath: string,
16
+ moduleFileName: string,
17
+ attributesFileName: string
18
+ ) {
19
+ let packagePath
20
+ try {
21
+ packagePath = path.dirname(require.resolve("expo-live-activity/package.json"));
22
+ } catch {
23
+ console.log("Building for example app")
24
+ }
25
+ const widgetsPath = path.join(packagePath ? packagePath : "..", "/ios-files");
26
+ console.log(`Widgets path: ${widgetsPath}`);
27
+ const imageAssetsPath = "./assets/live_activity";
28
+ const widgetFiles: WidgetFiles = {
29
+ swiftFiles: [],
30
+ entitlementFiles: [],
31
+ plistFiles: [],
32
+ assetDirectories: [],
33
+ intentFiles: [],
34
+ otherFiles: [],
35
+ };
36
+ console.log(`Getting widget files`)
37
+ if (!fs.existsSync(targetPath)) {
38
+ console.log(`Making directory at: ${targetPath}`)
39
+ fs.mkdirSync(targetPath, { recursive: true });
40
+ }
41
+
42
+ if (fs.lstatSync(widgetsPath).isDirectory()) {
43
+ const files = fs.readdirSync(widgetsPath);
44
+ console.log(`Files: ${files}`)
45
+
46
+ files.forEach((file) => {
47
+ const fileExtension = file.split(".").pop();
48
+
49
+ if (fileExtension === "swift") {
50
+ if (file !== moduleFileName) {
51
+ widgetFiles.swiftFiles.push(file);
52
+ }
53
+ } else if (fileExtension === "entitlements") {
54
+ widgetFiles.entitlementFiles.push(file);
55
+ } else if (fileExtension === "plist") {
56
+ widgetFiles.plistFiles.push(file);
57
+ } else if (fileExtension === "xcassets") {
58
+ widgetFiles.assetDirectories.push(file);
59
+ } else if (fileExtension === "intentdefinition") {
60
+ widgetFiles.intentFiles.push(file);
61
+ } else {
62
+ widgetFiles.otherFiles.push(file);
63
+ }
64
+ });
65
+
66
+ }
67
+
68
+ // Copy files
69
+ [
70
+ ...widgetFiles.swiftFiles,
71
+ ...widgetFiles.entitlementFiles,
72
+ ...widgetFiles.plistFiles,
73
+ ...widgetFiles.intentFiles,
74
+ ...widgetFiles.otherFiles,
75
+ ].forEach((file) => {
76
+ const source = path.join(widgetsPath, file);
77
+ copyFileSync(source, targetPath);
78
+ });
79
+
80
+ // Copy assets directory
81
+ const imagesXcassetsSource = path.join(widgetsPath, "Assets.xcassets");
82
+ copyFolderRecursiveSync(imagesXcassetsSource, targetPath);
83
+
84
+ // Move images to assets directory
85
+ console.log(`Images Path: ${imageAssetsPath}`)
86
+ if (fs.lstatSync(imageAssetsPath).isDirectory()) {
87
+ const imagesXcassetsTarget = path.join(targetPath, "Assets.xcassets");
88
+ console.log(`Assets Target: ${imagesXcassetsTarget}`)
89
+
90
+ const files = fs.readdirSync(imageAssetsPath);
91
+ console.log(`Images: ${files}`)
92
+ files.forEach((file) => {
93
+ if (path.extname(file).match(/\.(png|jpg|jpeg)$/)) {
94
+ const source = path.join(imageAssetsPath, file);
95
+ console.log(`Source: ${source}`)
96
+ const imageSetDir = path.join(imagesXcassetsTarget, `${path.basename(file, path.extname(file))}.imageset`);
97
+
98
+ console.log(`imageSetDir: ${source}`)
99
+ // Create the .imageset directory if it doesn't exist
100
+ if (!fs.existsSync(imageSetDir)) {
101
+ fs.mkdirSync(imageSetDir, { recursive: true });
102
+ }
103
+
104
+ // Copy image file to the .imageset directory
105
+ const destPath = path.join(imageSetDir, file);
106
+ fs.copyFileSync(source, destPath);
107
+
108
+ // Create Contents.json file
109
+ const contentsJson = {
110
+ images: [
111
+ {
112
+ filename : file,
113
+ idiom : "universal"
114
+ }
115
+ ],
116
+ info: {
117
+ author : "xcode",
118
+ version : 1
119
+ }
120
+ };
121
+
122
+ fs.writeFileSync(
123
+ path.join(imageSetDir, 'Contents.json'),
124
+ JSON.stringify(contentsJson, null, 2) // beautify the JSON output
125
+ );
126
+
127
+ console.log(`Processed ${file} into ${imageSetDir}`);
128
+ }
129
+ })
130
+ }
131
+
132
+ return widgetFiles;
133
+ }
134
+
135
+ export function copyFileSync(source: string, target: string) {
136
+ let targetFile = target;
137
+
138
+ if (fs.existsSync(target) && fs.lstatSync(target).isDirectory()) {
139
+ targetFile = path.join(target, path.basename(source));
140
+ }
141
+
142
+ fs.writeFileSync(targetFile, fs.readFileSync(source));
143
+ }
144
+
145
+ function copyFolderRecursiveSync(source: string, target: string) {
146
+ const targetPath = path.join(target, path.basename(source));
147
+ if (!fs.existsSync(targetPath)) {
148
+ fs.mkdirSync(targetPath, { recursive: true });
149
+ }
150
+
151
+ if (fs.lstatSync(source).isDirectory()) {
152
+ const files = fs.readdirSync(source);
153
+ files.forEach((file) => {
154
+ const currentPath = path.join(source, file);
155
+ if (fs.lstatSync(currentPath).isDirectory()) {
156
+ copyFolderRecursiveSync(currentPath, targetPath);
157
+ } else {
158
+ copyFileSync(currentPath, targetPath);
159
+ }
160
+ });
161
+ }
162
+ }
@@ -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,26 @@
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
+ console.log("Finishing running withWidgetExtensionEntitlements")
24
+ return config;
25
+ });
26
+ };
@@ -0,0 +1,93 @@
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
+ // widgetsFolder: string;
18
+ moduleFileName: string;
19
+ attributesFileName: string;
20
+ }> = (
21
+ config,
22
+ {
23
+ targetName,
24
+ bundleIdentifier,
25
+ deploymentTarget,
26
+ // widgetsFolder,
27
+ moduleFileName,
28
+ attributesFileName,
29
+ }
30
+ ) => {
31
+ return withXcodeProject(config, (config) => {
32
+ console.log("Running withXcode")
33
+ const xcodeProject = config.modResults;
34
+ // const widgetsPath = path.join(config.modRequest.projectRoot, widgetsFolder);
35
+
36
+ const targetUuid = xcodeProject.generateUuid();
37
+ const groupName = "Embed Foundation Extensions";
38
+ const { platformProjectRoot } = config.modRequest;
39
+ const marketingVersion = config.version;
40
+
41
+ const targetPath = path.join(platformProjectRoot, targetName);
42
+
43
+ const widgetFiles = getWidgetFiles(
44
+ // widgetsPath,
45
+ targetPath,
46
+ moduleFileName,
47
+ attributesFileName
48
+ );
49
+
50
+ console.log("Finished running withFiles")
51
+ const xCConfigurationList = addXCConfigurationList(xcodeProject, {
52
+ targetName,
53
+ currentProjectVersion: config.ios!.buildNumber || "1",
54
+ bundleIdentifier,
55
+ deploymentTarget,
56
+ marketingVersion,
57
+ });
58
+ console.log("Finished running addXCConfigurationList")
59
+
60
+ const productFile = addProductFile(xcodeProject, {
61
+ targetName,
62
+ groupName,
63
+ });
64
+ console.log("Finished running addProductFile")
65
+
66
+ const target = addToPbxNativeTargetSection(xcodeProject, {
67
+ targetName,
68
+ targetUuid,
69
+ productFile,
70
+ xCConfigurationList,
71
+ });
72
+ console.log("Finished running addToPbxNativeTargetSection")
73
+
74
+ addToPbxProjectSection(xcodeProject, target);
75
+
76
+ addTargetDependency(xcodeProject, target);
77
+
78
+ addBuildPhases(xcodeProject, {
79
+ targetUuid,
80
+ groupName,
81
+ productFile,
82
+ widgetFiles,
83
+ });
84
+
85
+ addPbxGroup(xcodeProject, {
86
+ targetName,
87
+ widgetFiles,
88
+ });
89
+
90
+ console.log("Finished running withXcode")
91
+ return config;
92
+ });
93
+ };
@@ -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
+ }