From a3eabf8f66f7dc0baf6e8ed6b9d123586ec174de Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 25 Mar 2026 16:51:38 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20move=20reaction-?= =?UTF-8?q?related=20code=20into=20a=20dedicated=20feature=20folder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group all reaction components, hooks, and logic under a single feature directory to improve code organization and maintainability. --- .../notifications/MainNotificationToast.tsx | 4 ++-- .../components/ReactionPortals.tsx} | 18 ++++++++++-------- .../components}/ReactionsToggle.tsx | 6 +++--- .../src/features/reactions/constants.ts | 5 +++++ .../hooks/useAnnounceReaction.ts | 5 +++-- .../hooks/useReactions.ts | 7 ++++--- src/frontend/src/features/reactions/types.ts | 17 +++++++++++++++++ .../reactionUtils.ts => reactions/utils.ts} | 0 .../prefabs/ControlBar/DesktopControlBar.tsx | 2 +- .../rooms/livekit/prefabs/VideoConference.tsx | 2 +- src/frontend/src/stores/reactions.ts | 19 +------------------ 11 files changed, 47 insertions(+), 38 deletions(-) rename src/frontend/src/features/{rooms/livekit/components/ReactionPortal.tsx => reactions/components/ReactionPortals.tsx} (91%) rename src/frontend/src/features/{rooms/livekit/components/controls => reactions/components}/ReactionsToggle.tsx (94%) create mode 100644 src/frontend/src/features/reactions/constants.ts rename src/frontend/src/features/{rooms/livekit => reactions}/hooks/useAnnounceReaction.ts (89%) rename src/frontend/src/features/{rooms/livekit => reactions}/hooks/useReactions.ts (91%) create mode 100644 src/frontend/src/features/reactions/types.ts rename src/frontend/src/features/{rooms/livekit/utils/reactionUtils.ts => reactions/utils.ts} (100%) diff --git a/src/frontend/src/features/notifications/MainNotificationToast.tsx b/src/frontend/src/features/notifications/MainNotificationToast.tsx index 29f4a74f..6e5ea93c 100644 --- a/src/frontend/src/features/notifications/MainNotificationToast.tsx +++ b/src/frontend/src/features/notifications/MainNotificationToast.tsx @@ -13,8 +13,8 @@ import { WaitingParticipantNotification } from './components/WaitingParticipantN import { layoutStore } from '@/stores/layout' import { PanelId } from '@/features/rooms/livekit/hooks/useSidePanel' import { useScreenReaderAnnounce } from '@/hooks/useScreenReaderAnnounce' -import { useReactions } from '@/features/rooms/livekit/hooks/useReactions' -import { Emoji } from '@/stores/reactions' +import { Emoji } from '@/features/reactions/types' +import { useReactions } from '@/features/reactions/hooks/useReactions' export const MainNotificationToast = () => { const room = useRoomContext() diff --git a/src/frontend/src/features/rooms/livekit/components/ReactionPortal.tsx b/src/frontend/src/features/reactions/components/ReactionPortals.tsx similarity index 91% rename from src/frontend/src/features/rooms/livekit/components/ReactionPortal.tsx rename to src/frontend/src/features/reactions/components/ReactionPortals.tsx index 3a2585aa..0129d55f 100644 --- a/src/frontend/src/features/rooms/livekit/components/ReactionPortal.tsx +++ b/src/frontend/src/features/reactions/components/ReactionPortals.tsx @@ -3,14 +3,16 @@ import { useState, useEffect, useMemo } from 'react' import { Text } from '@/primitives' import { css } from '@/styled-system/css' import { useSnapshot } from 'valtio' -import { Reaction, reactionsStore } from '@/stores/reactions' +import { reactionsStore } from '@/stores/reactions' import { useAnnounceReaction } from '../hooks/useAnnounceReaction' - -export const ANIMATION_DURATION = 3000 -export const ANIMATION_DISTANCE = 300 -export const FADE_OUT_THRESHOLD = 0.7 -export const REACTION_SPAWN_WIDTH_RATIO = 0.2 -export const INITIAL_POSITION = 200 +import { Reaction } from '../types' +import { + ANIMATION_DISTANCE, + ANIMATION_DURATION, + FADE_OUT_THRESHOLD, + INITIAL_POSITION, + REACTION_SPAWN_WIDTH_RATIO, +} from '../constants' interface FloatingReactionProps { emoji: string @@ -112,7 +114,7 @@ export function FloatingReaction({ ) } -export function ReactionPortal({ reaction }: { reaction: Reaction }) { +const ReactionPortal = ({ reaction }: { reaction: Reaction }) => { const speed = useMemo(() => Math.random() * 1.5 + 0.5, []) const scale = useMemo(() => Math.max(Math.random() + 0.5, 1), []) return createPortal( diff --git a/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx b/src/frontend/src/features/reactions/components/ReactionsToggle.tsx similarity index 94% rename from src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx rename to src/frontend/src/features/reactions/components/ReactionsToggle.tsx index 2d9bafce..24d4abe5 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx +++ b/src/frontend/src/features/reactions/components/ReactionsToggle.tsx @@ -4,7 +4,6 @@ import { useState } from 'react' import { css } from '@/styled-system/css' import { ToggleButton, Button } from '@/primitives' -import { getEmojiLabel } from '@/features/rooms/livekit/utils/reactionUtils' import { useRegisterKeyboardShortcut } from '@/features/shortcuts/useRegisterKeyboardShortcut' import { Popover as RACPopover, @@ -12,8 +11,9 @@ import { DialogTrigger, } from 'react-aria-components' import { FocusScope } from '@react-aria/focus' -import { useReactions } from '../../hooks/useReactions' -import { Emoji } from '@/stores/reactions.ts' +import { useReactions } from '../hooks/useReactions' +import { Emoji } from '../types' +import { getEmojiLabel } from '../utils' export const ReactionsToggle = () => { const { t } = useTranslation('rooms', { keyPrefix: 'controls.reactions' }) diff --git a/src/frontend/src/features/reactions/constants.ts b/src/frontend/src/features/reactions/constants.ts new file mode 100644 index 00000000..1bd3b29d --- /dev/null +++ b/src/frontend/src/features/reactions/constants.ts @@ -0,0 +1,5 @@ +export const ANIMATION_DURATION = 3000 +export const ANIMATION_DISTANCE = 300 +export const FADE_OUT_THRESHOLD = 0.7 +export const REACTION_SPAWN_WIDTH_RATIO = 0.2 +export const INITIAL_POSITION = 200 diff --git a/src/frontend/src/features/rooms/livekit/hooks/useAnnounceReaction.ts b/src/frontend/src/features/reactions/hooks/useAnnounceReaction.ts similarity index 89% rename from src/frontend/src/features/rooms/livekit/hooks/useAnnounceReaction.ts rename to src/frontend/src/features/reactions/hooks/useAnnounceReaction.ts index eadacd45..bf0fef70 100644 --- a/src/frontend/src/features/rooms/livekit/hooks/useAnnounceReaction.ts +++ b/src/frontend/src/features/reactions/hooks/useAnnounceReaction.ts @@ -3,8 +3,9 @@ import { useTranslation } from 'react-i18next' import { useSnapshot } from 'valtio' import { accessibilityStore } from '@/stores/accessibility' import { useScreenReaderAnnounce } from '@/hooks/useScreenReaderAnnounce' -import { getEmojiLabel } from '@/features/rooms/livekit/utils/reactionUtils' -import { Reaction } from '@/stores/reactions' + +import { getEmojiLabel } from '../utils' +import { Reaction } from '../types' export const useAnnounceReaction = (latestReaction: Reaction | undefined) => { const { t } = useTranslation('rooms', { keyPrefix: 'controls.reactions' }) diff --git a/src/frontend/src/features/rooms/livekit/hooks/useReactions.ts b/src/frontend/src/features/reactions/hooks/useReactions.ts similarity index 91% rename from src/frontend/src/features/rooms/livekit/hooks/useReactions.ts rename to src/frontend/src/features/reactions/hooks/useReactions.ts index 7223da51..80ec1697 100644 --- a/src/frontend/src/features/rooms/livekit/hooks/useReactions.ts +++ b/src/frontend/src/features/reactions/hooks/useReactions.ts @@ -1,11 +1,12 @@ import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { Emoji, reactionsStore } from '@/stores/reactions' +import { reactionsStore } from '@/stores/reactions' import { NotificationType } from '@/features/notifications/NotificationType' -import { ANIMATION_DURATION } from '@/features/rooms/livekit/components/ReactionPortal' -import useRateLimiter from '@/hooks/useRateLimiter' import { useNotifyParticipants } from '@/features/notifications' +import useRateLimiter from '@/hooks/useRateLimiter' import { Participant } from 'livekit-client' +import { Emoji } from '../types' +import { ANIMATION_DURATION } from '../constants' export const useReactions = () => { const { t } = useTranslation('rooms', { keyPrefix: 'controls.reactions' }) diff --git a/src/frontend/src/features/reactions/types.ts b/src/frontend/src/features/reactions/types.ts new file mode 100644 index 00000000..5acbdaf8 --- /dev/null +++ b/src/frontend/src/features/reactions/types.ts @@ -0,0 +1,17 @@ +export enum Emoji { + THUMBS_UP = 'thumbs-up', + THUMBS_DOWN = 'thumbs-down', + CLAP = 'clapping-hands', + HEART = 'red-heart', + LAUGHING = 'face-with-tears-of-joy', + SURPRISED = 'face-with-open-mouth', + CELEBRATION = 'party-popper', + PLEASE = 'folded-hands', +} + +export interface Reaction { + id: string + emoji: Emoji + participantName: string + isLocal: boolean +} diff --git a/src/frontend/src/features/rooms/livekit/utils/reactionUtils.ts b/src/frontend/src/features/reactions/utils.ts similarity index 100% rename from src/frontend/src/features/rooms/livekit/utils/reactionUtils.ts rename to src/frontend/src/features/reactions/utils.ts diff --git a/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/DesktopControlBar.tsx b/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/DesktopControlBar.tsx index 83c9a43e..67bce97c 100644 --- a/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/DesktopControlBar.tsx +++ b/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/DesktopControlBar.tsx @@ -3,7 +3,6 @@ import { ControlBarAuxProps } from './ControlBar' import { css } from '@/styled-system/css' import { LeaveButton } from '../../components/controls/LeaveButton' import { Track } from 'livekit-client' -import { ReactionsToggle } from '../../components/controls/ReactionsToggle' import { HandToggle } from '../../components/controls/HandToggle' import { ScreenShareToggle } from '../../components/controls/ScreenShareToggle' import { SubtitlesToggle } from '../../components/controls/SubtitlesToggle' @@ -15,6 +14,7 @@ import { useRegisterKeyboardShortcut } from '@/features/shortcuts/useRegisterKey import { useFullScreen } from '../../hooks/useFullScreen' import { VideoDeviceControl } from '../../components/controls/Device/VideoDeviceControl' import { AudioDevicesControl } from '../../components/controls/Device/AudioDevicesControl' +import { ReactionsToggle } from '@/features/reactions/components/ReactionsToggle' export function DesktopControlBar({ onDeviceError, diff --git a/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx b/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx index 7c6c2eaa..0c846e2f 100644 --- a/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx +++ b/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx @@ -44,7 +44,7 @@ import { GridLayout } from '../components/layout/GridLayout' import { IsIdleDisconnectModal } from '../components/IsIdleDisconnectModal' import { getParticipantName } from '@/features/rooms/utils/getParticipantName' import { useScreenReaderAnnounce } from '@/hooks/useScreenReaderAnnounce' -import { ReactionPortals } from '@/features/rooms/livekit/components/ReactionPortal' +import { ReactionPortals } from '@/features/reactions/components/ReactionPortals' const LayoutWrapper = styled( 'div', diff --git a/src/frontend/src/stores/reactions.ts b/src/frontend/src/stores/reactions.ts index 67309eef..cd853bc4 100644 --- a/src/frontend/src/stores/reactions.ts +++ b/src/frontend/src/stores/reactions.ts @@ -1,22 +1,5 @@ import { proxy } from 'valtio' - -export enum Emoji { - THUMBS_UP = 'thumbs-up', - THUMBS_DOWN = 'thumbs-down', - CLAP = 'clapping-hands', - HEART = 'red-heart', - LAUGHING = 'face-with-tears-of-joy', - SURPRISED = 'face-with-open-mouth', - CELEBRATION = 'party-popper', - PLEASE = 'folded-hands', -} - -export interface Reaction { - id: string - emoji: Emoji - participantName: string - isLocal: boolean -} +import { Reaction } from '@/features/reactions/types' type State = { reactions: Reaction[]