iidrak-analytics-react 1.2.4
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 +170 -0
- package/index.d.ts +1 -0
- package/index.js +4 -0
- package/metastreamio/metastreamio.account.js +65 -0
- package/metastreamio/metastreamio.cart.js +192 -0
- package/metastreamio/metastreamio.constants.js +256 -0
- package/metastreamio/metastreamio.date.js +41 -0
- package/metastreamio/metastreamio.environment.js +406 -0
- package/metastreamio/metastreamio.interface.js +591 -0
- package/metastreamio/metastreamio.logger.js +150 -0
- package/metastreamio/metastreamio.network.js +313 -0
- package/metastreamio/metastreamio.provider.js +50 -0
- package/metastreamio/metastreamio.queue.js +68 -0
- package/metastreamio/metastreamio.recorder.js +157 -0
- package/metastreamio/metastreamio.session.js +150 -0
- package/metastreamio/metastreamio.user.js +79 -0
- package/metastreamio/metastreamio.userproperties.js +76 -0
- package/metastreamio/metastreamio.utility.js +206 -0
- package/metastreamio/models/constructor.app.js +24 -0
- package/metastreamio/models/constructor.config.js +33 -0
- package/metastreamio/models/constructor.user.js +30 -0
- package/metastreamio/models/event.account.balance.js +12 -0
- package/metastreamio/models/event.account.js +22 -0
- package/metastreamio/models/event.appinfo.js +28 -0
- package/metastreamio/models/event.appperformance.js +25 -0
- package/metastreamio/models/event.cart.js +19 -0
- package/metastreamio/models/event.cartitem.js +34 -0
- package/metastreamio/models/event.device.js +55 -0
- package/metastreamio/models/event.event.js +88 -0
- package/metastreamio/models/event.network.js +27 -0
- package/metastreamio/models/event.parameter.js +12 -0
- package/metastreamio/models/event.parameters.js +38 -0
- package/metastreamio/models/event.session.js +24 -0
- package/metastreamio/models/event.session.utm.js +37 -0
- package/metastreamio/models/event.userproperty.js +14 -0
- package/metastreamio/string.format.js +7 -0
- package/package.json +21 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { strf } from "./string.format.js";
|
|
4
|
+
|
|
5
|
+
strf();
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
*
|
|
9
|
+
* Console logger
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
class MetaStreamIOLogger {
|
|
14
|
+
constructor({
|
|
15
|
+
constants,
|
|
16
|
+
logPrefix,
|
|
17
|
+
loggingEnabled = false,
|
|
18
|
+
loggingLevel = "INFO",
|
|
19
|
+
loggingCategories = null,
|
|
20
|
+
loggingAlwaysWarn = true,
|
|
21
|
+
loggingAlwaysError = true,
|
|
22
|
+
} = {}) {
|
|
23
|
+
this.constant = constants;
|
|
24
|
+
this.logPrefix = logPrefix ? logPrefix : "";
|
|
25
|
+
this.loggingEnabled = loggingEnabled;
|
|
26
|
+
this.loggingCategories = loggingCategories;
|
|
27
|
+
|
|
28
|
+
this.level = { info: 1, warn: 2, error: 3 };
|
|
29
|
+
|
|
30
|
+
this.loggingLevel = this.enumLevel(loggingLevel);
|
|
31
|
+
|
|
32
|
+
this.alwaysWarn = loggingAlwaysWarn;
|
|
33
|
+
this.alwaysError = loggingAlwaysError;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
enumLevel(level) {
|
|
37
|
+
switch (level) {
|
|
38
|
+
case "INFO":
|
|
39
|
+
return this.level.info;
|
|
40
|
+
break;
|
|
41
|
+
case "WARN":
|
|
42
|
+
return this.level.warn;
|
|
43
|
+
break;
|
|
44
|
+
case "ERROR":
|
|
45
|
+
return this.level.error;
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
return this.level.info;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
checkCategory(category = null) {
|
|
53
|
+
if (
|
|
54
|
+
this.loggingCategories !== null &&
|
|
55
|
+
this.loggingCategories.length === 0
|
|
56
|
+
) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (!Array.isArray(category)) {
|
|
60
|
+
category = [category];
|
|
61
|
+
}
|
|
62
|
+
for (let cat in category) {
|
|
63
|
+
if (category[cat] === null) {
|
|
64
|
+
return true;
|
|
65
|
+
} else if (
|
|
66
|
+
this.loggingCategories === null ||
|
|
67
|
+
this.loggingCategories === undefined
|
|
68
|
+
) {
|
|
69
|
+
return true;
|
|
70
|
+
} else if (this.loggingCategories.includes(category[cat])) {
|
|
71
|
+
return true;
|
|
72
|
+
} else {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
log(category = null, ...messages) {
|
|
79
|
+
if (
|
|
80
|
+
this.loggingEnabled == true &&
|
|
81
|
+
this.loggingLevel <= this.level.info &&
|
|
82
|
+
this.checkCategory(category)
|
|
83
|
+
) {
|
|
84
|
+
console.log(this.logPrefix, `<${category}>`, messages.join(" "));
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
log_unformatted(category = null, ...messages) {
|
|
89
|
+
if (
|
|
90
|
+
this.loggingEnabled == true &&
|
|
91
|
+
this.loggingLevel <= this.level.info &&
|
|
92
|
+
this.checkCategory(category)
|
|
93
|
+
) {
|
|
94
|
+
console.log(messages.join(" "));
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
json(category = null, data) {
|
|
99
|
+
if (
|
|
100
|
+
this.loggingEnabled == true &&
|
|
101
|
+
this.loggingLevel <= this.level.info &&
|
|
102
|
+
this.checkCategory(category)
|
|
103
|
+
) {
|
|
104
|
+
console.log(this.logPrefix, `<${category}>`);
|
|
105
|
+
console.log(JSON.stringify(data, null, 4));
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
info(category = null, ...messages) {
|
|
110
|
+
if (
|
|
111
|
+
this.loggingEnabled == true &&
|
|
112
|
+
this.loggingLevel <= this.level.info &&
|
|
113
|
+
this.checkCategory(category)
|
|
114
|
+
) {
|
|
115
|
+
console.log(this.logPrefix, `<${category}>`, messages.join(" "));
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
warn(category = null, ...messages) {
|
|
120
|
+
if (this.loggingEnabled && this.alwaysWarn) {
|
|
121
|
+
this._warn(category, messages);
|
|
122
|
+
} else if (
|
|
123
|
+
this.loggingEnabled == true &&
|
|
124
|
+
this.loggingLevel <= this.level.warn
|
|
125
|
+
) {
|
|
126
|
+
this._warn(category, messages);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
_warn(category, messages) {
|
|
131
|
+
console.warn(this.logPrefix, `<${category}>`, messages.join(" "));
|
|
132
|
+
}
|
|
133
|
+
error(category = null, ...messages) {
|
|
134
|
+
if (this.loggingEnabled && this.alwaysError) {
|
|
135
|
+
this._error(category, messages);
|
|
136
|
+
return true;
|
|
137
|
+
} else if (
|
|
138
|
+
this.loggingEnabled == true &&
|
|
139
|
+
this.loggingLevel <= this.level.error
|
|
140
|
+
) {
|
|
141
|
+
this._error(category, messages);
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
_error(category, messages) {
|
|
146
|
+
console.error(this.logPrefix, `<${category}>`, messages.join(" "));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export { MetaStreamIOLogger };
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { strf } from "./string.format.js";
|
|
4
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
5
|
+
import NetInfo from "@react-native-community/netinfo";
|
|
6
|
+
|
|
7
|
+
strf();
|
|
8
|
+
|
|
9
|
+
const EVENT_QUEUE_KEY = "metastream_offline_events";
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
*
|
|
13
|
+
* Network functions
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
class MetaStreamIONetwork {
|
|
18
|
+
constructor({ constants, endpoints, logger, silentMode, headers } = {}) {
|
|
19
|
+
this.silentMode = silentMode;
|
|
20
|
+
this.constant = constants;
|
|
21
|
+
this.endpoint = null;
|
|
22
|
+
this.endpoints = Array.isArray(endpoints) ? endpoints : [];
|
|
23
|
+
this.headers = headers;
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
|
|
26
|
+
// Initialize offline handling
|
|
27
|
+
this.initOfflineHandling();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
initOfflineHandling() {
|
|
31
|
+
// Flush on startup if connected
|
|
32
|
+
NetInfo.fetch().then(state => {
|
|
33
|
+
if (state.isConnected) {
|
|
34
|
+
this.flushEvents();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Flush when network comes back online
|
|
39
|
+
NetInfo.addEventListener(state => {
|
|
40
|
+
if (state.isConnected) {
|
|
41
|
+
this.flushEvents();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
reset() {
|
|
47
|
+
this.endpoint = null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async testConnection() {
|
|
51
|
+
if (!this.endpoint || this.endpoint === null) {
|
|
52
|
+
for (let _e in this.endpoints) {
|
|
53
|
+
this.endpoint = await this.getData({ endpoint: this.endpoints[_e] })
|
|
54
|
+
.then((data) => {
|
|
55
|
+
try {
|
|
56
|
+
if (data.status === 200) {
|
|
57
|
+
return this.endpoints[_e];
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
.catch(() => { });
|
|
64
|
+
if (this.endpoint) {
|
|
65
|
+
this.logger.log(
|
|
66
|
+
"network",
|
|
67
|
+
this.constant.MetaStreamIO_Network_EndpointSet.format(this.endpoint)
|
|
68
|
+
);
|
|
69
|
+
break;
|
|
70
|
+
} else {
|
|
71
|
+
this.logger.log(
|
|
72
|
+
"network",
|
|
73
|
+
this.constant.MetaStreamIO_Network_EndpointTestFailed.format(
|
|
74
|
+
this.endpoint
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
this.logger.log(
|
|
78
|
+
"network",
|
|
79
|
+
this.constant.MetaStreamIO_Network_SilentModeEnabled
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return Promise.resolve(this.endpoint);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async getData({ endpoint = this.endpoint } = {}) {
|
|
89
|
+
var rx;
|
|
90
|
+
|
|
91
|
+
let get_config = {
|
|
92
|
+
method: "GET",
|
|
93
|
+
// mode: "no-cors", // required for local testing
|
|
94
|
+
cache: "no-cache",
|
|
95
|
+
credentials: "same-origin",
|
|
96
|
+
redirect: "follow", // manual, *follow, error
|
|
97
|
+
referrerPolicy: "no-referrer", // no-referrer, *client
|
|
98
|
+
headers: {},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
if (this.headers !== null) {
|
|
102
|
+
get_config.headers = Object.assign(get_config.headers, this.headers);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
await fetch(endpoint, get_config)
|
|
107
|
+
.then((response) => {
|
|
108
|
+
const contentType = response.headers.get("content-type");
|
|
109
|
+
if (!contentType || !contentType.includes("application/json")) {
|
|
110
|
+
return null;
|
|
111
|
+
} else {
|
|
112
|
+
return response;
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
.catch((err) => {
|
|
116
|
+
return Promise.resolve(err);
|
|
117
|
+
})
|
|
118
|
+
.then(async (response) => {
|
|
119
|
+
rx = {
|
|
120
|
+
body: await response.json(),
|
|
121
|
+
status: response.status,
|
|
122
|
+
};
|
|
123
|
+
})
|
|
124
|
+
.catch((err) => {
|
|
125
|
+
return {
|
|
126
|
+
body: err,
|
|
127
|
+
status: 400,
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
return rx;
|
|
131
|
+
} catch (err) {
|
|
132
|
+
return Promise.reject(err);
|
|
133
|
+
throw this.constant.MetaStreamIO_Network_GetDataIssue.format(
|
|
134
|
+
err,
|
|
135
|
+
endpoint
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async postData({ data = {}, endpoint = null } = {}) {
|
|
141
|
+
var ret;
|
|
142
|
+
|
|
143
|
+
var _endpoint = this.endpoint + (endpoint ? endpoint : "");
|
|
144
|
+
|
|
145
|
+
this.logger.log(
|
|
146
|
+
"network-request",
|
|
147
|
+
this.constant.MetaStreamIO_Log_RequestObject
|
|
148
|
+
);
|
|
149
|
+
this.logger.json("network-request", data);
|
|
150
|
+
|
|
151
|
+
if (this.silentMode) {
|
|
152
|
+
return {
|
|
153
|
+
body: this.constant.MetaStreamIO_Network_SilentMode,
|
|
154
|
+
status: 1,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!this.endpoint) {
|
|
159
|
+
_endpoint = await this.testConnection()
|
|
160
|
+
.then((rx_endpoint) => {
|
|
161
|
+
return Promise.resolve(rx_endpoint + (endpoint ? endpoint : ""));
|
|
162
|
+
})
|
|
163
|
+
.catch((err) => err);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (_endpoint) {
|
|
167
|
+
return await this.post({
|
|
168
|
+
data: data,
|
|
169
|
+
endpoint: _endpoint,
|
|
170
|
+
})
|
|
171
|
+
.then((post_return) => {
|
|
172
|
+
return Promise.resolve(post_return);
|
|
173
|
+
})
|
|
174
|
+
.catch((err) => {
|
|
175
|
+
return Promise.resolve(err);
|
|
176
|
+
});
|
|
177
|
+
} else {
|
|
178
|
+
// Network configuration failed, try to store offline if it looks like a network issue
|
|
179
|
+
this.logger.log("network", "No endpoint resolved, storing offline...");
|
|
180
|
+
// Use the first endpoint candidate if available for offline storage purpose
|
|
181
|
+
const fallbackEndpoint = this.endpoints.length > 0 ? this.endpoints[0] : null;
|
|
182
|
+
if (fallbackEndpoint) {
|
|
183
|
+
await this.storeOfflineEvent(fallbackEndpoint + (endpoint ? endpoint : ""), data);
|
|
184
|
+
return {
|
|
185
|
+
body: "Stored offline",
|
|
186
|
+
status: 200 // Fake success to prevent app error
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
body: this.constant.MetaStreamIO_Network_PostDataIssue.format(
|
|
192
|
+
"attempted to reset network",
|
|
193
|
+
_endpoint
|
|
194
|
+
),
|
|
195
|
+
status: 400,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async post({ data = {}, endpoint = this.endpoint } = {}) {
|
|
201
|
+
let rx = {};
|
|
202
|
+
|
|
203
|
+
let post_config = {
|
|
204
|
+
method: "POST",
|
|
205
|
+
// mode: "no-cors", // required for local testing
|
|
206
|
+
cache: "no-cache",
|
|
207
|
+
credentials: "same-origin",
|
|
208
|
+
headers: {
|
|
209
|
+
"Content-Type": "application/json",
|
|
210
|
+
},
|
|
211
|
+
redirect: "follow", // manual, *follow, error
|
|
212
|
+
referrerPolicy: "no-referrer", // no-referrer, *client
|
|
213
|
+
body: JSON.stringify(data),
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
if (this.headers !== null) {
|
|
217
|
+
post_config.headers = Object.assign(post_config.headers, this.headers);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
let isOffline = false;
|
|
221
|
+
await NetInfo.fetch().then(state => {
|
|
222
|
+
if (!state.isConnected) {
|
|
223
|
+
isOffline = true;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
if (isOffline) {
|
|
228
|
+
this.logger.log("network", "Offline detected. Storing event.");
|
|
229
|
+
await this.storeOfflineEvent(endpoint, data);
|
|
230
|
+
return { status: 200, body: "Stored offline" };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
await fetch(endpoint, post_config)
|
|
234
|
+
.then((response) => {
|
|
235
|
+
let _contentType = response.headers.get("content-type");
|
|
236
|
+
if (!_contentType || !_contentType.includes("application/json")) {
|
|
237
|
+
return null;
|
|
238
|
+
} else {
|
|
239
|
+
rx.status = response.status;
|
|
240
|
+
return response;
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
.then(async (response) => {
|
|
244
|
+
rx.body = await response.json();
|
|
245
|
+
})
|
|
246
|
+
.catch(async (err) => {
|
|
247
|
+
this.logger.error("network", "fetch() response", err);
|
|
248
|
+
// Store offline on network error
|
|
249
|
+
await this.storeOfflineEvent(endpoint, data);
|
|
250
|
+
rx.status = 200; // Treat as success to deque
|
|
251
|
+
rx.body = "Stored offline on error";
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
return rx;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async storeOfflineEvent(endpoint, payload) {
|
|
258
|
+
try {
|
|
259
|
+
const existing = JSON.parse(await AsyncStorage.getItem(EVENT_QUEUE_KEY)) || [];
|
|
260
|
+
const newEvent = {
|
|
261
|
+
endpoint,
|
|
262
|
+
payload,
|
|
263
|
+
failedAt: new Date().toISOString(),
|
|
264
|
+
};
|
|
265
|
+
existing.push(newEvent);
|
|
266
|
+
await AsyncStorage.setItem(EVENT_QUEUE_KEY, JSON.stringify(existing));
|
|
267
|
+
this.logger.log("network", `Stored event locally. Queue size: ${existing.length}`);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
this.logger.error("network", "Failed to store event:", error);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async flushEvents() {
|
|
274
|
+
try {
|
|
275
|
+
const stored = JSON.parse(await AsyncStorage.getItem(EVENT_QUEUE_KEY)) || [];
|
|
276
|
+
if (stored.length === 0) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.logger.log("network", `Flushing ${stored.length} stored event(s)...`);
|
|
281
|
+
const remainingEvents = [];
|
|
282
|
+
|
|
283
|
+
for (const e of stored) {
|
|
284
|
+
try {
|
|
285
|
+
const response = await fetch(e.endpoint, {
|
|
286
|
+
method: "POST",
|
|
287
|
+
headers: { "Content-Type": "application/json" },
|
|
288
|
+
body: JSON.stringify(e.payload),
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
if (response.ok) {
|
|
292
|
+
this.logger.log("network", "Retried & sent event");
|
|
293
|
+
} else {
|
|
294
|
+
// Drop event if server rejects it (4xx, 5xx), avoid infinite loop
|
|
295
|
+
this.logger.warn("network", "Retry failed with non-OK status, dropping event");
|
|
296
|
+
}
|
|
297
|
+
} catch (err) {
|
|
298
|
+
// Keep if network error
|
|
299
|
+
remainingEvents.push(e);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
await AsyncStorage.setItem(EVENT_QUEUE_KEY, JSON.stringify(remainingEvents));
|
|
304
|
+
if (remainingEvents.length < stored.length) {
|
|
305
|
+
this.logger.log("network", `Flush complete. Remaining: ${remainingEvents.length}`);
|
|
306
|
+
}
|
|
307
|
+
} catch (error) {
|
|
308
|
+
this.logger.error("network", "Failed to flush events:", error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
}
|
|
313
|
+
export { MetaStreamIONetwork };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import { View, StyleSheet, Dimensions } from 'react-native';
|
|
3
|
+
import ViewShot from 'react-native-view-shot';
|
|
4
|
+
|
|
5
|
+
class MetaStreamProvider extends Component {
|
|
6
|
+
constructor(props) {
|
|
7
|
+
super(props);
|
|
8
|
+
this.viewShotRef = React.createRef();
|
|
9
|
+
this.tracker = props.tracker;
|
|
10
|
+
|
|
11
|
+
// Auto-start recording if tracker is available
|
|
12
|
+
if (this.tracker && this.tracker.recorder) {
|
|
13
|
+
// Small delay to ensure view is mounted
|
|
14
|
+
setTimeout(() => {
|
|
15
|
+
this.tracker.recorder.startRecording(this.viewShotRef);
|
|
16
|
+
}, 1000);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
handleTouch(e, type) {
|
|
21
|
+
if (this.tracker && this.tracker.recorder) {
|
|
22
|
+
this.tracker.recorder.recordInteraction(type, e.nativeEvent);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
render() {
|
|
27
|
+
const { children, style } = this.props;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<ViewShot ref={this.viewShotRef} style={{ flex: 1 }} options={{ format: "jpg", quality: 0.5 }}>
|
|
31
|
+
<View
|
|
32
|
+
style={[styles.container, style]}
|
|
33
|
+
onTouchStart={(e) => this.handleTouch(e, 'touch_start')}
|
|
34
|
+
onTouchMove={(e) => this.handleTouch(e, 'touch_move')}
|
|
35
|
+
onTouchEnd={(e) => this.handleTouch(e, 'touch_end')}
|
|
36
|
+
>
|
|
37
|
+
{children}
|
|
38
|
+
</View>
|
|
39
|
+
</ViewShot>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const styles = StyleSheet.create({
|
|
45
|
+
container: {
|
|
46
|
+
flex: 1,
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export { MetaStreamProvider };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// http://nickang.com
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Implementation of Queue.
|
|
5
|
+
*/
|
|
6
|
+
class Queue {
|
|
7
|
+
/**
|
|
8
|
+
* Create a queue.
|
|
9
|
+
*/
|
|
10
|
+
constructor() {
|
|
11
|
+
this.store = {};
|
|
12
|
+
this.front = 0;
|
|
13
|
+
this.end = 0;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Add item to end of queue.
|
|
19
|
+
* @param {*} The data to store in the position.
|
|
20
|
+
*/
|
|
21
|
+
Queue.prototype.enqueue = function (data) {
|
|
22
|
+
this.store[this.end] = data;
|
|
23
|
+
this.end++;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Remove item from queue and return its data.
|
|
28
|
+
* @return {*} The data stored in item.
|
|
29
|
+
*/
|
|
30
|
+
Queue.prototype.dequeue = function () {
|
|
31
|
+
if (this.front === this.end) return null;
|
|
32
|
+
|
|
33
|
+
const data = this.store[this.front];
|
|
34
|
+
delete this.store[this.front];
|
|
35
|
+
this.front++;
|
|
36
|
+
return data;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Return current size of queue.
|
|
41
|
+
* @return {number} Size of queue.
|
|
42
|
+
*/
|
|
43
|
+
Queue.prototype.size = function () {
|
|
44
|
+
return this.end - this.front;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Return item at front of queue without dequeueing.
|
|
49
|
+
* @return {*} The data stored in item.
|
|
50
|
+
*/
|
|
51
|
+
Queue.prototype.peek = function () {
|
|
52
|
+
if (this.size() === 0) return null;
|
|
53
|
+
return this.store[this.front];
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* The MetaStreamIO SAUCE
|
|
58
|
+
*
|
|
59
|
+
*/
|
|
60
|
+
Queue.prototype.run = function (callback) {
|
|
61
|
+
while (this.size() > 0) {
|
|
62
|
+
callback(this.dequeue()).catch(err => {
|
|
63
|
+
console.error('<queue callback>', err);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export {Queue};
|