Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 18 additions & 50 deletions packages/ui-voip/src/components/Widget/Widget.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,29 @@
import { FocusScope } from '@react-aria/focus';
import { Palette } from '@rocket.chat/fuselage';
import styled from '@rocket.chat/styled';
import type { ComponentProps, ReactNode } from 'react';
import { useLayoutEffect } from 'react';
import type { ReactNode } from 'react';

import { DragContext } from './WidgetDraggableContext';
import { useDraggable } from '../../hooks';
import { type LastKnownPosition } from '../../providers/useWidgetPositionTracker';

// TODO: Initial position from the draggable api instead of style props
// TODO: A11Y
const WidgetBase = styled('div')`
position: fixed;
padding: 0;
right: 2em;
top: 11em;
display: flex;
flex-direction: column;
width: 248px;
min-height: 128px;
border-radius: 4px;
border: 1px solid ${Palette.stroke['stroke-dark'].toString()};
box-shadow:
0px 0px 1px 0px ${Palette.shadow['shadow-elevation-2x'].toString()},
0px 0px 12px 0px ${Palette.shadow['shadow-elevation-2y'].toString()};
background-color: ${Palette.surface['surface-tint'].toString()};
color: ${Palette.text['font-default'].toString()};
z-index: 100;
overflow: hidden;
`;
import WidgetBase from './WidgetBase';
import { useDraggableWidget } from './WidgetDraggableContext';

export type WidgetProps = {
children: ReactNode;
restorePosition?: LastKnownPosition | null;
onChangePosition?: (position: LastKnownPosition | null) => void;
} & ComponentProps<typeof WidgetBase>;

const Widget = ({ children, onChangePosition, restorePosition, ...props }: WidgetProps) => {
const [draggableRef, boundingRef, handleRef] = useDraggable({ onChangePosition, restorePosition });
autoFocus?: boolean;
};

useLayoutEffect(() => {
boundingRef(document.body);
}, [boundingRef]);
const Widget = ({ children, autoFocus = true, ...props }: WidgetProps) => {
const draggableContext = useDraggableWidget();

return (
<DragContext.Provider value={{ draggableRef, boundingRef, handleRef }}>
<FocusScope autoFocus>
<WidgetBase
{...props}
ref={draggableRef}
role='dialog'
aria-labelledby='rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info'
>
{children}
</WidgetBase>
</FocusScope>
</DragContext.Provider>
<FocusScope autoFocus={autoFocus}>
<WidgetBase
{...props}
ref={draggableContext?.draggableRef}
inline={!draggableContext}
role='dialog'
aria-labelledby='rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info'
>
{children}
</WidgetBase>
</FocusScope>
);
};

Expand Down
38 changes: 38 additions & 0 deletions packages/ui-voip/src/components/Widget/WidgetBase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Palette } from '@rocket.chat/fuselage';
import styled from '@rocket.chat/styled';

type WidgetBaseProps = { inline?: boolean; borderless?: boolean };

const WidgetBase = styled('div', ({ borderless: _borderless, inline: _inline, ...props }: WidgetBaseProps) => props)`
padding: 0;
display: flex;
flex-direction: column;
width: 248px;
min-height: 128px;
border-radius: 4px;
background-color: ${Palette.surface['surface-tint'].toString()};
color: ${Palette.text['font-default'].toString()};
overflow: hidden;

${({ borderless }) =>
borderless
? ''
: `
border: 1px solid ${Palette.stroke['stroke-dark'].toString()};
`}

${({ inline }) =>
inline
? ''
: `
position: fixed;
right: 2em;
top: 11em;
z-index: 100;
box-shadow:
0px 0px 1px 0px ${Palette.shadow['shadow-elevation-2x'].toString()},
0px 0px 12px 0px ${Palette.shadow['shadow-elevation-2y'].toString()};
`}
`;

export default WidgetBase;
16 changes: 5 additions & 11 deletions packages/ui-voip/src/components/Widget/WidgetDraggableContext.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import type { Ref } from 'react';
import type { RefCallback } from 'react';
import { createContext, useContext } from 'react';

type DragContextValue = {
draggableRef: Ref<HTMLElement>;
boundingRef: Ref<HTMLElement>;
handleRef: Ref<HTMLElement>;
draggableRef: RefCallback<HTMLElement>;
boundingRef: RefCallback<HTMLElement>;
handleRef: RefCallback<HTMLElement>;
};

export const DragContext = createContext<DragContextValue | undefined>(undefined);

export const useDraggableWidget = (): DragContextValue => {
const context = useContext(DragContext);
if (!context) {
throw new Error('useDraggableWidget - context unavailable');
}
return context;
};
export const useDraggableWidget = (): DragContextValue | undefined => useContext(DragContext);
26 changes: 26 additions & 0 deletions packages/ui-voip/src/components/Widget/WidgetDraggableProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { ReactNode } from 'react';
import { useLayoutEffect } from 'react';

import { DragContext } from './WidgetDraggableContext';
import { useMediaCallView } from '../../context';
import { useDraggable } from '../../hooks';

type WidgetDraggableProviderProps = {
children: ReactNode;
};

const WidgetDraggableProvider = ({ children }: WidgetDraggableProviderProps) => {
const { widgetPositionTracker } = useMediaCallView();
const [draggableRef, boundingRef, handleRef] = useDraggable({
onChangePosition: widgetPositionTracker?.onChangePosition,
restorePosition: widgetPositionTracker?.getRestorePosition(),
});

useLayoutEffect(() => {
Comment thread
gabriellsh marked this conversation as resolved.
boundingRef(document.body);
}, [boundingRef]);
Comment thread
gabriellsh marked this conversation as resolved.

return <DragContext.Provider value={{ draggableRef, boundingRef, handleRef }}>{children}</DragContext.Provider>;
};

export default WidgetDraggableProvider;
6 changes: 5 additions & 1 deletion packages/ui-voip/src/components/Widget/WidgetHandle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ const dragHandle = css`
`;

const WidgetHandle = (props: ComponentProps<typeof Box>) => {
const { handleRef } = useDraggableWidget();
const draggableContext = useDraggableWidget();
if (!draggableContext) {
return null;
}
const { handleRef } = draggableContext;
return (
<Box height={20} display='flex' flexDirection='row' justifyContent='center' className={dragHandle} ref={handleRef} {...props}>
<Icon name='stacked-meatballs' size='x20' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,9 @@ exports[`renders FullWidget without crashing 1`] = `
/>
<div
aria-labelledby="rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info"
class="rcx-css-1rau14i"
class="rcx-css-1ww4mnk"
role="dialog"
>
<div
class="rcx-box rcx-box--full rcx-css-1aw4sw4 rcx-css-11m6c1h"
style="user-select: none; webkit-user-select: none;"
>
<i
aria-hidden="true"
class="rcx-box rcx-box--full rcx-icon--name-stacked-meatballs rcx-icon rcx-css-4pvxx3"
>
</i>
</div>
<header
class="rcx-box rcx-box--full rcx-css-4vvilp"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const mockedContexts = mockAppRoot()
.buildStoryDecorator();

const meta = {
title: 'Views/MediaCallWidget/Draggable Widget',
component: MediaCallWidget,
args: {
state: 'closed',
Expand Down
35 changes: 11 additions & 24 deletions packages/ui-voip/src/views/MediaCallWidget/MediaCallWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,27 @@
import { OngoingCall, NewCall, IncomingCall, OutgoingCall, IncomingCallTransfer, OutgoingCallTransfer } from '..';
import OngoingCallWithScreen from './OngoingCallWithScreen';
import MediaCallWidgetViewRouter from './MediaCallWidgetViewRouter';
import WidgetDraggableProvider from '../../components/Widget/WidgetDraggableProvider';
import { useMediaCallView } from '../../context/MediaCallViewContext';
import useRegisterView from '../../context/useRegisterView';

const MediaCallWidget = () => {
const currentViews = useRegisterView('widget');
const {
sessionState: { state, hidden, transferredBy, peerInfo, supportedFeatures },
sessionState: { state, hidden },
} = useMediaCallView();

if (hidden || !currentViews.includes('widget')) {
return null;
}

switch (state) {
case 'ongoing':
if ('username' in peerInfo && supportedFeatures.includes('screen-share')) {
return <OngoingCallWithScreen />;
}
return <OngoingCall />;
case 'new':
return <NewCall />;
case 'ringing':
if (transferredBy) {
return <IncomingCallTransfer />;
}
return <IncomingCall />;
case 'calling':
if (transferredBy) {
return <OutgoingCallTransfer />;
}
return <OutgoingCall />;
case 'closed':
default:
return null;
if (state === 'closed') {
return null;
}

return (
<WidgetDraggableProvider>
<MediaCallWidgetViewRouter />
</WidgetDraggableProvider>
);
};

export default MediaCallWidget;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { OngoingCall, NewCall, IncomingCall, OutgoingCall, IncomingCallTransfer, OutgoingCallTransfer } from '..';
Comment thread
gabriellsh marked this conversation as resolved.
import OngoingCallWithScreen from './OngoingCallWithScreen';
import { useMediaCallView } from '../../context/MediaCallViewContext';

const MediaCallWidgetViewRouter = () => {
const {
sessionState: { state, transferredBy, peerInfo, supportedFeatures },
Comment thread
gabriellsh marked this conversation as resolved.
} = useMediaCallView();

switch (state) {
case 'ongoing':
if ('username' in peerInfo && supportedFeatures.includes('screen-share')) {
Comment thread
gabriellsh marked this conversation as resolved.
return <OngoingCallWithScreen />;
}
return <OngoingCall />;
case 'new':
return <NewCall />;
case 'ringing':
if (transferredBy) {
return <IncomingCallTransfer />;
}
return <IncomingCall />;
case 'calling':
if (transferredBy) {
return <OutgoingCallTransfer />;
}
return <OutgoingCall />;
case 'closed':
default:
return null;
}
};

export default MediaCallWidgetViewRouter;
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const OngoingCall = () => {
onOpenPopout,
streams,
onToggleScreenSharing,
widgetPositionTracker,
onClosePopout,
} = useMediaCallView();
const { muted, held, remoteMuted, remoteHeld, peerInfo, connectionState, startedAt } = sessionState;
Expand All @@ -58,7 +57,7 @@ const OngoingCall = () => {
}

return (
<Widget restorePosition={widgetPositionTracker?.getRestorePosition()} onChangePosition={widgetPositionTracker?.onChangePosition}>
<Widget>
<WidgetHandle />
<WidgetHeader title={connecting ? t('meteor_status_connecting') : <Timer startAt={startedAt} />}>
{onClickDirectMessage && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ exports[`renders IncomingCall without crashing 1`] = `
/>
<div
aria-labelledby="rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info"
class="rcx-css-1rau14i"
class="rcx-css-6amvz1"
role="dialog"
>
<div
Expand Down Expand Up @@ -175,7 +175,7 @@ exports[`renders IncomingCallTransfer without crashing 1`] = `
/>
<div
aria-labelledby="rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info"
class="rcx-css-1rau14i"
class="rcx-css-6amvz1"
role="dialog"
>
<div
Expand Down Expand Up @@ -378,7 +378,7 @@ exports[`renders NewCall without crashing 1`] = `
/>
<div
aria-labelledby="rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info"
class="rcx-css-1rau14i"
class="rcx-css-6amvz1"
role="dialog"
>
<div
Expand Down Expand Up @@ -583,7 +583,7 @@ exports[`renders OngoingCall without crashing 1`] = `
/>
<div
aria-labelledby="rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info"
class="rcx-css-1rau14i"
class="rcx-css-6amvz1"
role="dialog"
>
<div
Expand Down Expand Up @@ -810,7 +810,7 @@ exports[`renders OutgoingCall without crashing 1`] = `
/>
<div
aria-labelledby="rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info"
class="rcx-css-1rau14i"
class="rcx-css-6amvz1"
role="dialog"
>
<div
Expand Down Expand Up @@ -959,7 +959,7 @@ exports[`renders OutgoingCallTransfer without crashing 1`] = `
/>
<div
aria-labelledby="rcx-media-call-widget-title-prefix rcx-media-call-widget-title rcx-media-call-widget-caller-info"
class="rcx-css-1rau14i"
class="rcx-css-6amvz1"
role="dialog"
>
<div
Expand Down
Loading