@livx.cc/appwrap 0.26.0 → 0.28.1

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 (40) hide show
  1. package/package.json +1 -1
  2. package/runtime/App_Resources/Android/src/main/AndroidManifest.xml +3 -0
  3. package/runtime/app/app.ts +57 -39
  4. package/runtime/app/shell/android-helpers.ts +6 -6
  5. package/runtime/app/shell/background-bootstrap.generated.ts +8 -0
  6. package/runtime/app/shell/background-context.ts +20 -0
  7. package/runtime/app/shell/banner.ts +9 -4
  8. package/runtime/app/shell/bridge.ts +2 -0
  9. package/runtime/app/shell/capabilities.manifest.ts +22 -3
  10. package/runtime/app/shell/custom-webview.android.ts +50 -23
  11. package/runtime/app/shell/custom-webview.ios.ts +90 -78
  12. package/runtime/app/shell/devmenu.ts +2 -2
  13. package/runtime/app/shell/env.ts +1 -3
  14. package/runtime/app/shell/events.ts +25 -4
  15. package/runtime/app/shell/fcm-firebase.d.ts +2 -1
  16. package/runtime/app/shell/handlers-android.ts +16 -12
  17. package/runtime/app/shell/handlers-background.ts +290 -0
  18. package/runtime/app/shell/handlers-billing.ts +90 -82
  19. package/runtime/app/shell/handlers-extended.ts +141 -110
  20. package/runtime/app/shell/handlers-fs.ts +53 -41
  21. package/runtime/app/shell/handlers-health.ts +27 -19
  22. package/runtime/app/shell/handlers-media.ts +8 -14
  23. package/runtime/app/shell/handlers-oauth.ts +19 -19
  24. package/runtime/app/shell/handlers-parity.ts +118 -89
  25. package/runtime/app/shell/handlers-push.ts +5 -15
  26. package/runtime/app/shell/handlers-reviews.ts +5 -5
  27. package/runtime/app/shell/handlers-scanner.ts +36 -38
  28. package/runtime/app/shell/handlers-speech.ts +43 -49
  29. package/runtime/app/shell/handlers-system.ts +122 -1
  30. package/runtime/app/shell/handlers.ts +10 -3
  31. package/runtime/app/shell/ios-frameworks.d.ts +9 -44
  32. package/runtime/app/shell/ios-ui-delegate.ts +112 -108
  33. package/runtime/app/shell/native-log.ts +1 -3
  34. package/runtime/app/shell/status-bar.ts +7 -4
  35. package/runtime/app/shell/toast.ts +1 -1
  36. package/runtime/references.d.ts +21 -0
  37. package/runtime/tsconfig.json +1 -0
  38. package/src/cli.ts +74 -18
  39. package/src/config.ts +20 -0
  40. package/src/derive.ts +75 -0
package/src/derive.ts CHANGED
@@ -7,6 +7,13 @@
7
7
  /** Normalized appwrap orientation — the three lock states the native shells can express. */
8
8
  export type Orientation = 'portrait' | 'landscape' | 'any';
9
9
 
10
+ /** A single PWA web-manifest icon entry (the subset appwrap reads). */
11
+ export interface WebManifestIcon {
12
+ src: string;
13
+ sizes?: string;
14
+ purpose?: string;
15
+ }
16
+
10
17
  /** The PWA web-manifest fields appwrap derives from (a subset; everything optional). */
11
18
  export interface WebManifest {
12
19
  name?: string;
@@ -14,6 +21,7 @@ export interface WebManifest {
14
21
  background_color?: string;
15
22
  theme_color?: string;
16
23
  orientation?: string;
24
+ icons?: WebManifestIcon[];
17
25
  }
18
26
 
19
27
  /**
@@ -97,3 +105,70 @@ export function stampAndroidOrientation(src: string, value: string): string {
97
105
  return stripped.replace(/(android:name="[^"]*")/, `$1\n\t\t\tandroid:screenOrientation="${value}"`);
98
106
  });
99
107
  }
108
+
109
+ /**
110
+ * Rewrite the `<!-- appwrap:queries -->…<!-- /appwrap:queries -->` block in an AndroidManifest string
111
+ * for `kit.app.canOpenUrl()` visibility probes (API 30+). Both child kinds live in ONE `<queries>`:
112
+ * - each `queryPackages` entry → explicit `<package android:name="…"/>` (Android-only package probe);
113
+ * - each `queryUrlSchemes` entry → a VIEW `<intent>` on that scheme, so a custom-scheme probe is
114
+ * symmetric with iOS's `LSApplicationQueriesSchemes` (no hand-mapping scheme→package needed).
115
+ * Pure + idempotent: always rewrites the marker block, so a re-sync never duplicates. No-op (empty
116
+ * block) when both lists are absent.
117
+ */
118
+ /**
119
+ * Stamp (or strip) the headless background-task wiring in an Info.plist string for the `backgroundTask`
120
+ * module: `BGTaskSchedulerPermittedIdentifiers` (the permitted ids — iOS requires them declared at
121
+ * build time or `BGTaskScheduler.register` throws) AND the `fetch`+`processing` `UIBackgroundModes`
122
+ * (BGAppRefreshTask needs `fetch`, BGProcessingTask needs `processing`). Pure + idempotent: rewrites an
123
+ * `appwrap:bgtask` marker block (added before `</dict>`), and MERGES the two modes into any existing
124
+ * `UIBackgroundModes` array (a second `<key>` would be invalid plist — same hazard as push's
125
+ * `remote-notification`). `ids` empty/undefined → strips the block + removes the two modes it added.
126
+ */
127
+ export function stampPlistBackgroundTasks(src: string, ids: string[] | undefined): string {
128
+ // 1) Always rewrite the marker block (permitted identifiers). Strip first → idempotent.
129
+ src = src.replace(/\s*<!-- appwrap:bgtask -->[\s\S]*?<!-- \/appwrap:bgtask -->/g, '');
130
+ const list = (ids ?? []).filter(Boolean);
131
+ if (list.length) {
132
+ const items = list.map((s) => ` <string>${s}</string>`).join('\n');
133
+ const block =
134
+ ` <!-- appwrap:bgtask -->\n` +
135
+ ` <key>BGTaskSchedulerPermittedIdentifiers</key>\n <array>\n${items}\n </array>\n` +
136
+ ` <!-- /appwrap:bgtask -->`;
137
+ src = src.replace(/<\/dict>\s*<\/plist>\s*$/, `${block}\n</dict>\n</plist>\n`);
138
+ }
139
+
140
+ // 2) Merge/remove the fetch + processing background modes (separate from the marker — they live in
141
+ // the shared UIBackgroundModes array, which may also hold audio/remote-notification).
142
+ const modes = ['fetch', 'processing'];
143
+ const bgArray = /(<key>UIBackgroundModes<\/key>\s*<array>)([\s\S]*?)(<\/array>)/;
144
+ if (list.length) {
145
+ const need = modes.filter((m) => !new RegExp(`<string>${m}</string>`).test(src));
146
+ if (need.length) {
147
+ const inject = need.map((m) => `\t<string>${m}</string>`).join('\n');
148
+ src = bgArray.test(src)
149
+ ? src.replace(bgArray, (_m, open, inner, close) => `${open}${inner}${inject}\n\t${close}`)
150
+ : src.replace(
151
+ /<\/dict>\s*<\/plist>\s*$/,
152
+ ` <key>UIBackgroundModes</key>\n <array>\n${need.map((m) => ` <string>${m}</string>`).join('\n')}\n </array>\n</dict>\n</plist>\n`
153
+ );
154
+ }
155
+ } else {
156
+ for (const m of modes) src = src.replace(new RegExp(`\\s*<string>${m}</string>`), '');
157
+ }
158
+ return src;
159
+ }
160
+
161
+ export function stampAndroidQueries(src: string, queryPackages?: string[], queryUrlSchemes?: string[]): string {
162
+ const children = [
163
+ ...(queryPackages ?? []).map((p) => `\t\t<package android:name="${p}"/>`),
164
+ ...(queryUrlSchemes ?? []).map(
165
+ (s) => `\t\t<intent><action android:name="android.intent.action.VIEW"/><data android:scheme="${s}"/></intent>`
166
+ ),
167
+ ];
168
+ return src.replace(
169
+ /<!-- appwrap:queries -->[\s\S]*?<!-- \/appwrap:queries -->/,
170
+ children.length
171
+ ? `<!-- appwrap:queries -->\n\t<queries>\n${children.join('\n')}\n\t</queries>\n\t<!-- /appwrap:queries -->`
172
+ : `<!-- appwrap:queries -->\n\t<!-- /appwrap:queries -->`
173
+ );
174
+ }