@react-native-tvos/config-tv 0.0.5 → 0.0.7
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 +22 -5
- package/build/types.d.ts +39 -0
- package/build/utils/appleBrandAssets.d.ts +85 -0
- package/build/utils/appleBrandAssets.js +113 -0
- package/build/{utils.d.ts → utils/config.d.ts} +3 -7
- package/build/utils/config.js +60 -0
- package/build/utils/index.d.ts +3 -0
- package/build/utils/index.js +19 -0
- package/build/utils/log.d.ts +6 -0
- package/build/utils/log.js +11 -0
- package/build/withTV.js +4 -0
- package/build/withTVAndroidManifest.d.ts +1 -0
- package/build/withTVAndroidManifest.js +38 -1
- package/build/withTVAppleIconImages.d.ts +7 -0
- package/build/withTVAppleIconImages.js +179 -0
- package/build/withTVInfoPlist.d.ts +3 -0
- package/build/withTVInfoPlist.js +17 -0
- package/build/withTVXcodeProject.js +17 -11
- package/package.json +3 -2
- package/build/utils.js +0 -42
package/README.md
CHANGED
|
@@ -38,7 +38,16 @@ or
|
|
|
38
38
|
"showVerboseWarnings": false,
|
|
39
39
|
"tvosDeploymentTarget": "13.4",
|
|
40
40
|
"removeFlipperOnAndroid": true,
|
|
41
|
-
"androidTVBanner": "assets/images/tv_banner.png"
|
|
41
|
+
"androidTVBanner": "assets/images/tv_banner.png",
|
|
42
|
+
"appleTVImages": {
|
|
43
|
+
"icon": "./assets/images/myimage-tvos-1280x768.png",
|
|
44
|
+
"iconSmall": "./assets/images/myimage-tvos-400x240.png",
|
|
45
|
+
"iconSmall2x": "./assets/images/myimage-tvos-800x480.png",
|
|
46
|
+
"topShelf": "./assets/images/myimage-tvos-1920x720.png",
|
|
47
|
+
"topShelf2x": "./assets/images/myimage-tvos-3840x1440.png",
|
|
48
|
+
"topShelfWide": "./assets/images/myimage-tvos-2320x720.png",
|
|
49
|
+
"topShelfWide2x": "./assets/images/myimage-tvos-4640x1440.png"
|
|
50
|
+
}
|
|
42
51
|
}
|
|
43
52
|
]
|
|
44
53
|
]
|
|
@@ -52,12 +61,20 @@ _Plugin parameters_:
|
|
|
52
61
|
|
|
53
62
|
- `isTV`: (optional boolean, default false) If true, prebuild should generate or modify Android and iOS files to build for TV (Android TV and Apple TV). If false, the plugin will have no effect. Setting the environment variable EXPO_TV to "true" or "1" will override this value and force a TV build.
|
|
54
63
|
- `showVerboseWarnings`: Deprecated. Verbose logging is now shown as in other config plugins, by setting an environment variable:
|
|
55
|
-
- EXPO_DEBUG=1 (shows debug messages from all plugins)
|
|
56
|
-
- DEBUG=expo
|
|
57
|
-
- DEBUG=expo:react-native-tvos:config-tv (shows debug messages from this plugin only)
|
|
64
|
+
- `EXPO_DEBUG=1` (shows debug messages from all plugins)
|
|
65
|
+
- `DEBUG=expo:*` (shows debug messages from all plugins)
|
|
66
|
+
- `DEBUG=expo:react-native-tvos:config-tv` (shows debug messages from this plugin only)
|
|
58
67
|
- `tvosDeploymentTarget`: (optional string, default '13.4') Used to set the tvOS deployment target version in the Xcode project.
|
|
59
68
|
- `removeFlipperOnAndroid`: (optional boolean, default true) Used to remove the Flipper dependency from `MainApplication.kt` (or `MainApplication.java`) and `android/app/build.gradle`. This is necessary for React Native TV 0.73 and higher, since Flipper integration is removed from these versions. If this causes issues, set the value to false, run `npx expo prebuild --clean` again, and then remove Flipper from your Android source manually.
|
|
60
69
|
- `androidTVBanner`: (optional string) If set, this should be a path to an existing PNG file appropriate for an Android TV banner image. See https://developer.android.com/design/ui/tv/guides/system/tv-app-icon-guidelines#banner . The Android manifest will be modified to reference this image, and the image will be copied into Android resource drawable directories.
|
|
70
|
+
- `appleTVImages`: (optional object) If set, this is an object with the paths to images needed to construct the Apple TV icon and top shelf brand assets. The images will be used to construct a brand asset catalog in the Xcode project Image catalog, and the project updated to use the brand assets as the source for the app icons. If this property is set, all image paths must be defined and the files must exist, or an error will be thrown. The images need to be the exact sizes shown here, in order to avoid errors during Xcode compilation and on submission to the App Store or TestFlight.
|
|
71
|
+
- `icon`: (string) Path to a 1280x760 image
|
|
72
|
+
- `iconSmall`: (string) Path to a 400x240 image
|
|
73
|
+
- `iconSmall2x`: (string) Path to a 800x480 image
|
|
74
|
+
- `topShelf`: (string) Path to a 1920x720 image
|
|
75
|
+
- `topShelf2x`: (string) Path to a 3840x1440 image
|
|
76
|
+
- `topShelfWide`: (string) Path to a 2320x720 image
|
|
77
|
+
- `topShelfWide2x`: (string) Path to a 4640x1440 image
|
|
61
78
|
|
|
62
79
|
_Warning_:
|
|
63
80
|
|
|
@@ -66,7 +83,7 @@ When this plugin is used to generate files in the iOS directory that build an Ap
|
|
|
66
83
|
```json
|
|
67
84
|
{
|
|
68
85
|
"dependencies": {
|
|
69
|
-
"react-native": "npm:react-native-tvos@^0.73.
|
|
86
|
+
"react-native": "npm:react-native-tvos@^0.73.6-0"
|
|
70
87
|
}
|
|
71
88
|
}
|
|
72
89
|
```
|
package/build/types.d.ts
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
export type AppleTVImages = {
|
|
2
|
+
/**
|
|
3
|
+
* Path to 400x240 image
|
|
4
|
+
*/
|
|
5
|
+
iconSmall: string;
|
|
6
|
+
/**
|
|
7
|
+
* Path to 800x480 image
|
|
8
|
+
*/
|
|
9
|
+
iconSmall2x: string;
|
|
10
|
+
/**
|
|
11
|
+
* Path to 1280x760 image
|
|
12
|
+
*/
|
|
13
|
+
icon: string;
|
|
14
|
+
/**
|
|
15
|
+
* Path to 1920x720 image
|
|
16
|
+
*/
|
|
17
|
+
topShelf: string;
|
|
18
|
+
/**
|
|
19
|
+
* Path to 3840x1440 image
|
|
20
|
+
*/
|
|
21
|
+
topShelf2x: string;
|
|
22
|
+
/**
|
|
23
|
+
* Path to 2320x720 image
|
|
24
|
+
*/
|
|
25
|
+
topShelfWide: string;
|
|
26
|
+
/**
|
|
27
|
+
* Path to 4640x1440 image
|
|
28
|
+
*/
|
|
29
|
+
topShelfWide2x: string;
|
|
30
|
+
};
|
|
1
31
|
export type ConfigData = {
|
|
2
32
|
/**
|
|
3
33
|
* If true, prebuild should generate Android and iOS files for TV (Android TV and Apple TV).
|
|
@@ -30,4 +60,13 @@ export type ConfigData = {
|
|
|
30
60
|
* Android resource drawable directories.
|
|
31
61
|
*/
|
|
32
62
|
androidTVBanner?: string;
|
|
63
|
+
/**
|
|
64
|
+
* If set, this is an object with the paths to images needed to construct the Apple TV icon and
|
|
65
|
+
* top shelf brand assets. The images will be used to construct a brand asset catalog in the Xcode
|
|
66
|
+
* project Image catalog, and the project updated to use the brand assets as the source for the app
|
|
67
|
+
* icons. If this property is set, all six image paths must be defined and the files must exist,
|
|
68
|
+
* or an error will be thrown. The images need to be the exact sizes shown here, in order to avoid
|
|
69
|
+
* errors during Xcode compilation and on submission to the App Store or TestFlight.
|
|
70
|
+
*/
|
|
71
|
+
appleTVImages?: AppleTVImages;
|
|
33
72
|
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export type ContentsJsonImageIdiom = 'tv';
|
|
2
|
+
export type ContentsJsonImageAppearance = {
|
|
3
|
+
appearance: 'luminosity';
|
|
4
|
+
value: 'dark';
|
|
5
|
+
};
|
|
6
|
+
export type ContentsJsonImageScale = '1x' | '2x' | '3x';
|
|
7
|
+
export type ContentsJsonImageRole = 'primary-app-icon' | 'top-shelf-image' | 'top-shelf-image-wide';
|
|
8
|
+
export interface ContentsJsonImage {
|
|
9
|
+
appearances?: ContentsJsonImageAppearance[];
|
|
10
|
+
idiom: ContentsJsonImageIdiom;
|
|
11
|
+
size?: string;
|
|
12
|
+
scale?: ContentsJsonImageScale;
|
|
13
|
+
filename: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ContentsJsonImageLayer {
|
|
16
|
+
filename: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ContentsJsonAsset {
|
|
19
|
+
filename?: string;
|
|
20
|
+
idiom?: ContentsJsonImageIdiom;
|
|
21
|
+
role?: ContentsJsonImageRole;
|
|
22
|
+
size?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ContentsJson {
|
|
25
|
+
assets?: ContentsJsonAsset[];
|
|
26
|
+
images?: ContentsJsonImage[];
|
|
27
|
+
layers?: ContentsJsonImageLayer[];
|
|
28
|
+
info: {
|
|
29
|
+
version: number;
|
|
30
|
+
author: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface SourceImageJson {
|
|
34
|
+
path: string;
|
|
35
|
+
scale?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface SourceImageSetJson {
|
|
38
|
+
name: string;
|
|
39
|
+
sourceImages: SourceImageJson[];
|
|
40
|
+
}
|
|
41
|
+
export interface SourceImageLayerJson {
|
|
42
|
+
name: string;
|
|
43
|
+
sourceImages: SourceImageJson[];
|
|
44
|
+
}
|
|
45
|
+
export interface SourceImageStackJson {
|
|
46
|
+
name: string;
|
|
47
|
+
sourceLayers: SourceImageLayerJson[];
|
|
48
|
+
}
|
|
49
|
+
export interface SourceBrandAssetJson {
|
|
50
|
+
role: ContentsJsonImageRole;
|
|
51
|
+
size: string;
|
|
52
|
+
imageStack?: SourceImageStackJson;
|
|
53
|
+
imageSet?: SourceImageSetJson;
|
|
54
|
+
}
|
|
55
|
+
export interface SourceBrandAssetsJson {
|
|
56
|
+
name: string;
|
|
57
|
+
assets: SourceBrandAssetJson[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Writes the Config.json which is used to assign images to their respective platform, dpi, and idiom.
|
|
61
|
+
*
|
|
62
|
+
* @param directory path to add the Contents.json to.
|
|
63
|
+
* @param contents image json data
|
|
64
|
+
*/
|
|
65
|
+
export declare function writeContentsJsonAsync(directory: string, options: {
|
|
66
|
+
assets?: ContentsJsonAsset[];
|
|
67
|
+
images?: ContentsJsonImage[];
|
|
68
|
+
layers?: ContentsJsonImageLayer[];
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Creates an image set directory with its Contents.json and any images
|
|
72
|
+
*/
|
|
73
|
+
export declare function createImageSetAsync(destinationPath: string, imageSet: SourceImageSetJson): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Creates an image stack layer directory with its Contents.json and any images
|
|
76
|
+
*/
|
|
77
|
+
export declare function createImageStackLayerAsync(destinationPath: string, layer: SourceImageLayerJson): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Creates an image stack directory with its Contents.json and any layers
|
|
80
|
+
*/
|
|
81
|
+
export declare function createImageStackAsync(destinationPath: string, stack: SourceImageStackJson): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Creates a brand assets directory with its Contents.json and any assets
|
|
84
|
+
*/
|
|
85
|
+
export declare function createBrandAssetsAsync(destinationPath: string, brandAssets: SourceBrandAssetsJson): Promise<void>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createBrandAssetsAsync = exports.createImageStackAsync = exports.createImageStackLayerAsync = exports.createImageSetAsync = exports.writeContentsJsonAsync = void 0;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
/**
|
|
10
|
+
* Writes the Config.json which is used to assign images to their respective platform, dpi, and idiom.
|
|
11
|
+
*
|
|
12
|
+
* @param directory path to add the Contents.json to.
|
|
13
|
+
* @param contents image json data
|
|
14
|
+
*/
|
|
15
|
+
async function writeContentsJsonAsync(directory, options) {
|
|
16
|
+
await fs_1.promises.mkdir(directory, { recursive: true });
|
|
17
|
+
await fs_1.promises.writeFile(path_1.default.join(directory, 'Contents.json'), JSON.stringify({
|
|
18
|
+
assets: options.assets,
|
|
19
|
+
images: options.images,
|
|
20
|
+
layers: options.layers,
|
|
21
|
+
info: {
|
|
22
|
+
version: 1,
|
|
23
|
+
// common practice is for the tool that generated the icons to be the "author"
|
|
24
|
+
author: 'expo',
|
|
25
|
+
},
|
|
26
|
+
}, null, 2));
|
|
27
|
+
}
|
|
28
|
+
exports.writeContentsJsonAsync = writeContentsJsonAsync;
|
|
29
|
+
/**
|
|
30
|
+
* Creates an image set directory with its Contents.json and any images
|
|
31
|
+
*/
|
|
32
|
+
async function createImageSetAsync(destinationPath, imageSet) {
|
|
33
|
+
const imageSetPath = path_1.default.join(destinationPath, `${imageSet.name}.imageset`);
|
|
34
|
+
await writeContentsJsonAsync(imageSetPath, {
|
|
35
|
+
images: imageSet.sourceImages.map((image) => ({
|
|
36
|
+
filename: path_1.default.basename(image.path),
|
|
37
|
+
idiom: 'tv',
|
|
38
|
+
scale: image.scale,
|
|
39
|
+
})),
|
|
40
|
+
});
|
|
41
|
+
for (const image of imageSet.sourceImages) {
|
|
42
|
+
await fs_1.promises.copyFile(image.path, path_1.default.join(imageSetPath, path_1.default.basename(image.path)));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.createImageSetAsync = createImageSetAsync;
|
|
46
|
+
/**
|
|
47
|
+
* Creates an image stack layer directory with its Contents.json and any images
|
|
48
|
+
*/
|
|
49
|
+
async function createImageStackLayerAsync(destinationPath, layer) {
|
|
50
|
+
const imageStackLayerPath = path_1.default.join(destinationPath, `${layer.name}.imagestacklayer`);
|
|
51
|
+
await writeContentsJsonAsync(imageStackLayerPath, {});
|
|
52
|
+
await createImageSetAsync(imageStackLayerPath, {
|
|
53
|
+
name: 'Content',
|
|
54
|
+
sourceImages: layer.sourceImages,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
exports.createImageStackLayerAsync = createImageStackLayerAsync;
|
|
58
|
+
/**
|
|
59
|
+
* Creates an image stack directory with its Contents.json and any layers
|
|
60
|
+
*/
|
|
61
|
+
async function createImageStackAsync(destinationPath, stack) {
|
|
62
|
+
const imageStackPath = path_1.default.join(destinationPath, `${stack.name}.imagestack`);
|
|
63
|
+
await writeContentsJsonAsync(imageStackPath, {
|
|
64
|
+
layers: stack.sourceLayers.map((layer) => ({
|
|
65
|
+
filename: `${layer.name}.imagestacklayer`,
|
|
66
|
+
})),
|
|
67
|
+
});
|
|
68
|
+
for (const sourceLayer of stack.sourceLayers) {
|
|
69
|
+
await createImageStackLayerAsync(imageStackPath, {
|
|
70
|
+
name: sourceLayer.name,
|
|
71
|
+
sourceImages: sourceLayer.sourceImages,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.createImageStackAsync = createImageStackAsync;
|
|
76
|
+
/**
|
|
77
|
+
* Creates a brand assets directory with its Contents.json and any assets
|
|
78
|
+
*/
|
|
79
|
+
async function createBrandAssetsAsync(destinationPath, brandAssets) {
|
|
80
|
+
const brandAssetsPath = path_1.default.join(destinationPath, `${brandAssets.name}.brandassets`);
|
|
81
|
+
await writeContentsJsonAsync(brandAssetsPath, {
|
|
82
|
+
assets: brandAssets.assets.map((brandAsset) => {
|
|
83
|
+
if (brandAsset.imageStack) {
|
|
84
|
+
return {
|
|
85
|
+
filename: `${brandAsset.imageStack.name}.imagestack`,
|
|
86
|
+
role: brandAsset.role,
|
|
87
|
+
size: brandAsset.size,
|
|
88
|
+
idiom: 'tv',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
else if (brandAsset.imageSet) {
|
|
92
|
+
return {
|
|
93
|
+
filename: `${brandAsset.imageSet.name}.imageset`,
|
|
94
|
+
role: brandAsset.role,
|
|
95
|
+
size: brandAsset.size,
|
|
96
|
+
idiom: 'tv',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return {}; // Should never happen, but need this to keep Typescript happy
|
|
101
|
+
}
|
|
102
|
+
}),
|
|
103
|
+
});
|
|
104
|
+
for (const asset of brandAssets.assets) {
|
|
105
|
+
if (asset.imageSet) {
|
|
106
|
+
await createImageSetAsync(brandAssetsPath, asset.imageSet);
|
|
107
|
+
}
|
|
108
|
+
if (asset.imageStack) {
|
|
109
|
+
await createImageStackAsync(brandAssetsPath, asset.imageStack);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.createBrandAssetsAsync = createBrandAssetsAsync;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { ConfigData } from '
|
|
1
|
+
import { ConfigData } from '../types';
|
|
2
2
|
export declare const packageNameAndVersion: string;
|
|
3
3
|
export declare function isTVEnabled(params: ConfigData): boolean;
|
|
4
|
-
export declare function showVerboseWarnings(params: ConfigData): boolean;
|
|
5
4
|
export declare function tvosDeploymentTarget(params: ConfigData): string;
|
|
6
5
|
export declare function shouldRemoveFlipperOnAndroid(params: ConfigData): boolean;
|
|
7
6
|
export declare function androidTVBanner(params: ConfigData): string | undefined;
|
|
8
|
-
export declare
|
|
9
|
-
|
|
10
|
-
platform?: 'android' | 'ios';
|
|
11
|
-
property?: string;
|
|
12
|
-
}): void;
|
|
7
|
+
export declare const appleTVImageTypes: string[];
|
|
8
|
+
export declare function appleTVImagePathForType(params: ConfigData, imageType: string): string | undefined;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appleTVImagePathForType = exports.appleTVImageTypes = exports.androidTVBanner = exports.shouldRemoveFlipperOnAndroid = exports.tvosDeploymentTarget = exports.isTVEnabled = exports.packageNameAndVersion = void 0;
|
|
4
|
+
const getenv_1 = require("getenv");
|
|
5
|
+
class Env {
|
|
6
|
+
/** Enable prebuild for TV */
|
|
7
|
+
get EXPO_TV() {
|
|
8
|
+
return (0, getenv_1.boolish)('EXPO_TV', false);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const env = new Env();
|
|
12
|
+
const pkg = require('../../package.json');
|
|
13
|
+
const defaultTvosDeploymentVersion = '13.4';
|
|
14
|
+
exports.packageNameAndVersion = `${pkg.name}@${pkg.version}`;
|
|
15
|
+
function isTVEnabled(params) {
|
|
16
|
+
return env.EXPO_TV || (params?.isTV ?? false);
|
|
17
|
+
}
|
|
18
|
+
exports.isTVEnabled = isTVEnabled;
|
|
19
|
+
function tvosDeploymentTarget(params) {
|
|
20
|
+
return params?.tvosDeploymentTarget ?? defaultTvosDeploymentVersion;
|
|
21
|
+
}
|
|
22
|
+
exports.tvosDeploymentTarget = tvosDeploymentTarget;
|
|
23
|
+
function shouldRemoveFlipperOnAndroid(params) {
|
|
24
|
+
return params?.removeFlipperOnAndroid ?? true;
|
|
25
|
+
}
|
|
26
|
+
exports.shouldRemoveFlipperOnAndroid = shouldRemoveFlipperOnAndroid;
|
|
27
|
+
function androidTVBanner(params) {
|
|
28
|
+
return params?.androidTVBanner;
|
|
29
|
+
}
|
|
30
|
+
exports.androidTVBanner = androidTVBanner;
|
|
31
|
+
exports.appleTVImageTypes = [
|
|
32
|
+
'icon',
|
|
33
|
+
'iconSmall',
|
|
34
|
+
'iconSmall2x',
|
|
35
|
+
'topShelf',
|
|
36
|
+
'topShelf2x',
|
|
37
|
+
'topShelfWide',
|
|
38
|
+
'topShelfWide2x',
|
|
39
|
+
];
|
|
40
|
+
function appleTVImagePathForType(params, imageType) {
|
|
41
|
+
switch (imageType) {
|
|
42
|
+
case 'icon':
|
|
43
|
+
return params?.appleTVImages?.icon;
|
|
44
|
+
case 'iconSmall':
|
|
45
|
+
return params?.appleTVImages?.iconSmall;
|
|
46
|
+
case 'iconSmall2x':
|
|
47
|
+
return params?.appleTVImages?.iconSmall2x;
|
|
48
|
+
case 'topShelf':
|
|
49
|
+
return params?.appleTVImages?.topShelf;
|
|
50
|
+
case 'topShelf2x':
|
|
51
|
+
return params?.appleTVImages?.topShelf2x;
|
|
52
|
+
case 'topShelfWide':
|
|
53
|
+
return params?.appleTVImages?.topShelfWide;
|
|
54
|
+
case 'topShelfWide2x':
|
|
55
|
+
return params?.appleTVImages?.topShelfWide2x;
|
|
56
|
+
default:
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.appleTVImagePathForType = appleTVImagePathForType;
|
|
@@ -0,0 +1,19 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./appleBrandAssets"), exports);
|
|
18
|
+
__exportStar(require("./config"), exports);
|
|
19
|
+
__exportStar(require("./log"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verboseLog = void 0;
|
|
4
|
+
const debug = require('debug')('expo:react-native-tvos:config-tv');
|
|
5
|
+
function verboseLog(message, options) {
|
|
6
|
+
const tokens = [message];
|
|
7
|
+
options?.property && tokens.unshift(options?.property);
|
|
8
|
+
options?.platform && tokens.unshift(options?.platform);
|
|
9
|
+
debug(tokens.join(': '));
|
|
10
|
+
}
|
|
11
|
+
exports.verboseLog = verboseLog;
|
package/build/withTV.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const config_plugins_1 = require("expo/config-plugins");
|
|
4
4
|
const withTVAndroidManifest_1 = require("./withTVAndroidManifest");
|
|
5
|
+
const withTVAppleIconImages_1 = require("./withTVAppleIconImages");
|
|
6
|
+
const withTVInfoPlist_1 = require("./withTVInfoPlist");
|
|
5
7
|
const withTVPodfile_1 = require("./withTVPodfile");
|
|
6
8
|
const withTVSplashScreen_1 = require("./withTVSplashScreen");
|
|
7
9
|
const withTVXcodeProject_1 = require("./withTVXcodeProject");
|
|
@@ -18,8 +20,10 @@ const withTVPlugin = (config, params = {}) => {
|
|
|
18
20
|
config = withTVNoEffect(config, params);
|
|
19
21
|
return config;
|
|
20
22
|
}
|
|
23
|
+
config = (0, withTVAppleIconImages_1.withTVAppleIconImages)(config, params); // This should be done before Apple Xcode project config
|
|
21
24
|
config = (0, withTVXcodeProject_1.withTVXcodeProject)(config, params);
|
|
22
25
|
config = (0, withTVPodfile_1.withTVPodfile)(config, params);
|
|
26
|
+
config = (0, withTVInfoPlist_1.withTVInfoPlist)(config, params);
|
|
23
27
|
config = (0, withTVSplashScreen_1.withTVSplashScreen)(config, params);
|
|
24
28
|
config = (0, withTVAndroidBannerImage_1.withTVAndroidBannerImage)(config, params); // This should be done before Android manifest config
|
|
25
29
|
config = (0, withTVAndroidManifest_1.withTVAndroidManifest)(config, params);
|
|
@@ -5,3 +5,4 @@ export declare const withTVAndroidManifest: ConfigPlugin<ConfigData>;
|
|
|
5
5
|
export declare function setLeanBackLauncherIntent(_config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData): AndroidConfig.Manifest.AndroidManifest;
|
|
6
6
|
export declare function removePortraitOrientation(_config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData): AndroidConfig.Manifest.AndroidManifest;
|
|
7
7
|
export declare function setTVBanner(_config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData, androidTVBannerPath: string | undefined): AndroidConfig.Manifest.AndroidManifest;
|
|
8
|
+
export declare function addTouchscreenHardwareFeatureToManifest(_config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData): AndroidConfig.Manifest.AndroidManifest;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setTVBanner = exports.removePortraitOrientation = exports.setLeanBackLauncherIntent = exports.withTVAndroidManifest = void 0;
|
|
3
|
+
exports.addTouchscreenHardwareFeatureToManifest = exports.setTVBanner = exports.removePortraitOrientation = exports.setLeanBackLauncherIntent = exports.withTVAndroidManifest = void 0;
|
|
4
4
|
const config_plugins_1 = require("expo/config-plugins");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
const { getMainActivity, getMainApplication } = config_plugins_1.AndroidConfig.Manifest;
|
|
@@ -9,6 +9,7 @@ const withTVAndroidManifest = (config, params = {}) => {
|
|
|
9
9
|
return (0, config_plugins_1.withAndroidManifest)(config, (config) => {
|
|
10
10
|
config.modResults = setLeanBackLauncherIntent(config, config.modResults, params);
|
|
11
11
|
config.modResults = removePortraitOrientation(config, config.modResults, params);
|
|
12
|
+
config.modResults = addTouchscreenHardwareFeatureToManifest(config, config.modResults, params);
|
|
12
13
|
if (androidTVBannerPath) {
|
|
13
14
|
config.modResults = setTVBanner(config, config.modResults, params, androidTVBannerPath);
|
|
14
15
|
}
|
|
@@ -90,3 +91,39 @@ function setTVBanner(_config, androidManifest, params, androidTVBannerPath) {
|
|
|
90
91
|
return androidManifest;
|
|
91
92
|
}
|
|
92
93
|
exports.setTVBanner = setTVBanner;
|
|
94
|
+
function addTouchscreenHardwareFeatureToManifest(_config, androidManifest, params) {
|
|
95
|
+
// Add `<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>` to the AndroidManifest.xml
|
|
96
|
+
if (!Array.isArray(androidManifest.manifest['uses-feature'])) {
|
|
97
|
+
androidManifest.manifest['uses-feature'] = [];
|
|
98
|
+
}
|
|
99
|
+
if (!androidManifest.manifest['uses-feature'].find((item) => item.$['android:name'] === 'android.hardware.touchscreen') &&
|
|
100
|
+
!androidManifest.manifest['uses-feature'].find((item) => item.$['android:name'] === 'android.hardware.faketouch') &&
|
|
101
|
+
!androidManifest.manifest['uses-feature'].find((item) => item.$['android:name'] === 'android.software.leanback')) {
|
|
102
|
+
(0, utils_1.verboseLog)('adding TV touchscreen hardware feature tag to AndroidManifest.xml', {
|
|
103
|
+
params,
|
|
104
|
+
platform: 'android',
|
|
105
|
+
property: 'manifest',
|
|
106
|
+
});
|
|
107
|
+
androidManifest.manifest['uses-feature']?.push({
|
|
108
|
+
$: {
|
|
109
|
+
'android:name': 'android.hardware.touchscreen',
|
|
110
|
+
'android:required': 'false',
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
androidManifest.manifest['uses-feature']?.push({
|
|
114
|
+
$: {
|
|
115
|
+
'android:name': 'android.hardware.faketouch',
|
|
116
|
+
'android:required': 'false',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
// add android.software.leanback to false
|
|
120
|
+
androidManifest.manifest['uses-feature']?.push({
|
|
121
|
+
$: {
|
|
122
|
+
'android:name': 'android.software.leanback',
|
|
123
|
+
'android:required': 'false',
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return androidManifest;
|
|
128
|
+
}
|
|
129
|
+
exports.addTouchscreenHardwareFeatureToManifest = addTouchscreenHardwareFeatureToManifest;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ConfigPlugin } from 'expo/config-plugins';
|
|
2
|
+
import { ConfigData } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Constructs Apple TV brand assets from images passed into the `appleTVImages` plugin property
|
|
5
|
+
* If any images do not exist, an exception is thrown.
|
|
6
|
+
*/
|
|
7
|
+
export declare const withTVAppleIconImages: ConfigPlugin<ConfigData>;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.withTVAppleIconImages = void 0;
|
|
7
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
const { getProjectName } = config_plugins_1.IOSConfig.XcodeUtils;
|
|
12
|
+
/**
|
|
13
|
+
* Constructs Apple TV brand assets from images passed into the `appleTVImages` plugin property
|
|
14
|
+
* If any images do not exist, an exception is thrown.
|
|
15
|
+
*/
|
|
16
|
+
const withTVAppleIconImages = (c, params = {}) => {
|
|
17
|
+
return (0, config_plugins_1.withDangerousMod)(c, [
|
|
18
|
+
'ios',
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
20
|
+
async (config) => {
|
|
21
|
+
if (!params.appleTVImages) {
|
|
22
|
+
return config;
|
|
23
|
+
}
|
|
24
|
+
(0, utils_1.verboseLog)(`adding Apple TV brand assets to Apple TV native code`, {
|
|
25
|
+
params,
|
|
26
|
+
platform: 'ios',
|
|
27
|
+
property: 'xcodeproject',
|
|
28
|
+
});
|
|
29
|
+
utils_1.appleTVImageTypes.forEach((imageType) => {
|
|
30
|
+
const imagePath = (0, utils_1.appleTVImagePathForType)(params, imageType);
|
|
31
|
+
if (!imagePath) {
|
|
32
|
+
throw new Error(`One or more image paths not defined`);
|
|
33
|
+
}
|
|
34
|
+
if (!(0, fs_1.existsSync)(imagePath)) {
|
|
35
|
+
throw new Error(`No image found at path ${imagePath}`);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const projectRoot = config.modRequest.projectRoot;
|
|
39
|
+
const iosImagesPath = path_1.default.join(getIosNamedProjectPath(projectRoot), IMAGES_PATH);
|
|
40
|
+
const iconSmallSourceImages = [
|
|
41
|
+
{
|
|
42
|
+
path: params.appleTVImages.iconSmall,
|
|
43
|
+
scale: '1x',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
path: params.appleTVImages.iconSmall2x,
|
|
47
|
+
scale: '2x',
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
const iconLargeSourceImages = [
|
|
51
|
+
{
|
|
52
|
+
path: params.appleTVImages.icon,
|
|
53
|
+
scale: '1x',
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
/*
|
|
57
|
+
const appStoreIconSourceImages: SourceImageJson[] = [
|
|
58
|
+
{
|
|
59
|
+
path: params.appleTVImages.icon,
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
*/
|
|
63
|
+
const topShelfSourceImages = [
|
|
64
|
+
{
|
|
65
|
+
path: params.appleTVImages.topShelf,
|
|
66
|
+
scale: '1x',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
path: params.appleTVImages.topShelf2x,
|
|
70
|
+
scale: '2x',
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
const topShelfWideSourceImages = [
|
|
74
|
+
{
|
|
75
|
+
path: params.appleTVImages.topShelfWide,
|
|
76
|
+
scale: '1x',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
path: params.appleTVImages.topShelfWide2x,
|
|
80
|
+
scale: '2x',
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
const sourceBrandAssets = {
|
|
84
|
+
name: 'TVAppIcon',
|
|
85
|
+
assets: [
|
|
86
|
+
{
|
|
87
|
+
role: 'top-shelf-image',
|
|
88
|
+
size: '1920x720',
|
|
89
|
+
imageSet: {
|
|
90
|
+
name: 'Top Shelf Image',
|
|
91
|
+
sourceImages: topShelfSourceImages,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
role: 'top-shelf-image-wide',
|
|
96
|
+
size: '2320x720',
|
|
97
|
+
imageSet: {
|
|
98
|
+
name: 'Top Shelf Image Wide',
|
|
99
|
+
sourceImages: topShelfWideSourceImages,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
/*
|
|
103
|
+
{
|
|
104
|
+
role: 'primary-app-icon',
|
|
105
|
+
size: '1280x768',
|
|
106
|
+
imageStack: {
|
|
107
|
+
name: 'App Icon - App Store',
|
|
108
|
+
sourceLayers: [
|
|
109
|
+
{
|
|
110
|
+
name: 'Front',
|
|
111
|
+
sourceImages: appStoreIconSourceImages,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'Middle',
|
|
115
|
+
sourceImages: appStoreIconSourceImages,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: 'Back',
|
|
119
|
+
sourceImages: appStoreIconSourceImages,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
*/
|
|
125
|
+
{
|
|
126
|
+
role: 'primary-app-icon',
|
|
127
|
+
size: '400x240',
|
|
128
|
+
imageStack: {
|
|
129
|
+
name: 'App Icon - Small',
|
|
130
|
+
sourceLayers: [
|
|
131
|
+
{
|
|
132
|
+
name: 'Front',
|
|
133
|
+
sourceImages: iconSmallSourceImages,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'Middle',
|
|
137
|
+
sourceImages: iconSmallSourceImages,
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'Back',
|
|
141
|
+
sourceImages: iconSmallSourceImages,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
role: 'primary-app-icon',
|
|
148
|
+
size: '1280x768',
|
|
149
|
+
imageStack: {
|
|
150
|
+
name: 'App Icon - Large',
|
|
151
|
+
sourceLayers: [
|
|
152
|
+
{
|
|
153
|
+
name: 'Front',
|
|
154
|
+
sourceImages: iconLargeSourceImages,
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'Middle',
|
|
158
|
+
sourceImages: iconLargeSourceImages,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: 'Back',
|
|
162
|
+
sourceImages: iconLargeSourceImages,
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
await (0, utils_1.createBrandAssetsAsync)(iosImagesPath, sourceBrandAssets);
|
|
170
|
+
return config;
|
|
171
|
+
},
|
|
172
|
+
]);
|
|
173
|
+
};
|
|
174
|
+
exports.withTVAppleIconImages = withTVAppleIconImages;
|
|
175
|
+
function getIosNamedProjectPath(projectRoot) {
|
|
176
|
+
const projectName = getProjectName(projectRoot);
|
|
177
|
+
return path_1.default.join(projectRoot, 'ios', projectName);
|
|
178
|
+
}
|
|
179
|
+
const IMAGES_PATH = 'Images.xcassets';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withTVInfoPlist = void 0;
|
|
4
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const withTVInfoPlist = (c, params = {}) => {
|
|
7
|
+
(0, utils_1.verboseLog)('Modifying UIRequiredDeviceCapabilities for TV', {
|
|
8
|
+
params,
|
|
9
|
+
platform: 'ios',
|
|
10
|
+
property: 'Info.plist',
|
|
11
|
+
});
|
|
12
|
+
return (0, config_plugins_1.withInfoPlist)(c, (config) => {
|
|
13
|
+
config.modResults.UIRequiredDeviceCapabilities = ['arm64'];
|
|
14
|
+
return config;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
exports.withTVInfoPlist = withTVInfoPlist;
|
|
@@ -21,18 +21,24 @@ function setXcodeProjectBuildSettings(config, { project, params, deploymentTarge
|
|
|
21
21
|
for (const { buildSettings } of Object.values(configurations || {})) {
|
|
22
22
|
// Guessing that this is the best way to emulate Xcode.
|
|
23
23
|
// Using `project.addToBuildSettings` modifies too many targets.
|
|
24
|
+
if (buildSettings !== undefined) {
|
|
25
|
+
buildSettings.SDKROOT = 'appletvos';
|
|
26
|
+
}
|
|
24
27
|
if (typeof buildSettings?.PRODUCT_NAME !== 'undefined') {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
buildSettings
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
(0, utils_1.verboseLog)(`modifying target ${buildSettings?.PRODUCT_NAME} for tvOS`, {
|
|
29
|
+
params,
|
|
30
|
+
platform: 'ios',
|
|
31
|
+
property: 'xcodeproject',
|
|
32
|
+
});
|
|
33
|
+
buildSettings.TARGETED_DEVICE_FAMILY = '3';
|
|
34
|
+
buildSettings.TVOS_DEPLOYMENT_TARGET = deploymentTarget;
|
|
35
|
+
if (typeof buildSettings?.IOS_DEPLOYMENT_TARGET !== 'undefined') {
|
|
36
|
+
delete buildSettings?.IOS_DEPLOYMENT_TARGET;
|
|
37
|
+
}
|
|
38
|
+
if (params.appleTVImages) {
|
|
39
|
+
// set the app icon source
|
|
40
|
+
if (buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME === 'AppIcon') {
|
|
41
|
+
buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME = 'TVAppIcon';
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
44
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-tvos/config-tv",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Config plugin to reconfigure native directories for Apple TV and Android TV development if needed",
|
|
5
5
|
"main": "build/withTV.js",
|
|
6
6
|
"types": "build/withTV.d.ts",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/getenv": "^1.0.1",
|
|
41
41
|
"expo-module-scripts": "^3.0.3",
|
|
42
|
-
"jest": "^29.7.0"
|
|
42
|
+
"jest": "^29.7.0",
|
|
43
|
+
"memfs": "^4.7.6"
|
|
43
44
|
},
|
|
44
45
|
"upstreamPackage": "tv",
|
|
45
46
|
"dependencies": {
|
package/build/utils.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.verboseLog = exports.androidTVBanner = exports.shouldRemoveFlipperOnAndroid = exports.tvosDeploymentTarget = exports.showVerboseWarnings = exports.isTVEnabled = exports.packageNameAndVersion = void 0;
|
|
4
|
-
const getenv_1 = require("getenv");
|
|
5
|
-
class Env {
|
|
6
|
-
/** Enable prebuild for TV */
|
|
7
|
-
get EXPO_TV() {
|
|
8
|
-
return (0, getenv_1.boolish)('EXPO_TV', false);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
const debug = require('debug')('expo:react-native-tvos:config-tv');
|
|
12
|
-
const env = new Env();
|
|
13
|
-
const pkg = require('../package.json');
|
|
14
|
-
const defaultTvosDeploymentVersion = '13.4';
|
|
15
|
-
exports.packageNameAndVersion = `${pkg.name}@${pkg.version}`;
|
|
16
|
-
function isTVEnabled(params) {
|
|
17
|
-
return env.EXPO_TV || (params?.isTV ?? false);
|
|
18
|
-
}
|
|
19
|
-
exports.isTVEnabled = isTVEnabled;
|
|
20
|
-
function showVerboseWarnings(params) {
|
|
21
|
-
return params?.showVerboseWarnings ?? false;
|
|
22
|
-
}
|
|
23
|
-
exports.showVerboseWarnings = showVerboseWarnings;
|
|
24
|
-
function tvosDeploymentTarget(params) {
|
|
25
|
-
return params?.tvosDeploymentTarget ?? defaultTvosDeploymentVersion;
|
|
26
|
-
}
|
|
27
|
-
exports.tvosDeploymentTarget = tvosDeploymentTarget;
|
|
28
|
-
function shouldRemoveFlipperOnAndroid(params) {
|
|
29
|
-
return params?.removeFlipperOnAndroid ?? true;
|
|
30
|
-
}
|
|
31
|
-
exports.shouldRemoveFlipperOnAndroid = shouldRemoveFlipperOnAndroid;
|
|
32
|
-
function androidTVBanner(params) {
|
|
33
|
-
return params?.androidTVBanner;
|
|
34
|
-
}
|
|
35
|
-
exports.androidTVBanner = androidTVBanner;
|
|
36
|
-
function verboseLog(message, options) {
|
|
37
|
-
const tokens = [message];
|
|
38
|
-
options?.property && tokens.unshift(options?.property);
|
|
39
|
-
options?.platform && tokens.unshift(options?.platform);
|
|
40
|
-
debug(tokens.join(': '));
|
|
41
|
-
}
|
|
42
|
-
exports.verboseLog = verboseLog;
|