Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased
Capture requests ("show me the issue"): when a workflow, an AI agent or a teammate asks the customer for a screenshot or a screen recording in a conversation, the customer answers from the card in the widget and the SDK captures the page. On desktop Chrome and Edge the screenshot is taken from the tab itself after one "Share this tab" confirmation (exact pixels); everywhere else, and when sharing is declined, the page is rendered in the browser. Screen recordings use the browser's screen sharing (MP4 where supported, otherwise WebM with its duration written in so players can seek), with the microphone if the project allows it; while recording, everything a screenshot masks is blurred on the page. When screen sharing doesn't start, and on phones and tablets, the customer can record the page instead (a page recording the dashboard plays like a session replay). Password, one-time-code and card fields, the `gl-mask` / `gl-block` / `rr-mask` / `rr-block` classes, the `setReplayOptions` privacy options, payment frames and the project's masked elements are left out. The capture bar is a small dark pill the customer can drag; all its texts come from the widget's translations.
Logs requests: workflows, AI agents and teammates can collect the page's console logs, network logs, custom data, environment data and events in the background, the same data a bug report carries. They arrive over the SDK's websocket and are uploaded once, gzipped.
New: `Gleap.setCaptureEnabled(enabled)` (off: the widget only offers a file upload) and `Gleap.setRemoteLogCollectionEnabled(enabled)` (off: logs requests are answered as unsupported and captures are sent without logs).
The classic screen recording now stops cleanly when the customer clicks the browser's "Stop sharing" and is no longer uploaded twice. The browser bundle grows by about 34 KB gzipped.

## 19.0.1
Fixed: the SDK's injected styles made the host page slower. The product tour rule `.gleap-tour-popover-navigation-btns button + button` ends in a bare `button`, so Chrome restyled sibling elements across the whole page whenever a node was inserted anywhere, not only inside Gleap's UI (on a page with ~19k nodes, ~2,000 extra elements per popover open or close). The tour buttons are now spaced with `gap` on their flex container, which looks the same; when the Previous button is hidden, the Next button no longer keeps a stray 4px margin.

Expand Down
16 changes: 15 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,19 @@ module.exports = {
],
plugins: [
["@babel/plugin-transform-class-properties"]
],
overrides: [
{
// The capture request modules only run where the rest of the bundle does: its untranspiled
// dependencies (modern-screenshot, rrweb) already need ES2020 (?. and ??). Compiled for those
// browsers they stay smaller (no ES5 classes, arrows, spread or destructuring helpers).
test: /[\\/]src[\\/](GleapCapture(Api|Manager|Recorder|Screenshot|Settings|Tasks|UI|Veil)|GleapWebmDuration)\.js$/,
presets: [
[
"@babel/env",
{ targets: { chrome: "80", edge: "80", firefox: "74", safari: "13.1", ios: "13.4", samsung: "13" } }
]
]
}
]
};
};
13 changes: 13 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,19 @@ export namespace Gleap {
}[];
errorHandler?: (error: Error) => void;
}): void;
/**
* Enables or disables screenshots and screen recordings that teammates, AI agents or workflows
* ask the customer for in the widget (default: enabled). While disabled, the widget offers
* uploading a file instead. Can be called before initialize.
*/
function setCaptureEnabled(enabled: boolean): void;
/**
* Enables or disables sending logs when teammates, AI agents or workflows request them, on their
* own or along with a screenshot or screen recording (default: enabled). Only data a bug report
* carries is sent: console and network logs, custom data, environment data and events. Can be
* called before initialize.
*/
function setRemoteLogCollectionEnabled(enabled: boolean): void;
}
export default Gleap;

Expand Down
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"@floating-ui/dom": "^1.7.5",
"@rrweb/packer": "^2.1.0",
"@rrweb/record": "^2.1.0",
"modern-screenshot": "4.7.0",
"unique-selector": "^0.5.0"
}
}
31 changes: 31 additions & 0 deletions src/Gleap.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import GleapAgentToolManager from './GleapAgentToolManager';
import GleapAiChatbarManager from './GleapAiChatbarManager';
import GleapAudioManager from './GleapAudioManager';
import GleapBannerManager from './GleapBannerManager';
import GleapCaptureManager from './GleapCaptureManager';
import { registerGleapChecklist } from './GleapChecklist';
import GleapClickListener from './GleapClickListener';
import GleapConfigManager from './GleapConfigManager';
Expand Down Expand Up @@ -279,6 +280,11 @@ class Gleap {
// Check for URL params.
Gleap.checkForUrlParams();

// A capture request that was in progress before this page load.
try {
GleapCaptureManager.getInstance().resumeFromStorage();
} catch (exp) {}

// Notify event.
GleapEventManager.notifyEvent('initialized');
});
Expand Down Expand Up @@ -354,6 +360,9 @@ class Gleap {
* @returns
*/
static destroy() {
try {
GleapCaptureManager.getInstance().destroy();
} catch (exp) {}
GleapReplayRecorder.getInstance().stop();
GleapStreamedEvent.getInstance().stop();
GleapFrameManager.getInstance().destroy();
Expand Down Expand Up @@ -541,6 +550,27 @@ class Gleap {
GleapReplayRecorder.getInstance().setOptions(options);
}

/**
* Enables or disables screenshots and screen recordings that teammates, AI agents or workflows
* ask the customer for in the widget (default: enabled). While disabled, the widget offers
* uploading a file instead. Can be called before initialize.
* @param {boolean} enabled
*/
static setCaptureEnabled(enabled) {
GleapCaptureManager.getInstance().setCaptureEnabled(enabled);
}

/**
* Enables or disables sending logs when teammates, AI agents or workflows request them, on their
* own or along with a screenshot or screen recording (default: enabled). Only data a bug report
* carries is sent (console and network logs, custom data, environment data, events). Can be
* called before initialize.
* @param {boolean} enabled
*/
static setRemoteLogCollectionEnabled(enabled) {
GleapCaptureManager.getInstance().setRemoteLogCollectionEnabled(enabled);
}

/**
* Closes any open Gleap dialogs.
* @param {boolean} resetRoutes
Expand Down Expand Up @@ -1667,6 +1697,7 @@ export {
GleapAiChatbarManager,
GleapAudioManager,
GleapBannerManager,
GleapCaptureManager,
GleapClickListener,
GleapConfigManager,
GleapConsoleLogManager,
Expand Down
5 changes: 5 additions & 0 deletions src/GleapBannerManager.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Gleap, { GleapFrameManager } from './Gleap';
import { isOutboundActionBlocked } from './GleapCaptureSettings';
import { bootstrapGleapFrame } from './GleapHelper';

export default class GleapBannerManager {
Expand Down Expand Up @@ -65,6 +66,10 @@ export default class GleapBannerManager {
if (data.name === 'banner-close') {
this.removeBannerUI();
}
// While the widget is hidden for a capture (screenshot or recording), actions open nothing.
if (isOutboundActionBlocked(data.name)) {
return;
}
if (data.name === 'start-conversation') {
Gleap.startBot(data.data?.botId);
}
Expand Down
Loading
Loading