77 * - ScriptBox 접힘 상태를 관리하고 SlideViewer에 전달
88 * - Zustand store로 슬라이드 상태 관리
99 */
10- import { useEffect , useRef , useState } from 'react' ;
10+ import { useEffect , useMemo , useRef , useState } from 'react' ;
1111
1212import { SLIDE_MAX_WIDTH } from '@/constants/layout' ;
1313import { useSlideActions , useSlideId , useSlideScript } from '@/hooks' ;
14- import { useScript } from '@/hooks/queries/useScript' ;
14+ import { useProjectScripts , useScript } from '@/hooks/queries/useScript' ;
1515import { useSlideCommentsLoader } from '@/hooks/useSlideCommentsLoader' ;
1616import type { SlideListItem } from '@/types/slide' ;
1717
@@ -28,24 +28,42 @@ export default function SlideWorkspace({ slide, isLoading }: SlideWorkspaceProps
2828 const { initSlide, updateScript, updateSlide } = useSlideActions ( ) ;
2929 const slideId = useSlideId ( ) ;
3030 const script = useSlideScript ( ) ;
31- const { data : scriptData } = useScript ( slideId ) ;
3231 const lastSyncedSlideIdRef = useRef < string > ( '' ) ;
3332 const lastSyncedScriptRef = useRef < string | null > ( null ) ;
3433
34+ const projectId = slide ?. projectId ?? '' ;
35+ const currentSlideId = slide ?. slideId ?? '' ;
36+ const { data : projectScripts } = useProjectScripts ( projectId , {
37+ enabled : ! ! projectId ,
38+ staleTime : 1000 * 60 * 10 ,
39+ } ) ;
40+
41+ const projectScript = useMemo ( ( ) => {
42+ if ( ! currentSlideId ) return undefined ;
43+ return projectScripts ?. scripts . find ( ( item ) => item . slideId === currentSlideId ) ?. scriptText ;
44+ } , [ projectScripts , currentSlideId ] ) ;
45+
46+ const shouldFetchDetailScript = ! projectScript && ! slide ?. script ;
47+ const { data : scriptData } = useScript ( currentSlideId , {
48+ enabled : shouldFetchDetailScript ,
49+ staleTime : 1000 * 60 * 10 ,
50+ } ) ;
51+
52+ const resolvedServerScript = projectScript ?? slide ?. script ?? scriptData ?. scriptText ?? '' ;
53+
3554 useEffect ( ( ) => {
3655 if ( ! slide ) return ;
56+ const nextSlide =
57+ resolvedServerScript !== slide . script ? { ...slide , script : resolvedServerScript } : slide ;
3758
3859 const isSameSlide = slide . slideId === slideId ;
3960 if ( isSameSlide ) {
40- updateSlide ( slide ) ;
61+ updateSlide ( nextSlide ) ;
4162 return ;
4263 }
4364
44- initSlide ( slide ) ;
45- updateScript ( '' ) ;
46- } , [ slide , slideId , initSlide , updateScript , updateSlide ] ) ;
47-
48- useSlideCommentsLoader ( slide ?. slideId ) ;
65+ initSlide ( nextSlide ) ;
66+ } , [ slide , slideId , initSlide , resolvedServerScript , updateSlide ] ) ;
4967
5068 useEffect ( ( ) => {
5169 if ( lastSyncedSlideIdRef . current !== slideId ) {
@@ -55,21 +73,23 @@ export default function SlideWorkspace({ slide, isLoading }: SlideWorkspaceProps
5573 } , [ slideId ] ) ;
5674
5775 useEffect ( ( ) => {
58- if ( ! scriptData ) return ;
76+ if ( ! slideId ) return ;
5977
60- const serverScript = scriptData . scriptText ;
78+ const serverScript = resolvedServerScript ;
6179 const hasSyncedOnce = lastSyncedScriptRef . current !== null ;
6280 const hasLocalEditAfterSync = hasSyncedOnce && script !== lastSyncedScriptRef . current ;
6381
64- // 로컬 편집이 있는 동안에는 서버 응답으로 덮어쓰지 않습니다.
82+ // 로컬 편집 중에는 서버 값으로 덮어쓰지 않습니다.
6583 if ( hasLocalEditAfterSync && script !== serverScript ) return ;
6684
6785 if ( script !== serverScript ) {
6886 updateScript ( serverScript ) ;
6987 }
7088
7189 lastSyncedScriptRef . current = serverScript ;
72- } , [ script , scriptData , updateScript ] ) ;
90+ } , [ resolvedServerScript , script , slideId , updateScript ] ) ;
91+
92+ useSlideCommentsLoader ( slide ?. slideId ) ;
7393
7494 return (
7595 < div className = "relative h-full min-h-0 flex flex-col pb-[clamp(12rem,30vh,20rem)] md:pb-0" >
0 commit comments