Skip to content

Commit 7b7a4a6

Browse files
committed
✨ feat: support standalone plugin
1 parent b0e4f1c commit 7b7a4a6

11 files changed

Lines changed: 75 additions & 8 deletions

File tree

src/client/const.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
export enum PluginChannel {
22
fetchPluginMessage = 'lobe-chat:fetch-plugin-message',
3+
fetchPluginState = 'lobe-chat:fetch-plugin-state',
4+
fillStandalonePluginContent = 'lobe-chat:fill-plugin-content',
5+
initStandalonePlugin = 'lobe-chat:init-standalone-plugin',
36
pluginReadyForRender = 'lobe-chat:plugin-ready-for-render',
47
renderPlugin = 'lobe-chat:render-plugin',
8+
updatePluginState = 'lobe-chat:update-plugin-state',
59
}

src/client/fetch/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './message';
2+
export * from './pluginState';
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { PluginChannel } from './const';
2-
import { onReceiveData } from './utils';
1+
import { PluginChannel } from '../const';
2+
import { onReceiveData } from '../utils';
33

44
export const fetchPluginMessage = <T = any>() =>
55
new Promise<T>((resolve) => {

src/client/fetch/pluginState.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { PluginChannel } from '../const';
2+
import { onReceiveData } from '../utils';
3+
4+
export const fetchPluginState = <T = any>() =>
5+
new Promise<T>((resolve) => {
6+
const receiverData = (e: MessageEvent) => {
7+
onReceiveData(e, (data) => {
8+
resolve(data.content as T);
9+
window.removeEventListener('message', receiverData);
10+
});
11+
};
12+
13+
window.addEventListener('message', receiverData);
14+
15+
top?.postMessage({ type: PluginChannel.fetchPluginState }, '*');
16+
});

src/client/hooks/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './useOnStandalonePluginInit';
2+
export * from './useWatchPluginMessage';
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useEffect } from 'react';
2+
3+
import { PluginChannel } from '@/client';
4+
import { PluginRequestPayload } from '@/schema/market';
5+
6+
interface PluginPayload<T = any> {
7+
args?: T;
8+
func: string;
9+
}
10+
11+
export const useOnStandalonePluginInit = <T = any>(
12+
callback: (payload: PluginPayload<T>) => void,
13+
) => {
14+
const fn = (e: MessageEvent) => {
15+
if (e.data.type === PluginChannel.initStandalonePlugin) {
16+
const payload = e.data.props as PluginRequestPayload;
17+
const func = payload.apiName;
18+
const args = JSON.parse(payload.arguments || '{}');
19+
callback({ args, func });
20+
}
21+
};
22+
23+
useEffect(() => {
24+
window.addEventListener('message', fn);
25+
26+
top?.postMessage({ type: PluginChannel.pluginReadyForRender }, '*');
27+
return () => {
28+
window.removeEventListener('message', fn);
29+
};
30+
}, []);
31+
};
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { useEffect, useState } from 'react';
22

3-
import { PluginChannel } from './const';
4-
import { PluginRenderProps } from './type';
5-
import { onReceiveData } from './utils';
3+
import { PluginChannel } from '../const';
4+
import { PluginRenderProps } from '../type';
5+
import { onReceiveData } from '../utils';
66

77
export const useWatchPluginMessage = <T = any>() => {
88
const [result, setData] = useState<{ data: T; loading: boolean }>({

src/client/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './const';
2-
export { fetchPluginMessage } from './message';
2+
export * from './fetch';
3+
export * from './hooks';
4+
export * from './postMessage';
35
export * from './type';
4-
export * from './useWatchPluginMessage';

src/client/postMessage.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { PluginChannel } from './const';
2+
3+
export const postToFillPluginContent = (content: any) => {
4+
top?.postMessage({ content, type: PluginChannel.fillStandalonePluginContent }, '*');
5+
};
6+
7+
export const postToUpdatePluginState = (state: any) => {
8+
top?.postMessage({ state, type: PluginChannel.updatePluginState }, '*');
9+
};

src/schema/market.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const pluginRequestPayloadSchema = z.object({
2626
identifier: z.string(),
2727
indexUrl: z.string().optional(),
2828
manifest: pluginManifestSchema.optional(),
29+
type: z.string().optional(),
2930
});
3031

3132
export type PluginRequestPayload = z.infer<typeof pluginRequestPayloadSchema>;

0 commit comments

Comments
 (0)