@zoho_apptics/apptics-js-sdk 2.0.0-beta → 2.0.0-beta.2
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 +191 -21
- package/README.md +519 -333
- 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-C6m1W7jo.min.js +3 -0
- package/dist/chunks/lifecycle-C6m1W7jo.min.js.map +1 -0
- package/dist/chunks/send-CgUO82ne.min.js +3 -0
- package/dist/chunks/send-CgUO82ne.min.js.map +1 -0
- package/dist/cjs/core/attempts.js +1 -1
- package/dist/cjs/core/batch.js +2 -2
- package/dist/cjs/core/consent.d.ts +18 -4
- package/dist/cjs/core/consent.js +31 -15
- package/dist/cjs/core/constants.d.ts +57 -27
- package/dist/cjs/core/constants.js +52 -33
- 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.d.ts +0 -3
- package/dist/cjs/core/env.js +1 -9
- 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 +7 -4
- package/dist/cjs/core/hooks.js +3 -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 +9 -6
- package/dist/cjs/core/state.js +3 -5
- package/dist/cjs/core/storage.d.ts +20 -5
- package/dist/cjs/core/storage.js +115 -20
- 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 +30 -18
- package/dist/cjs/core/utils.js +1 -1
- package/dist/cjs/core/validate.js +2 -2
- package/dist/cjs/device/appversion.d.ts +10 -6
- package/dist/cjs/device/appversion.js +38 -3
- package/dist/cjs/device/index.d.ts +28 -2
- package/dist/cjs/device/index.js +312 -44
- 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 +12 -3
- package/dist/cjs/engagement/session.d.ts +29 -3
- package/dist/cjs/engagement/session.js +253 -26
- package/dist/cjs/engagement/track.d.ts +4 -4
- package/dist/cjs/engagement/track.js +58 -30
- package/dist/cjs/errors/send.js +2 -2
- package/dist/cjs/errors/track.d.ts +2 -1
- package/dist/cjs/errors/track.js +49 -7
- package/dist/cjs/feedback/controls.d.ts +12 -0
- package/dist/cjs/feedback/controls.js +104 -25
- package/dist/cjs/feedback/index.d.ts +8 -7
- package/dist/cjs/feedback/index.js +32 -13
- package/dist/cjs/feedback/logs.d.ts +13 -11
- package/dist/cjs/feedback/logs.js +57 -28
- package/dist/cjs/feedback/quartz.d.ts +18 -0
- package/dist/cjs/feedback/quartz.js +105 -0
- package/dist/cjs/feedback/send.d.ts +5 -2
- package/dist/cjs/feedback/send.js +30 -28
- 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 +20 -12
- package/dist/cjs/feedback/ui.d.ts +21 -6
- package/dist/cjs/feedback/ui.js +283 -70
- package/dist/cjs/heatmap/send.d.ts +2 -0
- package/dist/cjs/heatmap/send.js +3 -5
- package/dist/cjs/heatmap/track.d.ts +1 -1
- package/dist/cjs/heatmap/track.js +87 -16
- package/dist/cjs/index.d.ts +16 -63
- package/dist/cjs/index.js +144 -95
- package/dist/cjs/lifecycle.d.ts +21 -3
- package/dist/cjs/lifecycle.js +353 -89
- 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 +16 -9
- package/dist/cjs/remoteconfig/fetch.js +120 -39
- package/dist/cjs/remoteconfig/index.d.ts +19 -8
- package/dist/cjs/remoteconfig/index.js +81 -39
- package/dist/cjs/remoteconfig/store.d.ts +15 -7
- package/dist/cjs/remoteconfig/store.js +68 -35
- package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/cjs/remoteconfig/tz-countries.js +13 -0
- package/dist/{esm/core → cjs/remotelog}/callsite.d.ts +11 -4
- package/dist/cjs/{core → remotelog}/callsite.js +30 -7
- 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 +31 -59
- package/dist/cjs/remotelog/send.js +11 -11
- package/dist/cjs/remotelogger/index.d.ts +12 -0
- package/dist/cjs/remotelogger/index.js +18 -0
- package/dist/cjs/scheduler.d.ts +3 -1
- package/dist/cjs/scheduler.js +25 -22
- package/dist/cjs/types.d.ts +208 -90
- package/dist/cjs/user/index.js +16 -7
- package/dist/esm/core/attempts.js +1 -1
- package/dist/esm/core/batch.js +2 -2
- package/dist/esm/core/consent.d.ts +18 -4
- package/dist/esm/core/consent.js +32 -17
- package/dist/esm/core/constants.d.ts +57 -27
- package/dist/esm/core/constants.js +51 -33
- 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.d.ts +0 -3
- package/dist/esm/core/env.js +2 -9
- 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 +7 -4
- package/dist/esm/core/hooks.js +3 -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 +9 -6
- package/dist/esm/core/state.js +3 -5
- package/dist/esm/core/storage.d.ts +20 -5
- package/dist/esm/core/storage.js +113 -21
- 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 +30 -19
- package/dist/esm/core/utils.js +1 -1
- package/dist/esm/core/validate.js +2 -2
- package/dist/esm/device/appversion.d.ts +10 -6
- package/dist/esm/device/appversion.js +37 -4
- package/dist/esm/device/index.d.ts +28 -2
- package/dist/esm/device/index.js +313 -49
- 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 +12 -3
- package/dist/esm/engagement/session.d.ts +29 -3
- package/dist/esm/engagement/session.js +251 -30
- package/dist/esm/engagement/track.d.ts +4 -4
- package/dist/esm/engagement/track.js +65 -37
- package/dist/esm/errors/send.js +2 -2
- package/dist/esm/errors/track.d.ts +2 -1
- package/dist/esm/errors/track.js +49 -7
- package/dist/esm/feedback/controls.d.ts +12 -0
- package/dist/esm/feedback/controls.js +103 -26
- package/dist/esm/feedback/index.d.ts +8 -7
- package/dist/esm/feedback/index.js +34 -13
- package/dist/esm/feedback/logs.d.ts +13 -11
- package/dist/esm/feedback/logs.js +59 -30
- package/dist/esm/feedback/quartz.d.ts +18 -0
- package/dist/esm/feedback/quartz.js +99 -0
- package/dist/esm/feedback/send.d.ts +5 -2
- package/dist/esm/feedback/send.js +31 -31
- 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 +20 -12
- package/dist/esm/feedback/ui.d.ts +21 -6
- package/dist/esm/feedback/ui.js +283 -71
- package/dist/esm/heatmap/send.d.ts +2 -0
- package/dist/esm/heatmap/send.js +3 -5
- package/dist/esm/heatmap/track.d.ts +1 -1
- package/dist/esm/heatmap/track.js +87 -16
- package/dist/esm/index.d.ts +16 -63
- package/dist/esm/index.js +148 -83
- package/dist/esm/lifecycle.d.ts +21 -3
- package/dist/esm/lifecycle.js +359 -98
- 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 +16 -9
- package/dist/esm/remoteconfig/fetch.js +120 -39
- package/dist/esm/remoteconfig/index.d.ts +19 -8
- package/dist/esm/remoteconfig/index.js +82 -40
- package/dist/esm/remoteconfig/store.d.ts +15 -7
- package/dist/esm/remoteconfig/store.js +68 -36
- package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/esm/remoteconfig/tz-countries.js +11 -0
- package/dist/{cjs/core → esm/remotelog}/callsite.d.ts +11 -4
- package/dist/esm/{core → remotelog}/callsite.js +30 -8
- 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 +33 -61
- package/dist/esm/remotelog/send.js +13 -13
- package/dist/esm/remotelogger/index.d.ts +12 -0
- package/dist/esm/remotelogger/index.js +13 -0
- package/dist/esm/scheduler.d.ts +3 -1
- package/dist/esm/scheduler.js +26 -24
- package/dist/esm/types.d.ts +208 -90
- package/dist/esm/user/index.js +18 -8
- package/dist/feedback.esm.min.js +2 -2
- package/dist/feedback.esm.min.js.map +1 -1
- package/dist/remoteconfig.esm.min.js +3 -0
- package/dist/remoteconfig.esm.min.js.map +1 -0
- package/dist/remotelogger.esm.min.js +3 -0
- package/dist/remotelogger.esm.min.js.map +1 -0
- package/package.json +16 -17
- 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/auto-init.d.ts +0 -8
- package/dist/cjs/auto-init.js +0 -32
- 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/auto-init.d.ts +0 -8
- package/dist/esm/auto-init.js +0 -29
- 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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Properties } from '../types.js';
|
|
2
2
|
export declare function trackError(errorEvent: any, jsonObj?: Properties): void;
|
|
3
|
-
|
|
3
|
+
/** AppticsError.setErrorTracking: uncaught errors on or off, as the `track_error` config sets it. */
|
|
4
|
+
export declare function setErrorTracking(status?: boolean): void;
|
|
4
5
|
export declare function extractMethodNameFromStackTrace(stackTrace: string): string;
|
package/dist/esm/errors/track.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
2
|
import { AP_CONSTANTS } from '../core/constants.js';
|
|
3
3
|
import { _ZAP } from '../core/state.js';
|
|
4
4
|
import { Console } from '../core/logger.js';
|
|
@@ -36,19 +36,59 @@ function stackOf(errorEvent) {
|
|
|
36
36
|
}
|
|
37
37
|
/** Said in place of a stack when there is none, so `message` is never sent empty. */
|
|
38
38
|
const NO_STACK = 'no stack available'; // no i18n
|
|
39
|
+
/** The element an event came from, as `<script src="…">`, so a failed load says what failed. */
|
|
40
|
+
function describeTarget(target) {
|
|
41
|
+
var el = target;
|
|
42
|
+
if (!el || typeof el.tagName !== 'string') { // no i18n
|
|
43
|
+
return ''; // no i18n
|
|
44
|
+
}
|
|
45
|
+
var tag = el.tagName.toLowerCase();
|
|
46
|
+
var url = el.currentSrc || el.src || el.href || ''; // no i18n
|
|
47
|
+
return ' on <' + tag + (url ? (el.href && !el.src ? ' href="' : ' src="') + url + '"' : '') + '>'; // no i18n
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* What was thrown or rejected, as text an issue can be named by. An Error reads as itself. A
|
|
51
|
+
* promise rejected with an Event - what a failed script or image load hands over - used to be
|
|
52
|
+
* recorded as "[object Event]"; it is named by its type and where it came from instead. Anything
|
|
53
|
+
* else that is an object is shown as its JSON, cut short.
|
|
54
|
+
*/
|
|
55
|
+
function describeThrown(thrown) {
|
|
56
|
+
if (thrown === null || thrown === undefined) {
|
|
57
|
+
return ''; // no i18n
|
|
58
|
+
}
|
|
59
|
+
if (typeof thrown !== 'object') { // no i18n
|
|
60
|
+
return String(thrown);
|
|
61
|
+
}
|
|
62
|
+
if (thrown instanceof Error || typeof thrown.message === 'string' && typeof thrown.name === 'string') { // no i18n
|
|
63
|
+
return String(thrown);
|
|
64
|
+
}
|
|
65
|
+
if (typeof Event !== 'undefined' && thrown instanceof Event) { // no i18n
|
|
66
|
+
return 'Event "' + thrown.type + '"' + describeTarget(thrown.target); // no i18n
|
|
67
|
+
}
|
|
68
|
+
var text = String(thrown);
|
|
69
|
+
if (text !== '[object Object]') { // no i18n
|
|
70
|
+
return text;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
return JSON.stringify(thrown).slice(0, 300);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
return text;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
39
79
|
function trackError(errorEvent, jsonObj) {
|
|
40
80
|
if (!canTrackErrors('trackError')) { // no i18n
|
|
41
81
|
return;
|
|
42
82
|
}
|
|
43
83
|
if (isEmpty(errorEvent)) {
|
|
44
|
-
Console.warn('
|
|
84
|
+
Console.warn('AppticsError.trackError: Invalid error'); // no i18n
|
|
45
85
|
return;
|
|
46
86
|
}
|
|
47
87
|
var _jsonObj = validateJSON(jsonObj);
|
|
48
88
|
var stack = stackOf(errorEvent);
|
|
49
89
|
var methodName = extractMethodNameFromStackTrace(stack) || "";
|
|
50
90
|
var issuetype = errorEvent.type || "";
|
|
51
|
-
var thrown = errorEvent.reason || errorEvent.error || errorEvent.message || "";
|
|
91
|
+
var thrown = describeThrown(errorEvent.reason || errorEvent.error || errorEvent.message || "");
|
|
52
92
|
// "Error: x at handler", or just "Error: x" when the stack names no method. issuename is
|
|
53
93
|
// required too, so something that carried no message at all is still named rather than blank
|
|
54
94
|
var described = !isEmpty(String(thrown)) ? String(thrown) : (!isEmpty(issuetype) ? String(issuetype) : 'Unknown error'); // no i18n
|
|
@@ -74,11 +114,13 @@ function trackError(errorEvent, jsonObj) {
|
|
|
74
114
|
commitPendingSession();
|
|
75
115
|
noteDebugActivity();
|
|
76
116
|
error_transactions.add(errorData);
|
|
77
|
-
Console.log('
|
|
117
|
+
Console.log('AppticsError.trackError(\'' + issuetype + '\',\'' + message + '\',' + JSON.stringify(_jsonObj || {}) + ')'); // no i18n
|
|
78
118
|
Console.dir(errorData);
|
|
79
119
|
}
|
|
80
|
-
|
|
81
|
-
|
|
120
|
+
/** AppticsError.setErrorTracking: uncaught errors on or off, as the `track_error` config sets it. */
|
|
121
|
+
function setErrorTracking(status) {
|
|
122
|
+
_ZAP._config.track_error = typeof status === "boolean" ? status : true; // no i18n
|
|
123
|
+
Console.log('automatic error tracking: ' + (_ZAP._config.track_error ? 'on' : 'off')); // no i18n
|
|
82
124
|
}
|
|
83
125
|
function extractMethodNameFromStackTrace(stackTrace) {
|
|
84
126
|
let methodName = ''; // no i18n
|
|
@@ -120,4 +162,4 @@ function extractMethodNameFromStackTrace(stackTrace) {
|
|
|
120
162
|
return methodName;
|
|
121
163
|
}
|
|
122
164
|
|
|
123
|
-
export {
|
|
165
|
+
export { extractMethodNameFromStackTrace, setErrorTracking, trackError };
|
|
@@ -12,6 +12,12 @@ export declare const logChoice: {
|
|
|
12
12
|
includeLog?: boolean;
|
|
13
13
|
includeDyninfo?: boolean;
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Who a sendFeedback() report, made without the form, is attributed to: nobody when `anonymous`,
|
|
17
|
+
* else the user AppticsUser.setUser set (or the active registered one, status 1). Returns a function
|
|
18
|
+
* that puts back the choice that was there, so a form left open keeps its own.
|
|
19
|
+
*/
|
|
20
|
+
export declare function chooseUserForSend(anonymous: boolean): () => void;
|
|
15
21
|
/**
|
|
16
22
|
* The "User" dropdown above the description. It lists Anonymous plus every registered user, and
|
|
17
23
|
* starts on the active one (status 1) unless the caller asked for anonymous.
|
|
@@ -29,3 +35,9 @@ export declare function wireLogControls(modal: HTMLElement, opts: Dict): void;
|
|
|
29
35
|
* kept inside the viewport.
|
|
30
36
|
*/
|
|
31
37
|
export declare function wireDrag(box: HTMLElement): void;
|
|
38
|
+
/**
|
|
39
|
+
* Lets the recording timer be dragged anywhere on the page. A press that moves it is a drag, and
|
|
40
|
+
* does not also stop the recording, as a plain click on it does. Call before the click listener
|
|
41
|
+
* is added, so a drag's click is stopped ahead of it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function wireTimerDrag(timer: HTMLElement): void;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
2
|
import { Console } from '../core/logger.js';
|
|
3
3
|
import { hooks } from '../core/hooks.js';
|
|
4
4
|
import { user_defaults } from '../core/storage.js';
|
|
5
5
|
import { isEmpty } from '../core/utils.js';
|
|
6
|
+
import { _ZAP } from '../core/state.js';
|
|
6
7
|
import { hasLogLines, hasDiagnostics, logText, diagnosticsText } from './logs.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -23,6 +24,34 @@ function resetUserChoice() {
|
|
|
23
24
|
userChoice.userid = ''; // no i18n
|
|
24
25
|
userChoice.groupid = ''; // no i18n
|
|
25
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Who a sendFeedback() report, made without the form, is attributed to: nobody when `anonymous`,
|
|
29
|
+
* else the user AppticsUser.setUser set (or the active registered one, status 1). Returns a function
|
|
30
|
+
* that puts back the choice that was there, so a form left open keeps its own.
|
|
31
|
+
*/
|
|
32
|
+
function chooseUserForSend(anonymous) {
|
|
33
|
+
var before = { anonymous: userChoice.anonymous, userid: userChoice.userid, groupid: userChoice.groupid };
|
|
34
|
+
resetUserChoice();
|
|
35
|
+
if (!anonymous) {
|
|
36
|
+
// the user setUser set on this page, else the active one of those registered before
|
|
37
|
+
var active = !isEmpty(_ZAP._user_info.userid) ? _ZAP._user_info : null;
|
|
38
|
+
storedUsers().forEach(function (user) {
|
|
39
|
+
if (!active && user && user.status == 1 && !isEmpty(user.userid)) {
|
|
40
|
+
active = user;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
if (active) {
|
|
44
|
+
userChoice.anonymous = false;
|
|
45
|
+
userChoice.userid = String(active.userid);
|
|
46
|
+
userChoice.groupid = String(active.groupid || ''); // no i18n
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return function restore() {
|
|
50
|
+
userChoice.anonymous = before.anonymous;
|
|
51
|
+
userChoice.userid = before.userid;
|
|
52
|
+
userChoice.groupid = before.groupid;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
26
55
|
/** Every distinct registered user, by the address the picker shows. */
|
|
27
56
|
function storedUsers() {
|
|
28
57
|
var users = user_defaults.item('users'); // no i18n
|
|
@@ -236,45 +265,93 @@ function wireDrag(box) {
|
|
|
236
265
|
if (!header) {
|
|
237
266
|
return;
|
|
238
267
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
268
|
+
makeDraggable(box, header, function (target) {
|
|
269
|
+
// the close button is not a drag handle
|
|
270
|
+
return !!target.closest('.zasdk-close'); // no i18n
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
/** Where the recording timer was last dragged to, so the next recording's timer starts there. */
|
|
274
|
+
var timerSpot = null;
|
|
275
|
+
/**
|
|
276
|
+
* Lets the recording timer be dragged anywhere on the page. A press that moves it is a drag, and
|
|
277
|
+
* does not also stop the recording, as a plain click on it does. Call before the click listener
|
|
278
|
+
* is added, so a drag's click is stopped ahead of it.
|
|
279
|
+
*/
|
|
280
|
+
function wireTimerDrag(timer) {
|
|
281
|
+
if (timerSpot) {
|
|
282
|
+
placeAt(timer, timerSpot.left, timerSpot.top);
|
|
283
|
+
}
|
|
284
|
+
makeDraggable(timer, timer, undefined, function (left, top) {
|
|
285
|
+
timerSpot = { left: left, top: top };
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/** Puts a fixed box at left/top, inside the viewport. */
|
|
289
|
+
function placeAt(box, left, top) {
|
|
290
|
+
box.style.right = 'auto'; // no i18n
|
|
291
|
+
box.style.bottom = 'auto'; // no i18n
|
|
292
|
+
box.style.left = Math.max(0, Math.min(left, window.innerWidth - box.offsetWidth)) + 'px'; // no i18n
|
|
293
|
+
box.style.top = Math.max(0, Math.min(top, window.innerHeight - box.offsetHeight)) + 'px'; // no i18n
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Moves `box` with the mouse or a finger pressed on `handle`. `skip` says which presses are not a
|
|
297
|
+
* drag; `moved` hears where the box ended up. A click that ends a drag goes no further.
|
|
298
|
+
*/
|
|
299
|
+
function makeDraggable(box, handle, skip, moved) {
|
|
300
|
+
var startX = 0, startY = 0, boxLeft = 0, boxTop = 0, dragging = false, dragged = false;
|
|
301
|
+
handle.addEventListener('pointerdown', function (event) {
|
|
302
|
+
if (event.button !== 0 || (skip && skip(event.target))) {
|
|
303
|
+
return;
|
|
250
304
|
}
|
|
305
|
+
var rect = box.getBoundingClientRect();
|
|
251
306
|
dragging = true;
|
|
307
|
+
dragged = false;
|
|
252
308
|
startX = event.clientX;
|
|
253
309
|
startY = event.clientY;
|
|
254
|
-
boxLeft =
|
|
255
|
-
boxTop =
|
|
256
|
-
|
|
310
|
+
boxLeft = rect.left;
|
|
311
|
+
boxTop = rect.top;
|
|
312
|
+
handle.style.cursor = 'move'; // no i18n
|
|
313
|
+
// the moves and the release come to the handle however far the pointer goes, so nothing
|
|
314
|
+
// is left listening on the document once the box is gone
|
|
315
|
+
try {
|
|
316
|
+
handle.setPointerCapture(event.pointerId);
|
|
317
|
+
}
|
|
318
|
+
catch (err) { /* a pointer already released */ }
|
|
257
319
|
event.preventDefault();
|
|
258
320
|
});
|
|
259
|
-
|
|
321
|
+
handle.addEventListener('pointermove', function (event) {
|
|
260
322
|
if (!dragging) {
|
|
261
323
|
return;
|
|
262
324
|
}
|
|
263
|
-
var
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
box.style.top = Math.max(0, Math.min(top, window.innerHeight - box.offsetHeight)) + 'px'; // no i18n
|
|
267
|
-
});
|
|
268
|
-
document.addEventListener('mouseup', function () {
|
|
269
|
-
if (dragging) {
|
|
270
|
-
dragging = false;
|
|
271
|
-
header.style.cursor = 'grab'; // no i18n
|
|
325
|
+
var dx = event.clientX - startX, dy = event.clientY - startY;
|
|
326
|
+
if (!dragged && Math.abs(dx) < 4 && Math.abs(dy) < 4) {
|
|
327
|
+
return; // a press that wobbles is still a click
|
|
272
328
|
}
|
|
329
|
+
dragged = true;
|
|
330
|
+
placeAt(box, boxLeft + dx, boxTop + dy);
|
|
273
331
|
});
|
|
332
|
+
function stop() {
|
|
333
|
+
if (!dragging) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
dragging = false;
|
|
337
|
+
handle.style.cursor = ''; // no i18n
|
|
338
|
+
if (dragged && moved) {
|
|
339
|
+
moved(parseInt(box.style.left, 10), parseInt(box.style.top, 10));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
handle.addEventListener('pointerup', stop); // no i18n
|
|
343
|
+
handle.addEventListener('pointercancel', stop); // no i18n
|
|
344
|
+
box.addEventListener('click', function (event) {
|
|
345
|
+
if (dragged) {
|
|
346
|
+
dragged = false;
|
|
347
|
+
event.stopImmediatePropagation();
|
|
348
|
+
event.preventDefault();
|
|
349
|
+
}
|
|
350
|
+
}, true);
|
|
274
351
|
}
|
|
275
352
|
// core/transport asks for the picked user when it builds the feedback request's parameters
|
|
276
353
|
hooks.feedbackUser = function () {
|
|
277
354
|
return userChoice.anonymous || isEmpty(userChoice.userid) ? null : userChoice;
|
|
278
355
|
};
|
|
279
356
|
|
|
280
|
-
export { logChoice, userChoice, wireDrag, wireLogControls, wireUserPicker };
|
|
357
|
+
export { chooseUserForSend, logChoice, userChoice, wireDrag, wireLogControls, wireTimerDrag, wireUserPicker };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { feedbackClose as feedbackCloseImpl } from './ui.js';
|
|
2
1
|
import type { AppticsFeedbackApi } from '../types.js';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
export type { FeedbackOpenOptions, SendFeedbackOptions } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Android's AppticsFeedback: the form, sending feedback without it, and the context recorded for
|
|
5
|
+
* the next one. Every feedback call, addFeedbackLog and addDiagnosticsInfo included, is here and
|
|
6
|
+
* only here: the main entry has no AppticsFeedback.
|
|
7
|
+
*/
|
|
8
|
+
export declare const AppticsFeedback: AppticsFeedbackApi;
|
|
9
|
+
export default AppticsFeedback;
|
|
@@ -1,30 +1,51 @@
|
|
|
1
|
-
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
-
import { guard } from '../core/guard.js';
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
import { forward, guard } from '../core/guard.js';
|
|
3
|
+
import { AP_FEEDBACK_TYPE } from '../core/constants.js';
|
|
3
4
|
import { Console } from '../core/logger.js';
|
|
4
5
|
import { ready } from '../lifecycle.js';
|
|
5
|
-
import {
|
|
6
|
+
import { setFeedbackTheme, sendFeedback, feedbackFormClose, feedbackFormOpen } from './ui.js';
|
|
7
|
+
import { addDiagnosticsInfo, addFeedbackLog } from './logs.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Optional feedback modal, shipped as its own entry point:
|
|
9
|
-
* import {
|
|
10
|
-
*
|
|
11
|
+
* import { AppticsFeedback } from '@zoho_apptics/apptics-js-sdk/feedback';
|
|
12
|
+
* AppticsFeedback.feedbackFormOpen();
|
|
11
13
|
* Apps that never import it don't pay for the modal or its markup.
|
|
12
14
|
* The <script> build includes it, so snippet users are unaffected.
|
|
13
15
|
*/
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
+
const feedbackFormOpenGuarded = guard('AppticsFeedback.feedbackFormOpen', feedbackFormOpen); // no i18n
|
|
17
|
+
const feedbackFormCloseGuarded = guard('AppticsFeedback.feedbackFormClose', feedbackFormClose); // no i18n
|
|
18
|
+
const addFeedbackLogGuarded = guard('AppticsFeedback.addFeedbackLog', addFeedbackLog); // no i18n
|
|
19
|
+
const addDiagnosticsInfoGuarded = guard('AppticsFeedback.addDiagnosticsInfo', addDiagnosticsInfo); // no i18n
|
|
20
|
+
const setFeedbackThemeGuarded = guard('AppticsFeedback.setFeedbackTheme', setFeedbackTheme); // no i18n
|
|
16
21
|
/** Resolves once the feedback is sent; rejects when it wasn't (SDK not started, offline, refused). */
|
|
17
|
-
const
|
|
22
|
+
const sendFeedbackGuarded = guard('AppticsFeedback.sendFeedback', function (...args) {
|
|
18
23
|
return ready().then(function (started) {
|
|
19
24
|
if (!started) {
|
|
20
|
-
throw new Error('
|
|
25
|
+
throw new Error('AppticsFeedback.sendFeedback: not sent, the SDK has not started; call Apptics.init() first'); // no i18n
|
|
21
26
|
}
|
|
22
|
-
return sendFeedback
|
|
27
|
+
return sendFeedback(...args);
|
|
23
28
|
}).catch(function (err) {
|
|
24
|
-
Console.error('
|
|
29
|
+
Console.error('AppticsFeedback.sendFeedback failed:', err); // no i18n
|
|
25
30
|
throw err;
|
|
26
31
|
});
|
|
27
32
|
});
|
|
28
|
-
|
|
33
|
+
/* each call a function of its own, with the parameter names the console shows (see forward) */
|
|
34
|
+
/**
|
|
35
|
+
* Android's AppticsFeedback: the form, sending feedback without it, and the context recorded for
|
|
36
|
+
* the next one. Every feedback call, addFeedbackLog and addDiagnosticsInfo included, is here and
|
|
37
|
+
* only here: the main entry has no AppticsFeedback.
|
|
38
|
+
*/
|
|
39
|
+
const AppticsFeedback = {
|
|
40
|
+
/** The feedback types: BUG, FEEDBACK, HELP, REPORT. */
|
|
41
|
+
AP_FEEDBACK_TYPE: AP_FEEDBACK_TYPE,
|
|
42
|
+
feedbackFormOpen: function feedbackFormOpen(options) { return forward(feedbackFormOpenGuarded, arguments); },
|
|
43
|
+
feedbackFormClose: function feedbackFormClose() { return forward(feedbackFormCloseGuarded, arguments); },
|
|
44
|
+
sendFeedback: function sendFeedback(options) { return forward(sendFeedbackGuarded, arguments); },
|
|
45
|
+
addFeedbackLog: function addFeedbackLog(message) { return forward(addFeedbackLogGuarded, arguments); },
|
|
46
|
+
addDiagnosticsInfo: function addDiagnosticsInfo(heading, key, value) { return forward(addDiagnosticsInfoGuarded, arguments); },
|
|
47
|
+
/** The form's theme from now on, and of a form open now: 'light', 'dark' or 'auto'. */
|
|
48
|
+
setFeedbackTheme: function setFeedbackTheme(theme) { return forward(setFeedbackThemeGuarded, arguments); },
|
|
49
|
+
};
|
|
29
50
|
|
|
30
|
-
export {
|
|
51
|
+
export { AppticsFeedback, AppticsFeedback as default };
|
|
@@ -15,26 +15,28 @@ export declare function trimStoredLogs(): Promise<void>;
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function addFeedbackLog(message: string): void;
|
|
17
17
|
/**
|
|
18
|
-
* Records a diagnostics
|
|
19
|
-
*
|
|
18
|
+
* Records a diagnostics entry, `value` under `key` in the `heading` block of dyninfo.txt. All three
|
|
19
|
+
* are required: an entry without a value says nothing, so it is refused and the console says why.
|
|
20
|
+
* A value of 0 or false is a value.
|
|
20
21
|
*/
|
|
21
|
-
export declare function addDiagnosticsInfo(heading: string, key: string, value
|
|
22
|
+
export declare function addDiagnosticsInfo(heading: string, key: string, value: unknown): void;
|
|
22
23
|
/** Removes every stored entry. */
|
|
23
24
|
export declare function clearFeedbackLogs(): Promise<void>;
|
|
24
25
|
/** Removes the entries a submission carried, by the ids the rendered files reported. */
|
|
25
|
-
export declare function
|
|
26
|
+
export declare function feedbacklog_transactions_remove(sentIds: string[]): Promise<void>;
|
|
26
27
|
/** feedbacklog.txt from the stored log lines, or null when there are none. */
|
|
27
28
|
export declare function toLogFile(): Promise<RenderedFile | null>;
|
|
28
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* The log lines for showing in the modal before sending, each time in the visitor's local zone.
|
|
31
|
+
* The file that is sent (toLogFile) keeps the ISO 8601 UTC stamps, so the server and anything
|
|
32
|
+
* that parses it are unaffected.
|
|
33
|
+
*/
|
|
29
34
|
export declare function logText(): Promise<string>;
|
|
30
|
-
/** The diagnostics entries as dyninfo.txt
|
|
35
|
+
/** The diagnostics entries as dyninfo.txt carries them. */
|
|
31
36
|
export declare function diagnosticsText(): Promise<string>;
|
|
32
37
|
/** True when any log line is waiting, so the modal knows whether to offer the toggle. */
|
|
33
38
|
export declare function hasLogLines(): Promise<boolean>;
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
* `deviceInfo`. Returns null only when there is nothing at all to put in it.
|
|
37
|
-
*/
|
|
38
|
-
export declare function toDyninfoFile(deviceInfo: string | null): Promise<RenderedFile | null>;
|
|
39
|
+
/** dyninfo.txt: the stored diagnostics entries. Returns null when there are none. */
|
|
40
|
+
export declare function toDyninfoFile(): Promise<RenderedFile | null>;
|
|
39
41
|
/** True when any diagnostics entry is waiting, so a submission knows to send dyninfo unasked. */
|
|
40
42
|
export declare function hasDiagnostics(): Promise<boolean>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
-
import { Console } from '../core/logger.js';
|
|
3
|
-
import {
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
import { warnAlways, Console } from '../core/logger.js';
|
|
3
|
+
import { FEEDBACK_LOG, FEEDBACK_DIAGNOSTICS } from '../core/db.js';
|
|
4
|
+
import { feedbacklog_transactions } from '../core/storage.js';
|
|
4
5
|
import { isExpired } from '../core/state.js';
|
|
5
6
|
import { nowMs } from '../core/utils.js';
|
|
6
7
|
|
|
@@ -24,18 +25,19 @@ const MAX_LOG_FILE_SIZE = 2 * 1024 * 1024;
|
|
|
24
25
|
const TRIM_DELAY_MS = 2000;
|
|
25
26
|
const LOG_FILE_NAME = 'feedbacklog.txt'; // no i18n
|
|
26
27
|
const DYNINFO_FILE_NAME = 'dyninfo.txt'; // no i18n
|
|
27
|
-
|
|
28
|
-
const
|
|
28
|
+
// the types the entries are stored under (2.0.0-beta and 1.x said log and diagnostics)
|
|
29
|
+
const LOG = FEEDBACK_LOG;
|
|
30
|
+
const DIAGNOSTICS = FEEDBACK_DIAGNOSTICS;
|
|
29
31
|
let trimScheduled = false;
|
|
30
32
|
/** Drops the oldest entries once the store is over MAX_ENTRIES. */
|
|
31
33
|
function trimStoredLogs() {
|
|
32
|
-
return
|
|
34
|
+
return feedbacklog_transactions.all().then(function (items) {
|
|
33
35
|
const excess = items.length - MAX_ENTRIES;
|
|
34
36
|
if (excess <= 0) {
|
|
35
37
|
return undefined;
|
|
36
38
|
}
|
|
37
39
|
Console.warn('apptics: dropping ' + excess + ' oldest feedback log entries (cap is ' + MAX_ENTRIES + ')'); // no i18n
|
|
38
|
-
return
|
|
40
|
+
return feedbacklog_transactions.remove(items.slice(0, excess));
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
43
|
/** One trim per burst of adds, so a chatty app pays for one pass over the store, not one per line. */
|
|
@@ -50,7 +52,7 @@ function scheduleTrim() {
|
|
|
50
52
|
}, TRIM_DELAY_MS);
|
|
51
53
|
}
|
|
52
54
|
function store(item) {
|
|
53
|
-
|
|
55
|
+
feedbacklog_transactions.add(item);
|
|
54
56
|
scheduleTrim();
|
|
55
57
|
}
|
|
56
58
|
function truncate(text) {
|
|
@@ -70,11 +72,30 @@ function addFeedbackLog(message) {
|
|
|
70
72
|
* Records a diagnostics key/value under a heading, sent inside dyninfo.txt.
|
|
71
73
|
* Entries sharing a heading are grouped together in the file.
|
|
72
74
|
*/
|
|
75
|
+
/** Messages already printed, so a call repeated in a loop says so once. */
|
|
76
|
+
const refusedSaid = {};
|
|
77
|
+
function refuse(message) {
|
|
78
|
+
if (!refusedSaid[message]) {
|
|
79
|
+
refusedSaid[message] = true;
|
|
80
|
+
warnAlways('AppticsFeedback.addDiagnosticsInfo: ' + message + ', so the entry is not recorded'); // no i18n
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Records a diagnostics entry, `value` under `key` in the `heading` block of dyninfo.txt. All three
|
|
85
|
+
* are required: an entry without a value says nothing, so it is refused and the console says why.
|
|
86
|
+
* A value of 0 or false is a value.
|
|
87
|
+
*/
|
|
73
88
|
function addDiagnosticsInfo(heading, key, value) {
|
|
74
89
|
if (typeof heading !== 'string' || heading.length === 0) { // no i18n
|
|
90
|
+
refuse('a heading is required');
|
|
75
91
|
return;
|
|
76
92
|
}
|
|
77
93
|
if (typeof key !== 'string' || key.length === 0) { // no i18n
|
|
94
|
+
refuse('a key is required');
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (value === undefined || value === null || value === '') { // no i18n
|
|
98
|
+
refuse('a value is required for "' + heading + '" / "' + key + '"');
|
|
78
99
|
return;
|
|
79
100
|
}
|
|
80
101
|
store({
|
|
@@ -82,16 +103,16 @@ function addDiagnosticsInfo(heading, key, value) {
|
|
|
82
103
|
happenedat: nowMs(),
|
|
83
104
|
heading: heading,
|
|
84
105
|
key: key,
|
|
85
|
-
value: truncate(String(value
|
|
106
|
+
value: truncate(String(value)),
|
|
86
107
|
});
|
|
87
108
|
}
|
|
88
109
|
/** Removes the entries a submission carried, by the ids the rendered files reported. */
|
|
89
|
-
function
|
|
90
|
-
return
|
|
110
|
+
function feedbacklog_transactions_remove(sentIds) {
|
|
111
|
+
return feedbacklog_transactions.remove(sentIds.map(function (id) { return { id: id }; }));
|
|
91
112
|
}
|
|
92
113
|
/** Entries of one type, oldest first, skipping any that have passed batch_request_timeout. */
|
|
93
114
|
function entriesOfType(type) {
|
|
94
|
-
return
|
|
115
|
+
return feedbacklog_transactions.all().then(function (items) {
|
|
95
116
|
return items.filter(function (item) {
|
|
96
117
|
return item.type === type && !isExpired(item.happenedat);
|
|
97
118
|
});
|
|
@@ -145,11 +166,29 @@ function toLogFile() {
|
|
|
145
166
|
return asFile(LOG_FILE_NAME, renderLogLines(items), items);
|
|
146
167
|
});
|
|
147
168
|
}
|
|
148
|
-
/**
|
|
169
|
+
/** `16 Oct 2026, 11:53:48 PM`: a log line's time in the visitor's own zone, for the viewer. */
|
|
170
|
+
function readableStamp(item) {
|
|
171
|
+
var iso = stamp(item);
|
|
172
|
+
var d = new Date(iso);
|
|
173
|
+
if (isNaN(d.getTime())) {
|
|
174
|
+
return iso;
|
|
175
|
+
}
|
|
176
|
+
return d.toLocaleDateString(undefined, { day: '2-digit', month: 'short', year: 'numeric' }) + ', ' + // no i18n
|
|
177
|
+
d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit' }); // no i18n
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The log lines for showing in the modal before sending, each time in the visitor's local zone.
|
|
181
|
+
* The file that is sent (toLogFile) keeps the ISO 8601 UTC stamps, so the server and anything
|
|
182
|
+
* that parses it are unaffected.
|
|
183
|
+
*/
|
|
149
184
|
function logText() {
|
|
150
|
-
return entriesOfType(LOG).then(
|
|
185
|
+
return entriesOfType(LOG).then(function (items) {
|
|
186
|
+
return items.map(function (item) {
|
|
187
|
+
return '[' + readableStamp(item) + '] ' + item.message; // no i18n
|
|
188
|
+
}).join('\n'); // no i18n
|
|
189
|
+
});
|
|
151
190
|
}
|
|
152
|
-
/** The diagnostics entries as dyninfo.txt
|
|
191
|
+
/** The diagnostics entries as dyninfo.txt carries them. */
|
|
153
192
|
function diagnosticsText() {
|
|
154
193
|
return entriesOfType(DIAGNOSTICS).then(groupDiagnostics);
|
|
155
194
|
}
|
|
@@ -159,23 +198,13 @@ function hasLogLines() {
|
|
|
159
198
|
return items.length > 0;
|
|
160
199
|
});
|
|
161
200
|
}
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
* `deviceInfo`. Returns null only when there is nothing at all to put in it.
|
|
165
|
-
*/
|
|
166
|
-
function toDyninfoFile(deviceInfo) {
|
|
201
|
+
/** dyninfo.txt: the stored diagnostics entries. Returns null when there are none. */
|
|
202
|
+
function toDyninfoFile() {
|
|
167
203
|
return entriesOfType(DIAGNOSTICS).then(function (items) {
|
|
168
|
-
|
|
169
|
-
if (items.length > 0) {
|
|
170
|
-
blocks.push(groupDiagnostics(items));
|
|
171
|
-
}
|
|
172
|
-
if (deviceInfo) {
|
|
173
|
-
blocks.push('[Device Info]\n' + deviceInfo); // no i18n
|
|
174
|
-
}
|
|
175
|
-
if (blocks.length === 0) {
|
|
204
|
+
if (items.length === 0) {
|
|
176
205
|
return null;
|
|
177
206
|
}
|
|
178
|
-
return asFile(DYNINFO_FILE_NAME,
|
|
207
|
+
return asFile(DYNINFO_FILE_NAME, groupDiagnostics(items), items);
|
|
179
208
|
});
|
|
180
209
|
}
|
|
181
210
|
/** True when any diagnostics entry is waiting, so a submission knows to send dyninfo unasked. */
|
|
@@ -185,4 +214,4 @@ function hasDiagnostics() {
|
|
|
185
214
|
});
|
|
186
215
|
}
|
|
187
216
|
|
|
188
|
-
export { DYNINFO_FILE_NAME, LOG_FILE_NAME, MAX_LOG_FILE_SIZE, addDiagnosticsInfo, addFeedbackLog, diagnosticsText, hasDiagnostics, hasLogLines, logText,
|
|
217
|
+
export { DYNINFO_FILE_NAME, LOG_FILE_NAME, MAX_LOG_FILE_SIZE, addDiagnosticsInfo, addFeedbackLog, diagnosticsText, feedbacklog_transactions_remove, hasDiagnostics, hasLogLines, logText, toDyninfoFile, toLogFile, trimStoredLogs };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** quartz_domain as a recording host: zoho.com → https://quartz.zoho.com. '' when it isn't a domain. */
|
|
2
|
+
export declare function recordingDomain(domain: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* The Quartz script for an app whose getsdkconfig answer carries no quartz_cdn_url, chosen by
|
|
5
|
+
* the serviceUrl: a localzoho server's apps load it from Zoho's local CDN, every other app from
|
|
6
|
+
* the public one.
|
|
7
|
+
*/
|
|
8
|
+
export declare function defaultQuartzScriptUrl(serviceUrl: string): string;
|
|
9
|
+
/** The script to load: quartz_cdn_url when getsdkconfig gave one, else the CDN the serviceUrl points to. */
|
|
10
|
+
export declare function quartzScriptSource(cdnUrl: string, serviceUrl: string): string;
|
|
11
|
+
/** The url to load, or '' when it isn't an https url on a Zoho host. */
|
|
12
|
+
export declare function quartzScriptUrl(url: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Makes Quartz available: resolves true once it is on the page, false when it can't be (no url,
|
|
15
|
+
* a url that isn't allowed, or a script that failed to load). Adds the script once; every caller
|
|
16
|
+
* waits on the same load, and a failed one may be tried again on the next open.
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadQuartz(url: string): Promise<boolean>;
|