@akylas/nativescript-cli 8.8.6 → 8.9.4
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/config/test-deps-versions-generated.json +16 -0
- package/docs/man_pages/project/configuration/widget-ios.md +24 -0
- package/docs/man_pages/project/configuration/widget.md +24 -0
- package/docs/man_pages/start.md +1 -1
- package/lib/.d.ts +2 -0
- package/lib/bootstrap.js +1 -0
- package/lib/bun-package-manager.js +1 -1
- package/lib/commands/appstore-upload.js +3 -6
- package/lib/commands/create-project.js +6 -1
- package/lib/commands/generate.js +2 -41
- package/lib/commands/widget.js +799 -0
- package/lib/common/file-system.js +1 -2
- package/lib/common/logger/logger.js +4 -4
- package/lib/common/mobile/android/android-emulator-services.js +1 -1
- package/lib/common/mobile/android/android-ini-file-parser.js +8 -6
- package/lib/common/mobile/android/logcat-helper.js +1 -1
- package/lib/common/mobile/emulator-helper.js +1 -0
- package/lib/common/mobile/mobile-core/devices-service.js +2 -1
- package/lib/common/opener.js +2 -2
- package/lib/common/services/hooks-service.js +23 -6
- package/lib/constants.js +2 -1
- package/lib/controllers/migrate-controller.js +8 -8
- package/lib/controllers/prepare-controller.js +7 -6
- package/lib/data/prepare-data.js +1 -0
- package/lib/declarations.d.ts +1 -1
- package/lib/definitions/ios.d.ts +11 -1
- package/lib/definitions/prepare.d.ts +2 -0
- package/lib/definitions/project.d.ts +50 -24
- package/lib/key-commands/index.js +28 -21
- package/lib/node-package-manager.js +1 -1
- package/lib/options.js +1 -0
- package/lib/services/analytics/analytics-service.js +2 -1
- package/lib/services/android/gradle-build-args-service.js +1 -1
- package/lib/services/android-plugin-build-service.js +1 -1
- package/lib/services/apple-portal/apple-portal-application-service.js +1 -1
- package/lib/services/apple-portal/apple-portal-session-service.js +36 -9
- package/lib/services/apple-portal/srp/srp-wrapper.js +61 -0
- package/lib/services/assets-generation/assets-generation-service.js +33 -15
- package/lib/services/ios/export-options-plist-service.js +4 -2
- package/lib/services/ios/ios-signing-service.js +45 -23
- package/lib/services/ios/spm-service.js +10 -1
- package/lib/services/ios/xcodebuild-service.js +2 -0
- package/lib/services/ios-debugger-port-service.js +1 -1
- package/lib/services/ios-project-service.js +45 -14
- package/lib/services/livesync/android-livesync-tool.js +1 -1
- package/lib/services/project-config-service.js +12 -3
- package/lib/services/webpack/webpack-compiler-service.js +10 -3
- package/lib/tools/config-manipulation/config-transformer.js +9 -0
- package/package.json +51 -56
- package/vendor/gradle-app/app/build.gradle +347 -119
- package/vendor/gradle-app/build.gradle +7 -7
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WidgetIOSCommand = exports.WidgetCommand = void 0;
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const prompts = require("prompts");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const plist = require("plist");
|
|
8
|
+
const yok_1 = require("../common/yok");
|
|
9
|
+
const utils_1 = require("../common/utils");
|
|
10
|
+
const os_1 = require("os");
|
|
11
|
+
class WidgetCommand {
|
|
12
|
+
constructor($projectData, $projectConfigService, $logger, $errors) {
|
|
13
|
+
this.$projectData = $projectData;
|
|
14
|
+
this.$projectConfigService = $projectConfigService;
|
|
15
|
+
this.$logger = $logger;
|
|
16
|
+
this.$errors = $errors;
|
|
17
|
+
this.allowedParameters = [];
|
|
18
|
+
this.$projectData.initializeProjectData();
|
|
19
|
+
}
|
|
20
|
+
async execute(args) {
|
|
21
|
+
this.failWithUsage();
|
|
22
|
+
return Promise.resolve();
|
|
23
|
+
}
|
|
24
|
+
failWithUsage() {
|
|
25
|
+
this.$errors.failWithHelp("Usage: ns widget ios");
|
|
26
|
+
}
|
|
27
|
+
async canExecute(args) {
|
|
28
|
+
this.failWithUsage();
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
getIosSourcePathBase() {
|
|
32
|
+
const resources = this.$projectData.getAppResourcesDirectoryPath();
|
|
33
|
+
return path.join(resources, "iOS", "src");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.WidgetCommand = WidgetCommand;
|
|
37
|
+
class WidgetIOSCommand extends WidgetCommand {
|
|
38
|
+
constructor($projectData, $projectConfigService, $logger, $errors) {
|
|
39
|
+
super($projectData, $projectConfigService, $logger, $errors);
|
|
40
|
+
}
|
|
41
|
+
async canExecute(args) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
async execute(args) {
|
|
45
|
+
this.startPrompt(args);
|
|
46
|
+
}
|
|
47
|
+
async startPrompt(args) {
|
|
48
|
+
let result = await prompts.prompt({
|
|
49
|
+
type: "text",
|
|
50
|
+
name: "name",
|
|
51
|
+
message: `What name would you like for this widget? (Default is 'widget')`,
|
|
52
|
+
});
|
|
53
|
+
const name = (result.name || "widget").toLowerCase();
|
|
54
|
+
result = await prompts.prompt({
|
|
55
|
+
type: "select",
|
|
56
|
+
name: "value",
|
|
57
|
+
message: `What type of widget would you like?`,
|
|
58
|
+
choices: [
|
|
59
|
+
{
|
|
60
|
+
title: "Live Activity",
|
|
61
|
+
description: "This will create a Live Activity that will display on the iOS Lock Screen.",
|
|
62
|
+
value: 0,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
title: "Live Activity with Home Screen Widget",
|
|
66
|
+
description: "This will create a Live Activity that will display on the iOS Lock Screen with ability to also display a Home Screen Widget.",
|
|
67
|
+
value: 1,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
title: "Home Screen Widget",
|
|
71
|
+
description: "This will create just a Home Screen Widget.",
|
|
72
|
+
value: 2,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
initial: 1,
|
|
76
|
+
});
|
|
77
|
+
const bundleId = this.$projectConfigService.getValue(`id`, "");
|
|
78
|
+
if ([0, 1].includes(result.value)) {
|
|
79
|
+
await this.generateSharedWidgetPackage(this.$projectData.projectDir, name);
|
|
80
|
+
}
|
|
81
|
+
this.generateWidget(this.$projectData.projectDir, name, bundleId, result.value);
|
|
82
|
+
this.generateAppleUtility(this.$projectData.projectDir, name, bundleId, result.value);
|
|
83
|
+
}
|
|
84
|
+
async generateSharedWidgetPackage(projectDir, name) {
|
|
85
|
+
var _a;
|
|
86
|
+
const sharedWidgetDir = "Shared_Resources/iOS/SharedWidget";
|
|
87
|
+
const sharedWidgetPath = path.join(projectDir, sharedWidgetDir);
|
|
88
|
+
const sharedWidgetSourceDir = "Sources/SharedWidget";
|
|
89
|
+
const sharedWidgetPackagePath = path.join(projectDir, `${sharedWidgetDir}/Package.swift`);
|
|
90
|
+
const sharedWidgetSourcePath = path.join(sharedWidgetPath, `${sharedWidgetSourceDir}/${(0, utils_1.capitalizeFirstLetter)(name)}Model.swift`);
|
|
91
|
+
const gitIgnorePath = path.join(projectDir, ".gitignore");
|
|
92
|
+
if (!fs.existsSync(sharedWidgetPackagePath)) {
|
|
93
|
+
fs.mkdirSync(sharedWidgetPath, { recursive: true });
|
|
94
|
+
fs.mkdirSync(path.join(sharedWidgetPath, sharedWidgetSourceDir), {
|
|
95
|
+
recursive: true,
|
|
96
|
+
});
|
|
97
|
+
let content = `// swift-tools-version:5.9
|
|
98
|
+
import PackageDescription
|
|
99
|
+
|
|
100
|
+
let package = Package(
|
|
101
|
+
name: "SharedWidget",
|
|
102
|
+
platforms: [
|
|
103
|
+
.iOS(.v13)
|
|
104
|
+
],
|
|
105
|
+
products: [
|
|
106
|
+
.library(
|
|
107
|
+
name: "SharedWidget",
|
|
108
|
+
targets: ["SharedWidget"])
|
|
109
|
+
],
|
|
110
|
+
dependencies: [
|
|
111
|
+
// Dependencies declare other packages that this package depends on.
|
|
112
|
+
],
|
|
113
|
+
targets: [
|
|
114
|
+
.target(
|
|
115
|
+
name: "SharedWidget",
|
|
116
|
+
dependencies: []
|
|
117
|
+
)
|
|
118
|
+
]
|
|
119
|
+
)${os_1.EOL}`;
|
|
120
|
+
fs.writeFileSync(sharedWidgetPackagePath, content);
|
|
121
|
+
content = `import ActivityKit
|
|
122
|
+
import WidgetKit
|
|
123
|
+
|
|
124
|
+
public struct ${(0, utils_1.capitalizeFirstLetter)(name)}Model: ActivityAttributes {
|
|
125
|
+
public typealias DeliveryStatus = ContentState
|
|
126
|
+
|
|
127
|
+
public struct ContentState: Codable, Hashable {
|
|
128
|
+
// Dynamic stateful properties about your activity go here!
|
|
129
|
+
public var message: String
|
|
130
|
+
public var deliveryTime: Double
|
|
131
|
+
|
|
132
|
+
public init(message: String, deliveryTime: Double) {
|
|
133
|
+
self.message = message
|
|
134
|
+
self.deliveryTime = deliveryTime
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Fixed non-changing properties about your activity go here!
|
|
139
|
+
public var numberOfPizzas: Int
|
|
140
|
+
public var totalAmount: String
|
|
141
|
+
|
|
142
|
+
public init(numberOfPizzas: Int, totalAmount: String) {
|
|
143
|
+
self.numberOfPizzas = numberOfPizzas
|
|
144
|
+
self.totalAmount = totalAmount
|
|
145
|
+
}
|
|
146
|
+
}${os_1.EOL}`;
|
|
147
|
+
fs.writeFileSync(sharedWidgetSourcePath, content);
|
|
148
|
+
const configData = this.$projectConfigService.readConfig(projectDir);
|
|
149
|
+
if (!configData.ios) {
|
|
150
|
+
configData.ios = {};
|
|
151
|
+
}
|
|
152
|
+
if (!configData.ios.SPMPackages) {
|
|
153
|
+
configData.ios.SPMPackages = [];
|
|
154
|
+
}
|
|
155
|
+
const spmPackages = configData.ios.SPMPackages;
|
|
156
|
+
const sharedWidgetPackage = spmPackages === null || spmPackages === void 0 ? void 0 : spmPackages.find((p) => p.name === "SharedWidget");
|
|
157
|
+
if (!sharedWidgetPackage) {
|
|
158
|
+
spmPackages.push({
|
|
159
|
+
name: "SharedWidget",
|
|
160
|
+
libs: ["SharedWidget"],
|
|
161
|
+
path: "./Shared_Resources/iOS/SharedWidget",
|
|
162
|
+
targets: [name],
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
if (!((_a = sharedWidgetPackage.targets) === null || _a === void 0 ? void 0 : _a.includes(name))) {
|
|
167
|
+
sharedWidgetPackage.targets.push(name);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
configData.ios.SPMPackages = spmPackages;
|
|
171
|
+
await this.$projectConfigService.setValue("", configData);
|
|
172
|
+
if (fs.existsSync(gitIgnorePath)) {
|
|
173
|
+
const gitIgnore = fs.readFileSync(gitIgnorePath, {
|
|
174
|
+
encoding: "utf-8",
|
|
175
|
+
});
|
|
176
|
+
const swiftBuildIgnore = `# Swift
|
|
177
|
+
.build
|
|
178
|
+
.swiftpm`;
|
|
179
|
+
if (gitIgnore.indexOf(swiftBuildIgnore) === -1) {
|
|
180
|
+
content = `${gitIgnore}${os_1.EOL}${swiftBuildIgnore}${os_1.EOL}`;
|
|
181
|
+
fs.writeFileSync(gitIgnorePath, content);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
console.log(`\nCreated Shared Resources: ${sharedWidgetDir}.\n`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
generateWidget(projectDir, name, bundleId, type) {
|
|
188
|
+
const appResourcePath = this.$projectData.appResourcesDirectoryPath;
|
|
189
|
+
const capitalName = (0, utils_1.capitalizeFirstLetter)(name);
|
|
190
|
+
const appInfoPlistPath = path.join(appResourcePath, "iOS", "Info.plist");
|
|
191
|
+
const extensionDir = path.join(appResourcePath, "iOS", "extensions");
|
|
192
|
+
const widgetPath = path.join(extensionDir, name);
|
|
193
|
+
const extensionProvisionPath = path.join(extensionDir, `provisioning.json`);
|
|
194
|
+
const extensionsInfoPath = path.join(widgetPath, `Info.plist`);
|
|
195
|
+
const extensionsPrivacyPath = path.join(widgetPath, `PrivacyInfo.xcprivacy`);
|
|
196
|
+
const extensionsConfigPath = path.join(widgetPath, `extension.json`);
|
|
197
|
+
const entitlementsPath = path.join(widgetPath, `${name}.entitlements`);
|
|
198
|
+
const widgetBundlePath = path.join(widgetPath, `${capitalName}Bundle.swift`);
|
|
199
|
+
const widgetHomeScreenPath = path.join(widgetPath, `${capitalName}HomeScreenWidget.swift`);
|
|
200
|
+
const widgetLiveActivityPath = path.join(widgetPath, `${capitalName}LiveActivity.swift`);
|
|
201
|
+
const appEntitlementsPath = path.join(appResourcePath, "iOS", "app.entitlements");
|
|
202
|
+
if (!fs.existsSync(extensionsConfigPath)) {
|
|
203
|
+
fs.mkdirSync(widgetPath, { recursive: true });
|
|
204
|
+
let content = `<?xml version="1.0" encoding="UTF-8"?>
|
|
205
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
206
|
+
<plist version="1.0">
|
|
207
|
+
<dict>
|
|
208
|
+
<key>NSExtension</key>
|
|
209
|
+
<dict>
|
|
210
|
+
<key>NSExtensionPointIdentifier</key>
|
|
211
|
+
<string>com.apple.widgetkit-extension</string>
|
|
212
|
+
</dict>
|
|
213
|
+
<key>CFBundleShortVersionString</key>
|
|
214
|
+
<string>1.0</string>
|
|
215
|
+
<key>CFBundleVersion</key>
|
|
216
|
+
<string>1.0</string>
|
|
217
|
+
</dict>
|
|
218
|
+
</plist>${os_1.EOL}`;
|
|
219
|
+
fs.writeFileSync(extensionsInfoPath, content);
|
|
220
|
+
content = `<?xml version="1.0" encoding="UTF-8"?>
|
|
221
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
222
|
+
<plist version="1.0">
|
|
223
|
+
<dict>
|
|
224
|
+
<key>NSPrivacyAccessedAPITypes</key>
|
|
225
|
+
<array>
|
|
226
|
+
<dict>
|
|
227
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
228
|
+
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
|
229
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
230
|
+
<array>
|
|
231
|
+
<string>CA92.1</string>
|
|
232
|
+
</array>
|
|
233
|
+
</dict>
|
|
234
|
+
</array>
|
|
235
|
+
<key>NSPrivacyCollectedDataTypes</key>
|
|
236
|
+
<array/>
|
|
237
|
+
<key>NSPrivacyTracking</key>
|
|
238
|
+
<false/>
|
|
239
|
+
</dict>
|
|
240
|
+
</plist>${os_1.EOL}`;
|
|
241
|
+
fs.writeFileSync(extensionsPrivacyPath, content);
|
|
242
|
+
content = `import WidgetKit
|
|
243
|
+
import SwiftUI
|
|
244
|
+
|
|
245
|
+
@main
|
|
246
|
+
struct ${capitalName}Bundle: SwiftUI.WidgetBundle {
|
|
247
|
+
var body: some Widget {
|
|
248
|
+
${[1, 2].includes(type) ? capitalName + "HomeScreenWidget()" : ""}
|
|
249
|
+
${[0, 1].includes(type) ? capitalName + "LiveActivity()" : ""}
|
|
250
|
+
}
|
|
251
|
+
}${os_1.EOL}`;
|
|
252
|
+
fs.writeFileSync(widgetBundlePath, content);
|
|
253
|
+
if ([0, 1].includes(type)) {
|
|
254
|
+
content = `import ActivityKit
|
|
255
|
+
import SwiftUI
|
|
256
|
+
import WidgetKit
|
|
257
|
+
import Foundation
|
|
258
|
+
import SharedWidget
|
|
259
|
+
import os
|
|
260
|
+
|
|
261
|
+
struct ${capitalName}LiveActivity: Widget {
|
|
262
|
+
|
|
263
|
+
var body: some WidgetConfiguration {
|
|
264
|
+
ActivityConfiguration(for: ${capitalName}Model.self) { context in
|
|
265
|
+
|
|
266
|
+
LockScreenView(message: context.state.message, deliveryTime: context.state.deliveryTime)
|
|
267
|
+
.activityBackgroundTint(Color.black)
|
|
268
|
+
.activitySystemActionForegroundColor(Color.white)
|
|
269
|
+
|
|
270
|
+
} dynamicIsland: { context in
|
|
271
|
+
DynamicIsland {
|
|
272
|
+
DynamicIslandExpandedRegion(.leading) {
|
|
273
|
+
Image(systemName: context.state.deliveryTime >= 0 ? "car.side.arrowtriangle.up.fill" : "face.smiling.inverse")
|
|
274
|
+
.resizable()
|
|
275
|
+
.scaledToFit()
|
|
276
|
+
.frame(width: 50, height: 50)
|
|
277
|
+
.foregroundColor(context.state.deliveryTime >= 0 ? Color.green : Color.blue)
|
|
278
|
+
}
|
|
279
|
+
DynamicIslandExpandedRegion(.trailing) {
|
|
280
|
+
if (context.state.deliveryTime >= 0) {
|
|
281
|
+
ZStack {
|
|
282
|
+
ProgressView(value: context.state.deliveryTime, total: 60)
|
|
283
|
+
.progressViewStyle(.circular)
|
|
284
|
+
.tint(Color.green)
|
|
285
|
+
.frame(width: 75, height: 75)
|
|
286
|
+
Text("\\(formatter.string(for: context.state.deliveryTime) ?? "") mins")
|
|
287
|
+
.font(.system(size: 11))
|
|
288
|
+
.foregroundStyle(.white)
|
|
289
|
+
}.frame(width: 75, height: 75)
|
|
290
|
+
} else {
|
|
291
|
+
Image(systemName: "checkmark.circle.fill")
|
|
292
|
+
.resizable()
|
|
293
|
+
.scaledToFit()
|
|
294
|
+
.frame(width: 50, height: 50)
|
|
295
|
+
.foregroundColor(.blue)
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
DynamicIslandExpandedRegion(.bottom) {
|
|
299
|
+
Text("\\(context.state.message)")
|
|
300
|
+
}
|
|
301
|
+
} compactLeading: {
|
|
302
|
+
Image(systemName: context.state.deliveryTime >= 0 ? "car.side.arrowtriangle.up.fill" : "face.smiling.inverse")
|
|
303
|
+
.resizable()
|
|
304
|
+
.scaledToFit()
|
|
305
|
+
.frame(width: 20, height: 20)
|
|
306
|
+
.foregroundColor(context.state.deliveryTime >= 0 ? .green : .blue)
|
|
307
|
+
} compactTrailing: {
|
|
308
|
+
Image(systemName: context.state.deliveryTime >= 0 ? "timer.circle.fill" : "checkmark.circle.fill")
|
|
309
|
+
.resizable()
|
|
310
|
+
.scaledToFit()
|
|
311
|
+
.frame(width: 20, height: 20)
|
|
312
|
+
.foregroundColor(context.state.deliveryTime >= 0 ? .green : .blue)
|
|
313
|
+
} minimal: {
|
|
314
|
+
Text(context.state.message).font(.system(size: 12))
|
|
315
|
+
}
|
|
316
|
+
.widgetURL(URL(string: "http://www.apple.com"))
|
|
317
|
+
.keylineTint(Color.red)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private let formatter: NumberFormatter = {
|
|
322
|
+
let formatter = NumberFormatter()
|
|
323
|
+
formatter.maximumFractionDigits = 0
|
|
324
|
+
formatter.minimumFractionDigits = 0
|
|
325
|
+
return formatter
|
|
326
|
+
}()
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
struct LockScreenView: View {
|
|
330
|
+
@State private var message = ""
|
|
331
|
+
@State private var deliveryTime: Double = 0
|
|
332
|
+
// for console debugging
|
|
333
|
+
let logger = Logger(subsystem: "${bundleId}.${name}", category: "Widget")
|
|
334
|
+
|
|
335
|
+
var body: some View {
|
|
336
|
+
ZStack {
|
|
337
|
+
LinearGradient(
|
|
338
|
+
gradient: Gradient(colors: [Color.gray.opacity(0.3), Color.black]),
|
|
339
|
+
startPoint: .top,
|
|
340
|
+
endPoint: .bottom
|
|
341
|
+
)
|
|
342
|
+
VStack {
|
|
343
|
+
Spacer()
|
|
344
|
+
Image(systemName: deliveryTime >= 0 ? "car.side.arrowtriangle.up.fill" : "face.smiling.inverse")
|
|
345
|
+
.resizable()
|
|
346
|
+
.scaledToFit()
|
|
347
|
+
.frame(width: 50, height: 50)
|
|
348
|
+
.foregroundColor(deliveryTime >= 0 ? .green : .blue)
|
|
349
|
+
Spacer()
|
|
350
|
+
Text("\\(message)")
|
|
351
|
+
.foregroundStyle(.white)
|
|
352
|
+
Spacer()
|
|
353
|
+
}
|
|
354
|
+
}.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
init(message: String = "", deliveryTime: Double = 0) {
|
|
358
|
+
_message = State(initialValue: message)
|
|
359
|
+
_deliveryTime = State(initialValue: deliveryTime)
|
|
360
|
+
|
|
361
|
+
// Logs the deliveryTime at init for debugging purposes if needed
|
|
362
|
+
logger.log("deliveryTime: \\(deliveryTime)")
|
|
363
|
+
}
|
|
364
|
+
}${os_1.EOL}`;
|
|
365
|
+
fs.writeFileSync(widgetLiveActivityPath, content);
|
|
366
|
+
}
|
|
367
|
+
if ([1, 2].includes(type)) {
|
|
368
|
+
content = `import SwiftUI
|
|
369
|
+
import WidgetKit
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Widget data shared between the app and the widget extension.
|
|
373
|
+
*/
|
|
374
|
+
struct WidgetData: Codable {
|
|
375
|
+
let pizzas: [String]
|
|
376
|
+
let orderTime: Double
|
|
377
|
+
let delivered: Bool
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
struct Provider: TimelineProvider {
|
|
381
|
+
|
|
382
|
+
func placeholder(in context: Context) -> SimpleEntry {
|
|
383
|
+
SimpleEntry(date: Date(), pizza: "Pepperoni", delivered: false, orderTime: Date())
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
|
|
387
|
+
let entry = SimpleEntry(date: Date(), pizza: "Pepperoni", delivered: false, orderTime: Date())
|
|
388
|
+
completion(entry)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
func getTimeline(in context: Context, completion: @escaping @Sendable (Timeline<Entry>) -> ()) {
|
|
392
|
+
var entries: [SimpleEntry] = []
|
|
393
|
+
|
|
394
|
+
if let sharedDefaults = UserDefaults(suiteName: "group.${bundleId}") {
|
|
395
|
+
let currentDate = Date()
|
|
396
|
+
if let jsonString = sharedDefaults.string(forKey: "widgetData") {
|
|
397
|
+
if let jsonData = jsonString.data(using: .utf8) {
|
|
398
|
+
do {
|
|
399
|
+
let widgetData = try JSONDecoder().decode(WidgetData.self, from: jsonData)
|
|
400
|
+
let pizzas = widgetData.pizzas
|
|
401
|
+
let orderTime = Date(timeIntervalSince1970: widgetData.orderTime/1000)
|
|
402
|
+
let delivered = widgetData.delivered
|
|
403
|
+
|
|
404
|
+
// Generate a timeline of entries 1 second apart, starting from the current date.
|
|
405
|
+
for secondOffset in 0..<pizzas.count {
|
|
406
|
+
let entryDate = Calendar.current.date(
|
|
407
|
+
byAdding: .second, value: secondOffset, to: currentDate)!
|
|
408
|
+
let entry = SimpleEntry(date: entryDate, pizza: secondOffset < pizzas.count ? pizzas[secondOffset] : pizzas[0], delivered: delivered, orderTime: orderTime)
|
|
409
|
+
entries.append(entry)
|
|
410
|
+
}
|
|
411
|
+
} catch {
|
|
412
|
+
print("Failed to decode JSON: (error)")
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
} else {
|
|
416
|
+
let entry = SimpleEntry(date: currentDate, pizza: "", delivered: false, orderTime: nil)
|
|
417
|
+
entries.append(entry)
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
let timeline = Timeline(entries: entries, policy: .atEnd)
|
|
422
|
+
completion(timeline)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// func relevances() async -> WidgetRelevances<Void> {
|
|
426
|
+
// // Generate a list containing the contexts this widget is relevant in.
|
|
427
|
+
// }
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
struct SimpleEntry: TimelineEntry {
|
|
431
|
+
let date: Date
|
|
432
|
+
let pizza: String
|
|
433
|
+
let delivered: Bool
|
|
434
|
+
let orderTime: Date?
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
struct WidgetView: View {
|
|
438
|
+
@Environment(\\.widgetFamily) var widgetFamily
|
|
439
|
+
var entry: Provider.Entry
|
|
440
|
+
|
|
441
|
+
var body: some View {
|
|
442
|
+
VStack {
|
|
443
|
+
if (entry.pizza != "") {
|
|
444
|
+
Spacer()
|
|
445
|
+
Image(systemName: entry.delivered ? "face.smiling.inverse" : "car.side")
|
|
446
|
+
.resizable()
|
|
447
|
+
.scaledToFit()
|
|
448
|
+
.frame(width: iconSize(for: widgetFamily), height: iconSize(for: widgetFamily))
|
|
449
|
+
.foregroundColor(entry.delivered ? .blue : .green)
|
|
450
|
+
Spacer()
|
|
451
|
+
if (entry.delivered) {
|
|
452
|
+
Text("Pizza Delivered!")
|
|
453
|
+
.font(.system(size: fontSize(for: widgetFamily), weight: .bold))
|
|
454
|
+
.foregroundStyle(.white)
|
|
455
|
+
} else {
|
|
456
|
+
HStack(spacing: 4) {
|
|
457
|
+
Text("Ordered:")
|
|
458
|
+
.font(.system(size: fontSize(for: widgetFamily)))
|
|
459
|
+
.foregroundStyle(.white)
|
|
460
|
+
Text(entry.orderTime!, style: .time)
|
|
461
|
+
.font(.system(size: fontSize(for: widgetFamily), weight: .bold))
|
|
462
|
+
.foregroundStyle(.white)
|
|
463
|
+
}
|
|
464
|
+
HStack(spacing: 4) {
|
|
465
|
+
Text("Pizza:")
|
|
466
|
+
.font(.system(size: fontSize(for: widgetFamily)))
|
|
467
|
+
.foregroundStyle(.white)
|
|
468
|
+
Text(entry.pizza)
|
|
469
|
+
.font(.system(size: fontSize(for: widgetFamily), weight: .bold))
|
|
470
|
+
.foregroundStyle(.white)
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
Spacer()
|
|
474
|
+
} else {
|
|
475
|
+
Spacer()
|
|
476
|
+
Image(systemName: "car.side.rear.open")
|
|
477
|
+
.resizable()
|
|
478
|
+
.scaledToFit()
|
|
479
|
+
.frame(width: iconSize(for: widgetFamily), height: iconSize(for: widgetFamily))
|
|
480
|
+
.foregroundColor(.gray)
|
|
481
|
+
Spacer()
|
|
482
|
+
Text("Awaiting orders...")
|
|
483
|
+
.foregroundStyle(.white)
|
|
484
|
+
Spacer()
|
|
485
|
+
}
|
|
486
|
+
}.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
private func iconSize(for family: WidgetFamily) -> CGFloat {
|
|
490
|
+
switch family {
|
|
491
|
+
case .systemSmall:
|
|
492
|
+
return 65
|
|
493
|
+
case .systemMedium:
|
|
494
|
+
return 85
|
|
495
|
+
case .systemLarge:
|
|
496
|
+
return 150
|
|
497
|
+
default:
|
|
498
|
+
return 65
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private func fontSize(for family: WidgetFamily) -> CGFloat {
|
|
503
|
+
switch family {
|
|
504
|
+
case .systemSmall:
|
|
505
|
+
return 12
|
|
506
|
+
case .systemMedium:
|
|
507
|
+
return 14
|
|
508
|
+
case .systemLarge:
|
|
509
|
+
return 18
|
|
510
|
+
default:
|
|
511
|
+
return 14
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
@available(iOSApplicationExtension 17.0, *)
|
|
517
|
+
struct ${capitalName}HomeScreenWidget: Widget {
|
|
518
|
+
let kind: String = "widget"
|
|
519
|
+
|
|
520
|
+
var body: some WidgetConfiguration {
|
|
521
|
+
StaticConfiguration(kind: kind, provider: Provider()) { entry in
|
|
522
|
+
WidgetView(entry: entry)
|
|
523
|
+
.containerBackground(for: .widget) {
|
|
524
|
+
LinearGradient(
|
|
525
|
+
gradient: Gradient(colors: [Color.black.opacity(0.6), Color.black]),
|
|
526
|
+
startPoint: .top,
|
|
527
|
+
endPoint: .bottom
|
|
528
|
+
)
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
.configurationDisplayName("${capitalName} Widget")
|
|
532
|
+
.description("${capitalName} delivery service.")
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
#Preview(as: .systemSmall) {
|
|
537
|
+
${capitalName}HomeScreenWidget()
|
|
538
|
+
} timeline: {
|
|
539
|
+
SimpleEntry(date: .now, pizza: "Pepperoni", delivered: false, orderTime: Date())
|
|
540
|
+
SimpleEntry(date: .now, pizza: "Hawaiian", delivered: false, orderTime: Date())
|
|
541
|
+
}${os_1.EOL}`;
|
|
542
|
+
fs.writeFileSync(widgetHomeScreenPath, content);
|
|
543
|
+
}
|
|
544
|
+
content = `{
|
|
545
|
+
"${bundleId}.${name}": "{set-your-provision-profile-id}"
|
|
546
|
+
}`;
|
|
547
|
+
fs.writeFileSync(extensionProvisionPath, content);
|
|
548
|
+
content = `<?xml version="1.0" encoding="UTF-8"?>
|
|
549
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
550
|
+
<plist version="1.0">
|
|
551
|
+
<dict>
|
|
552
|
+
<key>com.apple.security.application-groups</key>
|
|
553
|
+
<array>
|
|
554
|
+
<string>group.${bundleId}</string>
|
|
555
|
+
</array>
|
|
556
|
+
</dict>
|
|
557
|
+
</plist>${os_1.EOL}`;
|
|
558
|
+
fs.writeFileSync(entitlementsPath, content);
|
|
559
|
+
if (fs.existsSync(appInfoPlistPath)) {
|
|
560
|
+
const appSupportLiveActivity = "NSSupportsLiveActivities";
|
|
561
|
+
const appInfoPlist = plist.parse(fs.readFileSync(appInfoPlistPath, {
|
|
562
|
+
encoding: "utf-8",
|
|
563
|
+
}));
|
|
564
|
+
if (!appInfoPlist[appSupportLiveActivity]) {
|
|
565
|
+
appInfoPlist[appSupportLiveActivity] = true;
|
|
566
|
+
const appPlist = plist.build(appInfoPlist);
|
|
567
|
+
fs.writeFileSync(appInfoPlistPath, appPlist);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
const appGroupKey = "com.apple.security.application-groups";
|
|
571
|
+
if (fs.existsSync(appEntitlementsPath)) {
|
|
572
|
+
const appEntitlementsPlist = plist.parse(fs.readFileSync(appEntitlementsPath, {
|
|
573
|
+
encoding: "utf-8",
|
|
574
|
+
}));
|
|
575
|
+
if (!appEntitlementsPlist[appGroupKey]) {
|
|
576
|
+
appEntitlementsPlist[appGroupKey] = [`group.${bundleId}`];
|
|
577
|
+
const appEntitlements = plist.build(appEntitlementsPlist);
|
|
578
|
+
console.log("appentitlement:", appEntitlements);
|
|
579
|
+
fs.writeFileSync(appEntitlementsPath, appEntitlements);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
content = `<?xml version="1.0" encoding="UTF-8"?>
|
|
584
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
585
|
+
<plist version="1.0">
|
|
586
|
+
<dict>
|
|
587
|
+
<key>com.apple.security.application-groups</key>
|
|
588
|
+
<array>
|
|
589
|
+
<string>group.${bundleId}</string>
|
|
590
|
+
</array>
|
|
591
|
+
</dict>
|
|
592
|
+
</plist>${os_1.EOL}`;
|
|
593
|
+
fs.writeFileSync(appEntitlementsPath, content);
|
|
594
|
+
}
|
|
595
|
+
content = `{
|
|
596
|
+
"frameworks": [
|
|
597
|
+
"SwiftUI.framework",
|
|
598
|
+
"WidgetKit.framework"
|
|
599
|
+
],
|
|
600
|
+
"targetBuildConfigurationProperties": {
|
|
601
|
+
"ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME": "AccentColor",
|
|
602
|
+
"ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME": "WidgetBackground",
|
|
603
|
+
"CLANG_ANALYZER_NONNULL": "YES",
|
|
604
|
+
"CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION": "YES_AGGRESSIVE",
|
|
605
|
+
"CLANG_CXX_LANGUAGE_STANDARD": "\\"gnu++20\\"",
|
|
606
|
+
"CLANG_ENABLE_OBJC_WEAK": "YES",
|
|
607
|
+
"CLANG_WARN_DOCUMENTATION_COMMENTS": "YES",
|
|
608
|
+
"CLANG_WARN_UNGUARDED_AVAILABILITY": "YES_AGGRESSIVE",
|
|
609
|
+
"CURRENT_PROJECT_VERSION": 1,
|
|
610
|
+
"GCC_C_LANGUAGE_STANDARD": "gnu11",
|
|
611
|
+
"GCC_WARN_UNINITIALIZED_AUTOS": "YES_AGGRESSIVE",
|
|
612
|
+
"GENERATE_INFOPLIST_FILE": "YES",
|
|
613
|
+
"INFOPLIST_KEY_CFBundleDisplayName": "widget",
|
|
614
|
+
"INFOPLIST_KEY_NSHumanReadableCopyright": "\\"Copyright © All rights reserved.\\"",
|
|
615
|
+
"IPHONEOS_DEPLOYMENT_TARGET": 18.0,
|
|
616
|
+
"MARKETING_VERSION": "1.0",
|
|
617
|
+
"MTL_FAST_MATH": "YES",
|
|
618
|
+
"PRODUCT_NAME": "widget",
|
|
619
|
+
"SWIFT_EMIT_LOC_STRINGS": "YES",
|
|
620
|
+
"SWIFT_VERSION": "5.0",
|
|
621
|
+
"TARGETED_DEVICE_FAMILY": "\\"1,2\\"",
|
|
622
|
+
"MTL_ENABLE_DEBUG_INFO": "NO",
|
|
623
|
+
"SWIFT_OPTIMIZATION_LEVEL": "\\"-O\\"",
|
|
624
|
+
"COPY_PHASE_STRIP": "NO",
|
|
625
|
+
"SWIFT_COMPILATION_MODE": "wholemodule",
|
|
626
|
+
"CODE_SIGN_ENTITLEMENTS": "../../App_Resources/iOS/extensions/${name}/${name}.entitlements"
|
|
627
|
+
},
|
|
628
|
+
"targetNamedBuildConfigurationProperties": {
|
|
629
|
+
"debug": {
|
|
630
|
+
"DEBUG_INFORMATION_FORMAT": "dwarf",
|
|
631
|
+
"GCC_PREPROCESSOR_DEFINITIONS": "(\\"DEBUG=1\\",\\"$(inherited)\\",)",
|
|
632
|
+
"MTL_ENABLE_DEBUG_INFO": "INCLUDE_SOURCE",
|
|
633
|
+
"SWIFT_ACTIVE_COMPILATION_CONDITIONS": "DEBUG",
|
|
634
|
+
"SWIFT_OPTIMIZATION_LEVEL": "\\"-Onone\\""
|
|
635
|
+
},
|
|
636
|
+
"release": {
|
|
637
|
+
"CODE_SIGN_STYLE": "Manual",
|
|
638
|
+
"MTL_ENABLE_DEBUG_INFO": "NO",
|
|
639
|
+
"SWIFT_OPTIMIZATION_LEVEL": "\\"-O\\"",
|
|
640
|
+
"COPY_PHASE_STRIP": "NO",
|
|
641
|
+
"SWIFT_COMPILATION_MODE": "wholemodule"
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}${os_1.EOL}`;
|
|
645
|
+
fs.writeFileSync(extensionsConfigPath, content);
|
|
646
|
+
console.log(`🚀 Your widget is now ready to develop: App_Resources/iOS/extensions/${name}.\n`);
|
|
647
|
+
const steps = ["Followup steps:"];
|
|
648
|
+
steps.push("- Check App_Resources/iOS/build.xcconfig uses IPHONEOS_DEPLOYMENT_TARGET = 17 or higher.");
|
|
649
|
+
steps.push("- Update App_Resources/iOS/extensions/provisioning.json with your profile id.");
|
|
650
|
+
if ([0, 1].includes(type)) {
|
|
651
|
+
steps.push(`- Customize App_Resources/iOS/extensions/${name}/${(0, utils_1.capitalizeFirstLetter)(name)}LiveActivity.swift for your display.`);
|
|
652
|
+
steps.push(`- Customize Shared_Resources/iOS/SharedWidget/Sources/SharedWidget/${(0, utils_1.capitalizeFirstLetter)(name)}Model.swift for your data.`);
|
|
653
|
+
}
|
|
654
|
+
console.log(steps.join("\n"));
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
generateAppleUtility(projectDir, name, bundleId, type) {
|
|
658
|
+
const capitalName = (0, utils_1.capitalizeFirstLetter)(name);
|
|
659
|
+
const appResourcePath = this.$projectData.appResourcesDirectoryPath;
|
|
660
|
+
const appResourceSrcPath = path.join(appResourcePath, "iOS", "src");
|
|
661
|
+
const appleUtilityPath = path.join(appResourceSrcPath, `AppleWidgetUtils.swift`);
|
|
662
|
+
const referenceTypesPath = path.join(projectDir, "references.d.ts");
|
|
663
|
+
if (!fs.existsSync(appleUtilityPath)) {
|
|
664
|
+
fs.mkdirSync(appResourceSrcPath, { recursive: true });
|
|
665
|
+
}
|
|
666
|
+
if (!fs.existsSync(appleUtilityPath)) {
|
|
667
|
+
}
|
|
668
|
+
const liveActivityUtilities = `// Live Activity Handling
|
|
669
|
+
public static func startActivity(_ data: NSDictionary) {
|
|
670
|
+
if ActivityAuthorizationInfo().areActivitiesEnabled {
|
|
671
|
+
let numberOfPizzas = data.object(forKey: "numberOfPizzas") as! Int
|
|
672
|
+
let totalAmount = data.object(forKey: "totalAmount") as! String
|
|
673
|
+
let attrs = ${capitalName}Model(numberOfPizzas: numberOfPizzas, totalAmount: totalAmount)
|
|
674
|
+
|
|
675
|
+
let message = data.object(forKey: "message") as! String
|
|
676
|
+
let deliveryTime = data.object(forKey: "deliveryTime") as! Double
|
|
677
|
+
let initialStatus = ${capitalName}Model.DeliveryStatus(
|
|
678
|
+
message: message, deliveryTime: deliveryTime)
|
|
679
|
+
let content = ActivityContent(state: initialStatus, staleDate: nil)
|
|
680
|
+
|
|
681
|
+
do {
|
|
682
|
+
let activity = try Activity<${capitalName}Model>.request(
|
|
683
|
+
attributes: attrs,
|
|
684
|
+
content: content,
|
|
685
|
+
pushType: nil)
|
|
686
|
+
print("Requested a Live Activity \\(activity.id)")
|
|
687
|
+
} catch (let error) {
|
|
688
|
+
print("Error requesting Live Activity \\(error.localizedDescription)")
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
public static func updateActivity(_ data: NSDictionary) {
|
|
693
|
+
if ActivityAuthorizationInfo().areActivitiesEnabled {
|
|
694
|
+
Task {
|
|
695
|
+
let message = data.object(forKey: "message") as! String
|
|
696
|
+
let deliveryTime = data.object(forKey: "deliveryTime") as! Double
|
|
697
|
+
let status = ${capitalName}Model.DeliveryStatus(
|
|
698
|
+
message: message, deliveryTime: deliveryTime)
|
|
699
|
+
let content = ActivityContent(state: status, staleDate: nil)
|
|
700
|
+
|
|
701
|
+
for activity in Activity<${capitalName}Model>.activities {
|
|
702
|
+
await activity.update(content)
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
public static func cancelActivity(_ data: NSDictionary) {
|
|
708
|
+
if ActivityAuthorizationInfo().areActivitiesEnabled {
|
|
709
|
+
Task {
|
|
710
|
+
let message = data.object(forKey: "message") as! String
|
|
711
|
+
let status = ${capitalName}Model.DeliveryStatus(
|
|
712
|
+
message: message, deliveryTime: 0)
|
|
713
|
+
let content = ActivityContent(state: status, staleDate: nil)
|
|
714
|
+
|
|
715
|
+
for activity in Activity<${capitalName}Model>.activities {
|
|
716
|
+
await activity.end(content, dismissalPolicy: .immediate)
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}`;
|
|
721
|
+
let content = `import Foundation
|
|
722
|
+
import UIKit
|
|
723
|
+
import ActivityKit
|
|
724
|
+
import WidgetKit
|
|
725
|
+
${[0, 1].includes(type) ? "import SharedWidget" : ""}
|
|
726
|
+
|
|
727
|
+
@objcMembers
|
|
728
|
+
public class AppleWidgetUtils: NSObject {
|
|
729
|
+
${[0, 1].includes(type) ? liveActivityUtilities : ""}
|
|
730
|
+
// Shared App Group Data
|
|
731
|
+
public static func getData(key: String) -> String? {
|
|
732
|
+
guard let sharedDefaults = UserDefaults(suiteName: "group.${bundleId}") else {
|
|
733
|
+
return nil
|
|
734
|
+
}
|
|
735
|
+
return sharedDefaults.object(forKey: key) as? String
|
|
736
|
+
}
|
|
737
|
+
public static func updateData(key: String, _ data: String) {
|
|
738
|
+
guard let sharedDefaults = UserDefaults(suiteName: "group.${bundleId}") else {
|
|
739
|
+
return
|
|
740
|
+
}
|
|
741
|
+
sharedDefaults.set(data, forKey: key)
|
|
742
|
+
sharedDefaults.synchronize()
|
|
743
|
+
}
|
|
744
|
+
public static func removeData(key: String) {
|
|
745
|
+
guard let sharedDefaults = UserDefaults(suiteName: "group.${bundleId}") else {
|
|
746
|
+
return
|
|
747
|
+
}
|
|
748
|
+
sharedDefaults.removeObject(forKey: key)
|
|
749
|
+
sharedDefaults.synchronize()
|
|
750
|
+
}
|
|
751
|
+
// Home Screen Widget Handling
|
|
752
|
+
public static func updateWidget() {
|
|
753
|
+
if #available(iOS 14.0, *) {
|
|
754
|
+
Task.detached(priority: .userInitiated) {
|
|
755
|
+
WidgetCenter.shared.reloadAllTimelines()
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}${os_1.EOL}`;
|
|
760
|
+
fs.writeFileSync(appleUtilityPath, content);
|
|
761
|
+
content = `/**
|
|
762
|
+
* Customize for your own Apple Widget Data
|
|
763
|
+
*/
|
|
764
|
+
declare interface AppleWidgetModelData {
|
|
765
|
+
numberOfPizzas: number;
|
|
766
|
+
totalAmount: string;
|
|
767
|
+
message: string;
|
|
768
|
+
deliveryTime: number;
|
|
769
|
+
}
|
|
770
|
+
declare class AppleWidgetUtils extends NSObject {
|
|
771
|
+
static startActivity(data: AppleWidgetModelData): void;
|
|
772
|
+
static updateActivity(
|
|
773
|
+
data: Pick<AppleWidgetModelData, "message" | "deliveryTime">
|
|
774
|
+
): void;
|
|
775
|
+
static cancelActivity(data: Pick<AppleWidgetModelData, "message">): void;
|
|
776
|
+
static updateWidget(): void;
|
|
777
|
+
static updateDataWithKey(key: string, data: string): void;
|
|
778
|
+
static getDataWithKey(key: string): string;
|
|
779
|
+
static removeDataWithKey(key: string): void;
|
|
780
|
+
}${os_1.EOL}`;
|
|
781
|
+
if (!fs.existsSync(referenceTypesPath)) {
|
|
782
|
+
const references = `/// <reference path="./node_modules/@nativescript/types-android/index.d.ts" />
|
|
783
|
+
/// <reference path="./node_modules/@nativescript/types-ios/complete.d.ts" />${os_1.EOL}${content}`;
|
|
784
|
+
fs.writeFileSync(referenceTypesPath, references);
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
const references = fs.readFileSync(referenceTypesPath, {
|
|
788
|
+
encoding: "utf-8",
|
|
789
|
+
});
|
|
790
|
+
if ((references === null || references === void 0 ? void 0 : references.indexOf("AppleWidgetUtils")) === -1) {
|
|
791
|
+
content = `${references.toString()}${os_1.EOL}${content}`;
|
|
792
|
+
fs.writeFileSync(referenceTypesPath, content);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
exports.WidgetIOSCommand = WidgetIOSCommand;
|
|
798
|
+
yok_1.injector.registerCommand(["widget"], WidgetCommand);
|
|
799
|
+
yok_1.injector.registerCommand(["widget|ios"], WidgetIOSCommand);
|