@zoho_apptics/apptics-js-sdk 2.0.0-beta → 2.0.0-beta.1
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/CHANGELOG.md +111 -5
- package/README.md +399 -300
- package/dist/apptics.esm.min.js +2 -2
- package/dist/apptics.esm.min.js.map +1 -1
- package/dist/apptics.min.js +2 -2
- package/dist/apptics.min.js.map +1 -1
- package/dist/chunks/lifecycle-VYr43KcB.min.js +3 -0
- package/dist/chunks/lifecycle-VYr43KcB.min.js.map +1 -0
- package/dist/cjs/auto-init.d.ts +3 -3
- package/dist/cjs/auto-init.js +1 -1
- package/dist/cjs/core/attempts.js +1 -1
- package/dist/cjs/core/batch.js +2 -1
- package/dist/cjs/core/callsite.d.ts +6 -0
- package/dist/cjs/core/callsite.js +25 -3
- package/dist/cjs/core/consent.d.ts +5 -1
- package/dist/cjs/core/consent.js +8 -6
- package/dist/cjs/core/constants.d.ts +35 -10
- package/dist/cjs/core/constants.js +31 -15
- package/dist/cjs/core/db.d.ts +12 -4
- package/dist/cjs/core/db.js +167 -34
- package/dist/cjs/core/debug.js +1 -1
- package/dist/cjs/core/env.js +1 -1
- package/dist/cjs/core/framework-id.d.ts +1 -1
- package/dist/cjs/core/framework-id.js +3 -3
- package/dist/cjs/core/guard.d.ts +9 -0
- package/dist/cjs/core/guard.js +27 -13
- package/dist/cjs/core/hooks.d.ts +2 -4
- package/dist/cjs/core/hooks.js +2 -3
- package/dist/cjs/core/locks.d.ts +9 -0
- package/dist/cjs/core/locks.js +22 -0
- package/dist/cjs/core/logger.d.ts +3 -4
- package/dist/cjs/core/logger.js +4 -40
- package/dist/cjs/core/state.d.ts +3 -2
- package/dist/cjs/core/state.js +2 -2
- package/dist/cjs/core/storage.d.ts +20 -5
- package/dist/cjs/core/storage.js +115 -17
- package/dist/cjs/core/stylesheet.d.ts +8 -0
- package/dist/cjs/core/stylesheet.js +29 -0
- package/dist/cjs/core/transport.d.ts +2 -0
- package/dist/cjs/core/transport.js +19 -4
- package/dist/cjs/core/utils.js +1 -1
- package/dist/cjs/core/validate.js +2 -2
- package/dist/cjs/device/appversion.d.ts +1 -6
- package/dist/cjs/device/appversion.js +13 -1
- package/dist/cjs/device/index.d.ts +11 -0
- package/dist/cjs/device/index.js +120 -20
- package/dist/cjs/engagement/api-rules.d.ts +32 -67
- package/dist/cjs/engagement/api-rules.js +144 -157
- package/dist/cjs/engagement/auto-api.js +2 -2
- package/dist/cjs/engagement/auto-screen.d.ts +2 -0
- package/dist/cjs/engagement/auto-screen.js +67 -3
- package/dist/cjs/engagement/defined-events.js +1 -1
- package/dist/cjs/engagement/send.js +6 -1
- package/dist/cjs/engagement/session.d.ts +12 -3
- package/dist/cjs/engagement/session.js +161 -25
- package/dist/cjs/engagement/track.js +45 -20
- package/dist/cjs/errors/send.js +1 -1
- package/dist/cjs/errors/track.d.ts +1 -1
- package/dist/cjs/errors/track.js +46 -6
- package/dist/cjs/feedback/controls.d.ts +6 -0
- package/dist/cjs/feedback/controls.js +31 -1
- package/dist/cjs/feedback/index.d.ts +8 -7
- package/dist/cjs/feedback/index.js +32 -13
- package/dist/cjs/feedback/logs.d.ts +10 -5
- package/dist/cjs/feedback/logs.js +52 -13
- package/dist/cjs/feedback/quartz.d.ts +18 -0
- package/dist/cjs/feedback/quartz.js +105 -0
- package/dist/cjs/feedback/send.d.ts +3 -0
- package/dist/cjs/feedback/send.js +28 -3
- package/dist/cjs/feedback/styles.d.ts +10 -0
- package/dist/cjs/feedback/styles.js +8 -0
- package/dist/cjs/feedback/template.d.ts +1 -1
- package/dist/cjs/feedback/template.js +12 -12
- package/dist/cjs/feedback/ui.d.ts +14 -6
- package/dist/cjs/feedback/ui.js +126 -48
- package/dist/cjs/heatmap/send.js +1 -1
- package/dist/cjs/heatmap/track.d.ts +1 -1
- package/dist/cjs/heatmap/track.js +87 -16
- package/dist/cjs/index.d.ts +17 -63
- package/dist/cjs/index.js +104 -92
- package/dist/cjs/lifecycle.d.ts +8 -1
- package/dist/cjs/lifecycle.js +258 -62
- package/dist/cjs/remoteconfig/country.d.ts +4 -0
- package/dist/cjs/remoteconfig/country.js +73 -0
- package/dist/cjs/remoteconfig/custom.d.ts +7 -7
- package/dist/cjs/remoteconfig/custom.js +31 -51
- package/dist/cjs/remoteconfig/evaluate.d.ts +3 -3
- package/dist/cjs/remoteconfig/evaluate.js +56 -43
- package/dist/cjs/remoteconfig/fetch.d.ts +3 -3
- package/dist/cjs/remoteconfig/fetch.js +9 -23
- package/dist/cjs/remoteconfig/index.d.ts +10 -8
- package/dist/cjs/remoteconfig/index.js +65 -39
- package/dist/cjs/remoteconfig/store.js +1 -1
- package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/cjs/remoteconfig/tz-countries.js +13 -0
- package/dist/cjs/remotelog/gate.d.ts +2 -11
- package/dist/cjs/remotelog/gate.js +9 -35
- package/dist/cjs/remotelog/index.d.ts +4 -21
- package/dist/cjs/remotelog/logger.d.ts +11 -17
- package/dist/cjs/remotelog/logger.js +30 -58
- package/dist/cjs/remotelog/send.js +10 -10
- package/dist/cjs/remotelogger/index.d.ts +12 -0
- package/dist/cjs/remotelogger/index.js +18 -0
- package/dist/cjs/scheduler.js +2 -2
- package/dist/cjs/types.d.ts +155 -82
- package/dist/cjs/user/index.js +11 -6
- package/dist/esm/auto-init.d.ts +3 -3
- package/dist/esm/auto-init.js +1 -1
- package/dist/esm/core/attempts.js +1 -1
- package/dist/esm/core/batch.js +2 -1
- package/dist/esm/core/callsite.d.ts +6 -0
- package/dist/esm/core/callsite.js +25 -4
- package/dist/esm/core/consent.d.ts +5 -1
- package/dist/esm/core/consent.js +9 -7
- package/dist/esm/core/constants.d.ts +35 -10
- package/dist/esm/core/constants.js +30 -15
- package/dist/esm/core/db.d.ts +12 -4
- package/dist/esm/core/db.js +164 -35
- package/dist/esm/core/debug.js +1 -1
- package/dist/esm/core/env.js +1 -1
- package/dist/esm/core/framework-id.d.ts +1 -1
- package/dist/esm/core/framework-id.js +3 -3
- package/dist/esm/core/guard.d.ts +9 -0
- package/dist/esm/core/guard.js +27 -14
- package/dist/esm/core/hooks.d.ts +2 -4
- package/dist/esm/core/hooks.js +2 -3
- package/dist/esm/core/locks.d.ts +9 -0
- package/dist/esm/core/locks.js +20 -0
- package/dist/esm/core/logger.d.ts +3 -4
- package/dist/esm/core/logger.js +4 -40
- package/dist/esm/core/state.d.ts +3 -2
- package/dist/esm/core/state.js +2 -2
- package/dist/esm/core/storage.d.ts +20 -5
- package/dist/esm/core/storage.js +113 -18
- package/dist/esm/core/stylesheet.d.ts +8 -0
- package/dist/esm/core/stylesheet.js +27 -0
- package/dist/esm/core/transport.d.ts +2 -0
- package/dist/esm/core/transport.js +19 -5
- package/dist/esm/core/utils.js +1 -1
- package/dist/esm/core/validate.js +2 -2
- package/dist/esm/device/appversion.d.ts +1 -6
- package/dist/esm/device/appversion.js +13 -2
- package/dist/esm/device/index.d.ts +11 -0
- package/dist/esm/device/index.js +123 -24
- package/dist/esm/engagement/api-rules.d.ts +32 -67
- package/dist/esm/engagement/api-rules.js +143 -155
- package/dist/esm/engagement/auto-api.js +3 -3
- package/dist/esm/engagement/auto-screen.d.ts +2 -0
- package/dist/esm/engagement/auto-screen.js +67 -4
- package/dist/esm/engagement/defined-events.js +1 -1
- package/dist/esm/engagement/send.js +6 -1
- package/dist/esm/engagement/session.d.ts +12 -3
- package/dist/esm/engagement/session.js +162 -29
- package/dist/esm/engagement/track.js +52 -27
- package/dist/esm/errors/send.js +1 -1
- package/dist/esm/errors/track.d.ts +1 -1
- package/dist/esm/errors/track.js +46 -6
- package/dist/esm/feedback/controls.d.ts +6 -0
- package/dist/esm/feedback/controls.js +31 -2
- package/dist/esm/feedback/index.d.ts +8 -7
- package/dist/esm/feedback/index.js +34 -13
- package/dist/esm/feedback/logs.d.ts +10 -5
- package/dist/esm/feedback/logs.js +54 -15
- package/dist/esm/feedback/quartz.d.ts +18 -0
- package/dist/esm/feedback/quartz.js +99 -0
- package/dist/esm/feedback/send.d.ts +3 -0
- package/dist/esm/feedback/send.js +28 -5
- package/dist/esm/feedback/styles.d.ts +10 -0
- package/dist/esm/feedback/styles.js +4 -0
- package/dist/esm/feedback/template.d.ts +1 -1
- package/dist/esm/feedback/template.js +12 -12
- package/dist/esm/feedback/ui.d.ts +14 -6
- package/dist/esm/feedback/ui.js +126 -49
- package/dist/esm/heatmap/send.js +1 -1
- package/dist/esm/heatmap/track.d.ts +1 -1
- package/dist/esm/heatmap/track.js +87 -16
- package/dist/esm/index.d.ts +17 -63
- package/dist/esm/index.js +108 -80
- package/dist/esm/lifecycle.d.ts +8 -1
- package/dist/esm/lifecycle.js +266 -71
- package/dist/esm/remoteconfig/country.d.ts +4 -0
- package/dist/esm/remoteconfig/country.js +70 -0
- package/dist/esm/remoteconfig/custom.d.ts +7 -7
- package/dist/esm/remoteconfig/custom.js +32 -52
- package/dist/esm/remoteconfig/evaluate.d.ts +3 -3
- package/dist/esm/remoteconfig/evaluate.js +57 -44
- package/dist/esm/remoteconfig/fetch.d.ts +3 -3
- package/dist/esm/remoteconfig/fetch.js +9 -23
- package/dist/esm/remoteconfig/index.d.ts +10 -8
- package/dist/esm/remoteconfig/index.js +66 -40
- package/dist/esm/remoteconfig/store.js +1 -1
- package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/esm/remoteconfig/tz-countries.js +11 -0
- package/dist/esm/remotelog/gate.d.ts +2 -11
- package/dist/esm/remotelog/gate.js +10 -32
- package/dist/esm/remotelog/index.d.ts +4 -21
- package/dist/esm/remotelog/logger.d.ts +11 -17
- package/dist/esm/remotelog/logger.js +32 -60
- package/dist/esm/remotelog/send.js +12 -12
- package/dist/esm/remotelogger/index.d.ts +12 -0
- package/dist/esm/remotelogger/index.js +13 -0
- package/dist/esm/scheduler.js +2 -2
- package/dist/esm/types.d.ts +155 -82
- package/dist/esm/user/index.js +12 -6
- package/dist/feedback.esm.min.js +2 -2
- package/dist/feedback.esm.min.js.map +1 -1
- package/package.json +14 -16
- package/dist/chunks/batch-BU_mTpm1.min.js +0 -3
- package/dist/chunks/batch-BU_mTpm1.min.js.map +0 -1
- package/dist/chunks/logs-Bea5zUW_.min.js +0 -3
- package/dist/chunks/logs-Bea5zUW_.min.js.map +0 -1
- package/dist/cjs/heatmap/index.d.ts +0 -16
- package/dist/cjs/heatmap/index.js +0 -22
- package/dist/cjs/remotelog/index.js +0 -55
- package/dist/esm/heatmap/index.d.ts +0 -16
- package/dist/esm/heatmap/index.js +0 -17
- package/dist/esm/remotelog/index.js +0 -51
- package/dist/heatmap.esm.min.js +0 -3
- package/dist/heatmap.esm.min.js.map +0 -1
- package/dist/style.css +0 -1
package/dist/esm/lifecycle.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
-
import { REQUIRED_CONFIG, AP_CONFIG,
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
import { REQUIRED_CONFIG, CONFIG_KEYS, AP_CONFIG, RETIRED_CONFIG_NAMES, DEFAULT_INACTIVE_MINUTES } from './core/constants.js';
|
|
3
3
|
import { _ZAP } from './core/state.js';
|
|
4
|
-
import {
|
|
5
|
-
import { isEmpty,
|
|
6
|
-
import { storageReady, user_defaults,
|
|
4
|
+
import { Console, warnAlways } from './core/logger.js';
|
|
5
|
+
import { isEmpty, isSuccess } from './core/utils.js';
|
|
6
|
+
import { storageReady, user_defaults, engagement_transactions, error_transactions, tracking_preference } from './core/storage.js';
|
|
7
7
|
import { hooks } from './core/hooks.js';
|
|
8
8
|
import { applyDebugConfig } from './core/debug.js';
|
|
9
9
|
import { getConnectionType, getOrientation } from './core/env.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { checkAndUpdateSession, updateLastActiveTimeOfSession, updateScreenWithEndtime, endCurrentSession } from './engagement/session.js';
|
|
10
|
+
import { restoreServerSettings, prepareDevice, updateDeviceWithApptics, refreshServerSettings, needsDevice, deviceReady } from './device/index.js';
|
|
11
|
+
import { clearAppVersion, registerAppVersion, appVersionFailedForNetwork } from './device/appversion.js';
|
|
12
|
+
import { holdTabLock, checkAndUpdateSession, updateLastActiveTimeOfSession, updateScreenWithEndtime, endCurrentSession } from './engagement/session.js';
|
|
14
13
|
import { enableApiTracking } from './engagement/auto-api.js';
|
|
15
|
-
import { enableScreenTracking } from './engagement/auto-screen.js';
|
|
14
|
+
import { routePath, enableScreenTracking } from './engagement/auto-screen.js';
|
|
16
15
|
import { resumeScreen, trackEvent } from './engagement/track.js';
|
|
17
16
|
import { trackError } from './errors/track.js';
|
|
18
17
|
import { startTimers, flush, stopTimers } from './scheduler.js';
|
|
19
|
-
import './remotelog/
|
|
18
|
+
import { sendStoredLogs, forgetStoredLogs } from './remotelog/send.js';
|
|
20
19
|
import { getUserInfo } from './user/index.js';
|
|
21
20
|
import { clearAttempts } from './core/attempts.js';
|
|
22
|
-
import {
|
|
21
|
+
import { FRAMEWORK_ID } from './core/framework-id.js';
|
|
23
22
|
|
|
24
23
|
let listenersAttached = false;
|
|
25
24
|
/** The config init() was last called with; reset() starts again from it. */
|
|
@@ -38,16 +37,29 @@ function isBrowser() {
|
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
40
|
+
* The config as the SDK keeps it: base_url, auth_key and app_domain under their inside names
|
|
41
|
+
* (serviceUrl, zak, identifier; see CONFIG_KEYS), and appversion as text. An earlier name of a
|
|
42
|
+
* key is still read when the key itself is not given, with a warning naming the key to use.
|
|
43
|
+
* The base url loses any trailing slash, because request paths add their own.
|
|
44
44
|
*/
|
|
45
45
|
function normaliseConfig(config) {
|
|
46
46
|
var settings = Object.assign({}, config);
|
|
47
|
-
Object.keys(
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
Object.keys(CONFIG_KEYS).forEach(function (key) {
|
|
48
|
+
var inside = CONFIG_KEYS[key];
|
|
49
|
+
if (!isEmpty(config[key])) {
|
|
50
|
+
settings[inside] = config[key];
|
|
51
|
+
return;
|
|
50
52
|
}
|
|
53
|
+
delete settings[inside];
|
|
54
|
+
Object.keys(RETIRED_CONFIG_NAMES).forEach(function (old) {
|
|
55
|
+
if (RETIRED_CONFIG_NAMES[old] !== key || isEmpty(config[old])) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
warnAlways('Apptics.init: ' + old + ' is now ' + key + '; rename it in your config'); // no i18n
|
|
59
|
+
if (isEmpty(settings[inside])) {
|
|
60
|
+
settings[inside] = config[old];
|
|
61
|
+
}
|
|
62
|
+
});
|
|
51
63
|
});
|
|
52
64
|
if (!isEmpty(settings.serviceUrl)) {
|
|
53
65
|
settings.serviceUrl = String(settings.serviceUrl).replace(/\/+$/, ''); // no i18n
|
|
@@ -73,21 +85,51 @@ const APPVERSION_PLACEHOLDERS = ['YOUR_APP_VERSION', 'YOUR_BUILD_OR_APP_VERSION'
|
|
|
73
85
|
function isAppVersionPlaceholder(version) {
|
|
74
86
|
return APPVERSION_PLACEHOLDERS.indexOf(version.toUpperCase()) !== -1;
|
|
75
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* The framework id this SDK reports to serviceUrl. The id built into the package is the one
|
|
90
|
+
* sdk-apptics.zoho.com issued at publish time, and localzoho servers don't know it: any
|
|
91
|
+
* localzoho serviceUrl reports 5970 instead, the id apptics.localzoho.com issued for 2.0.0-beta
|
|
92
|
+
* (Browser), so the same package also runs there.
|
|
93
|
+
*/
|
|
94
|
+
const LOCALZOHO_FRAMEWORK_ID = 5970;
|
|
95
|
+
function frameworkIdFor(serviceUrl) {
|
|
96
|
+
var host = serviceUrl;
|
|
97
|
+
try {
|
|
98
|
+
host = new URL(serviceUrl).hostname;
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
// not a url: judge the text as it is
|
|
102
|
+
}
|
|
103
|
+
return host.indexOf('localzoho') !== -1 ? LOCALZOHO_FRAMEWORK_ID : FRAMEWORK_ID; // no i18n
|
|
104
|
+
}
|
|
76
105
|
/** Which app this browser's stored data belongs to, before app/addversion has named it. */
|
|
77
106
|
function appKey(settings) {
|
|
78
107
|
return settings.serviceUrl + '|' + settings.identifier; // no i18n
|
|
79
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* The app version stored data belongs to, read before app/addversion replaces it: what tells a
|
|
111
|
+
* new release of the app from a reload. '' on a first visit.
|
|
112
|
+
*/
|
|
113
|
+
var previousAppVersion = ''; // no i18n
|
|
80
114
|
/**
|
|
81
115
|
* Data stored for another app on this origin is discarded before anything else reads it,
|
|
82
116
|
* including the stored app/addversion answer that would otherwise hand out that app's ids.
|
|
83
117
|
*/
|
|
84
118
|
function discardOtherAppData(settings) {
|
|
85
|
-
|
|
119
|
+
// which app it is, and which version, are in app_version_info (serviceUrl, identifier and
|
|
120
|
+
// appversion): no keys of their own. 2.0.0-beta's appkey and appversion are read this once
|
|
121
|
+
var info = user_defaults.item('app_version_info') || {}; // no i18n
|
|
122
|
+
var stored = !isEmpty(info.serviceUrl) && !isEmpty(info.identifier)
|
|
123
|
+
? appKey(info)
|
|
124
|
+
: user_defaults.item('appkey'); // no i18n
|
|
125
|
+
previousAppVersion = String((!isEmpty(info.appversion) ? info.appversion : user_defaults.item('appversion')) || ''); // no i18n
|
|
126
|
+
user_defaults.add('appkey', undefined); // no i18n
|
|
127
|
+
user_defaults.add('appversion', undefined); // no i18n
|
|
86
128
|
if (!isEmpty(stored) && stored !== appKey(settings)) {
|
|
87
129
|
Console.log('init: stored data belongs to another app, resetting'); // no i18n
|
|
88
130
|
clearStorage();
|
|
131
|
+
previousAppVersion = ''; // no i18n
|
|
89
132
|
}
|
|
90
|
-
user_defaults.add('appkey', appKey(settings)); // no i18n
|
|
91
133
|
}
|
|
92
134
|
/**
|
|
93
135
|
* Timing an app may tune in init(). Each has a range: a value outside it is ignored with a
|
|
@@ -140,18 +182,18 @@ function clearStorage() {
|
|
|
140
182
|
/**
|
|
141
183
|
* Starts the SDK. The config object is required: pass it directly, or let the console snippet
|
|
142
184
|
* supply it (auto-init reads window.appticssettings._defaultoptions and calls init with it).
|
|
143
|
-
* Returns true when the config has
|
|
185
|
+
* Returns true when the config has base_url, auth_key, app_domain and appversion and start-up has
|
|
144
186
|
* begun (see ready()), false when it was already running, the config is missing or incomplete, or
|
|
145
187
|
* there is no browser. Start-up calls app/addversion with those four, which answers with aaid, the
|
|
146
188
|
* portal and project ids and the rest; then device/add registers the browser, as in 1.x.
|
|
147
189
|
*/
|
|
148
190
|
function init(config) {
|
|
149
191
|
if (!config || typeof config !== 'object') { // no i18n
|
|
150
|
-
warnAlways('Apptics.init: a config object is required, e.g.
|
|
192
|
+
warnAlways('Apptics.init: a config object is required, e.g. Apptics.init({ base_url, auth_key, app_domain, appversion })'); // no i18n
|
|
151
193
|
return false;
|
|
152
194
|
}
|
|
153
195
|
if (_ZAP._initialised) {
|
|
154
|
-
Console.warn('Apptics.init: already initialised; call
|
|
196
|
+
Console.warn('Apptics.init: already initialised; call Apptics.reset() to start again'); // no i18n
|
|
155
197
|
return false;
|
|
156
198
|
}
|
|
157
199
|
if (!isBrowser()) {
|
|
@@ -160,7 +202,7 @@ function init(config) {
|
|
|
160
202
|
}
|
|
161
203
|
var settings = normaliseConfig(config);
|
|
162
204
|
var missing = REQUIRED_CONFIG.filter(function (key) {
|
|
163
|
-
return isEmpty(settings[key]);
|
|
205
|
+
return isEmpty(settings[CONFIG_KEYS[key] || key]);
|
|
164
206
|
});
|
|
165
207
|
if (missing.length > 0) {
|
|
166
208
|
warnAlways('Apptics.init: missing required config: ' + missing.join(', ')); // no i18n
|
|
@@ -174,16 +216,14 @@ function init(config) {
|
|
|
174
216
|
_ZAP._defaultoptions = settings;
|
|
175
217
|
// every request goes to serviceUrl; there is no other host to learn about
|
|
176
218
|
_ZAP._defaultoptions.base_domain = settings.serviceUrl;
|
|
219
|
+
// decided per init(), so a reset() or a page on another host never keeps the last one
|
|
220
|
+
_ZAP._frameworkID = frameworkIdFor(settings.serviceUrl);
|
|
177
221
|
// marks the SDK as started for the checks that need it; app/addversion replaces it with aaid
|
|
178
222
|
_ZAP._token = settings.identifier;
|
|
179
223
|
// console_log: the SDK's own activity in the browser console
|
|
180
224
|
if (!isEmpty(config.console_log)) {
|
|
181
225
|
_ZAP._config.debug = !!config.console_log;
|
|
182
226
|
}
|
|
183
|
-
// track_session: false records no sessions, as Android's automaticSessionsTrackingStatus
|
|
184
|
-
_ZAP._config.track_session = typeof config.track_session === 'boolean' ? config.track_session : AP_CONFIG.track_session; // no i18n
|
|
185
|
-
// show_logs: the app's own logger lines in the browser console, as Android's showLogs
|
|
186
|
-
_ZAP._config.show_logs = typeof config.show_logs === 'boolean' ? config.show_logs : AP_CONFIG.show_logs; // no i18n
|
|
187
227
|
if (typeof config.ignore_do_not_track === 'boolean') { // no i18n
|
|
188
228
|
_ZAP._config.ignore_do_not_track = config.ignore_do_not_track;
|
|
189
229
|
}
|
|
@@ -196,10 +236,14 @@ function init(config) {
|
|
|
196
236
|
applyDebugConfig(_ZAP._config.debug_api);
|
|
197
237
|
// what to call this device in the debug stream; see devicename in core/transport.ts
|
|
198
238
|
_ZAP._config.device_name = typeof config.device_name === 'string' ? config.device_name : AP_CONFIG.device_name; // no i18n
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
if (
|
|
202
|
-
|
|
239
|
+
// the SDK no longer reports its own failures to the Remote Logger page: only the lines an app
|
|
240
|
+
// logs with AppticsLogger go there
|
|
241
|
+
if (config.remote_log !== undefined) {
|
|
242
|
+
warnAlways('Apptics.init: remote_log is no longer read; the Remote Logger page shows the lines your app logs with AppticsLogger'); // no i18n
|
|
243
|
+
}
|
|
244
|
+
// AppticsLogger lines go to the Remote Logger page only, never to the browser console
|
|
245
|
+
if (config.show_logs !== undefined) {
|
|
246
|
+
warnAlways('Apptics.init: show_logs is no longer read; AppticsLogger lines are not printed to the browser console'); // no i18n
|
|
203
247
|
}
|
|
204
248
|
// automatic api tracking: the app's own requests, wrapped. Which hosts it records is
|
|
205
249
|
// configureApiTracking's to say; the two keys that once did it are refused out loud rather
|
|
@@ -207,22 +251,38 @@ function init(config) {
|
|
|
207
251
|
_ZAP._config.track_api = AP_CONFIG.track_api;
|
|
208
252
|
['track_api_hosts', 'track_api_exclude_hosts'].forEach(function (key) {
|
|
209
253
|
if (config[key] !== undefined) {
|
|
210
|
-
warnAlways('Apptics.init: ' + key + ' is no longer supported; use
|
|
254
|
+
warnAlways('Apptics.init: ' + key + ' is no longer supported; use AppticsApi.configure(new AppticsApi.ApiTrackingBuilder().' // no i18n
|
|
211
255
|
+ (key === 'track_api_hosts' ? 'allowOnlyDomains' : 'ignoreDomains') + '(...).build())'); // no i18n
|
|
212
256
|
}
|
|
213
257
|
});
|
|
258
|
+
// screen recording is set up in the console now, and arrives with getsdkconfig
|
|
259
|
+
['DC', 'quartz_workspace_key', 'quartz_department_key'].forEach(function (key) {
|
|
260
|
+
if (config[key] !== undefined) {
|
|
261
|
+
warnAlways('Apptics.init: ' + key + ' is no longer read; screen recording in the feedback form is set up from the Apptics console'); // no i18n
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
// sessions are what everything else is recorded in; an app that wants nothing tracked uses
|
|
265
|
+
// AppticsSettings.setTrackingStatus instead
|
|
266
|
+
if (config.track_session !== undefined) {
|
|
267
|
+
warnAlways('Apptics.init: track_session is no longer read; sessions are always recorded. To stop tracking, use AppticsSettings.setTrackingStatus(AppticsSettings.AP_TRACKING_STATUS.NO_TRACKING)'); // no i18n
|
|
268
|
+
}
|
|
214
269
|
if (typeof config.track_api === 'boolean') { // no i18n
|
|
215
270
|
_ZAP._config.track_api = config.track_api;
|
|
216
271
|
}
|
|
217
272
|
enableApiTracking(_ZAP._config.track_api);
|
|
218
|
-
// heatmap capture:
|
|
273
|
+
// heatmap capture: switched through the hook heatmap/track.ts sets
|
|
219
274
|
_ZAP._config.track_heatmap = typeof config.track_heatmap === 'boolean' // no i18n
|
|
220
275
|
? config.track_heatmap
|
|
221
276
|
: AP_CONFIG.track_heatmap;
|
|
222
|
-
hooks.
|
|
277
|
+
hooks.trackHeatmap(_ZAP._config.track_heatmap);
|
|
223
278
|
// automatic screen tracking, on unless the config says false: switched on by start(), once a
|
|
224
279
|
// screen view can be stored
|
|
225
280
|
_ZAP._config.track_screen = typeof config.track_screen === 'boolean' ? config.track_screen : AP_CONFIG.track_screen; // no i18n
|
|
281
|
+
_ZAP._config.screen_routes = screenRouteRules(config.screen_routes);
|
|
282
|
+
// a theme in the config wins; without one, what AppticsFeedback.setFeedbackTheme set stays
|
|
283
|
+
if (config.feedback_theme === 'light' || config.feedback_theme === 'dark' || config.feedback_theme === 'auto') { // no i18n
|
|
284
|
+
_ZAP._config.feedback_theme = config.feedback_theme;
|
|
285
|
+
}
|
|
226
286
|
applyIntervals(config);
|
|
227
287
|
lastConfig = config;
|
|
228
288
|
_ZAP._initialised = true;
|
|
@@ -248,6 +308,23 @@ function init(config) {
|
|
|
248
308
|
if (myGeneration !== generation) {
|
|
249
309
|
return false;
|
|
250
310
|
}
|
|
311
|
+
if (!registered && appVersionFailedForNetwork()) {
|
|
312
|
+
// a first visit with no network: start once it is back, keeping what the app
|
|
313
|
+
// tracks until then queued, rather than giving up for the rest of the page
|
|
314
|
+
warnAlways('Apptics.init: offline, so app/addversion is tried again when the browser is back online; calls made until then are kept'); // no i18n
|
|
315
|
+
return registerWhenOnline(myGeneration).then(function (ok) {
|
|
316
|
+
if (myGeneration !== generation) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
if (!ok) {
|
|
320
|
+
_ZAP._initialised = false;
|
|
321
|
+
_ZAP._token = ''; // no i18n
|
|
322
|
+
_ZAP._pending = [];
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
return start(config, myGeneration);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
251
328
|
if (!registered) {
|
|
252
329
|
warnAlways('Apptics.init: app/addversion did not return the app ids, not starting'); // no i18n
|
|
253
330
|
_ZAP._initialised = false;
|
|
@@ -263,42 +340,137 @@ function init(config) {
|
|
|
263
340
|
});
|
|
264
341
|
return true;
|
|
265
342
|
}
|
|
343
|
+
/** How often a start-up waiting on the network tries app/addversion again, besides on `online`. */
|
|
344
|
+
const OFFLINE_RETRY_MS = 60 * 1000;
|
|
345
|
+
/**
|
|
346
|
+
* app/addversion again once the network is back: on the `online` event, and every minute for a
|
|
347
|
+
* network that came back without one. Resolves true once registered, false when the server
|
|
348
|
+
* refuses it or a reset()/new init() took over.
|
|
349
|
+
*/
|
|
350
|
+
function registerWhenOnline(myGeneration) {
|
|
351
|
+
return new Promise(function (resolve) {
|
|
352
|
+
var timer = null;
|
|
353
|
+
var trying = false;
|
|
354
|
+
function done(ok) {
|
|
355
|
+
window.removeEventListener('online', attempt); // no i18n
|
|
356
|
+
if (timer !== null)
|
|
357
|
+
clearInterval(timer);
|
|
358
|
+
resolve(ok);
|
|
359
|
+
}
|
|
360
|
+
function attempt() {
|
|
361
|
+
if (myGeneration !== generation) {
|
|
362
|
+
done(false);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (trying || navigator.onLine === false) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
trying = true;
|
|
369
|
+
registerAppVersion().then(function (registered) {
|
|
370
|
+
trying = false;
|
|
371
|
+
if (registered) {
|
|
372
|
+
done(true);
|
|
373
|
+
}
|
|
374
|
+
else if (!appVersionFailedForNetwork()) {
|
|
375
|
+
warnAlways('Apptics.init: app/addversion did not return the app ids, not starting'); // no i18n
|
|
376
|
+
done(false);
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
window.addEventListener('online', attempt); // no i18n
|
|
381
|
+
timer = setInterval(attempt, OFFLINE_RETRY_MS);
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* screen_routes as init() keeps it: each entry checked, an exact path cleaned up, a regex given as
|
|
386
|
+
* a string compiled. An entry that cannot be used is left out, and said, rather than matching
|
|
387
|
+
* something its author did not mean.
|
|
388
|
+
*/
|
|
389
|
+
function screenRouteRules(routes) {
|
|
390
|
+
if (!Array.isArray(routes)) {
|
|
391
|
+
return [];
|
|
392
|
+
}
|
|
393
|
+
var out = [];
|
|
394
|
+
routes.forEach(function (route) {
|
|
395
|
+
if (typeof route === 'string') { // no i18n
|
|
396
|
+
if (route.trim() !== '') { // no i18n
|
|
397
|
+
out.push({ kind: 'pattern', pattern: route.trim() }); // no i18n
|
|
398
|
+
}
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
var rule = route && typeof route === 'object' ? route : null; // no i18n
|
|
402
|
+
var name = rule && typeof rule.name === 'string' ? rule.name.trim() : ''; // no i18n
|
|
403
|
+
if (rule && name !== '' && typeof rule.equals === 'string' && rule.equals.trim() !== '') { // no i18n
|
|
404
|
+
out.push({ kind: 'equals', path: routePath(rule.equals.trim()), name: name }); // no i18n
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (rule && name !== '' && rule.regex !== undefined) {
|
|
408
|
+
var regex = null;
|
|
409
|
+
if (rule.regex instanceof RegExp) {
|
|
410
|
+
regex = rule.regex;
|
|
411
|
+
}
|
|
412
|
+
else if (typeof rule.regex === 'string' && rule.regex !== '') { // no i18n
|
|
413
|
+
try {
|
|
414
|
+
regex = new RegExp(rule.regex);
|
|
415
|
+
}
|
|
416
|
+
catch (err) {
|
|
417
|
+
regex = null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (regex) {
|
|
421
|
+
out.push({ kind: 'regex', regex: regex, name: name }); // no i18n
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
warnAlways('Apptics.init: screen_routes entry ' + safeJson(route) + ' is left out: give a route pattern, { equals, name } or { regex, name }'); // no i18n
|
|
426
|
+
});
|
|
427
|
+
return out;
|
|
428
|
+
}
|
|
429
|
+
/** An entry as the warning shows it: a RegExp as its source, which JSON.stringify would hide. */
|
|
430
|
+
function safeJson(value) {
|
|
431
|
+
try {
|
|
432
|
+
return JSON.stringify(value, function (_key, one) { return one instanceof RegExp ? String(one) : one; }) || String(value);
|
|
433
|
+
}
|
|
434
|
+
catch (err) {
|
|
435
|
+
return String(value);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
266
438
|
/** Resolves true once start-up has finished, false if init() refused or storage is unusable. */
|
|
267
439
|
function ready() {
|
|
268
440
|
return _ZAP._readyPromise || Promise.resolve(false);
|
|
269
441
|
}
|
|
270
442
|
function start(config, myGeneration) {
|
|
443
|
+
// this tab's lock, before any screen view: it is how other tabs tell this one is still open
|
|
444
|
+
holdTabLock();
|
|
271
445
|
// app/addversion named the app; data stored for another one was discarded before it ran
|
|
272
446
|
_ZAP._token = String(_ZAP._defaultoptions.aaid);
|
|
273
|
-
user_defaults.add('token', _ZAP._token); // no i18n
|
|
274
447
|
// last known server settings (getupdates) apply before anything is tracked
|
|
275
448
|
restoreServerSettings();
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
var uuid = user_defaults.item('uuid'); // no i18n
|
|
280
|
-
if (isEmpty(uuid)) {
|
|
281
|
-
uuid = getNewUUID();
|
|
282
|
-
user_defaults.add('uuid', uuid); // no i18n
|
|
283
|
-
}
|
|
284
|
-
_ZAP._uuid = uuid;
|
|
285
|
-
var stored_appversion = user_defaults.item('appversion'); // no i18n
|
|
286
|
-
if (isEmpty(stored_appversion)) {
|
|
287
|
-
user_defaults.add('appversion', _ZAP._defaultoptions.appversion); // no i18n
|
|
288
|
-
stored_appversion = _ZAP._defaultoptions.appversion;
|
|
289
|
-
}
|
|
290
|
-
var appVersionChanged = stored_appversion != _ZAP._defaultoptions.appversion;
|
|
449
|
+
// a new release of the app, against the version the stored data was for (see
|
|
450
|
+
// discardOtherAppData): a first visit has none, and is no change
|
|
451
|
+
var appVersionChanged = previousAppVersion !== '' && previousAppVersion != _ZAP._defaultoptions.appversion; // no i18n
|
|
291
452
|
_ZAP._ignoreDnt = _ZAP._config.ignore_do_not_track;
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
//
|
|
296
|
-
|
|
453
|
+
// the visitor's own stored choice, not getTrackingStatus(): that answers NO_TRACKING while Do
|
|
454
|
+
// Not Track is on, and storing it made one such visit switch tracking off for good
|
|
455
|
+
tracking_preference.update_status(tracking_preference.opt_in_status());
|
|
456
|
+
// the uuid and device info, and a registration on a first visit, under a lock shared with the
|
|
457
|
+
// site's other tabs (see prepareDevice)
|
|
458
|
+
return prepareDevice().then(function () {
|
|
459
|
+
if (myGeneration !== generation) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
return startTracking(appVersionChanged, myGeneration);
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
/** The rest of start-up, once the device is set up. */
|
|
466
|
+
function startTracking(appVersionChanged, myGeneration) {
|
|
467
|
+
// no getsdkconfig here, straight after app/addversion: it is asked for once device/add has
|
|
468
|
+
// succeeded (registerDeviceWithApptics), then every getupdates_interval. A returning visit
|
|
469
|
+
// starts from the settings saved by the last one (restoreServerSettings, in start())
|
|
297
470
|
if (appVersionChanged) {
|
|
298
471
|
_ZAP._device_info.appversionid = ''; // no i18n
|
|
299
472
|
updateDeviceWithApptics(_ZAP._device_info).then(function (result) {
|
|
300
473
|
if (isSuccess(result)) {
|
|
301
|
-
user_defaults.add('appversion', _ZAP._defaultoptions.appversion); // no i18n
|
|
302
474
|
Console.log('init: appversion updated to ' + _ZAP._defaultoptions.appversion); // no i18n
|
|
303
475
|
}
|
|
304
476
|
}).catch(function (err) {
|
|
@@ -349,7 +521,7 @@ function reset() {
|
|
|
349
521
|
enableApiTracking(false);
|
|
350
522
|
enableScreenTracking(false);
|
|
351
523
|
clearAppVersion();
|
|
352
|
-
hooks.
|
|
524
|
+
hooks.trackHeatmap(false);
|
|
353
525
|
hooks.resetHeatmap();
|
|
354
526
|
hooks.resetRemoteConfig();
|
|
355
527
|
clearStorage();
|
|
@@ -365,7 +537,7 @@ function reset() {
|
|
|
365
537
|
_ZAP._apid = ''; // no i18n
|
|
366
538
|
_ZAP._mapid = ''; // no i18n
|
|
367
539
|
_ZAP._sending = false;
|
|
368
|
-
Console.log('
|
|
540
|
+
Console.log('Apptics.reset()'); // no i18n
|
|
369
541
|
// start again with the config init() was called with
|
|
370
542
|
if (lastConfig) {
|
|
371
543
|
init(lastConfig);
|
|
@@ -374,7 +546,20 @@ function reset() {
|
|
|
374
546
|
function isActive() {
|
|
375
547
|
return _ZAP._ready;
|
|
376
548
|
}
|
|
377
|
-
|
|
549
|
+
/**
|
|
550
|
+
* A click-tracking attribute, in either spelling: `apeventaction`, or `data-apeventaction`, which
|
|
551
|
+
* is valid HTML and what React and TypeScript accept without declaring the attribute.
|
|
552
|
+
*/
|
|
553
|
+
function trackingAttribute(el, name) {
|
|
554
|
+
var value = el.getAttribute(name);
|
|
555
|
+
return value !== null && value !== '' ? value : el.getAttribute('data-' + name); // no i18n
|
|
556
|
+
}
|
|
557
|
+
/** `[name]` and `[data-name]`, empty values left out, for closest(). */
|
|
558
|
+
function trackingSelector(name) {
|
|
559
|
+
return '[' + name + ']:not([' + name + '=""]),[data-' + name + ']:not([data-' + name + '=""])'; // no i18n
|
|
560
|
+
}
|
|
561
|
+
// Declarative click tracking: <el apeventaction="name" apeventprops='{"k":"v"}'> inside <el apgroupaction="group">,
|
|
562
|
+
// or the same attributes with a data- prefix
|
|
378
563
|
function onDocumentClick(event) {
|
|
379
564
|
if (!window.appticsReadyStatus || !isActive()) {
|
|
380
565
|
return;
|
|
@@ -386,15 +571,15 @@ function onDocumentClick(event) {
|
|
|
386
571
|
if (!start) {
|
|
387
572
|
return;
|
|
388
573
|
}
|
|
389
|
-
var targetElem = start.closest('
|
|
574
|
+
var targetElem = start.closest(trackingSelector('apeventaction')); // no i18n
|
|
390
575
|
if (!targetElem) {
|
|
391
576
|
return;
|
|
392
577
|
}
|
|
393
|
-
var eventName = targetElem
|
|
394
|
-
var groupElem = targetElem.closest('
|
|
395
|
-
var groupName = (groupElem && groupElem
|
|
578
|
+
var eventName = trackingAttribute(targetElem, 'apeventaction') || ''; // no i18n
|
|
579
|
+
var groupElem = targetElem.closest(trackingSelector('apgroupaction')); // no i18n
|
|
580
|
+
var groupName = (groupElem && trackingAttribute(groupElem, 'apgroupaction')) || AP_CONFIG.default_group_name; // no i18n
|
|
396
581
|
var eventProps = {};
|
|
397
|
-
var rawProps = targetElem
|
|
582
|
+
var rawProps = trackingAttribute(targetElem, 'apeventprops'); // no i18n
|
|
398
583
|
if (!isEmpty(rawProps)) {
|
|
399
584
|
try {
|
|
400
585
|
eventProps = JSON.parse(rawProps);
|
|
@@ -500,8 +685,8 @@ function attachListeners() {
|
|
|
500
685
|
// until it has them: register before flushing, and flush once that has landed
|
|
501
686
|
if (needsDevice()) {
|
|
502
687
|
Console.log('back online: registering this device before sending'); // no i18n
|
|
503
|
-
|
|
504
|
-
|
|
688
|
+
// the same locked path as start-up, so two tabs coming back online register it once
|
|
689
|
+
prepareDevice().then(deviceReady).then(function () {
|
|
505
690
|
if (!isActive())
|
|
506
691
|
return;
|
|
507
692
|
flush();
|
|
@@ -523,12 +708,22 @@ function attachListeners() {
|
|
|
523
708
|
trackError(event);
|
|
524
709
|
}
|
|
525
710
|
});
|
|
711
|
+
// in the capture phase: a <script>, <img> or <link> that fails to load fires `error` on the
|
|
712
|
+
// element, and it does not bubble, so a bubbling listener never hears of it. One listener
|
|
713
|
+
// hears both kinds, the window's own errors included, so none is counted twice
|
|
526
714
|
window.addEventListener('error', function (event) {
|
|
527
|
-
if (isActive()
|
|
528
|
-
|
|
715
|
+
if (!isActive() || !_ZAP._isGlobalErrorTracking) {
|
|
716
|
+
return;
|
|
529
717
|
}
|
|
530
|
-
|
|
718
|
+
var target = event.target;
|
|
719
|
+
if (target && target !== window && typeof target.tagName === 'string') { // no i18n
|
|
720
|
+
// named by describeTarget: Event "error" on <script src="...">
|
|
721
|
+
trackError({ type: 'error', reason: event }); // no i18n
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
trackError(event);
|
|
725
|
+
}, true);
|
|
531
726
|
window.addEventListener('click', onDocumentClick, true); // no i18n
|
|
532
727
|
}
|
|
533
728
|
|
|
534
|
-
export { init, ready, reset };
|
|
729
|
+
export { init, ready, reset, screenRouteRules };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The ISO code of a time zone's country, '' for one with none (UTC) or unknown. */
|
|
2
|
+
export declare function timeZoneCountryCode(timeZone: string): string;
|
|
3
|
+
/** The country: the user's, else the time zone's. '' when neither says. */
|
|
4
|
+
export declare function deviceCountry(): string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
import { _ZAP } from '../core/state.js';
|
|
3
|
+
import { getTimeZone } from '../core/env.js';
|
|
4
|
+
import { TZ_COUNTRIES } from './tz-countries.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The country of this device, for remote config's `country` criteria, by its English name as the
|
|
8
|
+
* console lists it ("India").
|
|
9
|
+
*
|
|
10
|
+
* The one AppticsUser.setUser registered comes first. Otherwise it is the country of the
|
|
11
|
+
* browser's time zone, which is the device clock's: Asia/Kolkata (or Chrome's Asia/Calcutta) is
|
|
12
|
+
* India, whatever language the browser is in. A browser has no other source short of asking for
|
|
13
|
+
* the user's location, which is a permission prompt. A zone shared by several countries is the
|
|
14
|
+
* one tzdata names for it.
|
|
15
|
+
*/
|
|
16
|
+
/** Zone -> ISO code, unpacked on first use. */
|
|
17
|
+
var byZone = null;
|
|
18
|
+
function zones() {
|
|
19
|
+
if (byZone !== null) {
|
|
20
|
+
return byZone;
|
|
21
|
+
}
|
|
22
|
+
var out = {};
|
|
23
|
+
TZ_COUNTRIES.split(';').forEach(function (entry) {
|
|
24
|
+
var colon = entry.indexOf(':'); // no i18n
|
|
25
|
+
var code = entry.slice(0, colon);
|
|
26
|
+
entry.slice(colon + 1).split('|').forEach(function (group) {
|
|
27
|
+
// "Area/City,City", or bare names with no area ("Cuba,Egypt")
|
|
28
|
+
var slash = group.indexOf('/'); // no i18n
|
|
29
|
+
var area = slash === -1 ? '' : group.slice(0, slash + 1); // no i18n
|
|
30
|
+
group.slice(area.length).split(',').forEach(function (city) {
|
|
31
|
+
out[area + city] = code;
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
byZone = out;
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/** The ISO code of a time zone's country, '' for one with none (UTC) or unknown. */
|
|
39
|
+
function timeZoneCountryCode(timeZone) {
|
|
40
|
+
var all = zones();
|
|
41
|
+
return Object.prototype.hasOwnProperty.call(all, timeZone) ? all[timeZone] : ''; // no i18n
|
|
42
|
+
}
|
|
43
|
+
/** IN -> India, in English; the code itself where the browser has no region names. */
|
|
44
|
+
function regionName(code) {
|
|
45
|
+
try {
|
|
46
|
+
var names = new Intl.DisplayNames(['en'], { type: 'region' }); // no i18n
|
|
47
|
+
return names.of(code) || code;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return code;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** The country: the user's, else the time zone's. '' when neither says. */
|
|
54
|
+
function deviceCountry() {
|
|
55
|
+
var named = String(_ZAP._user_info.country || '').trim(); // no i18n
|
|
56
|
+
if (named !== '') {
|
|
57
|
+
return named;
|
|
58
|
+
}
|
|
59
|
+
var timeZone = ''; // no i18n
|
|
60
|
+
try {
|
|
61
|
+
timeZone = String(getTimeZone() || ''); // no i18n
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
timeZone = ''; // no i18n
|
|
65
|
+
}
|
|
66
|
+
var code = timeZoneCountryCode(timeZone);
|
|
67
|
+
return code === '' ? '' : regionName(code); // no i18n
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { deviceCountry, timeZoneCountryCode };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/** The
|
|
2
|
-
export declare function
|
|
1
|
+
/** The values set for a condition, by its name; empty when none are. */
|
|
2
|
+
export declare function customConditionValues(conditionname: string): string[];
|
|
3
3
|
/**
|
|
4
|
-
* Sets what this device is for a custom
|
|
5
|
-
* the stored rules
|
|
6
|
-
* fetch.
|
|
4
|
+
* Sets what this device is for a custom condition, by its name, as comma separated values; an
|
|
5
|
+
* empty value removes it. Re-applies the stored rules once storage is ready, so the next read sees
|
|
6
|
+
* the new result without a fetch.
|
|
7
7
|
*/
|
|
8
|
-
export declare function setCustomConditionValue(
|
|
9
|
-
/** reset(): forgets the values set on this page
|
|
8
|
+
export declare function setCustomConditionValue(conditionname: string, value: string | number | boolean | null | undefined): void;
|
|
9
|
+
/** reset(): forgets the values set on this page. */
|
|
10
10
|
export declare function clearCustomConditionValues(): void;
|