feat: add embeding meeting view in mobile when start meeting between conversation

chore/upgrade-rn-0.72.7
moonrailgun 1 year ago
parent 09200ad339
commit b97dddf60d

@ -27,12 +27,13 @@ UpdateRoom.displayName = 'UpdateRoom';
type ActiveRoomProps = {
userChoices: LocalUserChoices;
roomName: string;
autoInviteIds?: string[];
region?: string;
onLeave?: () => void;
hq?: boolean;
};
export const ActiveRoom: React.FC<ActiveRoomProps> = React.memo((props) => {
const { roomName, userChoices, onLeave, hq } = props;
const { roomName, userChoices, autoInviteIds, onLeave, hq } = props;
const token = useToken(roomName);
const liveKitUrl = useServerUrl();
@ -73,7 +74,10 @@ export const ActiveRoom: React.FC<ActiveRoomProps> = React.memo((props) => {
onDisconnected={onLeave}
>
<MeetingContextProvider meetingId={roomName}>
<VideoConference chatMessageFormatter={formatChatMessageLinks} />
<VideoConference
autoInviteIds={autoInviteIds}
chatMessageFormatter={formatChatMessageLinks}
/>
</MeetingContextProvider>
<UpdateRoom />

@ -10,6 +10,7 @@ import { useLivekitState } from '../store/useLivekitState';
interface LivekitViewProps {
roomName: string;
url: string;
autoInviteIds?: string[];
}
const _LivekitView: React.FC<LivekitViewProps> = React.memo((props) => {
const { setActive, setDeactive } = useLivekitState();
@ -26,6 +27,7 @@ const _LivekitView: React.FC<LivekitViewProps> = React.memo((props) => {
return (
<PureLivekitView
roomName={props.roomName}
autoInviteIds={props.autoInviteIds}
onJoin={handleJoin}
onLeave={handleLeave}
/>
@ -39,6 +41,7 @@ export const LivekitView = withKeepAliveOverlay(_LivekitView, {
interface PureLivekitViewProps {
roomName: string;
autoInviteIds?: string[];
onJoin?: () => Promise<void>;
onLeave?: () => void;
}
@ -73,6 +76,7 @@ export const PureLivekitView: React.FC<PureLivekitViewProps> = React.memo(
<ActiveRoom
roomName={props.roomName}
userChoices={preJoinChoices}
autoInviteIds={props.autoInviteIds}
onLeave={handleLeave}
/>
) : (

@ -36,6 +36,7 @@ import styled from 'styled-components';
export interface VideoConferenceProps
extends React.HTMLAttributes<HTMLDivElement> {
autoInviteIds?: string[];
chatMessageFormatter?: MessageFormatter;
}
@ -68,14 +69,14 @@ const IsCallingContainer = styled.div`
* @public
*/
export const VideoConference: React.FC<VideoConferenceProps> = React.memo(
({ chatMessageFormatter, ...props }) => {
({ autoInviteIds, chatMessageFormatter, ...props }) => {
const lastAutoFocusedScreenShareTrack =
React.useRef<TrackReferenceOrPlaceholder | null>(null);
const rightPanel = useMeetingContextState((state) => state.rightPanel);
const invitingUserIds = useMeetingContextState(
(state) => state.invitingUserIds
);
useMeetingInit();
useMeetingInit({ autoInviteIds });
const tracks = useTracks(
[
@ -179,7 +180,7 @@ export const VideoConference: React.FC<VideoConferenceProps> = React.memo(
);
VideoConference.displayName = 'VideoConference';
function useMeetingInit() {
function useMeetingInit({ autoInviteIds }: { autoInviteIds?: string[] }) {
const inviteUsers = useMeetingContextState((state) => state.inviteUsers);
const inviteUserCompleted = useMeetingContextState(
(state) => state.inviteUserCompleted
@ -201,7 +202,6 @@ function useMeetingInit() {
hasBeenSendInviteRef.current = true;
// Auto invite user on start
const autoInviteIds = (window as any).autoInviteIds as string[];
if (Array.isArray(autoInviteIds) && autoInviteIds.length > 0) {
inviteUsers(autoInviteIds);
}

@ -8,13 +8,15 @@ import {
regSocketEventListener,
getGlobalState,
showNotification,
navigate,
isMobile,
} from '@capital/common';
import { Loadable } from '@capital/component';
import { useIconIsShow } from './navbar/useIconIsShow';
import { useIconIsShow, usePersionPanelIsShow } from './navbar/useIconIsShow';
import { Translate } from './translate';
import React from 'react';
const PLUGIN_ID = 'com.msgbyte.livekit';
import { useLivekitState } from './store/useLivekitState';
import { PLUGIN_ID } from './consts';
console.log(`Plugin ${PLUGIN_ID} is loaded`);
@ -80,6 +82,15 @@ regPluginPanelRoute({
component: LivekitMeetingPanel,
});
regCustomPanel({
position: 'personal',
icon: 'mingcute:voice-line',
name: `${PLUGIN_ID}/livekitPersonMeeting`,
label: Translate.voiceChannel,
render: LivekitMeetingPanel,
useIsShow: usePersionPanelIsShow,
});
// 发起私信会议
regPluginPanelAction({
name: `${PLUGIN_ID}/groupAction`,
@ -92,14 +103,26 @@ regPluginPanelAction({
const members: string[] =
state.chat?.converses?.[converseId]?.members ?? [];
const shouldInviteUserIds = members.filter((m) => m !== currentUserId);
const win = panelWindowManager.open(
`/panel/plugin/${PLUGIN_ID}/meeting/${converseId}`,
{
width: 1280,
height: 768,
}
);
(win.window as any).autoInviteIds = shouldInviteUserIds;
if (isMobile()) {
// 如果是手机端则内嵌显示
useLivekitState.setState({
currentMeetingId: converseId,
autoInviteIds: shouldInviteUserIds,
});
const url = `/main/personal/custom/${PLUGIN_ID}/livekitPersonMeeting`;
navigate(url);
} else {
// 如果是桌面端则弹出独立窗口
const win = panelWindowManager.open(
`/panel/plugin/${PLUGIN_ID}/meeting/${converseId}`,
{
width: 1280,
height: 768,
}
);
(win.window as any).autoInviteIds = shouldInviteUserIds;
}
},
});

@ -3,3 +3,7 @@ import { useLivekitState } from '../store/useLivekitState';
export function useIconIsShow() {
return useLivekitState().isActive;
}
export function usePersionPanelIsShow() {
return useLivekitState().isActive;
}

@ -1,13 +1,36 @@
import React from 'react';
import { PureLivekitView } from '../components/LivekitView';
import { LivekitView } from '../components/LivekitView';
import { useParams } from 'react-router';
import { PLUGIN_ID } from '../consts';
import { useLivekitState } from '../store/useLivekitState';
import { NotFound } from '@capital/component';
import { Translate } from '../translate';
const LivekitMeetingPanel: React.FC = React.memo(() => {
const { meetingId } = useParams<{ meetingId: string }>();
const { currentMeetingId, autoInviteIds } = useLivekitState();
const { meetingId: paramsMeetingId } = useParams<{ meetingId?: string }>();
const meetingId = paramsMeetingId || currentMeetingId;
const url = paramsMeetingId
? `/${PLUGIN_ID}/meeting/${paramsMeetingId}`
: `/main/personal/custom/${PLUGIN_ID}/livekitPersonMeeting`;
if (!meetingId) {
return (
<div className="w-full h-full" style={{ paddingTop: 40 }}>
<NotFound message={Translate.notFoundMeeting} />
</div>
);
}
return (
<div className="w-full h-full">
<PureLivekitView roomName={meetingId} />
<LivekitView
className="w-full h-full"
roomName={meetingId}
url={url}
autoInviteIds={autoInviteIds}
/>
</div>
);
});

@ -4,7 +4,9 @@ import { immer } from 'zustand/middleware/immer';
interface LivekitState {
isActive: boolean;
currentMeetingId: string;
url: string;
autoInviteIds: string[]; // 自动邀请用户仅用于LivekitMeetingPanel(不用于LivekitGroupPanel)
activeRoom: Room | null;
setActive: (url: string) => void;
setDeactive: () => Promise<void>;
@ -13,7 +15,11 @@ interface LivekitState {
export const useLivekitState = create<LivekitState>()(
immer((set, get) => ({
isActive: false,
currentMeetingId: '',
url: '',
autoInviteIds: Array.isArray((window as any).autoInviteIds)
? (window as any).autoInviteIds
: [],
activeRoom: null,
setActive(url) {
set((state) => {

@ -89,4 +89,8 @@ export const Translate = {
'zh-CN': '邀请你加入会话',
'en-US': 'invite you to join conversation',
}),
notFoundMeeting: localTrans({
'zh-CN': '没有找到会议',
'en-US': 'Not found meeting',
}),
};

Loading…
Cancel
Save