10 Commits

Author SHA1 Message Date
b49707a727 1.2.4
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-04-20 20:18:07 +00:00
2ea29cffbb fix(build): Update build script and async function signature 2025-04-20 20:18:07 +00:00
8e18898542 1.2.3
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-04-20 20:09:42 +00:00
7e7608c63a fix(core): Update dependency versions and adjust UI CSS for fab and combox elements 2025-04-20 20:09:42 +00:00
4cf9f3cd77 1.2.2
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-01-26 20:48:32 +01:00
1d799532e9 fix(sio-recorder): solve full checkouts for consistent recordings 2025-01-26 20:48:32 +01:00
39e94a11f8 1.2.1
Some checks failed
Default (tags) / security (push) Failing after 2s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-01-25 13:38:06 +01:00
9f3cdde7eb fix(sio-recorder): Enhance styling and positioning for rrweb player elements in SioRecorder component. 2025-01-25 13:38:06 +01:00
8d18e60d22 1.2.0
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-01-25 04:21:30 +01:00
8603b7876f feat(elements): Added sio-recorder element for recording and replaying sessions 2025-01-25 04:21:30 +01:00
9 changed files with 5116 additions and 2148 deletions

View File

@@ -1,5 +1,39 @@
# Changelog
## 2025-04-20 - 1.2.4 - fix(build)
Update build script and async function signature
- Added '--skiplibcheck' flag to the tsbuild command in package.json
- Changed startRecording return type to Promise<void> in ts_web/elements/sio-recorder.ts for proper async handling
## 2025-04-20 - 1.2.3 - fix(core)
Update dependency versions and adjust UI CSS for fab and combox elements
- Bumped @design.estate/dees-catalog, dees-domtools, dees-element, and @social.io/interfaces to newer versions in package.json
- Updated devDependencies to latest compatible versions
- Adjusted CSS positioning in sio-fab and sio-combox for improved layout
## 2025-01-26 - 1.2.2 - fix(sio-recorder)
Fixed the recording loop and ensured it stops correctly
- Added an await for domtoolsPromise in startRecording method.
- Introduced a while loop to manage the recording status effectively.
- Added delay and stop function call within the loop to manage record sessions.
## 2025-01-25 - 1.2.1 - fix(sio-recorder)
Enhance styling and positioning for rrweb player elements in SioRecorder component.
- Fixed positioning and added styling for the replayer mouse and iframe in the SioRecorder component.
- Ensured compatibility with cross-origin iframes.
## 2025-01-25 - 1.2.0 - feat(elements)
Added sio-recorder element for recording and replaying sessions
- Introduced a new 'sio-recorder' custom element that allows for recording and replaying DOM events.
- Integrated rrweb and rrweb-player dependencies for session recording and playback.
- Updated import/export in ts_web/elements/index.ts to include sio-recorder.
- Fixed assetbroker URL in the html index.html file.
## 2024-12-27 - 1.1.0 - feat(ci)
Add Gitea workflows for CI/CD process.

View File

@@ -8,9 +8,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--Lets load standard fonts-->
<link rel="preconnect" href="https://" crossorigin>
<link rel="stylesheet" href="https:///fonts/fonts.css">
<link rel="preconnect" href="https://assetbroker.lossless.one" crossorigin>
<link rel="stylesheet" href="https://assetbroker.lossless.one/fonts/fonts.css">
<style>
body {
margin: 0px;

View File

@@ -1,6 +1,6 @@
{
"name": "@social.io/catalog",
"version": "1.1.0",
"version": "1.2.4",
"private": false,
"description": "catalog for social.io",
"main": "dist_ts_web/index.js",
@@ -8,30 +8,33 @@
"type": "module",
"scripts": {
"test": "tstest test/",
"build": "tsbuild tsfolders --allowimplicitany && tsbundle element --production",
"build": "tsbuild tsfolders --allowimplicitany --skiplibcheck && tsbundle element --production",
"watch": "tswatch element",
"buildDocs": "tsdoc"
},
"author": "Lossless GmbH",
"license": "UNLICENSED",
"dependencies": {
"@design.estate/dees-catalog": "^1.2.0",
"@design.estate/dees-domtools": "^2.0.64",
"@design.estate/dees-element": "^2.0.39",
"@design.estate/dees-catalog": "^1.5.6",
"@design.estate/dees-domtools": "^2.3.2",
"@design.estate/dees-element": "^2.0.42",
"@design.estate/dees-wcctools": "^1.0.90",
"@losslessone_private/loint-pubapi": "^1.0.14",
"@social.io/interfaces": "^1.0.5"
"@social.io/interfaces": "^1.2.1",
"rrweb": "2.0.0-alpha.4",
"rrweb-player": "1.0.0-alpha.4",
"rrweb-snapshot": "2.0.0-alpha.4"
},
"devDependencies": {
"@git.zone/tsbuild": "^2.1.84",
"@git.zone/tsbundle": "^2.0.15",
"@git.zone/tsrun": "^1.2.49",
"@git.zone/tstest": "^1.0.90",
"@git.zone/tswatch": "^2.0.23",
"@git.zone/tsbuild": "^2.3.2",
"@git.zone/tsbundle": "^2.2.5",
"@git.zone/tsrun": "^1.3.3",
"@git.zone/tstest": "^1.0.96",
"@git.zone/tswatch": "^2.1.0",
"@push.rocks/projectinfo": "^5.0.2",
"@push.rocks/smartenv": "^5.0.12",
"@push.rocks/tapbundle": "^5.3.0",
"@types/node": "^22.7.5"
"@push.rocks/tapbundle": "^5.6.3",
"@types/node": "^22.14.1"
},
"files": [
"ts/**/*",
@@ -55,5 +58,6 @@
"bugs": {
"url": "https://gitlab.com/social.io/private/catalog/issues"
},
"homepage": "https://gitlab.com/social.io/private/catalog#readme"
"homepage": "https://gitlab.com/social.io/private/catalog#readme",
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6"
}

6967
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@social.io/catalog',
version: '1.1.0',
version: '1.2.4',
description: 'catalog for social.io'
}

View File

@@ -2,3 +2,4 @@ export * from './sio-fab.js';
export * from './sio-combox.js';
export * from './sio-subwidget-onboardme.js';
export * from './sio-subwidget-conversations.js';
export * from './sio-recorder.js';

View File

@@ -4,6 +4,7 @@ import {
html,
customElement,
type TemplateResult,
cssManager,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
@@ -124,7 +125,7 @@ export class SioCombox extends DeesElement {
width: 100%;
padding-bottom: 16px;
grid-template-columns: repeat(2, 1fr);
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 50%);
background-image: linear-gradient(to bottom, ${cssManager.bdTheme('#eeeeeb00', 'rgba(0, 0, 0, 0)')} 0%, ${cssManager.bdTheme('#eeeeebff', 'rgba(0, 0, 0, 1)')} 50%);
padding-top: 24px;
}

View File

@@ -120,7 +120,9 @@ export class SioFab extends DeesElement {
height: 100%;
font-size: 32px;
color: ${cssManager.bdTheme('#777', '#999')};
top: 2px;
top: 0px;
left: 0px;
transform: translateY(2px);
}
#mainbox .icon.close dees-icon {
@@ -128,6 +130,8 @@ export class SioFab extends DeesElement {
width: 100%;
height: 100%;
font-size: 24px;
top: 0px;
left: 0px;
color: ${cssManager.bdTheme('#666', '#CCC')};
}

View File

@@ -0,0 +1,213 @@
import {
DeesElement,
html,
css,
customElement,
property,
query,
} from '@design.estate/dees-element';
import * as rrwebMod from 'rrweb';
import rrwebPlayerMod from 'rrweb-player';
const rrweb: any = rrwebMod;
const rrwebPlayer: typeof rrwebPlayerMod.default = rrwebPlayerMod as any;
/**
* Use rrweb's eventWithTime if you like strict typing:
*
* import { eventWithTime } from 'rrweb';
* export interface IRecordingEvent extends eventWithTime {}
*
* Here, for brevity, we define an empty interface
* and cast all events to any.
*/
export interface IRecordingEvent {}
@customElement('sio-recorder')
export class SioRecorder extends DeesElement {
public static demo = () => html`<sio-recorder></sio-recorder>`;
/**
* Holds all recorded events from rrweb.
*/
private events: IRecordingEvent[] = [];
/**
* status
*/
public status: 'recording' | 'playing' | 'stopped' = 'stopped';
/**
* A reference to rrweb's stop recording function.
* We'll store it when we begin a record session so we can call it later.
*/
private stopFn: (() => void) | null = null;
/**
* Query for the div in our template that will be used for playback.
*/
@query('#playback')
private playbackDiv!: HTMLDivElement;
static styles = css`
:host {
display: block;
}
/* The playback container: set a fixed size for demonstration. */
#playback {
width: 800px;
height: 600px;
border: 1px solid #ccc;
background-color: #fff;
position: relative;
}
`;
render() {
return html` <div id="playback"></div> `;
}
/**
* Lifecycle: Called when the element is inserted into the DOM.
*/
async connectedCallback(): Promise<void> {
super.connectedCallback();
console.log('sio-recorder connectedCallback');
// Start recording immediately
this.startRecording();
// Use the domtools-based approach you have (Ctrl+H):
const domtools = await this.domtoolsPromise;
domtools.keyboard
.on([domtools.keyboard.keyEnum.Ctrl, domtools.keyboard.keyEnum.H])
.subscribe(this.handleKeydown);
await this.domtoolsPromise;
this.domtools.convenience.smartdelay.delayFor(2000).then(() => {
// this.handleKeydown();
});
}
/**
* Lifecycle: Called when the element is removed from the DOM.
*/
public async disconnectedCallback(): Promise<void> {
super.disconnectedCallback();
// Stop recording if it's still running
this.stopRecording();
// Clean up your subscription or any global listeners if needed
}
/**
* Starts an rrweb recording session that tracks the entire DOM,
* including canvases and cross-origin iframes (if permissible).
*/
private async startRecording(): Promise<void> {
await this.domtoolsPromise;
this.status = 'recording';
this.events = [];
// For capturing "everything," enable advanced flags:
while (this.status === 'recording') {
this.stopFn = rrweb.record({
emit: (event: any) => {
// If you have a stricter type:
// this.events.push(event as IRecordingEvent);
// else store as any:
this.events.push(event);
},
// Some recommended settings to capture the "complete" page:
recordCanvas: true, // record canvas elements
recordCrossOriginIframes: true, // attempt capturing cross-origin iframes
// checkoutEveryNms: 1000, // check every N milliseconds
});
await this.domtools.convenience.smartdelay.delayFor(1000);
await this.stopFn();
}
console.log('Recording has started...');
}
/**
* Stops the rrweb recording session
*/
private stopRecording(): void {
if (this.stopFn) {
this.stopFn();
this.stopFn = null;
console.log('Recording has stopped.');
}
}
/**
* Plays back the recorded events in the `playbackDiv`
*/
private async playRecording(): Promise<void> {
await this.domtoolsPromise;
if (!this.playbackDiv) return;
const replayer = new rrwebPlayer({
target: this.playbackDiv, // customizable root element
props: {
events: this.events as any,
root: this.playbackDiv,
showController: false,
width: this.playbackDiv.offsetWidth,
height: this.playbackDiv.offsetHeight,
},
});
this.domtools.convenience.smartdelay.delayFor(0).then(async () => {
while (true) {
await this.domtools.convenience.smartdelay.delayFor(30000);
await replayer.play();
await this.domtools.convenience.smartdelay.delayFor(0);
// this.fixPosition();
}
});
this.fixPosition();
}
public async fixPosition() {
await this.domtoolsPromise;
await this.domtools.convenience.smartdelay.delayFor(0);
const playbackDiv = this.shadowRoot.querySelector('#playback') as HTMLElement;
const replayerWrapper = this.shadowRoot.querySelector('.replayer-wrapper') as HTMLElement;
const replayerMouse = this.shadowRoot.querySelector('.replayer-mouse') as HTMLElement;
const replayerMouseTail = this.shadowRoot.querySelector('.replayer-mouse-tail') as HTMLElement;
const iframe = this.shadowRoot.querySelector('iframe');
replayerWrapper.style.position = 'absolute';
replayerWrapper.style.top = '0px';
replayerWrapper.style.left = '0px';
replayerWrapper.style.transformOrigin = 'center center';
replayerMouse.style.position = 'absolute';
replayerMouseTail.style.position = 'absolute';
iframe.style.position = 'absolute';
iframe.style.top = '0px';
iframe.style.left = '0px';
iframe.style.border = 'none';
// set z-index
replayerWrapper.style.zIndex = '1000';
iframe.style.zIndex = '1000';
replayerMouse.style.zIndex = '1002';
replayerMouseTail.style.zIndex = '1001';
// lets show a mouse cursor
replayerMouse.style.width = '10px';
replayerMouse.style.height = '10px';
replayerMouse.style.background = 'green';
replayerMouse.style.transform = 'translate(-50%, -50%)';
replayerMouse.style.borderRadius = '50%';
replayerMouse.style.border = '1px solid white';
}
/**
* Keydown handler. If Ctrl + H is pressed, stop the recording and replay the session
*/
private handleKeydown = (): void => {
this.stopRecording();
this.playRecording();
};
}