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.
- package/LICENSE.txt +21 -0
- package/README.md +84 -19
- package/app.plugin.js +2 -0
- package/build/ExpoLiveActivityModule.d.ts +1 -8
- package/build/ExpoLiveActivityModule.d.ts.map +1 -1
- package/build/ExpoLiveActivityModule.js +2 -3
- package/build/ExpoLiveActivityModule.js.map +1 -1
- package/build/index.d.ts +36 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +37 -5
- package/build/index.js.map +1 -1
- package/expo-module.config.json +3 -11
- package/ios/ExpoLiveActivity.podspec +1 -1
- package/ios/ExpoLiveActivityModule.swift +130 -38
- package/ios/LiveActivityAttributes.swift +32 -0
- package/ios-files/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/ios-files/Assets.xcassets/AppIcon.appiconset/Contents.json +35 -0
- package/ios-files/Assets.xcassets/Contents.json +6 -0
- package/ios-files/Assets.xcassets/WidgetBackground.colorset/Contents.json +11 -0
- package/ios-files/Color+hex.swift +37 -0
- package/ios-files/Info.plist +11 -0
- package/ios-files/LiveActivityBundle.swift +16 -0
- package/ios-files/LiveActivityLiveActivity.swift +142 -0
- package/ios-files/LiveActivityView.swift +73 -0
- package/package.json +13 -14
- package/plugin/build/index.d.ts +3 -0
- package/plugin/build/index.js +40 -0
- package/plugin/build/lib/getWidgetExtensionEntitlements.d.ts +3 -0
- package/plugin/build/lib/getWidgetExtensionEntitlements.js +16 -0
- package/plugin/build/lib/getWidgetFiles.d.ts +10 -0
- package/plugin/build/lib/getWidgetFiles.js +172 -0
- package/plugin/build/withConfig.d.ts +6 -0
- package/plugin/build/withConfig.js +54 -0
- package/plugin/build/withPodfile.d.ts +4 -0
- package/plugin/build/withPodfile.js +92 -0
- package/plugin/build/withWidgetExtensionEntitlements.d.ts +6 -0
- package/plugin/build/withWidgetExtensionEntitlements.js +57 -0
- package/plugin/build/withXcode.d.ts +8 -0
- package/plugin/build/withXcode.js +99 -0
- package/plugin/build/xcode/addBuildPhases.d.ts +13 -0
- package/plugin/build/xcode/addBuildPhases.js +57 -0
- package/plugin/build/xcode/addPbxGroup.d.ts +6 -0
- package/plugin/build/xcode/addPbxGroup.js +25 -0
- package/plugin/build/xcode/addProductFile.d.ts +5 -0
- package/plugin/build/xcode/addProductFile.js +21 -0
- package/plugin/build/xcode/addTargetDependency.d.ts +4 -0
- package/plugin/build/xcode/addTargetDependency.js +14 -0
- package/plugin/build/xcode/addToPbxNativeTargetSection.d.ts +24 -0
- package/plugin/build/xcode/addToPbxNativeTargetSection.js +29 -0
- package/plugin/build/xcode/addToPbxProjectSection.d.ts +4 -0
- package/plugin/build/xcode/addToPbxProjectSection.js +14 -0
- package/plugin/build/xcode/addXCConfigurationList.d.ts +8 -0
- package/plugin/build/xcode/addXCConfigurationList.js +61 -0
- package/plugin/src/index.ts +49 -0
- package/plugin/src/lib/getWidgetExtensionEntitlements.ts +26 -0
- package/plugin/src/lib/getWidgetFiles.ts +162 -0
- package/plugin/src/withConfig.ts +62 -0
- package/plugin/src/withPodfile.ts +72 -0
- package/plugin/src/withWidgetExtensionEntitlements.ts +26 -0
- package/plugin/src/withXcode.ts +93 -0
- package/plugin/src/xcode/addBuildPhases.ts +83 -0
- package/plugin/src/xcode/addPbxGroup.ts +48 -0
- package/plugin/src/xcode/addProductFile.ts +25 -0
- package/plugin/src/xcode/addTargetDependency.ts +17 -0
- package/plugin/src/xcode/addToPbxNativeTargetSection.ts +46 -0
- package/plugin/src/xcode/addToPbxProjectSection.ts +23 -0
- package/plugin/src/xcode/addXCConfigurationList.ts +83 -0
- package/plugin/tsconfig.json +9 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/src/ExpoLiveActivityModule.ts +2 -11
- package/src/index.ts +59 -5
- package/android/build.gradle +0 -43
- package/android/src/main/AndroidManifest.xml +0 -2
- package/android/src/main/java/expo/modules/liveactivity/ExpoLiveActivityModule.kt +0 -50
- package/android/src/main/java/expo/modules/liveactivity/ExpoLiveActivityView.kt +0 -30
- package/build/ExpoLiveActivity.types.d.ts +0 -18
- package/build/ExpoLiveActivity.types.d.ts.map +0 -1
- package/build/ExpoLiveActivity.types.js +0 -2
- package/build/ExpoLiveActivity.types.js.map +0 -1
- package/build/ExpoLiveActivityModule.web.d.ts +0 -10
- package/build/ExpoLiveActivityModule.web.d.ts.map +0 -1
- package/build/ExpoLiveActivityModule.web.js +0 -12
- package/build/ExpoLiveActivityModule.web.js.map +0 -1
- package/build/ExpoLiveActivityView.d.ts +0 -4
- package/build/ExpoLiveActivityView.d.ts.map +0 -1
- package/build/ExpoLiveActivityView.js +0 -7
- package/build/ExpoLiveActivityView.js.map +0 -1
- package/build/ExpoLiveActivityView.web.d.ts +0 -4
- package/build/ExpoLiveActivityView.web.d.ts.map +0 -1
- package/build/ExpoLiveActivityView.web.js +0 -7
- package/build/ExpoLiveActivityView.web.js.map +0 -1
- package/ios/ExpoLiveActivityView.swift +0 -38
- package/src/ExpoLiveActivity.types.ts +0 -19
- package/src/ExpoLiveActivityModule.web.ts +0 -15
- package/src/ExpoLiveActivityView.tsx +0 -11
- 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.
|
|
4
|
-
"description": "
|
|
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
|
-
"
|
|
22
|
-
"
|
|
20
|
+
"live-activity",
|
|
21
|
+
"ios",
|
|
22
|
+
"apple"
|
|
23
23
|
],
|
|
24
|
-
"repository": "https://github.com/
|
|
24
|
+
"repository": "https://github.com/software-mansion-labs/expo-live-activity",
|
|
25
25
|
"bugs": {
|
|
26
|
-
"url": "https://github.com/
|
|
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/
|
|
29
|
+
"homepage": "https://github.com/software-mansion-labs/expo-live-activity#readme",
|
|
31
30
|
"dependencies": {},
|
|
32
31
|
"devDependencies": {
|
|
33
|
-
"@types/react": "~
|
|
34
|
-
"expo-module-scripts": "^4.
|
|
35
|
-
"expo": "~
|
|
36
|
-
"react-native": "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,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,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;
|