Skip to content

Commit

Permalink
feat: add livekit panel for converse dm meeting
Browse files Browse the repository at this point in the history
  • Loading branch information
moonrailgun committed Nov 18, 2023
1 parent 6ea7ca8 commit 0be2bf6
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 45 deletions.
9 changes: 9 additions & 0 deletions client/web/src/plugin/common/reg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,15 @@ export const [pluginRootRoute, regPluginRootRoute] = buildRegList<{
component: React.ComponentType;
}>();

/**
* 注册独立面板路由
*/
export const [pluginPanelRoute, regPluginPanelRoute] = buildRegList<{
name: string;
path: string;
component: React.ComponentType;
}>();

export interface BasePluginPanelActionProps {
/**
* 唯一标识
Expand Down
16 changes: 16 additions & 0 deletions client/web/src/routes/Panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { GroupDetail } from '@/components/modals/GroupDetail';
import { useParams } from 'react-router';
import { NotFound } from '@/components/NotFound';
import { Group } from '../Main/Content/Group';
import { pluginPanelRoute } from '@/plugin/common';

const GroupDetailRoute = React.memo(() => {
const { groupId } = useParams<{ groupId: string }>();
Expand Down Expand Up @@ -39,6 +40,21 @@ const PanelRoute: React.FC = React.memo(() => {
/>
<Route path="/group/main/:groupId/*" element={<Group />} />

<Route
path="/plugin/*"
element={
<Routes>
{pluginPanelRoute.map((r, i) => (
<Route
key={r.name}
path={r.path ?? `/fallback${i}`}
element={React.createElement(r.component)}
/>
))}
</Routes>
}
/>

<Route path="/*" element={t('未知的面板')} />
</Routes>
</MainProvider>
Expand Down
2 changes: 1 addition & 1 deletion client/web/src/utils/window-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class PanelWindowManager {
return this.openedPanelWindows[url];
}

const win = openInNewWindow(url);
const win = openInNewWindow(url, options);
if (!win) {
throw new Error('Create window failed');
}
Expand Down
18 changes: 18 additions & 0 deletions client/web/tailchat.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ declare module '@capital/common' {

export const postMessageEvent: any;

export const panelWindowManager: any;

export const getServiceUrl: () => string;

export const getCachedUserInfo: (
Expand Down Expand Up @@ -192,6 +194,10 @@ declare module '@capital/common' {

export const isDevelopment: boolean;

export const setWebviewKernel: any;

export const resetWebviewKernel: any;

export const navigate: any;

export const useLocation: any;
Expand Down Expand Up @@ -306,6 +312,10 @@ declare module '@capital/common' {

export const regPluginRootRoute: any;

export const pluginPanelRoute: any;

export const regPluginPanelRoute: any;

export const pluginPanelActions: any;

export const regPluginPanelAction: (
Expand Down Expand Up @@ -384,6 +394,10 @@ declare module '@capital/common' {

export const regLoginAction: any;

export const pluginChatInputPasteHandler: any;

export const regChatInputPasteHandler: any;

export const useGroupIdContext: () => string;

export const useGroupPanelContext: () => {
Expand Down Expand Up @@ -607,4 +621,8 @@ declare module '@capital/component' {
export const NotFound: any;

export const withKeepAliveOverlay: any;

export const AvatarUploader: any;

export const ImageUploader: any;
}
5 changes: 3 additions & 2 deletions pnpm-lock.yaml

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

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@types/lodash": "^4.14.196",
"@types/styled-components": "^5.1.26",
"react": "18.2.0",
"react-router": "^6.8.1",
"styled-components": "^5.3.6"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,54 +12,86 @@ interface LivekitViewProps {
url: string;
}
const _LivekitView: React.FC<LivekitViewProps> = React.memo((props) => {
const [preJoinChoices, setPreJoinChoices] = useState<
LocalUserChoices | undefined
>(undefined);
const { setActive, setDeactive } = useLivekitState();

const handleError = useEvent((err: Error) => {
showErrorToasts('error while setting up prejoin');
console.log('error while setting up prejoin', err);
});

const handleJoin = useEvent(async (userChoices: LocalUserChoices) => {
const handleJoin = useEvent(async () => {
await setDeactive(); // 先退出之前的房间

setPreJoinChoices(userChoices);
setActive(props.url);
});

const handleLeave = useEvent(() => {
setPreJoinChoices(undefined);
setDeactive();
});

return (
<LivekitContainer>
{props.roomName && preJoinChoices ? (
<ActiveRoom
roomName={props.roomName}
userChoices={preJoinChoices}
onLeave={handleLeave}
/>
) : (
<div style={{ display: 'grid', placeItems: 'center', height: '100%' }}>
<PreJoinView
roomName={props.roomName}
onError={handleError}
defaults={{
videoEnabled: false,
audioEnabled: false,
}}
onSubmit={handleJoin}
/>
</div>
)}
</LivekitContainer>
<PureLivekitView
roomName={props.roomName}
onJoin={handleJoin}
onLeave={handleLeave}
/>
);
});
_LivekitView.displayName = 'LivekitView';

export const LivekitView = withKeepAliveOverlay(_LivekitView, {
cacheId: (props) => props.url,
});

interface PureLivekitViewProps {
roomName: string;
onJoin?: () => Promise<void>;
onLeave?: () => void;
}
/**
* Without context just for meeting view
*/
export const PureLivekitView: React.FC<PureLivekitViewProps> = React.memo(
(props) => {
const [preJoinChoices, setPreJoinChoices] = useState<
LocalUserChoices | undefined
>(undefined);

const handleError = useEvent((err: Error) => {
showErrorToasts('error while setting up prejoin');
console.log('error while setting up prejoin', err);
});

const handleJoin = useEvent(async (userChoices: LocalUserChoices) => {
await props.onJoin?.();

setPreJoinChoices(userChoices);
});

const handleLeave = useEvent(() => {
props.onLeave?.();
setPreJoinChoices(undefined);
});

return (
<LivekitContainer>
{props.roomName && preJoinChoices ? (
<ActiveRoom
roomName={props.roomName}
userChoices={preJoinChoices}
onLeave={handleLeave}
/>
) : (
<div
style={{ display: 'grid', placeItems: 'center', height: '100%' }}
>
<PreJoinView
roomName={props.roomName}
onError={handleError}
defaults={{
videoEnabled: false,
audioEnabled: false,
}}
onSubmit={handleJoin}
/>
</div>
)}
</LivekitContainer>
);
}
);
PureLivekitView.displayName = 'PureLivekitView';
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const DEFAULT_USER_CHOICES = {
/** @public */
export type PreJoinProps = Omit<
React.HTMLAttributes<HTMLDivElement>,
'onSubmit'
'onSubmit' | 'onError'
> & {
roomName: string;
/** This function is called with the `LocalUserChoices` if validation is passed. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import {
regCustomPanel,
regGroupPanel,
regGroupPanelBadge,
regPluginPanelAction,
regPluginPanelRoute,
panelWindowManager,
} from '@capital/common';
import { Loadable } from '@capital/component';
import { useIconIsShow } from './navbar/useIconIsShow';
Expand All @@ -11,13 +14,22 @@ const PLUGIN_ID = 'com.msgbyte.livekit';

console.log(`Plugin ${PLUGIN_ID} is loaded`);

const LivekitPanel = Loadable(() => import('./group/LivekitPanel'), {
componentName: `${PLUGIN_ID}:LivekitPanel`,
});

const LivekitMeetingPanel = Loadable(
() => import('./panel/LivekitMeetingPanel'),
{
componentName: `${PLUGIN_ID}:LivekitMeetingPanel`,
}
);

regGroupPanel({
name: `${PLUGIN_ID}/livekitPanel`,
label: Translate.voiceChannel,
provider: PLUGIN_ID,
render: Loadable(() => import('./group/LivekitPanel'), {
componentName: `${PLUGIN_ID}:LivekitPanel`,
}),
render: LivekitPanel,
});

regGroupPanelBadge({
Expand Down Expand Up @@ -45,3 +57,26 @@ regCustomPanel({
),
useIsShow: useIconIsShow,
});

regPluginPanelRoute({
name: `${PLUGIN_ID}/livekitPanel`,
path: `/${PLUGIN_ID}/meeting/:meetingId`,
component: LivekitMeetingPanel,
});

// 发起私信会议
regPluginPanelAction({
name: `${PLUGIN_ID}/groupAction`,
label: Translate.startCall,
position: 'dm',
icon: 'mdi:video-box',
onClick: ({ converseId }) => {
panelWindowManager.open(
`/panel/plugin/${PLUGIN_ID}/meeting/${converseId}`,
{
width: 1280,
height: 768,
}
);
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { PureLivekitView } from '../components/LivekitView';
import { useParams } from 'react-router';

const LivekitMeetingPanel: React.FC = React.memo(() => {
const { meetingId } = useParams<{ meetingId: string }>();

return (
<div className="w-full h-full">
<PureLivekitView roomName={meetingId} />
</div>
);
});
LivekitMeetingPanel.displayName = 'LivekitMeetingPanel';

export default LivekitMeetingPanel;
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,8 @@ export const Translate = {
'zh-CN': '当前浏览器不支持视图全屏',
'en-US': 'Current browser does not support DOM full screen',
}),
startCall: localTrans({
'zh-CN': '发起/加入通话',
'en-US': 'Start/Join Call',
}),
};
Loading

0 comments on commit 0be2bf6

Please sign in to comment.