Skip to content

Commit

Permalink
Add StartMediaButton and fix useStartVideo hook (#717)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasIO authored Nov 24, 2023
1 parent da5ffe3 commit 11ec05d
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .changeset/pretty-badgers-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@livekit/components-core": patch
"@livekit/components-react": patch
---

Add StartMediaButton
12 changes: 12 additions & 0 deletions packages/core/etc/components-core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,11 @@ export function roomInfoObserver(room: Room): Observable<{
// @public (undocumented)
export function roomObserver(room: Room): Observable<Room>;

// @public (undocumented)
export function roomVideoPlaybackAllowedObservable(room: Room): Observable<{
canPlayVideo: boolean;
}>;

// @alpha
export function saveUserChoices(userChoices: LocalUserChoices,
preventSave?: boolean): void;
Expand Down Expand Up @@ -493,6 +498,13 @@ export function setupStartAudio(): {
handleStartAudioPlayback: (room: Room) => Promise<void>;
};

// @public (undocumented)
export function setupStartVideo(): {
className: string;
roomVideoPlaybackAllowedObservable: typeof roomVideoPlaybackAllowedObservable;
handleStartVideoPlayback: (room: Room) => Promise<void>;
};

// @public (undocumented)
export function setupTrackMutedIndicator(trackRef: TrackReferenceOrPlaceholder): {
className: string;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/startVideo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { prefixClass } from '../styles-interface';
export function setupStartVideo() {
const handleStartVideoPlayback = async (room: Room) => {
log.info('Start Video for room: ', room);
await room.startAudio();
await room.startVideo();
};
const className: string = prefixClass('start-audio-button');
return { className, roomVideoPlaybackAllowedObservable, handleStartVideoPlayback };
Expand Down
20 changes: 20 additions & 0 deletions packages/react/etc/components-react.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,26 @@ export interface UseStartAudioProps {
room?: Room;
}

// @alpha
export function useStartVideo({ room, props }: UseStartVideoProps): {
mergedProps: React_2.ButtonHTMLAttributes<HTMLButtonElement> & {
className: string;
onClick: () => void;
style: {
display: string;
};
};
canPlayVideo: boolean;
};

// @alpha (undocumented)
export interface UseStartVideoProps {
// (undocumented)
props: React_2.ButtonHTMLAttributes<HTMLButtonElement>;
// (undocumented)
room?: Room;
}

// @alpha
export function useSwipe(element: React_2.RefObject<HTMLElement>, options?: UseSwipeOptions): void;

Expand Down
37 changes: 37 additions & 0 deletions packages/react/src/components/controls/StartMediaButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from 'react';
import { useRoomContext } from '../../context';
import { useStartAudio, useStartVideo } from '../../hooks';

/** @public */
export interface AllowMediaPlaybackProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
label?: string;
}

/**
* The `StartMediaButton` component is only visible when the browser blocks media playback. This is due to some browser implemented autoplay policies.
* To start media playback, the user must perform a user-initiated event such as clicking this button.
* As soon as media playback starts, the button hides itself again.
*
* @example
* ```tsx
* <LiveKitRoom>
* <StartMediaButton label="Click to allow media playback" />
* </LiveKitRoom>
* ```
*
* @see Autoplay policy on MDN web docs: {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Best_practices#autoplay_policy}
* @public
*/
export function StartMediaButton({ label, ...props }: AllowMediaPlaybackProps) {
const room = useRoomContext();
const { mergedProps: audioProps, canPlayAudio } = useStartAudio({ room, props });
const { mergedProps, canPlayVideo } = useStartVideo({ room, props: audioProps });
const { style, ...restProps } = mergedProps;
style.display = canPlayAudio && canPlayVideo ? 'none' : 'block';

return (
<button style={style} {...restProps}>
{label ?? `Start ${!canPlayAudio ? 'Audio' : 'Video'}`}
</button>
);
}
1 change: 1 addition & 0 deletions packages/react/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export { UseRoomInfoOptions, useRoomInfo } from './useRoomInfo';
export { useSortedParticipants } from './useSortedParticipants';
export { useSpeakingParticipants } from './useSpeakingParticipants';
export { UseStartAudioProps, useStartAudio } from './useStartAudio';
export { UseStartVideoProps, useStartVideo } from './useStartVideo';
export { UseSwipeOptions, useSwipe } from './useSwipe';
export { UseChatToggleProps, useChatToggle } from './useChatToggle';
export { UseTokenOptions, UserInfo, useToken } from './useToken';
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/prefabs/ControlBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import * as React from 'react';
import { MediaDeviceMenu } from './MediaDeviceMenu';
import { DisconnectButton } from '../components/controls/DisconnectButton';
import { TrackToggle } from '../components/controls/TrackToggle';
import { StartAudio } from '../components/controls/StartAudio';
import { ChatIcon, LeaveIcon } from '../assets/icons';
import { ChatToggle } from '../components/controls/ChatToggle';
import { useLocalParticipantPermissions, usePersistentUserChoices } from '../hooks';
import { useMediaQuery } from '../hooks/internal';
import { useMaybeLayoutContext } from '../context';
import { supportsScreenSharing } from '@livekit/components-core';
import { mergeProps } from '../utils';
import { StartMediaButton } from '../components/controls/StartMediaButton';

/** @public */
export type ControlBarControls = {
Expand Down Expand Up @@ -168,7 +168,7 @@ export function ControlBar({
{showText && 'Leave'}
</DisconnectButton>
)}
<StartAudio label="Start Audio" />
<StartMediaButton />
</div>
);
}

0 comments on commit 11ec05d

Please sign in to comment.