@nethesis/phone-island 1.1.7 → 1.1.8-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AlertView/index.js +1 -1
- package/dist/components/AlertView/index.js.map +1 -1
- package/dist/components/AudioPlayerView/PlayerFooterActions.js +1 -1
- package/dist/components/AudioPlayerView/PlayerFooterActions.js.map +1 -1
- package/dist/components/AudioPlayerView/Progress.js +1 -1
- package/dist/components/AudioPlayerView/Progress.js.map +1 -1
- package/dist/components/AudioPlayerView/index.js +1 -1
- package/dist/components/AudioPlayerView/index.js.map +1 -1
- package/dist/components/Button.js +1 -1
- package/dist/components/Button.js.map +1 -1
- package/dist/components/CallView/Actions.js +1 -1
- package/dist/components/CallView/Actions.js.map +1 -1
- package/dist/components/CallView/Number.js +1 -1
- package/dist/components/CallView/Number.js.map +1 -1
- package/dist/components/CallView/index.js +1 -1
- package/dist/components/CallView/index.js.map +1 -1
- package/dist/components/ConferenceView/index.js +1 -1
- package/dist/components/ConferenceView/index.js.map +1 -1
- package/dist/components/ContactView/ContactListView.js +1 -1
- package/dist/components/ContactView/ContactListView.js.map +1 -1
- package/dist/components/ContactView/TransferActions.js +1 -1
- package/dist/components/ContactView/TransferActions.js.map +1 -1
- package/dist/components/CustomThemedTooltip.js.map +1 -1
- package/dist/components/Events.js +1 -1
- package/dist/components/Events.js.map +1 -1
- package/dist/components/Hangup.js +1 -1
- package/dist/components/Hangup.js.map +1 -1
- package/dist/components/Island.js +1 -1
- package/dist/components/Island.js.map +1 -1
- package/dist/components/IslandDrag.js +1 -1
- package/dist/components/IslandDrag.js.map +1 -1
- package/dist/components/IslandMotion.js +1 -1
- package/dist/components/IslandMotion.js.map +1 -1
- package/dist/components/KeypadView/Actions.js +1 -1
- package/dist/components/KeypadView/Actions.js.map +1 -1
- package/dist/components/KeypadView/index.js +1 -1
- package/dist/components/KeypadView/index.js.map +1 -1
- package/dist/components/PhysicalRecorderView/index.js +1 -1
- package/dist/components/PhysicalRecorderView/index.js.map +1 -1
- package/dist/components/RecorderView/Actions.js +1 -1
- package/dist/components/RecorderView/Actions.js.map +1 -1
- package/dist/components/SettingsView/AudioView.js +1 -1
- package/dist/components/SettingsView/AudioView.js.map +1 -1
- package/dist/components/SettingsView/MicrophoneView.js +1 -1
- package/dist/components/SettingsView/MicrophoneView.js.map +1 -1
- package/dist/components/SettingsView/ThemeView.js +1 -1
- package/dist/components/SettingsView/ThemeView.js.map +1 -1
- package/dist/components/SettingsView/VideoInputView.js +1 -1
- package/dist/components/SettingsView/VideoInputView.js.map +1 -1
- package/dist/components/SideView/hooks/useSideViewLogic.js +1 -1
- package/dist/components/SideView/hooks/useSideViewLogic.js.map +1 -1
- package/dist/components/Socket.js +1 -1
- package/dist/components/Socket.js.map +1 -1
- package/dist/components/StreamingAnswerView/index.js +1 -1
- package/dist/components/StreamingAnswerView/index.js.map +1 -1
- package/dist/components/StreamingImage/index.js +1 -1
- package/dist/components/StreamingImage/index.js.map +1 -1
- package/dist/components/StreamingUnlock/index.js +2 -0
- package/dist/components/StreamingUnlock/index.js.map +1 -0
- package/dist/components/StreamingVideo/index.js +2 -0
- package/dist/components/StreamingVideo/index.js.map +1 -0
- package/dist/components/SwitchInputView/DropdownContent.js +1 -1
- package/dist/components/SwitchInputView/DropdownContent.js.map +1 -1
- package/dist/components/SwitchInputView/Index.js +1 -1
- package/dist/components/TranscriptionView/TranscriptionView.js +1 -1
- package/dist/components/TranscriptionView/TranscriptionView.js.map +1 -1
- package/dist/components/TransferButton.js +1 -1
- package/dist/components/TransferButton.js.map +1 -1
- package/dist/components/VideoView/index.js +1 -1
- package/dist/components/VideoView/index.js.map +1 -1
- package/dist/components/WebRTC.js +1 -1
- package/dist/components/WebRTC.js.map +1 -1
- package/dist/events/CallEvents.js +1 -1
- package/dist/events/CallEvents.js.map +1 -1
- package/dist/events/PlayerEvents.js +1 -1
- package/dist/events/PlayerEvents.js.map +1 -1
- package/dist/events/RecorderEvents.js +1 -1
- package/dist/events/RecorderEvents.js.map +1 -1
- package/dist/events/SocketEvents.js +1 -1
- package/dist/events/SocketEvents.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/lib/darkTheme.js +1 -1
- package/dist/lib/darkTheme.js.map +1 -1
- package/dist/lib/devices/devices.js +1 -1
- package/dist/lib/devices/devices.js.map +1 -1
- package/dist/lib/island/island.js +1 -1
- package/dist/lib/island/island.js.map +1 -1
- package/dist/lib/phone/call.js +1 -1
- package/dist/lib/phone/call.js.map +1 -1
- package/dist/lib/phone/video.js +1 -1
- package/dist/lib/phone/video.js.map +1 -1
- package/dist/lib/storage/local_storage.js +1 -1
- package/dist/lib/storage/local_storage.js.map +1 -1
- package/dist/lib/streaming/streamingVideo.js +2 -0
- package/dist/lib/streaming/streamingVideo.js.map +1 -0
- package/dist/lib/streaming/whepPlayer.js +2 -0
- package/dist/lib/streaming/whepPlayer.js.map +1 -0
- package/dist/models/currentCall.js +1 -1
- package/dist/models/currentCall.js.map +1 -1
- package/dist/models/island.js +1 -1
- package/dist/models/island.js.map +1 -1
- package/dist/models/motions.js +1 -1
- package/dist/models/motions.js.map +1 -1
- package/dist/models/streaming.js +1 -1
- package/dist/models/streaming.js.map +1 -1
- package/dist/node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js +1 -1
- package/dist/node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js.map +1 -1
- package/dist/node_modules/react-redux/node_modules/react-is/index.js +1 -1
- package/dist/node_modules/tslib/tslib.es6.js +1 -1
- package/dist/node_modules/tslib/tslib.es6.js.map +1 -1
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.development.js +1 -1
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js +1 -1
- package/dist/node_modules/use-sync-external-store/shim/index.js +1 -1
- package/dist/package.json.js +1 -1
- package/dist/public/locales/en/translation.json.js +1 -1
- package/dist/public/locales/it/translation.json.js +1 -1
- package/dist/services/user.js +1 -1
- package/dist/services/user.js.map +1 -1
- package/dist/utils/customHooks/useStreamingAspectRatio.js +2 -0
- package/dist/utils/customHooks/useStreamingAspectRatio.js.map +1 -0
- package/dist/utils/customHooks/useStreamingContentHeight.js +2 -0
- package/dist/utils/customHooks/useStreamingContentHeight.js.map +1 -0
- package/dist/utils/customHooks/useStreamingVideo.js +2 -0
- package/dist/utils/customHooks/useStreamingVideo.js.map +1 -0
- package/dist/utils/streaming/previewSize.js +2 -0
- package/dist/utils/streaming/previewSize.js.map +1 -0
- package/dist/utils/streaming/streamingUtils.js +1 -1
- package/dist/utils/streaming/streamingUtils.js.map +1 -1
- package/dist/utils/streaming/videoSource.js +2 -0
- package/dist/utils/streaming/videoSource.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/StreamingAnswerView/index.tsx"],"sourcesContent":["// Copyright (C) 2025 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { type FC, useEffect, useRef, useState } from 'react'\nimport { Button } from '../Button'\nimport { useDispatch, useSelector } from 'react-redux'\nimport { Dispatch, RootState } from '../../store'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n faMicrophone,\n faMicrophoneSlash,\n faVideoSlash,\n} from '@fortawesome/free-solid-svg-icons'\nimport { t } from 'i18next'\nimport { useIsomorphicLayoutEffect } from '../../utils'\nimport Hangup from '../Hangup'\nimport {\n muteCurrentCall,\n unmuteCurrentCall,\n} from '../../lib/phone/call'\nimport Avatar from '../CallView/Avatar'\nimport Timer from '../CallView/Timer'\nimport { isPhysical } from '../../lib/user/default_device'\nimport { AudioBars } from '../AudioBars'\nimport { CustomThemedTooltip } from '../CustomThemedTooltip'\nimport { faCamera, faLockOpen } from '@fortawesome/free-solid-svg-icons'\nimport { capitalizeFirstLetter, getISODateForFilename, handleStreamingUnlock } from '../../utils'\n\nexport interface StreamingAnswerViewProps { }\n\nexport const StreamingAnswerView: FC<StreamingAnswerViewProps> = () => {\n const dispatch = useDispatch<Dispatch>()\n const {\n muted,\n startTime,\n paused,\n streamingSourceNumber,\n } = useSelector((state: RootState) => state.currentCall)\n const { isOpen, isExtraLarge } = useSelector((state: RootState) => state.island)\n const { remoteAudioStream } = useSelector((state: RootState) => state.webrtc)\n const { videoSources, sourceImages } = useSelector((state: RootState) => state.streaming)\n\n // Get streaming source image and check if unlock is available\n const streamingSourceData = React.useMemo(() => {\n if (!streamingSourceNumber || !videoSources) return { image: null, canUnlock: false, tooltipText: '' }\n\n const source = Object.values(videoSources).find(\n (source) => source.extension === streamingSourceNumber,\n )\n if (!source) return { image: null, canUnlock: false, tooltipText: '' }\n\n const image = sourceImages[source.id] || source.image || null\n const canUnlock = Boolean(source.cmdOpen && source.cmdOpen.trim() !== '')\n const tooltipText = canUnlock ? `${t('VideoStreaming.Open')}: ${source.description}` : ''\n\n return { image, canUnlock, tooltipText }\n }, [streamingSourceNumber, videoSources, sourceImages, t])\n\n const [isFullscreen, setIsFullscreen] = useState(false)\n const streamingAnswerViewRef = useRef(null)\n const localScreen = useRef<HTMLVideoElement>(null)\n const remoteScreen = useRef<HTMLVideoElement>(null)\n const localVideo = useRef<HTMLVideoElement>(null)\n const largeRemoteVideo = useRef<HTMLVideoElement>(null)\n const smallRemoteVideo = useRef<HTMLVideoElement>(null)\n\n useIsomorphicLayoutEffect(() => {\n dispatch.player.updatePlayer({\n localScreen: localScreen,\n remoteScreen: remoteScreen,\n localVideo: localVideo,\n largeRemoteVideo: largeRemoteVideo,\n smallRemoteVideo: smallRemoteVideo,\n })\n }, [])\n\n const handleFullscreenChange = () => {\n setIsFullscreen(!!document.fullscreenElement)\n }\n\n const toggleFullScreen = () => {\n if (document.fullscreenElement) {\n // exit full screen\n document.exitFullscreen()\n } else {\n // enter full screen\n if (streamingAnswerViewRef.current) {\n ; (streamingAnswerViewRef.current as HTMLElement).requestFullscreen()\n }\n }\n }\n\n useEffect(() => {\n // register for full screen change\n addEventListener('fullscreenchange', handleFullscreenChange)\n\n return () => {\n removeEventListener('fullscreenchange', handleFullscreenChange)\n }\n }, [])\n\n const handleScreenshot = React.useCallback(() => {\n if (!streamingSourceNumber || !videoSources) return\n\n const source = Object.values(videoSources).find(\n (source) => source.extension === streamingSourceNumber,\n )\n if (!source || !source.image) return\n\n const filename = source.description\n ? `${capitalizeFirstLetter(source.description).replace(/\\s+/g, '_')}_${getISODateForFilename()}_screenshot.jpg`\n : `screenshot_${getISODateForFilename()}.jpg`\n\n // Create download link using the base64 image\n const link = document.createElement('a')\n link.href = source.image\n link.download = filename\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n }, [streamingSourceNumber, videoSources])\n\n return (\n <>\n {isOpen ? (\n <div\n ref={streamingAnswerViewRef}\n className={isFullscreen ? 'pi-h-screen pi-w-full' : isExtraLarge ? 'pi-h-[748px] pi-w-[936px]' : 'pi-h-[480px] pi-w-[600px]'}\n >\n <div className={`${isFullscreen ? `pi-h-[500px]` : isExtraLarge ? `pi-h-[648px]` : `pi-h-[380px]`} pi-flex pi-relative pi-justify-center pi-w-full pi-flex-col`}>\n {/* Video container with rounded corners */}\n <div className='pi-relative pi-flex-1'>\n {/* Streaming source image or placeholder */}\n {streamingSourceData.image ? (\n <img\n src={streamingSourceData.image}\n alt='Streaming source'\n className='pi-rounded-tl-[20px] pi-rounded-tr-[20px] pi-rounded-bl-[20px] pi-rounded-br-[20px] pi-w-full pi-h-full pi-object-cover'\n />\n ) : (\n <div className='pi-w-full pi-h-full pi-bg-gray-200 dark:pi-bg-gray-800 pi-flex pi-items-center pi-justify-center pi-rounded-tl-[20px] pi-rounded-tr-[20px] pi-rounded-bl-[20px] pi-rounded-br-[20px]'>\n <FontAwesomeIcon\n icon={faVideoSlash}\n className='pi-w-24 pi-h-24 pi-text-gray-400 dark:pi-text-gray-600'\n />\n </div>\n )}\n\n {/* Controls overlay (above the image with transparency) */}\n <div className='pi-absolute pi-bottom-0 pi-left-0 pi-right-0 pi-bg-black/30 pi-p-4 pi-rounded-b-3xl'>\n <div>\n <div className='pi-flex pi-items-center pi-justify-center pi-gap-6'>\n {/* Mute button */}\n <Button\n variant='default'\n onClick={muted ? unmuteCurrentCall : muteCurrentCall}\n data-tooltip-id='tooltip-mute-streaming'\n data-tooltip-content={muted ? t('Tooltip.Unmute') : t('Tooltip.Mute')}\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={muted ? faMicrophoneSlash : faMicrophone}\n />\n </Button>\n\n {/* Screenshot button */}\n <Button\n variant='default'\n onClick={handleScreenshot}\n data-tooltip-id='tooltip-screenshot-streaming'\n data-tooltip-content={t('VideoStreaming.Take a screenshot') || 'Take a screenshot'}\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={faCamera}\n />\n </Button>\n\n {/* Open door button - only show if cmdOpen is valid */}\n {streamingSourceData?.canUnlock && (\n <Button\n variant='default'\n onClick={handleStreamingUnlock}\n data-tooltip-id='tooltip-unlock-streaming'\n data-tooltip-content={streamingSourceData?.tooltipText}\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={faLockOpen}\n />\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {/* Footer below the image */}\n <div className='pi-bg-surfaceBackground dark:pi-bg-surfaceBackgroundDark pi-pt-4 pi-rounded-bl-[20px] pi-rounded-br-[20px]'>\n <Hangup\n buttonsVariant='default'\n showFullscreenButton={true}\n isFullscreen={isFullscreen}\n onToggleFullscreen={toggleFullScreen}\n isExtraLarge={isExtraLarge}\n onToggleExtraLarge={() => dispatch.island.setExtraLarge(!isExtraLarge)}\n />\n </div>\n\n </div>\n\n {/* Tooltips */}\n <CustomThemedTooltip className='pi-z-20' id='tooltip-mute-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-screenshot-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-unlock-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-record-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-pause-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-screen-share-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-toggle-fullscreen' place='bottom' />\n </div>\n ) : (\n // Collapsed view\n <>\n <div className='pi-flex pi-justify-between pi-items-center'>\n <Avatar />\n <Timer startTime={startTime} isNotAlwaysWhite />\n {!isOpen && remoteAudioStream && !isPhysical() && (\n <AudioBars\n audioStream={remoteAudioStream}\n paused={paused}\n size={isOpen ? 'large' : 'small'}\n />\n )}\n </div>\n </>\n )}\n </>\n )\n}\n\nexport default StreamingAnswerView\n"],"names":["StreamingAnswerView","dispatch","useDispatch","_a","useSelector","state","currentCall","muted","startTime","paused","streamingSourceNumber","_b","island","isOpen","isExtraLarge","remoteAudioStream","webrtc","_c","streaming","videoSources","sourceImages","streamingSourceData","React","useMemo","image","canUnlock","tooltipText","source","Object","values","find","extension","id","Boolean","cmdOpen","trim","concat","t","description","_d","useState","isFullscreen","setIsFullscreen","streamingAnswerViewRef","useRef","localScreen","remoteScreen","localVideo","largeRemoteVideo","smallRemoteVideo","useIsomorphicLayoutEffect","player","updatePlayer","handleFullscreenChange","document","fullscreenElement","useEffect","addEventListener","removeEventListener","handleScreenshot","useCallback","filename","capitalizeFirstLetter","replace","getISODateForFilename","link","createElement","href","download","body","appendChild","click","removeChild","Fragment","ref","className","src","alt","FontAwesomeIcon","icon","faVideoSlash","Button","variant","onClick","unmuteCurrentCall","muteCurrentCall","faMicrophoneSlash","faMicrophone","faCamera","handleStreamingUnlock","faLockOpen","Hangup","buttonsVariant","showFullscreenButton","onToggleFullscreen","exitFullscreen","current","requestFullscreen","onToggleExtraLarge","setExtraLarge","CustomThemedTooltip","place","Avatar","Timer","isNotAlwaysWhite","isPhysical","AudioBars","audioStream","size"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/StreamingAnswerView/index.tsx"],"sourcesContent":["// Copyright (C) 2025 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { type FC, useEffect, useRef, useState } from 'react'\nimport { Button } from '../Button'\nimport { useDispatch, useSelector } from 'react-redux'\nimport { Dispatch, RootState } from '../../store'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n faMicrophone,\n faMicrophoneSlash,\n faVideoSlash,\n} from '@fortawesome/free-solid-svg-icons'\nimport { t } from 'i18next'\nimport { useIsomorphicLayoutEffect } from '../../utils'\nimport Hangup from '../Hangup'\nimport {\n muteCurrentCall,\n unmuteCurrentCall,\n} from '../../lib/phone/call'\nimport Avatar from '../CallView/Avatar'\nimport Timer from '../CallView/Timer'\nimport { isPhysical } from '../../lib/user/default_device'\nimport { AudioBars } from '../AudioBars'\nimport { CustomThemedTooltip } from '../CustomThemedTooltip'\nimport { faCamera } from '@fortawesome/free-solid-svg-icons'\nimport { capitalizeFirstLetter, getISODateForFilename } from '../../utils'\nimport StreamingVideo, { captureVideoFrame } from '../StreamingVideo'\nimport StreamingUnlock from '../StreamingUnlock'\nimport { StreamingSourceImage } from '../StreamingImage'\nimport { findVideoSourceByNumber, isRtspVideoSource } from '../../utils/streaming/videoSource'\nimport { useStreamingAspectRatio } from '../../utils/customHooks/useStreamingAspectRatio'\nimport { getStreamingPreviewBoxRatio } from '../../utils/streaming/previewSize'\nimport { useStreamingContentHeight } from '../../utils/customHooks/useStreamingContentHeight'\n\nexport interface StreamingAnswerViewProps { }\n\nexport const StreamingAnswerView: FC<StreamingAnswerViewProps> = () => {\n const dispatch = useDispatch<Dispatch>()\n const {\n muted,\n startTime,\n paused,\n streamingSourceNumber,\n } = useSelector((state: RootState) => state.currentCall)\n const { isOpen, isExtraLarge } = useSelector((state: RootState) => state.island)\n const { remoteAudioStream } = useSelector((state: RootState) => state.webrtc)\n const { videoSources, sourceImages } = useSelector((state: RootState) => state.streaming)\n\n // The video source of the call and its last image (image sources)\n const streamingSource = React.useMemo(\n () => findVideoSourceByNumber(videoSources, streamingSourceNumber),\n [streamingSourceNumber, videoSources],\n )\n const isLiveVideo = isRtspVideoSource(streamingSource)\n const streamingSourceData = React.useMemo(() => {\n if (!streamingSource) return { image: null }\n return { image: sourceImages[streamingSource.id] || streamingSource.image || null }\n }, [streamingSource, sourceImages])\n const liveVideo = useRef<HTMLVideoElement>(null)\n // the video box takes the island width and follows the aspect ratio of the picture\n const previewBoxRatio = getStreamingPreviewBoxRatio(useStreamingAspectRatio())\n\n const [isFullscreen, setIsFullscreen] = useState(false)\n const streamingAnswerViewRef = useRef<HTMLDivElement | null>(null)\n // the island fits the measured content (see IslandMotion), not in full screen\n const measureContent = useStreamingContentHeight('streamingAnswer', isOpen && !isFullscreen)\n const setStreamingAnswerView = React.useCallback(\n (node: HTMLDivElement | null) => {\n streamingAnswerViewRef.current = node\n measureContent(node)\n },\n [measureContent],\n )\n const localScreen = useRef<HTMLVideoElement>(null)\n const remoteScreen = useRef<HTMLVideoElement>(null)\n const localVideo = useRef<HTMLVideoElement>(null)\n const largeRemoteVideo = useRef<HTMLVideoElement>(null)\n const smallRemoteVideo = useRef<HTMLVideoElement>(null)\n\n useIsomorphicLayoutEffect(() => {\n dispatch.player.updatePlayer({\n localScreen: localScreen,\n remoteScreen: remoteScreen,\n localVideo: localVideo,\n largeRemoteVideo: largeRemoteVideo,\n smallRemoteVideo: smallRemoteVideo,\n })\n }, [])\n\n const handleFullscreenChange = () => {\n setIsFullscreen(!!document.fullscreenElement)\n }\n\n const toggleFullScreen = () => {\n if (document.fullscreenElement) {\n // exit full screen\n document.exitFullscreen()\n } else {\n // enter full screen\n if (streamingAnswerViewRef.current) {\n ; (streamingAnswerViewRef.current as HTMLElement).requestFullscreen()\n }\n }\n }\n\n useEffect(() => {\n // register for full screen change\n addEventListener('fullscreenchange', handleFullscreenChange)\n\n return () => {\n removeEventListener('fullscreenchange', handleFullscreenChange)\n }\n }, [])\n\n const handleScreenshot = React.useCallback(() => {\n const source = streamingSource\n if (!source) return\n\n // live video: the current frame, image source: the last image\n const image = isRtspVideoSource(source) ? captureVideoFrame(liveVideo.current) : source.image\n if (!image) return\n\n const filename = source.description\n ? `${capitalizeFirstLetter(source.description).replace(/\\s+/g, '_')}_${getISODateForFilename()}_screenshot.jpg`\n : `screenshot_${getISODateForFilename()}.jpg`\n\n // Create download link using the base64 image\n const link = document.createElement('a')\n link.href = image\n link.download = filename\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n }, [streamingSource])\n\n return (\n <>\n {isOpen ? (\n <div\n ref={setStreamingAnswerView}\n className={isFullscreen ? 'pi-h-screen pi-w-full' : 'pi-w-full'}\n >\n <div className={`${isFullscreen ? `pi-h-[500px]` : ''} pi-flex pi-relative pi-justify-center pi-w-full pi-flex-col`}>\n {/* Video container with rounded corners: the whole picture, letterboxed if needed */}\n <div\n className={`pi-relative pi-bg-black pi-rounded-[20px] ${isFullscreen ? 'pi-flex-1' : ''}`}\n style={isFullscreen ? undefined : { aspectRatio: previewBoxRatio }}\n >\n {/* Live video, streaming source image or placeholder */}\n {isLiveVideo && streamingSource ? (\n <div className='pi-absolute pi-inset-0'>\n <StreamingVideo\n source={streamingSource}\n videoRef={liveVideo}\n className='pi-w-full pi-h-full pi-rounded-[20px]'\n overlayClassName='pi-rounded-[20px]'\n reconnectingClassName='pi-bottom-24'\n />\n </div>\n ) : streamingSourceData.image ? (\n <StreamingSourceImage\n sourceId={streamingSource?.id}\n src={streamingSourceData.image}\n alt='Streaming source'\n className='pi-absolute pi-inset-0 pi-rounded-[20px] pi-w-full pi-h-full'\n />\n ) : (\n <div className='pi-absolute pi-inset-0 pi-bg-gray-200 dark:pi-bg-gray-800 pi-flex pi-items-center pi-justify-center pi-rounded-tl-[20px] pi-rounded-tr-[20px] pi-rounded-bl-[20px] pi-rounded-br-[20px]'>\n <FontAwesomeIcon\n icon={faVideoSlash}\n className='pi-w-24 pi-h-24 pi-text-gray-400 dark:pi-text-gray-600'\n />\n </div>\n )}\n\n {/* Controls overlay (above the image with transparency) */}\n <div className='pi-absolute pi-bottom-0 pi-left-0 pi-right-0 pi-bg-black/30 pi-p-4 pi-rounded-b-3xl'>\n <div>\n <div className='pi-flex pi-items-center pi-justify-center pi-gap-6'>\n {/* Mute button */}\n <Button\n variant='default'\n className='pi-flex-shrink-0'\n onClick={muted ? unmuteCurrentCall : muteCurrentCall}\n data-tooltip-id='tooltip-mute-streaming'\n data-tooltip-content={muted ? t('Tooltip.Unmute') : t('Tooltip.Mute')}\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={muted ? faMicrophoneSlash : faMicrophone}\n />\n </Button>\n\n {/* Screenshot button */}\n <Button\n variant='default'\n className='pi-flex-shrink-0'\n onClick={handleScreenshot}\n data-tooltip-id='tooltip-screenshot-streaming'\n data-tooltip-content={t('VideoStreaming.Take a screenshot') || 'Take a screenshot'}\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={faCamera}\n />\n </Button>\n\n {/* Open door button(s) - only shown when the source has gates */}\n {streamingSource && (\n <StreamingUnlock\n source={streamingSource}\n size='large'\n tooltipId='tooltip-unlock-streaming'\n tooltipPlace='bottom'\n feedbackPlacement='above'\n />\n )}\n </div>\n </div>\n </div>\n </div>\n\n {/* Footer below the image */}\n <div className='pi-bg-surfaceBackground dark:pi-bg-surfaceBackgroundDark pi-py-4 pi-rounded-bl-[20px] pi-rounded-br-[20px]'>\n <Hangup\n buttonsVariant='default'\n showFullscreenButton={true}\n isFullscreen={isFullscreen}\n onToggleFullscreen={toggleFullScreen}\n isExtraLarge={isExtraLarge}\n onToggleExtraLarge={() => dispatch.island.setExtraLarge(!isExtraLarge)}\n />\n </div>\n\n </div>\n\n {/* Tooltips */}\n <CustomThemedTooltip className='pi-z-20' id='tooltip-mute-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-screenshot-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-record-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-pause-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-screen-share-streaming' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-toggle-fullscreen' place='bottom' />\n </div>\n ) : (\n // Collapsed view\n <>\n <div className='pi-flex pi-justify-between pi-items-center'>\n <Avatar />\n <Timer startTime={startTime} isNotAlwaysWhite />\n {!isOpen && remoteAudioStream && !isPhysical() && (\n <AudioBars\n audioStream={remoteAudioStream}\n paused={paused}\n size={isOpen ? 'large' : 'small'}\n />\n )}\n </div>\n </>\n )}\n </>\n )\n}\n\nexport default StreamingAnswerView\n"],"names":["StreamingAnswerView","dispatch","useDispatch","_a","useSelector","state","currentCall","muted","startTime","paused","streamingSourceNumber","_b","island","isOpen","isExtraLarge","remoteAudioStream","webrtc","_c","streaming","videoSources","sourceImages","streamingSource","React","useMemo","findVideoSourceByNumber","isLiveVideo","isRtspVideoSource","streamingSourceData","image","id","liveVideo","useRef","previewBoxRatio","getStreamingPreviewBoxRatio","useStreamingAspectRatio","_d","useState","isFullscreen","setIsFullscreen","streamingAnswerViewRef","measureContent","useStreamingContentHeight","setStreamingAnswerView","useCallback","node","current","localScreen","remoteScreen","localVideo","largeRemoteVideo","smallRemoteVideo","useIsomorphicLayoutEffect","player","updatePlayer","handleFullscreenChange","document","fullscreenElement","useEffect","addEventListener","removeEventListener","handleScreenshot","source","captureVideoFrame","filename","description","concat","capitalizeFirstLetter","replace","getISODateForFilename","link","createElement","href","download","body","appendChild","click","removeChild","ref","className","style","undefined","aspectRatio","StreamingVideo","videoRef","overlayClassName","reconnectingClassName","StreamingSourceImage","sourceId","src","alt","FontAwesomeIcon","icon","faVideoSlash","Button","variant","onClick","unmuteCurrentCall","muteCurrentCall","t","faMicrophoneSlash","faMicrophone","faCamera","StreamingUnlock","size","tooltipId","tooltipPlace","feedbackPlacement","Hangup","buttonsVariant","showFullscreenButton","onToggleFullscreen","exitFullscreen","requestFullscreen","onToggleExtraLarge","setExtraLarge","CustomThemedTooltip","place","Fragment","Avatar","Timer","isNotAlwaysWhite","isPhysical","AudioBars","audioStream"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");require("../../node_modules/react-redux/es/index.js");var r=require("../../utils/streaming/getStreamingSourceId.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../node_modules/tslib/tslib.es6.js"),t=require("react");require("../../node_modules/react-redux/es/index.js");var r=require("../../utils/streaming/getStreamingSourceId.js"),n=require("../VideoStreamingSkeleton/index.js"),u=require("../../node_modules/react-redux/es/hooks/useDispatch.js"),a=require("../../node_modules/react-redux/es/hooks/useSelector.js");function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=i(t),s=function(t){var r=t.sourceId,n=t.className,a=void 0===n?"":n,i=t.onLoad,s=e.__rest(t,["sourceId","className","onLoad"]),c=u.useDispatch();return o.default.createElement("img",e.__assign({},s,{className:"pi-object-contain ".concat(a),onLoad:function(e){var t=e.currentTarget;r&&t.naturalWidth&&t.naturalHeight&&c.streaming.setSourceAspectRatio({source:r,aspectRatio:t.naturalWidth/t.naturalHeight}),null==i||i(e)}}))},c=t.memo(function(e){var u=e.className,i=void 0===u?"":u,c=a.useSelector(function(e){return e.currentCall.streamingSourceNumber}),l=a.useSelector(function(e){return e.island.isFromStreaming}),d=a.useSelector(function(e){return e.streaming.sourceImages}),f=a.useSelector(function(e){return e.streaming.videoSources}),m=t.useState(0),p=m[0],g=m[1],v=t.useState(!1),S=v[0],b=v[1],h=c?r.getStreamingSourceId(c):void 0,j=c&&f?Object.values(f).find(function(e){return e.extension===c}):null,_=h?d[h]||(null==j?void 0:j.image):null;return t.useEffect(function(){var e=setInterval(function(){g(function(e){return e+1})},500);return function(){return clearInterval(e)}},[]),t.useEffect(function(){_&&b(!1)},[_]),l&&c?_?o.default.createElement("div",{className:"pi-overflow-hidden pi-rounded-lg pi-border pi-border-gray-300 dark:pi-border-gray-700 pi-bg-black ".concat(i)},!S&&o.default.createElement(n.default,{className:"pi-absolute pi-inset-0 pi-w-full pi-h-full"}),o.default.createElement(s,{key:p,sourceId:null==j?void 0:j.id,src:_,alt:"Streaming view",className:"pi-absolute pi-inset-0 pi-w-full pi-h-full pi-transition-opacity pi-duration-300 ".concat(S?"pi-opacity-100":"pi-opacity-0"),onLoad:function(){return b(!0)},onError:function(){return b(!1)}})):o.default.createElement(n.default,{className:i}):null});exports.StreamingSourceImage=s,exports.default=c;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/StreamingImage/index.tsx"],"sourcesContent":["// Copyright (C) 2024 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { FC, memo, useEffect, useState } from 'react'\nimport { useSelector } from 'react-redux'\nimport { RootState } from '../../store'\nimport { getStreamingSourceId } from '../../utils/streaming/getStreamingSourceId'\nimport VideoStreamingSkeleton from '../VideoStreamingSkeleton'\n\n/**\n * Component that displays the streaming image from a source\n */\nconst StreamingImage: FC = () => {\n const streamingSourceNumber = useSelector(\n (state: RootState) => state.currentCall.streamingSourceNumber,\n )\n const isFromStreaming = useSelector((state: RootState) => state.island.isFromStreaming)\n const sourceImages = useSelector((state: RootState) => state.streaming.sourceImages)\n const videoSources = useSelector((state: RootState) => state.streaming.videoSources)\n\n const [refreshKey, setRefreshKey] = useState(0)\n const [imageLoaded, setImageLoaded] = useState(false)\n\n const sourceId = streamingSourceNumber ? getStreamingSourceId(streamingSourceNumber) : undefined\n\n // Find the source to get the image\n const source =\n streamingSourceNumber && videoSources\n ? Object.values(videoSources).find((source) => source.extension === streamingSourceNumber)\n : null\n\n // get image URL from the source ID or from the source object\n const imageUrl = sourceId ? (sourceImages[sourceId] || source?.image) : null\n\n useEffect(() => {\n const interval = setInterval(() => {\n setRefreshKey((prev) => prev + 1)\n }, 500)\n\n return () => clearInterval(interval)\n }, [])\n\n useEffect(() => {\n if (imageUrl) {\n setImageLoaded(false)\n }\n }, [imageUrl])\n\n if (!isFromStreaming || !streamingSourceNumber) {\n return null\n }\n\n if (!imageUrl) {\n return <VideoStreamingSkeleton className=
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/StreamingImage/index.tsx"],"sourcesContent":["// Copyright (C) 2024 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { FC, ImgHTMLAttributes, memo, useEffect, useState } from 'react'\nimport { useDispatch, useSelector } from 'react-redux'\nimport { Dispatch, RootState } from '../../store'\nimport { getStreamingSourceId } from '../../utils/streaming/getStreamingSourceId'\nimport VideoStreamingSkeleton from '../VideoStreamingSkeleton'\n\n/**\n * Image of a video source: the whole picture (letterboxed if needed), its aspect ratio is\n * stored to size the box that shows it\n */\nexport const StreamingSourceImage: FC<\n ImgHTMLAttributes<HTMLImageElement> & { sourceId?: string }\n> = ({ sourceId, className = '', onLoad, ...props }) => {\n const dispatch = useDispatch<Dispatch>()\n return (\n <img\n {...props}\n className={`pi-object-contain ${className}`}\n onLoad={(event) => {\n const image = event.currentTarget\n if (sourceId && image.naturalWidth && image.naturalHeight) {\n dispatch.streaming.setSourceAspectRatio({\n source: sourceId,\n aspectRatio: image.naturalWidth / image.naturalHeight,\n })\n }\n onLoad?.(event)\n }}\n />\n )\n}\n\n/**\n * Component that displays the streaming image from a source\n */\nconst StreamingImage: FC<StreamingImageProps> = ({ className = '' }) => {\n const streamingSourceNumber = useSelector(\n (state: RootState) => state.currentCall.streamingSourceNumber,\n )\n const isFromStreaming = useSelector((state: RootState) => state.island.isFromStreaming)\n const sourceImages = useSelector((state: RootState) => state.streaming.sourceImages)\n const videoSources = useSelector((state: RootState) => state.streaming.videoSources)\n\n const [refreshKey, setRefreshKey] = useState(0)\n const [imageLoaded, setImageLoaded] = useState(false)\n\n const sourceId = streamingSourceNumber ? getStreamingSourceId(streamingSourceNumber) : undefined\n\n // Find the source to get the image\n const source =\n streamingSourceNumber && videoSources\n ? Object.values(videoSources).find((source) => source.extension === streamingSourceNumber)\n : null\n\n // get image URL from the source ID or from the source object\n const imageUrl = sourceId ? (sourceImages[sourceId] || source?.image) : null\n\n useEffect(() => {\n const interval = setInterval(() => {\n setRefreshKey((prev) => prev + 1)\n }, 500)\n\n return () => clearInterval(interval)\n }, [])\n\n useEffect(() => {\n if (imageUrl) {\n setImageLoaded(false)\n }\n }, [imageUrl])\n\n if (!isFromStreaming || !streamingSourceNumber) {\n return null\n }\n\n if (!imageUrl) {\n return <VideoStreamingSkeleton className={className} />\n }\n\n return (\n <div\n className={`pi-overflow-hidden pi-rounded-lg pi-border pi-border-gray-300 dark:pi-border-gray-700 pi-bg-black ${className}`}\n >\n {!imageLoaded && (\n <VideoStreamingSkeleton className='pi-absolute pi-inset-0 pi-w-full pi-h-full' />\n )}\n <StreamingSourceImage\n key={refreshKey}\n sourceId={source?.id}\n src={imageUrl}\n alt='Streaming view'\n className={`pi-absolute pi-inset-0 pi-w-full pi-h-full pi-transition-opacity pi-duration-300 ${imageLoaded ? 'pi-opacity-100' : 'pi-opacity-0'\n }`}\n onLoad={() => setImageLoaded(true)}\n onError={() => setImageLoaded(false)}\n />\n </div>\n )\n}\n\nexport interface StreamingImageProps {\n // size and position of the box (e.g. filling a box with the aspect ratio of the picture)\n className?: string\n}\n\nexport default memo(StreamingImage)\n"],"names":["StreamingSourceImage","_a","sourceId","_b","className","onLoad","props","__rest","dispatch","useDispatch","React","createElement","__assign","concat","event","image","currentTarget","naturalWidth","naturalHeight","streaming","setSourceAspectRatio","source","aspectRatio","memo","streamingSourceNumber","useSelector","state","currentCall","isFromStreaming","island","sourceImages","videoSources","_c","useState","refreshKey","setRefreshKey","_d","imageLoaded","setImageLoaded","getStreamingSourceId","undefined","Object","values","find","extension","imageUrl","useEffect","interval","setInterval","prev","clearInterval","VideoStreamingSkeleton","key","id","src","alt","onError"],"mappings":"8gBAaaA,EAET,SAACC,GAAE,IAAAC,EAAQD,EAAAC,SAAEC,EAAcF,EAAAG,UAAdA,OAAY,IAAAD,EAAA,GAAEA,EAAEE,EAAMJ,EAAAI,OAAKC,EAAKC,EAAAA,OAAAN,EAA5C,mCACGO,EAAWC,EAAAA,cACjB,OACEC,EAAA,QAAAC,cAAA,MAAAC,EAAAA,SAAA,CAAA,EACMN,EAAK,CACTF,UAAW,qBAAqBS,OAAAT,GAChCC,OAAQ,SAACS,GACP,IAAMC,EAAQD,EAAME,cAChBd,GAAYa,EAAME,cAAgBF,EAAMG,eAC1CV,EAASW,UAAUC,qBAAqB,CACtCC,OAAQnB,EACRoB,YAAaP,EAAME,aAAeF,EAAMG,gBAG5Cb,SAAAA,EAASS,EACV,IAGP,EA2EeS,EAAAA,EAAAA,KAtEiC,SAACtB,GAAE,IAAAE,EAAAF,EAAAG,UAAAA,OAAY,IAAAD,EAAA,GAAEA,EACzDqB,EAAwBC,cAC5B,SAACC,GAAqB,OAAAA,EAAMC,YAAYH,qBAAlB,GAElBI,EAAkBH,cAAY,SAACC,GAAqB,OAAAA,EAAMG,OAAOD,eAAb,GACpDE,EAAeL,cAAY,SAACC,GAAqB,OAAAA,EAAMP,UAAUW,YAAhB,GACjDC,EAAeN,cAAY,SAACC,GAAqB,OAAAA,EAAMP,UAAUY,YAAhB,GAEjDC,EAA8BC,EAAAA,SAAS,GAAtCC,EAAUF,EAAA,GAAEG,EAAaH,EAAA,GAC1BI,EAAgCH,EAAAA,UAAS,GAAxCI,EAAWD,EAAA,GAAEE,EAAcF,EAAA,GAE5BlC,EAAWsB,EAAwBe,EAAoBA,qBAACf,QAAyBgB,EAGjFnB,EACJG,GAAyBO,EACrBU,OAAOC,OAAOX,GAAcY,KAAK,SAACtB,GAAW,OAAAA,EAAOuB,YAAcpB,CAArB,GAC7C,KAGAqB,EAAW3C,EAAY4B,EAAa5B,KAAamB,aAAA,EAAAA,EAAQN,OAAS,KAgBxE,OAdA+B,EAAAA,UAAU,WACR,IAAMC,EAAWC,YAAY,WAC3Bb,EAAc,SAACc,GAAS,OAAAA,EAAO,CAAC,EACjC,EAAE,KAEH,OAAO,WAAM,OAAAC,cAAcH,EAAS,CACrC,EAAE,IAEHD,EAAAA,UAAU,WACJD,GACFP,GAAe,EAEnB,EAAG,CAACO,IAECjB,GAAoBJ,EAIpBqB,EAKHnC,EACE,QAAAC,cAAA,MAAA,CAAAP,UAAW,qGAAAS,OAAqGT,KAE9GiC,GACA3B,EAAAA,QAACC,cAAAwC,EAAsB,SAAC/C,UAAU,+CAEpCM,UAAAC,cAACX,EAAoB,CACnBoD,IAAKlB,EACLhC,SAAUmB,aAAM,EAANA,EAAQgC,GAClBC,IAAKT,EACLU,IAAI,iBACJnD,UAAW,oFAAoFS,OAAAwB,EAAc,iBAAmB,gBAEhIhC,OAAQ,WAAM,OAAAiC,GAAe,IAC7BkB,QAAS,WAAM,OAAAlB,GAAe,EAAf,KAlBZ5B,EAAAA,sBAACyC,EAAAA,QAAsB,CAAC/C,UAAWA,IAJnC,IA0BX"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../node_modules/tslib/tslib.es6.js"),t=require("react"),a=require("react-dom"),i=require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),n=require("../../node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js");require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");var o=require("../../node_modules/react-i18next/dist/es/useTranslation.js");require("../../node_modules/react-redux/es/index.js");var r=require("../Button.js"),l=require("../CustomThemedTooltip.js"),s=require("../../services/user.js"),c=require("../../utils/streaming/streamingUtils.js"),u=require("../../utils/streaming/videoSource.js"),d=require("../../node_modules/react-redux/es/hooks/useSelector.js");function p(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var m=p(t),f=function(p){var f=p.source,g=p.size,h=void 0===g?"small":g,x=p.tooltipId,k=p.tooltipPlace,v=void 0===k?"left":k,w=p.feedbackPlacement,b=void 0===w?"below":w,E=p.onChoose,C=p.onChooserChange,_=p.gatesContainer,S=o.useTranslation().t,y=u.getVideoSourceGates(f),N=d.useSelector(function(e){return e.currentCall.accepted}),j=t.useState(!1),q=j[0],I=j[1],T=t.useState(null),V=T[0],A=T[1],O=t.useState(null),F=O[0],U=O[1],R=t.useRef(null),z=t.useRef(void 0),B=t.useRef(!0),P=void 0!==_,D=q||P&&null!==F;if(t.useEffect(function(){return B.current=!0,function(){B.current=!1,R.current&&clearTimeout(R.current)}},[]),t.useEffect(function(){I(!1),U(null)},[f.id]),t.useEffect(function(){null==C||C(D)},[D]),t.useEffect(function(){return function(){return null==C?void 0:C(!1)}},[]),0===y.length)return null;var G,W=S("VideoStreaming.Answer the call to open"),L=function(e){return!N&&u.isDtmfGate(e)},X=function(e){R.current&&clearTimeout(R.current),U(e),R.current=setTimeout(function(){R.current=null,B.current&&(U(null),e.ok&&I(!1))},e.ok?2e3:5e3)},M=function(t){return e.__awaiter(void 0,void 0,void 0,function(){var a;return e.__generator(this,function(e){switch(e.label){case 0:if(null!==V)return[2];if(L(t))return!q&&x||X({gateId:t.id,ok:!1,hint:!0,message:W}),[2];A(t.id),U(null),e.label=1;case 1:return e.trys.push([1,3,4,5]),[4,c.openStreamingGate(f.id,t.id)];case 2:return e.sent(),B.current?(X({gateId:t.id,ok:!0,message:S("VideoStreaming.Opened")}),[3,5]):[2];case 3:return a=e.sent(),console.error("Error opening the gate:",a),B.current?(X({gateId:t.id,ok:!1,message:(i=a,n=i instanceof s.StreamingRequestError?i.code:void 0,o=i instanceof s.StreamingRequestError?i.status:void 0,"gate_timeout"===n||504===o?S("VideoStreaming.The gate did not respond in time"):"gate_unreachable"===n?S("VideoStreaming.The gate is unreachable"):"call_not_answered"===n?W:S(403===o?"VideoStreaming.You are not allowed to open this gate":"VideoStreaming.Unable to open the gate"))}),[3,5]):[2];case 4:return B.current&&A(null),[7];case 5:return[2]}var i,n,o})})},Y="large"===h?"pi-h-6 pi-w-6":"pi-h-5 pi-w-5",H=function(e,t){return void 0===t&&(t="large"===h?n.faLockOpen:n.faUnlock),V===e?n.faCircleNotch:(null==F?void 0:F.gateId)!==e||F.hint?t:F.ok?n.faCheck:n.faTriangleExclamation},J=function(e){return V===e?"pi-animate-spin":(null==F?void 0:F.gateId)!==e||F.hint?"":F.ok?"pi-text-green-500 dark:pi-text-green-600":"pi-text-red-500 dark:pi-text-red-600"},K=function(e){return e.name||f.description||e.id},Q=function(e){return L(e)?"".concat(K(e),": ").concat(W):"".concat(S("VideoStreaming.Open"),": ").concat(K(e))},Z="".concat(x||"tooltip-streaming-unlock","-gates"),$="!pi-opacity-40 !pi-cursor-not-allowed",ee="pi-left-1/2 -pi-translate-x-1/2 ".concat("above"===b?"pi-bottom-full pi-mb-2":"pi-top-full pi-mt-2"),te=function(e){return e.ok?"pi-bg-green-600 pi-text-white dark:pi-bg-green-400 dark:pi-text-gray-950":e.hint?"pi-bg-gray-700 pi-text-white dark:pi-bg-gray-200 dark:pi-text-gray-950":"pi-bg-red-600 pi-text-white dark:pi-bg-red-400 dark:pi-text-gray-950"},ae=function(e){return{role:e.ok||e.hint?"status":"alert","data-streaming-unlock-feedback":e.ok?"ok":e.hint?"hint":"error"}},ie=function(){I(!1),U(null)},ne=m.default.createElement("div",{className:"pi-flex pi-min-w-0 pi-items-center pi-gap-1.5 ".concat(P?"pi-w-full pi-overflow-x-auto pi-scrollbar-none":"large"===h?"pi-max-w-full pi-flex-wrap pi-justify-center":"pi-max-w-[18rem] pi-overflow-x-auto pi-scrollbar-none")},y.map(function(t){var a=(null==F?void 0:F.gateId)===t.id?F:null,o=a&&!P;return m.default.createElement("button",{key:t.id,type:"button","data-stop-propagation":!0,"data-streaming-gate":t.id,onClick:function(e){z.current=e.currentTarget.offsetWidth,M(t)},disabled:null!==V,"aria-disabled":!!L(t)||void 0,"data-tooltip-id":a&&!o?void 0:Z,"data-tooltip-content":a?o?a.message:void 0:Q(t),style:o?{minWidth:z.current}:void 0,className:"".concat(L(t)?a?"!pi-cursor-not-allowed":$:""," pi-flex pi-flex-shrink-0 pi-items-center pi-justify-center pi-gap-1.5 pi-rounded-full pi-px-3 ").concat("large"===h?"pi-h-12":"pi-h-10"," pi-text-xs pi-font-medium ").concat(a?te(a):"pi-bg-phoneIslandActive dark:pi-bg-phoneIslandActiveDark hover:pi-bg-gray-500 dark:hover:pi-bg-gray-50 pi-text-primaryInvert dark:pi-text-primaryInvertDark"," pi-transition-colors pi-duration-200 disabled:pi-cursor-not-allowed focus:pi-outline-none focus:pi-ring-2 focus:pi-ring-emerald-500 dark:focus:pi-ring-emerald-300")},m.default.createElement(i.FontAwesomeIcon,{className:"pi-h-3.5 pi-w-3.5 ".concat(a?"":J(t.id)),icon:H(t.id,n.faUnlock)}),a?m.default.createElement("span",e.__assign({className:"".concat(P?"pi-max-w-[16rem]":"pi-max-w-[9rem]"," pi-truncate")},ae(a)),a.message):m.default.createElement("span",{className:"pi-max-w-[9rem] pi-truncate"},K(t)))}));return m.default.createElement("div",{className:"pi-relative pi-flex pi-min-w-0 pi-items-center pi-gap-1.5","data-stop-propagation":!0},P&&q?m.default.createElement(r.Button,{variant:"default",onClick:ie,"aria-label":S("Common.Close")||"Close","data-streaming-unlock":"close","data-tooltip-id":x,"data-tooltip-content":S("Common.Close")||"Close"},m.default.createElement(i.FontAwesomeIcon,{className:Y,icon:n.faXmark})):q?m.default.createElement(m.default.Fragment,null,ne,m.default.createElement(r.Button,{variant:"default",className:"pi-flex-shrink-0 ".concat("large"===h?"":"!pi-h-10 !pi-w-10"),onClick:ie,"aria-label":S("Common.Close")||"Close","data-streaming-unlock":"close","data-tooltip-id":x,"data-tooltip-content":S("Common.Close")||"Close"},m.default.createElement(i.FontAwesomeIcon,{className:Y,icon:n.faXmark}))):m.default.createElement(r.Button,{variant:"default",onClick:function(){1===y.length?M(y[0]):(null==E||E(),I(!0))},disabled:null!==V,"aria-label":S("VideoStreaming.Open door")||"Open door","aria-disabled":!(1!==y.length||!L(y[0]))||void 0,className:1===y.length&&L(y[0])?$:"","data-streaming-unlock":1===y.length?"single":"multiple","data-tooltip-id":x,"data-tooltip-content":1===y.length?(G=y[0],L(G)?W:"".concat(S("VideoStreaming.Open"),": ").concat(K(G))):S("VideoStreaming.Choose the gate to open")||""},m.default.createElement(i.FontAwesomeIcon,{className:"".concat(Y," ").concat(1===y.length?J(y[0].id):""),icon:1===y.length?H(y[0].id):"large"===h?n.faLockOpen:n.faUnlock})),F&&!P&&!q&&m.default.createElement("div",e.__assign({},ae(F),{className:"pi-absolute ".concat(ee," pi-z-20 pi-max-w-[16rem] pi-whitespace-nowrap pi-truncate pi-rounded-md pi-px-2.5 pi-py-1 pi-text-xs pi-font-medium pi-shadow-md ").concat(te(F))}),F.message),_&&D&&a.createPortal(m.default.createElement("div",{className:"pi-flex pi-w-full pi-min-w-0 pi-items-center","data-stop-propagation":!0},q?ne:F&&m.default.createElement("div",e.__assign({},ae(F),{className:"pi-ml-auto pi-flex pi-h-8 pi-max-w-full pi-items-center pi-gap-1.5 pi-rounded-full pi-px-3 pi-text-xs pi-font-medium ".concat(te(F))}),m.default.createElement(i.FontAwesomeIcon,{className:"pi-h-3.5 pi-w-3.5 pi-flex-shrink-0",icon:F.ok?n.faCheck:n.faTriangleExclamation}),m.default.createElement("span",{className:"pi-truncate"},F.message))),_),x&&m.default.createElement(l.CustomThemedTooltip,{className:"pi-z-20",id:x,place:v}),y.length>1&&m.default.createElement(l.CustomThemedTooltip,{className:"pi-z-20",id:Z,place:P||"below"===b?"bottom":"top",maxWidth:"260px"}))};exports.StreamingUnlock=f,exports.default=f;
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/StreamingUnlock/index.tsx"],"sourcesContent":["// Copyright (C) 2025 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { FC, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n faCheck,\n faCircleNotch,\n faLockOpen,\n faTriangleExclamation,\n faUnlock,\n faXmark,\n} from '@fortawesome/free-solid-svg-icons'\nimport { useTranslation } from 'react-i18next'\nimport { useSelector } from 'react-redux'\nimport type { RootState } from '../../store'\nimport { Button } from '../Button'\nimport { CustomThemedTooltip } from '../CustomThemedTooltip'\nimport type { ITooltip } from 'react-tooltip'\nimport type { VideoSourceGateType, VideoSourceType } from '../../models/streaming'\nimport { StreamingRequestError } from '../../services/user'\nimport { openStreamingGate } from '../../utils/streaming/streamingUtils'\nimport { getVideoSourceGates, isDtmfGate } from '../../utils/streaming/videoSource'\n\n// How long the result of an opening stays visible\nconst SUCCESS_FEEDBACK_MS = 2000\nconst ERROR_FEEDBACK_MS = 5000\n\ninterface Feedback {\n gateId: string\n ok: boolean\n message: string\n // a hint (e.g. the call must be answered first), not the result of an opening\n hint?: boolean\n}\n\n/**\n * Unlock button of a video source.\n *\n * One gate: the button opens it. Several gates: the button expands in place into one small\n * labelled button per gate (no popup, so it also fits the compact incoming call layout).\n * The result of the opening replaces the name of its gate, or (one gate) is shown in a small\n * message attached to the button.\n * DTMF gates are sent by the PBX into the call: until the call is answered they look disabled\n * and only show a hint (the tones would get lost).\n * With a gatesContainer (the compact incoming call layout) the labelled gates and the results\n * are shown in that element, a row of their own, and the button becomes the close button.\n */\nexport const StreamingUnlock: FC<StreamingUnlockProps> = ({\n source,\n size = 'small',\n tooltipId,\n tooltipPlace = 'left',\n feedbackPlacement = 'below',\n onChoose,\n onChooserChange,\n gatesContainer,\n}) => {\n const { t } = useTranslation()\n const gates = getVideoSourceGates(source)\n const callAnswered = useSelector((state: RootState) => state.currentCall.accepted)\n const [choosing, setChoosing] = useState(false)\n const [pendingGate, setPendingGate] = useState<string | null>(null)\n const [feedback, setFeedback] = useState<Feedback | null>(null)\n const feedbackTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n // width of the pressed gate: its result keeps it, the row does not jump\n const pressedWidth = useRef<number | undefined>(undefined)\n const mounted = useRef(true)\n // the gates and the results go in the gatesContainer row\n const rowMode = gatesContainer !== undefined\n const rowOpen = choosing || (rowMode && feedback !== null)\n\n useEffect(() => {\n mounted.current = true\n return () => {\n mounted.current = false\n if (feedbackTimer.current) clearTimeout(feedbackTimer.current)\n }\n }, [])\n\n // a different source (or a reconfigured one) closes the chooser\n useEffect(() => {\n setChoosing(false)\n setFeedback(null)\n }, [source.id])\n\n useEffect(() => {\n onChooserChange?.(rowOpen)\n }, [rowOpen])\n\n useEffect(() => () => onChooserChange?.(false), [])\n\n if (gates.length === 0) return null\n\n const answerToOpen = t('VideoStreaming.Answer the call to open')\n const needsAnswer = (gate: VideoSourceGateType) => !callAnswered && isDtmfGate(gate)\n\n const errorMessage = (error: any) => {\n const code = error instanceof StreamingRequestError ? error.code : undefined\n const status = error instanceof StreamingRequestError ? error.status : undefined\n if (code === 'gate_timeout' || status === 504) {\n return t('VideoStreaming.The gate did not respond in time')\n }\n if (code === 'gate_unreachable') {\n return t('VideoStreaming.The gate is unreachable')\n }\n if (code === 'call_not_answered') {\n return answerToOpen\n }\n if (status === 403) {\n return t('VideoStreaming.You are not allowed to open this gate')\n }\n return t('VideoStreaming.Unable to open the gate')\n }\n\n const showFeedback = (next: Feedback) => {\n if (feedbackTimer.current) clearTimeout(feedbackTimer.current)\n setFeedback(next)\n feedbackTimer.current = setTimeout(\n () => {\n feedbackTimer.current = null\n if (!mounted.current) return\n setFeedback(null)\n // a successful opening closes the chooser\n if (next.ok) setChoosing(false)\n },\n next.ok ? SUCCESS_FEEDBACK_MS : ERROR_FEEDBACK_MS,\n )\n }\n\n const openGate = async (gate: VideoSourceGateType) => {\n if (pendingGate !== null) return\n if (needsAnswer(gate)) {\n // the single button already shows the hint in its tooltip\n if (!choosing && tooltipId) return\n showFeedback({ gateId: gate.id, ok: false, hint: true, message: answerToOpen })\n return\n }\n setPendingGate(gate.id)\n setFeedback(null)\n try {\n await openStreamingGate(source.id, gate.id)\n if (!mounted.current) return\n showFeedback({ gateId: gate.id, ok: true, message: t('VideoStreaming.Opened') })\n } catch (error) {\n console.error('Error opening the gate:', error)\n if (!mounted.current) return\n showFeedback({ gateId: gate.id, ok: false, message: errorMessage(error) })\n } finally {\n if (mounted.current) setPendingGate(null)\n }\n }\n\n const iconSize = size === 'large' ? 'pi-h-6 pi-w-6' : 'pi-h-5 pi-w-5'\n const gateIcon = (gateId: string, base = size === 'large' ? faLockOpen : faUnlock) => {\n if (pendingGate === gateId) return faCircleNotch\n if (feedback?.gateId === gateId && !feedback.hint) {\n return feedback.ok ? faCheck : faTriangleExclamation\n }\n return base\n }\n const gateIconClass = (gateId: string) =>\n pendingGate === gateId\n ? 'pi-animate-spin'\n : feedback?.gateId === gateId && !feedback.hint\n ? feedback.ok\n ? 'pi-text-green-500 dark:pi-text-green-600'\n : 'pi-text-red-500 dark:pi-text-red-600'\n : ''\n const gateName = (gate: VideoSourceGateType) => gate.name || source.description || gate.id\n const gateTitle = (gate: VideoSourceGateType) =>\n needsAnswer(gate) ? answerToOpen : `${t('VideoStreaming.Open')}: ${gateName(gate)}`\n // chooser gates: the full name (the label may be truncated) and what a click does\n const gateTooltip = (gate: VideoSourceGateType) =>\n needsAnswer(gate)\n ? `${gateName(gate)}: ${answerToOpen}`\n : `${t('VideoStreaming.Open')}: ${gateName(gate)}`\n const gatesTooltipId = `${tooltipId || 'tooltip-streaming-unlock'}-gates`\n // not the disabled attribute: the hint must still show on hover and on click\n const waitingClasses = '!pi-opacity-40 !pi-cursor-not-allowed'\n\n // centred on the single button, not at the edge of the bar\n const feedbackClasses = `pi-left-1/2 -pi-translate-x-1/2 ${\n feedbackPlacement === 'above' ? 'pi-bottom-full pi-mb-2' : 'pi-top-full pi-mt-2'\n }`\n const feedbackColors = (shown: Feedback) =>\n shown.ok\n ? 'pi-bg-green-600 pi-text-white dark:pi-bg-green-400 dark:pi-text-gray-950'\n : shown.hint\n ? 'pi-bg-gray-700 pi-text-white dark:pi-bg-gray-200 dark:pi-text-gray-950'\n : 'pi-bg-red-600 pi-text-white dark:pi-bg-red-400 dark:pi-text-gray-950'\n const feedbackAttributes = (shown: Feedback) => ({\n role: shown.ok || shown.hint ? 'status' : 'alert',\n 'data-streaming-unlock-feedback': shown.ok ? 'ok' : shown.hint ? 'hint' : 'error',\n })\n const closeChooser = () => {\n setChoosing(false)\n setFeedback(null)\n }\n\n const gateButtons = (\n <div\n className={`pi-flex pi-min-w-0 pi-items-center pi-gap-1.5 ${\n rowMode\n ? 'pi-w-full pi-overflow-x-auto pi-scrollbar-none'\n : size === 'large'\n ? // answered call bar: the room left by the other buttons, more lines if needed\n 'pi-max-w-full pi-flex-wrap pi-justify-center'\n : 'pi-max-w-[18rem] pi-overflow-x-auto pi-scrollbar-none'\n }`}\n >\n {gates.map((gate) => {\n // the result replaces the name of its gate\n const result = feedback?.gateId === gate.id ? feedback : null\n // over the picture the result may be truncated: the full text in the tooltip\n const resultTooltip = result && !rowMode\n return (\n <button\n key={gate.id}\n type='button'\n data-stop-propagation={true}\n data-streaming-gate={gate.id}\n onClick={(event) => {\n pressedWidth.current = event.currentTarget.offsetWidth\n openGate(gate)\n }}\n disabled={pendingGate !== null}\n aria-disabled={needsAnswer(gate) ? true : undefined}\n data-tooltip-id={result && !resultTooltip ? undefined : gatesTooltipId}\n data-tooltip-content={\n result ? (resultTooltip ? result.message : undefined) : gateTooltip(gate)\n }\n style={resultTooltip ? { minWidth: pressedWidth.current } : undefined}\n className={`${\n needsAnswer(gate) ? (result ? '!pi-cursor-not-allowed' : waitingClasses) : ''\n } pi-flex pi-flex-shrink-0 pi-items-center pi-justify-center pi-gap-1.5 pi-rounded-full pi-px-3 ${\n size === 'large' ? 'pi-h-12' : 'pi-h-10'\n } pi-text-xs pi-font-medium ${\n result\n ? feedbackColors(result)\n : 'pi-bg-phoneIslandActive dark:pi-bg-phoneIslandActiveDark hover:pi-bg-gray-500 dark:hover:pi-bg-gray-50 pi-text-primaryInvert dark:pi-text-primaryInvertDark'\n } pi-transition-colors pi-duration-200 disabled:pi-cursor-not-allowed focus:pi-outline-none focus:pi-ring-2 focus:pi-ring-emerald-500 dark:focus:pi-ring-emerald-300`}\n >\n <FontAwesomeIcon\n className={`pi-h-3.5 pi-w-3.5 ${result ? '' : gateIconClass(gate.id)}`}\n icon={gateIcon(gate.id, faUnlock)}\n />\n {result ? (\n <span\n className={`${rowMode ? 'pi-max-w-[16rem]' : 'pi-max-w-[9rem]'} pi-truncate`}\n {...feedbackAttributes(result)}\n >\n {result.message}\n </span>\n ) : (\n <span className='pi-max-w-[9rem] pi-truncate'>{gateName(gate)}</span>\n )}\n </button>\n )\n })}\n </div>\n )\n\n return (\n <div\n className='pi-relative pi-flex pi-min-w-0 pi-items-center pi-gap-1.5'\n data-stop-propagation={true}\n >\n {rowMode && choosing ? (\n <Button\n variant='default'\n onClick={closeChooser}\n aria-label={t('Common.Close') || 'Close'}\n data-streaming-unlock='close'\n data-tooltip-id={tooltipId}\n data-tooltip-content={t('Common.Close') || 'Close'}\n >\n <FontAwesomeIcon className={iconSize} icon={faXmark} />\n </Button>\n ) : !choosing ? (\n <Button\n variant='default'\n onClick={() => {\n if (gates.length === 1) {\n openGate(gates[0])\n } else {\n onChoose?.()\n setChoosing(true)\n }\n }}\n disabled={pendingGate !== null}\n aria-label={t('VideoStreaming.Open door') || 'Open door'}\n aria-disabled={gates.length === 1 && needsAnswer(gates[0]) ? true : undefined}\n className={gates.length === 1 && needsAnswer(gates[0]) ? waitingClasses : ''}\n data-streaming-unlock={gates.length === 1 ? 'single' : 'multiple'}\n data-tooltip-id={tooltipId}\n data-tooltip-content={\n gates.length === 1\n ? gateTitle(gates[0])\n : t('VideoStreaming.Choose the gate to open') || ''\n }\n >\n <FontAwesomeIcon\n className={`${iconSize} ${gates.length === 1 ? gateIconClass(gates[0].id) : ''}`}\n icon={\n gates.length === 1 ? gateIcon(gates[0].id) : size === 'large' ? faLockOpen : faUnlock\n }\n />\n </Button>\n ) : (\n <>\n {gateButtons}\n {/* a filled round button like the others: visible on any picture */}\n <Button\n variant='default'\n className={`pi-flex-shrink-0 ${size === 'large' ? '' : '!pi-h-10 !pi-w-10'}`}\n onClick={closeChooser}\n aria-label={t('Common.Close') || 'Close'}\n data-streaming-unlock='close'\n data-tooltip-id={tooltipId}\n data-tooltip-content={t('Common.Close') || 'Close'}\n >\n <FontAwesomeIcon className={iconSize} icon={faXmark} />\n </Button>\n </>\n )}\n\n {feedback && !rowMode && !choosing && (\n <div\n {...feedbackAttributes(feedback)}\n className={`pi-absolute ${feedbackClasses} pi-z-20 pi-max-w-[16rem] pi-whitespace-nowrap pi-truncate pi-rounded-md pi-px-2.5 pi-py-1 pi-text-xs pi-font-medium pi-shadow-md ${feedbackColors(\n feedback,\n )}`}\n >\n {feedback.message}\n </div>\n )}\n {/* the row: the gates to choose from, or the result of the single gate under its button */}\n {gatesContainer &&\n rowOpen &&\n createPortal(\n <div className='pi-flex pi-w-full pi-min-w-0 pi-items-center' data-stop-propagation={true}>\n {choosing\n ? gateButtons\n : feedback && (\n <div\n {...feedbackAttributes(feedback)}\n className={`pi-ml-auto pi-flex pi-h-8 pi-max-w-full pi-items-center pi-gap-1.5 pi-rounded-full pi-px-3 pi-text-xs pi-font-medium ${feedbackColors(\n feedback,\n )}`}\n >\n <FontAwesomeIcon\n className='pi-h-3.5 pi-w-3.5 pi-flex-shrink-0'\n icon={feedback.ok ? faCheck : faTriangleExclamation}\n />\n <span className='pi-truncate'>{feedback.message}</span>\n </div>\n )}\n </div>,\n gatesContainer,\n )}\n {tooltipId && <CustomThemedTooltip className='pi-z-20' id={tooltipId} place={tooltipPlace} />}\n {/* over the picture, never over the call buttons: below the gates row, above the bar */}\n {gates.length > 1 && (\n <CustomThemedTooltip\n className='pi-z-20'\n id={gatesTooltipId}\n place={rowMode || feedbackPlacement === 'below' ? 'bottom' : 'top'}\n maxWidth='260px'\n />\n )}\n </div>\n )\n}\n\nexport interface StreamingUnlockProps {\n source: VideoSourceType\n size?: 'small' | 'large'\n tooltipId?: string\n tooltipPlace?: ITooltip['place']\n // where the result message appears, relative to the buttons\n feedbackPlacement?: 'above' | 'below'\n // called when the gate chooser opens (e.g. to expand a collapsed island to make room)\n onChoose?: () => void\n // called when the gate chooser opens or closes (e.g. to give it the room of the caller name)\n onChooserChange?: (open: boolean) => void\n // element where the gates and the results are shown (a row below the buttons): the\n // chooser then never squeezes the buttons, null while the element is not mounted yet\n gatesContainer?: HTMLElement | null\n}\n\nexport default StreamingUnlock\n"],"names":["StreamingUnlock","_a","source","_b","size","tooltipId","_c","tooltipPlace","_d","feedbackPlacement","onChoose","onChooserChange","gatesContainer","t","useTranslation","gates","getVideoSourceGates","callAnswered","useSelector","state","currentCall","accepted","_e","useState","choosing","setChoosing","_f","pendingGate","setPendingGate","_g","feedback","setFeedback","feedbackTimer","useRef","pressedWidth","undefined","mounted","rowMode","rowOpen","useEffect","current","clearTimeout","id","length","gate","answerToOpen","needsAnswer","isDtmfGate","showFeedback","next","setTimeout","ok","openGate","__awaiter","gateId","hint","message","openStreamingGate","sent","console","error","error_1","code","StreamingRequestError","status","iconSize","gateIcon","base","faLockOpen","faUnlock","faCircleNotch","faCheck","faTriangleExclamation","gateIconClass","gateName","name","description","gateTooltip","concat","gatesTooltipId","waitingClasses","feedbackClasses","feedbackColors","shown","feedbackAttributes","role","closeChooser","gateButtons","React","className","map","result","resultTooltip","key","type","onClick","event","currentTarget","offsetWidth","disabled","style","minWidth","createElement","FontAwesomeIcon","icon","Button","variant","faXmark","Fragment","__assign","createPortal","CustomThemedTooltip","place","maxWidth"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),i=require("../../node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js");require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");var a=require("../../node_modules/react-i18next/dist/es/useTranslation.js");require("../../node_modules/react-redux/es/index.js");var n=require("../../utils/customHooks/useStreamingVideo.js"),o=require("../VideoStreamingSkeleton/index.js"),s=require("../VideoStreamingEmptyState/index.js"),r=require("../../node_modules/react-redux/es/hooks/useDispatch.js");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var u=c(e),l=function(e){if(!e||!e.videoWidth||!e.videoHeight)return null;var t=document.createElement("canvas");t.width=e.videoWidth,t.height=e.videoHeight;var i=t.getContext("2d");return i?(i.drawImage(e,0,0,t.width,t.height),t.toDataURL("image/jpeg",.92)):null},d=e.memo(function(c){var d=c.source,p=c.active,m=void 0===p||p,f=c.className,v=void 0===f?"":f,g=c.videoClassName,h=void 0===g?"":g,x=c.overlayClassName,w=void 0===x?"pi-rounded-lg":x,b=c.reconnectingClassName,j=void 0===b?"pi-bottom-3":b,y=c.videoRef,N=a.useTranslation().t,q=r.useDispatch(),S=e.useRef(null),E=y||S,_=e.useState(null),R=_[0],V=_[1],k=e.useRef(null),C=n.useStreamingVideo(d.id,d.whep,m,function(e){"reconnecting"===e.state.status?k.current||(k.current=l(E.current),V(k.current)):k.current&&(k.current=null,V(null))}),H=C.state,I=C.stream;e.useEffect(function(){var e=E.current;e&&(e.srcObject!==I&&(e.srcObject=I),I&&e.play().catch(function(){}))},[I,E]);var P,W=function(){var e=E.current;e&&e.videoWidth&&e.videoHeight&&q.streaming.setSourceAspectRatio({source:d.id,aspectRatio:e.videoWidth/e.videoHeight})},D="playing"===H.status||"reconnecting"===H.status;return"codec"===H.failure?P=N("VideoStreaming.The browser cannot play the video format of this source"):"forbidden"===H.failure&&(P=N("VideoStreaming.You are not allowed to watch this video source")),u.default.createElement("div",{className:"pi-relative pi-overflow-hidden ".concat(v),"data-streaming-video":H.status},u.default.createElement("video",{ref:E,muted:!0,autoPlay:!0,playsInline:!0,disablePictureInPicture:!0,onLoadedMetadata:W,onResize:W,className:"pi-w-full pi-h-full pi-object-contain pi-bg-black pi-transition-opacity pi-duration-300 ".concat(D?"pi-opacity-100":"pi-opacity-0"," ").concat(h)}),"connecting"===H.status&&u.default.createElement(o.default,{className:"pi-absolute pi-inset-0 pi-w-full pi-h-full ".concat(w)}),"unavailable"===H.status&&u.default.createElement(s.default,{className:"pi-absolute pi-inset-0 pi-w-full pi-h-full ".concat(w),message:P}),"reconnecting"===H.status&&R&&u.default.createElement("img",{src:R,alt:"",className:"pi-absolute pi-inset-0 pi-w-full pi-h-full pi-object-contain ".concat(h)}),"reconnecting"===H.status&&u.default.createElement("div",{className:"pi-absolute ".concat(j," pi-left-1/2 -pi-translate-x-1/2 pi-flex pi-items-center pi-whitespace-nowrap pi-gap-1.5 pi-rounded-full pi-bg-black/60 pi-px-2.5 pi-py-1 pi-text-xs pi-font-medium pi-text-white")},u.default.createElement(t.FontAwesomeIcon,{icon:i.faCircleNotch,className:"pi-h-3 pi-w-3 pi-animate-spin"}),N("VideoStreaming.Reconnecting")))});exports.captureVideoFrame=l,exports.default=d;
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/StreamingVideo/index.tsx"],"sourcesContent":["// Copyright (C) 2025 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { FC, memo, RefObject, useEffect, useRef, useState } from 'react'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { faCircleNotch } from '@fortawesome/free-solid-svg-icons'\nimport { useTranslation } from 'react-i18next'\nimport { useDispatch } from 'react-redux'\nimport type { Dispatch } from '../../store'\nimport type { VideoSourceType } from '../../models/streaming'\nimport { useStreamingVideo } from '../../utils/customHooks/useStreamingVideo'\nimport VideoStreamingSkeleton from '../VideoStreamingSkeleton'\nimport VideoStreamingEmptyState from '../VideoStreamingEmptyState'\n\n/**\n * Live video of an \"rtsp\" video source (door intercom).\n *\n * The video is always muted: the audio of the intercom is the SIP call itself.\n * The whole picture is shown (letterboxed if needed): its aspect ratio is stored to size the box.\n */\nconst StreamingVideo: FC<StreamingVideoProps> = ({\n source,\n active = true,\n className = '',\n videoClassName = '',\n overlayClassName = 'pi-rounded-lg',\n reconnectingClassName = 'pi-bottom-3',\n videoRef,\n}) => {\n const { t } = useTranslation()\n const dispatch = useDispatch<Dispatch>()\n const ownVideoRef = useRef<HTMLVideoElement>(null)\n const ref = videoRef || ownVideoRef\n // last frame shown while reconnecting: the <video> turns black when the stalled connection\n // is closed, so the frame is grabbed when the stall is detected, before the close\n const [frozenFrame, setFrozenFrame] = useState<string | null>(null)\n const frozenFrameRef = useRef<string | null>(null)\n const { state, stream } = useStreamingVideo(source.id, source.whep, active, (next) => {\n if (next.state.status === 'reconnecting') {\n if (!frozenFrameRef.current) {\n // synchronous: the stalled connection is still open here\n frozenFrameRef.current = captureVideoFrame(ref.current)\n setFrozenFrame(frozenFrameRef.current)\n }\n } else if (frozenFrameRef.current) {\n frozenFrameRef.current = null\n setFrozenFrame(null)\n }\n })\n\n useEffect(() => {\n const video = ref.current\n if (!video) return\n if (video.srcObject !== stream) {\n video.srcObject = stream\n }\n if (stream) {\n video.play().catch(() => {})\n }\n }, [stream, ref])\n\n // the size of the video is known with the first frame and changes if the source changes it\n const storeAspectRatio = () => {\n const video = ref.current\n if (video && video.videoWidth && video.videoHeight) {\n dispatch.streaming.setSourceAspectRatio({\n source: source.id,\n aspectRatio: video.videoWidth / video.videoHeight,\n })\n }\n }\n\n // the last frame stays visible while reconnecting\n const showVideo = state.status === 'playing' || state.status === 'reconnecting'\n\n let unavailableMessage: string | undefined\n if (state.failure === 'codec') {\n unavailableMessage = t('VideoStreaming.The browser cannot play the video format of this source')\n } else if (state.failure === 'forbidden') {\n unavailableMessage = t('VideoStreaming.You are not allowed to watch this video source')\n }\n\n return (\n <div\n className={`pi-relative pi-overflow-hidden ${className}`}\n data-streaming-video={state.status}\n >\n <video\n ref={ref}\n muted\n autoPlay\n playsInline\n disablePictureInPicture\n onLoadedMetadata={storeAspectRatio}\n onResize={storeAspectRatio}\n className={`pi-w-full pi-h-full pi-object-contain pi-bg-black pi-transition-opacity pi-duration-300 ${\n showVideo ? 'pi-opacity-100' : 'pi-opacity-0'\n } ${videoClassName}`}\n />\n {state.status === 'connecting' && (\n <VideoStreamingSkeleton\n className={`pi-absolute pi-inset-0 pi-w-full pi-h-full ${overlayClassName}`}\n />\n )}\n {state.status === 'unavailable' && (\n <VideoStreamingEmptyState\n className={`pi-absolute pi-inset-0 pi-w-full pi-h-full ${overlayClassName}`}\n message={unavailableMessage}\n />\n )}\n {state.status === 'reconnecting' && frozenFrame && (\n <img\n src={frozenFrame}\n alt=''\n className={`pi-absolute pi-inset-0 pi-w-full pi-h-full pi-object-contain ${videoClassName}`}\n />\n )}\n {state.status === 'reconnecting' && (\n // bottom centre: devices often print the time in the top corners\n <div\n className={`pi-absolute ${reconnectingClassName} pi-left-1/2 -pi-translate-x-1/2 pi-flex pi-items-center pi-whitespace-nowrap pi-gap-1.5 pi-rounded-full pi-bg-black/60 pi-px-2.5 pi-py-1 pi-text-xs pi-font-medium pi-text-white`}\n >\n <FontAwesomeIcon icon={faCircleNotch} className='pi-h-3 pi-w-3 pi-animate-spin' />\n {t('VideoStreaming.Reconnecting')}\n </div>\n )}\n </div>\n )\n}\n\n/**\n * Current frame of a video as a JPEG data URI, null when there is no frame\n */\nexport const captureVideoFrame = (video: HTMLVideoElement | null): string | null => {\n if (!video || !video.videoWidth || !video.videoHeight) return null\n const canvas = document.createElement('canvas')\n canvas.width = video.videoWidth\n canvas.height = video.videoHeight\n const context = canvas.getContext('2d')\n if (!context) return null\n context.drawImage(video, 0, 0, canvas.width, canvas.height)\n return canvas.toDataURL('image/jpeg', 0.92)\n}\n\nexport interface StreamingVideoProps {\n source: VideoSourceType\n // the session runs only while active (e.g. the island is expanded)\n active?: boolean\n className?: string\n videoClassName?: string\n // classes of the skeleton and empty state overlays (rounded corners)\n overlayClassName?: string\n // position of the \"reconnecting\" badge (bottom centre), e.g. above an overlay bar\n reconnectingClassName?: string\n videoRef?: RefObject<HTMLVideoElement>\n}\n\nexport default memo(StreamingVideo)\n"],"names":["captureVideoFrame","video","videoWidth","videoHeight","canvas","document","createElement","width","height","context","getContext","drawImage","toDataURL","memo","_a","source","_b","active","_c","className","_d","videoClassName","_e","overlayClassName","_f","reconnectingClassName","videoRef","t","useTranslation","dispatch","useDispatch","ownVideoRef","useRef","ref","_g","useState","frozenFrame","setFrozenFrame","frozenFrameRef","_h","useStreamingVideo","id","whep","next","state","status","current","stream","useEffect","srcObject","play","catch","unavailableMessage","storeAspectRatio","streaming","setSourceAspectRatio","aspectRatio","showVideo","failure","React","concat","muted","autoPlay","playsInline","disablePictureInPicture","onLoadedMetadata","onResize","VideoStreamingSkeleton","VideoStreamingEmptyState","message","src","alt","FontAwesomeIcon","icon","faCircleNotch"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");require("../../node_modules/react-redux/es/index.js");var t=require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),i=require("../../node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js"),a=require("../../node_modules/@headlessui/react/dist/components/menu/menu.js"),r=require("../../node_modules/@headlessui/react/dist/components/transition/transition.js"),n=require("../../lib/user/default_device.js"),o=require("../../utils/customHooks/useEventListener.js"),l=require("../../utils/genericFunctions/eventDispatch.js"),c=require("../../utils/genericFunctions/localStorage.js");require("../../node_modules/tslib/tslib.es6.js"),require("../../store/index.js");var d=require("../CustomThemedTooltip.js");require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");var s=require("../../node_modules/react-i18next/dist/es/useTranslation.js"),p=require("../../node_modules/react-redux/es/hooks/useSelector.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var m=u(e);exports.default=function(u){u.isTransferView;var f=p.useSelector(function(e){return e.webrtc}).sipcall,g=s.useTranslation().t,v=p.useSelector(function(e){return e.player.remoteAudio}),y=e.useState(c.getJSONItem("phone-island-audio-input-device").deviceId||null),h=y[0],x=y[1],k=e.useState(c.getJSONItem("phone-island-audio-output-device").deviceId||null),b=k[0],E=k[1],I=function(e){x(e),f.webrtcStuff.myStream?null==f||f.replaceTracks({tracks:[{type:"audio",mid:"0",capture:{deviceId:{exact:e}}}],success:function(){console.info("Audio input device switch success!"),c.setJSONItem("phone-island-audio-input-device",{deviceId:e}),l.eventDispatch("phone-island-call-audio-input-switched",{})},error:function(e){console.error("Audio input device switch error:",e)}}):(c.setJSONItem("phone-island-audio-input-device",{deviceId:e}),l.eventDispatch("phone-island-call-audio-input-switched",{}))};o.useEventListener("phone-island-call-audio-input-switch",function(e){I(e.deviceId)});var w=function(e){E(e),null==v||v.current.setSinkId(e).then(function(){console.info("Audio output device switch success!"),c.setJSONItem("phone-island-audio-output-device",{deviceId:e}),l.eventDispatch("phone-island-call-audio-output-switched",{})}).catch(function(e){console.error("Audio output device switch error:",e)})};o.useEventListener("phone-island-call-audio-output-switch",function(e){w(e.deviceId)});var N=e.useState([]),S=N[0],j=N[1];e.useEffect(function(){var e=function(){navigator.mediaDevices.enumerateDevices().then(function(e){j(e)}).catch(function(e){console.error("error",e)})};return e(),navigator.mediaDevices.addEventListener("devicechange",e),function(){navigator.mediaDevices.removeEventListener("devicechange",e)}},[b,h]);var C=p.useSelector(function(e){return e.darkTheme}).theme,F=function(e){l.eventDispatch("phone-island-theme-change",{selectedTheme:e})},q=p.useSelector(function(e){return e.currentCall}).transferring,A=p.useSelector(function(e){return e.listen}).isListen;return m.default.createElement(m.default.Fragment,null,n.isWebRTC()?m.default.createElement(a.Menu,{as:"div",className:"relative inline-block text-left","data-stop-propagation":!0,"data-tooltip-id":"tooltip-left-settings-devices","data-tooltip-content":g("Tooltip.Settings")},m.default.createElement(a.MenuButton,{className:"pi-bg-transparent dark:enabled:hover:pi-bg-gray-600/30 enabled:hover:pi-bg-gray-200/70 dark:focus:pi-ring-gray-500 focus:pi-ring-gray-400 pi-flex pi-font-light pi-content-center pi-items-center pi-justify-center pi-tracking-wide pi-duration-200 pi-transform pi-outline-none focus:pi-ring-2 focus:pi-z-20 focus:pi-ring-offset-2 disabled:pi-opacity-75 dark:pi-text-white pi-text-gray-600 pi-border pi-border-transparent focus:pi-ring-offset-gray-200 dark:focus:pi-ring-offset-black pi-rounded-full pi-text-sm pi-leading-4 pi-h-12 pi-w-12 pi-col-start-auto pi-transition-color pi-shrink-0","data-stop-propagation":!0},m.default.createElement(t.FontAwesomeIcon,{size:"xl",icon:i.faEllipsis,className:"dark:pi-text-gray-200 pi-text-gray-700","data-stop-propagation":!0})),m.default.createElement(r.Transition,{as:e.Fragment,enter:"transition ease-out duration-100",enterFrom:"transform opacity-0 scale-95",enterTo:"transform opacity-100 scale-100",leave:"transition ease-in duration-75",leaveFrom:"transform opacity-100 scale-100",leaveTo:"transform opacity-0 scale-95"},m.default.createElement(a.MenuItems,{className:"".concat(q?"pi-right-[1.5rem]":"pi-right-[4.5rem]"," \n ").concat(A?"pi-max-h-[9.125rem] pi-mt-[-8.5rem]":"pi-max-h-[13.125rem] pi-mt-[-12.5rem]","\n pi-z-50 pi-absolute pi-w-56 pi-origin-top-right pi-rounded-md pi-shadow-lg pi-ring-1 dark:pi-bg-gray-950 pi-bg-gray-50 pi-bg-opacity-[0.99] dark:pi-bg-opacity-[0.99] pi-ring-black pi-ring-opacity-5 pi-focus:outline-none pi-cursor-auto pi-border-gray-300 dark:pi-border-gray-600 pi-border pi-py-2 pi-overflow-y-auto pi-scrollbar-thin pi-scrollbar-thumb-gray-400 pi-dark:scrollbar-thumb-gray-400 pi-scrollbar-thumb-rounded-full pi-scrollbar-thumb-opacity-50 dark:pi-scrollbar-track-gray-900 pi-scrollbar-track-gray-200 pi-dark:scrollbar-track-gray-900 pi-scrollbar-track-rounded-full pi-scrollbar-track-opacity-25"),"data-stop-propagation":!0},m.default.createElement("div",{className:"","data-stop-propagation":!0},!A&&m.default.createElement(m.default.Fragment,null," ",m.default.createElement("div",{className:"pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4"},g("DropdownContent.Microphones")),S.filter(function(e){return"audioinput"===(null==e?void 0:e.kind)}).map(function(e,r){return m.default.createElement(a.MenuItem,{key:r},function(a){var n=a.active;return m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 ".concat(n?"pi-bg-gray-200 dark:pi-bg-gray-700":""),onClick:function(){return I(e.deviceId)},"data-stop-propagation":!0},h===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),!h&&"default"===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faMicrophone,className:"".concat(null!==h&&""!==h&&h!==(null==e?void 0:e.deviceId)?"pi-ml-6":""!==h&&null!==h&&h===(null==e?void 0:e.deviceId)?"":null===h&&"default"!==(null==e?void 0:e.deviceId)?"pi-ml-6":""," dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1")}),m.default.createElement("div",{className:"".concat(n?"dark:pi-text-gray-50 pi-text-gray-900":"dark:pi-text-gray-50 pi-text-gray-700")},(null==e?void 0:e.label)||"Input device ".concat(r+1)))})}),m.default.createElement("div",{className:"pi-relative pi-py-2"},m.default.createElement("div",{className:"pi-absolute pi-inset-0 pi-flex pi-items-center","aria-hidden":"true"},m.default.createElement("div",{className:"pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600"})))),m.default.createElement("div",{className:"pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4","data-stop-propagation":!0},g("DropdownContent.Speakers")),S.filter(function(e){return"audiooutput"===(null==e?void 0:e.kind)}).map(function(e,r){return m.default.createElement(a.MenuItem,{key:r},function(a){var n=a.active;return m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 ".concat(n?"pi-bg-gray-200 dark:pi-bg-gray-700":""),onClick:function(){return w(null==e?void 0:e.deviceId)},"data-stop-propagation":!0},b===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),!b&&"default"===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faVolumeHigh,className:"".concat(null!==b&&""!==b&&b!==(null==e?void 0:e.deviceId)?"pi-ml-6":""!==b&&null!==b&&b===(null==e?void 0:e.deviceId)?"":null===b&&"default"!==(null==e?void 0:e.deviceId)?"pi-ml-6":""," dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1")}),m.default.createElement("div",{className:"".concat(n?"dark:pi-text-gray-50 pi-text-gray-900":"dark:pi-text-gray-50 pi-text-gray-700")},(null==e?void 0:e.label)||"Output device ".concat(r+1)))})}),m.default.createElement("div",{className:"pi-relative pi-py-2"},m.default.createElement("div",{className:"pi-absolute pi-inset-0 pi-flex pi-items-center","aria-hidden":"true"},m.default.createElement("div",{className:"pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600"}))),m.default.createElement("div",{className:"pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4","data-stop-propagation":!0},g("DropdownContent.Theme")),m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700",onClick:function(){return F("dark")},"data-stop-propagation":!0},"dark"===C&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.57rem]"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faMoon,className:"".concat("dark"!==C?"pi-ml-[1.49rem] pi-mr-[0.42rem]":"pi-mr-[0.4rem]"," dark:pi-text-gray-100 pi-text-gray-600 ")}),m.default.createElement("div",null,g("DropdownContent.Dark"))),m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700",onClick:function(){return F("light")},"data-stop-propagation":!0},"light"===C&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.4rem]"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faSun,className:"".concat("light"!==C?"pi-ml-[1.4rem] pi-mr-[0.27rem]":"pi-mr-[0.28rem]"," dark:pi-text-gray-100 pi-text-gray-600 ")}),m.default.createElement("div",null,g("DropdownContent.Light"))))))):m.default.createElement("div",null),m.default.createElement(d.CustomThemedTooltip,{id:"tooltip-left-settings-devices",place:"left"}))};
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");require("../../node_modules/react-redux/es/index.js");var t=require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),i=require("../../node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js"),a=require("../../node_modules/@headlessui/react/dist/components/menu/menu.js"),r=require("../../node_modules/@headlessui/react/dist/components/transition/transition.js"),n=require("../../lib/user/default_device.js"),o=require("../../utils/customHooks/useEventListener.js"),l=require("../../utils/genericFunctions/eventDispatch.js"),c=require("../../utils/genericFunctions/localStorage.js");require("../../node_modules/tslib/tslib.es6.js"),require("../../store/index.js"),require("../../services/user.js");var d=require("../CustomThemedTooltip.js");require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");var s=require("../../node_modules/react-i18next/dist/es/useTranslation.js"),p=require("../../node_modules/react-redux/es/hooks/useSelector.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var m=u(e);exports.default=function(u){u.isTransferView;var f=p.useSelector(function(e){return e.webrtc}).sipcall,g=s.useTranslation().t,v=p.useSelector(function(e){return e.player.remoteAudio}),y=e.useState(c.getJSONItem("phone-island-audio-input-device").deviceId||null),h=y[0],x=y[1],k=e.useState(c.getJSONItem("phone-island-audio-output-device").deviceId||null),b=k[0],E=k[1],I=function(e){x(e),f.webrtcStuff.myStream?null==f||f.replaceTracks({tracks:[{type:"audio",mid:"0",capture:{deviceId:{exact:e}}}],success:function(){console.info("Audio input device switch success!"),c.setJSONItem("phone-island-audio-input-device",{deviceId:e}),l.eventDispatch("phone-island-call-audio-input-switched",{})},error:function(e){console.error("Audio input device switch error:",e)}}):(c.setJSONItem("phone-island-audio-input-device",{deviceId:e}),l.eventDispatch("phone-island-call-audio-input-switched",{}))};o.useEventListener("phone-island-call-audio-input-switch",function(e){I(e.deviceId)});var w=function(e){E(e),null==v||v.current.setSinkId(e).then(function(){console.info("Audio output device switch success!"),c.setJSONItem("phone-island-audio-output-device",{deviceId:e}),l.eventDispatch("phone-island-call-audio-output-switched",{})}).catch(function(e){console.error("Audio output device switch error:",e)})};o.useEventListener("phone-island-call-audio-output-switch",function(e){w(e.deviceId)});var N=e.useState([]),j=N[0],S=N[1];e.useEffect(function(){var e=function(){navigator.mediaDevices.enumerateDevices().then(function(e){S(e)}).catch(function(e){console.error("error",e)})};return e(),navigator.mediaDevices.addEventListener("devicechange",e),function(){navigator.mediaDevices.removeEventListener("devicechange",e)}},[b,h]);var C=p.useSelector(function(e){return e.darkTheme}).theme,q=function(e){l.eventDispatch("phone-island-theme-change",{selectedTheme:e})},F=p.useSelector(function(e){return e.currentCall}).transferring,A=p.useSelector(function(e){return e.listen}).isListen;return m.default.createElement(m.default.Fragment,null,n.isWebRTC()?m.default.createElement(a.Menu,{as:"div",className:"relative inline-block text-left","data-stop-propagation":!0,"data-tooltip-id":"tooltip-left-settings-devices","data-tooltip-content":g("Tooltip.Settings")},m.default.createElement(a.MenuButton,{className:"pi-bg-transparent dark:enabled:hover:pi-bg-gray-600/30 enabled:hover:pi-bg-gray-200/70 dark:focus:pi-ring-gray-500 focus:pi-ring-gray-400 pi-flex pi-font-light pi-content-center pi-items-center pi-justify-center pi-tracking-wide pi-duration-200 pi-transform pi-outline-none focus:pi-ring-2 focus:pi-z-20 focus:pi-ring-offset-2 disabled:pi-opacity-75 dark:pi-text-white pi-text-gray-600 pi-border pi-border-transparent focus:pi-ring-offset-gray-200 dark:focus:pi-ring-offset-black pi-rounded-full pi-text-sm pi-leading-4 pi-h-12 pi-w-12 pi-col-start-auto pi-transition-color pi-shrink-0","data-stop-propagation":!0},m.default.createElement(t.FontAwesomeIcon,{size:"xl",icon:i.faEllipsis,className:"dark:pi-text-gray-200 pi-text-gray-700","data-stop-propagation":!0})),m.default.createElement(r.Transition,{as:e.Fragment,enter:"transition ease-out duration-100",enterFrom:"transform opacity-0 scale-95",enterTo:"transform opacity-100 scale-100",leave:"transition ease-in duration-75",leaveFrom:"transform opacity-100 scale-100",leaveTo:"transform opacity-0 scale-95"},m.default.createElement(a.MenuItems,{className:"".concat(F?"pi-right-[1.5rem]":"pi-right-[4.5rem]"," \n ").concat(A?"pi-max-h-[9.125rem] pi-mt-[-8.5rem]":"pi-max-h-[13.125rem] pi-mt-[-12.5rem]","\n pi-z-50 pi-absolute pi-w-56 pi-origin-top-right pi-rounded-md pi-shadow-lg pi-ring-1 dark:pi-bg-gray-950 pi-bg-gray-50 pi-bg-opacity-[0.99] dark:pi-bg-opacity-[0.99] pi-ring-black pi-ring-opacity-5 pi-focus:outline-none pi-cursor-auto pi-border-gray-300 dark:pi-border-gray-600 pi-border pi-py-2 pi-overflow-y-auto pi-scrollbar-thin pi-scrollbar-thumb-gray-400 pi-dark:scrollbar-thumb-gray-400 pi-scrollbar-thumb-rounded-full pi-scrollbar-thumb-opacity-50 dark:pi-scrollbar-track-gray-900 pi-scrollbar-track-gray-200 pi-dark:scrollbar-track-gray-900 pi-scrollbar-track-rounded-full pi-scrollbar-track-opacity-25"),"data-stop-propagation":!0},m.default.createElement("div",{className:"","data-stop-propagation":!0},!A&&m.default.createElement(m.default.Fragment,null," ",m.default.createElement("div",{className:"pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4"},g("DropdownContent.Microphones")),j.filter(function(e){return"audioinput"===(null==e?void 0:e.kind)}).map(function(e,r){return m.default.createElement(a.MenuItem,{key:r},function(a){var n=a.active;return m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 ".concat(n?"pi-bg-gray-200 dark:pi-bg-gray-700":""),onClick:function(){return I(e.deviceId)},"data-stop-propagation":!0},h===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),!h&&"default"===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faMicrophone,className:"".concat(null!==h&&""!==h&&h!==(null==e?void 0:e.deviceId)?"pi-ml-6":""!==h&&null!==h&&h===(null==e?void 0:e.deviceId)?"":null===h&&"default"!==(null==e?void 0:e.deviceId)?"pi-ml-6":""," dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1")}),m.default.createElement("div",{className:"".concat(n?"dark:pi-text-gray-50 pi-text-gray-900":"dark:pi-text-gray-50 pi-text-gray-700")},(null==e?void 0:e.label)||"Input device ".concat(r+1)))})}),m.default.createElement("div",{className:"pi-relative pi-py-2"},m.default.createElement("div",{className:"pi-absolute pi-inset-0 pi-flex pi-items-center","aria-hidden":"true"},m.default.createElement("div",{className:"pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600"})))),m.default.createElement("div",{className:"pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4","data-stop-propagation":!0},g("DropdownContent.Speakers")),j.filter(function(e){return"audiooutput"===(null==e?void 0:e.kind)}).map(function(e,r){return m.default.createElement(a.MenuItem,{key:r},function(a){var n=a.active;return m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 ".concat(n?"pi-bg-gray-200 dark:pi-bg-gray-700":""),onClick:function(){return w(null==e?void 0:e.deviceId)},"data-stop-propagation":!0},b===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),!b&&"default"===(null==e?void 0:e.deviceId)&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-2"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faVolumeHigh,className:"".concat(null!==b&&""!==b&&b!==(null==e?void 0:e.deviceId)?"pi-ml-6":""!==b&&null!==b&&b===(null==e?void 0:e.deviceId)?"":null===b&&"default"!==(null==e?void 0:e.deviceId)?"pi-ml-6":""," dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1")}),m.default.createElement("div",{className:"".concat(n?"dark:pi-text-gray-50 pi-text-gray-900":"dark:pi-text-gray-50 pi-text-gray-700")},(null==e?void 0:e.label)||"Output device ".concat(r+1)))})}),m.default.createElement("div",{className:"pi-relative pi-py-2"},m.default.createElement("div",{className:"pi-absolute pi-inset-0 pi-flex pi-items-center","aria-hidden":"true"},m.default.createElement("div",{className:"pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600"}))),m.default.createElement("div",{className:"pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4","data-stop-propagation":!0},g("DropdownContent.Theme")),m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700",onClick:function(){return q("dark")},"data-stop-propagation":!0},"dark"===C&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.57rem]"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faMoon,className:"".concat("dark"!==C?"pi-ml-[1.49rem] pi-mr-[0.42rem]":"pi-mr-[0.4rem]"," dark:pi-text-gray-100 pi-text-gray-600 ")}),m.default.createElement("div",null,g("DropdownContent.Dark"))),m.default.createElement("div",{className:"pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700",onClick:function(){return q("light")},"data-stop-propagation":!0},"light"===C&&m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faCheck,className:"pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.4rem]"}),m.default.createElement(t.FontAwesomeIcon,{size:"lg",icon:i.faSun,className:"".concat("light"!==C?"pi-ml-[1.4rem] pi-mr-[0.27rem]":"pi-mr-[0.28rem]"," dark:pi-text-gray-100 pi-text-gray-600 ")}),m.default.createElement("div",null,g("DropdownContent.Light"))))))):m.default.createElement("div",null),m.default.createElement(d.CustomThemedTooltip,{id:"tooltip-left-settings-devices",place:"left"}))};
|
|
2
2
|
//# sourceMappingURL=DropdownContent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownContent.js","sources":["../../../src/components/SwitchInputView/DropdownContent.tsx"],"sourcesContent":["// Copyright (C) 2024 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { type FC, ComponentProps, Fragment, useState, useEffect } from 'react'\nimport { useSelector } from 'react-redux'\nimport { RootState } from '../../store'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n faCheck,\n faEllipsis,\n faMicrophone,\n faMoon,\n faSun,\n faVolumeHigh,\n} from '@fortawesome/free-solid-svg-icons'\nimport { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'\nimport { isWebRTC } from '../../lib/user/default_device'\nimport { eventDispatch, getJSONItem, setJSONItem, useEventListener } from '../../utils'\nimport { CustomThemedTooltip } from '../CustomThemedTooltip'\nimport { useTranslation } from 'react-i18next'\n\nconst DropdownContent: FC<DropdownContentProps> = ({ isTransferView }) => {\n const { sipcall }: any = useSelector((state: RootState) => state.webrtc)\n const { t } = useTranslation()\n const remoteAudioElement: any = useSelector((state: RootState) => state.player.remoteAudio)\n\n const [selectedAudioInput, setSelectedAudioInput] = useState<string | null>(\n getJSONItem('phone-island-audio-input-device').deviceId || null,\n )\n const [selectedAudioOutput, setSelectedAudioOutput] = useState<string | null>(\n getJSONItem('phone-island-audio-output-device').deviceId || null,\n )\n\n const handleClickAudioInput = (audioInputDevice: string) => {\n setSelectedAudioInput(audioInputDevice)\n\n if (sipcall.webrtcStuff.myStream) {\n sipcall?.replaceTracks({\n tracks: [\n {\n type: 'audio',\n mid: '0', // We assume mid 0 is audio\n capture: { deviceId: { exact: audioInputDevice } },\n },\n ],\n success: function () {\n console.info('Audio input device switch success!')\n // set device to localstorage\n setJSONItem('phone-island-audio-input-device', { deviceId: audioInputDevice })\n\n // dispatch event\n eventDispatch('phone-island-call-audio-input-switched', {})\n },\n error: function (err) {\n console.error('Audio input device switch error:', err)\n },\n })\n } else {\n // set device to localstorage\n setJSONItem('phone-island-audio-input-device', { deviceId: audioInputDevice })\n\n // dispatch event\n eventDispatch('phone-island-call-audio-input-switched', {})\n }\n }\n useEventListener('phone-island-call-audio-input-switch', (data: DeviceInputOutputTypes) => {\n handleClickAudioInput(data.deviceId)\n })\n\n const handleClickAudioOutput = (audioOutputDevice: string) => {\n setSelectedAudioOutput(audioOutputDevice)\n\n remoteAudioElement?.current\n .setSinkId(audioOutputDevice)\n .then(function () {\n console.info('Audio output device switch success!')\n // set device to localstorage\n setJSONItem('phone-island-audio-output-device', { deviceId: audioOutputDevice })\n\n // dispatch event\n eventDispatch('phone-island-call-audio-output-switched', {})\n })\n .catch(function (err) {\n console.error('Audio output device switch error:', err)\n })\n }\n useEventListener('phone-island-call-audio-output-switch', (data: DeviceInputOutputTypes) => {\n handleClickAudioOutput(data.deviceId)\n })\n\n const [actualDevice, setActualDevice]: any = useState([])\n\n useEffect(() => {\n const checkInputOutputDevices = () => {\n navigator.mediaDevices\n .enumerateDevices()\n .then((deviceInfos) => {\n setActualDevice(deviceInfos)\n })\n .catch((error) => {\n console.error('error', error)\n })\n }\n\n checkInputOutputDevices()\n\n navigator.mediaDevices.addEventListener('devicechange', checkInputOutputDevices)\n\n return () => {\n navigator.mediaDevices.removeEventListener('devicechange', checkInputOutputDevices)\n }\n }, [selectedAudioOutput, selectedAudioInput])\n\n const { theme } = useSelector((state: RootState) => state.darkTheme)\n\n const handleSelectTheme = (clickedTheme: string) => {\n eventDispatch('phone-island-theme-change', { selectedTheme: clickedTheme })\n }\n const { transferring } = useSelector((state: RootState) => state.currentCall)\n const { isListen } = useSelector((state: RootState) => state.listen)\n\n return (\n <>\n {isWebRTC() ? (\n <Menu\n as='div'\n className='relative inline-block text-left'\n data-stop-propagation={true}\n data-tooltip-id='tooltip-left-settings-devices'\n data-tooltip-content={t('Tooltip.Settings')}\n >\n <MenuButton\n className='pi-bg-transparent dark:enabled:hover:pi-bg-gray-600/30 enabled:hover:pi-bg-gray-200/70 dark:focus:pi-ring-gray-500 focus:pi-ring-gray-400 pi-flex pi-font-light pi-content-center pi-items-center pi-justify-center pi-tracking-wide pi-duration-200 pi-transform pi-outline-none focus:pi-ring-2 focus:pi-z-20 focus:pi-ring-offset-2 disabled:pi-opacity-75 dark:pi-text-white pi-text-gray-600 pi-border pi-border-transparent focus:pi-ring-offset-gray-200 dark:focus:pi-ring-offset-black pi-rounded-full pi-text-sm pi-leading-4 pi-h-12 pi-w-12 pi-col-start-auto pi-transition-color pi-shrink-0'\n data-stop-propagation={true}\n >\n <FontAwesomeIcon\n size='xl'\n icon={faEllipsis}\n className='dark:pi-text-gray-200 pi-text-gray-700'\n data-stop-propagation={true}\n />\n </MenuButton>\n\n <Transition\n as={Fragment}\n enter='transition ease-out duration-100'\n enterFrom='transform opacity-0 scale-95'\n enterTo='transform opacity-100 scale-100'\n leave='transition ease-in duration-75'\n leaveFrom='transform opacity-100 scale-100'\n leaveTo='transform opacity-0 scale-95'\n >\n <MenuItems\n className={`${transferring ? 'pi-right-[1.5rem]' : 'pi-right-[4.5rem]'} \n ${\n isListen\n ? 'pi-max-h-[9.125rem] pi-mt-[-8.5rem]'\n : 'pi-max-h-[13.125rem] pi-mt-[-12.5rem]'\n }\n pi-z-50 pi-absolute pi-w-56 pi-origin-top-right pi-rounded-md pi-shadow-lg pi-ring-1 dark:pi-bg-gray-950 pi-bg-gray-50 pi-bg-opacity-[0.99] dark:pi-bg-opacity-[0.99] pi-ring-black pi-ring-opacity-5 pi-focus:outline-none pi-cursor-auto pi-border-gray-300 dark:pi-border-gray-600 pi-border pi-py-2 pi-overflow-y-auto pi-scrollbar-thin pi-scrollbar-thumb-gray-400 pi-dark:scrollbar-thumb-gray-400 pi-scrollbar-thumb-rounded-full pi-scrollbar-thumb-opacity-50 dark:pi-scrollbar-track-gray-900 pi-scrollbar-track-gray-200 pi-dark:scrollbar-track-gray-900 pi-scrollbar-track-rounded-full pi-scrollbar-track-opacity-25`}\n data-stop-propagation={true}\n >\n <div className='' data-stop-propagation={true}>\n {!isListen && (\n <>\n {' '}\n {/* Microphones */}\n <div className='pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4'>\n {t('DropdownContent.Microphones')}\n </div>\n {actualDevice\n .filter((device) => device?.kind === 'audioinput')\n .map((audioDevice, index) => (\n <MenuItem key={index}>\n {({ active }: any) => (\n <div\n className={`pi-flex pi-py-2 pi-px-2 ${\n active ? 'pi-bg-gray-200 dark:pi-bg-gray-700' : ''\n }`}\n onClick={() => handleClickAudioInput(audioDevice.deviceId)}\n data-stop-propagation={true}\n >\n {/* faCheck on selectedAudioInput */}\n {selectedAudioInput === audioDevice?.deviceId && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n {/* faCheck if user has no selectedAudioInput and audioDevice is default */}\n {!selectedAudioInput && audioDevice?.deviceId === 'default' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n <FontAwesomeIcon\n size='lg'\n icon={faMicrophone}\n className={`${\n selectedAudioInput !== null &&\n selectedAudioInput !== '' &&\n selectedAudioInput !== audioDevice?.deviceId\n ? 'pi-ml-6'\n : selectedAudioInput !== '' &&\n selectedAudioInput !== null &&\n selectedAudioInput === audioDevice?.deviceId\n ? ''\n : selectedAudioInput === null &&\n audioDevice?.deviceId !== 'default'\n ? 'pi-ml-6'\n : ''\n } dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1`}\n />\n <div\n className={`${\n active\n ? 'dark:pi-text-gray-50 pi-text-gray-900'\n : 'dark:pi-text-gray-50 pi-text-gray-700'\n }`}\n >\n {audioDevice?.label || `Input device ${index + 1}`}\n </div>\n </div>\n )}\n </MenuItem>\n ))}\n {/* Divider */}\n <div className='pi-relative pi-py-2'>\n <div\n className='pi-absolute pi-inset-0 pi-flex pi-items-center'\n aria-hidden='true'\n >\n <div className='pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600' />\n </div>\n </div>\n </>\n )}\n\n {/* Speaker */}\n <div\n className='pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4'\n data-stop-propagation={true}\n >\n {t('DropdownContent.Speakers')}\n </div>\n {actualDevice\n .filter((device) => device?.kind === 'audiooutput')\n .map((audioDevice, index) => (\n <MenuItem key={index}>\n {({ active }: any) => (\n <div\n className={`pi-flex pi-py-2 pi-px-2 ${\n active ? 'pi-bg-gray-200 dark:pi-bg-gray-700' : ''\n }`}\n onClick={() => handleClickAudioOutput(audioDevice?.deviceId)}\n data-stop-propagation={true}\n >\n {/* faCheck on selectedAudioOutput */}\n {selectedAudioOutput === audioDevice?.deviceId && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n {/* faCheck if user has no selectedAudioInput and audioDevice is default */}\n {!selectedAudioOutput && audioDevice?.deviceId === 'default' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n <FontAwesomeIcon\n size='lg'\n icon={faVolumeHigh}\n className={`${\n selectedAudioOutput !== null &&\n selectedAudioOutput !== '' &&\n selectedAudioOutput !== audioDevice?.deviceId\n ? 'pi-ml-6'\n : selectedAudioOutput !== '' &&\n selectedAudioOutput !== null &&\n selectedAudioOutput === audioDevice?.deviceId\n ? ''\n : selectedAudioOutput === null &&\n audioDevice?.deviceId !== 'default'\n ? 'pi-ml-6'\n : ''\n } dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1`}\n />\n\n <div\n className={`${\n active\n ? 'dark:pi-text-gray-50 pi-text-gray-900'\n : 'dark:pi-text-gray-50 pi-text-gray-700'\n }`}\n >\n {audioDevice?.label || `Output device ${index + 1}`}\n </div>\n </div>\n )}\n </MenuItem>\n ))}\n {/* Divider */}\n <div className='pi-relative pi-py-2'>\n <div\n className='pi-absolute pi-inset-0 pi-flex pi-items-center'\n aria-hidden='true'\n >\n <div className='pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600' />\n </div>\n </div>\n {/* theme selection */}\n <div\n className='pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4'\n data-stop-propagation={true}\n >\n {t('DropdownContent.Theme')}\n </div>\n\n {/* dark theme */}\n <div\n className={`pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700`}\n onClick={() => handleSelectTheme('dark')}\n data-stop-propagation={true}\n >\n {theme === 'dark' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.57rem]'\n />\n )}\n <FontAwesomeIcon\n size='lg'\n icon={faMoon}\n className={`${\n theme !== 'dark' ? 'pi-ml-[1.49rem] pi-mr-[0.42rem]' : 'pi-mr-[0.4rem]'\n } dark:pi-text-gray-100 pi-text-gray-600 `}\n />\n\n <div>{t('DropdownContent.Dark')}</div>\n </div>\n\n {/* light theme */}\n <div\n className={`pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700`}\n onClick={() => handleSelectTheme('light')}\n data-stop-propagation={true}\n >\n {theme === 'light' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.4rem]'\n />\n )}\n\n <FontAwesomeIcon\n size='lg'\n icon={faSun}\n className={`${\n theme !== 'light' ? 'pi-ml-[1.4rem] pi-mr-[0.27rem]' : 'pi-mr-[0.28rem]'\n } dark:pi-text-gray-100 pi-text-gray-600 `}\n />\n <div>{t('DropdownContent.Light')}</div>\n </div>\n\n {/* Video\n <div className='pi-font-semibold pi-text-gray-700 pi-py-1 pi-px-4'>\n Video\n </div>\n {actualDevice\n .filter((device) => device.kind === 'videoinput')\n .map((videoDevice, index) => (\n <MenuItem key={index}>\n {({ active }) => (\n <div className='pi-text-gray-700'>\n Webcam: {videoDevice.label || `Device ${index + 1}`}\n </div>\n )}\n </MenuItem>\n ))}*/}\n </div>\n </MenuItems>\n </Transition>\n </Menu>\n ) : (\n <div></div>\n )}\n <CustomThemedTooltip id='tooltip-left-settings-devices' place='left' />\n </>\n )\n}\n\ninterface DropdownContentProps extends ComponentProps<'div'> {\n isTransferView?: boolean\n}\n\ninterface DeviceInputOutputTypes {\n deviceId: string\n}\n\nexport default DropdownContent\n"],"names":["_a","isTransferView","sipcall","useSelector","state","webrtc","t","useTranslation","remoteAudioElement","player","remoteAudio","_b","useState","getJSONItem","deviceId","selectedAudioInput","setSelectedAudioInput","_c","selectedAudioOutput","setSelectedAudioOutput","handleClickAudioInput","audioInputDevice","webrtcStuff","myStream","replaceTracks","tracks","type","mid","capture","exact","success","console","info","setJSONItem","eventDispatch","error","err","useEventListener","data","handleClickAudioOutput","audioOutputDevice","current","setSinkId","then","catch","_d","actualDevice","setActualDevice","useEffect","checkInputOutputDevices","navigator","mediaDevices","enumerateDevices","deviceInfos","addEventListener","removeEventListener","theme","darkTheme","handleSelectTheme","clickedTheme","selectedTheme","transferring","currentCall","isListen","listen","React","createElement","Fragment","isWebRTC","Menu","as","className","MenuButton","FontAwesomeIcon","size","icon","faEllipsis","Transition","enter","enterFrom","enterTo","leave","leaveFrom","leaveTo","MenuItems","filter","device","kind","map","audioDevice","index","MenuItem","key","active","concat","onClick","faCheck","faMicrophone","label","faVolumeHigh","faMoon","faSun","CustomThemedTooltip","id","place"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DropdownContent.js","sources":["../../../src/components/SwitchInputView/DropdownContent.tsx"],"sourcesContent":["// Copyright (C) 2024 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { type FC, ComponentProps, Fragment, useState, useEffect } from 'react'\nimport { useSelector } from 'react-redux'\nimport { RootState } from '../../store'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n faCheck,\n faEllipsis,\n faMicrophone,\n faMoon,\n faSun,\n faVolumeHigh,\n} from '@fortawesome/free-solid-svg-icons'\nimport { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'\nimport { isWebRTC } from '../../lib/user/default_device'\nimport { eventDispatch, getJSONItem, setJSONItem, useEventListener } from '../../utils'\nimport { CustomThemedTooltip } from '../CustomThemedTooltip'\nimport { useTranslation } from 'react-i18next'\n\nconst DropdownContent: FC<DropdownContentProps> = ({ isTransferView }) => {\n const { sipcall }: any = useSelector((state: RootState) => state.webrtc)\n const { t } = useTranslation()\n const remoteAudioElement: any = useSelector((state: RootState) => state.player.remoteAudio)\n\n const [selectedAudioInput, setSelectedAudioInput] = useState<string | null>(\n getJSONItem('phone-island-audio-input-device').deviceId || null,\n )\n const [selectedAudioOutput, setSelectedAudioOutput] = useState<string | null>(\n getJSONItem('phone-island-audio-output-device').deviceId || null,\n )\n\n const handleClickAudioInput = (audioInputDevice: string) => {\n setSelectedAudioInput(audioInputDevice)\n\n if (sipcall.webrtcStuff.myStream) {\n sipcall?.replaceTracks({\n tracks: [\n {\n type: 'audio',\n mid: '0', // We assume mid 0 is audio\n capture: { deviceId: { exact: audioInputDevice } },\n },\n ],\n success: function () {\n console.info('Audio input device switch success!')\n // set device to localstorage\n setJSONItem('phone-island-audio-input-device', { deviceId: audioInputDevice })\n\n // dispatch event\n eventDispatch('phone-island-call-audio-input-switched', {})\n },\n error: function (err) {\n console.error('Audio input device switch error:', err)\n },\n })\n } else {\n // set device to localstorage\n setJSONItem('phone-island-audio-input-device', { deviceId: audioInputDevice })\n\n // dispatch event\n eventDispatch('phone-island-call-audio-input-switched', {})\n }\n }\n useEventListener('phone-island-call-audio-input-switch', (data: DeviceInputOutputTypes) => {\n handleClickAudioInput(data.deviceId)\n })\n\n const handleClickAudioOutput = (audioOutputDevice: string) => {\n setSelectedAudioOutput(audioOutputDevice)\n\n remoteAudioElement?.current\n .setSinkId(audioOutputDevice)\n .then(function () {\n console.info('Audio output device switch success!')\n // set device to localstorage\n setJSONItem('phone-island-audio-output-device', { deviceId: audioOutputDevice })\n\n // dispatch event\n eventDispatch('phone-island-call-audio-output-switched', {})\n })\n .catch(function (err) {\n console.error('Audio output device switch error:', err)\n })\n }\n useEventListener('phone-island-call-audio-output-switch', (data: DeviceInputOutputTypes) => {\n handleClickAudioOutput(data.deviceId)\n })\n\n const [actualDevice, setActualDevice]: any = useState([])\n\n useEffect(() => {\n const checkInputOutputDevices = () => {\n navigator.mediaDevices\n .enumerateDevices()\n .then((deviceInfos) => {\n setActualDevice(deviceInfos)\n })\n .catch((error) => {\n console.error('error', error)\n })\n }\n\n checkInputOutputDevices()\n\n navigator.mediaDevices.addEventListener('devicechange', checkInputOutputDevices)\n\n return () => {\n navigator.mediaDevices.removeEventListener('devicechange', checkInputOutputDevices)\n }\n }, [selectedAudioOutput, selectedAudioInput])\n\n const { theme } = useSelector((state: RootState) => state.darkTheme)\n\n const handleSelectTheme = (clickedTheme: string) => {\n eventDispatch('phone-island-theme-change', { selectedTheme: clickedTheme })\n }\n const { transferring } = useSelector((state: RootState) => state.currentCall)\n const { isListen } = useSelector((state: RootState) => state.listen)\n\n return (\n <>\n {isWebRTC() ? (\n <Menu\n as='div'\n className='relative inline-block text-left'\n data-stop-propagation={true}\n data-tooltip-id='tooltip-left-settings-devices'\n data-tooltip-content={t('Tooltip.Settings')}\n >\n <MenuButton\n className='pi-bg-transparent dark:enabled:hover:pi-bg-gray-600/30 enabled:hover:pi-bg-gray-200/70 dark:focus:pi-ring-gray-500 focus:pi-ring-gray-400 pi-flex pi-font-light pi-content-center pi-items-center pi-justify-center pi-tracking-wide pi-duration-200 pi-transform pi-outline-none focus:pi-ring-2 focus:pi-z-20 focus:pi-ring-offset-2 disabled:pi-opacity-75 dark:pi-text-white pi-text-gray-600 pi-border pi-border-transparent focus:pi-ring-offset-gray-200 dark:focus:pi-ring-offset-black pi-rounded-full pi-text-sm pi-leading-4 pi-h-12 pi-w-12 pi-col-start-auto pi-transition-color pi-shrink-0'\n data-stop-propagation={true}\n >\n <FontAwesomeIcon\n size='xl'\n icon={faEllipsis}\n className='dark:pi-text-gray-200 pi-text-gray-700'\n data-stop-propagation={true}\n />\n </MenuButton>\n\n <Transition\n as={Fragment}\n enter='transition ease-out duration-100'\n enterFrom='transform opacity-0 scale-95'\n enterTo='transform opacity-100 scale-100'\n leave='transition ease-in duration-75'\n leaveFrom='transform opacity-100 scale-100'\n leaveTo='transform opacity-0 scale-95'\n >\n <MenuItems\n className={`${transferring ? 'pi-right-[1.5rem]' : 'pi-right-[4.5rem]'} \n ${\n isListen\n ? 'pi-max-h-[9.125rem] pi-mt-[-8.5rem]'\n : 'pi-max-h-[13.125rem] pi-mt-[-12.5rem]'\n }\n pi-z-50 pi-absolute pi-w-56 pi-origin-top-right pi-rounded-md pi-shadow-lg pi-ring-1 dark:pi-bg-gray-950 pi-bg-gray-50 pi-bg-opacity-[0.99] dark:pi-bg-opacity-[0.99] pi-ring-black pi-ring-opacity-5 pi-focus:outline-none pi-cursor-auto pi-border-gray-300 dark:pi-border-gray-600 pi-border pi-py-2 pi-overflow-y-auto pi-scrollbar-thin pi-scrollbar-thumb-gray-400 pi-dark:scrollbar-thumb-gray-400 pi-scrollbar-thumb-rounded-full pi-scrollbar-thumb-opacity-50 dark:pi-scrollbar-track-gray-900 pi-scrollbar-track-gray-200 pi-dark:scrollbar-track-gray-900 pi-scrollbar-track-rounded-full pi-scrollbar-track-opacity-25`}\n data-stop-propagation={true}\n >\n <div className='' data-stop-propagation={true}>\n {!isListen && (\n <>\n {' '}\n {/* Microphones */}\n <div className='pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4'>\n {t('DropdownContent.Microphones')}\n </div>\n {actualDevice\n .filter((device) => device?.kind === 'audioinput')\n .map((audioDevice, index) => (\n <MenuItem key={index}>\n {({ active }: any) => (\n <div\n className={`pi-flex pi-py-2 pi-px-2 ${\n active ? 'pi-bg-gray-200 dark:pi-bg-gray-700' : ''\n }`}\n onClick={() => handleClickAudioInput(audioDevice.deviceId)}\n data-stop-propagation={true}\n >\n {/* faCheck on selectedAudioInput */}\n {selectedAudioInput === audioDevice?.deviceId && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n {/* faCheck if user has no selectedAudioInput and audioDevice is default */}\n {!selectedAudioInput && audioDevice?.deviceId === 'default' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n <FontAwesomeIcon\n size='lg'\n icon={faMicrophone}\n className={`${\n selectedAudioInput !== null &&\n selectedAudioInput !== '' &&\n selectedAudioInput !== audioDevice?.deviceId\n ? 'pi-ml-6'\n : selectedAudioInput !== '' &&\n selectedAudioInput !== null &&\n selectedAudioInput === audioDevice?.deviceId\n ? ''\n : selectedAudioInput === null &&\n audioDevice?.deviceId !== 'default'\n ? 'pi-ml-6'\n : ''\n } dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1`}\n />\n <div\n className={`${\n active\n ? 'dark:pi-text-gray-50 pi-text-gray-900'\n : 'dark:pi-text-gray-50 pi-text-gray-700'\n }`}\n >\n {audioDevice?.label || `Input device ${index + 1}`}\n </div>\n </div>\n )}\n </MenuItem>\n ))}\n {/* Divider */}\n <div className='pi-relative pi-py-2'>\n <div\n className='pi-absolute pi-inset-0 pi-flex pi-items-center'\n aria-hidden='true'\n >\n <div className='pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600' />\n </div>\n </div>\n </>\n )}\n\n {/* Speaker */}\n <div\n className='pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4'\n data-stop-propagation={true}\n >\n {t('DropdownContent.Speakers')}\n </div>\n {actualDevice\n .filter((device) => device?.kind === 'audiooutput')\n .map((audioDevice, index) => (\n <MenuItem key={index}>\n {({ active }: any) => (\n <div\n className={`pi-flex pi-py-2 pi-px-2 ${\n active ? 'pi-bg-gray-200 dark:pi-bg-gray-700' : ''\n }`}\n onClick={() => handleClickAudioOutput(audioDevice?.deviceId)}\n data-stop-propagation={true}\n >\n {/* faCheck on selectedAudioOutput */}\n {selectedAudioOutput === audioDevice?.deviceId && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n {/* faCheck if user has no selectedAudioInput and audioDevice is default */}\n {!selectedAudioOutput && audioDevice?.deviceId === 'default' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-2'\n />\n )}\n\n <FontAwesomeIcon\n size='lg'\n icon={faVolumeHigh}\n className={`${\n selectedAudioOutput !== null &&\n selectedAudioOutput !== '' &&\n selectedAudioOutput !== audioDevice?.deviceId\n ? 'pi-ml-6'\n : selectedAudioOutput !== '' &&\n selectedAudioOutput !== null &&\n selectedAudioOutput === audioDevice?.deviceId\n ? ''\n : selectedAudioOutput === null &&\n audioDevice?.deviceId !== 'default'\n ? 'pi-ml-6'\n : ''\n } dark:pi-text-gray-100 pi-text-gray-600 pi-mr-1`}\n />\n\n <div\n className={`${\n active\n ? 'dark:pi-text-gray-50 pi-text-gray-900'\n : 'dark:pi-text-gray-50 pi-text-gray-700'\n }`}\n >\n {audioDevice?.label || `Output device ${index + 1}`}\n </div>\n </div>\n )}\n </MenuItem>\n ))}\n {/* Divider */}\n <div className='pi-relative pi-py-2'>\n <div\n className='pi-absolute pi-inset-0 pi-flex pi-items-center'\n aria-hidden='true'\n >\n <div className='pi-w-full pi-border-t pi-border-gray-400 dark:pi-border-gray-600' />\n </div>\n </div>\n {/* theme selection */}\n <div\n className='pi-font-semibold dark:pi-text-gray-50 pi-text-gray-600 pi-py-1 pi-px-4'\n data-stop-propagation={true}\n >\n {t('DropdownContent.Theme')}\n </div>\n\n {/* dark theme */}\n <div\n className={`pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700`}\n onClick={() => handleSelectTheme('dark')}\n data-stop-propagation={true}\n >\n {theme === 'dark' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.57rem]'\n />\n )}\n <FontAwesomeIcon\n size='lg'\n icon={faMoon}\n className={`${\n theme !== 'dark' ? 'pi-ml-[1.49rem] pi-mr-[0.42rem]' : 'pi-mr-[0.4rem]'\n } dark:pi-text-gray-100 pi-text-gray-600 `}\n />\n\n <div>{t('DropdownContent.Dark')}</div>\n </div>\n\n {/* light theme */}\n <div\n className={`pi-flex pi-py-2 pi-px-2 dark:hover:pi-text-gray-50 hover:pi-text-gray-900 dark:pi-text-gray-50 pi-text-gray-700 hover:pi-bg-gray-200 dark:hover:pi-bg-gray-700`}\n onClick={() => handleSelectTheme('light')}\n data-stop-propagation={true}\n >\n {theme === 'light' && (\n <FontAwesomeIcon\n size='lg'\n icon={faCheck}\n className='pi-text-green-600 dark:pi-text-green-400 pi-mr-[0.4rem]'\n />\n )}\n\n <FontAwesomeIcon\n size='lg'\n icon={faSun}\n className={`${\n theme !== 'light' ? 'pi-ml-[1.4rem] pi-mr-[0.27rem]' : 'pi-mr-[0.28rem]'\n } dark:pi-text-gray-100 pi-text-gray-600 `}\n />\n <div>{t('DropdownContent.Light')}</div>\n </div>\n\n {/* Video\n <div className='pi-font-semibold pi-text-gray-700 pi-py-1 pi-px-4'>\n Video\n </div>\n {actualDevice\n .filter((device) => device.kind === 'videoinput')\n .map((videoDevice, index) => (\n <MenuItem key={index}>\n {({ active }) => (\n <div className='pi-text-gray-700'>\n Webcam: {videoDevice.label || `Device ${index + 1}`}\n </div>\n )}\n </MenuItem>\n ))}*/}\n </div>\n </MenuItems>\n </Transition>\n </Menu>\n ) : (\n <div></div>\n )}\n <CustomThemedTooltip id='tooltip-left-settings-devices' place='left' />\n </>\n )\n}\n\ninterface DropdownContentProps extends ComponentProps<'div'> {\n isTransferView?: boolean\n}\n\ninterface DeviceInputOutputTypes {\n deviceId: string\n}\n\nexport default DropdownContent\n"],"names":["_a","isTransferView","sipcall","useSelector","state","webrtc","t","useTranslation","remoteAudioElement","player","remoteAudio","_b","useState","getJSONItem","deviceId","selectedAudioInput","setSelectedAudioInput","_c","selectedAudioOutput","setSelectedAudioOutput","handleClickAudioInput","audioInputDevice","webrtcStuff","myStream","replaceTracks","tracks","type","mid","capture","exact","success","console","info","setJSONItem","eventDispatch","error","err","useEventListener","data","handleClickAudioOutput","audioOutputDevice","current","setSinkId","then","catch","_d","actualDevice","setActualDevice","useEffect","checkInputOutputDevices","navigator","mediaDevices","enumerateDevices","deviceInfos","addEventListener","removeEventListener","theme","darkTheme","handleSelectTheme","clickedTheme","selectedTheme","transferring","currentCall","isListen","listen","React","createElement","Fragment","isWebRTC","Menu","as","className","MenuButton","FontAwesomeIcon","size","icon","faEllipsis","Transition","enter","enterFrom","enterTo","leave","leaveFrom","leaveTo","MenuItems","filter","device","kind","map","audioDevice","index","MenuItem","key","active","concat","onClick","faCheck","faMicrophone","label","faVolumeHigh","faMoon","faSun","CustomThemedTooltip","id","place"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";require("react"),require("../../node_modules/react-redux/es/index.js"),require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),require("../../store/index.js"),require("../../node_modules/tslib/tslib.es6.js"),require("../../node_modules/react-tooltip/dist/react-tooltip.min.mjs.js"),require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");
|
|
1
|
+
"use strict";require("react"),require("../../node_modules/react-redux/es/index.js"),require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),require("../../store/index.js"),require("../../node_modules/tslib/tslib.es6.js"),require("../../services/user.js"),require("../../node_modules/react-tooltip/dist/react-tooltip.min.mjs.js"),require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");
|
|
2
2
|
//# sourceMappingURL=Index.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../node_modules/tslib/tslib.es6.js"),t=require("react");require("../../node_modules/react-redux/es/index.js"),require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");var i=require("../../node_modules/react-i18next/dist/es/useTranslation.js"),r=require("../../utils/customHooks/useEventListener.js"),a=require("../../utils/genericFunctions/eventDispatch.js");require("../../store/index.js");var n=require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),s=require("../../node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js"),l=require("../../node_modules/framer-motion/dist/es/components/AnimatePresence/index.mjs.js"),o=require("../../node_modules/framer-motion/dist/es/render/components/motion/proxy.mjs.js"),p=require("../../node_modules/react-redux/es/hooks/useSelector.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var d=u(t),c={initial:{height:0,opacity:0},animate:{height:"360px",opacity:1},exit:{height:0,opacity:0},transition:{duration:.1,ease:"easeOut"}},m={borderBottomLeftRadius:"20px",borderBottomRightRadius:"20px",transformOrigin:"top",overflow:"hidden"},f=function(e){var i=e.text,r=e.isFinal,a=e.speed,n=void 0===a?50:a,s=t.useState(""),l=s[0],o=s[1];return t.useEffect(function(){if(!r){o("");var e=0,t=setInterval(function(){e<i.length?(o(i.slice(0,e+1)),e++):clearInterval(t)},n);return function(){return clearInterval(t)}}o(i)},[i,r,n]),d.default.createElement("div",{className:"pi-inline-flex pi-items-center pi-flex-wrap"},d.default.createElement("span",null,l))},g=t.memo(function(u){var g=u.isVisible,y=p.useSelector(function(e){return e.island}),b=y.actionsExpanded,x=y.view,v=p.useSelector(function(e){return e.currentUser}),h=p.useSelector(function(e){return e.currentCall.startTime}),k=i.useTranslation().t,_=t.useState([]),N=_[0],E=_[1],w=t.useState([]),j=w[0],A=w[1],F=t.useState(!1),S=F[0],q=F[1],I=t.useState(!1),M=I[0],T=I[1],D=t.useState(0),L=D[0],C=D[1],R=t.useRef(null),V=t.useRef(null),H=t.useRef(null),O=t.useState(!0),P=O[0],U=O[1],z=function(){H.current=null,E([]),A([]),q(!1),T(!1),C(0),U(!0)},B=function(e){var t,i,r,a;return!(!v||!e)&&((null===(r=null===(i=null===(t=v.endpoints)||void 0===t?void 0:t.mainextension)||void 0===i?void 0:i[0])||void 0===r?void 0:r.id)===e||!!(null===(a=v.endpoints)||void 0===a?void 0:a.extension)&&Object.values(v.endpoints.extension).some(function(t){return t.id===e||t.exten===e}))};t.useEffect(function(){var t=Math.max(0,N.length-100),i=N.slice(t),r=e.__spreadArray([],i,!0).sort(function(e,t){return e.timestamp-t.timestamp});A(r)},[N]);var W=function(t){var i,r=Number(t.timestamp)||0,a=Number.isFinite(Number(t.channel_index))?Number(t.channel_index):-1,n=Number.isFinite(Number(t.segment_start))?Number(t.segment_start):r,s=t.uniqueid&&a>=0?"".concat(t.uniqueid,"_").concat(a,"_").concat(n.toFixed(3)):"".concat(t.uniqueid,"_").concat(r),l=(i=Number(h),!Number.isFinite(i)||i<=0?null:Math.max(0,Math.floor(Date.now()/1e3)-i)),o=r;if(null!==l){if(null===H.current)H.current=l-r;else{var p=l-(r+H.current),u=Math.max(-2,Math.min(2,p));H.current+=.2*u}o=r+(H.current||0),o=Math.max(0,Math.min(l,o))}var d={id:s,timestamp:o,channelIndex:a,segmentStart:n,speaker:t.speaker_name||"Unknown",speakerNumber:t.speaker_number||"",counterpart:t.speaker_counterpart_name||"",counterpartNumber:t.speaker_counterpart_number||"",text:t.transcription||"",isFinal:t.is_final||!1};E(function(t){var i=function(e){for(var i=t.length-1;i>=0;i-=1)if(e(t[i]))return i;return-1},r=function(e){return d.channelIndex>=0&&e.channelIndex>=0?e.channelIndex===d.channelIndex:d.speakerNumber&&e.speakerNumber?e.speakerNumber===d.speakerNumber:e.speaker===d.speaker},a=t.findIndex(function(e){return e.id===s});if(-1!==a)return t[a].isFinal&&!d.isFinal?e.__spreadArray(e.__spreadArray([],t,!0),[e.__assign(e.__assign({},d),{id:"".concat(d.id,"_").concat(Date.now())})],!1):((o=e.__spreadArray([],t,!0))[a]=d,o);if(d.isFinal){var n=i(function(e){return e.isFinal&&r(e)&&e.text.trim()===d.text.trim()&&Math.abs(e.timestamp-d.timestamp)<=1});if(-1!==n)return(o=e.__spreadArray([],t,!0))[n]=e.__assign(e.__assign({},d),{id:t[n].id}),o;var l=i(function(e){return!e.isFinal&&r(e)});return-1!==l?((o=e.__spreadArray([],t,!0))[l]=e.__assign(e.__assign({},d),{id:t[l].id}),o):e.__spreadArray(e.__spreadArray([],t,!0),[d],!1)}var o,p=i(function(e){return!e.isFinal&&r(e)});return-1!==p?((o=e.__spreadArray([],t,!0))[p]=e.__assign(e.__assign({},d),{id:t[p].id}),o):e.__spreadArray(e.__spreadArray([],t,!0),[d],!1)})},G=Math.max(0,N.length-L);t.useEffect(function(){0!==N.length&&(P&&V.current?setTimeout(function(){V.current&&(V.current.scrollTop=V.current.scrollHeight)},100):M&&!P&&q(!0))},[N]),t.useEffect(function(){g&&N.length>0&&(U(!0),T(!1),q(!1))},[g]),r.useEventListener("phone-island-conversation-transcription",function(e){W(e)}),r.useEventListener("phone-island-transcription-opened",function(){z()}),r.useEventListener("phone-island-transcription-closed",function(){z()});var J="pi-absolute pi-w-full pi-bg-elevationL2 pi-flex pi-flex-col pi-text-iconWhite dark:pi-text-iconWhiteDark pi-left-0 -pi-z-10 pi-pointer-events-auto ".concat("settings"===x||b?"pi-top-[17rem]":"pi-top-[13rem]");return d.default.createElement(d.default.Fragment,null,d.default.createElement(l.AnimatePresence,null,g&&d.default.createElement(o.motion.div,e.__assign({className:J,style:m},c),d.default.createElement("div",{className:"pi-h-full pi-rounded-lg pi-overflow-hidden pi-bg-elevationL2 dark:pi-bg-elevationL2Dark pi-relative pi-flex pi-flex-col pi-border-2 pi-border-gray-100 dark:pi-border-gray-600 pi-shadow-lg"},d.default.createElement("div",{className:"pi-flex-1 pi-pt-4 pi-px-4 pi-mt-8"},d.default.createElement("div",{className:"pi-h-60 pi-bg-gray-100 dark:pi-bg-gray-800 pi-rounded-lg pi-border pi-border-gray-200 dark:pi-border-gray-700 pi-overflow-hidden pi-flex pi-flex-col"},d.default.createElement(l.AnimatePresence,null,S&&M&&d.default.createElement(o.motion.div,{initial:{opacity:0,y:-10,scale:.9},animate:{opacity:1,y:0,scale:1},exit:{opacity:0,y:-10,scale:.9},className:"pi-absolute pi-top-16 pi-left-0 pi-right-0 pi-flex pi-justify-center pi-z-20"},d.default.createElement("button",{onClick:function(){V.current&&(V.current.scrollTop=V.current.scrollHeight,q(!1),T(!1),U(!0),C(N.length))},className:"pi-bg-phoneIslandActive dark:pi-bg-phoneIslandActiveDark hover:pi-bg-gray-500 dark:hover:pi-bg-gray-50 focus:pi-ring-emerald-500 dark:focus:pi-ring-emerald-300 pi-text-primaryInvert dark:pi-text-primaryInvertDark pi-px-4 pi-py-2 pi-rounded-full pi-text-sm pi-shadow-lg pi-flex pi-items-center pi-gap-2 pi-transition-all pi-duration-200 pi-border pi-backdrop-blur-sm"},d.default.createElement(n.FontAwesomeIcon,{icon:s.faArrowDown,className:"pi-w-4 pi-h-4"}),k(G>1?"TranscriptionView.New messages":"TranscriptionView.New message")))),d.default.createElement("div",{ref:V,onScroll:function(){if(V.current){var e=function(){if(!V.current)return!0;var e=V.current,t=e.scrollTop;return e.scrollHeight-t<=e.clientHeight+10}();e?(q(!1),T(!1),U(!0),C(N.length)):(T(!0),U(!1))}},className:"pi-flex-1 pi-p-4 ".concat(j.length>0?"pi-overflow-y-auto pi-scrollbar-thin pi-scrollbar-thumb-gray-400 pi-scrollbar-thumb-rounded-full pi-scrollbar-thumb-opacity-50 pi-scrollbar-track-gray-200 dark:pi-scrollbar-track-gray-900 pi-scrollbar-track-rounded-full pi-scrollbar-track-opacity-25":"pi-overflow-hidden")},0===j.length?d.default.createElement(function(){return d.default.createElement("div",{className:"pi-space-y-2 pi-animate-pulse"},d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-2/5"}),d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-4/5"}),d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-2/5"}),d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-4/5"}))},null):d.default.createElement("div",{className:"pi-space-y-4"},N.length>100&&d.default.createElement("div",{className:"pi-text-center pi-py-2 pi-text-xs pi-text-gray-500 dark:pi-text-gray-400 pi-border-b pi-border-gray-200 dark:pi-border-gray-700"},k("TranscriptionView.Showing messages",{visible:j.length,total:N.length})),j.map(function(e,t){return d.default.createElement(o.motion.div,{key:e.id,layout:!0,initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{duration:.3,layout:{duration:.25}},className:"pi-mb-4"},d.default.createElement("div",{className:"pi-mb-2"},d.default.createElement("span",{className:"pi-font-medium pi-text-xs pi-text-secondaryNeutral dark:pi-text-secondaryNeutralDark"},B(e.speakerNumber)?k("Common.Me","Me"):e.speaker)),d.default.createElement("div",{className:"pi-relative pi-p-3 pi-rounded-lg pi-text-xs pi-font-regular ".concat(B(e.speakerNumber)?"pi-text-gray-800 dark:pi-text-gray-100 pi-bg-gray-200 dark:pi-bg-gray-600":"pi-text-indigo-800 dark:pi-text-indigo-100 pi-bg-indigo-100 dark:pi-bg-indigo-700")},d.default.createElement("div",{className:"pi-flex pi-items-start pi-justify-between pi-gap-3"},d.default.createElement("div",{className:"pi-flex-1"},d.default.createElement(f,{text:e.text,isFinal:e.isFinal,speed:30})),d.default.createElement("div",{className:"pi-flex-shrink-0 pi-mt-1 pi-text-xs pi-font-regular ".concat(B(e.speakerNumber)?"pi-text-gray-800 dark:pi-text-gray-100 pi-bg-gray-200 dark:pi-bg-gray-600":"pi-text-indigo-800 dark:pi-text-indigo-100 pi-bg-indigo-100 dark:pi-bg-indigo-700")},(i=e.timestamp,r=Math.floor(i/60),a=Math.floor(i%60),"".concat(r.toString().padStart(2,"0"),":").concat(a.toString().padStart(2,"0")))))),!e.isFinal&&""!==e.text.trim()&&d.default.createElement(o.motion.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:"pi-mt-1 pi-ml-3 pi-flex pi-items-center pi-gap-1"},d.default.createElement("span",{className:"pi-text-xs pi-text-gray-400 dark:pi-text-gray-500 pi-italic"},k("TranscriptionView.Is speaking","")),d.default.createElement("div",{className:"pi-inline-flex pi-items-center pi-gap-1"},d.default.createElement(o.motion.div,{className:"pi-w-1 pi-h-1 pi-bg-gray-400 dark:pi-bg-gray-500 pi-rounded-full",animate:{opacity:[.3,1,.3]},transition:{duration:1.5,repeat:1/0,delay:0}}),d.default.createElement(o.motion.div,{className:"pi-w-1 pi-h-1 pi-bg-gray-400 dark:pi-bg-gray-500 pi-rounded-full",animate:{opacity:[.3,1,.3]},transition:{duration:1.5,repeat:1/0,delay:.2}}),d.default.createElement(o.motion.div,{className:"pi-w-1 pi-h-1 pi-bg-gray-400 dark:pi-bg-gray-500 pi-rounded-full",animate:{opacity:[.3,1,.3]},transition:{duration:1.5,repeat:1/0,delay:.4}}))));var i,r,a}),d.default.createElement("div",{ref:R,className:"pi-pb-4"}))))),d.default.createElement("div",{className:"pi-flex pi-items-center pi-justify-center pi-py-2"},d.default.createElement("button",{onClick:function(){return a.eventDispatch("phone-island-transcription-close",{})},className:"pi-bg-transparent dark:enabled:hover:pi-bg-gray-700/30 enabled:hover:pi-bg-gray-300/70 focus:pi-ring-offset-gray-200 dark:focus:pi-ring-gray-500 focus:pi-ring-gray-400 pi-text-secondaryNeutral pi-outline-none pi-border-transparent dark:pi-text-secondaryNeutralDark pi-h-12 pi-w-24 pi-rounded-fullpi-px-4 pi-py-2 pi-rounded-full pi-text-lg pi-flex pi-items-center pi-gap-2 pi-transition-all pi-duration-200 pi-border pi-backdrop-blur-sm"},d.default.createElement(n.FontAwesomeIcon,{icon:s.faAngleUp,className:"pi-w-4 pi-h-4 pi-ml-1"}),k("Common.Close")))))))});g.displayName="TranscriptionView",exports.default=g;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../node_modules/tslib/tslib.es6.js"),t=require("react");require("../../node_modules/react-redux/es/index.js"),require("../../node_modules/i18next/dist/esm/i18next.js"),require("../../node_modules/react-i18next/dist/es/context.js");var i=require("../../node_modules/react-i18next/dist/es/useTranslation.js"),r=require("../../utils/customHooks/useEventListener.js"),a=require("../../utils/genericFunctions/eventDispatch.js");require("../../store/index.js"),require("../../services/user.js");var n=require("../../node_modules/@fortawesome/react-fontawesome/dist/index.js"),s=require("../../node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js"),l=require("../../node_modules/framer-motion/dist/es/components/AnimatePresence/index.mjs.js"),o=require("../../node_modules/framer-motion/dist/es/render/components/motion/proxy.mjs.js"),p=require("../../node_modules/react-redux/es/hooks/useSelector.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var d=u(t),c={initial:{height:0,opacity:0},animate:{height:"360px",opacity:1},exit:{height:0,opacity:0},transition:{duration:.1,ease:"easeOut"}},m={borderBottomLeftRadius:"20px",borderBottomRightRadius:"20px",transformOrigin:"top",overflow:"hidden"},f=function(e){var i=e.text,r=e.isFinal,a=e.speed,n=void 0===a?50:a,s=t.useState(""),l=s[0],o=s[1];return t.useEffect(function(){if(!r){o("");var e=0,t=setInterval(function(){e<i.length?(o(i.slice(0,e+1)),e++):clearInterval(t)},n);return function(){return clearInterval(t)}}o(i)},[i,r,n]),d.default.createElement("div",{className:"pi-inline-flex pi-items-center pi-flex-wrap"},d.default.createElement("span",null,l))},g=t.memo(function(u){var g=u.isVisible,y=p.useSelector(function(e){return e.island}),b=y.actionsExpanded,x=y.view,v=p.useSelector(function(e){return e.currentUser}),h=p.useSelector(function(e){return e.currentCall.startTime}),k=i.useTranslation().t,_=t.useState([]),N=_[0],E=_[1],w=t.useState([]),j=w[0],A=w[1],F=t.useState(!1),q=F[0],S=F[1],I=t.useState(!1),M=I[0],T=I[1],D=t.useState(0),L=D[0],C=D[1],R=t.useRef(null),V=t.useRef(null),H=t.useRef(null),O=t.useState(!0),P=O[0],U=O[1],z=function(){H.current=null,E([]),A([]),S(!1),T(!1),C(0),U(!0)},B=function(e){var t,i,r,a;return!(!v||!e)&&((null===(r=null===(i=null===(t=v.endpoints)||void 0===t?void 0:t.mainextension)||void 0===i?void 0:i[0])||void 0===r?void 0:r.id)===e||!!(null===(a=v.endpoints)||void 0===a?void 0:a.extension)&&Object.values(v.endpoints.extension).some(function(t){return t.id===e||t.exten===e}))};t.useEffect(function(){var t=Math.max(0,N.length-100),i=N.slice(t),r=e.__spreadArray([],i,!0).sort(function(e,t){return e.timestamp-t.timestamp});A(r)},[N]);var W=function(t){var i,r=Number(t.timestamp)||0,a=Number.isFinite(Number(t.channel_index))?Number(t.channel_index):-1,n=Number.isFinite(Number(t.segment_start))?Number(t.segment_start):r,s=t.uniqueid&&a>=0?"".concat(t.uniqueid,"_").concat(a,"_").concat(n.toFixed(3)):"".concat(t.uniqueid,"_").concat(r),l=(i=Number(h),!Number.isFinite(i)||i<=0?null:Math.max(0,Math.floor(Date.now()/1e3)-i)),o=r;if(null!==l){if(null===H.current)H.current=l-r;else{var p=l-(r+H.current),u=Math.max(-2,Math.min(2,p));H.current+=.2*u}o=r+(H.current||0),o=Math.max(0,Math.min(l,o))}var d={id:s,timestamp:o,channelIndex:a,segmentStart:n,speaker:t.speaker_name||"Unknown",speakerNumber:t.speaker_number||"",counterpart:t.speaker_counterpart_name||"",counterpartNumber:t.speaker_counterpart_number||"",text:t.transcription||"",isFinal:t.is_final||!1};E(function(t){var i=function(e){for(var i=t.length-1;i>=0;i-=1)if(e(t[i]))return i;return-1},r=function(e){return d.channelIndex>=0&&e.channelIndex>=0?e.channelIndex===d.channelIndex:d.speakerNumber&&e.speakerNumber?e.speakerNumber===d.speakerNumber:e.speaker===d.speaker},a=t.findIndex(function(e){return e.id===s});if(-1!==a)return t[a].isFinal&&!d.isFinal?e.__spreadArray(e.__spreadArray([],t,!0),[e.__assign(e.__assign({},d),{id:"".concat(d.id,"_").concat(Date.now())})],!1):((o=e.__spreadArray([],t,!0))[a]=d,o);if(d.isFinal){var n=i(function(e){return e.isFinal&&r(e)&&e.text.trim()===d.text.trim()&&Math.abs(e.timestamp-d.timestamp)<=1});if(-1!==n)return(o=e.__spreadArray([],t,!0))[n]=e.__assign(e.__assign({},d),{id:t[n].id}),o;var l=i(function(e){return!e.isFinal&&r(e)});return-1!==l?((o=e.__spreadArray([],t,!0))[l]=e.__assign(e.__assign({},d),{id:t[l].id}),o):e.__spreadArray(e.__spreadArray([],t,!0),[d],!1)}var o,p=i(function(e){return!e.isFinal&&r(e)});return-1!==p?((o=e.__spreadArray([],t,!0))[p]=e.__assign(e.__assign({},d),{id:t[p].id}),o):e.__spreadArray(e.__spreadArray([],t,!0),[d],!1)})},G=Math.max(0,N.length-L);t.useEffect(function(){0!==N.length&&(P&&V.current?setTimeout(function(){V.current&&(V.current.scrollTop=V.current.scrollHeight)},100):M&&!P&&S(!0))},[N]),t.useEffect(function(){g&&N.length>0&&(U(!0),T(!1),S(!1))},[g]),r.useEventListener("phone-island-conversation-transcription",function(e){W(e)}),r.useEventListener("phone-island-transcription-opened",function(){z()}),r.useEventListener("phone-island-transcription-closed",function(){z()});var J="pi-absolute pi-w-full pi-bg-elevationL2 pi-flex pi-flex-col pi-text-iconWhite dark:pi-text-iconWhiteDark pi-left-0 -pi-z-10 pi-pointer-events-auto ".concat("settings"===x||b?"pi-top-[17rem]":"pi-top-[13rem]");return d.default.createElement(d.default.Fragment,null,d.default.createElement(l.AnimatePresence,null,g&&d.default.createElement(o.motion.div,e.__assign({className:J,style:m},c),d.default.createElement("div",{className:"pi-h-full pi-rounded-lg pi-overflow-hidden pi-bg-elevationL2 dark:pi-bg-elevationL2Dark pi-relative pi-flex pi-flex-col pi-border-2 pi-border-gray-100 dark:pi-border-gray-600 pi-shadow-lg"},d.default.createElement("div",{className:"pi-flex-1 pi-pt-4 pi-px-4 pi-mt-8"},d.default.createElement("div",{className:"pi-h-60 pi-bg-gray-100 dark:pi-bg-gray-800 pi-rounded-lg pi-border pi-border-gray-200 dark:pi-border-gray-700 pi-overflow-hidden pi-flex pi-flex-col"},d.default.createElement(l.AnimatePresence,null,q&&M&&d.default.createElement(o.motion.div,{initial:{opacity:0,y:-10,scale:.9},animate:{opacity:1,y:0,scale:1},exit:{opacity:0,y:-10,scale:.9},className:"pi-absolute pi-top-16 pi-left-0 pi-right-0 pi-flex pi-justify-center pi-z-20"},d.default.createElement("button",{onClick:function(){V.current&&(V.current.scrollTop=V.current.scrollHeight,S(!1),T(!1),U(!0),C(N.length))},className:"pi-bg-phoneIslandActive dark:pi-bg-phoneIslandActiveDark hover:pi-bg-gray-500 dark:hover:pi-bg-gray-50 focus:pi-ring-emerald-500 dark:focus:pi-ring-emerald-300 pi-text-primaryInvert dark:pi-text-primaryInvertDark pi-px-4 pi-py-2 pi-rounded-full pi-text-sm pi-shadow-lg pi-flex pi-items-center pi-gap-2 pi-transition-all pi-duration-200 pi-border pi-backdrop-blur-sm"},d.default.createElement(n.FontAwesomeIcon,{icon:s.faArrowDown,className:"pi-w-4 pi-h-4"}),k(G>1?"TranscriptionView.New messages":"TranscriptionView.New message")))),d.default.createElement("div",{ref:V,onScroll:function(){if(V.current){var e=function(){if(!V.current)return!0;var e=V.current,t=e.scrollTop;return e.scrollHeight-t<=e.clientHeight+10}();e?(S(!1),T(!1),U(!0),C(N.length)):(T(!0),U(!1))}},className:"pi-flex-1 pi-p-4 ".concat(j.length>0?"pi-overflow-y-auto pi-scrollbar-thin pi-scrollbar-thumb-gray-400 pi-scrollbar-thumb-rounded-full pi-scrollbar-thumb-opacity-50 pi-scrollbar-track-gray-200 dark:pi-scrollbar-track-gray-900 pi-scrollbar-track-rounded-full pi-scrollbar-track-opacity-25":"pi-overflow-hidden")},0===j.length?d.default.createElement(function(){return d.default.createElement("div",{className:"pi-space-y-2 pi-animate-pulse"},d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-2/5"}),d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-4/5"}),d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-2/5"}),d.default.createElement("div",{className:"pi-h-4 pi-bg-gray-200 dark:pi-bg-gray-700 pi-rounded pi-w-4/5"}))},null):d.default.createElement("div",{className:"pi-space-y-4"},N.length>100&&d.default.createElement("div",{className:"pi-text-center pi-py-2 pi-text-xs pi-text-gray-500 dark:pi-text-gray-400 pi-border-b pi-border-gray-200 dark:pi-border-gray-700"},k("TranscriptionView.Showing messages",{visible:j.length,total:N.length})),j.map(function(e,t){return d.default.createElement(o.motion.div,{key:e.id,layout:!0,initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{duration:.3,layout:{duration:.25}},className:"pi-mb-4"},d.default.createElement("div",{className:"pi-mb-2"},d.default.createElement("span",{className:"pi-font-medium pi-text-xs pi-text-secondaryNeutral dark:pi-text-secondaryNeutralDark"},B(e.speakerNumber)?k("Common.Me","Me"):e.speaker)),d.default.createElement("div",{className:"pi-relative pi-p-3 pi-rounded-lg pi-text-xs pi-font-regular ".concat(B(e.speakerNumber)?"pi-text-gray-800 dark:pi-text-gray-100 pi-bg-gray-200 dark:pi-bg-gray-600":"pi-text-indigo-800 dark:pi-text-indigo-100 pi-bg-indigo-100 dark:pi-bg-indigo-700")},d.default.createElement("div",{className:"pi-flex pi-items-start pi-justify-between pi-gap-3"},d.default.createElement("div",{className:"pi-flex-1"},d.default.createElement(f,{text:e.text,isFinal:e.isFinal,speed:30})),d.default.createElement("div",{className:"pi-flex-shrink-0 pi-mt-1 pi-text-xs pi-font-regular ".concat(B(e.speakerNumber)?"pi-text-gray-800 dark:pi-text-gray-100 pi-bg-gray-200 dark:pi-bg-gray-600":"pi-text-indigo-800 dark:pi-text-indigo-100 pi-bg-indigo-100 dark:pi-bg-indigo-700")},(i=e.timestamp,r=Math.floor(i/60),a=Math.floor(i%60),"".concat(r.toString().padStart(2,"0"),":").concat(a.toString().padStart(2,"0")))))),!e.isFinal&&""!==e.text.trim()&&d.default.createElement(o.motion.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:"pi-mt-1 pi-ml-3 pi-flex pi-items-center pi-gap-1"},d.default.createElement("span",{className:"pi-text-xs pi-text-gray-400 dark:pi-text-gray-500 pi-italic"},k("TranscriptionView.Is speaking","")),d.default.createElement("div",{className:"pi-inline-flex pi-items-center pi-gap-1"},d.default.createElement(o.motion.div,{className:"pi-w-1 pi-h-1 pi-bg-gray-400 dark:pi-bg-gray-500 pi-rounded-full",animate:{opacity:[.3,1,.3]},transition:{duration:1.5,repeat:1/0,delay:0}}),d.default.createElement(o.motion.div,{className:"pi-w-1 pi-h-1 pi-bg-gray-400 dark:pi-bg-gray-500 pi-rounded-full",animate:{opacity:[.3,1,.3]},transition:{duration:1.5,repeat:1/0,delay:.2}}),d.default.createElement(o.motion.div,{className:"pi-w-1 pi-h-1 pi-bg-gray-400 dark:pi-bg-gray-500 pi-rounded-full",animate:{opacity:[.3,1,.3]},transition:{duration:1.5,repeat:1/0,delay:.4}}))));var i,r,a}),d.default.createElement("div",{ref:R,className:"pi-pb-4"}))))),d.default.createElement("div",{className:"pi-flex pi-items-center pi-justify-center pi-py-2"},d.default.createElement("button",{onClick:function(){return a.eventDispatch("phone-island-transcription-close",{})},className:"pi-bg-transparent dark:enabled:hover:pi-bg-gray-700/30 enabled:hover:pi-bg-gray-300/70 focus:pi-ring-offset-gray-200 dark:focus:pi-ring-gray-500 focus:pi-ring-gray-400 pi-text-secondaryNeutral pi-outline-none pi-border-transparent dark:pi-text-secondaryNeutralDark pi-h-12 pi-w-24 pi-rounded-fullpi-px-4 pi-py-2 pi-rounded-full pi-text-lg pi-flex pi-items-center pi-gap-2 pi-transition-all pi-duration-200 pi-border pi-backdrop-blur-sm"},d.default.createElement(n.FontAwesomeIcon,{icon:s.faAngleUp,className:"pi-w-4 pi-h-4 pi-ml-1"}),k("Common.Close")))))))});g.displayName="TranscriptionView",exports.default=g;
|
|
2
2
|
//# sourceMappingURL=TranscriptionView.js.map
|