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,16 @@
1
+ //
2
+ // LiveActivityBundle.swift
3
+ // LiveActivity
4
+ //
5
+ // Created by Anna Olak on 02/06/2025.
6
+ //
7
+
8
+ import WidgetKit
9
+ import SwiftUI
10
+
11
+ @main
12
+ struct LiveActivityBundle: WidgetBundle {
13
+ var body: some Widget {
14
+ LiveActivityLiveActivity()
15
+ }
16
+ }
@@ -0,0 +1,142 @@
1
+ //
2
+ // LiveActivityLiveActivity.swift
3
+ // LiveActivity
4
+ //
5
+ // Created by Anna Olak on 02/06/2025.
6
+ //
7
+
8
+ import ActivityKit
9
+ import SwiftUI
10
+ import WidgetKit
11
+
12
+ struct LiveActivityAttributes: ActivityAttributes {
13
+ public struct ContentState: Codable, Hashable {
14
+ var title: String
15
+ var subtitle: String?
16
+ var date: Date?
17
+ var imageName: String?
18
+ var dynamicIslandImageName: String?
19
+ }
20
+
21
+ var name: String
22
+ var backgroundColor: String?
23
+ var titleColor: String?
24
+ var subtitleColor: String?
25
+ var progressViewTint: String?
26
+ var progressViewLabelColor: String?
27
+ var timerType: DynamicIslandTimerType
28
+
29
+ enum DynamicIslandTimerType: String, Codable {
30
+ case circular
31
+ case digital
32
+ }
33
+ }
34
+
35
+ struct LiveActivityLiveActivity: Widget {
36
+ var body: some WidgetConfiguration {
37
+ ActivityConfiguration(for: LiveActivityAttributes.self) { context in
38
+ LiveActivityView(contentState: context.state, attributes: context.attributes)
39
+ .activityBackgroundTint(context.attributes.backgroundColor != nil ? Color(hex: context.attributes.backgroundColor!) : nil)
40
+ .activitySystemActionForegroundColor(Color.black)
41
+
42
+ } dynamicIsland: { context in
43
+ DynamicIsland {
44
+ DynamicIslandExpandedRegion(.leading, priority: 1) {
45
+ dynamicIslandExpandedLeading(title: context.state.title, subtitle: context.state.subtitle)
46
+ .dynamicIsland(verticalPlacement: .belowIfTooWide)
47
+ .padding(.leading, 5)
48
+ }
49
+ DynamicIslandExpandedRegion(.trailing) {
50
+ if let imageName = context.state.imageName {
51
+ dynamicIslandExpandedTrailing(imageName: imageName)
52
+ .padding(.trailing, 5)
53
+ }
54
+ }
55
+ DynamicIslandExpandedRegion(.bottom) {
56
+ if let date = context.state.date {
57
+ dynamicIslandExpandedBottom(endDate: date, progressViewTint: context.attributes.progressViewTint)
58
+ .padding(.horizontal, 5)
59
+ }
60
+ }
61
+ } compactLeading: {
62
+ if let dynamicIslandImageName = context.state.dynamicIslandImageName {
63
+ resizableImage(imageName: dynamicIslandImageName)
64
+ .frame(maxWidth: 23, maxHeight: 23)
65
+ }
66
+ } compactTrailing: {
67
+ if let date = context.state.date {
68
+ compactTimer(endDate: date, timerType: context.attributes.timerType, progressViewTint: context.attributes.progressViewTint)
69
+ }
70
+ } minimal: {
71
+ if let date = context.state.date {
72
+ compactTimer(endDate: date, timerType: context.attributes.timerType, progressViewTint: context.attributes.progressViewTint)
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ @ViewBuilder
79
+ private func compactTimer(endDate: Date, timerType: LiveActivityAttributes.DynamicIslandTimerType, progressViewTint: String?) -> some View {
80
+ if timerType == .digital {
81
+ Text(timerInterval: Date.now...max(Date.now, endDate))
82
+ .font(.system(size: 15))
83
+ .minimumScaleFactor(0.8)
84
+ .fontWeight(.semibold)
85
+ .frame(maxWidth: 60)
86
+ .multilineTextAlignment(.trailing)
87
+ } else {
88
+ circularTimer(endDate: endDate)
89
+ .tint(progressViewTint != nil ? Color(hex: progressViewTint!) : nil)
90
+ }
91
+ }
92
+
93
+ private func dynamicIslandExpandedLeading(title: String, subtitle: String?) -> some View {
94
+ VStack(alignment: .leading) {
95
+ Spacer()
96
+ Text(title)
97
+ .font(.title2)
98
+ .foregroundStyle(.white)
99
+ .fontWeight(.semibold)
100
+ if let subtitle {
101
+ Text(subtitle)
102
+ .font(.title3)
103
+ .minimumScaleFactor(0.8)
104
+ .foregroundStyle(.white.opacity(0.75))
105
+ }
106
+ Spacer()
107
+ }
108
+ }
109
+
110
+ private func dynamicIslandExpandedTrailing(imageName: String) -> some View {
111
+ VStack {
112
+ Spacer()
113
+ resizableImage(imageName: imageName)
114
+ .frame(maxHeight: 64)
115
+ Spacer()
116
+ }
117
+ }
118
+
119
+ private func dynamicIslandExpandedBottom(endDate: Date, progressViewTint: String?) -> some View {
120
+ ProgressView(timerInterval: Date.now...max(Date.now, endDate))
121
+ .foregroundStyle(.white)
122
+ .tint(progressViewTint != nil ? Color(hex: progressViewTint!) : nil)
123
+ .padding(.top, 5)
124
+ }
125
+
126
+ private func circularTimer(endDate: Date) -> some View {
127
+ ProgressView(
128
+ timerInterval: Date.now...max(Date.now, endDate),
129
+ countsDown: false,
130
+ label: { EmptyView() },
131
+ currentValueLabel: {
132
+ EmptyView()
133
+ }
134
+ )
135
+ .progressViewStyle(.circular)
136
+ }
137
+ private func resizableImage(imageName: String) -> some View {
138
+ Image(imageName)
139
+ .resizable()
140
+ .scaledToFit()
141
+ }
142
+ }
@@ -0,0 +1,73 @@
1
+ //
2
+ // LiveActivityView.swift
3
+ // ExpoLiveActivity
4
+ //
5
+ // Created by Anna Olak on 03/06/2025.
6
+ //
7
+
8
+ import SwiftUI
9
+ import WidgetKit
10
+
11
+ #if canImport(ActivityKit)
12
+
13
+ struct LiveActivityView: View {
14
+ let contentState: LiveActivityAttributes.ContentState
15
+ let attributes: LiveActivityAttributes
16
+
17
+ var progressViewTint: Color? {
18
+ attributes.progressViewTint != nil ? Color(hex: attributes.progressViewTint!) : nil
19
+ }
20
+
21
+ var body: some View {
22
+ VStack(alignment: .leading) {
23
+ HStack(alignment: .center) {
24
+ VStack(alignment: .leading, spacing: 2) {
25
+ if let titleColor = attributes.titleColor {
26
+ Text(contentState.title)
27
+ .font(.title2)
28
+ .foregroundStyle(Color(hex: titleColor))
29
+ .fontWeight(.semibold)
30
+ } else {
31
+ Text(contentState.title)
32
+ .font(.title2)
33
+ .fontWeight(.semibold)
34
+ }
35
+
36
+ if let subtitle = contentState.subtitle {
37
+ if let subtitleColor = attributes.subtitleColor {
38
+ Text(subtitle)
39
+ .font(.title3)
40
+ .foregroundStyle(Color(hex: subtitleColor))
41
+ } else {
42
+ Text(subtitle)
43
+ .font(.title3)
44
+ }
45
+ }
46
+ }
47
+
48
+ Spacer()
49
+
50
+ if let imageName = contentState.imageName {
51
+ Image(imageName)
52
+ .resizable()
53
+ .scaledToFit()
54
+ .frame(maxHeight: 64)
55
+ }
56
+ }
57
+
58
+ if let date = contentState.date {
59
+ if let progressViewLabelColor = attributes.progressViewLabelColor {
60
+ ProgressView(timerInterval: Date.now...max(Date.now, date))
61
+ .tint(progressViewTint)
62
+ .foregroundStyle(Color(hex: progressViewLabelColor))
63
+ } else {
64
+ ProgressView(timerInterval: Date.now...max(Date.now, date))
65
+ .tint(progressViewTint)
66
+ }
67
+ }
68
+ }
69
+ .padding(24)
70
+ }
71
+ }
72
+
73
+ #endif
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-live-activity",
3
- "version": "0.1.0",
4
- "description": "My new module",
3
+ "version": "0.2.0-alpha1",
4
+ "description": "A module for adding Live Activity to a React Native app for iOS.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
7
7
  "scripts": {
@@ -12,28 +12,29 @@
12
12
  "prepare": "expo-module prepare",
13
13
  "prepublishOnly": "expo-module prepublishOnly",
14
14
  "expo-module": "expo-module",
15
- "open:ios": "xed example/ios",
16
- "open:android": "open -a \"Android Studio\" example/android"
15
+ "open:ios": "xed example/ios"
17
16
  },
18
17
  "keywords": [
19
18
  "react-native",
20
19
  "expo",
21
- "expo-live-activity",
22
- "ExpoLiveActivity"
20
+ "live-activity",
21
+ "ios",
22
+ "apple"
23
23
  ],
24
- "repository": "https://github.com/kowczarz/expo-live-activity",
24
+ "author": "Kamil Owczarz <kamil.owczarz@swmansion.com> (https://github.com/kowczarz)",
25
+ "contributors": ["Anna Olak <anna.olak@swmansion.com> (https://github.com/anna1901)"],
26
+ "repository": "https://github.com/software-mansion-labs/expo-live-activity.git",
25
27
  "bugs": {
26
- "url": "https://github.com/kowczarz/expo-live-activity/issues"
28
+ "url": "https://github.com/software-mansion-labs/expo-live-activity/issues"
27
29
  },
28
- "author": "Kamil Owczarz <kamil.owczarz@swmansion.com> (https://github.com/kowczarz)",
29
30
  "license": "MIT",
30
- "homepage": "https://github.com/kowczarz/expo-live-activity#readme",
31
+ "homepage": "https://github.com/software-mansion-labs/expo-live-activity#readme",
31
32
  "dependencies": {},
32
33
  "devDependencies": {
33
- "@types/react": "~18.3.12",
34
- "expo-module-scripts": "^4.0.4",
35
- "expo": "~52.0.0",
36
- "react-native": "0.76.0"
34
+ "@types/react": "~19.0.0",
35
+ "expo-module-scripts": "^4.1.6",
36
+ "expo": "~53.0.0",
37
+ "react-native": "0.79.1"
37
38
  },
38
39
  "peerDependencies": {
39
40
  "expo": "*",
@@ -0,0 +1,3 @@
1
+ import { ConfigPlugin } from "expo/config-plugins";
2
+ declare const withWidgetsAndLiveActivities: ConfigPlugin;
3
+ export default withWidgetsAndLiveActivities;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_plugins_1 = require("expo/config-plugins");
4
+ const withConfig_1 = require("./withConfig");
5
+ const withPodfile_1 = require("./withPodfile");
6
+ const withXcode_1 = require("./withXcode");
7
+ const withWidgetExtensionEntitlements_1 = require("./withWidgetExtensionEntitlements");
8
+ const withWidgetsAndLiveActivities = (config) => {
9
+ const deploymentTarget = "16.2";
10
+ const targetName = `${config_plugins_1.IOSConfig.XcodeUtils.sanitizedName(config.name)}LiveActivity`;
11
+ const bundleIdentifier = `${config.ios?.bundleIdentifier}.${targetName}`;
12
+ config.ios = {
13
+ ...config.ios,
14
+ infoPlist: {
15
+ ...config.ios?.infoPlist,
16
+ NSSupportsLiveActivities: true,
17
+ NSSupportsLiveActivitiesFrequentUpdates: false,
18
+ },
19
+ };
20
+ config = (0, config_plugins_1.withPlugins)(config, [
21
+ [
22
+ withXcode_1.withXcode,
23
+ {
24
+ targetName,
25
+ bundleIdentifier,
26
+ deploymentTarget,
27
+ },
28
+ ],
29
+ [withWidgetExtensionEntitlements_1.withWidgetExtensionEntitlements, { targetName }],
30
+ [withPodfile_1.withPodfile, { targetName }],
31
+ [withConfig_1.withConfig, { targetName, bundleIdentifier }],
32
+ ]);
33
+ return config;
34
+ };
35
+ exports.default = withWidgetsAndLiveActivities;
@@ -0,0 +1,3 @@
1
+ import { ExportedConfig, InfoPlist } from "@expo/config-plugins";
2
+ export declare function getWidgetExtensionEntitlements(iosConfig: ExportedConfig["ios"], {}: {}): InfoPlist;
3
+ export declare function addApplicationGroupsEntitlement(entitlements: InfoPlist, groupIdentifier?: string): InfoPlist;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWidgetExtensionEntitlements = getWidgetExtensionEntitlements;
4
+ exports.addApplicationGroupsEntitlement = addApplicationGroupsEntitlement;
5
+ function getWidgetExtensionEntitlements(iosConfig, {}) {
6
+ const entitlements = {};
7
+ addApplicationGroupsEntitlement(entitlements);
8
+ return entitlements;
9
+ }
10
+ function addApplicationGroupsEntitlement(entitlements, groupIdentifier) {
11
+ // if (groupIdentifier) {
12
+ // const existingApplicationGroups = (entitlements["com.apple.security.application-groups"] as string[]) ?? [];
13
+ // entitlements["com.apple.security.application-groups"] = [groupIdentifier, ...existingApplicationGroups];
14
+ // }
15
+ return entitlements;
16
+ }
@@ -0,0 +1,10 @@
1
+ export type WidgetFiles = {
2
+ swiftFiles: string[];
3
+ entitlementFiles: string[];
4
+ plistFiles: string[];
5
+ assetDirectories: string[];
6
+ intentFiles: string[];
7
+ otherFiles: string[];
8
+ };
9
+ export declare function getWidgetFiles(targetPath: string): WidgetFiles;
10
+ export declare function copyFileSync(source: string, target: string): void;
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getWidgetFiles = getWidgetFiles;
37
+ exports.copyFileSync = copyFileSync;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ function getWidgetFiles(targetPath) {
41
+ let packagePath;
42
+ try {
43
+ packagePath = path.dirname(require.resolve("expo-live-activity/package.json"));
44
+ }
45
+ catch {
46
+ console.log("Building for example app");
47
+ }
48
+ const liveActivityFilesPath = path.join(packagePath ? packagePath : "..", "/ios-files");
49
+ const imageAssetsPath = "./assets/live_activity";
50
+ const widgetFiles = {
51
+ swiftFiles: [],
52
+ entitlementFiles: [],
53
+ plistFiles: [],
54
+ assetDirectories: [],
55
+ intentFiles: [],
56
+ otherFiles: [],
57
+ };
58
+ if (!fs.existsSync(targetPath)) {
59
+ fs.mkdirSync(targetPath, { recursive: true });
60
+ }
61
+ if (fs.lstatSync(liveActivityFilesPath).isDirectory()) {
62
+ const files = fs.readdirSync(liveActivityFilesPath);
63
+ files.forEach((file) => {
64
+ const fileExtension = file.split(".").pop();
65
+ if (fileExtension === "swift") {
66
+ widgetFiles.swiftFiles.push(file);
67
+ }
68
+ else if (fileExtension === "entitlements") {
69
+ widgetFiles.entitlementFiles.push(file);
70
+ }
71
+ else if (fileExtension === "plist") {
72
+ widgetFiles.plistFiles.push(file);
73
+ }
74
+ else if (fileExtension === "xcassets") {
75
+ widgetFiles.assetDirectories.push(file);
76
+ }
77
+ else if (fileExtension === "intentdefinition") {
78
+ widgetFiles.intentFiles.push(file);
79
+ }
80
+ else {
81
+ widgetFiles.otherFiles.push(file);
82
+ }
83
+ });
84
+ }
85
+ // Copy files
86
+ [
87
+ ...widgetFiles.swiftFiles,
88
+ ...widgetFiles.entitlementFiles,
89
+ ...widgetFiles.plistFiles,
90
+ ...widgetFiles.intentFiles,
91
+ ...widgetFiles.otherFiles,
92
+ ].forEach((file) => {
93
+ const source = path.join(liveActivityFilesPath, file);
94
+ copyFileSync(source, targetPath);
95
+ });
96
+ // Copy assets directory
97
+ const imagesXcassetsSource = path.join(liveActivityFilesPath, "Assets.xcassets");
98
+ copyFolderRecursiveSync(imagesXcassetsSource, targetPath);
99
+ // Move images to assets directory
100
+ if (fs.lstatSync(imageAssetsPath).isDirectory()) {
101
+ const imagesXcassetsTarget = path.join(targetPath, "Assets.xcassets");
102
+ const files = fs.readdirSync(imageAssetsPath);
103
+ files.forEach((file) => {
104
+ if (path.extname(file).match(/\.(png|jpg|jpeg)$/)) {
105
+ const source = path.join(imageAssetsPath, file);
106
+ const imageSetDir = path.join(imagesXcassetsTarget, `${path.basename(file, path.extname(file))}.imageset`);
107
+ // Create the .imageset directory if it doesn't exist
108
+ if (!fs.existsSync(imageSetDir)) {
109
+ fs.mkdirSync(imageSetDir, { recursive: true });
110
+ }
111
+ // Copy image file to the .imageset directory
112
+ const destPath = path.join(imageSetDir, file);
113
+ fs.copyFileSync(source, destPath);
114
+ // Create Contents.json file
115
+ const contentsJson = {
116
+ images: [
117
+ {
118
+ filename: file,
119
+ idiom: "universal"
120
+ }
121
+ ],
122
+ info: {
123
+ author: "xcode",
124
+ version: 1
125
+ }
126
+ };
127
+ fs.writeFileSync(path.join(imageSetDir, 'Contents.json'), JSON.stringify(contentsJson, null, 2));
128
+ }
129
+ });
130
+ }
131
+ return widgetFiles;
132
+ }
133
+ function copyFileSync(source, target) {
134
+ let targetFile = target;
135
+ if (fs.existsSync(target) && fs.lstatSync(target).isDirectory()) {
136
+ targetFile = path.join(target, path.basename(source));
137
+ }
138
+ fs.writeFileSync(targetFile, fs.readFileSync(source));
139
+ }
140
+ function copyFolderRecursiveSync(source, target) {
141
+ const targetPath = path.join(target, path.basename(source));
142
+ if (!fs.existsSync(targetPath)) {
143
+ fs.mkdirSync(targetPath, { recursive: true });
144
+ }
145
+ if (fs.lstatSync(source).isDirectory()) {
146
+ const files = fs.readdirSync(source);
147
+ files.forEach((file) => {
148
+ const currentPath = path.join(source, file);
149
+ if (fs.lstatSync(currentPath).isDirectory()) {
150
+ copyFolderRecursiveSync(currentPath, targetPath);
151
+ }
152
+ else {
153
+ copyFileSync(currentPath, targetPath);
154
+ }
155
+ });
156
+ }
157
+ }
@@ -0,0 +1,6 @@
1
+ import { ConfigPlugin } from "@expo/config-plugins";
2
+ export declare const withConfig: ConfigPlugin<{
3
+ bundleIdentifier: string;
4
+ targetName: string;
5
+ groupIdentifier?: string;
6
+ }>;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withConfig = void 0;
4
+ const getWidgetExtensionEntitlements_1 = require("./lib/getWidgetExtensionEntitlements");
5
+ const withConfig = (config, { bundleIdentifier, targetName, groupIdentifier }) => {
6
+ let configIndex = null;
7
+ config.extra?.eas?.build?.experimental?.ios?.appExtensions?.forEach((ext, index) => {
8
+ if (ext.targetName === targetName) {
9
+ configIndex = index;
10
+ }
11
+ });
12
+ if (!configIndex) {
13
+ config.extra = {
14
+ ...config.extra,
15
+ eas: {
16
+ ...config.extra?.eas,
17
+ build: {
18
+ ...config.extra?.eas?.build,
19
+ experimental: {
20
+ ...config.extra?.eas?.build?.experimental,
21
+ ios: {
22
+ ...config.extra?.eas?.build?.experimental?.ios,
23
+ appExtensions: [
24
+ ...(config.extra?.eas?.build?.experimental?.ios?.appExtensions ?? []),
25
+ {
26
+ targetName,
27
+ bundleIdentifier,
28
+ },
29
+ ],
30
+ },
31
+ },
32
+ },
33
+ },
34
+ };
35
+ configIndex = 0;
36
+ }
37
+ if (configIndex != null && config.extra) {
38
+ const widgetsExtensionConfig = config.extra.eas.build.experimental.ios.appExtensions[configIndex];
39
+ widgetsExtensionConfig.entitlements = {
40
+ ...widgetsExtensionConfig.entitlements,
41
+ ...(0, getWidgetExtensionEntitlements_1.getWidgetExtensionEntitlements)(config.ios, {
42
+ groupIdentifier,
43
+ }),
44
+ };
45
+ config.ios = {
46
+ ...config.ios,
47
+ entitlements: {
48
+ ...(0, getWidgetExtensionEntitlements_1.addApplicationGroupsEntitlement)(config.ios?.entitlements ?? {}, groupIdentifier),
49
+ },
50
+ };
51
+ }
52
+ return config;
53
+ };
54
+ exports.withConfig = withConfig;
@@ -0,0 +1,4 @@
1
+ import { ConfigPlugin } from "@expo/config-plugins";
2
+ export declare const withPodfile: ConfigPlugin<{
3
+ targetName: string;
4
+ }>;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.withPodfile = void 0;
37
+ const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
38
+ const config_plugins_1 = require("@expo/config-plugins");
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const withPodfile = (config, { targetName }) => {
42
+ return (0, config_plugins_1.withDangerousMod)(config, [
43
+ "ios",
44
+ (config) => {
45
+ const podFilePath = path.join(config.modRequest.platformProjectRoot, "Podfile");
46
+ let podFileContent = fs.readFileSync(podFilePath).toString();
47
+ /* podFileContent = mergeContents({
48
+ tag: "withWidgetExtensionPodfile1999999999",
49
+ src: podFileContent,
50
+ newSrc: ` target '${targetName}' do\n \n end`,
51
+ anchor: /post_install/,
52
+ offset: 0,
53
+ comment: "#",
54
+ }).contents; */
55
+ /* podFileContent = podFileContent.replace(
56
+ /use_expo_modules!/,
57
+ `use_expo_modules!(searchPaths: ["./node_modules", "../../node_modules", "../../../WidgetExtension"])`
58
+ ); */
59
+ podFileContent = (0, generateCode_1.mergeContents)({
60
+ tag: "react-native-widget-extension-1",
61
+ src: podFileContent,
62
+ newSrc: `installer.pods_project.targets.each do |target|
63
+ target.build_configurations.each do |config|
64
+ # Sentry has build errors unless configured as 'YES' for the Sentry target: https://github.com/bndkt/react-native-widget-extension/issues/24
65
+ config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = target.name == 'Sentry' ? 'YES' : 'No'
66
+ end
67
+ end`,
68
+ anchor: /installer.target_installation_results.pod_target_installation_results/,
69
+ offset: 0,
70
+ comment: "#",
71
+ }).contents;
72
+ /* podFileContent = mergeContents({
73
+ tag: "react-native-widget-extension-2",
74
+ src: podFileContent,
75
+ newSrc: `pod 'WidgetExtension', :path => '../WidgetExtension/ios'`,
76
+ anchor: /use_react_native/,
77
+ offset: -1,
78
+ comment: "#",
79
+ }).contents; */
80
+ podFileContent = podFileContent
81
+ .concat(`\n\n# >>> Inserted by react-native-widget-extension\n`)
82
+ .concat(`target '${targetName}' do
83
+ use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
84
+ use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
85
+ end`)
86
+ .concat(`\n# >>> Inserted by react-native-widget-extension`);
87
+ fs.writeFileSync(podFilePath, podFileContent);
88
+ return config;
89
+ },
90
+ ]);
91
+ };
92
+ exports.withPodfile = withPodfile;