@stream-io/video-react-sdk 1.43.4 → 1.44.0

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/esm/index.js CHANGED
@@ -59,6 +59,7 @@ export { PermissionNotification } from './src/components/Notification/Permission
59
59
  export { SpeakingWhileMutedNotification } from './src/components/Notification/SpeakingWhileMutedNotification.js';
60
60
  export { RecordingInProgressNotification } from './src/components/Notification/RecordingInProgressNotification.js';
61
61
  export { MicCaptureErrorNotification } from './src/components/Notification/MicCaptureErrorNotification.js';
62
+ export { CameraUnavailableNotification } from './src/components/Notification/CameraUnavailableNotification.js';
62
63
  export { Reaction, defaultEmojiReactionMap } from './src/components/Reaction/Reaction.js';
63
64
  export { RingingCallControls } from './src/components/RingingCall/RingingCallControls.js';
64
65
  export { RingingCall } from './src/components/RingingCall/RingingCall.js';
@@ -82,7 +83,7 @@ export { useModeration } from './src/hooks/useModeration.js';
82
83
  export { useLoopbackRecording } from './src/hooks/useLoopbackRecording.js';
83
84
  export { applyFilter } from './src/utilities/filter.js';
84
85
 
85
- const [major, minor, patch] = ("1.43.4").split('.');
86
+ const [major, minor, patch] = ("1.44.0").split('.');
86
87
  setSdkInfo({
87
88
  type: SfuModels.SdkType.REACT,
88
89
  major,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../index.ts"],"sourcesContent":["import { setSdkInfo, SfuModels } from '@stream-io/video-client';\n\nexport * from '@stream-io/video-client';\nexport * from '@stream-io/video-react-bindings';\n\nexport * from './src/core';\n\nexport * from './src/components';\nexport * from './src/wrappers';\nexport * from './src/translations';\nexport {\n useHorizontalScrollPosition,\n useVerticalScrollPosition,\n useRequestPermission,\n usePersistedDevicePreferences,\n useDeviceList,\n useModeration,\n useLoopbackRecording,\n type LoopbackRecordingState,\n type StartLoopbackRecordingOptions,\n type UseLoopbackRecordingResult,\n} from './src/hooks';\nexport { applyFilter, type Filter } from './src/utilities/filter';\n\nconst [major, minor, patch] = (\n process.env.PKG_VERSION || '0.0.0-development'\n).split('.');\n\nsetSdkInfo({\n type: SfuModels.SdkType.REACT,\n major,\n minor,\n patch,\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAC5B,QAA8C,EAC9C,KAAK,CAAC,GAAG,CAAC;AAEZ,UAAU,CAAC;AACT,IAAA,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK;IAC7B,KAAK;IACL,KAAK;IACL,KAAK;AACN,CAAA,CAAC"}
1
+ {"version":3,"file":"index.js","sources":["../../../../index.ts"],"sourcesContent":["import { setSdkInfo, SfuModels } from '@stream-io/video-client';\n\nexport * from '@stream-io/video-client';\nexport * from '@stream-io/video-react-bindings';\n\nexport * from './src/core';\n\nexport * from './src/components';\nexport * from './src/wrappers';\nexport * from './src/translations';\nexport {\n useHorizontalScrollPosition,\n useVerticalScrollPosition,\n useRequestPermission,\n usePersistedDevicePreferences,\n useDeviceList,\n useModeration,\n useLoopbackRecording,\n type LoopbackRecordingState,\n type StartLoopbackRecordingOptions,\n type UseLoopbackRecordingResult,\n} from './src/hooks';\nexport { applyFilter, type Filter } from './src/utilities/filter';\n\nconst [major, minor, patch] = (\n process.env.PKG_VERSION || '0.0.0-development'\n).split('.');\n\nsetSdkInfo({\n type: SfuModels.SdkType.REACT,\n major,\n minor,\n patch,\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAC5B,QAA8C,EAC9C,KAAK,CAAC,GAAG,CAAC;AAEZ,UAAU,CAAC;AACT,IAAA,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK;IAC7B,KAAK;IACL,KAAK;IACL,KAAK;AACN,CAAA,CAAC"}
@@ -13,6 +13,7 @@ import '../DropdownSelect/DropdownSelect.js';
13
13
  import '../Menu/MenuToggle.js';
14
14
  import { DeviceSelectorVideo } from '../DeviceSettings/DeviceSelectorVideo.js';
15
15
  import { PermissionNotification } from '../Notification/PermissionNotification.js';
16
+ import { CameraUnavailableNotification } from '../Notification/CameraUnavailableNotification.js';
16
17
  import { WithTooltip } from '../Tooltip/WithTooltip.js';
17
18
  import { createCallControlHandler } from '../../utilities/callControlHandler.js';
18
19
 
@@ -25,16 +26,16 @@ const ToggleVideoPreviewButton = (props) => {
25
26
  const isSystemMuted = !!localParticipant?.interruptedTracks?.includes(SfuModels.TrackType.VIDEO);
26
27
  const [tooltipDisabled, setTooltipDisabled] = useState(false);
27
28
  const handleClick = createCallControlHandler(props, () => camera.toggle());
28
- return (jsx(WithTooltip, { title: !hasBrowserPermission
29
- ? t('Check your browser video permissions')
30
- : isSystemMuted
31
- ? t('Camera is paused by your system')
32
- : (caption ?? t('Video')), tooltipDisabled: tooltipDisabled, children: jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, className: clsx(!hasBrowserPermission && 'str-video__device-unavailable'), variant: "secondary", "data-testid": optionsAwareIsMute
33
- ? 'preview-video-unmute-button'
34
- : 'preview-video-mute-button', onClick: handleClick, disabled: !hasBrowserPermission || (!optimisticUpdates && isTogglePending), Menu: Menu, menuPlacement: menuPlacement, ...restCompositeButtonProps, onMenuToggle: (shown) => {
35
- setTooltipDisabled(shown);
36
- onMenuToggle?.(shown);
37
- }, children: [jsx(Icon, { icon: !optionsAwareIsMute ? 'camera' : 'camera-off' }), !hasBrowserPermission && (jsx("span", { className: "str-video__no-media-permission", title: t('Check your browser video permissions'), children: "!" })), isPromptingPermission && (jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted && hasBrowserPermission && (jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }));
29
+ return (jsx(CameraUnavailableNotification, { children: jsx(WithTooltip, { title: !hasBrowserPermission
30
+ ? t('Check your browser video permissions')
31
+ : isSystemMuted
32
+ ? t('Camera is paused by your system')
33
+ : (caption ?? t('Video')), tooltipDisabled: tooltipDisabled, children: jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, className: clsx(!hasBrowserPermission && 'str-video__device-unavailable'), variant: "secondary", "data-testid": optionsAwareIsMute
34
+ ? 'preview-video-unmute-button'
35
+ : 'preview-video-mute-button', onClick: handleClick, disabled: !hasBrowserPermission || (!optimisticUpdates && isTogglePending), Menu: Menu, menuPlacement: menuPlacement, ...restCompositeButtonProps, onMenuToggle: (shown) => {
36
+ setTooltipDisabled(shown);
37
+ onMenuToggle?.(shown);
38
+ }, children: [jsx(Icon, { icon: !optionsAwareIsMute ? 'camera' : 'camera-off' }), !hasBrowserPermission && (jsx("span", { className: "str-video__no-media-permission", title: t('Check your browser video permissions'), children: "!" })), isPromptingPermission && (jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted && hasBrowserPermission && (jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }) }));
38
39
  };
39
40
  const ToggleVideoPublishingButton = (props) => {
40
41
  const { t } = useI18n();
@@ -55,26 +56,26 @@ const ToggleVideoPublishingButton = (props) => {
55
56
  await camera.toggle();
56
57
  }
57
58
  });
58
- return (jsx(Restricted, { requiredGrants: [OwnCapability.SEND_VIDEO], children: jsx(PermissionNotification, { permission: OwnCapability.SEND_VIDEO, isAwaitingApproval: isAwaitingPermission, messageApproved: t('You can now share your video.'), messageAwaitingApproval: t('Awaiting for an approval to share your video.'), messageRevoked: t('You can no longer share your video.'), children: jsx(WithTooltip, { title: !hasPermission
59
- ? t('You have no permission to share your video')
60
- : !hasBrowserPermission
61
- ? t('Check your browser video permissions')
62
- : !isPublishingVideoAllowed
63
- ? t('Video publishing is disabled by the system')
64
- : isSystemMuted
65
- ? t('Camera is paused by your system')
66
- : caption || t('Video'), tooltipDisabled: tooltipDisabled, children: jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, variant: "secondary", disabled: !hasBrowserPermission ||
67
- !hasPermission ||
68
- !isPublishingVideoAllowed ||
69
- (!optimisticUpdates && isTogglePending), "data-testid": optionsAwareIsMute ? 'video-unmute-button' : 'video-mute-button', onClick: handleClick, Menu: Menu, menuPlacement: menuPlacement, menuOffset: 16, ...restCompositeButtonProps, onMenuToggle: (shown) => {
70
- setTooltipDisabled(shown);
71
- onMenuToggle?.(shown);
72
- }, children: [jsx(Icon, { icon: optionsAwareIsMute ? 'camera-off' : 'camera' }), (!hasBrowserPermission ||
59
+ return (jsx(Restricted, { requiredGrants: [OwnCapability.SEND_VIDEO], children: jsx(PermissionNotification, { permission: OwnCapability.SEND_VIDEO, isAwaitingApproval: isAwaitingPermission, messageApproved: t('You can now share your video.'), messageAwaitingApproval: t('Awaiting for an approval to share your video.'), messageRevoked: t('You can no longer share your video.'), children: jsx(CameraUnavailableNotification, { children: jsx(WithTooltip, { title: !hasPermission
60
+ ? t('You have no permission to share your video')
61
+ : !hasBrowserPermission
62
+ ? t('Check your browser video permissions')
63
+ : !isPublishingVideoAllowed
64
+ ? t('Video publishing is disabled by the system')
65
+ : isSystemMuted
66
+ ? t('Camera is paused by your system')
67
+ : caption || t('Video'), tooltipDisabled: tooltipDisabled, children: jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, variant: "secondary", disabled: !hasBrowserPermission ||
73
68
  !hasPermission ||
74
- !isPublishingVideoAllowed) && (jsx("span", { className: "str-video__no-media-permission", children: "!" })), isPromptingPermission && (jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted &&
75
- hasBrowserPermission &&
76
- hasPermission &&
77
- isPublishingVideoAllowed && (jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }) }) }));
69
+ !isPublishingVideoAllowed ||
70
+ (!optimisticUpdates && isTogglePending), "data-testid": optionsAwareIsMute ? 'video-unmute-button' : 'video-mute-button', onClick: handleClick, Menu: Menu, menuPlacement: menuPlacement, menuOffset: 16, ...restCompositeButtonProps, onMenuToggle: (shown) => {
71
+ setTooltipDisabled(shown);
72
+ onMenuToggle?.(shown);
73
+ }, children: [jsx(Icon, { icon: optionsAwareIsMute ? 'camera-off' : 'camera' }), (!hasBrowserPermission ||
74
+ !hasPermission ||
75
+ !isPublishingVideoAllowed) && (jsx("span", { className: "str-video__no-media-permission", children: "!" })), isPromptingPermission && (jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted &&
76
+ hasBrowserPermission &&
77
+ hasPermission &&
78
+ isPublishingVideoAllowed && (jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }) }) }) }));
78
79
  };
79
80
 
80
81
  export { ToggleVideoPreviewButton, ToggleVideoPublishingButton };
@@ -1 +1 @@
1
- {"version":3,"file":"ToggleVideoButton.js","sources":["../../../../../../../src/components/CallControls/ToggleVideoButton.tsx"],"sourcesContent":["import {\n Restricted,\n useCallStateHooks,\n useI18n,\n UseInputMediaDeviceOptions,\n} from '@stream-io/video-react-bindings';\nimport clsx from 'clsx';\nimport {\n OwnCapability,\n RequestPermissionRequestPermissionsEnum,\n SfuModels,\n} from '@stream-io/video-client';\nimport { CompositeButton, IconButtonWithMenuProps } from '../Button/';\nimport { DeviceSelectorVideo } from '../DeviceSettings';\nimport { PermissionNotification } from '../Notification';\nimport { useRequestPermission } from '../../hooks';\nimport { Icon } from '../Icon';\nimport { WithTooltip } from '../Tooltip';\nimport { useState } from 'react';\nimport {\n createCallControlHandler,\n PropsWithErrorHandler,\n} from '../../utilities/callControlHandler';\n\nexport type ToggleVideoPreviewButtonProps = PropsWithErrorHandler<\n Pick<\n IconButtonWithMenuProps,\n 'caption' | 'Menu' | 'menuPlacement' | 'onMenuToggle'\n > &\n UseInputMediaDeviceOptions\n>;\n\nexport const ToggleVideoPreviewButton = (\n props: ToggleVideoPreviewButtonProps,\n) => {\n const {\n caption,\n Menu = DeviceSelectorVideo,\n menuPlacement = 'top',\n onMenuToggle,\n optimisticUpdates,\n ...restCompositeButtonProps\n } = props;\n const { t } = useI18n();\n const { useCameraState, useLocalParticipant } = useCallStateHooks();\n const {\n camera,\n hasBrowserPermission,\n isPromptingPermission,\n isTogglePending,\n optionsAwareIsMute,\n } = useCameraState({ optimisticUpdates });\n const localParticipant = useLocalParticipant();\n const isSystemMuted = !!localParticipant?.interruptedTracks?.includes(\n SfuModels.TrackType.VIDEO,\n );\n const [tooltipDisabled, setTooltipDisabled] = useState(false);\n const handleClick = createCallControlHandler(props, () => camera.toggle());\n\n return (\n <WithTooltip\n title={\n !hasBrowserPermission\n ? t('Check your browser video permissions')\n : isSystemMuted\n ? t('Camera is paused by your system')\n : (caption ?? t('Video'))\n }\n tooltipDisabled={tooltipDisabled}\n >\n <CompositeButton\n active={optionsAwareIsMute}\n caption={caption}\n className={clsx(\n !hasBrowserPermission && 'str-video__device-unavailable',\n )}\n variant=\"secondary\"\n data-testid={\n optionsAwareIsMute\n ? 'preview-video-unmute-button'\n : 'preview-video-mute-button'\n }\n onClick={handleClick}\n disabled={\n !hasBrowserPermission || (!optimisticUpdates && isTogglePending)\n }\n Menu={Menu}\n menuPlacement={menuPlacement}\n {...restCompositeButtonProps}\n onMenuToggle={(shown) => {\n setTooltipDisabled(shown);\n onMenuToggle?.(shown);\n }}\n >\n <Icon icon={!optionsAwareIsMute ? 'camera' : 'camera-off'} />\n {!hasBrowserPermission && (\n <span\n className=\"str-video__no-media-permission\"\n title={t('Check your browser video permissions')}\n children=\"!\"\n />\n )}\n {isPromptingPermission && (\n <span\n className=\"str-video__pending-permission\"\n title={t('Waiting for permission')}\n children=\"?\"\n />\n )}\n {isSystemMuted && hasBrowserPermission && (\n <span\n className=\"str-video__system-muted\"\n title={t('Camera is paused by your system')}\n children=\"!\"\n />\n )}\n </CompositeButton>\n </WithTooltip>\n );\n};\n\ntype ToggleVideoPublishingButtonProps = PropsWithErrorHandler<\n Pick<\n IconButtonWithMenuProps,\n 'caption' | 'Menu' | 'menuPlacement' | 'onMenuToggle'\n > &\n UseInputMediaDeviceOptions\n>;\n\nexport const ToggleVideoPublishingButton = (\n props: ToggleVideoPublishingButtonProps,\n) => {\n const { t } = useI18n();\n const {\n caption,\n Menu = <DeviceSelectorVideo visualType=\"list\" />,\n menuPlacement = 'top',\n onMenuToggle,\n optimisticUpdates,\n ...restCompositeButtonProps\n } = props;\n\n const { hasPermission, requestPermission, isAwaitingPermission } =\n useRequestPermission(RequestPermissionRequestPermissionsEnum.SEND_VIDEO);\n\n const { useCameraState, useCallSettings, useLocalParticipant } =\n useCallStateHooks();\n const {\n camera,\n optionsAwareIsMute,\n hasBrowserPermission,\n isPromptingPermission,\n isTogglePending,\n } = useCameraState({ optimisticUpdates });\n const localParticipant = useLocalParticipant();\n const isSystemMuted = !!localParticipant?.interruptedTracks?.includes(\n SfuModels.TrackType.VIDEO,\n );\n const callSettings = useCallSettings();\n const isPublishingVideoAllowed = callSettings?.video.enabled;\n const [tooltipDisabled, setTooltipDisabled] = useState(false);\n const handleClick = createCallControlHandler(props, async () => {\n if (!hasPermission) {\n await requestPermission();\n } else {\n await camera.toggle();\n }\n });\n\n return (\n <Restricted requiredGrants={[OwnCapability.SEND_VIDEO]}>\n <PermissionNotification\n permission={OwnCapability.SEND_VIDEO}\n isAwaitingApproval={isAwaitingPermission}\n messageApproved={t('You can now share your video.')}\n messageAwaitingApproval={t(\n 'Awaiting for an approval to share your video.',\n )}\n messageRevoked={t('You can no longer share your video.')}\n >\n <WithTooltip\n title={\n !hasPermission\n ? t('You have no permission to share your video')\n : !hasBrowserPermission\n ? t('Check your browser video permissions')\n : !isPublishingVideoAllowed\n ? t('Video publishing is disabled by the system')\n : isSystemMuted\n ? t('Camera is paused by your system')\n : caption || t('Video')\n }\n tooltipDisabled={tooltipDisabled}\n >\n <CompositeButton\n active={optionsAwareIsMute}\n caption={caption}\n variant=\"secondary\"\n disabled={\n !hasBrowserPermission ||\n !hasPermission ||\n !isPublishingVideoAllowed ||\n (!optimisticUpdates && isTogglePending)\n }\n data-testid={\n optionsAwareIsMute ? 'video-unmute-button' : 'video-mute-button'\n }\n onClick={handleClick}\n Menu={Menu}\n menuPlacement={menuPlacement}\n menuOffset={16}\n {...restCompositeButtonProps}\n onMenuToggle={(shown) => {\n setTooltipDisabled(shown);\n onMenuToggle?.(shown);\n }}\n >\n <Icon icon={optionsAwareIsMute ? 'camera-off' : 'camera'} />\n {(!hasBrowserPermission ||\n !hasPermission ||\n !isPublishingVideoAllowed) && (\n <span className=\"str-video__no-media-permission\">!</span>\n )}\n {isPromptingPermission && (\n <span\n className=\"str-video__pending-permission\"\n title={t('Waiting for permission')}\n >\n ?\n </span>\n )}\n {isSystemMuted &&\n hasBrowserPermission &&\n hasPermission &&\n isPublishingVideoAllowed && (\n <span\n className=\"str-video__system-muted\"\n title={t('Camera is paused by your system')}\n >\n !\n </span>\n )}\n </CompositeButton>\n </WithTooltip>\n </PermissionNotification>\n </Restricted>\n );\n};\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"ToggleVideoButton.js","sources":["../../../../../../../src/components/CallControls/ToggleVideoButton.tsx"],"sourcesContent":["import {\n Restricted,\n useCallStateHooks,\n useI18n,\n UseInputMediaDeviceOptions,\n} from '@stream-io/video-react-bindings';\nimport clsx from 'clsx';\nimport {\n OwnCapability,\n RequestPermissionRequestPermissionsEnum,\n SfuModels,\n} from '@stream-io/video-client';\nimport { CompositeButton, IconButtonWithMenuProps } from '../Button/';\nimport { DeviceSelectorVideo } from '../DeviceSettings';\nimport {\n CameraUnavailableNotification,\n PermissionNotification,\n} from '../Notification';\nimport { useRequestPermission } from '../../hooks';\nimport { Icon } from '../Icon';\nimport { WithTooltip } from '../Tooltip';\nimport { useState } from 'react';\nimport {\n createCallControlHandler,\n PropsWithErrorHandler,\n} from '../../utilities/callControlHandler';\n\nexport type ToggleVideoPreviewButtonProps = PropsWithErrorHandler<\n Pick<\n IconButtonWithMenuProps,\n 'caption' | 'Menu' | 'menuPlacement' | 'onMenuToggle'\n > &\n UseInputMediaDeviceOptions\n>;\n\nexport const ToggleVideoPreviewButton = (\n props: ToggleVideoPreviewButtonProps,\n) => {\n const {\n caption,\n Menu = DeviceSelectorVideo,\n menuPlacement = 'top',\n onMenuToggle,\n optimisticUpdates,\n ...restCompositeButtonProps\n } = props;\n const { t } = useI18n();\n const { useCameraState, useLocalParticipant } = useCallStateHooks();\n const {\n camera,\n hasBrowserPermission,\n isPromptingPermission,\n isTogglePending,\n optionsAwareIsMute,\n } = useCameraState({ optimisticUpdates });\n const localParticipant = useLocalParticipant();\n const isSystemMuted = !!localParticipant?.interruptedTracks?.includes(\n SfuModels.TrackType.VIDEO,\n );\n const [tooltipDisabled, setTooltipDisabled] = useState(false);\n const handleClick = createCallControlHandler(props, () => camera.toggle());\n\n return (\n <CameraUnavailableNotification>\n <WithTooltip\n title={\n !hasBrowserPermission\n ? t('Check your browser video permissions')\n : isSystemMuted\n ? t('Camera is paused by your system')\n : (caption ?? t('Video'))\n }\n tooltipDisabled={tooltipDisabled}\n >\n <CompositeButton\n active={optionsAwareIsMute}\n caption={caption}\n className={clsx(\n !hasBrowserPermission && 'str-video__device-unavailable',\n )}\n variant=\"secondary\"\n data-testid={\n optionsAwareIsMute\n ? 'preview-video-unmute-button'\n : 'preview-video-mute-button'\n }\n onClick={handleClick}\n disabled={\n !hasBrowserPermission || (!optimisticUpdates && isTogglePending)\n }\n Menu={Menu}\n menuPlacement={menuPlacement}\n {...restCompositeButtonProps}\n onMenuToggle={(shown) => {\n setTooltipDisabled(shown);\n onMenuToggle?.(shown);\n }}\n >\n <Icon icon={!optionsAwareIsMute ? 'camera' : 'camera-off'} />\n {!hasBrowserPermission && (\n <span\n className=\"str-video__no-media-permission\"\n title={t('Check your browser video permissions')}\n children=\"!\"\n />\n )}\n {isPromptingPermission && (\n <span\n className=\"str-video__pending-permission\"\n title={t('Waiting for permission')}\n children=\"?\"\n />\n )}\n {isSystemMuted && hasBrowserPermission && (\n <span\n className=\"str-video__system-muted\"\n title={t('Camera is paused by your system')}\n children=\"!\"\n />\n )}\n </CompositeButton>\n </WithTooltip>\n </CameraUnavailableNotification>\n );\n};\n\ntype ToggleVideoPublishingButtonProps = PropsWithErrorHandler<\n Pick<\n IconButtonWithMenuProps,\n 'caption' | 'Menu' | 'menuPlacement' | 'onMenuToggle'\n > &\n UseInputMediaDeviceOptions\n>;\n\nexport const ToggleVideoPublishingButton = (\n props: ToggleVideoPublishingButtonProps,\n) => {\n const { t } = useI18n();\n const {\n caption,\n Menu = <DeviceSelectorVideo visualType=\"list\" />,\n menuPlacement = 'top',\n onMenuToggle,\n optimisticUpdates,\n ...restCompositeButtonProps\n } = props;\n\n const { hasPermission, requestPermission, isAwaitingPermission } =\n useRequestPermission(RequestPermissionRequestPermissionsEnum.SEND_VIDEO);\n\n const { useCameraState, useCallSettings, useLocalParticipant } =\n useCallStateHooks();\n const {\n camera,\n optionsAwareIsMute,\n hasBrowserPermission,\n isPromptingPermission,\n isTogglePending,\n } = useCameraState({ optimisticUpdates });\n const localParticipant = useLocalParticipant();\n const isSystemMuted = !!localParticipant?.interruptedTracks?.includes(\n SfuModels.TrackType.VIDEO,\n );\n const callSettings = useCallSettings();\n const isPublishingVideoAllowed = callSettings?.video.enabled;\n const [tooltipDisabled, setTooltipDisabled] = useState(false);\n const handleClick = createCallControlHandler(props, async () => {\n if (!hasPermission) {\n await requestPermission();\n } else {\n await camera.toggle();\n }\n });\n\n return (\n <Restricted requiredGrants={[OwnCapability.SEND_VIDEO]}>\n <PermissionNotification\n permission={OwnCapability.SEND_VIDEO}\n isAwaitingApproval={isAwaitingPermission}\n messageApproved={t('You can now share your video.')}\n messageAwaitingApproval={t(\n 'Awaiting for an approval to share your video.',\n )}\n messageRevoked={t('You can no longer share your video.')}\n >\n <CameraUnavailableNotification>\n <WithTooltip\n title={\n !hasPermission\n ? t('You have no permission to share your video')\n : !hasBrowserPermission\n ? t('Check your browser video permissions')\n : !isPublishingVideoAllowed\n ? t('Video publishing is disabled by the system')\n : isSystemMuted\n ? t('Camera is paused by your system')\n : caption || t('Video')\n }\n tooltipDisabled={tooltipDisabled}\n >\n <CompositeButton\n active={optionsAwareIsMute}\n caption={caption}\n variant=\"secondary\"\n disabled={\n !hasBrowserPermission ||\n !hasPermission ||\n !isPublishingVideoAllowed ||\n (!optimisticUpdates && isTogglePending)\n }\n data-testid={\n optionsAwareIsMute ? 'video-unmute-button' : 'video-mute-button'\n }\n onClick={handleClick}\n Menu={Menu}\n menuPlacement={menuPlacement}\n menuOffset={16}\n {...restCompositeButtonProps}\n onMenuToggle={(shown) => {\n setTooltipDisabled(shown);\n onMenuToggle?.(shown);\n }}\n >\n <Icon icon={optionsAwareIsMute ? 'camera-off' : 'camera'} />\n {(!hasBrowserPermission ||\n !hasPermission ||\n !isPublishingVideoAllowed) && (\n <span className=\"str-video__no-media-permission\">!</span>\n )}\n {isPromptingPermission && (\n <span\n className=\"str-video__pending-permission\"\n title={t('Waiting for permission')}\n >\n ?\n </span>\n )}\n {isSystemMuted &&\n hasBrowserPermission &&\n hasPermission &&\n isPublishingVideoAllowed && (\n <span\n className=\"str-video__system-muted\"\n title={t('Camera is paused by your system')}\n >\n !\n </span>\n )}\n </CompositeButton>\n </WithTooltip>\n </CameraUnavailableNotification>\n </PermissionNotification>\n </Restricted>\n );\n};\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;AAmCO,MAAM,wBAAwB,GAAG,CACtC,KAAoC,KAClC;IACF,MAAM,EACJ,OAAO,EACP,IAAI,GAAG,mBAAmB,EAC1B,aAAa,GAAG,KAAK,EACrB,YAAY,EACZ,iBAAiB,EACjB,GAAG,wBAAwB,EAC5B,GAAG,KAAK;AACT,IAAA,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;IACvB,MAAM,EAAE,cAAc,EAAE,mBAAmB,EAAE,GAAG,iBAAiB,EAAE;AACnE,IAAA,MAAM,EACJ,MAAM,EACN,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,GACnB,GAAG,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAC;AACzC,IAAA,MAAM,gBAAgB,GAAG,mBAAmB,EAAE;AAC9C,IAAA,MAAM,aAAa,GAAG,CAAC,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,QAAQ,CACnE,SAAS,CAAC,SAAS,CAAC,KAAK,CAC1B;IACD,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;AAC7D,IAAA,MAAM,WAAW,GAAG,wBAAwB,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;IAE1E,QACEA,GAAA,CAAC,6BAA6B,EAAA,EAAA,QAAA,EAC5BA,GAAA,CAAC,WAAW,EAAA,EACV,KAAK,EACH,CAAC;AACC,kBAAE,CAAC,CAAC,sCAAsC;AAC1C,kBAAE;AACA,sBAAE,CAAC,CAAC,iCAAiC;AACrC,uBAAG,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,EAE/B,eAAe,EAAE,eAAe,YAEhCC,IAAA,CAAC,eAAe,IACd,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,IAAI,CACb,CAAC,oBAAoB,IAAI,+BAA+B,CACzD,EACD,OAAO,EAAC,WAAW,iBAEjB;AACE,sBAAE;AACF,sBAAE,2BAA2B,EAEjC,OAAO,EAAE,WAAW,EACpB,QAAQ,EACN,CAAC,oBAAoB,KAAK,CAAC,iBAAiB,IAAI,eAAe,CAAC,EAElE,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,aAAa,EAAA,GACxB,wBAAwB,EAC5B,YAAY,EAAE,CAAC,KAAK,KAAI;oBACtB,kBAAkB,CAAC,KAAK,CAAC;AACzB,oBAAA,YAAY,GAAG,KAAK,CAAC;AACvB,gBAAA,CAAC,aAEDD,GAAA,CAAC,IAAI,IAAC,IAAI,EAAE,CAAC,kBAAkB,GAAG,QAAQ,GAAG,YAAY,EAAA,CAAI,EAC5D,CAAC,oBAAoB,KACpBA,cACE,SAAS,EAAC,gCAAgC,EAC1C,KAAK,EAAE,CAAC,CAAC,sCAAsC,CAAC,EAChD,QAAQ,EAAC,GAAG,GACZ,CACH,EACA,qBAAqB,KACpBA,GAAA,CAAA,MAAA,EAAA,EACE,SAAS,EAAC,+BAA+B,EACzC,KAAK,EAAE,CAAC,CAAC,wBAAwB,CAAC,EAClC,QAAQ,EAAC,GAAG,EAAA,CACZ,CACH,EACA,aAAa,IAAI,oBAAoB,KACpCA,GAAA,CAAA,MAAA,EAAA,EACE,SAAS,EAAC,yBAAyB,EACnC,KAAK,EAAE,CAAC,CAAC,iCAAiC,CAAC,EAC3C,QAAQ,EAAC,GAAG,EAAA,CACZ,CACH,IACe,EAAA,CACN,EAAA,CACgB;AAEpC;AAUO,MAAM,2BAA2B,GAAG,CACzC,KAAuC,KACrC;AACF,IAAA,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;IACvB,MAAM,EACJ,OAAO,EACP,IAAI,GAAGA,GAAA,CAAC,mBAAmB,EAAA,EAAC,UAAU,EAAC,MAAM,EAAA,CAAG,EAChD,aAAa,GAAG,KAAK,EACrB,YAAY,EACZ,iBAAiB,EACjB,GAAG,wBAAwB,EAC5B,GAAG,KAAK;AAET,IAAA,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,GAC9D,oBAAoB,CAAC,uCAAuC,CAAC,UAAU,CAAC;IAE1E,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,GAC5D,iBAAiB,EAAE;AACrB,IAAA,MAAM,EACJ,MAAM,EACN,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,GAChB,GAAG,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAC;AACzC,IAAA,MAAM,gBAAgB,GAAG,mBAAmB,EAAE;AAC9C,IAAA,MAAM,aAAa,GAAG,CAAC,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,QAAQ,CACnE,SAAS,CAAC,SAAS,CAAC,KAAK,CAC1B;AACD,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AACtC,IAAA,MAAM,wBAAwB,GAAG,YAAY,EAAE,KAAK,CAAC,OAAO;IAC5D,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC7D,MAAM,WAAW,GAAG,wBAAwB,CAAC,KAAK,EAAE,YAAW;QAC7D,IAAI,CAAC,aAAa,EAAE;YAClB,MAAM,iBAAiB,EAAE;QAC3B;aAAO;AACL,YAAA,MAAM,MAAM,CAAC,MAAM,EAAE;QACvB;AACF,IAAA,CAAC,CAAC;IAEF,QACEA,GAAA,CAAC,UAAU,EAAA,EAAC,cAAc,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,EAAA,QAAA,EACpDA,IAAC,sBAAsB,EAAA,EACrB,UAAU,EAAE,aAAa,CAAC,UAAU,EACpC,kBAAkB,EAAE,oBAAoB,EACxC,eAAe,EAAE,CAAC,CAAC,+BAA+B,CAAC,EACnD,uBAAuB,EAAE,CAAC,CACxB,+CAA+C,CAChD,EACD,cAAc,EAAE,CAAC,CAAC,qCAAqC,CAAC,EAAA,QAAA,EAExDA,GAAA,CAAC,6BAA6B,EAAA,EAAA,QAAA,EAC5BA,GAAA,CAAC,WAAW,EAAA,EACV,KAAK,EACH,CAAC;AACC,0BAAE,CAAC,CAAC,4CAA4C;0BAC9C,CAAC;AACD,8BAAE,CAAC,CAAC,sCAAsC;8BACxC,CAAC;AACD,kCAAE,CAAC,CAAC,4CAA4C;AAChD,kCAAE;AACA,sCAAE,CAAC,CAAC,iCAAiC;AACrC,sCAAE,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,EAEjC,eAAe,EAAE,eAAe,EAAA,QAAA,EAEhCC,KAAC,eAAe,EAAA,EACd,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAC,WAAW,EACnB,QAAQ,EACN,CAAC,oBAAoB;AACrB,4BAAA,CAAC,aAAa;AACd,4BAAA,CAAC,wBAAwB;AACzB,6BAAC,CAAC,iBAAiB,IAAI,eAAe,CAAC,iBAGvC,kBAAkB,GAAG,qBAAqB,GAAG,mBAAmB,EAElE,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,EAAE,EAAA,GACV,wBAAwB,EAC5B,YAAY,EAAE,CAAC,KAAK,KAAI;4BACtB,kBAAkB,CAAC,KAAK,CAAC;AACzB,4BAAA,YAAY,GAAG,KAAK,CAAC;AACvB,wBAAA,CAAC,aAEDD,GAAA,CAAC,IAAI,IAAC,IAAI,EAAE,kBAAkB,GAAG,YAAY,GAAG,QAAQ,GAAI,EAC3D,CAAC,CAAC,oBAAoB;AACrB,gCAAA,CAAC,aAAa;AACd,gCAAA,CAAC,wBAAwB,MACzBA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,gCAAgC,EAAA,QAAA,EAAA,GAAA,EAAA,CAAS,CAC1D,EACA,qBAAqB,KACpBA,GAAA,CAAA,MAAA,EAAA,EACE,SAAS,EAAC,+BAA+B,EACzC,KAAK,EAAE,CAAC,CAAC,wBAAwB,CAAC,EAAA,QAAA,EAAA,GAAA,EAAA,CAG7B,CACR,EACA,aAAa;gCACZ,oBAAoB;gCACpB,aAAa;gCACb,wBAAwB,KACtBA,GAAA,CAAA,MAAA,EAAA,EACE,SAAS,EAAC,yBAAyB,EACnC,KAAK,EAAE,CAAC,CAAC,iCAAiC,CAAC,kBAGtC,CACR,CAAA,EAAA,CACa,GACN,EAAA,CACgB,EAAA,CACT,EAAA,CACd;AAEjB;;;;"}
@@ -15,7 +15,7 @@ const SpeakerTest = (props) => {
15
15
  const audioElementRef = useRef(null);
16
16
  const [isPlaying, setIsPlaying] = useState(false);
17
17
  const { t } = useI18n();
18
- const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.43.4"}/assets/piano.mp3`, } = props;
18
+ const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.44.0"}/assets/piano.mp3`, } = props;
19
19
  // Update audio output device when selection changes
20
20
  useEffect(() => {
21
21
  const audio = audioElementRef.current;
@@ -0,0 +1,30 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import clsx from 'clsx';
4
+ import { useCallStateHooks, useI18n } from '@stream-io/video-react-bindings';
5
+ import { Notification } from './Notification.js';
6
+
7
+ const UNAVAILABLE_ERRORS = ['NotReadableError', 'AbortError'];
8
+ const isCameraUnavailable = (error) => !!error?.name && UNAVAILABLE_ERRORS.includes(error.name);
9
+ /**
10
+ * Shows when the last attempt to start the camera failed (e.g. the camera is
11
+ * in use by another app). Reads the error from the camera state, so it shows
12
+ * failures that happened before it was mounted.
13
+ *
14
+ * For error-specific copy, build your own notification on top of
15
+ * `useCameraState().error`.
16
+ */
17
+ const CameraUnavailableNotification = ({ children, placement, className, }) => {
18
+ const { useCameraState } = useCallStateHooks();
19
+ const { error } = useCameraState();
20
+ const { t } = useI18n();
21
+ const [isVisible, setIsVisible] = useState(() => isCameraUnavailable(error));
22
+ useEffect(() => {
23
+ setIsVisible(isCameraUnavailable(error));
24
+ }, [error]);
25
+ const message = (jsxs(Fragment, { children: [jsx("span", { className: "str-video__notification__line str-video__notification__title", children: t('Camera unavailable') }), jsx("span", { className: "str-video__notification__line", children: t('Close other apps that might be using your camera and try again.') })] }));
26
+ return (jsx(Notification, { message: message, isVisible: isVisible, placement: placement, className: clsx('str-video__camera-unavailable-notification', className), close: () => setIsVisible(false), children: children }));
27
+ };
28
+
29
+ export { CameraUnavailableNotification };
30
+ //# sourceMappingURL=CameraUnavailableNotification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CameraUnavailableNotification.js","sources":["../../../../../../../src/components/Notification/CameraUnavailableNotification.tsx"],"sourcesContent":["import { PropsWithChildren, useEffect, useState } from 'react';\nimport { Placement } from '@floating-ui/react';\nimport clsx from 'clsx';\nimport { useCallStateHooks, useI18n } from '@stream-io/video-react-bindings';\nimport { Notification } from './Notification';\n\nexport type CameraUnavailableNotificationProps = {\n placement?: Placement;\n className?: string;\n};\n\nconst UNAVAILABLE_ERRORS = ['NotReadableError', 'AbortError'];\n\nconst isCameraUnavailable = (error: Error | undefined) =>\n !!error?.name && UNAVAILABLE_ERRORS.includes(error.name);\n\n/**\n * Shows when the last attempt to start the camera failed (e.g. the camera is\n * in use by another app). Reads the error from the camera state, so it shows\n * failures that happened before it was mounted.\n *\n * For error-specific copy, build your own notification on top of\n * `useCameraState().error`.\n */\nexport const CameraUnavailableNotification = ({\n children,\n placement,\n className,\n}: PropsWithChildren<CameraUnavailableNotificationProps>) => {\n const { useCameraState } = useCallStateHooks();\n const { error } = useCameraState();\n const { t } = useI18n();\n const [isVisible, setIsVisible] = useState(() => isCameraUnavailable(error));\n\n useEffect(() => {\n setIsVisible(isCameraUnavailable(error));\n }, [error]);\n\n const message = (\n <>\n <span className=\"str-video__notification__line str-video__notification__title\">\n {t('Camera unavailable')}\n </span>\n <span className=\"str-video__notification__line\">\n {t('Close other apps that might be using your camera and try again.')}\n </span>\n </>\n );\n\n return (\n <Notification\n message={message}\n isVisible={isVisible}\n placement={placement}\n className={clsx('str-video__camera-unavailable-notification', className)}\n close={() => setIsVisible(false)}\n >\n {children}\n </Notification>\n );\n};\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":";;;;;;AAWA,MAAM,kBAAkB,GAAG,CAAC,kBAAkB,EAAE,YAAY,CAAC;AAE7D,MAAM,mBAAmB,GAAG,CAAC,KAAwB,KACnD,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;AAE1D;;;;;;;AAOG;AACI,MAAM,6BAA6B,GAAG,CAAC,EAC5C,QAAQ,EACR,SAAS,EACT,SAAS,GAC6C,KAAI;AAC1D,IAAA,MAAM,EAAE,cAAc,EAAE,GAAG,iBAAiB,EAAE;AAC9C,IAAA,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,EAAE;AAClC,IAAA,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;AACvB,IAAA,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAE5E,SAAS,CAAC,MAAK;AACb,QAAA,YAAY,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;AAC1C,IAAA,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAEX,MAAM,OAAO,IACXA,IAAA,CAAAC,QAAA,EAAA,EAAA,QAAA,EAAA,CACEC,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,8DAA8D,EAAA,QAAA,EAC3E,CAAC,CAAC,oBAAoB,CAAC,EAAA,CACnB,EACPA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,+BAA+B,EAAA,QAAA,EAC5C,CAAC,CAAC,iEAAiE,CAAC,EAAA,CAChE,CAAA,EAAA,CACN,CACJ;AAED,IAAA,QACEA,GAAA,CAAC,YAAY,EAAA,EACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,IAAI,CAAC,4CAA4C,EAAE,SAAS,CAAC,EACxE,KAAK,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,YAE/B,QAAQ,EAAA,CACI;AAEnB;;;;"}
@@ -91,6 +91,8 @@ var en = {
91
91
  "Camera on": "Camera on",
92
92
  "Camera off": "Camera off",
93
93
  "Camera is paused by your system": "Camera is paused by your system",
94
+ "Camera unavailable": "Camera unavailable",
95
+ "Close other apps that might be using your camera and try again.": "Close other apps that might be using your camera and try again.",
94
96
  "No camera found": "No camera found",
95
97
  "Video is disabled": "Video is disabled",
96
98
  Pinned: Pinned,
@@ -1 +1 @@
1
- {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.cjs.js CHANGED
@@ -1129,6 +1129,28 @@ const MicCaptureErrorNotification = ({ children, text, placement, }) => {
1129
1129
  return (jsxRuntime.jsx(Notification, { message: message, isVisible: isVisible, placement: placement, close: () => setIsVisible(false), children: children }));
1130
1130
  };
1131
1131
 
1132
+ const UNAVAILABLE_ERRORS = ['NotReadableError', 'AbortError'];
1133
+ const isCameraUnavailable = (error) => !!error?.name && UNAVAILABLE_ERRORS.includes(error.name);
1134
+ /**
1135
+ * Shows when the last attempt to start the camera failed (e.g. the camera is
1136
+ * in use by another app). Reads the error from the camera state, so it shows
1137
+ * failures that happened before it was mounted.
1138
+ *
1139
+ * For error-specific copy, build your own notification on top of
1140
+ * `useCameraState().error`.
1141
+ */
1142
+ const CameraUnavailableNotification = ({ children, placement, className, }) => {
1143
+ const { useCameraState } = videoReactBindings.useCallStateHooks();
1144
+ const { error } = useCameraState();
1145
+ const { t } = videoReactBindings.useI18n();
1146
+ const [isVisible, setIsVisible] = react.useState(() => isCameraUnavailable(error));
1147
+ react.useEffect(() => {
1148
+ setIsVisible(isCameraUnavailable(error));
1149
+ }, [error]);
1150
+ const message = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "str-video__notification__line str-video__notification__title", children: t('Camera unavailable') }), jsxRuntime.jsx("span", { className: "str-video__notification__line", children: t('Close other apps that might be using your camera and try again.') })] }));
1151
+ return (jsxRuntime.jsx(Notification, { message: message, isVisible: isVisible, placement: placement, className: clsx('str-video__camera-unavailable-notification', className), close: () => setIsVisible(false), children: children }));
1152
+ };
1153
+
1132
1154
  const LoadingIndicator = ({ className, type = 'spinner', text, tooltip, }) => {
1133
1155
  return (jsxRuntime.jsxs("div", { className: clsx('str-video__loading-indicator', className), title: tooltip, children: [jsxRuntime.jsx("div", { className: clsx('str-video__loading-indicator__icon', type) }), text && jsxRuntime.jsx("p", { className: "str-video__loading-indicator-text", children: text })] }));
1134
1156
  };
@@ -1538,7 +1560,7 @@ const SpeakerTest = (props) => {
1538
1560
  const audioElementRef = react.useRef(null);
1539
1561
  const [isPlaying, setIsPlaying] = react.useState(false);
1540
1562
  const { t } = videoReactBindings.useI18n();
1541
- const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.43.4"}/assets/piano.mp3`, } = props;
1563
+ const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.44.0"}/assets/piano.mp3`, } = props;
1542
1564
  // Update audio output device when selection changes
1543
1565
  react.useEffect(() => {
1544
1566
  const audio = audioElementRef.current;
@@ -1712,16 +1734,16 @@ const ToggleVideoPreviewButton = (props) => {
1712
1734
  const isSystemMuted = !!localParticipant?.interruptedTracks?.includes(videoClient.SfuModels.TrackType.VIDEO);
1713
1735
  const [tooltipDisabled, setTooltipDisabled] = react.useState(false);
1714
1736
  const handleClick = createCallControlHandler(props, () => camera.toggle());
1715
- return (jsxRuntime.jsx(WithTooltip, { title: !hasBrowserPermission
1716
- ? t('Check your browser video permissions')
1717
- : isSystemMuted
1718
- ? t('Camera is paused by your system')
1719
- : (caption ?? t('Video')), tooltipDisabled: tooltipDisabled, children: jsxRuntime.jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, className: clsx(!hasBrowserPermission && 'str-video__device-unavailable'), variant: "secondary", "data-testid": optionsAwareIsMute
1720
- ? 'preview-video-unmute-button'
1721
- : 'preview-video-mute-button', onClick: handleClick, disabled: !hasBrowserPermission || (!optimisticUpdates && isTogglePending), Menu: Menu, menuPlacement: menuPlacement, ...restCompositeButtonProps, onMenuToggle: (shown) => {
1722
- setTooltipDisabled(shown);
1723
- onMenuToggle?.(shown);
1724
- }, children: [jsxRuntime.jsx(Icon, { icon: !optionsAwareIsMute ? 'camera' : 'camera-off' }), !hasBrowserPermission && (jsxRuntime.jsx("span", { className: "str-video__no-media-permission", title: t('Check your browser video permissions'), children: "!" })), isPromptingPermission && (jsxRuntime.jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted && hasBrowserPermission && (jsxRuntime.jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }));
1737
+ return (jsxRuntime.jsx(CameraUnavailableNotification, { children: jsxRuntime.jsx(WithTooltip, { title: !hasBrowserPermission
1738
+ ? t('Check your browser video permissions')
1739
+ : isSystemMuted
1740
+ ? t('Camera is paused by your system')
1741
+ : (caption ?? t('Video')), tooltipDisabled: tooltipDisabled, children: jsxRuntime.jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, className: clsx(!hasBrowserPermission && 'str-video__device-unavailable'), variant: "secondary", "data-testid": optionsAwareIsMute
1742
+ ? 'preview-video-unmute-button'
1743
+ : 'preview-video-mute-button', onClick: handleClick, disabled: !hasBrowserPermission || (!optimisticUpdates && isTogglePending), Menu: Menu, menuPlacement: menuPlacement, ...restCompositeButtonProps, onMenuToggle: (shown) => {
1744
+ setTooltipDisabled(shown);
1745
+ onMenuToggle?.(shown);
1746
+ }, children: [jsxRuntime.jsx(Icon, { icon: !optionsAwareIsMute ? 'camera' : 'camera-off' }), !hasBrowserPermission && (jsxRuntime.jsx("span", { className: "str-video__no-media-permission", title: t('Check your browser video permissions'), children: "!" })), isPromptingPermission && (jsxRuntime.jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted && hasBrowserPermission && (jsxRuntime.jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }) }));
1725
1747
  };
1726
1748
  const ToggleVideoPublishingButton = (props) => {
1727
1749
  const { t } = videoReactBindings.useI18n();
@@ -1742,26 +1764,26 @@ const ToggleVideoPublishingButton = (props) => {
1742
1764
  await camera.toggle();
1743
1765
  }
1744
1766
  });
1745
- return (jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [videoClient.OwnCapability.SEND_VIDEO], children: jsxRuntime.jsx(PermissionNotification, { permission: videoClient.OwnCapability.SEND_VIDEO, isAwaitingApproval: isAwaitingPermission, messageApproved: t('You can now share your video.'), messageAwaitingApproval: t('Awaiting for an approval to share your video.'), messageRevoked: t('You can no longer share your video.'), children: jsxRuntime.jsx(WithTooltip, { title: !hasPermission
1746
- ? t('You have no permission to share your video')
1747
- : !hasBrowserPermission
1748
- ? t('Check your browser video permissions')
1749
- : !isPublishingVideoAllowed
1750
- ? t('Video publishing is disabled by the system')
1751
- : isSystemMuted
1752
- ? t('Camera is paused by your system')
1753
- : caption || t('Video'), tooltipDisabled: tooltipDisabled, children: jsxRuntime.jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, variant: "secondary", disabled: !hasBrowserPermission ||
1754
- !hasPermission ||
1755
- !isPublishingVideoAllowed ||
1756
- (!optimisticUpdates && isTogglePending), "data-testid": optionsAwareIsMute ? 'video-unmute-button' : 'video-mute-button', onClick: handleClick, Menu: Menu, menuPlacement: menuPlacement, menuOffset: 16, ...restCompositeButtonProps, onMenuToggle: (shown) => {
1757
- setTooltipDisabled(shown);
1758
- onMenuToggle?.(shown);
1759
- }, children: [jsxRuntime.jsx(Icon, { icon: optionsAwareIsMute ? 'camera-off' : 'camera' }), (!hasBrowserPermission ||
1767
+ return (jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [videoClient.OwnCapability.SEND_VIDEO], children: jsxRuntime.jsx(PermissionNotification, { permission: videoClient.OwnCapability.SEND_VIDEO, isAwaitingApproval: isAwaitingPermission, messageApproved: t('You can now share your video.'), messageAwaitingApproval: t('Awaiting for an approval to share your video.'), messageRevoked: t('You can no longer share your video.'), children: jsxRuntime.jsx(CameraUnavailableNotification, { children: jsxRuntime.jsx(WithTooltip, { title: !hasPermission
1768
+ ? t('You have no permission to share your video')
1769
+ : !hasBrowserPermission
1770
+ ? t('Check your browser video permissions')
1771
+ : !isPublishingVideoAllowed
1772
+ ? t('Video publishing is disabled by the system')
1773
+ : isSystemMuted
1774
+ ? t('Camera is paused by your system')
1775
+ : caption || t('Video'), tooltipDisabled: tooltipDisabled, children: jsxRuntime.jsxs(CompositeButton, { active: optionsAwareIsMute, caption: caption, variant: "secondary", disabled: !hasBrowserPermission ||
1760
1776
  !hasPermission ||
1761
- !isPublishingVideoAllowed) && (jsxRuntime.jsx("span", { className: "str-video__no-media-permission", children: "!" })), isPromptingPermission && (jsxRuntime.jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted &&
1762
- hasBrowserPermission &&
1763
- hasPermission &&
1764
- isPublishingVideoAllowed && (jsxRuntime.jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }) }) }));
1777
+ !isPublishingVideoAllowed ||
1778
+ (!optimisticUpdates && isTogglePending), "data-testid": optionsAwareIsMute ? 'video-unmute-button' : 'video-mute-button', onClick: handleClick, Menu: Menu, menuPlacement: menuPlacement, menuOffset: 16, ...restCompositeButtonProps, onMenuToggle: (shown) => {
1779
+ setTooltipDisabled(shown);
1780
+ onMenuToggle?.(shown);
1781
+ }, children: [jsxRuntime.jsx(Icon, { icon: optionsAwareIsMute ? 'camera-off' : 'camera' }), (!hasBrowserPermission ||
1782
+ !hasPermission ||
1783
+ !isPublishingVideoAllowed) && (jsxRuntime.jsx("span", { className: "str-video__no-media-permission", children: "!" })), isPromptingPermission && (jsxRuntime.jsx("span", { className: "str-video__pending-permission", title: t('Waiting for permission'), children: "?" })), isSystemMuted &&
1784
+ hasBrowserPermission &&
1785
+ hasPermission &&
1786
+ isPublishingVideoAllowed && (jsxRuntime.jsx("span", { className: "str-video__system-muted", title: t('Camera is paused by your system'), children: "!" }))] }) }) }) }) }));
1765
1787
  };
1766
1788
 
1767
1789
  const EndCallMenu = (props) => {
@@ -2716,6 +2738,8 @@ var en = {
2716
2738
  "Camera on": "Camera on",
2717
2739
  "Camera off": "Camera off",
2718
2740
  "Camera is paused by your system": "Camera is paused by your system",
2741
+ "Camera unavailable": "Camera unavailable",
2742
+ "Close other apps that might be using your camera and try again.": "Close other apps that might be using your camera and try again.",
2719
2743
  "No camera found": "No camera found",
2720
2744
  "Video is disabled": "Video is disabled",
2721
2745
  Pinned: Pinned,
@@ -3411,7 +3435,7 @@ const checkCanJoinEarly = (startsAt, joinAheadTimeSeconds) => {
3411
3435
  return Date.now() >= +startsAt - (joinAheadTimeSeconds ?? 0) * 1000;
3412
3436
  };
3413
3437
 
3414
- const [major, minor, patch] = ("1.43.4").split('.');
3438
+ const [major, minor, patch] = ("1.44.0").split('.');
3415
3439
  videoClient.setSdkInfo({
3416
3440
  type: videoClient.SfuModels.SdkType.REACT,
3417
3441
  major,
@@ -3437,6 +3461,7 @@ exports.CallRecordingListHeader = CallRecordingListHeader;
3437
3461
  exports.CallRecordingListItem = CallRecordingListItem;
3438
3462
  exports.CallStats = CallStats;
3439
3463
  exports.CallStatsButton = CallStatsButton;
3464
+ exports.CameraUnavailableNotification = CameraUnavailableNotification;
3440
3465
  exports.CancelCallButton = CancelCallButton;
3441
3466
  exports.CancelCallConfirmButton = CancelCallConfirmButton;
3442
3467
  exports.CompositeButton = CompositeButton;