@driftengine/package 4.13.1 → 4.13.3
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/README.md +18 -1
- package/dist/android.js +3 -0
- package/dist/cli.js +3 -0
- package/dist/manifest.d.ts +19 -0
- package/dist/manifest.js +4 -1
- package/dist/mobile/androidManifest.d.ts +17 -1
- package/dist/mobile/androidManifest.js +52 -2
- package/package.json +2 -2
- package/src/android.ts +3 -0
- package/src/cli.ts +7 -0
- package/src/manifest.ts +16 -1
- package/src/mobile/androidManifest.ts +68 -2
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ Beside your `package.json`, in the project that produces the web build:
|
|
|
59
59
|
"splash": { "show": true, "minMs": 1400 },
|
|
60
60
|
"targets": ["linux-x64", "win-x64", "mac-arm64"],
|
|
61
61
|
"steam": { "appId": null },
|
|
62
|
-
"android": { "permissions": [], "cleartextTraffic": false }
|
|
62
|
+
"android": { "permissions": [], "cleartextTraffic": false, "orientation": "unspecified" }
|
|
63
63
|
}
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -280,6 +280,23 @@ renderer cannot disagree — which they would if only the manifest moved.
|
|
|
280
280
|
Set it only for the case it exists for: a relay on a LAN, which cannot hold a certificate for an
|
|
281
281
|
address that is not a name. A public relay should be `wss://` and this should stay false.
|
|
282
282
|
|
|
283
|
+
### Which way the app is held
|
|
284
|
+
|
|
285
|
+
`orientation` is the activity's `android:screenOrientation`, and it is `unspecified` by default,
|
|
286
|
+
which leaves it to the phone. A game played sideways says so:
|
|
287
|
+
|
|
288
|
+
```json
|
|
289
|
+
"android": { "orientation": "sensorLandscape" }
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Any value Android documents is accepted (`landscape`, `sensorLandscape`, `portrait`,
|
|
293
|
+
`sensorPortrait`, `userLandscape`, `fullSensor` and the rest), and one it does not is refused when
|
|
294
|
+
the manifest is read, since Android ignores an attribute value it does not know and the build would
|
|
295
|
+
quietly be the phone's choice again. `sensorLandscape` lets a player turn the phone over;
|
|
296
|
+
`landscape` does not. It is written into the copied manifest like the permissions, so the activity
|
|
297
|
+
starts the right way round before any of the game's code runs, which a `lockOrientation` taken at
|
|
298
|
+
run time cannot do.
|
|
299
|
+
|
|
283
300
|
**Signing is not optional here and there is no unsigned option to offer**: Android refuses to
|
|
284
301
|
install an unsigned APK at all. Without a keystore the packager generates one and says so on every
|
|
285
302
|
build. That APK installs on a device with developer mode on; it cannot go to the Play Store.
|
package/dist/android.js
CHANGED
|
@@ -85,6 +85,9 @@ export async function buildAndroid(manifest, projectDir, outDir, options = {}) {
|
|
|
85
85
|
*/
|
|
86
86
|
console.log('[drift-package] android: cleartext traffic permitted (http:// and ws:// allowed)');
|
|
87
87
|
}
|
|
88
|
+
if (manifest.android.orientation !== 'unspecified') {
|
|
89
|
+
console.log(`[drift-package] android: held ${manifest.android.orientation}`);
|
|
90
|
+
}
|
|
88
91
|
if (manifest.icon !== null) {
|
|
89
92
|
/* One PNG at one density: Android scales it for the rest, and a game that wants a full set
|
|
90
93
|
supplies its own `res/` through its own build rather than through this. */
|
package/dist/cli.js
CHANGED
|
@@ -115,6 +115,9 @@ async function doctor(cwd, options = {}) {
|
|
|
115
115
|
console.log(` android: cleartext ${manifest.android.cleartextTraffic
|
|
116
116
|
? 'permitted — http:// and ws:// are allowed, and mixed content with them'
|
|
117
117
|
: 'refused — a relay must be wss://'}`);
|
|
118
|
+
console.log(` android: orientation ${manifest.android.orientation === 'unspecified'
|
|
119
|
+
? "unspecified — the phone's own choice"
|
|
120
|
+
: manifest.android.orientation}`);
|
|
118
121
|
}
|
|
119
122
|
/*
|
|
120
123
|
* **What each target still needs, and the command that fetches it.** A `doctor` that only
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `drift.package.json`, parsed once and trusted afterwards.
|
|
3
|
+
*
|
|
4
|
+
* **Every rejection names its field.** A packaging manifest is written by hand, usually once, and
|
|
5
|
+
* a wrong value surfaces at signing or at first launch on a machine the author does not have. The
|
|
6
|
+
* cost of validating here is a few dozen lines; the cost of not validating is a build.
|
|
7
|
+
*
|
|
8
|
+
* **What is defaulted and what is not** is the only interesting decision in this file. Window size
|
|
9
|
+
* and features default, because a short manifest is easier to read and a wrong window is visible
|
|
10
|
+
* immediately. The id, the entry, the targets and the backend policy do not, because each of them
|
|
11
|
+
* is silent when wrong: the wrong id writes saves to a directory nobody looks in.
|
|
12
|
+
*/
|
|
13
|
+
import { type AndroidOrientation } from './mobile/androidManifest.ts';
|
|
1
14
|
export type WebGpuPolicy = 'prefer' | 'require' | 'off';
|
|
2
15
|
export type Target = 'win-x64' | 'mac-arm64' | 'mac-x64' | 'linux-x64' | 'native-linux-x64' | 'android' | 'ios';
|
|
3
16
|
/** The two that are a phone rather than a desktop, and differ in almost every way that matters. */
|
|
@@ -49,10 +62,16 @@ export interface PackageManifest {
|
|
|
49
62
|
* sets `android:usesCleartextTraffic` *and* is what `MainActivity` reads at runtime to allow
|
|
50
63
|
* mixed content in the WebView, so the platform and the renderer cannot disagree about it. A
|
|
51
64
|
* relay on a LAN cannot hold a certificate, which is the case it exists for.
|
|
65
|
+
*
|
|
66
|
+
* **`orientation` is `unspecified` by default**, which leaves it to the phone, and takes any
|
|
67
|
+
* value Android documents for an activity (`landscape`, `sensorLandscape`, `portrait`, ...). A
|
|
68
|
+
* game played sideways says so here, and the activity starts that way before any of its code
|
|
69
|
+
* runs; one Android does not know is refused rather than written.
|
|
52
70
|
*/
|
|
53
71
|
readonly android: {
|
|
54
72
|
readonly permissions: readonly string[];
|
|
55
73
|
readonly cleartextTraffic: boolean;
|
|
74
|
+
readonly orientation: AndroidOrientation;
|
|
56
75
|
};
|
|
57
76
|
/**
|
|
58
77
|
* Who an installer says this is from.
|
package/dist/manifest.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* immediately. The id, the entry, the targets and the backend policy do not, because each of them
|
|
11
11
|
* is silent when wrong: the wrong id writes saves to a directory nobody looks in.
|
|
12
12
|
*/
|
|
13
|
-
import { checkPermission, fullPermissionName } from './mobile/androidManifest.js';
|
|
13
|
+
import { checkOrientation, checkPermission, fullPermissionName, } from './mobile/androidManifest.js';
|
|
14
14
|
/** The two that are a phone rather than a desktop, and differ in almost every way that matters. */
|
|
15
15
|
export const MOBILE_TARGETS = ['android', 'ios'];
|
|
16
16
|
const POLICIES = ['prefer', 'require', 'off'];
|
|
@@ -117,6 +117,9 @@ export function parseManifest(raw) {
|
|
|
117
117
|
android: {
|
|
118
118
|
permissions,
|
|
119
119
|
cleartextTraffic: androidRaw.cleartextTraffic === true,
|
|
120
|
+
orientation: androidRaw.orientation === undefined
|
|
121
|
+
? 'unspecified'
|
|
122
|
+
: checkOrientation(androidRaw.orientation),
|
|
120
123
|
},
|
|
121
124
|
splash: {
|
|
122
125
|
show: splashRaw.show !== false,
|
|
@@ -5,9 +5,24 @@ export interface AndroidOptions {
|
|
|
5
5
|
readonly permissions: readonly string[];
|
|
6
6
|
/** Whether the app may open `http://` and `ws://` at all. */
|
|
7
7
|
readonly cleartextTraffic: boolean;
|
|
8
|
+
/** The activity's `android:screenOrientation`, one of `ANDROID_ORIENTATIONS`. */
|
|
9
|
+
readonly orientation: AndroidOrientation;
|
|
8
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Every value Android documents for an activity's `android:screenOrientation`.
|
|
13
|
+
*
|
|
14
|
+
* **The whole list, not the two a landscape game wants**, because which way a game is held is the
|
|
15
|
+
* game's decision and the engine has no reason to prefer one: a card game is held upright, a
|
|
16
|
+
* racing game sideways, and `sensorLandscape` against `landscape` is whether a player may turn
|
|
17
|
+
* the phone over. What the list buys is a refusal at parse time, since the value is written into
|
|
18
|
+
* an XML attribute and Android answers one it does not know by ignoring it.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ANDROID_ORIENTATIONS: readonly ['unspecified', 'behind', 'landscape', 'portrait', 'reverseLandscape', 'reversePortrait', 'sensorLandscape', 'sensorPortrait', 'userLandscape', 'userPortrait', 'sensor', 'fullSensor', 'nosensor', 'user', 'fullUser', 'locked'];
|
|
21
|
+
export type AndroidOrientation = (typeof ANDROID_ORIENTATIONS)[number];
|
|
9
22
|
/** Nothing asked for: what every build got before this existed, and still gets. */
|
|
10
23
|
export declare const NO_ANDROID_OPTIONS: AndroidOptions;
|
|
24
|
+
/** Refuse an orientation Android does not document, at parse time where a consumer can fix it. */
|
|
25
|
+
export declare function checkOrientation(value: unknown): AndroidOrientation;
|
|
11
26
|
/**
|
|
12
27
|
* `INTERNET` and `android.permission.INTERNET` are the same thing, written two ways.
|
|
13
28
|
*
|
|
@@ -20,7 +35,8 @@ export declare function fullPermissionName(name: string): string;
|
|
|
20
35
|
/** Refuse a name that cannot go into the XML, at parse time where a consumer can fix it. */
|
|
21
36
|
export declare function checkPermission(name: string): void;
|
|
22
37
|
/**
|
|
23
|
-
* The template manifest with a game's permissions in it,
|
|
38
|
+
* The template manifest with a game's permissions in it, its cleartext policy set, and its
|
|
39
|
+
* activity held the way the game asked.
|
|
24
40
|
*
|
|
25
41
|
* **Written into the copy, not into the template**, the way the icon already is: `buildAndroid`
|
|
26
42
|
* stages `packages/package/android/` into `out/android/project` and edits it there, so this
|
|
@@ -1,9 +1,46 @@
|
|
|
1
1
|
/** What a game asks the Android manifest for, written into the copied template before Gradle runs. */
|
|
2
|
+
/**
|
|
3
|
+
* Every value Android documents for an activity's `android:screenOrientation`.
|
|
4
|
+
*
|
|
5
|
+
* **The whole list, not the two a landscape game wants**, because which way a game is held is the
|
|
6
|
+
* game's decision and the engine has no reason to prefer one: a card game is held upright, a
|
|
7
|
+
* racing game sideways, and `sensorLandscape` against `landscape` is whether a player may turn
|
|
8
|
+
* the phone over. What the list buys is a refusal at parse time, since the value is written into
|
|
9
|
+
* an XML attribute and Android answers one it does not know by ignoring it.
|
|
10
|
+
*/
|
|
11
|
+
export const ANDROID_ORIENTATIONS = [
|
|
12
|
+
'unspecified',
|
|
13
|
+
'behind',
|
|
14
|
+
'landscape',
|
|
15
|
+
'portrait',
|
|
16
|
+
'reverseLandscape',
|
|
17
|
+
'reversePortrait',
|
|
18
|
+
'sensorLandscape',
|
|
19
|
+
'sensorPortrait',
|
|
20
|
+
'userLandscape',
|
|
21
|
+
'userPortrait',
|
|
22
|
+
'sensor',
|
|
23
|
+
'fullSensor',
|
|
24
|
+
'nosensor',
|
|
25
|
+
'user',
|
|
26
|
+
'fullUser',
|
|
27
|
+
'locked',
|
|
28
|
+
];
|
|
2
29
|
/** Nothing asked for: what every build got before this existed, and still gets. */
|
|
3
30
|
export const NO_ANDROID_OPTIONS = Object.freeze({
|
|
4
31
|
permissions: Object.freeze([]),
|
|
5
32
|
cleartextTraffic: false,
|
|
33
|
+
orientation: 'unspecified',
|
|
6
34
|
});
|
|
35
|
+
/** Refuse an orientation Android does not document, at parse time where a consumer can fix it. */
|
|
36
|
+
export function checkOrientation(value) {
|
|
37
|
+
const known = ANDROID_ORIENTATIONS.find((name) => name === value);
|
|
38
|
+
if (known === undefined) {
|
|
39
|
+
throw new Error(`drift.package.json: "android.orientation" is ${JSON.stringify(value)}, expected one of ` +
|
|
40
|
+
`${ANDROID_ORIENTATIONS.join(', ')}.`);
|
|
41
|
+
}
|
|
42
|
+
return known;
|
|
43
|
+
}
|
|
7
44
|
/**
|
|
8
45
|
* `INTERNET` and `android.permission.INTERNET` are the same thing, written two ways.
|
|
9
46
|
*
|
|
@@ -32,7 +69,8 @@ export function checkPermission(name) {
|
|
|
32
69
|
}
|
|
33
70
|
}
|
|
34
71
|
/**
|
|
35
|
-
* The template manifest with a game's permissions in it,
|
|
72
|
+
* The template manifest with a game's permissions in it, its cleartext policy set, and its
|
|
73
|
+
* activity held the way the game asked.
|
|
36
74
|
*
|
|
37
75
|
* **Written into the copy, not into the template**, the way the icon already is: `buildAndroid`
|
|
38
76
|
* stages `packages/package/android/` into `out/android/project` and edits it there, so this
|
|
@@ -83,7 +121,19 @@ export function withAndroidManifest(xml, options) {
|
|
|
83
121
|
throw new Error('the Android manifest template no longer declares android:usesCleartextTraffic, so asking ' +
|
|
84
122
|
'for cleartext traffic would do nothing');
|
|
85
123
|
}
|
|
86
|
-
|
|
124
|
+
/*
|
|
125
|
+
* **Rewritten on the activity for the same reason**: the template carries `unspecified`, which
|
|
126
|
+
* leaves the choice to the phone. Held by the manifest rather than by `lockOrientation` at run
|
|
127
|
+
* time, because the activity is laid out before any of the game's code runs, and a lock taken
|
|
128
|
+
* then turns a picture the player has already seen.
|
|
129
|
+
*/
|
|
130
|
+
const oriented = replaced.replace(/android:screenOrientation="[A-Za-z]+"/, `android:screenOrientation="${options.orientation}"`);
|
|
131
|
+
if (!/android:screenOrientation="[A-Za-z]+"/.test(replaced) &&
|
|
132
|
+
options.orientation !== 'unspecified') {
|
|
133
|
+
throw new Error('the Android manifest template no longer declares android:screenOrientation, so asking for ' +
|
|
134
|
+
`"${options.orientation}" would do nothing`);
|
|
135
|
+
}
|
|
136
|
+
return oriented;
|
|
87
137
|
}
|
|
88
138
|
/** The whitespace at the start of the line `at` falls on, so an inserted element lines up. */
|
|
89
139
|
function indentOf(xml, at) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftengine/package",
|
|
3
|
-
"version": "4.13.
|
|
3
|
+
"version": "4.13.3",
|
|
4
4
|
"description": "Builds an installable application from a game built on the engine",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"drift-package": "bin/drift-package.mjs"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@driftengine/core": "4.13.
|
|
52
|
+
"@driftengine/core": "4.13.3",
|
|
53
53
|
"steamworks.js": ">=0.4.0"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
package/src/android.ts
CHANGED
|
@@ -101,6 +101,9 @@ export async function buildAndroid(
|
|
|
101
101
|
*/
|
|
102
102
|
console.log('[drift-package] android: cleartext traffic permitted (http:// and ws:// allowed)');
|
|
103
103
|
}
|
|
104
|
+
if (manifest.android.orientation !== 'unspecified') {
|
|
105
|
+
console.log(`[drift-package] android: held ${manifest.android.orientation}`);
|
|
106
|
+
}
|
|
104
107
|
|
|
105
108
|
if (manifest.icon !== null) {
|
|
106
109
|
/* One PNG at one density: Android scales it for the rest, and a game that wants a full set
|
package/src/cli.ts
CHANGED
|
@@ -125,6 +125,13 @@ async function doctor(cwd: string, options: ResourceOptions = {}): Promise<Packa
|
|
|
125
125
|
: 'refused — a relay must be wss://'
|
|
126
126
|
}`,
|
|
127
127
|
);
|
|
128
|
+
console.log(
|
|
129
|
+
` android: orientation ${
|
|
130
|
+
manifest.android.orientation === 'unspecified'
|
|
131
|
+
? "unspecified — the phone's own choice"
|
|
132
|
+
: manifest.android.orientation
|
|
133
|
+
}`,
|
|
134
|
+
);
|
|
128
135
|
}
|
|
129
136
|
|
|
130
137
|
/*
|
package/src/manifest.ts
CHANGED
|
@@ -10,7 +10,12 @@
|
|
|
10
10
|
* immediately. The id, the entry, the targets and the backend policy do not, because each of them
|
|
11
11
|
* is silent when wrong: the wrong id writes saves to a directory nobody looks in.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
checkOrientation,
|
|
15
|
+
checkPermission,
|
|
16
|
+
fullPermissionName,
|
|
17
|
+
type AndroidOrientation,
|
|
18
|
+
} from './mobile/androidManifest.ts';
|
|
14
19
|
|
|
15
20
|
export type WebGpuPolicy = 'prefer' | 'require' | 'off';
|
|
16
21
|
export type Target =
|
|
@@ -77,10 +82,16 @@ export interface PackageManifest {
|
|
|
77
82
|
* sets `android:usesCleartextTraffic` *and* is what `MainActivity` reads at runtime to allow
|
|
78
83
|
* mixed content in the WebView, so the platform and the renderer cannot disagree about it. A
|
|
79
84
|
* relay on a LAN cannot hold a certificate, which is the case it exists for.
|
|
85
|
+
*
|
|
86
|
+
* **`orientation` is `unspecified` by default**, which leaves it to the phone, and takes any
|
|
87
|
+
* value Android documents for an activity (`landscape`, `sensorLandscape`, `portrait`, ...). A
|
|
88
|
+
* game played sideways says so here, and the activity starts that way before any of its code
|
|
89
|
+
* runs; one Android does not know is refused rather than written.
|
|
80
90
|
*/
|
|
81
91
|
readonly android: {
|
|
82
92
|
readonly permissions: readonly string[];
|
|
83
93
|
readonly cleartextTraffic: boolean;
|
|
94
|
+
readonly orientation: AndroidOrientation;
|
|
84
95
|
};
|
|
85
96
|
/**
|
|
86
97
|
* Who an installer says this is from.
|
|
@@ -202,6 +213,10 @@ export function parseManifest(raw: unknown): PackageManifest {
|
|
|
202
213
|
android: {
|
|
203
214
|
permissions,
|
|
204
215
|
cleartextTraffic: androidRaw.cleartextTraffic === true,
|
|
216
|
+
orientation:
|
|
217
|
+
androidRaw.orientation === undefined
|
|
218
|
+
? 'unspecified'
|
|
219
|
+
: checkOrientation(androidRaw.orientation),
|
|
205
220
|
},
|
|
206
221
|
splash: {
|
|
207
222
|
show: splashRaw.show !== false,
|
|
@@ -6,14 +6,59 @@ export interface AndroidOptions {
|
|
|
6
6
|
readonly permissions: readonly string[];
|
|
7
7
|
/** Whether the app may open `http://` and `ws://` at all. */
|
|
8
8
|
readonly cleartextTraffic: boolean;
|
|
9
|
+
/** The activity's `android:screenOrientation`, one of `ANDROID_ORIENTATIONS`. */
|
|
10
|
+
readonly orientation: AndroidOrientation;
|
|
9
11
|
}
|
|
10
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Every value Android documents for an activity's `android:screenOrientation`.
|
|
15
|
+
*
|
|
16
|
+
* **The whole list, not the two a landscape game wants**, because which way a game is held is the
|
|
17
|
+
* game's decision and the engine has no reason to prefer one: a card game is held upright, a
|
|
18
|
+
* racing game sideways, and `sensorLandscape` against `landscape` is whether a player may turn
|
|
19
|
+
* the phone over. What the list buys is a refusal at parse time, since the value is written into
|
|
20
|
+
* an XML attribute and Android answers one it does not know by ignoring it.
|
|
21
|
+
*/
|
|
22
|
+
export const ANDROID_ORIENTATIONS = [
|
|
23
|
+
'unspecified',
|
|
24
|
+
'behind',
|
|
25
|
+
'landscape',
|
|
26
|
+
'portrait',
|
|
27
|
+
'reverseLandscape',
|
|
28
|
+
'reversePortrait',
|
|
29
|
+
'sensorLandscape',
|
|
30
|
+
'sensorPortrait',
|
|
31
|
+
'userLandscape',
|
|
32
|
+
'userPortrait',
|
|
33
|
+
'sensor',
|
|
34
|
+
'fullSensor',
|
|
35
|
+
'nosensor',
|
|
36
|
+
'user',
|
|
37
|
+
'fullUser',
|
|
38
|
+
'locked',
|
|
39
|
+
] as const;
|
|
40
|
+
|
|
41
|
+
export type AndroidOrientation = (typeof ANDROID_ORIENTATIONS)[number];
|
|
42
|
+
|
|
11
43
|
/** Nothing asked for: what every build got before this existed, and still gets. */
|
|
12
44
|
export const NO_ANDROID_OPTIONS: AndroidOptions = Object.freeze({
|
|
13
45
|
permissions: Object.freeze([]) as readonly string[],
|
|
14
46
|
cleartextTraffic: false,
|
|
47
|
+
orientation: 'unspecified',
|
|
15
48
|
});
|
|
16
49
|
|
|
50
|
+
/** Refuse an orientation Android does not document, at parse time where a consumer can fix it. */
|
|
51
|
+
export function checkOrientation(value: unknown): AndroidOrientation {
|
|
52
|
+
const known = ANDROID_ORIENTATIONS.find((name) => name === value);
|
|
53
|
+
if (known === undefined) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`drift.package.json: "android.orientation" is ${JSON.stringify(value)}, expected one of ` +
|
|
56
|
+
`${ANDROID_ORIENTATIONS.join(', ')}.`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return known;
|
|
60
|
+
}
|
|
61
|
+
|
|
17
62
|
/**
|
|
18
63
|
* `INTERNET` and `android.permission.INTERNET` are the same thing, written two ways.
|
|
19
64
|
*
|
|
@@ -47,7 +92,8 @@ export function checkPermission(name: string): void {
|
|
|
47
92
|
}
|
|
48
93
|
|
|
49
94
|
/**
|
|
50
|
-
* The template manifest with a game's permissions in it,
|
|
95
|
+
* The template manifest with a game's permissions in it, its cleartext policy set, and its
|
|
96
|
+
* activity held the way the game asked.
|
|
51
97
|
*
|
|
52
98
|
* **Written into the copy, not into the template**, the way the icon already is: `buildAndroid`
|
|
53
99
|
* stages `packages/package/android/` into `out/android/project` and edits it there, so this
|
|
@@ -105,7 +151,27 @@ export function withAndroidManifest(xml: string, options: AndroidOptions): strin
|
|
|
105
151
|
'for cleartext traffic would do nothing',
|
|
106
152
|
);
|
|
107
153
|
}
|
|
108
|
-
|
|
154
|
+
|
|
155
|
+
/*
|
|
156
|
+
* **Rewritten on the activity for the same reason**: the template carries `unspecified`, which
|
|
157
|
+
* leaves the choice to the phone. Held by the manifest rather than by `lockOrientation` at run
|
|
158
|
+
* time, because the activity is laid out before any of the game's code runs, and a lock taken
|
|
159
|
+
* then turns a picture the player has already seen.
|
|
160
|
+
*/
|
|
161
|
+
const oriented = replaced.replace(
|
|
162
|
+
/android:screenOrientation="[A-Za-z]+"/,
|
|
163
|
+
`android:screenOrientation="${options.orientation}"`,
|
|
164
|
+
);
|
|
165
|
+
if (
|
|
166
|
+
!/android:screenOrientation="[A-Za-z]+"/.test(replaced) &&
|
|
167
|
+
options.orientation !== 'unspecified'
|
|
168
|
+
) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
'the Android manifest template no longer declares android:screenOrientation, so asking for ' +
|
|
171
|
+
`"${options.orientation}" would do nothing`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
return oriented;
|
|
109
175
|
}
|
|
110
176
|
|
|
111
177
|
/** The whitespace at the start of the line `at` falls on, so an inserted element lines up. */
|