Просмотр исходного кода

Merge pull request #5701 from weseek/support/commonize-browser-detection

support: Commonize browser detection
Yuki Takei 4 лет назад
Родитель
Сommit
60e24768b5

+ 10 - 11
packages/app/src/components/PageList/PageListItemL.tsx

@@ -3,24 +3,18 @@ import React, {
   ForwardRefRenderFunction, memo, useCallback, useImperativeHandle, useRef, useEffect,
 } from 'react';
 
-import { useTranslation } from 'react-i18next';
-import { CustomInput } from 'reactstrap';
 
-import Clamp from 'react-multiline-clamp';
+import { DevidedPagePath } from '@growi/core';
+import { UserPicture, PageListMeta } from '@growi/ui';
 import { format } from 'date-fns';
+import { useTranslation } from 'react-i18next';
+import Clamp from 'react-multiline-clamp';
+import { CustomInput } from 'reactstrap';
 import urljoin from 'url-join';
 
-import { UserPicture, PageListMeta } from '@growi/ui';
-import { DevidedPagePath } from '@growi/core';
-
-import { useSWRxPageInfo } from '../../stores/page';
 
 import { ISelectable } from '~/client/interfaces/selectable-all';
 import { bookmark, unbookmark } from '~/client/services/page-operation';
-import { useIsDeviceSmallerThanLg } from '~/stores/ui';
-import {
-  usePageRenameModal, usePageDuplicateModal, usePageDeleteModal, usePutBackPageModal,
-} from '~/stores/modal';
 import {
   IPageInfoAll, IPageInfoForEntity, IPageInfoForListing, IPageWithMeta, isIPageInfoForListing, isIPageInfoForEntity,
 } from '~/interfaces/page';
@@ -29,7 +23,12 @@ import {
   OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction,
 } from '~/interfaces/ui';
 import LinkedPagePath from '~/models/linked-page-path';
+import {
+  usePageRenameModal, usePageDuplicateModal, usePageDeleteModal, usePutBackPageModal,
+} from '~/stores/modal';
+import { useIsDeviceSmallerThanLg } from '~/stores/ui';
 
+import { useSWRxPageInfo } from '../../stores/page';
 import { ForceHideMenuItems, PageItemControl } from '../Common/Dropdown/PageItemControl';
 import PagePathHierarchicalLink from '../PagePathHierarchicalLink';
 

+ 14 - 16
packages/app/src/stores/ui.tsx

@@ -1,32 +1,30 @@
 import { RefObject } from 'react';
+
+import { isClient, pagePathUtils } from '@growi/core';
+import { Breakpoint, addBreakpointListener } from '@growi/ui';
+import SimpleBar from 'simplebar-react';
 import {
   useSWRConfig, SWRResponse, Key, Fetcher,
 } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
-import SimpleBar from 'simplebar-react';
-
-import { Breakpoint, addBreakpointListener } from '@growi/ui';
-import { pagePathUtils } from '@growi/core';
 
+import { IFocusable } from '~/client/interfaces/focusable';
+import { Nullable } from '~/interfaces/common';
 import { SidebarContentsType } from '~/interfaces/ui';
+import { UpdateDescCountData } from '~/interfaces/websocket';
 import loggerFactory from '~/utils/logger';
 
-import { useStaticSWR } from './use-static-swr';
 import {
   useCurrentPageId, useCurrentPagePath, useIsEditable, useIsTrashPage, useIsUserPage,
   useIsNotCreatable, useIsSharedUser, useNotFoundTargetPathOrId, useIsForbidden, useIsIdenticalPath, useIsNotFoundPermalink,
 } from './context';
-import { IFocusable } from '~/client/interfaces/focusable';
-import { Nullable } from '~/interfaces/common';
-import { UpdateDescCountData } from '~/interfaces/websocket';
+import { useStaticSWR } from './use-static-swr';
 
 const { isSharedPage } = pagePathUtils;
 
 const logger = loggerFactory('growi:stores:ui');
 
-const isServer = typeof window === 'undefined';
-
 
 /** **********************************************************
  *                          Unions
@@ -55,10 +53,10 @@ export const useSidebarScrollerRef = (initialData?: RefObject<SimpleBar>): SWRRe
  *********************************************************** */
 
 export const useIsMobile = (): SWRResponse<boolean, Error> => {
-  const key = isServer ? null : 'isMobile';
+  const key = isClient() ? 'isMobile' : null;
 
   let configuration;
-  if (!isServer) {
+  if (isClient()) {
     const userAgent = window.navigator.userAgent.toLowerCase();
     configuration = {
       fallbackData: /iphone|ipad|android/.test(userAgent),
@@ -166,11 +164,11 @@ export const useEditorMode = (): SWRResponse<EditorMode, Error> => {
 };
 
 export const useIsDeviceSmallerThanMd = (): SWRResponse<boolean, Error> => {
-  const key: Key = isServer ? null : 'isDeviceSmallerThanMd';
+  const key: Key = isClient() ? 'isDeviceSmallerThanMd' : null;
 
   const { cache, mutate } = useSWRConfig();
 
-  if (!isServer) {
+  if (isClient()) {
     const mdOrAvobeHandler = function(this: MediaQueryList): void {
       // sm -> md: matches will be true
       // md -> sm: matches will be false
@@ -190,11 +188,11 @@ export const useIsDeviceSmallerThanMd = (): SWRResponse<boolean, Error> => {
 };
 
 export const useIsDeviceSmallerThanLg = (): SWRResponse<boolean, Error> => {
-  const key: Key = isServer ? null : 'isDeviceSmallerThanLg';
+  const key: Key = isClient() ? 'isDeviceSmallerThanLg' : null;
 
   const { cache, mutate } = useSWRConfig();
 
-  if (!isServer) {
+  if (isClient()) {
     const lgOrAvobeHandler = function(this: MediaQueryList): void {
       // md -> lg: matches will be true
       // lg -> md: matches will be false

+ 3 - 2
packages/app/src/utils/project-dir-utils.ts

@@ -4,8 +4,9 @@ import fs from 'fs';
 import path from 'path';
 import process from 'process';
 
-const isServer = typeof window === 'undefined';
-const isCurrentDirRoot = isServer && fs.existsSync('./next.config.js');
+import { isServer } from '@growi/core';
+
+const isCurrentDirRoot = isServer() && fs.existsSync('./next.config.js');
 
 export const projectRoot = isCurrentDirRoot
   ? process.cwd()

+ 2 - 0
packages/app/test/cypress/integration/3-search/search.spec.ts

@@ -13,6 +13,7 @@ context('Access to search result page', () => {
   it('/_search with "q" param is successfully loaded', () => {
     cy.visit('/_search', { qs: { q: 'labels alerts cards blocks' } });
 
+    cy.getByTestid('search-result-base').should('be.visible');
     cy.getByTestid('search-result-list').should('be.visible');
     cy.getByTestid('search-result-content').should('be.visible');
 
@@ -24,6 +25,7 @@ context('Access to search result page', () => {
 
     cy.getByTestid('search-result-base').should('be.visible');
     cy.getByTestid('search-result-list').should('be.visible');
+    cy.getByTestid('search-result-content').should('be.visible');
 
     cy.getByTestid('cb-select').first().click({force: true});
     cy.screenshot(`${ssPrefix}-the-first-checkbox-on`);

+ 1 - 0
packages/core/src/index.js

@@ -18,4 +18,5 @@ export * from './plugin/service/tag-cache-manager';
 export * from './models/devided-page-path';
 export * from './service/localstorage-manager';
 export * from './utils/basic-interceptor';
+export * from './utils/browser-utils';
 export * from './utils/mongoose-utils';

+ 7 - 0
packages/core/src/utils/browser-utils.ts

@@ -0,0 +1,7 @@
+export const isClient = (): boolean => {
+  return (typeof window !== 'undefined') || (typeof navigator !== 'undefined' && navigator.webdriver);
+};
+
+export const isServer = (): boolean => {
+  return !isClient();
+};