Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: start/stop ui for transcription #2895

Merged
merged 28 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e5ed01e
feat: start/stop events for transcriptions
amar-1995 May 8, 2024
838f7a6
Merge branch 'dev' into WEB-2809-start-stop-transcription
amar-1995 May 10, 2024
8ad7740
feat: start/stop ui for transcription
amar-1995 May 14, 2024
02fd7dd
Merge branch 'dev' into WEB-2812-ui-start-stop-transcription
amar-1995 May 15, 2024
fbf3c4b
fix: added qa
amar-1995 May 15, 2024
27c099f
fix: added loading toast
amar-1995 May 17, 2024
beec9d6
fix: merged with dev
amar-1995 May 17, 2024
aa8fc06
fix: build error
amar-1995 May 17, 2024
b4b6186
fix: handling mweb ui
amar-1995 May 17, 2024
6da6ea4
fix: resolve pr comment
amar-1995 May 20, 2024
038c45e
Merge branch 'dev' into WEB-2809-start-stop-transcription
amar-1995 May 20, 2024
4d6a53d
Merge branch 'dev' into WEB-2809-start-stop-transcription
amar-1995 May 21, 2024
f8d4aa0
fix: added transcription initialized state
amar-1995 May 21, 2024
925abe5
Merge branch 'WEB-2809-start-stop-transcription' into WEB-2812-ui-sta…
amar-1995 May 21, 2024
0db32ec
fix: merge with dev
amar-1995 May 21, 2024
e17f66d
Update App.jsx
raviteja83 May 22, 2024
9b0d038
Merge branch 'dev' into WEB-2812-ui-start-stop-transcription
raviteja83 May 22, 2024
81cde41
fix: added starting toast
amar-1995 May 22, 2024
d0572f5
fix: removed log
amar-1995 May 22, 2024
ff5c45a
Merge branch 'dev' into WEB-2812-ui-start-stop-transcription
amar-1995 May 22, 2024
844fa20
fix: renaming
amar-1995 May 22, 2024
5fe9fe7
fix: renaming
amar-1995 May 22, 2024
50178f1
fix: lint error
amar-1995 May 22, 2024
9a6ddf9
fix: added proper msg
amar-1995 May 22, 2024
1255ace
fix: added mobile view
amar-1995 May 22, 2024
958447b
fix: added content
amar-1995 May 22, 2024
eba3662
fix: error occured and match removed
amar-1995 May 22, 2024
cbb8909
Merge branch 'dev' into WEB-2812-ui-start-stop-transcription
raviteja83 May 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/prebuilt-react-integration/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ import { getRoomCodeFromUrl } from './utils';
export default function App() {
const roomCode = getRoomCodeFromUrl();

return <HMSPrebuilt roomCode={roomCode} />;
return (
<HMSPrebuilt roomCode={roomCode} />
);
}
1 change: 1 addition & 0 deletions packages/hms-video-store/src/selectors/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ export const selectPermissions = createSelector(selectLocalPeerRole, role => rol
export const selectRecordingState = createSelector(selectRoom, room => room.recording);
export const selectRTMPState = createSelector(selectRoom, room => room.rtmp);
export const selectHLSState = createSelector(selectRoom, room => room.hls);
export const selectTranscriptionsState = createSelector(selectRoom, room => room.transcriptions);
export const selectSessionId = createSelector(selectRoom, room => room.sessionId);
export const selectRoomStartTime = createSelector(selectRoom, room => room.startedAt);
export const selectIsLargeRoom = createSelector(selectRoom, room => !!room.isLargeRoom);
Expand Down
2 changes: 1 addition & 1 deletion packages/hms-video-store/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const HMSEvents = {

export const PROTOCOL_VERSION = '2.5';

export const PROTOCOL_SPEC = '20240417';
export const PROTOCOL_SPEC = '20240521';

export const HAND_RAISE_GROUP_NAME = '_handraise';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ const initialAppData = {
[POLL_STATE.pollInView]: '',
[POLL_STATE.view]: '',
},
// by default off, so it will not appear in beam bots
[APP_DATA.caption]: false,
// by default on because of on demand now
[APP_DATA.caption]: true,
};

export const AppData = React.memo(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import React from 'react';
import { HMSTranscriptionMode, selectIsTranscriptionEnabled, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
import { AlertTriangleIcon, CrossIcon } from '@100mslive/react-icons';
import { Button } from '../../../Button';
import { Box, Flex } from '../../../Layout';
import { Loading } from '../../../Loading';
import { Text } from '../../../Text';
// @ts-ignore: No implicit Any
import { ToastManager } from '../Toast/ToastManager';
// @ts-ignore: No implicit Any
import { useSetIsCaptionEnabled } from '../AppData/useUISettings';

export const CaptionContent = ({ isMobile, onExit }: { isMobile: boolean; onExit: () => void }) => {
const DURATION = 2000;
const actions = useHMSActions();
const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);

const [isCaptionEnabled, setIsCaptionEnabled] = useSetIsCaptionEnabled();
return (
<>
<Text
variant={isMobile ? 'md' : 'lg'}
css={{
color: '$on_surface_high',
fontWeight: '$semiBold',
display: 'flex',
pb: '$4',
'@md': { px: '$8', borderBottom: '1px solid $border_default' },
}}
>
{isTranscriptionEnabled ? 'Disable' : 'Enable'} Closed Caption (CC) for this session?
<Box
css={{ color: 'inherit', ml: 'auto', '&:hover': { color: '$on_surface_medium', cursor: 'pointer' } }}
onClick={onExit}
>
<CrossIcon />
</Box>
</Text>
{!isMobile ? (
<Text variant="sm" css={{ color: '$on_surface_medium', pb: '$6', mb: '$8', '@md': { px: '$8', mt: '$4' } }}>
This will {isTranscriptionEnabled ? 'disable' : 'enable'} Closed Captions for everyone in this room. You can
{isTranscriptionEnabled ? 'enable' : 'disable'} it later.
</Text>
) : null}

<Flex
justify="between"
align="center"
css={{
width: '100%',
gap: '$md',
mt: '$10',
'@md': { px: '$4' },
}}
>
{isMobile ? null : (
<Button variant="standard" css={{ w: '100%' }} outlined onClick={onExit}>
Cancel
</Button>
)}
<Flex
direction="column"
justify="between"
align="center"
css={{
width: '100%',
}}
>
{isMobile && isTranscriptionEnabled ? (
<Button
variant="standard"
css={{ w: '100%', mb: '$8' }}
outlined
onClick={() => {
setIsCaptionEnabled(!isCaptionEnabled);
onExit();
}}
>
{isCaptionEnabled ? 'Hide For Me' : 'Show For Me'}
</Button>
) : null}
<Button
variant={isTranscriptionEnabled ? 'danger' : 'primary'}
css={{ width: '100%' }}
data-testid="popup_change_btn"
onClick={async () => {
try {
if (isTranscriptionEnabled) {
await actions.stopTranscription({
mode: HMSTranscriptionMode.CAPTION,
});
ToastManager.addToast({
title: `Disabling Closed Caption for everyone.`,
variant: 'standard',
duration: DURATION,
icon: <Loading color="currentColor" />,
});
onExit();
return;
}
await actions.startTranscription({
mode: HMSTranscriptionMode.CAPTION,
});
ToastManager.addToast({
title: `Enabling Closed Caption for everyone.`,
variant: 'standard',
duration: DURATION,
icon: <Loading color="currentColor" />,
});
} catch (err) {
ToastManager.addToast({
title: `Failed to ${isTranscriptionEnabled ? 'disabled' : 'enabled'} closed caption`,
variant: 'error',
icon: <AlertTriangleIcon style={{ marginRight: '0.5rem' }} />,
});
}
onExit();
}}
>
{isTranscriptionEnabled ? 'Disable' : 'Enable'} for Everyone
</Button>
</Flex>
</Flex>
{isMobile && (
<Text variant="sm" css={{ color: '$on_surface_medium', pb: '$6', mb: '$8', '@md': { px: '$8', mt: '$4' } }}>
This will {isTranscriptionEnabled ? 'disable' : 'enable'} Closed Captions for everyone in this room. You can
{isTranscriptionEnabled ? 'enable' : 'disable'} it later.
</Text>
)}
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { useMedia } from 'react-use';
import { config as cssConfig, Dialog } from '../../..';
import { Sheet } from '../../../Sheet';
import { CaptionContent } from './CaptionContent';

export const CaptionModal = ({ onOpenChange }: { onOpenChange: (value: boolean) => void }) => {
const isMobile = useMedia(cssConfig.media.md);

const props = {
isMobile,
onExit: () => {
onOpenChange(false);
},
};

if (isMobile) {
return (
<Sheet.Root defaultOpen onOpenChange={onOpenChange}>
<Sheet.Content css={{ bg: '$surface_dim', p: '$8 0' }}>
<CaptionContent {...props} />
</Sheet.Content>
</Sheet.Root>
);
}

return (
<Dialog.Root defaultOpen onOpenChange={onOpenChange}>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content css={{ bg: '$surface_dim', width: 'min(400px,80%)', p: '$10' }}>
<CaptionContent {...props} />
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,23 @@ import {
HLSLiveStreamingScreen_Elements,
} from '@100mslive/types-prebuilt';
import { match } from 'ts-pattern';
import { selectAppData, selectLocalPeerID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
import { BrbIcon, CheckIcon, HamburgerMenuIcon, InfoIcon, PipIcon, SettingsIcon } from '@100mslive/react-icons';
import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../..';
import {
selectAppData,
selectIsTranscriptionEnabled,
selectLocalPeerID,
useHMSActions,
useHMSStore,
} from '@100mslive/react-sdk';
import {
BrbIcon,
CheckIcon,
HamburgerMenuIcon,
InfoIcon,
OpenCaptionIcon,
PipIcon,
SettingsIcon,
} from '@100mslive/react-icons';
import { Checkbox, Dropdown, Flex, Switch, Text, Tooltip } from '../../../..';
import IconButton from '../../../IconButton';
// @ts-ignore: No implicit any
import { PIP } from '../../PIP';
Expand All @@ -24,6 +38,7 @@ import StartRecording from '../../Settings/StartRecording';
import { StatsForNerds } from '../../StatsForNerds';
// @ts-ignore: No implicit any
import { BulkRoleChangeModal } from '../BulkRoleChangeModal';
import { CaptionModal } from '../CaptionModal';
// @ts-ignore: No implicit any
import { FullScreenItem } from '../FullScreenItem';
import { MuteAllModal } from '../MuteAllModal';
Expand All @@ -43,6 +58,7 @@ const MODALS = {
BULK_ROLE_CHANGE: 'bulkRoleChange',
MUTE_ALL: 'muteAll',
EMBED_URL: 'embedUrl',
CAPTION: 'caption',
};

export const DesktopOptions = ({
Expand All @@ -59,6 +75,7 @@ export const DesktopOptions = ({
const { isBRBOn, toggleBRB } = useMyMetadata();
const isPipOn = PictureInPicture.isOn();
const isBRBEnabled = !!elements?.brb;
const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);

useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' });

Expand Down Expand Up @@ -115,6 +132,23 @@ export const DesktopOptions = ({
</Dropdown.Item>
) : null}

<Dropdown.Item
data-testid="closed_caption_admin"
onClick={() => {
updateState(MODALS.CAPTION, true);
}}
>
<OpenCaptionIcon />
<Flex direction="column" css={{ flexGrow: '1' }}>
<Text variant="sm" css={{ ml: '$4', color: '$on_surface_high' }}>
Closed Captions
</Text>
<Text variant="caption" css={{ ml: '$4', color: '$on_surface_medium' }}>
{isTranscriptionEnabled ? 'Enabled' : 'Disabled'}
</Text>
</Flex>
<Switch id="closed_caption_start_stop" checked={isTranscriptionEnabled} disabled={false} />
</Dropdown.Item>
{screenType !== 'hls_live_streaming' ? (
<Dropdown.Item css={{ p: 0, '&:empty': { display: 'none' } }}>
<PIP
Expand Down Expand Up @@ -211,6 +245,9 @@ export const DesktopOptions = ({
onOpenChange={(value: boolean) => updateState(MODALS.SELF_ROLE_CHANGE, value)}
/>
)}
{openModals.has(MODALS.CAPTION) && (
<CaptionModal onOpenChange={(value: boolean) => updateState(MODALS.CAPTION, value)} />
)}
{/* {openModals.has(MODALS.EMBED_URL) && (
<EmbedUrlModal onOpenChange={value => updateState(MODALS.EMBED_URL, value)} />
)} */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
SettingsIcon,
VirtualBackgroundIcon,
} from '@100mslive/react-icons';
import { Box, Loading, Tooltip } from '../../../..';
import { Box, Loading, Text, Tooltip } from '../../../..';
import { Sheet } from '../../../../Sheet';
// @ts-ignore: No implicit any
import IconButton from '../../../IconButton';
Expand All @@ -43,6 +43,7 @@ import SettingsModal from '../../Settings/SettingsModal';
import { ToastManager } from '../../Toast/ToastManager';
// @ts-ignore: No implicit any
import { ActionTile } from '../ActionTile';
import { CaptionModal } from '../CaptionModal';
// @ts-ignore: No implicit any
import { ChangeNameModal } from '../ChangeNameModal';
// @ts-ignore: No implicit any
Expand Down Expand Up @@ -73,6 +74,7 @@ const MODALS = {
BULK_ROLE_CHANGE: 'bulkRoleChange',
MUTE_ALL: 'muteAll',
EMBED_URL: 'embedUrl',
CAPTION: 'caption',
};

export const MwebOptions = ({
Expand Down Expand Up @@ -106,9 +108,9 @@ export const MwebOptions = ({
const isLocalVideoEnabled = useHMSStore(selectIsLocalVideoEnabled);
const { startRecording, isRecordingLoading } = useRecordingHandler();

const isCaptionPresent = useHMSStore(selectIsTranscriptionEnabled);
const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);

const [isCaptionEnabled, setIsCaptionEnabled] = useSetIsCaptionEnabled();
const [isCaptionEnabled] = useSetIsCaptionEnabled();
useDropdownList({ open: openModals.size > 0 || openOptionsSheet || openSettingsSheet, name: 'MoreSettings' });

const updateState = (modalName: string, value: boolean) => {
Expand Down Expand Up @@ -193,21 +195,17 @@ export const MwebOptions = ({
<ActionTile.Title>{isHandRaised ? 'Lower' : 'Raise'} Hand</ActionTile.Title>
</ActionTile.Root>
) : null}
{isCaptionPresent && screenType !== 'hls_live_streaming' ? (
<ActionTile.Root
onClick={() => {
setIsCaptionEnabled(!isCaptionEnabled);
}}
>
{isCaptionEnabled ? (
<ClosedCaptionIcon width="20" height="20px" />
) : (
<OpenCaptionIcon width="20" height="20px" />
)}
<ActionTile.Title>{isCaptionEnabled ? 'Hide Captions' : 'Captions Disabled'}</ActionTile.Title>
</ActionTile.Root>
) : null}

<ActionTile.Root
onClick={() => {
setOpenOptionsSheet(false);
updateState(MODALS.CAPTION, true);
}}
>
{isTranscriptionEnabled && isCaptionEnabled ? <ClosedCaptionIcon /> : <OpenCaptionIcon />}
<Text variant="sm" css={{ ml: '$4', color: '$on_surface_high', flexGrow: '1' }}>
Closed Caption
</Text>
</ActionTile.Root>
{isLocalVideoEnabled && !!elements?.virtual_background ? (
<ActionTile.Root
onClick={() => {
Expand Down Expand Up @@ -323,7 +321,9 @@ export const MwebOptions = ({
openParentSheet={() => setOpenOptionsSheet(true)}
/>
)}

{openModals.has(MODALS.CAPTION) && (
<CaptionModal onOpenChange={(value: boolean) => updateState(MODALS.CAPTION, value)} />
)}
{showEmojiCard && (
<Box
ref={emojiCardRef}
Expand Down
Loading
Loading