Yuki Takei пре 3 година
родитељ
комит
d2b7996d58

+ 0 - 31
packages/app/src/components/Page/PageContents.tsx

@@ -1,31 +0,0 @@
-import React from 'react';
-
-import dynamic from 'next/dynamic';
-
-import { useSWRxCurrentPage } from '~/stores/page';
-import { useViewOptions } from '~/stores/renderer';
-import loggerFactory from '~/utils/logger';
-
-import RevisionRenderer from './RevisionRenderer';
-
-
-const logger = loggerFactory('growi:cli:PageContents');
-
-
-const PageContentsUtilities = dynamic(() => import('./PageContentsUtilities').then(mod => mod.PageContentsUtilities), { ssr: false });
-
-export const PageContents = (): JSX.Element => {
-
-  const { data: currentPage } = useSWRxCurrentPage();
-  const { data: rendererOptions } = useViewOptions();
-
-  const markdown = currentPage?.revision.body;
-
-  return (
-    <>
-      <PageContentsUtilities />
-      <RevisionRenderer rendererOptions={rendererOptions} markdown={markdown} />
-    </>
-  );
-
-};

+ 33 - 30
packages/app/src/components/Page/PageView.tsx

@@ -3,11 +3,12 @@ import React, { useEffect, useMemo } from 'react';
 import { type IPagePopulatedToShowRevision, pagePathUtils } from '@growi/core';
 import { type IPagePopulatedToShowRevision, pagePathUtils } from '@growi/core';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
-
+import type { RendererConfig } from '~/interfaces/services/renderer';
 import { generateSSRViewOptions } from '~/services/renderer/renderer';
 import { generateSSRViewOptions } from '~/services/renderer/renderer';
 import {
 import {
   useIsForbidden, useIsIdenticalPath, useIsNotCreatable, useIsNotFound,
   useIsForbidden, useIsIdenticalPath, useIsNotCreatable, useIsNotFound,
 } from '~/stores/context';
 } from '~/stores/context';
+import { useSWRxCurrentPage } from '~/stores/page';
 import { useViewOptions } from '~/stores/renderer';
 import { useViewOptions } from '~/stores/renderer';
 import { useIsMobile } from '~/stores/ui';
 import { useIsMobile } from '~/stores/ui';
 import { registerGrowiFacade } from '~/utils/growi-facade';
 import { registerGrowiFacade } from '~/utils/growi-facade';
@@ -20,7 +21,7 @@ import type { PageSideContentsProps } from '../PageSideContents';
 import { UserInfo } from '../User/UserInfo';
 import { UserInfo } from '../User/UserInfo';
 import type { UsersHomePageFooterProps } from '../UsersHomePageFooter';
 import type { UsersHomePageFooterProps } from '../UsersHomePageFooter';
 
 
-import { PageContents } from './PageContents';
+import RevisionRenderer from './RevisionRenderer';
 
 
 import styles from './PageView.module.scss';
 import styles from './PageView.module.scss';
 
 
@@ -32,6 +33,7 @@ const NotCreatablePage = dynamic(() => import('../NotCreatablePage').then(mod =>
 const ForbiddenPage = dynamic(() => import('../ForbiddenPage'), { ssr: false });
 const ForbiddenPage = dynamic(() => import('../ForbiddenPage'), { ssr: false });
 const NotFoundPage = dynamic(() => import('../NotFoundPage'), { ssr: false });
 const NotFoundPage = dynamic(() => import('../NotFoundPage'), { ssr: false });
 const PageSideContents = dynamic<PageSideContentsProps>(() => import('../PageSideContents').then(mod => mod.PageSideContents), { ssr: false });
 const PageSideContents = dynamic<PageSideContentsProps>(() => import('../PageSideContents').then(mod => mod.PageSideContents), { ssr: false });
+const PageContentsUtilities = dynamic(() => import('./PageContentsUtilities').then(mod => mod.PageContentsUtilities), { ssr: false });
 const Comments = dynamic<CommentsProps>(() => import('../Comments').then(mod => mod.Comments), { ssr: false });
 const Comments = dynamic<CommentsProps>(() => import('../Comments').then(mod => mod.Comments), { ssr: false });
 const UsersHomePageFooter = dynamic<UsersHomePageFooterProps>(() => import('../UsersHomePageFooter')
 const UsersHomePageFooter = dynamic<UsersHomePageFooterProps>(() => import('../UsersHomePageFooter')
   .then(mod => mod.UsersHomePageFooter), { ssr: false });
   .then(mod => mod.UsersHomePageFooter), { ssr: false });
@@ -40,23 +42,27 @@ const IdenticalPathPage = dynamic(() => import('../IdenticalPathPage').then(mod
 
 
 type Props = {
 type Props = {
   pagePath: string,
   pagePath: string,
-  page?: IPagePopulatedToShowRevision,
+  rendererConfig: RendererConfig,
+  initialPage?: IPagePopulatedToShowRevision,
 }
 }
 
 
 export const PageView = (props: Props): JSX.Element => {
 export const PageView = (props: Props): JSX.Element => {
   const {
   const {
-    pagePath, page,
+    pagePath, initialPage, rendererConfig,
   } = props;
   } = props;
 
 
-  const pageId = page?._id;
-
   const { data: isIdenticalPathPage } = useIsIdenticalPath();
   const { data: isIdenticalPathPage } = useIsIdenticalPath();
   const { data: isForbidden } = useIsForbidden();
   const { data: isForbidden } = useIsForbidden();
   const { data: isNotCreatable } = useIsNotCreatable();
   const { data: isNotCreatable } = useIsNotCreatable();
-  const { data: isNotFound } = useIsNotFound();
+  const { data: isNotFoundMeta } = useIsNotFound();
   const { data: isMobile } = useIsMobile();
   const { data: isMobile } = useIsMobile();
 
 
-  const { mutate: mutateRendererOptions } = useViewOptions();
+  const { data: pageBySWR } = useSWRxCurrentPage();
+  const { data: viewOptions, mutate: mutateRendererOptions } = useViewOptions();
+
+  const page = pageBySWR ?? initialPage;
+  const isNotFound = isNotFoundMeta || page == null;
+  const isUsersHomePagePath = isUsersHomePage(pagePath);
 
 
   // register to facade
   // register to facade
   useEffect(() => {
   useEffect(() => {
@@ -79,10 +85,7 @@ export const PageView = (props: Props): JSX.Element => {
     if (isNotCreatable) {
     if (isNotCreatable) {
       return <NotCreatablePage />;
       return <NotCreatablePage />;
     }
     }
-    if (isNotFound) {
-      return <NotFoundPage path={pagePath} />;
-    }
-  }, [isForbidden, isIdenticalPathPage, isNotCreatable, isNotFound, pagePath]);
+  }, [isForbidden, isIdenticalPathPage, isNotCreatable]);
 
 
   const sideContents = !isNotFound && !isNotCreatable
   const sideContents = !isNotFound && !isNotCreatable
     ? (
     ? (
@@ -90,13 +93,11 @@ export const PageView = (props: Props): JSX.Element => {
     )
     )
     : null;
     : null;
 
 
-  const footerContents = !isIdenticalPathPage && !isNotFound && page != null
+  const footerContents = !isIdenticalPathPage && !isNotFound
     ? (
     ? (
       <>
       <>
-        { pageId != null && pagePath != null && (
-          <Comments pageId={pageId} pagePath={pagePath} revision={page.revision} />
-        ) }
-        { pagePath != null && isUsersHomePage(pagePath) && (
+        <Comments pageId={page._id} pagePath={pagePath} revision={page.revision} />
+        { isUsersHomePagePath && (
           <UsersHomePageFooter creatorId={page.creator._id}/>
           <UsersHomePageFooter creatorId={page.creator._id}/>
         ) }
         ) }
         <PageContentFooter page={page} />
         <PageContentFooter page={page} />
@@ -104,19 +105,21 @@ export const PageView = (props: Props): JSX.Element => {
     )
     )
     : null;
     : null;
 
 
-  const isUsersHomePagePath = isUsersHomePage(pagePath);
+  const Contents = () => {
+    if (isNotFound) {
+      return <NotFoundPage path={pagePath} />;
+    }
 
 
-  const contents = specialContents != null
-    ? <></>
-    // TODO: show SSR body
-    // : (() => {
-    //   const PageContents = dynamic(() => import('./PageContents').then(mod => mod.PageContents), {
-    //     ssr: false,
-    //     // loading: () => ssrBody ?? <></>,
-    //   });
-    //   return <PageContents />;
-    // })();
-    : <PageContents />;
+    const rendererOptions = viewOptions ?? generateSSRViewOptions(rendererConfig, pagePath);
+    const markdown = page.revision.body;
+
+    return (
+      <>
+        <PageContentsUtilities />
+        <RevisionRenderer rendererOptions={rendererOptions} markdown={markdown} />;
+      </>
+    );
+  };
 
 
   return (
   return (
     <MainPane
     <MainPane
@@ -130,7 +133,7 @@ export const PageView = (props: Props): JSX.Element => {
         <>
         <>
           { isUsersHomePagePath && <UserInfo author={page?.creator} /> }
           { isUsersHomePagePath && <UserInfo author={page?.creator} /> }
           <div className={`mb-5 ${isMobile ? `page-mobile ${styles['page-mobile']}` : ''}`}>
           <div className={`mb-5 ${isMobile ? `page-mobile ${styles['page-mobile']}` : ''}`}>
-            { contents }
+            <Contents />
           </div>
           </div>
         </>
         </>
       ) }
       ) }

+ 6 - 8
packages/app/src/components/PageSideContents.tsx

@@ -5,7 +5,6 @@ import { useTranslation } from 'next-i18next';
 import { Link } from 'react-scroll';
 import { Link } from 'react-scroll';
 
 
 import { DEFAULT_AUTO_SCROLL_OPTS } from '~/client/util/smooth-scroll';
 import { DEFAULT_AUTO_SCROLL_OPTS } from '~/client/util/smooth-scroll';
-import { useCurrentPathname } from '~/stores/context';
 import { useDescendantsPageListModal } from '~/stores/modal';
 import { useDescendantsPageListModal } from '~/stores/modal';
 
 
 import CountBadge from './Common/CountBadge';
 import CountBadge from './Common/CountBadge';
@@ -20,27 +19,26 @@ const { isTopPage, isUsersHomePage } = pagePathUtils;
 
 
 
 
 export type PageSideContentsProps = {
 export type PageSideContentsProps = {
-  page?: IPageHasId,
+  page: IPageHasId,
   isSharedUser?: boolean,
   isSharedUser?: boolean,
 }
 }
 
 
 export const PageSideContents = (props: PageSideContentsProps): JSX.Element => {
 export const PageSideContents = (props: PageSideContentsProps): JSX.Element => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
-  const { data: currentPathname } = useCurrentPathname();
   const { open: openDescendantPageListModal } = useDescendantsPageListModal();
   const { open: openDescendantPageListModal } = useDescendantsPageListModal();
 
 
   const { page, isSharedUser } = props;
   const { page, isSharedUser } = props;
 
 
-  const pagePath = page?.path ?? currentPathname;
-  const isTopPagePath = isTopPage(pagePath ?? '');
-  const isUsersHomePagePath = isUsersHomePage(pagePath ?? '');
+  const pagePath = page.path;
+  const isTopPagePath = isTopPage(pagePath);
+  const isUsersHomePagePath = isUsersHomePage(pagePath);
 
 
   return (
   return (
     <>
     <>
       {/* Page list */}
       {/* Page list */}
       <div className={`grw-page-accessories-control ${styles['grw-page-accessories-control']}`}>
       <div className={`grw-page-accessories-control ${styles['grw-page-accessories-control']}`}>
-        { pagePath != null && !isSharedUser && (
+        { !isSharedUser && (
           <button
           <button
             type="button"
             type="button"
             className="btn btn-block btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
             className="btn btn-block btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
@@ -57,7 +55,7 @@ export const PageSideContents = (props: PageSideContentsProps): JSX.Element => {
       </div>
       </div>
 
 
       {/* Comments */}
       {/* Comments */}
-      { page != null && !isTopPagePath && (
+      { !isTopPagePath && (
         <div className={`mt-2 grw-page-accessories-control ${styles['grw-page-accessories-control']}`}>
         <div className={`mt-2 grw-page-accessories-control ${styles['grw-page-accessories-control']}`}>
           <Link to={'page-comments'} offset={-100} {...DEFAULT_AUTO_SCROLL_OPTS}>
           <Link to={'page-comments'} offset={-100} {...DEFAULT_AUTO_SCROLL_OPTS}>
             <button
             <button

+ 2 - 1
packages/app/src/pages/[[...path]].page.tsx

@@ -319,7 +319,8 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
           pageView={
           pageView={
             <PageView
             <PageView
               pagePath={pagePath}
               pagePath={pagePath}
-              page={pageWithMeta?.data}
+              initialPage={pageWithMeta?.data}
+              rendererConfig={props.rendererConfig}
             />
             />
           }
           }
         />
         />

+ 5 - 0
packages/app/src/stores/renderer.tsx

@@ -50,6 +50,7 @@ export const useViewOptions = (): SWRResponse<RendererOptions, Error> => {
       return optionsGenerator(currentPagePath, rendererConfig, storeTocNodeHandler);
       return optionsGenerator(currentPagePath, rendererConfig, storeTocNodeHandler);
     },
     },
     {
     {
+      keepPreviousData: true,
       fallbackData: isAllDataValid ? generateViewOptions(currentPagePath, rendererConfig, storeTocNodeHandler) : undefined,
       fallbackData: isAllDataValid ? generateViewOptions(currentPagePath, rendererConfig, storeTocNodeHandler) : undefined,
     },
     },
   );
   );
@@ -68,6 +69,7 @@ export const useTocOptions = (): SWRResponse<RendererOptions, Error> => {
       : null,
       : null,
     ([, , tocNode, rendererConfig]) => generateTocOptions(rendererConfig, tocNode),
     ([, , tocNode, rendererConfig]) => generateTocOptions(rendererConfig, tocNode),
     {
     {
+      keepPreviousData: true,
       fallbackData: isAllDataValid ? generateTocOptions(rendererConfig, tocNode) : undefined,
       fallbackData: isAllDataValid ? generateTocOptions(rendererConfig, tocNode) : undefined,
     },
     },
   );
   );
@@ -89,6 +91,7 @@ export const usePreviewOptions = (): SWRResponse<RendererOptions, Error> => {
       return optionsGenerator(rendererConfig, pagePath);
       return optionsGenerator(rendererConfig, pagePath);
     },
     },
     {
     {
+      keepPreviousData: true,
       fallbackData: isAllDataValid ? generatePreviewOptions(rendererConfig, currentPagePath) : undefined,
       fallbackData: isAllDataValid ? generatePreviewOptions(rendererConfig, currentPagePath) : undefined,
     },
     },
   );
   );
@@ -111,6 +114,7 @@ export const useCommentForCurrentPageOptions = (): SWRResponse<RendererOptions,
       rendererConfig.isEnabledLinebreaksInComments,
       rendererConfig.isEnabledLinebreaksInComments,
     ),
     ),
     {
     {
+      keepPreviousData: true,
       fallbackData: isAllDataValid ? generateSimpleViewOptions(
       fallbackData: isAllDataValid ? generateSimpleViewOptions(
         rendererConfig,
         rendererConfig,
         currentPagePath,
         currentPagePath,
@@ -152,6 +156,7 @@ export const useCustomSidebarOptions = (): SWRResponse<RendererOptions, Error> =
       : null,
       : null,
     ([, rendererConfig]) => generateSimpleViewOptions(rendererConfig, '/'),
     ([, rendererConfig]) => generateSimpleViewOptions(rendererConfig, '/'),
     {
     {
+      keepPreviousData: true,
       fallbackData: isAllDataValid ? generateSimpleViewOptions(rendererConfig, '/') : undefined,
       fallbackData: isAllDataValid ? generateSimpleViewOptions(rendererConfig, '/') : undefined,
     },
     },
   );
   );