Skip to content

Commit c60e513

Browse files
committed
adding feature to trackEvents from outside of webplayer
1 parent 404a4e8 commit c60e513

File tree

6 files changed

+137
-1
lines changed

6 files changed

+137
-1
lines changed

src/APIManager.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,37 @@ module.exports = class APIManager {
8282
// eslint-disable-next-line max-len
8383
'Invoke a callback function with an array of tracked events. This function is called whenever a new event is recorded.',
8484
});
85+
86+
this.registerFunction({
87+
name: 'enableTrackEvents',
88+
category: 'analytics',
89+
fn: (isActive) => {
90+
this.instance.store.dispatch({type: 'ENABLE_TRACKED_EVENTS', payload: isActive});
91+
if (!isActive) {
92+
this.instance.store.dispatch({type: 'FLUSH_TRACKED_EVENTS'});
93+
}
94+
},
95+
description: 'call a callback with an array of tracked events',
96+
});
97+
98+
this.registerFunction({
99+
name: 'trackEvents',
100+
category: 'analytics',
101+
fn: (cb) => {
102+
// subcribe to store's TRACKEVENT change
103+
this.instance.store.subscribe(
104+
({trackedEvents}) => {
105+
if (this.instance.store.state.trackedEvents.events.length) {
106+
cb([...trackedEvents.events]);
107+
// flush the trackedEvents
108+
this.instance.store.dispatch({type: 'FLUSH_TRACKED_EVENTS'});
109+
}
110+
},
111+
['trackedEvents.events'],
112+
);
113+
},
114+
description: 'call a callback with an array of tracked events',
115+
});
85116
}
86117

87118
// Register a new API function with its name, category, function, and description

src/plugins/FileUpload.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,14 @@ module.exports = class FileUpload extends OverlayPlugin {
277277
textProgress.innerHTML = this.i18n.UPLOADER_INSTALLING || 'Installing...';
278278
} else if (data[0] === 'ready' && data.length >= 2) {
279279
if (data[1].indexOf('opengapps') !== -1) {
280+
this.instance.store.dispatch({
281+
type: 'ADD_TRACKED_EVENT',
282+
payload: {
283+
category: 'opengapps',
284+
type: 'installed',
285+
name: 'true',
286+
},
287+
});
280288
this.updateOpenGAppsStatus(true);
281289
}
282290

src/plugins/GamepadManager.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,13 @@ module.exports = class GamepadManager {
262262
* @param {GamepadEvent} event raw event coming from the browser Gamepad API
263263
*/
264264
onGamepadConnected(event) {
265+
this.instance.store.dispatch({
266+
type: 'ADD_TRACKED_EVENT',
267+
payload: {
268+
category: 'gamepad',
269+
action: 'plugged',
270+
},
271+
});
265272
const customEvent = new CustomEvent('gm-gamepadConnected', {detail: this.parseGamepad(event.gamepad)});
266273
window.dispatchEvent(customEvent);
267274
}
@@ -271,6 +278,13 @@ module.exports = class GamepadManager {
271278
* @param {GamepadEvent} event raw event coming from the browser Gamepad API
272279
*/
273280
onGamepadDisconnected(event) {
281+
this.instance.store.dispatch({
282+
type: 'ADD_TRACKED_EVENT',
283+
payload: {
284+
category: 'gamepad',
285+
action: 'unplugged',
286+
},
287+
});
274288
const customEvent = new CustomEvent('gm-gamepadDisconnected', {detail: this.parseGamepad(event.gamepad)});
275289
window.dispatchEvent(customEvent);
276290
this.stopListeningInputs(event.gamepad.index);

src/plugins/util/OverlayPlugin.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ class OverlayPlugin {
6161
if (this.toolbarBtnImage) {
6262
this.toolbarBtnImage.classList.add('gm-active');
6363
}
64+
this.instance.store.dispatch({
65+
type: 'ADD_TRACKED_EVENT',
66+
payload: {
67+
category: 'widget',
68+
action: 'open',
69+
name: this.constructor.name,
70+
},
71+
});
6472
}
6573

6674
/**

src/store/index.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ const initialState = {
1111
},
1212
isKeyboardEventsEnabled: false,
1313
isMouseEventsEnabled: false,
14+
trackedEvents: {
15+
isActive: false,
16+
events: [],
17+
},
1418
};
1519

1620
const createStore = (instance, reducer) => {
@@ -68,7 +72,8 @@ const createStore = (instance, reducer) => {
6872
const notifyListeners = (changedKeys) => {
6973
listeners.forEach(({keys, cb}) => {
7074
if (keys.length === 0 || keys.some((key) => hasChanged(changedKeys, key))) {
71-
cb(instance.store.state);
75+
// send a copy of the store's state, in order to avoid mutation of the store
76+
cb({...instance.store.state});
7277
}
7378
});
7479
};
@@ -131,6 +136,19 @@ const reducer = (state, action) => {
131136
state.isMouseEventsEnabled = true;
132137
}
133138
break;
139+
case 'ENABLE_TRACKED_EVENTS':
140+
state.trackedEvents.isActive = action.payload;
141+
break;
142+
case 'ADD_TRACKED_EVENT':
143+
if (!state.trackedEvents.isActive) {
144+
return state;
145+
}
146+
state.trackedEvents.events.push(action.payload);
147+
148+
break;
149+
case 'FLUSH_TRACKED_EVENTS':
150+
state.trackedEvents.events.length = 0;
151+
break;
134152
default:
135153
log.debug('Store not updated, action type :', action.type, ' unknown');
136154
break;

tests/unit/apiManager.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
'use strict';
2+
3+
const ApiManager = require('../../src/APIManager');
4+
const Instance = require('../mocks/DeviceRenderer');
5+
const Clipboard = require('../../src/plugins/Clipboard');
6+
const store = require('../../src/store/index');
7+
8+
let apiManager;
9+
let instance;
10+
let exposedApiFunctions;
11+
12+
describe('APIManager', () => {
13+
beforeEach(() => {
14+
instance = new Instance({});
15+
apiManager = new ApiManager(instance);
16+
exposedApiFunctions = apiManager.getExposedApiFunctions();
17+
store(instance);
18+
19+
new Clipboard(instance, {
20+
CLIPBOARD_TITLE: 'TEST CLIPBOARD PLUGIN TITLE',
21+
});
22+
});
23+
24+
describe('has exposed api', () => {
25+
test('getRegisteredFunctions', () => {
26+
const registeredFunctions = exposedApiFunctions.utils.getRegisteredFunctions();
27+
expect(Object.keys(registeredFunctions)).toEqual(
28+
expect.arrayContaining([
29+
'sendData',
30+
'getRegisteredFunctions',
31+
'addEventListener',
32+
'disconnect',
33+
'enableTrackEvents',
34+
'trackEvents',
35+
]),
36+
);
37+
});
38+
39+
test('sendTrackEvent', () => {
40+
let events = [];
41+
42+
exposedApiFunctions.analytics.enableTrackEvents(true);
43+
44+
// attach callback to get events
45+
exposedApiFunctions.analytics.trackEvents((evts) => {
46+
events = evts;
47+
});
48+
49+
const button = document.getElementsByClassName('gm-clipboard-button')[0];
50+
expect(button).toBeTruthy();
51+
button.click();
52+
53+
// expect object to be exactly the same
54+
expect(events).toEqual([{category: 'widget', action: 'open', name: 'Clipboard'}]);
55+
});
56+
});
57+
});

0 commit comments

Comments
 (0)