@react-native-tvos/config-tv 0.0.12 → 0.1.0
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 +4 -4
- package/build/types.d.ts +4 -4
- package/build/utils/appleBrandAssets.d.ts +5 -5
- package/build/utils/appleBrandAssets.js +11 -12
- package/build/utils/config.d.ts +1 -1
- package/build/utils/config.js +26 -26
- package/build/utils/index.d.ts +3 -3
- package/build/utils/log.d.ts +2 -2
- package/build/utils/log.js +3 -4
- package/build/withTV.d.ts +2 -2
- package/build/withTV.js +5 -5
- package/build/withTVAndroidBannerImage.d.ts +2 -2
- package/build/withTVAndroidBannerImage.js +11 -11
- package/build/withTVAndroidIconImage.d.ts +2 -2
- package/build/withTVAndroidIconImage.js +14 -14
- package/build/withTVAndroidManifest.d.ts +8 -8
- package/build/withTVAndroidManifest.js +44 -44
- package/build/withTVAndroidRemoveFlipper.d.ts +2 -2
- package/build/withTVAndroidRemoveFlipper.js +18 -18
- package/build/withTVAppleIconImages.d.ts +2 -2
- package/build/withTVAppleIconImages.js +31 -31
- package/build/withTVInfoPlist.d.ts +2 -2
- package/build/withTVInfoPlist.js +4 -4
- package/build/withTVPodfile.d.ts +2 -2
- package/build/withTVPodfile.js +13 -13
- package/build/withTVSplashScreen.d.ts +2 -2
- package/build/withTVSplashScreen.js +12 -12
- package/build/withTVXcodeProject.d.ts +3 -4
- package/build/withTVXcodeProject.js +11 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ or
|
|
|
36
36
|
{
|
|
37
37
|
"isTV": true,
|
|
38
38
|
"showVerboseWarnings": false,
|
|
39
|
-
"tvosDeploymentTarget": "
|
|
39
|
+
"tvosDeploymentTarget": "15.1",
|
|
40
40
|
"removeFlipperOnAndroid": true,
|
|
41
41
|
"androidTVBanner": "assets/images/tv_banner.png",
|
|
42
42
|
"androidTVIcon": "assets/images/tv_icon.png",
|
|
@@ -65,11 +65,11 @@ _Plugin parameters_:
|
|
|
65
65
|
- `EXPO_DEBUG=1` (shows debug messages from all plugins)
|
|
66
66
|
- `DEBUG=expo:*` (shows debug messages from all plugins)
|
|
67
67
|
- `DEBUG=expo:react-native-tvos:config-tv` (shows debug messages from this plugin only)
|
|
68
|
-
- `tvosDeploymentTarget`: (optional string, default '
|
|
69
|
-
- `removeFlipperOnAndroid`: (optional boolean, default
|
|
68
|
+
- `tvosDeploymentTarget`: (optional string, default '15.1') Used to set the tvOS deployment target version in the Xcode project.
|
|
69
|
+
- `removeFlipperOnAndroid`: (optional boolean, default false) Used to remove the Flipper dependency from `MainApplication.kt` (or `MainApplication.java`) and `android/app/build.gradle`. This may be 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. If enabled, this change will be made regardless of the setting of the `EXPO_TV` environment variable or the value of the `isTV` plugin parameter.
|
|
70
70
|
- `androidTVRequired`: (optional boolean, default false) If set, the Android manifest will be configured for Android TV only (no Android mobile support). Specifically, the "uses-feature" tag for "android.software.leanback" will be set to "required=true".
|
|
71
71
|
- `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.
|
|
72
|
-
-
|
|
72
|
+
- `androidTVIcon`: (optional string) If set, this should be a path to an existing PNG file appropriate for an Android TV icon image. See https://developer.android.com/design/ui/tv/guides/system/tv-app-icon-guidelines#launcher-icon . The Android manifest will be modified to reference this image, and the image will be copied into Android resource drawable and mipmap directories.
|
|
73
73
|
- `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.
|
|
74
74
|
- `icon`: (string) Path to a 1280x760 image
|
|
75
75
|
- `iconSmall`: (string) Path to a 400x240 image
|
package/build/types.d.ts
CHANGED
|
@@ -46,13 +46,13 @@ export type ConfigData = {
|
|
|
46
46
|
*/
|
|
47
47
|
showVerboseWarnings?: boolean;
|
|
48
48
|
/**
|
|
49
|
-
* If set, this will be used as the tvOS deployment target version instead of the default (
|
|
49
|
+
* If set, this will be used as the tvOS deployment target version instead of the default (15.1).
|
|
50
50
|
*/
|
|
51
51
|
tvosDeploymentTarget?: string;
|
|
52
52
|
/**
|
|
53
|
-
* If set, Android code that references Flipper will be removed. (Defaults to
|
|
54
|
-
*
|
|
55
|
-
* the value of the `isTV` plugin parameter
|
|
53
|
+
* If set, Android code that references Flipper will be removed. (Defaults to false.)
|
|
54
|
+
* If enabled, this change will be made regardless of the setting of the `EXPO_TV` environment variable or
|
|
55
|
+
* the value of the `isTV` plugin parameter.
|
|
56
56
|
*/
|
|
57
57
|
removeFlipperOnAndroid?: boolean;
|
|
58
58
|
/**
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export type ContentsJsonImageIdiom =
|
|
1
|
+
export type ContentsJsonImageIdiom = "tv";
|
|
2
2
|
export type ContentsJsonImageAppearance = {
|
|
3
|
-
appearance:
|
|
4
|
-
value:
|
|
3
|
+
appearance: "luminosity";
|
|
4
|
+
value: "dark";
|
|
5
5
|
};
|
|
6
|
-
export type ContentsJsonImageScale =
|
|
7
|
-
export type ContentsJsonImageRole =
|
|
6
|
+
export type ContentsJsonImageScale = "1x" | "2x" | "3x";
|
|
7
|
+
export type ContentsJsonImageRole = "primary-app-icon" | "top-shelf-image" | "top-shelf-image-wide";
|
|
8
8
|
export interface ContentsJsonImage {
|
|
9
9
|
appearances?: ContentsJsonImageAppearance[];
|
|
10
10
|
idiom: ContentsJsonImageIdiom;
|
|
@@ -3,7 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.writeContentsJsonAsync = writeContentsJsonAsync;
|
|
7
|
+
exports.createImageSetAsync = createImageSetAsync;
|
|
8
|
+
exports.createImageStackLayerAsync = createImageStackLayerAsync;
|
|
9
|
+
exports.createImageStackAsync = createImageStackAsync;
|
|
10
|
+
exports.createBrandAssetsAsync = createBrandAssetsAsync;
|
|
7
11
|
const fs_1 = require("fs");
|
|
8
12
|
const path_1 = __importDefault(require("path"));
|
|
9
13
|
/**
|
|
@@ -14,18 +18,17 @@ const path_1 = __importDefault(require("path"));
|
|
|
14
18
|
*/
|
|
15
19
|
async function writeContentsJsonAsync(directory, options) {
|
|
16
20
|
await fs_1.promises.mkdir(directory, { recursive: true });
|
|
17
|
-
await fs_1.promises.writeFile(path_1.default.join(directory,
|
|
21
|
+
await fs_1.promises.writeFile(path_1.default.join(directory, "Contents.json"), JSON.stringify({
|
|
18
22
|
assets: options.assets,
|
|
19
23
|
images: options.images,
|
|
20
24
|
layers: options.layers,
|
|
21
25
|
info: {
|
|
22
26
|
version: 1,
|
|
23
27
|
// common practice is for the tool that generated the icons to be the "author"
|
|
24
|
-
author:
|
|
28
|
+
author: "expo",
|
|
25
29
|
},
|
|
26
30
|
}, null, 2));
|
|
27
31
|
}
|
|
28
|
-
exports.writeContentsJsonAsync = writeContentsJsonAsync;
|
|
29
32
|
/**
|
|
30
33
|
* Creates an image set directory with its Contents.json and any images
|
|
31
34
|
*/
|
|
@@ -34,7 +37,7 @@ async function createImageSetAsync(destinationPath, imageSet) {
|
|
|
34
37
|
await writeContentsJsonAsync(imageSetPath, {
|
|
35
38
|
images: imageSet.sourceImages.map((image) => ({
|
|
36
39
|
filename: path_1.default.basename(image.path),
|
|
37
|
-
idiom:
|
|
40
|
+
idiom: "tv",
|
|
38
41
|
scale: image.scale,
|
|
39
42
|
})),
|
|
40
43
|
});
|
|
@@ -42,7 +45,6 @@ async function createImageSetAsync(destinationPath, imageSet) {
|
|
|
42
45
|
await fs_1.promises.copyFile(image.path, path_1.default.join(imageSetPath, path_1.default.basename(image.path)));
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
|
-
exports.createImageSetAsync = createImageSetAsync;
|
|
46
48
|
/**
|
|
47
49
|
* Creates an image stack layer directory with its Contents.json and any images
|
|
48
50
|
*/
|
|
@@ -50,11 +52,10 @@ async function createImageStackLayerAsync(destinationPath, layer) {
|
|
|
50
52
|
const imageStackLayerPath = path_1.default.join(destinationPath, `${layer.name}.imagestacklayer`);
|
|
51
53
|
await writeContentsJsonAsync(imageStackLayerPath, {});
|
|
52
54
|
await createImageSetAsync(imageStackLayerPath, {
|
|
53
|
-
name:
|
|
55
|
+
name: "Content",
|
|
54
56
|
sourceImages: layer.sourceImages,
|
|
55
57
|
});
|
|
56
58
|
}
|
|
57
|
-
exports.createImageStackLayerAsync = createImageStackLayerAsync;
|
|
58
59
|
/**
|
|
59
60
|
* Creates an image stack directory with its Contents.json and any layers
|
|
60
61
|
*/
|
|
@@ -72,7 +73,6 @@ async function createImageStackAsync(destinationPath, stack) {
|
|
|
72
73
|
});
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
exports.createImageStackAsync = createImageStackAsync;
|
|
76
76
|
/**
|
|
77
77
|
* Creates a brand assets directory with its Contents.json and any assets
|
|
78
78
|
*/
|
|
@@ -85,7 +85,7 @@ async function createBrandAssetsAsync(destinationPath, brandAssets) {
|
|
|
85
85
|
filename: `${brandAsset.imageStack.name}.imagestack`,
|
|
86
86
|
role: brandAsset.role,
|
|
87
87
|
size: brandAsset.size,
|
|
88
|
-
idiom:
|
|
88
|
+
idiom: "tv",
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
else if (brandAsset.imageSet) {
|
|
@@ -93,7 +93,7 @@ async function createBrandAssetsAsync(destinationPath, brandAssets) {
|
|
|
93
93
|
filename: `${brandAsset.imageSet.name}.imageset`,
|
|
94
94
|
role: brandAsset.role,
|
|
95
95
|
size: brandAsset.size,
|
|
96
|
-
idiom:
|
|
96
|
+
idiom: "tv",
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
else {
|
|
@@ -110,4 +110,3 @@ async function createBrandAssetsAsync(destinationPath, brandAssets) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
exports.createBrandAssetsAsync = createBrandAssetsAsync;
|
package/build/utils/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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
4
|
export declare function tvosDeploymentTarget(params: ConfigData): string;
|
package/build/utils/config.js
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.appleTVImageTypes = exports.packageNameAndVersion = void 0;
|
|
4
|
+
exports.isTVEnabled = isTVEnabled;
|
|
5
|
+
exports.tvosDeploymentTarget = tvosDeploymentTarget;
|
|
6
|
+
exports.shouldRemoveFlipperOnAndroid = shouldRemoveFlipperOnAndroid;
|
|
7
|
+
exports.isAndroidTVRequired = isAndroidTVRequired;
|
|
8
|
+
exports.androidTVBanner = androidTVBanner;
|
|
9
|
+
exports.androidTVIcon = androidTVIcon;
|
|
10
|
+
exports.appleTVImagePathForType = appleTVImagePathForType;
|
|
4
11
|
const getenv_1 = require("getenv");
|
|
5
12
|
class Env {
|
|
6
13
|
/** Enable prebuild for TV */
|
|
7
14
|
get EXPO_TV() {
|
|
8
|
-
return (0, getenv_1.boolish)(
|
|
15
|
+
return (0, getenv_1.boolish)("EXPO_TV", false);
|
|
9
16
|
}
|
|
10
17
|
}
|
|
11
18
|
const env = new Env();
|
|
12
|
-
const pkg = require(
|
|
13
|
-
const defaultTvosDeploymentVersion =
|
|
19
|
+
const pkg = require("../../package.json");
|
|
20
|
+
const defaultTvosDeploymentVersion = "15.1";
|
|
14
21
|
exports.packageNameAndVersion = `${pkg.name}@${pkg.version}`;
|
|
15
22
|
function isTVEnabled(params) {
|
|
16
23
|
return env.EXPO_TV || (params?.isTV ?? false);
|
|
17
24
|
}
|
|
18
|
-
exports.isTVEnabled = isTVEnabled;
|
|
19
25
|
function tvosDeploymentTarget(params) {
|
|
20
26
|
return params?.tvosDeploymentTarget ?? defaultTvosDeploymentVersion;
|
|
21
27
|
}
|
|
22
|
-
exports.tvosDeploymentTarget = tvosDeploymentTarget;
|
|
23
28
|
function shouldRemoveFlipperOnAndroid(params) {
|
|
24
|
-
return params?.removeFlipperOnAndroid ??
|
|
29
|
+
return params?.removeFlipperOnAndroid ?? false;
|
|
25
30
|
}
|
|
26
|
-
exports.shouldRemoveFlipperOnAndroid = shouldRemoveFlipperOnAndroid;
|
|
27
31
|
function isAndroidTVRequired(params) {
|
|
28
32
|
return params?.androidTVRequired ?? false;
|
|
29
33
|
}
|
|
30
|
-
exports.isAndroidTVRequired = isAndroidTVRequired;
|
|
31
34
|
function androidTVBanner(params) {
|
|
32
35
|
return params?.androidTVBanner;
|
|
33
36
|
}
|
|
34
|
-
exports.androidTVBanner = androidTVBanner;
|
|
35
37
|
function androidTVIcon(params) {
|
|
36
38
|
return params?.androidTVIcon;
|
|
37
39
|
}
|
|
38
|
-
exports.androidTVIcon = androidTVIcon;
|
|
39
40
|
exports.appleTVImageTypes = [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
"icon",
|
|
42
|
+
"iconSmall",
|
|
43
|
+
"iconSmall2x",
|
|
44
|
+
"topShelf",
|
|
45
|
+
"topShelf2x",
|
|
46
|
+
"topShelfWide",
|
|
47
|
+
"topShelfWide2x",
|
|
47
48
|
];
|
|
48
49
|
function appleTVImagePathForType(params, imageType) {
|
|
49
50
|
switch (imageType) {
|
|
50
|
-
case
|
|
51
|
+
case "icon":
|
|
51
52
|
return params?.appleTVImages?.icon;
|
|
52
|
-
case
|
|
53
|
+
case "iconSmall":
|
|
53
54
|
return params?.appleTVImages?.iconSmall;
|
|
54
|
-
case
|
|
55
|
+
case "iconSmall2x":
|
|
55
56
|
return params?.appleTVImages?.iconSmall2x;
|
|
56
|
-
case
|
|
57
|
+
case "topShelf":
|
|
57
58
|
return params?.appleTVImages?.topShelf;
|
|
58
|
-
case
|
|
59
|
+
case "topShelf2x":
|
|
59
60
|
return params?.appleTVImages?.topShelf2x;
|
|
60
|
-
case
|
|
61
|
+
case "topShelfWide":
|
|
61
62
|
return params?.appleTVImages?.topShelfWide;
|
|
62
|
-
case
|
|
63
|
+
case "topShelfWide2x":
|
|
63
64
|
return params?.appleTVImages?.topShelfWide2x;
|
|
64
65
|
default:
|
|
65
66
|
return undefined;
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
|
-
exports.appleTVImagePathForType = appleTVImagePathForType;
|
package/build/utils/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * from "./appleBrandAssets";
|
|
2
|
+
export * from "./config";
|
|
3
|
+
export * from "./log";
|
package/build/utils/log.d.ts
CHANGED
package/build/utils/log.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.verboseLog =
|
|
4
|
-
const debug = require(
|
|
3
|
+
exports.verboseLog = verboseLog;
|
|
4
|
+
const debug = require("debug")("expo:react-native-tvos:config-tv");
|
|
5
5
|
function verboseLog(message, options) {
|
|
6
6
|
const tokens = [message];
|
|
7
7
|
options?.property && tokens.unshift(options?.property);
|
|
8
8
|
options?.platform && tokens.unshift(options?.platform);
|
|
9
|
-
debug(tokens.join(
|
|
9
|
+
debug(tokens.join(": "));
|
|
10
10
|
}
|
|
11
|
-
exports.verboseLog = verboseLog;
|
package/build/withTV.d.ts
CHANGED
package/build/withTV.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const config_plugins_1 = require("expo/config-plugins");
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const withTVAndroidBannerImage_1 = require("./withTVAndroidBannerImage");
|
|
6
|
+
const withTVAndroidIconImage_1 = require("./withTVAndroidIconImage");
|
|
4
7
|
const withTVAndroidManifest_1 = require("./withTVAndroidManifest");
|
|
8
|
+
const withTVAndroidRemoveFlipper_1 = require("./withTVAndroidRemoveFlipper");
|
|
5
9
|
const withTVAppleIconImages_1 = require("./withTVAppleIconImages");
|
|
6
10
|
const withTVInfoPlist_1 = require("./withTVInfoPlist");
|
|
7
11
|
const withTVPodfile_1 = require("./withTVPodfile");
|
|
8
12
|
const withTVSplashScreen_1 = require("./withTVSplashScreen");
|
|
9
13
|
const withTVXcodeProject_1 = require("./withTVXcodeProject");
|
|
10
|
-
const withTVAndroidRemoveFlipper_1 = require("./withTVAndroidRemoveFlipper");
|
|
11
|
-
const withTVAndroidBannerImage_1 = require("./withTVAndroidBannerImage");
|
|
12
|
-
const withTVAndroidIconImage_1 = require("./withTVAndroidIconImage");
|
|
13
|
-
const utils_1 = require("./utils");
|
|
14
14
|
const withTVNoEffect = (config, params = {}) => {
|
|
15
15
|
(0, utils_1.verboseLog)(`${utils_1.packageNameAndVersion}: isTV == false, TV-specific modifications will not be made.`, {});
|
|
16
16
|
return config;
|
|
@@ -34,5 +34,5 @@ const withTVPlugin = (config, params = {}) => {
|
|
|
34
34
|
config = (0, withTVAndroidManifest_1.withTVAndroidManifest)(config, params);
|
|
35
35
|
return config;
|
|
36
36
|
};
|
|
37
|
-
const pkg = require(
|
|
37
|
+
const pkg = require("../package.json");
|
|
38
38
|
exports.default = (0, config_plugins_1.createRunOncePlugin)(withTVPlugin, pkg.name, pkg.version);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigPlugin } from
|
|
2
|
-
import { ConfigData } from
|
|
1
|
+
import { ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
3
3
|
/** Copies TV banner image to the Android resources drawable folders. If image does not exist, throw an exception. */
|
|
4
4
|
export declare const withTVAndroidBannerImage: ConfigPlugin<ConfigData>;
|
|
@@ -9,18 +9,18 @@ const fs_1 = require("fs");
|
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const utils_1 = require("./utils");
|
|
11
11
|
const drawableDirectoryNames = [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
"drawable",
|
|
13
|
+
"drawable-hdpi",
|
|
14
|
+
"drawable-mdpi",
|
|
15
|
+
"drawable-xhdpi",
|
|
16
|
+
"drawable-xxhdpi",
|
|
17
|
+
"drawable-xxxhdpi",
|
|
18
18
|
];
|
|
19
19
|
/** Copies TV banner image to the Android resources drawable folders. If image does not exist, throw an exception. */
|
|
20
20
|
const withTVAndroidBannerImage = (c, params = {}) => {
|
|
21
21
|
const androidTVBannerPath = (0, utils_1.androidTVBanner)(params);
|
|
22
22
|
return (0, config_plugins_1.withDangerousMod)(c, [
|
|
23
|
-
|
|
23
|
+
"android",
|
|
24
24
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
25
25
|
async (config) => {
|
|
26
26
|
if (!androidTVBannerPath) {
|
|
@@ -28,15 +28,15 @@ const withTVAndroidBannerImage = (c, params = {}) => {
|
|
|
28
28
|
}
|
|
29
29
|
(0, utils_1.verboseLog)(`adding TV banner image ${androidTVBannerPath} to Android resources`, {
|
|
30
30
|
params,
|
|
31
|
-
platform:
|
|
32
|
-
property:
|
|
31
|
+
platform: "android",
|
|
32
|
+
property: "manifest",
|
|
33
33
|
});
|
|
34
34
|
for (const drawableDirectoryName of drawableDirectoryNames) {
|
|
35
|
-
const drawableDirectoryPath = path_1.default.join(config.modRequest.platformProjectRoot,
|
|
35
|
+
const drawableDirectoryPath = path_1.default.join(config.modRequest.platformProjectRoot, "app", "src", "main", "res", drawableDirectoryName);
|
|
36
36
|
if (!(0, fs_1.existsSync)(drawableDirectoryPath)) {
|
|
37
37
|
await fs_1.promises.mkdir(drawableDirectoryPath);
|
|
38
38
|
}
|
|
39
|
-
await fs_1.promises.copyFile(androidTVBannerPath, path_1.default.join(drawableDirectoryPath,
|
|
39
|
+
await fs_1.promises.copyFile(androidTVBannerPath, path_1.default.join(drawableDirectoryPath, "tv_banner.png"));
|
|
40
40
|
}
|
|
41
41
|
return config;
|
|
42
42
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigPlugin } from
|
|
2
|
-
import { ConfigData } from
|
|
1
|
+
import { ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
3
3
|
/** Copies TV Icon image to the Android resources drawable folders. If image does not exist, throw an exception. */
|
|
4
4
|
export declare const withTVAndroidIconImage: ConfigPlugin<ConfigData>;
|
|
@@ -9,19 +9,19 @@ const fs_1 = require("fs");
|
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const utils_1 = require("./utils");
|
|
11
11
|
const drawableDirectoryNames = [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
"drawable",
|
|
13
|
+
"mipmap",
|
|
14
|
+
"mipmap-hdpi",
|
|
15
|
+
"mipmap-mdpi",
|
|
16
|
+
"mipmap-xhdpi",
|
|
17
|
+
"mipmap-xxhdpi",
|
|
18
|
+
"mipmap-xxxhdpi",
|
|
19
19
|
];
|
|
20
20
|
/** Copies TV Icon image to the Android resources drawable folders. If image does not exist, throw an exception. */
|
|
21
21
|
const withTVAndroidIconImage = (c, params = {}) => {
|
|
22
22
|
const androidTVIconPath = (0, utils_1.androidTVIcon)(params);
|
|
23
23
|
return (0, config_plugins_1.withDangerousMod)(c, [
|
|
24
|
-
|
|
24
|
+
"android",
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
26
26
|
async (config) => {
|
|
27
27
|
if (!androidTVIconPath) {
|
|
@@ -29,20 +29,20 @@ const withTVAndroidIconImage = (c, params = {}) => {
|
|
|
29
29
|
}
|
|
30
30
|
(0, utils_1.verboseLog)(`adding TV Icon image ${androidTVIconPath} to Android resources`, {
|
|
31
31
|
params,
|
|
32
|
-
platform:
|
|
33
|
-
property:
|
|
32
|
+
platform: "android",
|
|
33
|
+
property: "manifest",
|
|
34
34
|
});
|
|
35
35
|
for (const drawableDirectoryName of drawableDirectoryNames) {
|
|
36
|
-
const drawableDirectoryPath = path_1.default.join(config.modRequest.platformProjectRoot,
|
|
36
|
+
const drawableDirectoryPath = path_1.default.join(config.modRequest.platformProjectRoot, "app", "src", "main", "res", drawableDirectoryName);
|
|
37
37
|
if (!(0, fs_1.existsSync)(drawableDirectoryPath)) {
|
|
38
38
|
await fs_1.promises.mkdir(drawableDirectoryPath);
|
|
39
39
|
}
|
|
40
40
|
if (drawableDirectoryName === "drawable") {
|
|
41
|
-
await fs_1.promises.copyFile(androidTVIconPath, path_1.default.join(drawableDirectoryPath,
|
|
41
|
+
await fs_1.promises.copyFile(androidTVIconPath, path_1.default.join(drawableDirectoryPath, "tv_icon.png"));
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
|
-
await fs_1.promises.copyFile(androidTVIconPath, path_1.default.join(drawableDirectoryPath,
|
|
45
|
-
await fs_1.promises.copyFile(androidTVIconPath, path_1.default.join(drawableDirectoryPath,
|
|
44
|
+
await fs_1.promises.copyFile(androidTVIconPath, path_1.default.join(drawableDirectoryPath, "ic_launcher.png"));
|
|
45
|
+
await fs_1.promises.copyFile(androidTVIconPath, path_1.default.join(drawableDirectoryPath, "ic_launcher_round.png"));
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
return config;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ExpoConfig } from
|
|
2
|
-
import { AndroidConfig, ConfigPlugin } from
|
|
3
|
-
import { ConfigData } from
|
|
1
|
+
import { ExpoConfig } from "expo/config";
|
|
2
|
+
import { AndroidConfig, ConfigPlugin } from "expo/config-plugins";
|
|
3
|
+
import { ConfigData } from "./types";
|
|
4
4
|
export declare const withTVAndroidManifest: ConfigPlugin<ConfigData>;
|
|
5
|
-
export declare function setLeanBackLauncherIntent(_config: Pick<ExpoConfig,
|
|
6
|
-
export declare function removePortraitOrientation(_config: Pick<ExpoConfig,
|
|
7
|
-
export declare function setTVBanner(_config: Pick<ExpoConfig,
|
|
8
|
-
export declare function setTVIcon(_config: Pick<ExpoConfig,
|
|
9
|
-
export declare function addTouchscreenHardwareFeatureToManifest(_config: Pick<ExpoConfig,
|
|
5
|
+
export declare function setLeanBackLauncherIntent(_config: Pick<ExpoConfig, "android">, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData): AndroidConfig.Manifest.AndroidManifest;
|
|
6
|
+
export declare function removePortraitOrientation(_config: Pick<ExpoConfig, "android">, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData): AndroidConfig.Manifest.AndroidManifest;
|
|
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 setTVIcon(_config: Pick<ExpoConfig, "android">, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData, androidTVIconPath: string | undefined): AndroidConfig.Manifest.AndroidManifest;
|
|
9
|
+
export declare function addTouchscreenHardwareFeatureToManifest(_config: Pick<ExpoConfig, "android">, androidManifest: AndroidConfig.Manifest.AndroidManifest, params: ConfigData): AndroidConfig.Manifest.AndroidManifest;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.withTVAndroidManifest = void 0;
|
|
4
|
+
exports.setLeanBackLauncherIntent = setLeanBackLauncherIntent;
|
|
5
|
+
exports.removePortraitOrientation = removePortraitOrientation;
|
|
6
|
+
exports.setTVBanner = setTVBanner;
|
|
7
|
+
exports.setTVIcon = setTVIcon;
|
|
8
|
+
exports.addTouchscreenHardwareFeatureToManifest = addTouchscreenHardwareFeatureToManifest;
|
|
4
9
|
const config_plugins_1 = require("expo/config-plugins");
|
|
5
10
|
const utils_1 = require("./utils");
|
|
6
11
|
const { getMainActivity, getMainApplication } = config_plugins_1.AndroidConfig.Manifest;
|
|
@@ -21,22 +26,22 @@ const withTVAndroidManifest = (config, params = {}) => {
|
|
|
21
26
|
});
|
|
22
27
|
};
|
|
23
28
|
exports.withTVAndroidManifest = withTVAndroidManifest;
|
|
24
|
-
const LEANBACK_LAUNCHER_CATEGORY =
|
|
29
|
+
const LEANBACK_LAUNCHER_CATEGORY = "android.intent.category.LEANBACK_LAUNCHER";
|
|
25
30
|
function getMainLaunchIntent(androidManifest) {
|
|
26
31
|
const mainActivity = getMainActivity(androidManifest);
|
|
27
|
-
const intentFilters = mainActivity?.[
|
|
32
|
+
const intentFilters = mainActivity?.["intent-filter"];
|
|
28
33
|
const mainLaunchIntents = (intentFilters ?? []).filter((i) => {
|
|
29
34
|
const action = i.action ?? [];
|
|
30
35
|
if (action.length === 0) {
|
|
31
36
|
return false;
|
|
32
37
|
}
|
|
33
|
-
return action[0]?.$[
|
|
38
|
+
return action[0]?.$["android:name"] === "android.intent.action.MAIN";
|
|
34
39
|
});
|
|
35
40
|
return mainLaunchIntents.length ? mainLaunchIntents[0] : undefined;
|
|
36
41
|
}
|
|
37
42
|
function leanbackLauncherCategoryExistsInMainLaunchIntent(mainLaunchIntent) {
|
|
38
43
|
const mainLaunchCategories = mainLaunchIntent.category ?? [];
|
|
39
|
-
const mainLaunchIntentCategoriesWithLeanbackLauncher = mainLaunchCategories.filter((c) => c.$[
|
|
44
|
+
const mainLaunchIntentCategoriesWithLeanbackLauncher = mainLaunchCategories.filter((c) => c.$["android:name"] === LEANBACK_LAUNCHER_CATEGORY);
|
|
40
45
|
return mainLaunchIntentCategoriesWithLeanbackLauncher.length > 0;
|
|
41
46
|
}
|
|
42
47
|
function setLeanBackLauncherIntent(_config, androidManifest, params) {
|
|
@@ -46,38 +51,36 @@ function setLeanBackLauncherIntent(_config, androidManifest, params) {
|
|
|
46
51
|
}
|
|
47
52
|
if (!leanbackLauncherCategoryExistsInMainLaunchIntent(mainLaunchIntent)) {
|
|
48
53
|
// Leanback needs to be added
|
|
49
|
-
(0, utils_1.verboseLog)(
|
|
54
|
+
(0, utils_1.verboseLog)("adding TV leanback launcher category to main intent in AndroidManifest.xml", {
|
|
50
55
|
params,
|
|
51
|
-
platform:
|
|
52
|
-
property:
|
|
56
|
+
platform: "android",
|
|
57
|
+
property: "manifest",
|
|
53
58
|
});
|
|
54
59
|
const mainLaunchCategories = mainLaunchIntent.category ?? [];
|
|
55
60
|
mainLaunchCategories.push({
|
|
56
61
|
$: {
|
|
57
|
-
|
|
62
|
+
"android:name": LEANBACK_LAUNCHER_CATEGORY,
|
|
58
63
|
},
|
|
59
64
|
});
|
|
60
65
|
mainLaunchIntent.category = mainLaunchCategories;
|
|
61
66
|
}
|
|
62
67
|
return androidManifest;
|
|
63
68
|
}
|
|
64
|
-
exports.setLeanBackLauncherIntent = setLeanBackLauncherIntent;
|
|
65
69
|
function removePortraitOrientation(_config, androidManifest, params) {
|
|
66
70
|
const mainActivity = getMainActivity(androidManifest);
|
|
67
71
|
if (mainActivity?.$) {
|
|
68
72
|
const metadata = mainActivity?.$ ?? {};
|
|
69
|
-
if (metadata[
|
|
70
|
-
(0, utils_1.verboseLog)(
|
|
73
|
+
if (metadata["android:screenOrientation"]) {
|
|
74
|
+
(0, utils_1.verboseLog)("removing screen orientation from AndroidManifest.xml", {
|
|
71
75
|
params,
|
|
72
|
-
platform:
|
|
73
|
-
property:
|
|
76
|
+
platform: "android",
|
|
77
|
+
property: "manifest",
|
|
74
78
|
});
|
|
75
|
-
delete metadata[
|
|
79
|
+
delete metadata["android:screenOrientation"];
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
return androidManifest;
|
|
79
83
|
}
|
|
80
|
-
exports.removePortraitOrientation = removePortraitOrientation;
|
|
81
84
|
function setTVBanner(_config, androidManifest, params, androidTVBannerPath) {
|
|
82
85
|
if (!androidTVBannerPath) {
|
|
83
86
|
return androidManifest;
|
|
@@ -85,16 +88,15 @@ function setTVBanner(_config, androidManifest, params, androidTVBannerPath) {
|
|
|
85
88
|
const mainApplication = getMainApplication(androidManifest);
|
|
86
89
|
if (mainApplication?.$) {
|
|
87
90
|
const metadata = mainApplication?.$ ?? {};
|
|
88
|
-
(0, utils_1.verboseLog)(
|
|
91
|
+
(0, utils_1.verboseLog)("adding TV banner to AndroidManifest.xml", {
|
|
89
92
|
params,
|
|
90
|
-
platform:
|
|
91
|
-
property:
|
|
93
|
+
platform: "android",
|
|
94
|
+
property: "manifest",
|
|
92
95
|
});
|
|
93
|
-
metadata[
|
|
96
|
+
metadata["android:banner"] = "@drawable/tv_banner";
|
|
94
97
|
}
|
|
95
98
|
return androidManifest;
|
|
96
99
|
}
|
|
97
|
-
exports.setTVBanner = setTVBanner;
|
|
98
100
|
function setTVIcon(_config, androidManifest, params, androidTVIconPath) {
|
|
99
101
|
if (!androidTVIconPath) {
|
|
100
102
|
return androidManifest;
|
|
@@ -102,49 +104,47 @@ function setTVIcon(_config, androidManifest, params, androidTVIconPath) {
|
|
|
102
104
|
const mainApplication = getMainApplication(androidManifest);
|
|
103
105
|
if (mainApplication?.$) {
|
|
104
106
|
const metadata = mainApplication?.$ ?? {};
|
|
105
|
-
(0, utils_1.verboseLog)(
|
|
107
|
+
(0, utils_1.verboseLog)("adding TV icon to AndroidManifest.xml", {
|
|
106
108
|
params,
|
|
107
|
-
platform:
|
|
108
|
-
property:
|
|
109
|
+
platform: "android",
|
|
110
|
+
property: "manifest",
|
|
109
111
|
});
|
|
110
|
-
metadata[
|
|
112
|
+
metadata["android:icon"] = "@drawable/tv_icon";
|
|
111
113
|
}
|
|
112
114
|
return androidManifest;
|
|
113
115
|
}
|
|
114
|
-
exports.setTVIcon = setTVIcon;
|
|
115
116
|
function addTouchscreenHardwareFeatureToManifest(_config, androidManifest, params) {
|
|
116
117
|
// Add `<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>` to the AndroidManifest.xml
|
|
117
|
-
if (!Array.isArray(androidManifest.manifest[
|
|
118
|
-
androidManifest.manifest[
|
|
118
|
+
if (!Array.isArray(androidManifest.manifest["uses-feature"])) {
|
|
119
|
+
androidManifest.manifest["uses-feature"] = [];
|
|
119
120
|
}
|
|
120
|
-
if (!androidManifest.manifest[
|
|
121
|
-
!androidManifest.manifest[
|
|
122
|
-
!androidManifest.manifest[
|
|
123
|
-
(0, utils_1.verboseLog)(
|
|
121
|
+
if (!androidManifest.manifest["uses-feature"].find((item) => item.$["android:name"] === "android.hardware.touchscreen") &&
|
|
122
|
+
!androidManifest.manifest["uses-feature"].find((item) => item.$["android:name"] === "android.hardware.faketouch") &&
|
|
123
|
+
!androidManifest.manifest["uses-feature"].find((item) => item.$["android:name"] === "android.software.leanback")) {
|
|
124
|
+
(0, utils_1.verboseLog)("adding TV touchscreen hardware feature tag to AndroidManifest.xml", {
|
|
124
125
|
params,
|
|
125
|
-
platform:
|
|
126
|
-
property:
|
|
126
|
+
platform: "android",
|
|
127
|
+
property: "manifest",
|
|
127
128
|
});
|
|
128
|
-
androidManifest.manifest[
|
|
129
|
+
androidManifest.manifest["uses-feature"]?.push({
|
|
129
130
|
$: {
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
"android:name": "android.hardware.touchscreen",
|
|
132
|
+
"android:required": "false",
|
|
132
133
|
},
|
|
133
134
|
});
|
|
134
|
-
androidManifest.manifest[
|
|
135
|
+
androidManifest.manifest["uses-feature"]?.push({
|
|
135
136
|
$: {
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
"android:name": "android.hardware.faketouch",
|
|
138
|
+
"android:required": "false",
|
|
138
139
|
},
|
|
139
140
|
});
|
|
140
141
|
// add android.software.leanback to false
|
|
141
|
-
androidManifest.manifest[
|
|
142
|
+
androidManifest.manifest["uses-feature"]?.push({
|
|
142
143
|
$: {
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
"android:name": "android.software.leanback",
|
|
145
|
+
"android:required": (0, utils_1.isAndroidTVRequired)(params) ? "true" : "false",
|
|
145
146
|
},
|
|
146
147
|
});
|
|
147
148
|
}
|
|
148
149
|
return androidManifest;
|
|
149
150
|
}
|
|
150
|
-
exports.addTouchscreenHardwareFeatureToManifest = addTouchscreenHardwareFeatureToManifest;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigPlugin } from
|
|
2
|
-
import { ConfigData } from
|
|
1
|
+
import { ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
3
3
|
/** Dangerously makes or reverts TV changes in the project Podfile. */
|
|
4
4
|
export declare const withTVAndroidRemoveFlipper: ConfigPlugin<ConfigData>;
|
|
@@ -13,30 +13,30 @@ const utils_1 = require("./utils");
|
|
|
13
13
|
const withTVAndroidRemoveFlipper = (c, params = {}) => {
|
|
14
14
|
const androidRemoveFlipper = (0, utils_1.shouldRemoveFlipperOnAndroid)(params);
|
|
15
15
|
return (0, config_plugins_1.withDangerousMod)(c, [
|
|
16
|
-
|
|
16
|
+
"android",
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
18
18
|
async (config) => {
|
|
19
19
|
if (androidRemoveFlipper) {
|
|
20
20
|
// Modify main application
|
|
21
21
|
const mainApplicationFile = mainApplicationFilePath(config.modRequest.platformProjectRoot);
|
|
22
|
-
(0, utils_1.verboseLog)(
|
|
22
|
+
(0, utils_1.verboseLog)("removing Flipper from MainApplication file", {
|
|
23
23
|
params,
|
|
24
|
-
platform:
|
|
25
|
-
property:
|
|
24
|
+
platform: "android",
|
|
25
|
+
property: "manifest",
|
|
26
26
|
});
|
|
27
|
-
const mainApplicationContents = await fs_1.promises.readFile(mainApplicationFile,
|
|
28
|
-
const mainApplicationModifiedContents = commentOutLinesWithString(mainApplicationContents,
|
|
29
|
-
await fs_1.promises.writeFile(mainApplicationFile, mainApplicationModifiedContents,
|
|
27
|
+
const mainApplicationContents = await fs_1.promises.readFile(mainApplicationFile, "utf8");
|
|
28
|
+
const mainApplicationModifiedContents = commentOutLinesWithString(mainApplicationContents, "Flipper");
|
|
29
|
+
await fs_1.promises.writeFile(mainApplicationFile, mainApplicationModifiedContents, "utf-8");
|
|
30
30
|
// Modify app/build.gradle
|
|
31
31
|
const buildGradleFile = appBuildGradleFilePath(config.modRequest.platformProjectRoot);
|
|
32
|
-
(0, utils_1.verboseLog)(
|
|
32
|
+
(0, utils_1.verboseLog)("removing Flipper from android/app/build.gradle", {
|
|
33
33
|
params,
|
|
34
|
-
platform:
|
|
35
|
-
property:
|
|
34
|
+
platform: "android",
|
|
35
|
+
property: "manifest",
|
|
36
36
|
});
|
|
37
|
-
const buildGradleContents = await fs_1.promises.readFile(buildGradleFile,
|
|
38
|
-
const buildGradleModifiedContents = commentOutLinesWithString(buildGradleContents,
|
|
39
|
-
await fs_1.promises.writeFile(buildGradleFile, buildGradleModifiedContents,
|
|
37
|
+
const buildGradleContents = await fs_1.promises.readFile(buildGradleFile, "utf-8");
|
|
38
|
+
const buildGradleModifiedContents = commentOutLinesWithString(buildGradleContents, "flipper");
|
|
39
|
+
await fs_1.promises.writeFile(buildGradleFile, buildGradleModifiedContents, "utf-8");
|
|
40
40
|
}
|
|
41
41
|
return config;
|
|
42
42
|
},
|
|
@@ -49,18 +49,18 @@ const mainApplicationFilePath = (androidRoot) => {
|
|
|
49
49
|
return paths[0];
|
|
50
50
|
}
|
|
51
51
|
else {
|
|
52
|
-
throw new Error(
|
|
52
|
+
throw new Error("AndroidApplication path not found");
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
-
const appBuildGradleFilePath = (androidRoot) => path_1.default.resolve(androidRoot,
|
|
55
|
+
const appBuildGradleFilePath = (androidRoot) => path_1.default.resolve(androidRoot, "app", "build.gradle");
|
|
56
56
|
const commentOutLinesWithString = (contents, searchString) => {
|
|
57
57
|
return contents
|
|
58
|
-
.split(
|
|
58
|
+
.split("\n")
|
|
59
59
|
.map((line) => {
|
|
60
60
|
if (line.indexOf(searchString) !== -1) {
|
|
61
|
-
return line.replace(/^/,
|
|
61
|
+
return line.replace(/^/, "// ");
|
|
62
62
|
}
|
|
63
63
|
return line;
|
|
64
64
|
})
|
|
65
|
-
.join(
|
|
65
|
+
.join("\n");
|
|
66
66
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ConfigPlugin } from
|
|
2
|
-
import { ConfigData } from
|
|
1
|
+
import { ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* Constructs Apple TV brand assets from images passed into the `appleTVImages` plugin property
|
|
5
5
|
* If any images do not exist, an exception is thrown.
|
|
@@ -15,7 +15,7 @@ const { getProjectName } = config_plugins_1.IOSConfig.XcodeUtils;
|
|
|
15
15
|
*/
|
|
16
16
|
const withTVAppleIconImages = (c, params = {}) => {
|
|
17
17
|
return (0, config_plugins_1.withDangerousMod)(c, [
|
|
18
|
-
|
|
18
|
+
"ios",
|
|
19
19
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
20
20
|
async (config) => {
|
|
21
21
|
if (!params.appleTVImages) {
|
|
@@ -23,8 +23,8 @@ const withTVAppleIconImages = (c, params = {}) => {
|
|
|
23
23
|
}
|
|
24
24
|
(0, utils_1.verboseLog)(`adding Apple TV brand assets to Apple TV native code`, {
|
|
25
25
|
params,
|
|
26
|
-
platform:
|
|
27
|
-
property:
|
|
26
|
+
platform: "ios",
|
|
27
|
+
property: "xcodeproject",
|
|
28
28
|
});
|
|
29
29
|
utils_1.appleTVImageTypes.forEach((imageType) => {
|
|
30
30
|
const imagePath = (0, utils_1.appleTVImagePathForType)(params, imageType);
|
|
@@ -40,17 +40,17 @@ const withTVAppleIconImages = (c, params = {}) => {
|
|
|
40
40
|
const iconSmallSourceImages = [
|
|
41
41
|
{
|
|
42
42
|
path: params.appleTVImages.iconSmall,
|
|
43
|
-
scale:
|
|
43
|
+
scale: "1x",
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
path: params.appleTVImages.iconSmall2x,
|
|
47
|
-
scale:
|
|
47
|
+
scale: "2x",
|
|
48
48
|
},
|
|
49
49
|
];
|
|
50
50
|
const iconLargeSourceImages = [
|
|
51
51
|
{
|
|
52
52
|
path: params.appleTVImages.icon,
|
|
53
|
-
scale:
|
|
53
|
+
scale: "1x",
|
|
54
54
|
},
|
|
55
55
|
];
|
|
56
56
|
/*
|
|
@@ -63,39 +63,39 @@ const withTVAppleIconImages = (c, params = {}) => {
|
|
|
63
63
|
const topShelfSourceImages = [
|
|
64
64
|
{
|
|
65
65
|
path: params.appleTVImages.topShelf,
|
|
66
|
-
scale:
|
|
66
|
+
scale: "1x",
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
path: params.appleTVImages.topShelf2x,
|
|
70
|
-
scale:
|
|
70
|
+
scale: "2x",
|
|
71
71
|
},
|
|
72
72
|
];
|
|
73
73
|
const topShelfWideSourceImages = [
|
|
74
74
|
{
|
|
75
75
|
path: params.appleTVImages.topShelfWide,
|
|
76
|
-
scale:
|
|
76
|
+
scale: "1x",
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
path: params.appleTVImages.topShelfWide2x,
|
|
80
|
-
scale:
|
|
80
|
+
scale: "2x",
|
|
81
81
|
},
|
|
82
82
|
];
|
|
83
83
|
const sourceBrandAssets = {
|
|
84
|
-
name:
|
|
84
|
+
name: "TVAppIcon",
|
|
85
85
|
assets: [
|
|
86
86
|
{
|
|
87
|
-
role:
|
|
88
|
-
size:
|
|
87
|
+
role: "top-shelf-image",
|
|
88
|
+
size: "1920x720",
|
|
89
89
|
imageSet: {
|
|
90
|
-
name:
|
|
90
|
+
name: "Top Shelf Image",
|
|
91
91
|
sourceImages: topShelfSourceImages,
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
|
-
role:
|
|
96
|
-
size:
|
|
95
|
+
role: "top-shelf-image-wide",
|
|
96
|
+
size: "2320x720",
|
|
97
97
|
imageSet: {
|
|
98
|
-
name:
|
|
98
|
+
name: "Top Shelf Image Wide",
|
|
99
99
|
sourceImages: topShelfWideSourceImages,
|
|
100
100
|
},
|
|
101
101
|
},
|
|
@@ -123,42 +123,42 @@ const withTVAppleIconImages = (c, params = {}) => {
|
|
|
123
123
|
},
|
|
124
124
|
*/
|
|
125
125
|
{
|
|
126
|
-
role:
|
|
127
|
-
size:
|
|
126
|
+
role: "primary-app-icon",
|
|
127
|
+
size: "400x240",
|
|
128
128
|
imageStack: {
|
|
129
|
-
name:
|
|
129
|
+
name: "App Icon - Small",
|
|
130
130
|
sourceLayers: [
|
|
131
131
|
{
|
|
132
|
-
name:
|
|
132
|
+
name: "Front",
|
|
133
133
|
sourceImages: iconSmallSourceImages,
|
|
134
134
|
},
|
|
135
135
|
{
|
|
136
|
-
name:
|
|
136
|
+
name: "Middle",
|
|
137
137
|
sourceImages: iconSmallSourceImages,
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
|
-
name:
|
|
140
|
+
name: "Back",
|
|
141
141
|
sourceImages: iconSmallSourceImages,
|
|
142
142
|
},
|
|
143
143
|
],
|
|
144
144
|
},
|
|
145
145
|
},
|
|
146
146
|
{
|
|
147
|
-
role:
|
|
148
|
-
size:
|
|
147
|
+
role: "primary-app-icon",
|
|
148
|
+
size: "1280x768",
|
|
149
149
|
imageStack: {
|
|
150
|
-
name:
|
|
150
|
+
name: "App Icon - Large",
|
|
151
151
|
sourceLayers: [
|
|
152
152
|
{
|
|
153
|
-
name:
|
|
153
|
+
name: "Front",
|
|
154
154
|
sourceImages: iconLargeSourceImages,
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
|
-
name:
|
|
157
|
+
name: "Middle",
|
|
158
158
|
sourceImages: iconLargeSourceImages,
|
|
159
159
|
},
|
|
160
160
|
{
|
|
161
|
-
name:
|
|
161
|
+
name: "Back",
|
|
162
162
|
sourceImages: iconLargeSourceImages,
|
|
163
163
|
},
|
|
164
164
|
],
|
|
@@ -174,6 +174,6 @@ const withTVAppleIconImages = (c, params = {}) => {
|
|
|
174
174
|
exports.withTVAppleIconImages = withTVAppleIconImages;
|
|
175
175
|
function getIosNamedProjectPath(projectRoot) {
|
|
176
176
|
const projectName = getProjectName(projectRoot);
|
|
177
|
-
return path_1.default.join(projectRoot,
|
|
177
|
+
return path_1.default.join(projectRoot, "ios", projectName);
|
|
178
178
|
}
|
|
179
|
-
const IMAGES_PATH =
|
|
179
|
+
const IMAGES_PATH = "Images.xcassets";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { ConfigPlugin } from
|
|
2
|
-
import { ConfigData } from
|
|
1
|
+
import { ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
3
3
|
export declare const withTVInfoPlist: ConfigPlugin<ConfigData>;
|
package/build/withTVInfoPlist.js
CHANGED
|
@@ -4,13 +4,13 @@ exports.withTVInfoPlist = void 0;
|
|
|
4
4
|
const config_plugins_1 = require("expo/config-plugins");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
const withTVInfoPlist = (c, params = {}) => {
|
|
7
|
-
(0, utils_1.verboseLog)(
|
|
7
|
+
(0, utils_1.verboseLog)("Modifying UIRequiredDeviceCapabilities for TV", {
|
|
8
8
|
params,
|
|
9
|
-
platform:
|
|
10
|
-
property:
|
|
9
|
+
platform: "ios",
|
|
10
|
+
property: "Info.plist",
|
|
11
11
|
});
|
|
12
12
|
return (0, config_plugins_1.withInfoPlist)(c, (config) => {
|
|
13
|
-
config.modResults.UIRequiredDeviceCapabilities = [
|
|
13
|
+
config.modResults.UIRequiredDeviceCapabilities = ["arm64"];
|
|
14
14
|
return config;
|
|
15
15
|
});
|
|
16
16
|
};
|
package/build/withTVPodfile.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ConfigPlugin } from
|
|
2
|
-
import { ConfigData } from
|
|
1
|
+
import { ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
3
3
|
/** Dangerously makes or reverts TV changes in the project Podfile. */
|
|
4
4
|
export declare const withTVPodfile: ConfigPlugin<ConfigData>;
|
|
5
5
|
export declare function addTVPodfileModifications(src: string): string;
|
package/build/withTVPodfile.js
CHANGED
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.withTVPodfile = void 0;
|
|
7
|
+
exports.addTVPodfileModifications = addTVPodfileModifications;
|
|
7
8
|
const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
|
|
8
9
|
const config_plugins_1 = require("expo/config-plugins");
|
|
9
10
|
const fs_1 = require("fs");
|
|
@@ -12,26 +13,26 @@ const utils_1 = require("./utils");
|
|
|
12
13
|
/** Dangerously makes or reverts TV changes in the project Podfile. */
|
|
13
14
|
const withTVPodfile = (c, params = {}) => {
|
|
14
15
|
return (0, config_plugins_1.withDangerousMod)(c, [
|
|
15
|
-
|
|
16
|
+
"ios",
|
|
16
17
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
17
18
|
async (config) => {
|
|
18
|
-
const file = path_1.default.join(config.modRequest.platformProjectRoot,
|
|
19
|
-
const contents = await fs_1.promises.readFile(file,
|
|
19
|
+
const file = path_1.default.join(config.modRequest.platformProjectRoot, "Podfile");
|
|
20
|
+
const contents = await fs_1.promises.readFile(file, "utf8");
|
|
20
21
|
const modifiedContents = addTVPodfileModifications(contents);
|
|
21
|
-
(0, utils_1.verboseLog)(
|
|
22
|
+
(0, utils_1.verboseLog)("modifying Podfile for tvOS", {
|
|
22
23
|
params,
|
|
23
|
-
platform:
|
|
24
|
-
property:
|
|
24
|
+
platform: "ios",
|
|
25
|
+
property: "podfile",
|
|
25
26
|
});
|
|
26
|
-
await fs_1.promises.writeFile(file, modifiedContents,
|
|
27
|
+
await fs_1.promises.writeFile(file, modifiedContents, "utf-8");
|
|
27
28
|
return config;
|
|
28
29
|
},
|
|
29
30
|
]);
|
|
30
31
|
};
|
|
31
32
|
exports.withTVPodfile = withTVPodfile;
|
|
32
|
-
const MOD_TAG =
|
|
33
|
+
const MOD_TAG = "react-native-tvos-import";
|
|
33
34
|
function addTVPodfileModifications(src) {
|
|
34
|
-
if (src.indexOf(
|
|
35
|
+
if (src.indexOf("platform :tvos") !== -1) {
|
|
35
36
|
return src;
|
|
36
37
|
}
|
|
37
38
|
const newSrc = (0, generateCode_1.mergeContents)({
|
|
@@ -40,8 +41,7 @@ function addTVPodfileModifications(src) {
|
|
|
40
41
|
newSrc: "source 'https://github.com/react-native-tvos/react-native-tvos-podspecs.git'\nsource 'https://cdn.cocoapods.org/'\n",
|
|
41
42
|
anchor: /^/,
|
|
42
43
|
offset: 0,
|
|
43
|
-
comment:
|
|
44
|
+
comment: "#",
|
|
44
45
|
}).contents;
|
|
45
|
-
return newSrc.replace(
|
|
46
|
+
return newSrc.replace("platform :ios", "platform :tvos");
|
|
46
47
|
}
|
|
47
|
-
exports.addTVPodfileModifications = addTVPodfileModifications;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ConfigPlugin } from
|
|
2
|
-
import { ConfigData } from
|
|
1
|
+
import { ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
3
3
|
/** Dangerously makes changes needed for TV in SplashScreen.storyboard. */
|
|
4
4
|
export declare const withTVSplashScreen: ConfigPlugin<ConfigData>;
|
|
5
5
|
export declare function addTVSplashScreenModifications(src: string): string;
|
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.withTVSplashScreen = void 0;
|
|
7
|
+
exports.addTVSplashScreenModifications = addTVSplashScreenModifications;
|
|
7
8
|
const config_plugins_1 = require("expo/config-plugins");
|
|
8
9
|
const fs_1 = require("fs");
|
|
9
10
|
const path_1 = __importDefault(require("path"));
|
|
@@ -11,34 +12,34 @@ const utils_1 = require("./utils");
|
|
|
11
12
|
/** Dangerously makes changes needed for TV in SplashScreen.storyboard. */
|
|
12
13
|
const withTVSplashScreen = (config, params = {}) => {
|
|
13
14
|
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
14
|
-
|
|
15
|
+
"ios",
|
|
15
16
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
16
17
|
async (config) => {
|
|
17
18
|
if (!config.modRequest.projectName) {
|
|
18
19
|
throw new Error(`The ${utils_1.packageNameAndVersion} plugin requires a configured project name.`);
|
|
19
20
|
}
|
|
20
|
-
const file = path_1.default.join(config.modRequest.platformProjectRoot, config.modRequest.projectName,
|
|
21
|
-
const contents = await fs_1.promises.readFile(file,
|
|
21
|
+
const file = path_1.default.join(config.modRequest.platformProjectRoot, config.modRequest.projectName, "SplashScreen.storyboard");
|
|
22
|
+
const contents = await fs_1.promises.readFile(file, "utf8");
|
|
22
23
|
const modifiedContents = addTVSplashScreenModifications(contents);
|
|
23
|
-
(0, utils_1.verboseLog)(
|
|
24
|
+
(0, utils_1.verboseLog)("modifying SplashScreen.storyboard for tvOS", {
|
|
24
25
|
params,
|
|
25
|
-
platform:
|
|
26
|
-
property:
|
|
26
|
+
platform: "ios",
|
|
27
|
+
property: "splashscreen",
|
|
27
28
|
});
|
|
28
|
-
await fs_1.promises.writeFile(file, modifiedContents,
|
|
29
|
+
await fs_1.promises.writeFile(file, modifiedContents, "utf-8");
|
|
29
30
|
return config;
|
|
30
31
|
},
|
|
31
32
|
]);
|
|
32
33
|
};
|
|
33
34
|
exports.withTVSplashScreen = withTVSplashScreen;
|
|
34
35
|
const splashScreenStringsForPhone = [
|
|
35
|
-
|
|
36
|
+
"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB",
|
|
36
37
|
'targetRuntime="iOS.CocoaTouch"',
|
|
37
38
|
'id="retina5_5"',
|
|
38
39
|
'<deployment identifier="iOS"/>',
|
|
39
40
|
];
|
|
40
41
|
const splashScreenStringsForTV = [
|
|
41
|
-
|
|
42
|
+
"com.apple.InterfaceBuilder.AppleTV.Storyboard",
|
|
42
43
|
'targetRuntime="AppleTV"',
|
|
43
44
|
'id="appleTV"',
|
|
44
45
|
'<deployment identifier="tvOS"/>',
|
|
@@ -46,7 +47,7 @@ const splashScreenStringsForTV = [
|
|
|
46
47
|
function modifySource(src, originalStrings, replacementStrings) {
|
|
47
48
|
let modifiedSource = src;
|
|
48
49
|
originalStrings.forEach((s, i) => {
|
|
49
|
-
const original = new RegExp(`${s}`,
|
|
50
|
+
const original = new RegExp(`${s}`, "g");
|
|
50
51
|
const replacement = replacementStrings[i];
|
|
51
52
|
modifiedSource = modifiedSource.replace(original, replacement);
|
|
52
53
|
});
|
|
@@ -55,4 +56,3 @@ function modifySource(src, originalStrings, replacementStrings) {
|
|
|
55
56
|
function addTVSplashScreenModifications(src) {
|
|
56
57
|
return modifySource(src, splashScreenStringsForPhone, splashScreenStringsForTV);
|
|
57
58
|
}
|
|
58
|
-
exports.addTVSplashScreenModifications = addTVSplashScreenModifications;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ConfigData } from './types';
|
|
1
|
+
import { ConfigPlugin, ExportedConfigWithProps, XcodeProject } from "expo/config-plugins";
|
|
2
|
+
import { ConfigData } from "./types";
|
|
4
3
|
export declare const withTVXcodeProject: ConfigPlugin<ConfigData>;
|
|
5
|
-
export declare function setXcodeProjectBuildSettings(
|
|
4
|
+
export declare function setXcodeProjectBuildSettings(_: ExportedConfigWithProps<XcodeProject>, { project, params, deploymentTarget, }: {
|
|
6
5
|
project: XcodeProject;
|
|
7
6
|
params: ConfigData;
|
|
8
7
|
deploymentTarget: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.withTVXcodeProject = void 0;
|
|
4
|
+
exports.setXcodeProjectBuildSettings = setXcodeProjectBuildSettings;
|
|
4
5
|
const config_plugins_1 = require("expo/config-plugins");
|
|
5
6
|
const utils_1 = require("./utils");
|
|
6
7
|
const withTVXcodeProject = (config, params) => {
|
|
@@ -15,34 +16,33 @@ const withTVXcodeProject = (config, params) => {
|
|
|
15
16
|
});
|
|
16
17
|
};
|
|
17
18
|
exports.withTVXcodeProject = withTVXcodeProject;
|
|
18
|
-
function setXcodeProjectBuildSettings(
|
|
19
|
+
function setXcodeProjectBuildSettings(_, { project, params, deploymentTarget, }) {
|
|
19
20
|
const configurations = project.pbxXCBuildConfigurationSection();
|
|
20
21
|
// @ts-ignore
|
|
21
22
|
for (const { buildSettings } of Object.values(configurations || {})) {
|
|
22
23
|
// Guessing that this is the best way to emulate Xcode.
|
|
23
24
|
// Using `project.addToBuildSettings` modifies too many targets.
|
|
24
25
|
if (buildSettings !== undefined) {
|
|
25
|
-
buildSettings.SDKROOT =
|
|
26
|
+
buildSettings.SDKROOT = "appletvos";
|
|
26
27
|
}
|
|
27
|
-
if (typeof buildSettings?.PRODUCT_NAME !==
|
|
28
|
+
if (typeof buildSettings?.PRODUCT_NAME !== "undefined") {
|
|
28
29
|
(0, utils_1.verboseLog)(`modifying target ${buildSettings?.PRODUCT_NAME} for tvOS`, {
|
|
29
30
|
params,
|
|
30
|
-
platform:
|
|
31
|
-
property:
|
|
31
|
+
platform: "ios",
|
|
32
|
+
property: "xcodeproject",
|
|
32
33
|
});
|
|
33
|
-
buildSettings.TARGETED_DEVICE_FAMILY =
|
|
34
|
+
buildSettings.TARGETED_DEVICE_FAMILY = "3";
|
|
34
35
|
buildSettings.TVOS_DEPLOYMENT_TARGET = deploymentTarget;
|
|
35
|
-
if (typeof buildSettings?.IOS_DEPLOYMENT_TARGET !==
|
|
36
|
+
if (typeof buildSettings?.IOS_DEPLOYMENT_TARGET !== "undefined") {
|
|
36
37
|
delete buildSettings?.IOS_DEPLOYMENT_TARGET;
|
|
37
38
|
}
|
|
38
39
|
if (params.appleTVImages) {
|
|
39
40
|
// set the app icon source
|
|
40
|
-
if (buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME ===
|
|
41
|
-
buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME =
|
|
41
|
+
if (buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME === "AppIcon") {
|
|
42
|
+
buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME = "TVAppIcon";
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
return project;
|
|
47
48
|
}
|
|
48
|
-
exports.setXcodeProjectBuildSettings = setXcodeProjectBuildSettings;
|
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.1.0",
|
|
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",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"react-native-tvos"
|
|
35
35
|
],
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"expo": "^
|
|
37
|
+
"expo": "^52"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/getenv": "^1.0.1",
|