@24i/bigscreen-sdk 1.0.12 → 1.0.13-alpha.2281
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 +1 -1
- package/package.json +9 -9
- package/packages/analytics/src/clients/GoogleAnalytics/GoogleAnalytics.ts +27 -18
- package/packages/analytics/src/clients/GoogleAnalytics/constants.ts +64 -9
- package/packages/analytics/src/clients/GoogleAnalytics/interface.ts +26 -14
- package/packages/analytics/src/clients/GoogleAnalytics/mapPayload.ts +31 -14
- package/packages/create-package/dist/createPackage.js +66 -0
- package/packages/create-package/dist/createPackage.js.map +1 -0
- package/packages/create-package/dist/index.js +5 -0
- package/packages/create-package/dist/index.js.map +1 -0
- package/packages/create-package/dist/questionnaire/questions.js +35 -0
- package/packages/create-package/dist/questionnaire/questions.js.map +1 -0
- package/packages/create-package/dist/settings/Settings.js +10 -0
- package/packages/create-package/dist/settings/Settings.js.map +1 -0
- package/packages/create-package/dist/types.js +3 -0
- package/packages/create-package/dist/types.js.map +1 -0
- package/packages/driver-androidtv/src/DeviceAndroidTV.ts +11 -0
- package/packages/driver-base/src/KeyMap/Key.ts +8 -1
- package/packages/driver-base/src/KeyMap/interface.ts +1 -0
- package/packages/driver-base/src/KeyMap/overrideValues.ts +2 -1
- package/packages/driver-webos/src/keymap.ts +1 -1
- package/packages/input/src/Input.tsx +7 -5
- package/packages/types-bigscreen-jsx/index.d.ts +7 -7
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ sidebar_label: README
|
|
|
8
8
|
# SmartApps BIGscreen SDK
|
|
9
9
|
|
|
10
10
|
[](https://travis-ci.com/24i/smartapps-bigscreen-sdk)
|
|
11
|
-
[](https://coveralls.io/github/24i/smartapps-bigscreen-sdk?branch=development)
|
|
12
12
|
|
|
13
13
|
* [GitHub](https://github.com/24i/smartapps-bigscreen-sdk)
|
|
14
14
|
* [Confluence](https://24imedia.atlassian.net/wiki/spaces/PRDNGBIGSCR/overview)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@24i/bigscreen-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13-alpha.2281",
|
|
4
4
|
"description": "SmartApps BIGscreen SDK monorepo",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"lintcheck:cached": "npm run eslint -- --cache && npm run stylelint -- --cache",
|
|
18
18
|
"typecheck": "tsc --noEmit",
|
|
19
19
|
"typecheck:cached": "npm run typecheck -- --incremental",
|
|
20
|
-
"test": "npm run jest -- --no-cache
|
|
21
|
-
"test:cached": "npm run jest
|
|
20
|
+
"test": "npm run jest -- --no-cache",
|
|
21
|
+
"test:cached": "npm run jest",
|
|
22
22
|
"coverage": "npm run jest -- --runInBand --coverage && coveralls < coverage/lcov.info",
|
|
23
23
|
"branchlint": "branchlint",
|
|
24
24
|
"generate-changelog": "smartapps-bigscreen-changelog-generator",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
},
|
|
38
38
|
"homepage": "https://github.com/24i/smartapps-bigscreen-sdk#readme",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@24i/appstage-shared-analytics": "1.0.
|
|
41
|
-
"@24i/appstage-shared-events-manager": "1.0.
|
|
40
|
+
"@24i/appstage-shared-analytics": "1.0.1-alpha1",
|
|
41
|
+
"@24i/appstage-shared-events-manager": "1.0.7",
|
|
42
42
|
"@24i/appstage-shared-perf-utils": "1.0.5",
|
|
43
43
|
"@24i/player-base": "6.10.0",
|
|
44
|
-
"@24i/smartapps-datalayer": "3.0.
|
|
44
|
+
"@24i/smartapps-datalayer": "3.0.7-alpha.990",
|
|
45
45
|
"@sentry/browser": "7.35.0",
|
|
46
46
|
"@sentry/types": "7.35.0",
|
|
47
47
|
"@types/gtag.js": "^0.0.12",
|
|
@@ -55,15 +55,15 @@
|
|
|
55
55
|
"@24i/bigscreen-sdk": "file:.",
|
|
56
56
|
"@24i/eslint-config-smartapps-bigscreen-linters": "file:./libs/linters",
|
|
57
57
|
"@24i/smartapps-bigscreen-changelog-generator": "0.17.0",
|
|
58
|
-
"@babel/core": "^7.
|
|
58
|
+
"@babel/core": "^7.21.0",
|
|
59
59
|
"@babel/preset-env": "^7.20.2",
|
|
60
60
|
"@types/fs-extra": "^11.0.1",
|
|
61
61
|
"@types/inquirer": "^9.0.3",
|
|
62
62
|
"@types/jest": "^29.2.3",
|
|
63
63
|
"@types/minimist": "^1.2.2",
|
|
64
64
|
"@types/node": "^18.7.18",
|
|
65
|
-
"@types/react": "^18.0.
|
|
66
|
-
"babel-jest": "^29.4.
|
|
65
|
+
"@types/react": "^18.0.28",
|
|
66
|
+
"babel-jest": "^29.4.3",
|
|
67
67
|
"chalk": "^5.2.0",
|
|
68
68
|
"coveralls": "^3.1.1",
|
|
69
69
|
"cross-env": "^7.0.3",
|
|
@@ -34,15 +34,20 @@ export class GoogleAnalytics implements AnalyticsClient {
|
|
|
34
34
|
cid: '',
|
|
35
35
|
sid: 0,
|
|
36
36
|
uamb: 0,
|
|
37
|
-
uap: '',
|
|
38
|
-
uapv: '',
|
|
39
|
-
uam: '',
|
|
40
37
|
seg: 0,
|
|
41
38
|
sct: 0,
|
|
42
39
|
_p: generateUuid(),
|
|
40
|
+
'up.device_manufacturer': '',
|
|
41
|
+
'up.device_platform': '',
|
|
42
|
+
'up.device_platform_version': '',
|
|
43
|
+
'up.app_version': '',
|
|
43
44
|
};
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
manufacturer = '';
|
|
47
|
+
|
|
48
|
+
platform = '';
|
|
49
|
+
|
|
50
|
+
platformVersion = '';
|
|
46
51
|
|
|
47
52
|
lastOnEvent: number | undefined = undefined;
|
|
48
53
|
|
|
@@ -58,7 +63,7 @@ export class GoogleAnalytics implements AnalyticsClient {
|
|
|
58
63
|
|
|
59
64
|
firstVisit: boolean | undefined = undefined;
|
|
60
65
|
|
|
61
|
-
constructor(private id: string) {
|
|
66
|
+
constructor(private id: string, private appVersion: string = '') {
|
|
62
67
|
this.init();
|
|
63
68
|
}
|
|
64
69
|
|
|
@@ -73,16 +78,20 @@ export class GoogleAnalytics implements AnalyticsClient {
|
|
|
73
78
|
if (this.firstVisit) {
|
|
74
79
|
await Storage.setItem(GA_FIRST_VISIT, '0');
|
|
75
80
|
}
|
|
81
|
+
this.manufacturer = await device.getManufacturerName();
|
|
82
|
+
this.platform = await device.getPlatformName();
|
|
83
|
+
this.platformVersion = await device.getPlatformVersion();
|
|
76
84
|
await this.startSession();
|
|
77
|
-
params.uap = await device.getPlatformName();
|
|
78
|
-
params.uapv = await device.getPlatformVersion();
|
|
79
|
-
params.uam = await device.getModelName();
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
async startSession() {
|
|
83
88
|
const sessionNumber = parseInt(await Storage.getItem(GA_SESSION_COUNTER) ?? '0', 10) + 1;
|
|
84
89
|
this.constantUrlParams.sct = sessionNumber;
|
|
85
90
|
this.constantUrlParams.sid = generateSessionId();
|
|
91
|
+
this.constantUrlParams['up.device_manufacturer'] = this.manufacturer;
|
|
92
|
+
this.constantUrlParams['up.device_platform'] = this.platform;
|
|
93
|
+
this.constantUrlParams['up.device_platform_version'] = this.platformVersion;
|
|
94
|
+
this.constantUrlParams['up.app_version'] = this.appVersion;
|
|
86
95
|
await Storage.setItem(GA_SESSION_COUNTER, sessionNumber.toString());
|
|
87
96
|
this.isSessionActive = true;
|
|
88
97
|
this.setSessionTimeout();
|
|
@@ -113,11 +122,14 @@ export class GoogleAnalytics implements AnalyticsClient {
|
|
|
113
122
|
const engagementTime = this.lastOnEvent ? now - this.lastOnEvent : undefined;
|
|
114
123
|
this.lastOnEvent = now;
|
|
115
124
|
await Promise.all(events.map(async (event, index) => {
|
|
116
|
-
|
|
125
|
+
const sessionInfo = await this.getSessionInfo(
|
|
126
|
+
index === 0 ? engagementTime : undefined,
|
|
127
|
+
);
|
|
117
128
|
const gtagPayload = mapPayload(
|
|
118
|
-
event, triggerName,
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
event, triggerName, {
|
|
130
|
+
...payload,
|
|
131
|
+
...sessionInfo,
|
|
132
|
+
},
|
|
121
133
|
);
|
|
122
134
|
const urlParams = mapEventParamsToUrlParams(payload as SceneInfo);
|
|
123
135
|
this.send(event, gtagPayload, urlParams);
|
|
@@ -162,12 +174,6 @@ export class GoogleAnalytics implements AnalyticsClient {
|
|
|
162
174
|
|
|
163
175
|
private sendQueueWithDelay = debounce(this.sendQueue, SEND_DEBOUNCE_MS);
|
|
164
176
|
|
|
165
|
-
private shouldContinueWithA24iOperational() {
|
|
166
|
-
const { a24iOperational } = this;
|
|
167
|
-
if (!a24iOperational) this.a24iOperational = true;
|
|
168
|
-
return !a24iOperational;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
177
|
private async getSessionInfo(engagementTime: number | undefined): Promise<SessionInfo> {
|
|
172
178
|
const sessionStarted = !this.sessionStartSent;
|
|
173
179
|
this.sessionStartSent = true;
|
|
@@ -176,6 +182,9 @@ export class GoogleAnalytics implements AnalyticsClient {
|
|
|
176
182
|
const { firstVisit } = this;
|
|
177
183
|
this.firstVisit = false;
|
|
178
184
|
return {
|
|
185
|
+
appVersion: this.appVersion,
|
|
186
|
+
manufacturer: this.manufacturer,
|
|
187
|
+
platform: this.platform,
|
|
179
188
|
sessionStarted,
|
|
180
189
|
engagementTime,
|
|
181
190
|
firstEvent,
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { GAEventsNames } from './interface';
|
|
2
2
|
|
|
3
|
+
const stringParameter = 'ep';
|
|
4
|
+
const numericParameter = 'epn';
|
|
5
|
+
|
|
3
6
|
export const GOOGLE_ANALYTICS_TRIGGERS = [
|
|
7
|
+
'scene_view',
|
|
4
8
|
'app_close',
|
|
9
|
+
// player triggers
|
|
5
10
|
'playback_10',
|
|
6
11
|
'playback_25',
|
|
7
12
|
'playback_50',
|
|
@@ -12,42 +17,92 @@ export const GOOGLE_ANALYTICS_TRIGGERS = [
|
|
|
12
17
|
'playback_stop',
|
|
13
18
|
'player_close',
|
|
14
19
|
'player_open',
|
|
15
|
-
'
|
|
20
|
+
'heartbeat_5',
|
|
21
|
+
// scroll triggers
|
|
16
22
|
'scroll_25',
|
|
17
23
|
'scroll_50',
|
|
18
24
|
'scroll_75',
|
|
19
25
|
'scroll_90',
|
|
26
|
+
// additional triggers
|
|
27
|
+
'app_error',
|
|
28
|
+
'toggle_favorite',
|
|
29
|
+
'search',
|
|
30
|
+
'rate_content',
|
|
31
|
+
// ads triggers
|
|
32
|
+
'ad_loaded',
|
|
33
|
+
'ad_skipped',
|
|
34
|
+
// user triggers
|
|
35
|
+
'login',
|
|
36
|
+
'logout',
|
|
37
|
+
'sign_up',
|
|
38
|
+
// purchases
|
|
39
|
+
'purchase_cancel',
|
|
40
|
+
'purchase_complete',
|
|
41
|
+
'purchase_start',
|
|
42
|
+
|
|
20
43
|
] as const;
|
|
21
44
|
|
|
22
45
|
export const TRIGGER_NAME_TO_GA_EVENTS: Record<
|
|
23
46
|
typeof GOOGLE_ANALYTICS_TRIGGERS[number], GAEventsNames[]
|
|
24
47
|
> = {
|
|
25
48
|
// App
|
|
26
|
-
app_close: ['
|
|
49
|
+
app_close: ['close_player_session', 'video_progress'],
|
|
27
50
|
|
|
28
51
|
// Playback
|
|
52
|
+
heartbeat_5: ['video_progress'],
|
|
29
53
|
playback_10: ['video_progress'],
|
|
30
54
|
playback_25: ['video_progress'],
|
|
31
55
|
playback_50: ['video_progress'],
|
|
32
56
|
playback_75: ['video_progress'],
|
|
33
|
-
playback_90: ['
|
|
57
|
+
playback_90: ['video_complete'],
|
|
34
58
|
playback_pause: ['video_progress'],
|
|
35
59
|
playback_start: ['video_start'],
|
|
36
60
|
playback_stop: ['video_progress'],
|
|
37
61
|
|
|
38
62
|
// Player
|
|
39
|
-
player_close: ['
|
|
40
|
-
player_open: ['
|
|
63
|
+
player_close: ['close_player_session', 'video_progress'],
|
|
64
|
+
player_open: ['open_player_session'],
|
|
41
65
|
|
|
42
66
|
// Scenes
|
|
43
|
-
scene_view: [
|
|
44
|
-
'page_view',
|
|
45
|
-
'a24i_operational',
|
|
46
|
-
],
|
|
67
|
+
scene_view: ['page_view'],
|
|
47
68
|
|
|
48
69
|
// Scrolling in scene
|
|
49
70
|
scroll_25: ['scroll'],
|
|
50
71
|
scroll_50: ['scroll'],
|
|
51
72
|
scroll_75: ['scroll'],
|
|
52
73
|
scroll_90: ['scroll'],
|
|
74
|
+
|
|
75
|
+
// purchases
|
|
76
|
+
purchase_cancel: [],
|
|
77
|
+
purchase_complete: [],
|
|
78
|
+
purchase_start: [],
|
|
79
|
+
|
|
80
|
+
// additional triggers
|
|
81
|
+
app_error: [],
|
|
82
|
+
toggle_favorite: [],
|
|
83
|
+
search: [],
|
|
84
|
+
rate_content: [],
|
|
85
|
+
|
|
86
|
+
// ads triggers
|
|
87
|
+
ad_loaded: [],
|
|
88
|
+
ad_skipped: [],
|
|
89
|
+
|
|
90
|
+
// user triggers
|
|
91
|
+
login: ['login'],
|
|
92
|
+
logout: [],
|
|
93
|
+
sign_up: [],
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const gtagPayloadParams: Record<string, string> = {
|
|
97
|
+
contentType: `${stringParameter}.content_type`,
|
|
98
|
+
episodeNumber: `${numericParameter}.episode_number`,
|
|
99
|
+
seasonNumber: `${numericParameter}.season_number`,
|
|
100
|
+
currentTime: `${numericParameter}.video_current_time`,
|
|
101
|
+
duration: `${numericParameter}.video_duration`,
|
|
102
|
+
percent: `${numericParameter}.video_current_percent`,
|
|
103
|
+
provider: `${stringParameter}.video_provider`,
|
|
104
|
+
title: `${stringParameter}.video_title`,
|
|
105
|
+
seriesTitle: `${stringParameter}.video_series_title`,
|
|
106
|
+
url: `${stringParameter}.video_url`,
|
|
107
|
+
assetId: `${stringParameter}.video_asset_id`,
|
|
53
108
|
};
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
export type GAEventsNames = (
|
|
2
|
-
| '
|
|
3
|
-
| '
|
|
4
|
-
| '
|
|
5
|
-
| '
|
|
6
|
-
| '
|
|
7
|
-
| '
|
|
8
|
-
| '
|
|
9
|
-
| '
|
|
2
|
+
| 'app_close' // When the playback is active at the time the app or website is closing.
|
|
3
|
+
| 'page_view' // Each time the page loads or the browser history state is changed
|
|
4
|
+
| 'scroll' // The first time a user reaches the bottom of each page
|
|
5
|
+
| 'video_progress' // When the video progresses past 10%, 25%, 50%, and 75% duration time
|
|
6
|
+
| 'video_start' // When the video starts playing
|
|
7
|
+
| 'video_complete' // When the video ends
|
|
8
|
+
| 'open_player_session' // When the user opens a player scene and the player is initiated
|
|
9
|
+
| 'close_player_session' // When the user exits the player scene with initiated player
|
|
10
|
+
| 'select_content' // When a user has selected content
|
|
11
|
+
| 'login' // When a user logs in
|
|
12
|
+
| 'sign_up' // When a user has signed up Allows you to see which methods of signup are popular
|
|
13
|
+
| 'search' // When a user searches your content
|
|
14
|
+
| 'purchase' // When a user completes a purchase
|
|
15
|
+
| 'share' // When a user has shared content
|
|
16
|
+
| 'user_engagement' // Periodically, while the app is in the foreground
|
|
10
17
|
);
|
|
11
18
|
|
|
12
19
|
export type QueuedEvent = {
|
|
@@ -16,6 +23,9 @@ export type QueuedEvent = {
|
|
|
16
23
|
};
|
|
17
24
|
|
|
18
25
|
export type SessionInfo = {
|
|
26
|
+
appVersion: string,
|
|
27
|
+
manufacturer: string,
|
|
28
|
+
platform: string,
|
|
19
29
|
engagementTime: number | undefined,
|
|
20
30
|
sessionStarted: boolean,
|
|
21
31
|
firstEvent: boolean,
|
|
@@ -29,18 +39,20 @@ export type ConstantUrlParams = {
|
|
|
29
39
|
sid: number,
|
|
30
40
|
/** 1 for mobile devices, 0 otherwise */
|
|
31
41
|
uamb: number,
|
|
32
|
-
/** Platform name */
|
|
33
|
-
uap: string,
|
|
34
|
-
/** Platform version */
|
|
35
|
-
uapv: string,
|
|
36
|
-
/** Device model name */
|
|
37
|
-
uam: string,
|
|
38
42
|
/** Session engagement 0 for first event of session, 1 otherwise */
|
|
39
43
|
seg: number,
|
|
40
44
|
/** Session count */
|
|
41
45
|
sct: number,
|
|
42
46
|
/** Random page hash */
|
|
43
47
|
_p: string,
|
|
48
|
+
/** Device manufacturer e.g. 'Samsung' */
|
|
49
|
+
'up.device_manufacturer': string,
|
|
50
|
+
/** Platform e.g. 'Tizen' */
|
|
51
|
+
'up.device_platform': string,
|
|
52
|
+
/** Platform version e.g. '5.0' */
|
|
53
|
+
'up.device_platform_version': string,
|
|
54
|
+
/** Version of application 'v1.0.0' */
|
|
55
|
+
'up.app_version': string,
|
|
44
56
|
};
|
|
45
57
|
|
|
46
58
|
export type EventUrlParams = {
|
|
@@ -1,29 +1,46 @@
|
|
|
1
|
-
import type { AnalyticsEventsNames } from '../../interface';
|
|
2
|
-
import type { EventUrlParams, GAEventsNames
|
|
1
|
+
import type { AnalyticsEventsNames, AnyPayload } from '../../interface';
|
|
2
|
+
import type { EventUrlParams, GAEventsNames } from './interface';
|
|
3
|
+
import { gtagPayloadParams } from './constants';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const map: Record<string, string> = {
|
|
6
|
+
language: 'ul',
|
|
7
|
+
resolution: 'sr',
|
|
8
|
+
sceneId: 'dl',
|
|
9
|
+
sceneName: 'dt',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const mapEventParamsToUrlParams = (eventParams: Record<string, any>)
|
|
13
|
+
: EventUrlParams => {
|
|
14
|
+
const urlParams = {};
|
|
15
|
+
Object.entries(eventParams).forEach(([key]) => {
|
|
16
|
+
if (map[key]) {
|
|
17
|
+
Object.assign(urlParams, {
|
|
18
|
+
[map[key]]: eventParams[key] || '',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
10
22
|
return urlParams as EventUrlParams;
|
|
11
23
|
};
|
|
12
24
|
|
|
13
25
|
export const mapPayload = (
|
|
14
26
|
eventName: GAEventsNames,
|
|
15
27
|
triggerName: AnalyticsEventsNames,
|
|
16
|
-
|
|
28
|
+
payload: AnyPayload,
|
|
17
29
|
) => {
|
|
18
30
|
const gtagPayload: Record<string, any> = {
|
|
19
31
|
'ep.event_trigger': triggerName,
|
|
20
|
-
_et:
|
|
21
|
-
_ee:
|
|
22
|
-
_fv:
|
|
23
|
-
_ss:
|
|
32
|
+
_et: payload.engagementTime ?? 0,
|
|
33
|
+
_ee: payload.firstEvent ? 1 : 0,
|
|
34
|
+
_fv: payload.firstVisit ? 1 : 0,
|
|
35
|
+
_ss: payload.sessionStarted ? 1 : 0,
|
|
24
36
|
};
|
|
25
37
|
if (eventName === 'scroll') {
|
|
26
|
-
gtagPayload['epn.
|
|
38
|
+
gtagPayload['epn.percent_scrolled'] = parseInt(triggerName.split('_')[1], 10);
|
|
27
39
|
}
|
|
40
|
+
Object.keys(payload).forEach((key: keyof typeof payload) => {
|
|
41
|
+
if (gtagPayloadParams[key] !== undefined) {
|
|
42
|
+
gtagPayload[gtagPayloadParams[key]] = payload[key];
|
|
43
|
+
}
|
|
44
|
+
});
|
|
28
45
|
return gtagPayload;
|
|
29
46
|
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.main = void 0;
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const fse = require("fs-extra");
|
|
8
|
+
const chalk = require("chalk");
|
|
9
|
+
const minimist = require("minimist");
|
|
10
|
+
const questions_1 = require("./questionnaire/questions");
|
|
11
|
+
const Settings_1 = require("./settings/Settings");
|
|
12
|
+
async function isDirectoryEmpty(dirPath) {
|
|
13
|
+
const files = await fs.promises.readdir(dirPath);
|
|
14
|
+
return !files.length;
|
|
15
|
+
}
|
|
16
|
+
async function copyTemplateFiles(templateDir, targetDir) {
|
|
17
|
+
return fse.copy(templateDir, targetDir);
|
|
18
|
+
}
|
|
19
|
+
function updatePackageJsonFile(filePath, options) {
|
|
20
|
+
let data = fs.readFileSync(filePath, 'utf8');
|
|
21
|
+
const keywords = options.keywords.map((word) => `"${word}"`).join(', ');
|
|
22
|
+
data = data.replace(/("name": ")(.*)(")/, `$1${options.name}$3`);
|
|
23
|
+
data = data.replace(/("version": ")(.*)(")/, `$1${options.version}$3`);
|
|
24
|
+
data = data.replace(/("description": ")(.*)(")/, `$1${options.description}$3`);
|
|
25
|
+
data = data.replace(/("keywords": \[)(.*)(\])/, `$1${keywords}$3`);
|
|
26
|
+
data = data.replace(/("author": ")(.*)(")/, `$1${options.author}$3`);
|
|
27
|
+
fs.writeFileSync(filePath, data);
|
|
28
|
+
}
|
|
29
|
+
function parseArguments(rawArgv) {
|
|
30
|
+
const argv = minimist(rawArgv.slice(2));
|
|
31
|
+
const dirName = argv._[0];
|
|
32
|
+
if (!dirName) {
|
|
33
|
+
console.error('Error: Missing package name');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
dirName,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async function main() {
|
|
41
|
+
const { dirName: destDirName } = parseArguments(process.argv);
|
|
42
|
+
const destDir = path.join(process.cwd(), 'packages/', destDirName);
|
|
43
|
+
if (fs.existsSync(destDir)) {
|
|
44
|
+
console.error(`Error: Target directory "${destDir}" already exists`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
48
|
+
const isDirEmpty = await isDirectoryEmpty(destDir);
|
|
49
|
+
if (!isDirEmpty) {
|
|
50
|
+
console.error(`Error: Target directory "${destDir}" is not empty.`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const settings = Object.assign({}, Settings_1.Settings);
|
|
54
|
+
settings.name = `${Settings_1.Settings.name}${destDirName}`.toLowerCase();
|
|
55
|
+
const details = await (0, questions_1.promptPackageDetails)(settings);
|
|
56
|
+
const templateDir = path.join(__dirname, '..', 'templates/typescript');
|
|
57
|
+
await copyTemplateFiles(templateDir, destDir);
|
|
58
|
+
const packageJsonFile = path.join(destDir, 'package.json');
|
|
59
|
+
updatePackageJsonFile(packageJsonFile, details);
|
|
60
|
+
const docsSymlinkTarget = path.join('../../../packages/', destDirName, '/README.md');
|
|
61
|
+
const docsSymlinkPath = path.join(process.cwd(), 'docs/packages/', destDirName, '/README.md');
|
|
62
|
+
await fse.ensureSymlink(docsSymlinkTarget, docsSymlinkPath);
|
|
63
|
+
console.log(`${chalk.green('Success')}, package has been initialized!`);
|
|
64
|
+
}
|
|
65
|
+
exports.main = main;
|
|
66
|
+
//# sourceMappingURL=createPackage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createPackage.js","sourceRoot":"","sources":["../src/createPackage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,mDAAuC;AAEvC,IAAA,oBAAI,GAAE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptPackageDetails = void 0;
|
|
4
|
+
const inquirer = require("inquirer");
|
|
5
|
+
async function promptPackageDetails(defaultValues) {
|
|
6
|
+
return inquirer.prompt([
|
|
7
|
+
{
|
|
8
|
+
type: 'input',
|
|
9
|
+
name: 'name',
|
|
10
|
+
message: 'Package name:',
|
|
11
|
+
default: defaultValues.name,
|
|
12
|
+
}, {
|
|
13
|
+
type: 'input',
|
|
14
|
+
name: 'version',
|
|
15
|
+
message: 'Version:',
|
|
16
|
+
default: defaultValues.version,
|
|
17
|
+
}, {
|
|
18
|
+
type: 'input',
|
|
19
|
+
name: 'description',
|
|
20
|
+
message: 'Description:',
|
|
21
|
+
}, {
|
|
22
|
+
type: 'input',
|
|
23
|
+
name: 'keywords',
|
|
24
|
+
message: 'Keywords:',
|
|
25
|
+
filter: (ans) => ans.split(/[\s,]+/),
|
|
26
|
+
}, {
|
|
27
|
+
type: 'input',
|
|
28
|
+
name: 'author',
|
|
29
|
+
message: 'Author:',
|
|
30
|
+
default: defaultValues.author,
|
|
31
|
+
},
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
exports.promptPackageDetails = promptPackageDetails;
|
|
35
|
+
//# sourceMappingURL=questions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.js","sourceRoot":"","sources":["../../src/questionnaire/questions.ts"],"names":[],"mappings":";;;AAAA,qCAAqC;AAWrC,KAAK,UAAU,oBAAoB,CAAC,aAA4C;IAC5E,OAAO,QAAQ,CAAC,MAAM,CAAC;QACnB;YACI,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,eAAe;YACxB,OAAO,EAAE,aAAa,CAAC,IAAI;SAC9B,EAAE;YACC,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,UAAU;YACnB,OAAO,EAAE,aAAa,CAAC,OAAO;SACjC,EAAE;YACC,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,cAAc;SAC1B,EAAE;YACC,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;SACvC,EAAE;YACC,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE,aAAa,CAAC,MAAM;SAChC;KACJ,CAAC,CAAC;AACP,CAAC;AAEQ,oDAAoB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Settings = void 0;
|
|
4
|
+
const Settings = {
|
|
5
|
+
name: '@24i/smartapps-bigscreen-',
|
|
6
|
+
version: '0.0.1',
|
|
7
|
+
author: '24i',
|
|
8
|
+
};
|
|
9
|
+
exports.Settings = Settings;
|
|
10
|
+
//# sourceMappingURL=Settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Settings.js","sourceRoot":"","sources":["../../src/settings/Settings.ts"],"names":[],"mappings":";;;AAAA,MAAM,QAAQ,GAAG;IACb,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,KAAK;CAChB,CAAC;AAEO,4BAAQ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -52,6 +52,7 @@ export class DeviceAndroidTV extends DeviceBase {
|
|
|
52
52
|
* on the active (focused) element in the DOM tree.
|
|
53
53
|
* @param event keyboard event
|
|
54
54
|
*/
|
|
55
|
+
// eslint-disable-next-line complexity
|
|
55
56
|
relaunchKeyEvent = (event: CustomKeyboardEvent) => {
|
|
56
57
|
if (event.bigscreenSdkRelaunched) { // prevent to relaunch event in loop
|
|
57
58
|
return;
|
|
@@ -60,6 +61,16 @@ export class DeviceAndroidTV extends DeviceBase {
|
|
|
60
61
|
const { key } = event;
|
|
61
62
|
let { keyCode } = event;
|
|
62
63
|
|
|
64
|
+
// KeyCodes collisions for some key sent from Android wrapper or JavaScript (webView)
|
|
65
|
+
if (
|
|
66
|
+
key === 'u' // keyCode 85, same like PLAYPAUSE
|
|
67
|
+
|| key === 'v' // keyCode 86, same like STOP
|
|
68
|
+
|| key === 'y' // keyCode 89, same like REW
|
|
69
|
+
|| key === 'z' // keyCode 90, same like FF
|
|
70
|
+
) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
63
74
|
/**
|
|
64
75
|
* Remap KeyCode by its key value.
|
|
65
76
|
* On Android all colors keys and some others coming with "0" keyCode.
|
|
@@ -12,21 +12,25 @@ export class Key {
|
|
|
12
12
|
|
|
13
13
|
alternativeKeyCodes: number[];
|
|
14
14
|
|
|
15
|
+
key: string;
|
|
16
|
+
|
|
15
17
|
constructor({
|
|
16
18
|
id,
|
|
17
19
|
code = '',
|
|
18
20
|
keyCode = 0,
|
|
19
21
|
alternativeCodes = [],
|
|
20
22
|
alternativeKeyCodes = [],
|
|
23
|
+
key = '',
|
|
21
24
|
}: Partial<KeyConfig> = {}) {
|
|
22
25
|
this.id = id!;
|
|
23
26
|
this.code = code;
|
|
24
27
|
this.keyCode = keyCode;
|
|
25
28
|
this.alternativeCodes = alternativeCodes;
|
|
26
29
|
this.alternativeKeyCodes = alternativeKeyCodes;
|
|
30
|
+
this.key = key;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
is({ keyCode, code }: KeyboardEvent) {
|
|
33
|
+
is({ keyCode, code, key }: KeyboardEvent) {
|
|
30
34
|
return Boolean(
|
|
31
35
|
code && ( // empty string code means unknown/invalid --> should not compare
|
|
32
36
|
code === this.code
|
|
@@ -35,6 +39,9 @@ export class Key {
|
|
|
35
39
|
|| keyCode && ( // keyCode 0 means unknown/invalid --> should not compare
|
|
36
40
|
keyCode === this.keyCode
|
|
37
41
|
|| this.alternativeKeyCodes.length && includes(this.alternativeKeyCodes, keyCode)
|
|
42
|
+
)
|
|
43
|
+
|| key && ( // empty string code means unknown/invalid --> should not compare
|
|
44
|
+
key === this.key
|
|
38
45
|
),
|
|
39
46
|
);
|
|
40
47
|
}
|
|
@@ -6,11 +6,12 @@ import * as KeyMap from './KeyMap';
|
|
|
6
6
|
export const overrideValues = (map: Partial<Record<keyof KeycodeKeyMap, Partial<Key>>>) => {
|
|
7
7
|
// @ts-ignore - map and KeyMap have same keys
|
|
8
8
|
forEach(Object.entries(map), ([keyName, {
|
|
9
|
-
keyCode, code, alternativeKeyCodes, alternativeCodes,
|
|
9
|
+
keyCode, code, alternativeKeyCodes, alternativeCodes, key,
|
|
10
10
|
}]: [keyof typeof import('./KeyMap'), Partial<Key>]) => {
|
|
11
11
|
if (typeof keyCode === 'number') KeyMap[keyName].keyCode = keyCode;
|
|
12
12
|
if (typeof code === 'string') KeyMap[keyName].code = code;
|
|
13
13
|
if (alternativeKeyCodes) KeyMap[keyName].alternativeKeyCodes = alternativeKeyCodes;
|
|
14
14
|
if (alternativeCodes) KeyMap[keyName].alternativeCodes = alternativeCodes;
|
|
15
|
+
if (key) KeyMap[keyName].key = key;
|
|
15
16
|
});
|
|
16
17
|
};
|
|
@@ -126,12 +126,14 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
126
126
|
const range = new Range();
|
|
127
127
|
range.selectNode(textNode);
|
|
128
128
|
const wholeText = range.getBoundingClientRect();
|
|
129
|
-
range.setStart(textNode,
|
|
129
|
+
range.setStart(textNode, 0);
|
|
130
130
|
range.setEnd(textNode, position);
|
|
131
131
|
const caretText = range.getBoundingClientRect();
|
|
132
|
-
const
|
|
133
|
-
? wholeText.
|
|
134
|
-
: wholeText.left
|
|
132
|
+
const [initialCaretPosition, currentCarretPosition, offsetBase] = isRtl()
|
|
133
|
+
? [wholeText.right, caretText.left, wholeText.left]
|
|
134
|
+
: [wholeText.left, caretText.right, wholeText.right];
|
|
135
|
+
const caretPos = position === 0 ? initialCaretPosition : currentCarretPosition;
|
|
136
|
+
const offset = offsetBase - caretPos;
|
|
135
137
|
offsetPosition(this.caret, { x: -offset }, false);
|
|
136
138
|
}
|
|
137
139
|
|
|
@@ -220,7 +222,7 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
220
222
|
>
|
|
221
223
|
{placeholder}
|
|
222
224
|
</div>
|
|
223
|
-
<div ref={this.text} className="text"
|
|
225
|
+
<div ref={this.text} className="text">
|
|
224
226
|
{this.filterText(value)}
|
|
225
227
|
</div>
|
|
226
228
|
<div ref={this.caret} className="caret" />
|
|
@@ -783,10 +783,10 @@ declare namespace React {
|
|
|
783
783
|
|
|
784
784
|
/** Ensures that the props do not include ref at all */
|
|
785
785
|
type PropsWithoutRef<P> =
|
|
786
|
-
//
|
|
786
|
+
// Omit would not be sufficient for this. We'd like to avoid unnecessary mapping and need a distributive conditional to support unions.
|
|
787
787
|
// see: https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
|
|
788
788
|
// https://github.com/Microsoft/TypeScript/issues/28339
|
|
789
|
-
P extends any ? ('ref' extends keyof P ?
|
|
789
|
+
P extends any ? ('ref' extends keyof P ? Omit<P, 'ref'> : P) : P;
|
|
790
790
|
/** Ensures that the props do not include string ref, which cannot be forwarded */
|
|
791
791
|
type PropsWithRef<P> =
|
|
792
792
|
// Just "P extends { ref?: infer R }" looks sufficient, but R will infer as {} if P is {}.
|
|
@@ -1941,7 +1941,7 @@ declare namespace React {
|
|
|
1941
1941
|
content?: string | undefined;
|
|
1942
1942
|
controls?: boolean | undefined;
|
|
1943
1943
|
coords?: string | undefined;
|
|
1944
|
-
crossOrigin?:
|
|
1944
|
+
crossOrigin?: "anonymous" | "use-credentials" | "" | undefined;
|
|
1945
1945
|
data?: string | undefined;
|
|
1946
1946
|
dateTime?: string | undefined;
|
|
1947
1947
|
default?: boolean | undefined;
|
|
@@ -2229,7 +2229,7 @@ declare namespace React {
|
|
|
2229
2229
|
autoFocus?: boolean | undefined;
|
|
2230
2230
|
capture?: boolean | 'user' | 'environment' | undefined; // https://www.w3.org/TR/html-media-capture/#the-capture-attribute
|
|
2231
2231
|
checked?: boolean | undefined;
|
|
2232
|
-
crossOrigin?:
|
|
2232
|
+
crossOrigin?: "anonymous" | "use-credentials" | "" | undefined;
|
|
2233
2233
|
disabled?: boolean | undefined;
|
|
2234
2234
|
enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send' | undefined;
|
|
2235
2235
|
form?: string | undefined;
|
|
@@ -2281,7 +2281,7 @@ declare namespace React {
|
|
|
2281
2281
|
|
|
2282
2282
|
interface LinkHTMLAttributes<T> extends HTMLAttributes<T> {
|
|
2283
2283
|
as?: string | undefined;
|
|
2284
|
-
crossOrigin?:
|
|
2284
|
+
crossOrigin?: "anonymous" | "use-credentials" | "" | undefined;
|
|
2285
2285
|
href?: string | undefined;
|
|
2286
2286
|
hrefLang?: string | undefined;
|
|
2287
2287
|
integrity?: string | undefined;
|
|
@@ -2307,7 +2307,7 @@ declare namespace React {
|
|
|
2307
2307
|
autoPlay?: boolean | undefined;
|
|
2308
2308
|
controls?: boolean | undefined;
|
|
2309
2309
|
controlsList?: string | undefined;
|
|
2310
|
-
crossOrigin?:
|
|
2310
|
+
crossOrigin?: "anonymous" | "use-credentials" | "" | undefined;
|
|
2311
2311
|
loop?: boolean | undefined;
|
|
2312
2312
|
mediaGroup?: string | undefined;
|
|
2313
2313
|
muted?: boolean | undefined;
|
|
@@ -2392,7 +2392,7 @@ declare namespace React {
|
|
|
2392
2392
|
async?: boolean | undefined;
|
|
2393
2393
|
/** @deprecated */
|
|
2394
2394
|
charSet?: string | undefined;
|
|
2395
|
-
crossOrigin?:
|
|
2395
|
+
crossOrigin?: "anonymous" | "use-credentials" | "" | undefined;
|
|
2396
2396
|
defer?: boolean | undefined;
|
|
2397
2397
|
integrity?: string | undefined;
|
|
2398
2398
|
noModule?: boolean | undefined;
|