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,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-alpha",
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,27 @@
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
+ "repository": "https://github.com/software-mansion-labs/expo-live-activity",
25
25
  "bugs": {
26
- "url": "https://github.com/kowczarz/expo-live-activity/issues"
26
+ "url": "https://github.com/software-mansion-labs/expo-live-activity/issues"
27
27
  },
28
- "author": "Kamil Owczarz <kamil.owczarz@swmansion.com> (https://github.com/kowczarz)",
29
28
  "license": "MIT",
30
- "homepage": "https://github.com/kowczarz/expo-live-activity#readme",
29
+ "homepage": "https://github.com/software-mansion-labs/expo-live-activity#readme",
31
30
  "dependencies": {},
32
31
  "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"
32
+ "@types/react": "~19.0.0",
33
+ "expo-module-scripts": "^4.1.6",
34
+ "expo": "~53.0.0",
35
+ "react-native": "0.79.1"
37
36
  },
38
37
  "peerDependencies": {
39
38
  "expo": "*",
@@ -0,0 +1,3 @@
1
+ import { ConfigPlugin } from "expo/config-plugins";
2
+ declare const withWidgetsAndLiveActivities: ConfigPlugin;
3
+ export default withWidgetsAndLiveActivities;
@@ -0,0 +1,40 @@
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 moduleFileName = "ExpoNativeConfigurationModule.swift";
11
+ const attributesFileName = "LiveActivityAttributes.swift";
12
+ const targetName = `${config_plugins_1.IOSConfig.XcodeUtils.sanitizedName(config.name)}LiveActivity`; // Widgets => LiveActivity
13
+ const bundleIdentifier = `${config.ios?.bundleIdentifier}.${targetName}`;
14
+ config.ios = {
15
+ ...config.ios,
16
+ infoPlist: {
17
+ ...config.ios?.infoPlist,
18
+ NSSupportsLiveActivities: true,
19
+ NSSupportsLiveActivitiesFrequentUpdates: false,
20
+ },
21
+ };
22
+ config = (0, config_plugins_1.withPlugins)(config, [
23
+ [
24
+ withXcode_1.withXcode,
25
+ {
26
+ targetName,
27
+ bundleIdentifier,
28
+ deploymentTarget,
29
+ // widgetsFolder,
30
+ moduleFileName,
31
+ attributesFileName,
32
+ },
33
+ ],
34
+ [withWidgetExtensionEntitlements_1.withWidgetExtensionEntitlements, { targetName }],
35
+ [withPodfile_1.withPodfile, { targetName }],
36
+ [withConfig_1.withConfig, { targetName, bundleIdentifier }],
37
+ ]);
38
+ return config;
39
+ };
40
+ 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, moduleFileName: string, attributesFileName: string): WidgetFiles;
10
+ export declare function copyFileSync(source: string, target: string): void;
@@ -0,0 +1,172 @@
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(
41
+ // widgetsPath: string, // to zmieniamy, bo u nas to będzie "config.modRequest.projectRoot/[tu może coś jeszcze być]/node_modules/nasz-moduł/iosViews"
42
+ targetPath, moduleFileName, attributesFileName) {
43
+ let packagePath;
44
+ try {
45
+ packagePath = path.dirname(require.resolve("expo-live-activity/package.json"));
46
+ }
47
+ catch {
48
+ console.log("Building for example app");
49
+ }
50
+ const widgetsPath = path.join(packagePath ? packagePath : "..", "/ios-files");
51
+ console.log(`Widgets path: ${widgetsPath}`);
52
+ const imageAssetsPath = "./assets/live_activity";
53
+ const widgetFiles = {
54
+ swiftFiles: [],
55
+ entitlementFiles: [],
56
+ plistFiles: [],
57
+ assetDirectories: [],
58
+ intentFiles: [],
59
+ otherFiles: [],
60
+ };
61
+ console.log(`Getting widget files`);
62
+ if (!fs.existsSync(targetPath)) {
63
+ console.log(`Making directory at: ${targetPath}`);
64
+ fs.mkdirSync(targetPath, { recursive: true });
65
+ }
66
+ if (fs.lstatSync(widgetsPath).isDirectory()) {
67
+ const files = fs.readdirSync(widgetsPath);
68
+ console.log(`Files: ${files}`);
69
+ files.forEach((file) => {
70
+ const fileExtension = file.split(".").pop();
71
+ if (fileExtension === "swift") {
72
+ if (file !== moduleFileName) {
73
+ widgetFiles.swiftFiles.push(file);
74
+ }
75
+ }
76
+ else if (fileExtension === "entitlements") {
77
+ widgetFiles.entitlementFiles.push(file);
78
+ }
79
+ else if (fileExtension === "plist") {
80
+ widgetFiles.plistFiles.push(file);
81
+ }
82
+ else if (fileExtension === "xcassets") {
83
+ widgetFiles.assetDirectories.push(file);
84
+ }
85
+ else if (fileExtension === "intentdefinition") {
86
+ widgetFiles.intentFiles.push(file);
87
+ }
88
+ else {
89
+ widgetFiles.otherFiles.push(file);
90
+ }
91
+ });
92
+ }
93
+ // Copy files
94
+ [
95
+ ...widgetFiles.swiftFiles,
96
+ ...widgetFiles.entitlementFiles,
97
+ ...widgetFiles.plistFiles,
98
+ ...widgetFiles.intentFiles,
99
+ ...widgetFiles.otherFiles,
100
+ ].forEach((file) => {
101
+ const source = path.join(widgetsPath, file);
102
+ copyFileSync(source, targetPath);
103
+ });
104
+ // Copy assets directory
105
+ const imagesXcassetsSource = path.join(widgetsPath, "Assets.xcassets");
106
+ copyFolderRecursiveSync(imagesXcassetsSource, targetPath);
107
+ // Move images to assets directory
108
+ console.log(`Images Path: ${imageAssetsPath}`);
109
+ if (fs.lstatSync(imageAssetsPath).isDirectory()) {
110
+ const imagesXcassetsTarget = path.join(targetPath, "Assets.xcassets");
111
+ console.log(`Assets Target: ${imagesXcassetsTarget}`);
112
+ const files = fs.readdirSync(imageAssetsPath);
113
+ console.log(`Images: ${files}`);
114
+ files.forEach((file) => {
115
+ if (path.extname(file).match(/\.(png|jpg|jpeg)$/)) {
116
+ const source = path.join(imageAssetsPath, file);
117
+ console.log(`Source: ${source}`);
118
+ const imageSetDir = path.join(imagesXcassetsTarget, `${path.basename(file, path.extname(file))}.imageset`);
119
+ console.log(`imageSetDir: ${source}`);
120
+ // Create the .imageset directory if it doesn't exist
121
+ if (!fs.existsSync(imageSetDir)) {
122
+ fs.mkdirSync(imageSetDir, { recursive: true });
123
+ }
124
+ // Copy image file to the .imageset directory
125
+ const destPath = path.join(imageSetDir, file);
126
+ fs.copyFileSync(source, destPath);
127
+ // Create Contents.json file
128
+ const contentsJson = {
129
+ images: [
130
+ {
131
+ filename: file,
132
+ idiom: "universal"
133
+ }
134
+ ],
135
+ info: {
136
+ author: "xcode",
137
+ version: 1
138
+ }
139
+ };
140
+ fs.writeFileSync(path.join(imageSetDir, 'Contents.json'), JSON.stringify(contentsJson, null, 2) // beautify the JSON output
141
+ );
142
+ console.log(`Processed ${file} into ${imageSetDir}`);
143
+ }
144
+ });
145
+ }
146
+ return widgetFiles;
147
+ }
148
+ function copyFileSync(source, target) {
149
+ let targetFile = target;
150
+ if (fs.existsSync(target) && fs.lstatSync(target).isDirectory()) {
151
+ targetFile = path.join(target, path.basename(source));
152
+ }
153
+ fs.writeFileSync(targetFile, fs.readFileSync(source));
154
+ }
155
+ function copyFolderRecursiveSync(source, target) {
156
+ const targetPath = path.join(target, path.basename(source));
157
+ if (!fs.existsSync(targetPath)) {
158
+ fs.mkdirSync(targetPath, { recursive: true });
159
+ }
160
+ if (fs.lstatSync(source).isDirectory()) {
161
+ const files = fs.readdirSync(source);
162
+ files.forEach((file) => {
163
+ const currentPath = path.join(source, file);
164
+ if (fs.lstatSync(currentPath).isDirectory()) {
165
+ copyFolderRecursiveSync(currentPath, targetPath);
166
+ }
167
+ else {
168
+ copyFileSync(currentPath, targetPath);
169
+ }
170
+ });
171
+ }
172
+ }
@@ -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
+ }>;