From 266dc85097de7354601767d8cfdf5b3436ecd72b Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 13 Sep 2025 23:46:40 +0900 Subject: [PATCH 01/30] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=A1=9C=EC=A7=81=EC=9D=84=20useTimerPageState=20?= =?UTF-8?q?=ED=9B=85=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/hooks/useTimerPageState.ts | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/page/TimerPage/hooks/useTimerPageState.ts b/src/page/TimerPage/hooks/useTimerPageState.ts index 14e14ee6..af4a333c 100644 --- a/src/page/TimerPage/hooks/useTimerPageState.ts +++ b/src/page/TimerPage/hooks/useTimerPageState.ts @@ -17,6 +17,24 @@ import { } from '../../../type/type'; import { useTimerBackground } from './useTimerBackground'; +/** + * 브라우저별 접두사가 붙은 전체 화면 속성을 포함하는 사용자 정의 인터페이스 + */ +interface DocumentWithFullscreen extends Document { + mozCancelFullScreen?: () => Promise; + webkitExitFullscreen?: () => Promise; + msExitFullscreen?: () => Promise; + mozFullScreenElement?: Element; + webkitFullscreenElement?: Element; + msFullscreenElement?: Element; +} + +interface HTMLElementWithFullscreen extends HTMLElement { + mozRequestFullScreen?: () => Promise; + webkitRequestFullscreen?: () => Promise; + msRequestFullscreen?: () => Promise; +} + /** * 타이머 페이지의 상태(타이머, 라운드, 벨 등) 전반을 관리하는 커스텀 훅 */ @@ -44,6 +62,9 @@ export function useTimerPageState(tableId: number): TimerPageLogics { // 현재 진행 중인 토론 순서 인덱스 const [index, setIndex] = useState(0); + // 전체 화면 여부 + const [isFullscreen, setIsFullscreen] = useState(false); + // 자유토론 타이머, 일반 타이머 상태 관리 커스텀 훅 const timer1 = useTimeBasedTimer(); const timer2 = useTimeBasedTimer(); @@ -68,6 +89,54 @@ export function useTimerPageState(tableId: number): TimerPageLogics { index, }); + /** + * 전체 화면 여부 토글 + */ + const toggleFullscreen = async () => { + const doc = document as DocumentWithFullscreen; + const element = document.documentElement as HTMLElementWithFullscreen; + + try { + const isCurrentlyFullscreen = + doc.fullscreenElement || + doc.webkitFullscreenElement || + doc.mozFullScreenElement || + doc.msFullscreenElement; + + if (!isCurrentlyFullscreen) { + // 전체 화면 시작 (다양한 브라우저 지원) + if (element.requestFullscreen) { + await element.requestFullscreen(); + } else if (element.webkitRequestFullscreen) { + /* Safari */ + await element.webkitRequestFullscreen(); + } else if (element.mozRequestFullScreen) { + /* Firefox */ + await element.mozRequestFullScreen(); + } else if (element.msRequestFullscreen) { + /* IE11 */ + await element.msRequestFullscreen(); + } + } else { + // 전체 화면 종료 (다양한 브라우저 지원) + if (doc.exitFullscreen) { + await doc.exitFullscreen(); + } else if (doc.webkitExitFullscreen) { + /* Safari */ + await doc.webkitExitFullscreen(); + } else if (doc.mozCancelFullScreen) { + /* Firefox */ + await doc.mozCancelFullScreen(); + } else if (doc.msExitFullscreen) { + /* IE11 */ + await doc.msExitFullscreen(); + } + } + } catch (error) { + console.error('# Failed to toggle fullscreen mode:', error); + } + }; + /** * 라운드 이동 (이전/다음) */ @@ -146,6 +215,44 @@ export function useTimerPageState(tableId: number): TimerPageLogics { [prosConsSelected, switchCamp, timer1, timer2], ); + /** + * 전체 화면 상태 변경을 감지 + */ + useEffect(() => { + const handleFullscreenChange = () => { + const doc = document as DocumentWithFullscreen; + setIsFullscreen( + !!( + doc.fullscreenElement || + doc.webkitFullscreenElement || + doc.mozFullScreenElement || + doc.msFullscreenElement + ), + ); + }; + + document.addEventListener('fullscreenchange', handleFullscreenChange); + document.addEventListener('webkitfullscreenchange', handleFullscreenChange); + document.addEventListener('mozfullscreenchange', handleFullscreenChange); + document.addEventListener('MSFullscreenChange', handleFullscreenChange); + + return () => { + document.removeEventListener('fullscreenchange', handleFullscreenChange); + document.removeEventListener( + 'webkitfullscreenchange', + handleFullscreenChange, + ); + document.removeEventListener( + 'mozfullscreenchange', + handleFullscreenChange, + ); + document.removeEventListener( + 'MSFullscreenChange', + handleFullscreenChange, + ); + }; + }); + /** * 라운드 이동/초기 진입 시 타이머 상태 초기화 및 셋업 */ @@ -256,6 +363,8 @@ export function useTimerPageState(tableId: number): TimerPageLogics { isLoading, isError, refetch, + isFullscreen, + toggleFullscreen, }; } @@ -278,4 +387,6 @@ export interface TimerPageLogics { isLoading: boolean; isError: boolean; refetch: () => void; + isFullscreen: boolean; + toggleFullscreen: () => void; } From 7e11110876cbac36ff33f5304df1fe7246bbc969 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sun, 14 Sep 2025 00:23:04 +0900 Subject: [PATCH 02/30] =?UTF-8?q?design:=20=EC=BD=94=EC=9D=B8=20=ED=86=A0?= =?UTF-8?q?=EC=8A=A4=20=EB=AA=A8=EB=8B=AC=EC=9D=98=20=ED=86=A0=EB=A1=A0=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EB=B0=B0=EA=B2=BD=20=EC=83=89=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/TeamSelectionModal/TeamSelectionModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx b/src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx index 676f7315..7d89a5cb 100644 --- a/src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx +++ b/src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx @@ -160,7 +160,7 @@ export default function TeamSelectionModal({ {(coinState === 'front' || coinState === 'back') && (
); } From dc82289fb5d958df18fa2280e27bdb17b8401d7c Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sun, 14 Sep 2025 00:30:27 +0900 Subject: [PATCH 04/30] =?UTF-8?q?fix:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=EB=A8=B8=20=EC=8B=9C=EA=B0=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80/=EA=B0=90=EC=86=8C=20=EC=8B=9C=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=20=EC=8B=9C=EA=B0=84=20=EA=B8=B0=EC=A4=80=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=EB=90=98=EA=B2=8C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/hooks/useFeedbackTimer.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/page/TimerPage/hooks/useFeedbackTimer.ts b/src/page/TimerPage/hooks/useFeedbackTimer.ts index c073317e..3073ed56 100644 --- a/src/page/TimerPage/hooks/useFeedbackTimer.ts +++ b/src/page/TimerPage/hooks/useFeedbackTimer.ts @@ -82,16 +82,19 @@ export function useFeedbackTimer(): FeedbackTimerLogics { */ const adjustTime = useCallback( (amount: number) => { - if (isRunning) return; + if (isRunning) { + return; + } + + let newTime: number; - setTimer((prevTimer) => { - const newTime = (prevTimer ?? 0) + amount; + setDefaultTimer((prevDefault) => { + newTime = prevDefault + amount; return newTime < 0 ? 0 : newTime; }); - setDefaultTimer((prevDefault) => { - const newDefault = prevDefault + amount; - return newDefault < 0 ? 0 : newDefault; + setTimer(() => { + return newTime < 0 ? 0 : newTime; }); }, [isRunning], From fec80cc84626972c99d70ccf11f7d6a95451d23d Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sun, 14 Sep 2025 14:07:24 +0900 Subject: [PATCH 05/30] =?UTF-8?q?design:=20=ED=97=A4=EB=8D=94=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EB=B2=A1=ED=84=B0=20=EC=8D=A8=EB=8B=88?= =?UTF-8?q?=EA=B0=80=20=EB=91=90=EA=BB=98=20=EC=A4=84=EC=9D=B8=20=EA=B2=83?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/icons/Help.tsx | 12 +++++++----- src/components/icons/Home.tsx | 8 ++++---- src/components/icons/Login.tsx | 20 ++++++++++---------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/components/icons/Help.tsx b/src/components/icons/Help.tsx index b90e133e..8f2d2fb0 100644 --- a/src/components/icons/Help.tsx +++ b/src/components/icons/Help.tsx @@ -7,24 +7,26 @@ export default function DTHelp({ }: IconProps) { return ( ); diff --git a/src/components/icons/Home.tsx b/src/components/icons/Home.tsx index 746206a7..0ecfd16b 100644 --- a/src/components/icons/Home.tsx +++ b/src/components/icons/Home.tsx @@ -7,19 +7,19 @@ export default function DTHome({ }: IconProps) { return ( diff --git a/src/components/icons/Login.tsx b/src/components/icons/Login.tsx index a0736687..73444881 100644 --- a/src/components/icons/Login.tsx +++ b/src/components/icons/Login.tsx @@ -7,40 +7,40 @@ export default function DTLogin({ }: IconProps) { return ( From b0b4559a30a885d0a4910192933f5ec6f3f5b853 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sun, 14 Sep 2025 14:15:55 +0900 Subject: [PATCH 06/30] =?UTF-8?q?feat:=20=EB=8F=84=EC=9B=80=EB=A7=90?= =?UTF-8?q?=EC=97=90=20=EC=A0=84=EC=B2=B4=20=ED=99=94=EB=A9=B4=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimerPage/components/FirstUseToolTip.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/page/TimerPage/components/FirstUseToolTip.tsx b/src/page/TimerPage/components/FirstUseToolTip.tsx index ea3ded13..98d5c3ba 100644 --- a/src/page/TimerPage/components/FirstUseToolTip.tsx +++ b/src/page/TimerPage/components/FirstUseToolTip.tsx @@ -1,6 +1,7 @@ import { PropsWithChildren } from 'react'; import { LuKeyboard } from 'react-icons/lu'; import { MdOutlineTimer } from 'react-icons/md'; +import { RiFullscreenExitFill, RiFullscreenFill } from 'react-icons/ri'; // z-index // - 30: Tooltip @@ -68,6 +69,26 @@ export default function FirstUseToolTip({ onClose }: FirstUseToolTipProps) {
+
+
+ +

전체 화면

+
+ +
+ + 화면 우측 상단 헤더의 전체 화면 버튼 + + 으로 활성화 + + + 화면 우측 상단 헤더의 전체 화면 닫기 버튼 + + 또는 ESC 키를 눌러 전체 화면 비활성화 + +
+
+
+ From 8cf96cc6a239584352713de73c2a8a054ad51378 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 23 Sep 2025 13:38:54 +0900 Subject: [PATCH 08/30] =?UTF-8?q?fix:=20=ED=85=8D=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EA=B0=80=202=EC=A4=84=20=EC=9D=B4=EC=83=81=20=EB=8A=98?= =?UTF-8?q?=EC=96=B4=EB=82=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/components/header/StickyTriSectionHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/components/header/StickyTriSectionHeader.tsx b/src/layout/components/header/StickyTriSectionHeader.tsx index 5ba31c10..91c28825 100644 --- a/src/layout/components/header/StickyTriSectionHeader.tsx +++ b/src/layout/components/header/StickyTriSectionHeader.tsx @@ -64,7 +64,7 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { {isGuestFlow() && ( <> {/* Guest mode indicator */} -
+
비회원 모드
From 33e5dba8a39bb597a1c8328d255673f5d6fae191 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 23 Sep 2025 13:39:04 +0900 Subject: [PATCH 09/30] =?UTF-8?q?fix:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=B0=B0=EC=97=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/hooks/useTimerPageState.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page/TimerPage/hooks/useTimerPageState.ts b/src/page/TimerPage/hooks/useTimerPageState.ts index af4a333c..4ecfd4a9 100644 --- a/src/page/TimerPage/hooks/useTimerPageState.ts +++ b/src/page/TimerPage/hooks/useTimerPageState.ts @@ -251,7 +251,7 @@ export function useTimerPageState(tableId: number): TimerPageLogics { handleFullscreenChange, ); }; - }); + }, []); /** * 라운드 이동/초기 진입 시 타이머 상태 초기화 및 셋업 From b936bc2b8c0c2898eb0bc01da08a7acd96f7a6d0 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 23 Sep 2025 13:39:12 +0900 Subject: [PATCH 10/30] =?UTF-8?q?fix:=20=EC=95=84=EC=9D=B4=EC=BD=98=20?= =?UTF-8?q?=ED=81=AC=EA=B8=B0=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/TimerPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/page/TimerPage/TimerPage.tsx b/src/page/TimerPage/TimerPage.tsx index 86a6cc1d..8fdaea16 100644 --- a/src/page/TimerPage/TimerPage.tsx +++ b/src/page/TimerPage/TimerPage.tsx @@ -87,7 +87,7 @@ export default function TimerPage() { title="도움말" onClick={openUseTooltipModal} > - + From 76c6cc13e46359517fbc5eec3d2bacaf3b1e0ed4 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 23 Sep 2025 13:42:10 +0900 Subject: [PATCH 11/30] =?UTF-8?q?fix:=20=EC=95=84=EC=9D=B4=EC=BD=98=20?= =?UTF-8?q?=EB=B2=A1=ED=84=B0=EC=97=90=EC=84=9C=20=EB=B9=A0=EC=A7=84=20?= =?UTF-8?q?=EC=83=89=EC=83=81=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/icons/Help.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/icons/Help.tsx b/src/components/icons/Help.tsx index 8f2d2fb0..2be059da 100644 --- a/src/components/icons/Help.tsx +++ b/src/components/icons/Help.tsx @@ -25,7 +25,7 @@ export default function DTHelp({ From 277725ab8d46a536482339a1a3da1342a90b677c Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 23 Sep 2025 13:51:33 +0900 Subject: [PATCH 12/30] =?UTF-8?q?refactor:=20=EC=A0=84=EC=B2=B4=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=ED=86=A0=EA=B8=80=20=ED=95=A8=EC=88=98=20useCallba?= =?UTF-8?q?ck=20=EC=A0=81=EC=9A=A9=ED=95=98=EC=97=AC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/hooks/useTimerPageState.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/page/TimerPage/hooks/useTimerPageState.ts b/src/page/TimerPage/hooks/useTimerPageState.ts index 4ecfd4a9..4bd18288 100644 --- a/src/page/TimerPage/hooks/useTimerPageState.ts +++ b/src/page/TimerPage/hooks/useTimerPageState.ts @@ -92,7 +92,7 @@ export function useTimerPageState(tableId: number): TimerPageLogics { /** * 전체 화면 여부 토글 */ - const toggleFullscreen = async () => { + const toggleFullscreen = useCallback(async () => { const doc = document as DocumentWithFullscreen; const element = document.documentElement as HTMLElementWithFullscreen; @@ -135,7 +135,7 @@ export function useTimerPageState(tableId: number): TimerPageLogics { } catch (error) { console.error('# Failed to toggle fullscreen mode:', error); } - }; + }, []); /** * 라운드 이동 (이전/다음) From 534a001081f451b8804f1821dea474987359859c Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 23 Sep 2025 13:51:46 +0900 Subject: [PATCH 13/30] =?UTF-8?q?fix:=20=EC=A0=84=EC=B2=B4=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EB=84=88=EB=B9=84=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/TimerPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/page/TimerPage/TimerPage.tsx b/src/page/TimerPage/TimerPage.tsx index 8fdaea16..9547375b 100644 --- a/src/page/TimerPage/TimerPage.tsx +++ b/src/page/TimerPage/TimerPage.tsx @@ -90,14 +90,14 @@ export default function TimerPage() { From 397f7c06857a551aa3a1df1ed63979d627666dd7 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 23 Sep 2025 13:56:07 +0900 Subject: [PATCH 14/30] =?UTF-8?q?feat:=20=EB=B0=9C=EC=96=B8=20=EC=9C=A0?= =?UTF-8?q?=ED=98=95=20=EA=B8=B0=EB=B3=B8=EA=B0=92=EC=97=90=20=EA=B5=90?= =?UTF-8?q?=EC=B0=A8=20=EC=A1=B0=EC=82=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimerCreationContent/TimerCreationContent.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx b/src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx index 8a408f45..2a2363a7 100644 --- a/src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx +++ b/src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx @@ -38,13 +38,20 @@ type TimerCreationOption = | 'TIME_NORMAL' | 'BELL'; -type SpeechType = 'OPENING' | 'REBUTTAL' | 'TIMEOUT' | 'CLOSING' | 'CUSTOM'; +type SpeechType = + | 'OPENING' + | 'REBUTTAL' + | 'TIMEOUT' + | 'CLOSING' + | 'CROSS_EXAM' + | 'CUSTOM'; const SPEECH_TYPE_RECORD: Record = { OPENING: '입론', CLOSING: '최종 발언', CUSTOM: '직접 입력', REBUTTAL: '반론', + CROSS_EXAM: '교차 조사', TIMEOUT: '작전 시간', } as const; @@ -122,6 +129,9 @@ export default function TimerCreationContent({ case '작전시간': case '작전 시간': return 'TIMEOUT'; + case '교차조사': + case '교차 조사': + return 'CROSS_EXAM'; default: return 'CUSTOM'; } @@ -234,6 +244,7 @@ export default function TimerCreationContent({ { value: 'OPENING', label: SPEECH_TYPE_RECORD['OPENING'] }, { value: 'REBUTTAL', label: SPEECH_TYPE_RECORD['REBUTTAL'] }, { value: 'TIMEOUT', label: SPEECH_TYPE_RECORD['TIMEOUT'] }, + { value: 'CROSS_EXAM', label: SPEECH_TYPE_RECORD['CROSS_EXAM'] }, { value: 'CLOSING', label: SPEECH_TYPE_RECORD['CLOSING'] }, { value: 'CUSTOM', label: SPEECH_TYPE_RECORD['CUSTOM'] }, ] as const; From ddc8661675420eac9159b3141fbfb0888c1e85d9 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 30 Sep 2025 22:11:43 +0900 Subject: [PATCH 15/30] =?UTF-8?q?refactor:=20=ED=97=A4=EB=8D=94=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=97=90=20=EC=A0=91=EA=B7=BC=EC=84=B1=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/components/header/StickyTriSectionHeader.tsx | 4 ++++ src/page/TimerPage/TimerPage.tsx | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/layout/components/header/StickyTriSectionHeader.tsx b/src/layout/components/header/StickyTriSectionHeader.tsx index c243f946..a5cff81d 100644 --- a/src/layout/components/header/StickyTriSectionHeader.tsx +++ b/src/layout/components/header/StickyTriSectionHeader.tsx @@ -83,6 +83,8 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { return ( From 1722c9f52b61abd588b289cfc774528d597b8e78 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 30 Sep 2025 22:19:24 +0900 Subject: [PATCH 16/30] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B3=A0=EA=B0=80=20?= =?UTF-8?q?=EC=9B=90=ED=98=95=EC=9C=BC=EB=A1=9C=20=EC=9E=98=EB=A6=AC?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/template_logo/kondae_time.png | Bin 14424 -> 16223 bytes .../LandingPage/components/TemplateCard.tsx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/template_logo/kondae_time.png b/src/assets/template_logo/kondae_time.png index ed4dcee056ff772e8ddc412f95050b50473ade23..f75c2b8454758d1c99afa7cccaf3ab93c24c8e5f 100644 GIT binary patch literal 16223 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 e@yhZ))BZoJVj?P+y=6-P0000 )}
From 46a949a7d5674a594d983c43391f7a84f8b6ec2a Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 30 Sep 2025 22:26:07 +0900 Subject: [PATCH 17/30] =?UTF-8?q?fix:=20=EC=8B=9C=EA=B0=84=20=EC=B4=9D?= =?UTF-8?q?=EB=9F=89=EC=A0=9C=20=ED=83=80=EC=9D=B4=EB=A8=B8=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=20=EC=8B=9C=EA=B0=84=20=EC=A0=81=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/components/TimeBasedTimer.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/page/TimerPage/components/TimeBasedTimer.tsx b/src/page/TimerPage/components/TimeBasedTimer.tsx index c5e79b9c..05217554 100644 --- a/src/page/TimerPage/components/TimeBasedTimer.tsx +++ b/src/page/TimerPage/components/TimeBasedTimer.tsx @@ -141,11 +141,11 @@ export default function TimeBasedTimer({ 전체 시간 -

+

{minute}

:

-

+

{second}

@@ -161,12 +161,12 @@ export default function TimeBasedTimer({ > 현재 시간 - -

+ +

{speakingMinute}

:

-

+

{speakingSecond}

From 2b8fa0723fabb29492e68b3d3140c9991a4cd76e Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 30 Sep 2025 22:34:54 +0900 Subject: [PATCH 18/30] =?UTF-8?q?design:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=EB=A8=B8=20=EB=B0=8F=20=ED=86=A0=EB=A1=A0=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B0=80?= =?UTF-8?q?=EC=9A=B4=EB=8D=B0=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/DebateEndPage/DebateEndPage.tsx | 7 ++++--- src/page/TimerPage/FeedbackTimerPage.tsx | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/page/DebateEndPage/DebateEndPage.tsx b/src/page/DebateEndPage/DebateEndPage.tsx index f631fe5d..cc95557f 100644 --- a/src/page/DebateEndPage/DebateEndPage.tsx +++ b/src/page/DebateEndPage/DebateEndPage.tsx @@ -21,7 +21,7 @@ export default function DebateEndPage() { return (

@@ -56,7 +56,7 @@ export default function DebateEndPage() { {/* 승패투표 카드 */}

-
+ +
diff --git a/src/page/TimerPage/FeedbackTimerPage.tsx b/src/page/TimerPage/FeedbackTimerPage.tsx index 9e986b7a..b71eb917 100644 --- a/src/page/TimerPage/FeedbackTimerPage.tsx +++ b/src/page/TimerPage/FeedbackTimerPage.tsx @@ -21,7 +21,10 @@ export default function FeedbackTimerPage() {
- + +
+ +
From 8311a083186fb115ae464eb1561a4933dfa02e48 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Tue, 30 Sep 2025 22:40:36 +0900 Subject: [PATCH 19/30] =?UTF-8?q?fix:=20=EC=88=9C=EC=84=9C=20=EC=A0=84?= =?UTF-8?q?=ED=99=98=20=EC=8B=9C=20=ED=94=84=EB=A1=9C=EA=B7=B8=EB=A0=88?= =?UTF-8?q?=EC=8A=A4=20=EB=B0=94=20=ED=8A=95=EA=B8=B0=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/components/FeedbackTimer.tsx | 2 +- src/page/TimerPage/components/NormalTimer.tsx | 2 +- src/page/TimerPage/components/TimeBasedTimer.tsx | 2 +- src/page/TimerPage/hooks/useCircularTimerAnimation.ts | 9 ++++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/page/TimerPage/components/FeedbackTimer.tsx b/src/page/TimerPage/components/FeedbackTimer.tsx index f997cfa3..21981ff0 100644 --- a/src/page/TimerPage/components/FeedbackTimer.tsx +++ b/src/page/TimerPage/components/FeedbackTimer.tsx @@ -38,7 +38,7 @@ export default function FeedbackTimer({ timer !== null && defaultTimer > 0 ? ((defaultTimer - timer) / defaultTimer) * 100 : 0; - const progressMotionValue = useCircularTimerAnimation(rawProgress); + const progressMotionValue = useCircularTimerAnimation(rawProgress, isRunning); const breakpoint = useBreakpoint(); const getStrokeWidth = () => { diff --git a/src/page/TimerPage/components/NormalTimer.tsx b/src/page/TimerPage/components/NormalTimer.tsx index 8cb82690..c74af4f2 100644 --- a/src/page/TimerPage/components/NormalTimer.tsx +++ b/src/page/TimerPage/components/NormalTimer.tsx @@ -51,7 +51,7 @@ export default function NormalTimer({ const titleText = item.speechType; const rawProgress = timer !== null && item.time ? ((item.time - timer) / item.time) * 100 : 0; - const progressMotionValue = useCircularTimerAnimation(rawProgress); + const progressMotionValue = useCircularTimerAnimation(rawProgress, isRunning); const breakpoint = useBreakpoint(); const getStrokeWidth = () => { switch (breakpoint) { diff --git a/src/page/TimerPage/components/TimeBasedTimer.tsx b/src/page/TimerPage/components/TimeBasedTimer.tsx index 05217554..f72ae9dd 100644 --- a/src/page/TimerPage/components/TimeBasedTimer.tsx +++ b/src/page/TimerPage/components/TimeBasedTimer.tsx @@ -84,7 +84,7 @@ export default function TimeBasedTimer({ }; const rawProgress = initRawProgress(); - const progressMotionValue = useCircularTimerAnimation(rawProgress); + const progressMotionValue = useCircularTimerAnimation(rawProgress, isRunning); const breakpoint = useBreakpoint(); const getStrokeWidth = () => { diff --git a/src/page/TimerPage/hooks/useCircularTimerAnimation.ts b/src/page/TimerPage/hooks/useCircularTimerAnimation.ts index 228fd692..40459e34 100644 --- a/src/page/TimerPage/hooks/useCircularTimerAnimation.ts +++ b/src/page/TimerPage/hooks/useCircularTimerAnimation.ts @@ -1,18 +1,21 @@ import { animate, clamp, useMotionValue } from 'framer-motion'; import { useEffect } from 'react'; -export default function useCircularTimerAnimation(rawProgress: number) { +export default function useCircularTimerAnimation( + rawProgress: number, + isRunning: boolean, +) { const progress = clamp(0, 100, rawProgress); const progressMotionValue = useMotionValue(0); useEffect(() => { const controls = animate(progressMotionValue, progress, { - duration: 0.7, + duration: isRunning ? 0.7 : 0, ease: 'easeOut', }); return () => controls.stop(); - }, [progress, progressMotionValue]); + }, [progress, progressMotionValue, isRunning]); return progressMotionValue; } From b00c45fcae832bd2828a4af117766c81f49e7b57 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Wed, 1 Oct 2025 11:38:30 +0900 Subject: [PATCH 20/30] =?UTF-8?q?fix:=20=EA=B3=A0=EC=A0=95=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=ED=83=9C=EA=B7=B8=EB=A5=BC=20absolute?= =?UTF-8?q?=EC=97=90=EC=84=9C=20fixed=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/DebateEndPage/DebateEndPage.tsx | 4 ++-- src/page/TimerPage/FeedbackTimerPage.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/page/DebateEndPage/DebateEndPage.tsx b/src/page/DebateEndPage/DebateEndPage.tsx index cc95557f..c9d8d4c9 100644 --- a/src/page/DebateEndPage/DebateEndPage.tsx +++ b/src/page/DebateEndPage/DebateEndPage.tsx @@ -21,7 +21,7 @@ export default function DebateEndPage() { return (

@@ -80,7 +80,7 @@ export default function DebateEndPage() {

-
+
diff --git a/src/page/TimerPage/FeedbackTimerPage.tsx b/src/page/TimerPage/FeedbackTimerPage.tsx index b71eb917..cbb607bf 100644 --- a/src/page/TimerPage/FeedbackTimerPage.tsx +++ b/src/page/TimerPage/FeedbackTimerPage.tsx @@ -19,10 +19,10 @@ export default function FeedbackTimerPage() { return ( -
+
-
+
From cf91488c33f0e621ec5785c187934638aa2da6c5 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 4 Oct 2025 16:41:03 +0900 Subject: [PATCH 21/30] =?UTF-8?q?refactor:=20=EC=A0=84=EC=B2=B4=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=EB=B3=84=EB=8F=84=20=ED=8C=8C=EC=9D=BC=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/hooks/useTimerPageState.ts | 22 ++++--------------- src/type/fullscreen.d.ts | 17 ++++++++++++++ 2 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 src/type/fullscreen.d.ts diff --git a/src/page/TimerPage/hooks/useTimerPageState.ts b/src/page/TimerPage/hooks/useTimerPageState.ts index 4bd18288..3fb0b4e1 100644 --- a/src/page/TimerPage/hooks/useTimerPageState.ts +++ b/src/page/TimerPage/hooks/useTimerPageState.ts @@ -16,24 +16,10 @@ import { TimerBGState, } from '../../../type/type'; import { useTimerBackground } from './useTimerBackground'; - -/** - * 브라우저별 접두사가 붙은 전체 화면 속성을 포함하는 사용자 정의 인터페이스 - */ -interface DocumentWithFullscreen extends Document { - mozCancelFullScreen?: () => Promise; - webkitExitFullscreen?: () => Promise; - msExitFullscreen?: () => Promise; - mozFullScreenElement?: Element; - webkitFullscreenElement?: Element; - msFullscreenElement?: Element; -} - -interface HTMLElementWithFullscreen extends HTMLElement { - mozRequestFullScreen?: () => Promise; - webkitRequestFullscreen?: () => Promise; - msRequestFullscreen?: () => Promise; -} +import { + DocumentWithFullscreen, + HTMLElementWithFullscreen, +} from '../../../type/fullscreen'; /** * 타이머 페이지의 상태(타이머, 라운드, 벨 등) 전반을 관리하는 커스텀 훅 diff --git a/src/type/fullscreen.d.ts b/src/type/fullscreen.d.ts new file mode 100644 index 00000000..b7137659 --- /dev/null +++ b/src/type/fullscreen.d.ts @@ -0,0 +1,17 @@ +/** + * 브라우저별 접두사가 붙은 전체 화면 속성을 포함하는 사용자 정의 인터페이스 + */ +export interface DocumentWithFullscreen extends Document { + mozCancelFullScreen?: () => Promise; + webkitExitFullscreen?: () => Promise; + msExitFullscreen?: () => Promise; + mozFullScreenElement?: Element; + webkitFullscreenElement?: Element; + msFullscreenElement?: Element; +} + +export interface HTMLElementWithFullscreen extends HTMLElement { + mozRequestFullScreen?: () => Promise; + webkitRequestFullscreen?: () => Promise; + msRequestFullscreen?: () => Promise; +} From 6659e7831dc6b0c7a34cb2e11ce4aa32315055cb Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 4 Oct 2025 19:51:21 +0900 Subject: [PATCH 22/30] =?UTF-8?q?refactor:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EB=A1=9C=EC=A7=81=20=EB=B3=84=EB=8F=84=20?= =?UTF-8?q?=ED=9B=85=EC=9C=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useFullscreen.ts | 105 +++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/hooks/useFullscreen.ts diff --git a/src/hooks/useFullscreen.ts b/src/hooks/useFullscreen.ts new file mode 100644 index 00000000..958ed1c6 --- /dev/null +++ b/src/hooks/useFullscreen.ts @@ -0,0 +1,105 @@ +import { useCallback, useLayoutEffect, useState } from 'react'; +import { + DocumentWithFullscreen, + HTMLElementWithFullscreen, +} from '../type/fullscreen'; + +// 헬퍼 함수: 현재 전체 화면 요소가 무엇인지 반환 (없으면 null) +const getFullscreenElement = (): Element | null => { + const doc = document as DocumentWithFullscreen; + return ( + doc.fullscreenElement || + doc.webkitFullscreenElement || + doc.mozFullScreenElement || + doc.msFullscreenElement || + null + ); +}; + +// 헬퍼 함수: 전체 화면 진입 +const enterFullscreen = async (element: HTMLElementWithFullscreen) => { + try { + if (element.requestFullscreen) { + await element.requestFullscreen(); + } else if (element.webkitRequestFullscreen) { + await element.webkitRequestFullscreen(); // Safari + } else if (element.mozRequestFullScreen) { + await element.mozRequestFullScreen(); // Firefox + } else if (element.msRequestFullscreen) { + await element.msRequestFullscreen(); // IE11 + } + } catch (error) { + console.error('# Failed to enter fullscreen mode:', error); + } +}; + +// 헬퍼 함수: 전체 화면 해제 +const exitFullscreen = async () => { + const doc = document as DocumentWithFullscreen; + try { + if (doc.exitFullscreen) { + await doc.exitFullscreen(); + } else if (doc.webkitExitFullscreen) { + await doc.webkitExitFullscreen(); // Safari + } else if (doc.mozCancelFullScreen) { + await doc.mozCancelFullScreen(); // Firefox + } else if (doc.msExitFullscreen) { + await doc.msExitFullscreen(); // IE11 + } + } catch (error) { + console.error('# Failed to exit fullscreen mode:', error); + } +}; + +export default function useFullscreen() { + // 전체 화면 여부를 묘사하는 변수 + const [isFullscreen, setIsFullscreen] = useState(!!getFullscreenElement()); + const handleFullscreenChange = useCallback(() => { + setIsFullscreen(!!getFullscreenElement()); + }, []); + + // 이벤트 리스너 등록 + useLayoutEffect(() => { + const EVENTS = [ + 'fullscreenchange', + 'webkitfullscreenchange', + 'mozfullscreenchange', + 'MSFullscreenChange', + ]; + + EVENTS.forEach((event) => { + document.addEventListener(event, handleFullscreenChange); + }); + + return () => { + EVENTS.forEach((event) => { + document.removeEventListener(event, handleFullscreenChange); + }); + }; + }, [handleFullscreenChange]); + + // 토글 함수 + const toggleFullscreen = useCallback(async () => { + const element = document.documentElement as HTMLElementWithFullscreen; + + if (isFullscreen) { + await exitFullscreen(); + } else { + await enterFullscreen(element); + } + }, [isFullscreen]); + + // 값을 직접 입력하는 함수 + const setFullscreen = useCallback(async (value: boolean) => { + const element = document.documentElement as HTMLElementWithFullscreen; + const isCurrentlyFullscreen = !!getFullscreenElement(); + + if (value && !isCurrentlyFullscreen) { + await enterFullscreen(element); + } else if (!value && isCurrentlyFullscreen) { + await exitFullscreen(); + } + }, []); + + return { isFullscreen, toggleFullscreen, setFullscreen }; +} From ae356a099cb62f6dd7f598339d4ba2c03f5aadda Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 4 Oct 2025 19:51:46 +0900 Subject: [PATCH 23/30] =?UTF-8?q?feat:=20=ED=99=88,=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EB=B2=84=ED=8A=BC=20=ED=81=B4=EB=A6=AD=20?= =?UTF-8?q?=EC=8B=9C=20=EC=A0=84=EC=B2=B4=20=ED=99=94=EB=A9=B4=20=EB=81=84?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/header/StickyTriSectionHeader.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/layout/components/header/StickyTriSectionHeader.tsx b/src/layout/components/header/StickyTriSectionHeader.tsx index 91c28825..f3041208 100644 --- a/src/layout/components/header/StickyTriSectionHeader.tsx +++ b/src/layout/components/header/StickyTriSectionHeader.tsx @@ -11,6 +11,7 @@ import { useModal } from '../../../hooks/useModal'; import DialogModal from '../../../components/DialogModal/DialogModal'; import DTHome from '../../../components/icons/Home'; import DTLogin from '../../../components/icons/Login'; +import useFullscreen from '../../../hooks/useFullscreen'; // The type of header icons will be declared here. type HeaderIcons = 'home' | 'auth'; @@ -50,6 +51,7 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { const navigate = useNavigate(); const { mutate: logoutMutate } = useLogout(() => navigate('/home')); const { openModal, closeModal, ModalWrapper } = useModal({}); + const { isFullscreen, setFullscreen } = useFullscreen(); const defaultIcons: HeaderIcons[] = ['home', 'auth']; const handleLoginStart = (keepData: boolean) => { @@ -85,6 +87,11 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { className="flex h-full items-center justify-center p-[4px]" key={`${iconName}-${index}`} onClick={() => { + // 전체 화면 상태에서 홈으로 이동하는 경우, 전체 화면 비활성화 + if (isFullscreen) { + setFullscreen(false); + } + if (isGuestFlow()) { deleteSessionCustomizeTableData(); } @@ -100,6 +107,11 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { className="flex h-full items-center justify-center p-[4px]" key={`${iconName}-${index}`} onClick={() => { + // 전체 화면 상태에서 홈으로 이동하는 경우, 전체 화면 비활성화 + if (isFullscreen) { + setFullscreen(false); + } + if (isLoggedIn()) { logoutMutate(); } else { From a3cc47a0f44efc616db2d2a05116a2edd9628b72 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 4 Oct 2025 19:52:11 +0900 Subject: [PATCH 24/30] =?UTF-8?q?feat:=20=ED=86=A0=EB=A1=A0=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=20=EC=A0=84=EC=B2=B4=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=20=EB=81=84=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/TimerPage.tsx | 10 +- src/page/TimerPage/hooks/useTimerPageState.ts | 96 +------------------ 2 files changed, 13 insertions(+), 93 deletions(-) diff --git a/src/page/TimerPage/TimerPage.tsx b/src/page/TimerPage/TimerPage.tsx index 9547375b..5fe8774d 100644 --- a/src/page/TimerPage/TimerPage.tsx +++ b/src/page/TimerPage/TimerPage.tsx @@ -40,6 +40,7 @@ export default function TimerPage() { isError, refetch, isFullscreen, + setFullscreen, toggleFullscreen, } = state; @@ -121,7 +122,14 @@ export default function TimerPage() { table={data.table} index={index} goToOtherItem={goToOtherItem} - openDoneModal={openLoginAndStoreModalOrGoToDebateEndPage} + openDoneModal={() => { + // 전체 화면 상태에서 토론을 끝낼 경우, 전체 화면을 비활성화 + if (isFullscreen) { + setFullscreen(false); + } + + openLoginAndStoreModalOrGoToDebateEndPage(); + }} className="absolute bottom-[66px] left-1/2 -translate-x-1/2" /> )} diff --git a/src/page/TimerPage/hooks/useTimerPageState.ts b/src/page/TimerPage/hooks/useTimerPageState.ts index 3fb0b4e1..813150d7 100644 --- a/src/page/TimerPage/hooks/useTimerPageState.ts +++ b/src/page/TimerPage/hooks/useTimerPageState.ts @@ -16,10 +16,7 @@ import { TimerBGState, } from '../../../type/type'; import { useTimerBackground } from './useTimerBackground'; -import { - DocumentWithFullscreen, - HTMLElementWithFullscreen, -} from '../../../type/fullscreen'; +import useFullscreen from '../../../hooks/useFullscreen'; /** * 타이머 페이지의 상태(타이머, 라운드, 벨 등) 전반을 관리하는 커스텀 훅 @@ -48,9 +45,6 @@ export function useTimerPageState(tableId: number): TimerPageLogics { // 현재 진행 중인 토론 순서 인덱스 const [index, setIndex] = useState(0); - // 전체 화면 여부 - const [isFullscreen, setIsFullscreen] = useState(false); - // 자유토론 타이머, 일반 타이머 상태 관리 커스텀 훅 const timer1 = useTimeBasedTimer(); const timer2 = useTimeBasedTimer(); @@ -75,53 +69,7 @@ export function useTimerPageState(tableId: number): TimerPageLogics { index, }); - /** - * 전체 화면 여부 토글 - */ - const toggleFullscreen = useCallback(async () => { - const doc = document as DocumentWithFullscreen; - const element = document.documentElement as HTMLElementWithFullscreen; - - try { - const isCurrentlyFullscreen = - doc.fullscreenElement || - doc.webkitFullscreenElement || - doc.mozFullScreenElement || - doc.msFullscreenElement; - - if (!isCurrentlyFullscreen) { - // 전체 화면 시작 (다양한 브라우저 지원) - if (element.requestFullscreen) { - await element.requestFullscreen(); - } else if (element.webkitRequestFullscreen) { - /* Safari */ - await element.webkitRequestFullscreen(); - } else if (element.mozRequestFullScreen) { - /* Firefox */ - await element.mozRequestFullScreen(); - } else if (element.msRequestFullscreen) { - /* IE11 */ - await element.msRequestFullscreen(); - } - } else { - // 전체 화면 종료 (다양한 브라우저 지원) - if (doc.exitFullscreen) { - await doc.exitFullscreen(); - } else if (doc.webkitExitFullscreen) { - /* Safari */ - await doc.webkitExitFullscreen(); - } else if (doc.mozCancelFullScreen) { - /* Firefox */ - await doc.mozCancelFullScreen(); - } else if (doc.msExitFullscreen) { - /* IE11 */ - await doc.msExitFullscreen(); - } - } - } catch (error) { - console.error('# Failed to toggle fullscreen mode:', error); - } - }, []); + const { isFullscreen, setFullscreen, toggleFullscreen } = useFullscreen(); /** * 라운드 이동 (이전/다음) @@ -201,44 +149,6 @@ export function useTimerPageState(tableId: number): TimerPageLogics { [prosConsSelected, switchCamp, timer1, timer2], ); - /** - * 전체 화면 상태 변경을 감지 - */ - useEffect(() => { - const handleFullscreenChange = () => { - const doc = document as DocumentWithFullscreen; - setIsFullscreen( - !!( - doc.fullscreenElement || - doc.webkitFullscreenElement || - doc.mozFullScreenElement || - doc.msFullscreenElement - ), - ); - }; - - document.addEventListener('fullscreenchange', handleFullscreenChange); - document.addEventListener('webkitfullscreenchange', handleFullscreenChange); - document.addEventListener('mozfullscreenchange', handleFullscreenChange); - document.addEventListener('MSFullscreenChange', handleFullscreenChange); - - return () => { - document.removeEventListener('fullscreenchange', handleFullscreenChange); - document.removeEventListener( - 'webkitfullscreenchange', - handleFullscreenChange, - ); - document.removeEventListener( - 'mozfullscreenchange', - handleFullscreenChange, - ); - document.removeEventListener( - 'MSFullscreenChange', - handleFullscreenChange, - ); - }; - }, []); - /** * 라운드 이동/초기 진입 시 타이머 상태 초기화 및 셋업 */ @@ -351,6 +261,7 @@ export function useTimerPageState(tableId: number): TimerPageLogics { refetch, isFullscreen, toggleFullscreen, + setFullscreen, }; } @@ -375,4 +286,5 @@ export interface TimerPageLogics { refetch: () => void; isFullscreen: boolean; toggleFullscreen: () => void; + setFullscreen: (value: boolean) => void; } From 8a52ffa2ea1c87fb4268cb20be5fee3d44abb53d Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 4 Oct 2025 20:05:59 +0900 Subject: [PATCH 25/30] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/GoToHomeButton/GoToHomeButton.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/GoToHomeButton/GoToHomeButton.tsx b/src/components/GoToHomeButton/GoToHomeButton.tsx index 1e339bb3..fad1edee 100644 --- a/src/components/GoToHomeButton/GoToHomeButton.tsx +++ b/src/components/GoToHomeButton/GoToHomeButton.tsx @@ -7,7 +7,6 @@ export default function GoToHomeButton() { navigate('/'); }; - // "flex h-[72px] w-[492px] items-center justify-center gap-[12px] rounded-full border-[2px] border-default-disabled/hover bg-default-white px-[16px] py-[11px] font-semibold text-default-black opacity-80 transition-colors duration-200 hover:bg-default-disabled/hover" return ( ); } From a87031e59de7d71ebd6c71464a6dc9d9d22a5536 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 4 Oct 2025 20:14:58 +0900 Subject: [PATCH 27/30] =?UTF-8?q?feat:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=EB=A8=B8=EA=B0=80=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=EC=9D=B4=20=EC=95=84=EB=8B=88=EB=9D=BC=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=20=EC=8B=9C=EA=B0=84=20=EA=B8=B0=EC=A4=80?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9E=AC=EC=A1=B0=EC=A0=95=EB=90=98?= =?UTF-8?q?=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/hooks/useFeedbackTimer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/page/TimerPage/hooks/useFeedbackTimer.ts b/src/page/TimerPage/hooks/useFeedbackTimer.ts index 3073ed56..1e664193 100644 --- a/src/page/TimerPage/hooks/useFeedbackTimer.ts +++ b/src/page/TimerPage/hooks/useFeedbackTimer.ts @@ -88,12 +88,12 @@ export function useFeedbackTimer(): FeedbackTimerLogics { let newTime: number; - setDefaultTimer((prevDefault) => { - newTime = prevDefault + amount; + setTimer((prevTimer) => { + newTime = prevTimer === null ? 0 : prevTimer + amount; return newTime < 0 ? 0 : newTime; }); - setTimer(() => { + setDefaultTimer(() => { return newTime < 0 ? 0 : newTime; }); }, From c38d77655be6c46ce3c82653b79630fd3a8ef9b8 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Sat, 4 Oct 2025 20:24:37 +0900 Subject: [PATCH 28/30] =?UTF-8?q?fix:=20`timer`=20=EA=B0=92=EC=9D=B4=20nul?= =?UTF-8?q?l=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=EC=9D=98=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TimerPage/hooks/useFeedbackTimer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page/TimerPage/hooks/useFeedbackTimer.ts b/src/page/TimerPage/hooks/useFeedbackTimer.ts index 1e664193..d3df0cc3 100644 --- a/src/page/TimerPage/hooks/useFeedbackTimer.ts +++ b/src/page/TimerPage/hooks/useFeedbackTimer.ts @@ -89,7 +89,7 @@ export function useFeedbackTimer(): FeedbackTimerLogics { let newTime: number; setTimer((prevTimer) => { - newTime = prevTimer === null ? 0 : prevTimer + amount; + newTime = (prevTimer ?? 0) + amount; return newTime < 0 ? 0 : newTime; }); From 3c8d60c2a87f09db9e4074b122e86c94e3308ec0 Mon Sep 17 00:00:00 2001 From: Shawn Kang Date: Fri, 10 Oct 2025 16:08:35 +0900 Subject: [PATCH 29/30] Revert "Merge branch 'develop' into fix/#369" This reverts commit 039399109914ecf23bce8875d4ab65fe2217a9d7, reversing changes made to c38d77655be6c46ce3c82653b79630fd3a8ef9b8. --- src/components/icons/Help.tsx | 12 +- src/components/icons/Home.tsx | 8 +- src/components/icons/Login.tsx | 20 ++-- src/hooks/useFullscreen.ts | 105 ------------------ .../header/StickyTriSectionHeader.tsx | 14 +-- src/page/TimerPage/TimerPage.tsx | 34 +----- .../TimerPage/components/FirstUseToolTip.tsx | 21 ---- .../TimerPage/components/TimeBasedTimer.tsx | 56 ++++------ src/page/TimerPage/components/TimerView.tsx | 4 - src/page/TimerPage/hooks/useTimeBasedTimer.ts | 103 +++++------------ src/page/TimerPage/hooks/useTimerHotkey.ts | 24 ++-- src/page/TimerPage/hooks/useTimerPageState.ts | 9 -- .../stories/TimeBasedTimer.stories.tsx | 1 - src/type/fullscreen.d.ts | 17 --- 14 files changed, 80 insertions(+), 348 deletions(-) delete mode 100644 src/hooks/useFullscreen.ts delete mode 100644 src/type/fullscreen.d.ts diff --git a/src/components/icons/Help.tsx b/src/components/icons/Help.tsx index 2be059da..b90e133e 100644 --- a/src/components/icons/Help.tsx +++ b/src/components/icons/Help.tsx @@ -7,26 +7,24 @@ export default function DTHelp({ }: IconProps) { return ( ); diff --git a/src/components/icons/Home.tsx b/src/components/icons/Home.tsx index 0ecfd16b..746206a7 100644 --- a/src/components/icons/Home.tsx +++ b/src/components/icons/Home.tsx @@ -7,19 +7,19 @@ export default function DTHome({ }: IconProps) { return ( diff --git a/src/components/icons/Login.tsx b/src/components/icons/Login.tsx index 73444881..a0736687 100644 --- a/src/components/icons/Login.tsx +++ b/src/components/icons/Login.tsx @@ -7,40 +7,40 @@ export default function DTLogin({ }: IconProps) { return ( diff --git a/src/hooks/useFullscreen.ts b/src/hooks/useFullscreen.ts deleted file mode 100644 index 958ed1c6..00000000 --- a/src/hooks/useFullscreen.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { useCallback, useLayoutEffect, useState } from 'react'; -import { - DocumentWithFullscreen, - HTMLElementWithFullscreen, -} from '../type/fullscreen'; - -// 헬퍼 함수: 현재 전체 화면 요소가 무엇인지 반환 (없으면 null) -const getFullscreenElement = (): Element | null => { - const doc = document as DocumentWithFullscreen; - return ( - doc.fullscreenElement || - doc.webkitFullscreenElement || - doc.mozFullScreenElement || - doc.msFullscreenElement || - null - ); -}; - -// 헬퍼 함수: 전체 화면 진입 -const enterFullscreen = async (element: HTMLElementWithFullscreen) => { - try { - if (element.requestFullscreen) { - await element.requestFullscreen(); - } else if (element.webkitRequestFullscreen) { - await element.webkitRequestFullscreen(); // Safari - } else if (element.mozRequestFullScreen) { - await element.mozRequestFullScreen(); // Firefox - } else if (element.msRequestFullscreen) { - await element.msRequestFullscreen(); // IE11 - } - } catch (error) { - console.error('# Failed to enter fullscreen mode:', error); - } -}; - -// 헬퍼 함수: 전체 화면 해제 -const exitFullscreen = async () => { - const doc = document as DocumentWithFullscreen; - try { - if (doc.exitFullscreen) { - await doc.exitFullscreen(); - } else if (doc.webkitExitFullscreen) { - await doc.webkitExitFullscreen(); // Safari - } else if (doc.mozCancelFullScreen) { - await doc.mozCancelFullScreen(); // Firefox - } else if (doc.msExitFullscreen) { - await doc.msExitFullscreen(); // IE11 - } - } catch (error) { - console.error('# Failed to exit fullscreen mode:', error); - } -}; - -export default function useFullscreen() { - // 전체 화면 여부를 묘사하는 변수 - const [isFullscreen, setIsFullscreen] = useState(!!getFullscreenElement()); - const handleFullscreenChange = useCallback(() => { - setIsFullscreen(!!getFullscreenElement()); - }, []); - - // 이벤트 리스너 등록 - useLayoutEffect(() => { - const EVENTS = [ - 'fullscreenchange', - 'webkitfullscreenchange', - 'mozfullscreenchange', - 'MSFullscreenChange', - ]; - - EVENTS.forEach((event) => { - document.addEventListener(event, handleFullscreenChange); - }); - - return () => { - EVENTS.forEach((event) => { - document.removeEventListener(event, handleFullscreenChange); - }); - }; - }, [handleFullscreenChange]); - - // 토글 함수 - const toggleFullscreen = useCallback(async () => { - const element = document.documentElement as HTMLElementWithFullscreen; - - if (isFullscreen) { - await exitFullscreen(); - } else { - await enterFullscreen(element); - } - }, [isFullscreen]); - - // 값을 직접 입력하는 함수 - const setFullscreen = useCallback(async (value: boolean) => { - const element = document.documentElement as HTMLElementWithFullscreen; - const isCurrentlyFullscreen = !!getFullscreenElement(); - - if (value && !isCurrentlyFullscreen) { - await enterFullscreen(element); - } else if (!value && isCurrentlyFullscreen) { - await exitFullscreen(); - } - }, []); - - return { isFullscreen, toggleFullscreen, setFullscreen }; -} diff --git a/src/layout/components/header/StickyTriSectionHeader.tsx b/src/layout/components/header/StickyTriSectionHeader.tsx index 56d6d060..a5cff81d 100644 --- a/src/layout/components/header/StickyTriSectionHeader.tsx +++ b/src/layout/components/header/StickyTriSectionHeader.tsx @@ -11,7 +11,6 @@ import { useModal } from '../../../hooks/useModal'; import DialogModal from '../../../components/DialogModal/DialogModal'; import DTHome from '../../../components/icons/Home'; import DTLogin from '../../../components/icons/Login'; -import useFullscreen from '../../../hooks/useFullscreen'; // The type of header icons will be declared here. type HeaderIcons = 'home' | 'auth'; @@ -51,7 +50,6 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { const navigate = useNavigate(); const { mutate: logoutMutate } = useLogout(() => navigate('/home')); const { openModal, closeModal, ModalWrapper } = useModal({}); - const { isFullscreen, setFullscreen } = useFullscreen(); const defaultIcons: HeaderIcons[] = ['home', 'auth']; const handleLoginStart = (keepData: boolean) => { @@ -66,7 +64,7 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { {isGuestFlow() && ( <> {/* Guest mode indicator */} -
+
비회원 모드
@@ -89,11 +87,6 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { title="홈으로 이동" key={`${iconName}-${index}`} onClick={() => { - // 전체 화면 상태에서 홈으로 이동하는 경우, 전체 화면 비활성화 - if (isFullscreen) { - setFullscreen(false); - } - if (isGuestFlow()) { deleteSessionCustomizeTableData(); } @@ -111,11 +104,6 @@ StickyTriSectionHeader.Right = function Right(props: PropsWithChildren) { title={isLoggedIn() ? '로그아웃' : '로그인'} key={`${iconName}-${index}`} onClick={() => { - // 전체 화면 상태에서 홈으로 이동하는 경우, 전체 화면 비활성화 - if (isFullscreen) { - setFullscreen(false); - } - if (isLoggedIn()) { logoutMutate(); } else { diff --git a/src/page/TimerPage/TimerPage.tsx b/src/page/TimerPage/TimerPage.tsx index c6676b58..8646653b 100644 --- a/src/page/TimerPage/TimerPage.tsx +++ b/src/page/TimerPage/TimerPage.tsx @@ -14,7 +14,6 @@ import DTHelp from '../../components/icons/Help'; import clsx from 'clsx'; import ErrorIndicator from '../../components/ErrorIndicator/ErrorIndicator'; import LoadingIndicator from '../../components/LoadingIndicator/LoadingIndicator'; -import { RiFullscreenFill, RiFullscreenExitFill } from 'react-icons/ri'; export default function TimerPage() { const pathParams = useParams(); @@ -31,18 +30,7 @@ export default function TimerPage() { const state = useTimerPageState(tableId); useTimerHotkey(state); - const { - data, - bg, - index, - goToOtherItem, - isLoading, - isError, - refetch, - isFullscreen, - setFullscreen, - toggleFullscreen, - } = state; + const { data, bg, index, goToOtherItem, isLoading, isError, refetch } = state; // If error, print error message and let user be able to retry if (isError) { @@ -91,17 +79,6 @@ export default function TimerPage() { > - @@ -123,14 +100,7 @@ export default function TimerPage() { table={data.table} index={index} goToOtherItem={goToOtherItem} - openDoneModal={() => { - // 전체 화면 상태에서 토론을 끝낼 경우, 전체 화면을 비활성화 - if (isFullscreen) { - setFullscreen(false); - } - - openLoginAndStoreModalOrGoToDebateEndPage(); - }} + openDoneModal={openLoginAndStoreModalOrGoToDebateEndPage} className="absolute bottom-[66px] left-1/2 -translate-x-1/2" /> )} diff --git a/src/page/TimerPage/components/FirstUseToolTip.tsx b/src/page/TimerPage/components/FirstUseToolTip.tsx index 98d5c3ba..ea3ded13 100644 --- a/src/page/TimerPage/components/FirstUseToolTip.tsx +++ b/src/page/TimerPage/components/FirstUseToolTip.tsx @@ -1,7 +1,6 @@ import { PropsWithChildren } from 'react'; import { LuKeyboard } from 'react-icons/lu'; import { MdOutlineTimer } from 'react-icons/md'; -import { RiFullscreenExitFill, RiFullscreenFill } from 'react-icons/ri'; // z-index // - 30: Tooltip @@ -69,26 +68,6 @@ export default function FirstUseToolTip({ onClose }: FirstUseToolTipProps) {
-
-
- -

전체 화면

-
- -
- - 화면 우측 상단 헤더의 전체 화면 버튼 - - 으로 활성화 - - - 화면 우측 상단 헤더의 전체 화면 닫기 버튼 - - 또는 ESC 키를 눌러 전체 화면 비활성화 - -
-
-
); default: diff --git a/src/page/TimerPage/TimerPage.tsx b/src/page/TimerPage/TimerPage.tsx index c6676b58..86fe87f2 100644 --- a/src/page/TimerPage/TimerPage.tsx +++ b/src/page/TimerPage/TimerPage.tsx @@ -84,13 +84,14 @@ export default function TimerPage() { +