feat: add livekit call invite notication card and actions

chore/devcontainer
moonrailgun 2 years ago
parent 8906b933d7
commit 505c6c38ed

@ -108,6 +108,8 @@ export {
setAlert,
showGlobalLoading,
setGlobalLoading,
showNotification,
setNotification,
} from './manager/ui';
// model

@ -47,3 +47,11 @@ export const [showGlobalLoading, setGlobalLoading] = buildRegFn<
>('global-loading', () => {
return () => {};
});
/**
*
*/
export const [showNotification, setNotification] =
buildRegFn<(message: React.ReactNode, duration?: number) => () => void>(
'notification'
);

@ -92,6 +92,10 @@ const plugins: Configuration['plugins'] = [
from: path.resolve(ROOT_PATH, './assets/images/avatar/'),
to: 'images/avatar/',
},
{
from: path.resolve(ROOT_PATH, './assets/audio/'),
to: 'audio/',
},
{
from: path.resolve(ROOT_PATH, '../../vercel.json'),
to: 'vercel.json',

@ -1,4 +1,4 @@
import { message, Modal } from 'antd';
import { message, Modal, notification } from 'antd';
import React from 'react';
import {
buildStorage,
@ -18,10 +18,12 @@ import {
parseUrlStr,
onLanguageLoaded,
version,
setNotification,
} from 'tailchat-shared';
import { getPopupContainer } from './utils/dom-helper';
import { getUserJWT } from './utils/jwt-helper';
import _get from 'lodash/get';
import _uniqueId from 'lodash/uniqueId';
import { recordMeasure } from './utils/measure-helper';
import { postMessageEvent } from './utils/event-helper';
import { setImageUrlParser, setWebMetaFormConfig } from 'tailchat-design';
@ -73,6 +75,19 @@ setGlobalLoading((text) => {
return hide;
});
setNotification((message, duration) => {
const key = _uniqueId('notification');
notification.open({
key,
message,
duration,
});
return () => {
notification.close(key);
};
});
setImageUrlParser(parseUrlStr);
onLanguageLoaded(() => {

@ -62,6 +62,7 @@ export {
showToasts,
showSuccessToasts,
showErrorToasts,
showNotification,
fetchAvailableServices,
isValidStr,
useGroupPanelInfo,

@ -64,7 +64,7 @@ export { PortalAdd, PortalRemove } from '@/components/Portal';
export { ErrorBoundary } from '@/components/ErrorBoundary';
export { ErrorView } from '@/components/ErrorView';
export { UserAvatar } from '@/components/UserAvatar';
export { UserName } from '@/components/UserName';
export { UserName, UserNamePure } from '@/components/UserName';
export { UserListItem } from '@/components/UserListItem';
export { Markdown, MarkdownEditor } from '@/components/Markdown';
export { Webview, WebviewKeepAlive } from '@/components/Webview';

@ -183,6 +183,11 @@ declare module '@capital/common' {
export const showErrorToasts: (error: any) => void;
export const showNotification: (
message: React.ReactNode,
duration?: number
) => () => void;
export const fetchAvailableServices: any;
export const isValidStr: (str: any) => str is string;
@ -632,6 +637,8 @@ declare module '@capital/component' {
style?: React.CSSProperties;
}>;
export const UserNamePure: any;
export const UserListItem: any;
export const Markdown: any;

@ -0,0 +1,39 @@
import React from 'react';
import styled from 'styled-components';
import { Translate } from '../translate';
import { IconBtn, UserNamePure } from '@capital/component';
const Root = styled.div`
.actions {
display: flex;
gap: 8px;
justify-content: flex-end;
margin-top: 20px;
}
`;
interface InviteCallNotificationProps {
senderUserId: string;
roomName: string;
onJoin?: () => void;
}
const InviteCallNotification: React.FC<InviteCallNotificationProps> =
React.memo((props) => {
return (
<Root>
<audio src="/audio/telephone.mp3" loop={true} autoPlay={true} />
<div>
<b>
<UserNamePure userId={props.senderUserId} />
</b>{' '}
{Translate.inviteJoinCall}
</div>
<div className="actions">
<IconBtn icon="mdi:phone-in-talk" onClick={props.onJoin} />
</div>
</Root>
);
});
InviteCallNotification.displayName = 'InviteCallNotification';
export default InviteCallNotification;

@ -26,7 +26,7 @@ export const Member: React.FC = React.memo(() => {
const getAction = useEvent((participant: Participant) => {
return [
!participant.isSpeaking && (
participant.isSpeaking && (
<IsSpeakingTip>({Translate.isSpeaking})</IsSpeakingTip>
),
<div key="mic-state">

@ -7,10 +7,12 @@ import {
panelWindowManager,
regSocketEventListener,
getGlobalState,
showNotification,
} from '@capital/common';
import { Loadable } from '@capital/component';
import { useIconIsShow } from './navbar/useIconIsShow';
import { Translate } from './translate';
import React from 'react';
const PLUGIN_ID = 'com.msgbyte.livekit';
@ -27,6 +29,13 @@ const LivekitMeetingPanel = Loadable(
}
);
const InviteCallNotification = Loadable(
() => import('./components/InviteCallNotification'),
{
componentName: `${PLUGIN_ID}:InviteCallNotification`,
}
);
regGroupPanel({
name: `${PLUGIN_ID}/livekitPanel`,
label: Translate.voiceChannel,
@ -88,3 +97,27 @@ regPluginPanelAction({
(win.window as any).autoInviteIds = shouldInviteUserIds;
},
});
regSocketEventListener({
eventName: `plugin:${PLUGIN_ID}.inviteCall`,
eventFn: (data) => {
const { senderUserId, roomName } = data;
const close = showNotification(
<InviteCallNotification
senderUserId={senderUserId}
onJoin={() => {
panelWindowManager.open(
`/panel/plugin/${PLUGIN_ID}/meeting/${roomName}`,
{
width: 1280,
height: 768,
}
);
close();
}}
/>,
0
);
},
});

@ -85,4 +85,8 @@ export const Translate = {
'zh-CN': '用户呼叫失败,该用户离线',
'en-US': 'The user call failed because of offline',
}),
inviteJoinCall: localTrans({
'zh-CN': '邀请你加入会话',
'en-US': 'invite you to join conversation',
}),
};

@ -183,6 +183,11 @@ declare module '@capital/common' {
export const showErrorToasts: (error: any) => void;
export const showNotification: (
message: React.ReactNode,
duration?: number
) => () => void;
export const fetchAvailableServices: any;
export const isValidStr: (str: any) => str is string;
@ -237,8 +242,29 @@ declare module '@capital/common' {
};
export const createPluginRequest: (pluginName: string) => {
get: (actionName: string, config?: any) => Promise<any>;
post: (actionName: string, data?: any, config?: any) => Promise<any>;
get: (
actionName: string,
config?: any
) => Promise<{
data: any;
headers: Record<string, string>;
status: number;
statusText: string;
config: Record<string, any>;
request: any;
}>;
post: (
actionName: string,
data?: any,
config?: any
) => Promise<{
data: any;
headers: Record<string, string>;
status: number;
statusText: string;
config: Record<string, any>;
request: any;
}>;
};
export const postRequest: any;
@ -611,6 +637,8 @@ declare module '@capital/component' {
style?: React.CSSProperties;
}>;
export const UserNamePure: any;
export const UserListItem: any;
export const Markdown: any;

Loading…
Cancel
Save