@vxrn/utils 2.8.1 → 2.9.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.
- package/dist/cjs/nativeAppManifest.cjs +54 -7
- package/dist/cjs/nativeAppManifest.native.cjs +108 -36
- package/dist/cjs/nativeAppManifest.native.js +108 -36
- package/dist/cjs/nativeAppManifest.native.js.map +1 -1
- package/dist/esm/nativeAppManifest.mjs +52 -8
- package/dist/esm/nativeAppManifest.mjs.map +1 -1
- package/dist/esm/nativeAppManifest.native.js +106 -37
- package/dist/esm/nativeAppManifest.native.js.map +1 -1
- package/package.json +5 -5
- package/src/nativeAppManifest.test.ts +40 -4
- package/src/nativeAppManifest.ts +94 -17
- package/types/nativeAppManifest.d.ts +20 -8
- package/types/nativeAppManifest.d.ts.map +1 -1
package/src/nativeAppManifest.ts
CHANGED
|
@@ -10,6 +10,61 @@ export type PlistValue =
|
|
|
10
10
|
| PlistValue[]
|
|
11
11
|
| { [key: string]: PlistValue }
|
|
12
12
|
|
|
13
|
+
// a home screen icon. ios 18 also draws dark and tinted appearances: dark
|
|
14
|
+
// keeps the source's transparency unless a backgroundColor is given, and
|
|
15
|
+
// tinted is flattened to grayscale for the system to tint. both default to the
|
|
16
|
+
// primary source, and take their own when the artwork differs.
|
|
17
|
+
export interface NativeAppIcon {
|
|
18
|
+
source: string
|
|
19
|
+
backgroundColor: string
|
|
20
|
+
dark?: { source?: string; backgroundColor?: string }
|
|
21
|
+
tinted?: { source?: string; backgroundColor?: string }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// android resource names are lowercase: Blue -> blue, DarkMode -> dark_mode.
|
|
25
|
+
export function androidIconSuffix(name: string): string {
|
|
26
|
+
return name.replace(/([a-z\d])([A-Z])/g, '$1_$2').toLowerCase()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// the bundled preview image prebuild writes for an icon (undefined is the
|
|
30
|
+
// primary) and One.AppIcon.list reads back, by resource name on each platform.
|
|
31
|
+
export function appIconPreviewResources(name: string | undefined): {
|
|
32
|
+
ios: string
|
|
33
|
+
android: string
|
|
34
|
+
} {
|
|
35
|
+
return {
|
|
36
|
+
ios: `AppIconPreview${name ?? 'Primary'}`,
|
|
37
|
+
android: `app_icon_preview_${name === undefined ? 'primary' : androidIconSuffix(name)}`,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// build-time defines the native bundle reads: what One.LaunchScreen.Cover needs
|
|
42
|
+
// beyond the bundled launch resources, and the icon previews One.AppIcon.list
|
|
43
|
+
// pairs with prebuild's resources. each value is a JSON string literal.
|
|
44
|
+
export function nativeAppDefines(app: NativeAppManifest | undefined): Record<string, string> {
|
|
45
|
+
const defines: Record<string, string> = {}
|
|
46
|
+
if (app?.splash) {
|
|
47
|
+
defines['process.env.ONE_LAUNCH_SCREEN'] = JSON.stringify(
|
|
48
|
+
JSON.stringify({
|
|
49
|
+
width: app.splash.width ?? 200,
|
|
50
|
+
cover: app.splash.resizeMode === 'cover',
|
|
51
|
+
backgroundImage: app.splash.backgroundImage !== undefined,
|
|
52
|
+
})
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
if (app?.alternateIcons) {
|
|
56
|
+
defines['process.env.ONE_APP_ICONS'] = JSON.stringify(
|
|
57
|
+
JSON.stringify(
|
|
58
|
+
[undefined, ...Object.keys(app.alternateIcons)].map((name) => ({
|
|
59
|
+
name,
|
|
60
|
+
...appIconPreviewResources(name),
|
|
61
|
+
}))
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
return defines
|
|
66
|
+
}
|
|
67
|
+
|
|
13
68
|
export interface NativeAppManifest {
|
|
14
69
|
name: string
|
|
15
70
|
displayName?: string
|
|
@@ -22,10 +77,11 @@ export interface NativeAppManifest {
|
|
|
22
77
|
// light or dark locks the app's appearance; automatic, like unset, follows
|
|
23
78
|
// the system. expo treats unset as light.
|
|
24
79
|
userInterfaceStyle?: 'light' | 'dark' | 'automatic'
|
|
25
|
-
icon?:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
80
|
+
icon?: NativeAppIcon
|
|
81
|
+
// extra home screen icons selectable through One.AppIcon. keys are the
|
|
82
|
+
// icon names passed to setIcon; each source is a square 1024px image.
|
|
83
|
+
// prebuild turns them into ios icon sets and android launcher aliases.
|
|
84
|
+
alternateIcons?: Record<string, NativeAppIcon>
|
|
29
85
|
splash?: {
|
|
30
86
|
source: string
|
|
31
87
|
backgroundColor: string
|
|
@@ -149,9 +205,6 @@ export interface NativeAppManifest {
|
|
|
149
205
|
light: string
|
|
150
206
|
dark?: string
|
|
151
207
|
}
|
|
152
|
-
// extra home screen icons selectable through One.AppIcon. keys are
|
|
153
|
-
// the icon names passed to setIcon; each source is a square 1024px image.
|
|
154
|
-
alternateIcons?: Record<string, { source: string; backgroundColor: string }>
|
|
155
208
|
// system prompt text for Face ID through One.LocalAuthentication.
|
|
156
209
|
faceIdUsageDescription?: string
|
|
157
210
|
// exposes the app's Documents in the Files app and document pickers.
|
|
@@ -305,18 +358,42 @@ export function validateNativeApp(
|
|
|
305
358
|
) {
|
|
306
359
|
fail('icon requires source and a six-digit hex backgroundColor')
|
|
307
360
|
}
|
|
308
|
-
if (manifest.ios?.alternateIcons !== undefined) {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
361
|
+
if ((manifest.ios as { alternateIcons?: unknown } | undefined)?.alternateIcons !== undefined) {
|
|
362
|
+
fail('ios.alternateIcons moved to alternateIcons, which android uses too')
|
|
363
|
+
}
|
|
364
|
+
const alternates = Object.entries(manifest.alternateIcons ?? {})
|
|
365
|
+
if (manifest.alternateIcons !== undefined) {
|
|
366
|
+
if (!manifest.icon) fail('alternateIcons requires a primary icon')
|
|
367
|
+
if (alternates.length === 0) fail('alternateIcons requires at least one icon')
|
|
368
|
+
const lowered = new Set<string>()
|
|
369
|
+
for (const [name, icon] of alternates) {
|
|
370
|
+
if (name === 'AppIcon' || name === 'Primary' || !TARGET_NAME.test(name)) {
|
|
371
|
+
fail(`alternateIcons name "${name}" must be an identifier other than AppIcon or Primary`)
|
|
372
|
+
}
|
|
373
|
+
if (lowered.has(name.toLowerCase())) {
|
|
374
|
+
fail(`alternateIcons name "${name}" repeats another name apart from its case`)
|
|
315
375
|
}
|
|
376
|
+
lowered.add(name.toLowerCase())
|
|
316
377
|
if (!icon?.source || !HEX_COLOR.test(icon.backgroundColor)) {
|
|
317
|
-
fail(
|
|
318
|
-
|
|
319
|
-
|
|
378
|
+
fail(`alternateIcons.${name} requires source and a six-digit hex backgroundColor`)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const icons: Array<readonly [string, NativeAppIcon | undefined]> = [
|
|
383
|
+
['icon', manifest.icon],
|
|
384
|
+
...alternates.map(([name, alternate]) => [`alternateIcons.${name}`, alternate] as const),
|
|
385
|
+
]
|
|
386
|
+
for (const [label, icon] of icons) {
|
|
387
|
+
for (const appearance of ['dark', 'tinted'] as const) {
|
|
388
|
+
const variant = icon?.[appearance]
|
|
389
|
+
if (variant === undefined) continue
|
|
390
|
+
if (
|
|
391
|
+
typeof variant !== 'object' ||
|
|
392
|
+
variant === null ||
|
|
393
|
+
(variant.source !== undefined && !variant.source) ||
|
|
394
|
+
(variant.backgroundColor !== undefined && !HEX_COLOR.test(variant.backgroundColor))
|
|
395
|
+
) {
|
|
396
|
+
fail(`${label}.${appearance} takes an optional source and six-digit hex backgroundColor`)
|
|
320
397
|
}
|
|
321
398
|
}
|
|
322
399
|
}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
export type PlistValue = string | number | boolean | PlistValue[] | {
|
|
2
2
|
[key: string]: PlistValue;
|
|
3
3
|
};
|
|
4
|
+
export interface NativeAppIcon {
|
|
5
|
+
source: string;
|
|
6
|
+
backgroundColor: string;
|
|
7
|
+
dark?: {
|
|
8
|
+
source?: string;
|
|
9
|
+
backgroundColor?: string;
|
|
10
|
+
};
|
|
11
|
+
tinted?: {
|
|
12
|
+
source?: string;
|
|
13
|
+
backgroundColor?: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare function androidIconSuffix(name: string): string;
|
|
17
|
+
export declare function appIconPreviewResources(name: string | undefined): {
|
|
18
|
+
ios: string;
|
|
19
|
+
android: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function nativeAppDefines(app: NativeAppManifest | undefined): Record<string, string>;
|
|
4
22
|
export interface NativeAppManifest {
|
|
5
23
|
name: string;
|
|
6
24
|
displayName?: string;
|
|
@@ -8,10 +26,8 @@ export interface NativeAppManifest {
|
|
|
8
26
|
version?: string;
|
|
9
27
|
orientation?: 'portrait' | 'landscape' | 'default';
|
|
10
28
|
userInterfaceStyle?: 'light' | 'dark' | 'automatic';
|
|
11
|
-
icon?:
|
|
12
|
-
|
|
13
|
-
backgroundColor: string;
|
|
14
|
-
};
|
|
29
|
+
icon?: NativeAppIcon;
|
|
30
|
+
alternateIcons?: Record<string, NativeAppIcon>;
|
|
15
31
|
splash?: {
|
|
16
32
|
source: string;
|
|
17
33
|
backgroundColor: string;
|
|
@@ -79,10 +95,6 @@ export interface NativeAppManifest {
|
|
|
79
95
|
light: string;
|
|
80
96
|
dark?: string;
|
|
81
97
|
};
|
|
82
|
-
alternateIcons?: Record<string, {
|
|
83
|
-
source: string;
|
|
84
|
-
backgroundColor: string;
|
|
85
|
-
}>;
|
|
86
98
|
faceIdUsageDescription?: string;
|
|
87
99
|
fileSharing?: boolean;
|
|
88
100
|
associatedDomains?: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nativeAppManifest.d.ts","sourceRoot":"","sources":["../src/nativeAppManifest.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,MAAM,GACN,OAAO,GACP,UAAU,EAAE,GACZ;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"nativeAppManifest.d.ts","sourceRoot":"","sources":["../src/nativeAppManifest.ts"],"names":[],"mappings":"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"}
|