diff --git a/app/action/start.go b/app/action/start.go index 328e9ec..d03a2e6 100644 --- a/app/action/start.go +++ b/app/action/start.go @@ -237,12 +237,18 @@ func mustStartYJSServer() int { // prepare arguments internalPort := mustFindFreePort() - // execute the binary in a new process - cmd := exec.Command(bin.Name()) - cmd.Env = []string{ + // set envs + envs := []string{ fmt.Sprintf("PORT=%d", internalPort), fmt.Sprintf("DATABASE_PATH=%s", databasePath()), } + if StartOption.Readonly { + envs = append(envs, "READ_ONLY=true") + } + + // execute the binary in a new process + cmd := exec.Command(bin.Name()) + cmd.Env = envs zap.L().Info("start yjs-server server", zap.Int("port", internalPort)) cmd.Stderr = os.Stderr diff --git a/app/frontend/src/page/annotate/Panel/Load.tsx b/app/frontend/src/page/annotate/Panel/Load.tsx index cd4db08..89c2d0a 100644 --- a/app/frontend/src/page/annotate/Panel/Load.tsx +++ b/app/frontend/src/page/annotate/Panel/Load.tsx @@ -8,7 +8,7 @@ import {NutshClientContext} from 'common/context'; import PageLayout from 'page/Layout'; import type {Video} from 'openapi/nutsh'; import {PanelLoadProject} from './LoadProject'; -import {useJoinYjs} from '@@frontend/state/server/annotation'; +import {useAnnotationSync} from '@@frontend/state/server/annotation'; export const PanelLoad: FC<{id: Video['id']}> = ({id}) => { const client = useContext(NutshClientContext); @@ -16,13 +16,18 @@ export const PanelLoad: FC<{id: Video['id']}> = ({id}) => { // client state const isLoaded = useRenderStore(s => s.sliceUrls.length > 0); const startAnnotation = useRenderStore(s => s.startAnnotation); - const setAnnotation = useAnnoStore(s => s.setAnnotation); // server state const {isFetching: isFetchingVideo, data: videoData} = useGetVideo(client, id); - // yjs - useJoinYjs(id); + // sync + const {initial} = useAnnotationSync(id); + const setAnnotation = useAnnoStore(s => s.setAnnotation); + useEffect(() => { + if (initial) { + setAnnotation(initial); + } + }, [initial, setAnnotation]); // local state const [errorCode, setErrorCode] = useState(undefined); @@ -38,15 +43,17 @@ export const PanelLoad: FC<{id: Video['id']}> = ({id}) => { } startAnnotation(frameUrls, ''); - }, [videoData, setAnnotation, startAnnotation]); + }, [videoData, startAnnotation]); - if (!isLoaded || !videoData) { + if (!isLoaded || !videoData || initial === undefined || errorCode) { return ( - + {errorCode && } ); } + // Only AFTER the annotation is initialized should we render the panel, otherwise its yjs update listener will respond + // to the initialization, causing the page to re-render frequently and impossible to load heavy annotations. return ; }; diff --git a/app/frontend/src/page/project/Detail.tsx b/app/frontend/src/page/project/Detail.tsx index 0b8cc95..5483cf4 100644 --- a/app/frontend/src/page/project/Detail.tsx +++ b/app/frontend/src/page/project/Detail.tsx @@ -97,6 +97,7 @@ const DetailReady: FC<{project: Project; spec: ProjectSpec}> = ({project, spec}) />, config.readonly ? (