Skip to content

Commit

Permalink
Merge pull request #125 from HuolalaTech/refactor/whole-bundle
Browse files Browse the repository at this point in the history
refactor whole bundle plugin
  • Loading branch information
wqcstrong authored Jan 6, 2025
2 parents 2bb033e + c1ecc51 commit fefae57
Show file tree
Hide file tree
Showing 18 changed files with 987 additions and 377 deletions.
7 changes: 5 additions & 2 deletions packages/page-spy-plugin-whole-bundle/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
<title>Document</title>
</head>
<body>
<!-- <script type="module" src="./src/index.ts"></script> -->
<script src="./dist/iife/index.min.js#manual"></script>
<script type="module">
import Feedback from './src';
const feedback = new Feedback();
</script>
<!-- <script src="./dist/iife/index.min.js"></script> -->
</body>
</html>
4 changes: 3 additions & 1 deletion packages/page-spy-plugin-whole-bundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@
"build": "vite build"
},
"dependencies": {
"@huolala-tech/page-spy-base": "^2.0.0",
"@huolala-tech/page-spy-browser": "^2.0.2",
"@huolala-tech/page-spy-plugin-data-harbor": "^2.0.2",
"@huolala-tech/page-spy-plugin-rrweb": "^2.0.0"
"@huolala-tech/page-spy-plugin-rrweb": "^2.0.0",
"@huolala-tech/page-spy-types": "^2.0.0"
},
"devDependencies": {
"@babel/core": "^7.25.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/page-spy-plugin-whole-bundle/src/assets/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/page-spy-plugin-whole-bundle/src/assets/error.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/page-spy-plugin-whole-bundle/src/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/page-spy-plugin-whole-bundle/src/assets/refresh.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/page-spy-plugin-whole-bundle/src/assets/success.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
168 changes: 37 additions & 131 deletions packages/page-spy-plugin-whole-bundle/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,51 @@
import PageSpy from '@huolala-tech/page-spy-browser';
import DataHarborPlugin from '@huolala-tech/page-spy-plugin-data-harbor';
import RRWebPlugin from '@huolala-tech/page-spy-plugin-rrweb';
import { dot, formatTime, pageSpyExist } from './utils';
import { dot, pageSpyExist } from './utils';
import classes from './styles/index.module.less';
import './styles/normalize.less';
import pageSpyLogo from './assets/logo.svg?raw';
import closeSvg from './assets/close.svg?raw';
import exportSvg from './assets/export.svg?raw';
import replaySvg from './assets/replay.svg?raw';
import pageSpyLogo from './assets/logo.svg';
import { moveable, UElement } from './utils/moveable';
import { name } from '../package.json';
import { buildForm } from './utils/build-form';
import { modal } from './utils/modal';

interface Config {
title?: string;
title: string;
/**
* Online source: 'https://example.com/xxx.jpg'
* Data url: 'data:image/png;base64,xxxx...'
* Relative source: '../xxx.jpg'
* Plain SVG content: '<svg>xxx</svg>'
*/
logo?: string;
statement?: string;
replayLabUrl?: string;
logo: string;
primaryColor: string;
statement: string;
}

const defaultConfig: Config = {
title: '问题反馈',
logo: pageSpyLogo,
primaryColor: '#8434E9',
statement:
'声明:「问题反馈」组件处理的所有数据都是保存在您本地,不会主动将数据传输到任何服务器,可放心使用。',
// replayLabUrl: 'https://pagespy.org/#/replay-lab',
};

class WholeBundle {
$pageSpy: PageSpy | null = null;

$harbor: DataHarborPlugin | null = null;

$rrweb: RRWebPlugin | null = null;

config: Config = {
title: '问题反馈',
logo: pageSpyLogo,
statement:
'声明:「问题反馈」组件处理的所有数据都是保存在您本地,不会主动将数据传输到任何服务器,可放心使用。',
replayLabUrl: 'https://pagespy.org/#/replay-lab',
};

startTime = 0;

timer: ReturnType<typeof setInterval> | null = null;
config: Config = defaultConfig;

static instance: WholeBundle | null = null;

constructor(userCfg?: Config) {
constructor(userCfg: Partial<Config> = {}) {
if (pageSpyExist()) {
console.info(
"[PageSpy] [WholeBundle] Detected that PageSpy already exists in the current context, so I won't be inited.",
`PageSpy is already exist, please remove it before using ${name}.`,
);
return;
}
Expand All @@ -59,7 +57,7 @@ class WholeBundle {
}
WholeBundle.instance = this;
this.config = {
...this.config,
...defaultConfig,
...userCfg,
};
this.init();
Expand Down Expand Up @@ -95,7 +93,6 @@ class WholeBundle {
offline: true,
autoRender: false,
});
this.startTime = Date.now();
}

render() {
Expand All @@ -107,135 +104,44 @@ class WholeBundle {
}

startRender() {
const logo = this.getLogo();
const { statement, title, replayLabUrl } = this.config;
const { statement, title, logo } = this.config;

const doc = new DOMParser().parseFromString(
`
<div id="__pageSpyWholeBundle">
<div id="__pageSpyWholeBundle" style="--primary-color: ${this.config.primaryColor}">
<button class="${classes.float}">
${logo ?? ''}
<img src="${logo}" />
<span>${title}</span>
</button>
<div class="${classes.modal}">
<div class="${classes.content}">
<div class="${classes.header}">
<div class="${classes.h_left}">
${logo ?? ''}
<div class="${classes.h_title}">
<b>${title}</b>
<br />
<span>操作录制基于 PageSpy 技术实现,<a href="https://github.com/HuolalaTech/page-spy-web" target="_blank">查看详情</a>。</span>
</div>
</div>
<div class="${classes.h_right}">
${closeSvg}
</div>
</div>
<div class="${classes.main}">
<div class="${classes.m_process}">
<div class="${classes.m_p_item}">
${exportSvg}
<b>1. 导出文件到本地</b>
</div>
<div class="${classes.m_p_item}">
${replaySvg}
<b>2. 前往 <a href="${replayLabUrl}" target="_blank">回放实验室</a> 查看</b>
</div>
</div>
<div class="${classes.m_statement}">
${statement}
</div>
</div>
<div class="${classes.footer}">
<div class="${classes.f_left}">
<b>REC</b>
<span class="${classes.f_duration}">--</span>
</div>
<div class="${classes.f_right}">
<button class="${classes.f_export}">导出</button>
</div>
</div>
</div>
</div>
</div>
`,
'text/html',
);

const $c = (name: string) => {
return doc.querySelector.bind(doc)(dot(name)) as HTMLElement;
const $c = (className: string) => {
return doc.querySelector.bind(doc)(dot(className)) as HTMLElement;
};
const root = doc.querySelector('#__pageSpyWholeBundle') as HTMLDivElement;
const float = $c(classes.float) as UElement;
const modal = $c(classes.modal);
const close = $c(classes.h_right);
const content = $c(classes.content);
const duration = $c(classes.f_duration);
const exportBtn = $c(classes.f_export) as HTMLButtonElement;

const openModal = () => {
if (float.isMoveEvent) return;
modal.classList.add(classes.show);
};
float.addEventListener('click', openModal);
moveable(float);
const closeModal = () => {
modal.classList.remove(classes.show);
modal.classList.add(classes.leaving);
setTimeout(() => {
modal.classList.remove(classes.leaving);
}, 300);
};
close.addEventListener('click', closeModal);
modal.addEventListener('click', closeModal);
content.addEventListener('click', (e) => {
e.stopPropagation();
});
if (this.startTime && duration) {
this.timer = setInterval(() => {
const seconds = parseInt(
String((Date.now() - this.startTime) / 1000),
10,
);
duration.textContent = formatTime(seconds);
}, 1000);
}
exportBtn.addEventListener('click', async () => {
exportBtn.disabled = true;
exportBtn.textContent = '处理中';
await this.$harbor?.onOfflineLog('download');
exportBtn.textContent = '导出成功';
setTimeout(() => {
exportBtn.disabled = false;
exportBtn.textContent = '导出';
}, 1500);
float.addEventListener('click', () => {
modal.show();
});
const form = buildForm({ harborPlugin: this.$harbor! });

document.body.insertAdjacentElement('beforeend', root);
}

getLogo() {
const { logo } = this.config;
if (!logo) return null;

const isSvgContent = /<svg[^>]*>([\s\S]*?)<\/svg>/.test(logo);
if (isSvgContent) return logo;
modal.build({
logo,
title,
content: form,
mounted: root,
});

try {
const url = new URL(logo, window.location.href);
return `<img src="${url.href}" alt="logo" />`;
} catch (e) {
return null;
}
document.documentElement.insertAdjacentElement('beforeend', root);
}

abort() {
document.querySelector('#__pageSpyWholeBundle')?.remove();
this.$pageSpy?.abort();
if (this.timer) {
clearInterval(this.timer);
}
WholeBundle.instance = null;
}
}
Expand Down
Loading

0 comments on commit fefae57

Please sign in to comment.