You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by ro...@apache.org on 2024/06/05 08:19:23 UTC

(incubator-answer) 01/01: fix(plugins): Fix the problem that the dom obtained by hooks in the plugin is null

This is an automated email from the ASF dual-hosted git repository.

robin0716 pushed a commit to branch feat/1.3.5/embed
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git

commit bdbff79b61c7addfc24663089df5c3c796949773
Author: robin <ro...@rnode.me>
AuthorDate: Wed Jun 5 16:19:10 2024 +0800

    fix(plugins): Fix the problem that the dom obtained by hooks in the plugin is null
    
    Related issue: https://github.com/apache/incubator-answer-plugins/issues/121
---
 ui/src/components/Editor/index.tsx                 |  3 +-
 ui/src/components/PluginRender/index.tsx           |  2 +-
 .../Questions/Detail/components/Answer/index.tsx   |  3 +-
 ui/src/pages/Search/components/Head/index.tsx      |  3 +-
 ui/src/pages/Users/Login/index.tsx                 | 10 ++---
 ui/src/pages/Users/Register/index.tsx              |  3 +-
 ui/src/utils/pluginKit/index.ts                    | 51 ++++++++++++++--------
 ui/src/utils/pluginKit/interface.ts                | 31 ++++++++++++-
 ui/src/utils/pluginKit/utils.ts                    | 38 ++--------------
 9 files changed, 81 insertions(+), 63 deletions(-)

diff --git a/ui/src/components/Editor/index.tsx b/ui/src/components/Editor/index.tsx
index 8d157a68..dd004021 100644
--- a/ui/src/components/Editor/index.tsx
+++ b/ui/src/components/Editor/index.tsx
@@ -27,6 +27,7 @@ import {
 
 import classNames from 'classnames';
 
+import { PluginType } from '@/utils/pluginKit';
 import PluginRender from '../PluginRender';
 
 import {
@@ -115,7 +116,7 @@ const MDEditor: ForwardRefRenderFunction<EditorRef, Props> = (
         <EditorContext.Provider value={editor}>
           {editor && (
             <PluginRender
-              type="editor"
+              type={PluginType.Editor}
               className="toolbar-wrap px-3 d-flex align-items-center flex-wrap"
               editor={editor}
               previewElement={previewRef.current?.element}>
diff --git a/ui/src/components/PluginRender/index.tsx b/ui/src/components/PluginRender/index.tsx
index 3da9fd0b..9de283f5 100644
--- a/ui/src/components/PluginRender/index.tsx
+++ b/ui/src/components/PluginRender/index.tsx
@@ -33,7 +33,7 @@ import PluginKit, { Plugin, PluginType } from '@/utils/pluginKit';
 
 interface Props {
   slug_name?: string;
-  type?: PluginType;
+  type: PluginType;
   children?: ReactNode;
   [prop: string]: any;
 }
diff --git a/ui/src/pages/Questions/Detail/components/Answer/index.tsx b/ui/src/pages/Questions/Detail/components/Answer/index.tsx
index 474c83d6..fb4de275 100644
--- a/ui/src/pages/Questions/Detail/components/Answer/index.tsx
+++ b/ui/src/pages/Questions/Detail/components/Answer/index.tsx
@@ -59,7 +59,8 @@ const Index: FC<Props> = ({
   });
   const [searchParams] = useSearchParams();
   const answerRef = useRef<HTMLDivElement>(null);
-  useRenderHtmlPlugin(answerRef.current);
+
+  useRenderHtmlPlugin(answerRef);
 
   const acceptAnswer = () => {
     acceptanceAnswer({
diff --git a/ui/src/pages/Search/components/Head/index.tsx b/ui/src/pages/Search/components/Head/index.tsx
index cbb19283..4068b4ba 100644
--- a/ui/src/pages/Search/components/Head/index.tsx
+++ b/ui/src/pages/Search/components/Head/index.tsx
@@ -28,6 +28,7 @@ import { escapeRemove } from '@/utils';
 import { pathFactory } from '@/router/pathFactory';
 import { PluginRender } from '@/components';
 import Pattern from '@/common/pattern';
+import { PluginType } from '@/utils/pluginKit';
 
 interface Props {
   data;
@@ -57,7 +58,7 @@ const Index: FC<Props> = ({ data }) => {
       <div className="mb-3 d-flex align-items-center justify-content-between">
         <h3 className="mb-0">{t('title')}</h3>
 
-        <PluginRender type="search" slug_name="serarch_info" />
+        <PluginRender type={PluginType.Search} slug_name="serarch_info" />
       </div>
       <p>
         <span className="text-secondary me-1">{t('keywords')}</span>
diff --git a/ui/src/pages/Users/Login/index.tsx b/ui/src/pages/Users/Login/index.tsx
index 404bb4ce..9cec9a32 100644
--- a/ui/src/pages/Users/Login/index.tsx
+++ b/ui/src/pages/Users/Login/index.tsx
@@ -37,7 +37,7 @@ import {
   userCenter,
   scrollToElementTop,
 } from '@/utils';
-import { useCaptchaPlugin } from '@/utils/pluginKit';
+import { PluginType, useCaptchaPlugin } from '@/utils/pluginKit';
 import { login, UcAgent } from '@/services';
 import { setupAppTheme } from '@/utils/localize';
 
@@ -188,25 +188,25 @@ const Index: React.FC = () => {
       {step === 1 ? (
         <Col className="mx-auto" md={6} lg={4} xl={3}>
           <PluginRender
-            type="captcha"
+            type={PluginType.Captcha}
             slug_name="captcha_basic"
             className="mb-5"
           />
 
           <PluginRender
-            type="captcha"
+            type={PluginType.Captcha}
             slug_name="captcha_google_v2"
             className="mb-5"
           />
           {ucAgentInfo ? (
             <PluginRender
-              type="connector"
+              type={PluginType.Connector}
               slug_name="hosting_connector"
               className="mb-5"
             />
           ) : (
             <PluginRender
-              type="connector"
+              type={PluginType.Connector}
               slug_name="third_party_connector"
               className="mb-5"
             />
diff --git a/ui/src/pages/Users/Register/index.tsx b/ui/src/pages/Users/Register/index.tsx
index 857cd9d9..4d894b6a 100644
--- a/ui/src/pages/Users/Register/index.tsx
+++ b/ui/src/pages/Users/Register/index.tsx
@@ -26,6 +26,7 @@ import { usePageTags } from '@/hooks';
 import { Unactivate, WelcomeTitle, PluginRender } from '@/components';
 import { guard } from '@/utils';
 import { loginSettingStore } from '@/stores';
+import { PluginType } from '@/utils/pluginKit/interface';
 
 import SignUpForm from './components/SignUpForm';
 
@@ -55,7 +56,7 @@ const Index: React.FC = () => {
       {showForm ? (
         <Col className="mx-auto" md={6} lg={4} xl={3}>
           <PluginRender
-            type="connector"
+            type={PluginType.Connector}
             slug_name="third_party_connector"
             className="mb-5"
           />
diff --git a/ui/src/utils/pluginKit/index.ts b/ui/src/utils/pluginKit/index.ts
index 87851d80..5a106523 100644
--- a/ui/src/utils/pluginKit/index.ts
+++ b/ui/src/utils/pluginKit/index.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import React from 'react';
+import React, { RefObject } from 'react';
 
 import builtin from '@/plugins/builtin';
 import * as allPlugins from '@/plugins';
@@ -26,7 +26,8 @@ import { LOGGED_TOKEN_STORAGE_KEY } from '@/common/constants';
 import { getPluginsStatus } from '@/services';
 import Storage from '@/utils/storage';
 
-import { initI18nResource, Plugin, PluginInfo, PluginType } from './utils';
+import { initI18nResource } from './utils';
+import { Plugin, PluginInfo, PluginType } from './interface';
 
 /**
  * This information is to be defined for all components.
@@ -133,19 +134,10 @@ class Plugins {
 
 const plugins = new Plugins();
 
-const useRenderHtmlPlugin = (element: HTMLElement | null) => {
-  plugins
-    .getPlugins()
-    .filter((plugin) => plugin.activated && plugin.hooks?.useRender)
-    .forEach((plugin) => {
-      plugin.hooks?.useRender?.forEach((hook) => {
-        hook(element);
-      });
-    });
-};
-
 const getRoutePlugins = () => {
-  return plugins.getPlugins().filter((plugin) => plugin.info.type === 'route');
+  return plugins
+    .getPlugins()
+    .filter((plugin) => plugin.info.type === PluginType.Route);
 };
 
 const defaultProps = () => {
@@ -184,11 +176,36 @@ const mergeRoutePlugins = (routes) => {
   return routes;
 };
 
+/**
+ * Only used to enhance the capabilities of the markdown editor
+ * Add RefObject type to solve the problem of dom being null in hooks
+ */
+const useRenderHtmlPlugin = (
+  element: HTMLElement | RefObject<HTMLElement> | null,
+) => {
+  plugins
+    .getPlugins()
+    .filter((plugin) => {
+      return (
+        plugin.activated &&
+        plugin.hooks?.useRender &&
+        plugin.info.type === PluginType.Editor
+      );
+    })
+    .forEach((plugin) => {
+      plugin.hooks?.useRender?.forEach((hook) => {
+        hook(element);
+      });
+    });
+};
+
 // Only one captcha type plug-in can be enabled at the same time
 const useCaptchaPlugin = (key: Type.CaptchaKey) => {
   const captcha = plugins
     .getPlugins()
-    .filter((plugin) => plugin.info.type === 'captcha' && plugin.activated);
+    .filter(
+      (plugin) => plugin.info.type === PluginType.Captcha && plugin.activated,
+    );
   const pluginHooks = plugins.getOnePluginHooks(captcha[0]?.info.slug_name);
   return pluginHooks?.useCaptcha?.({
     captchaKey: key,
@@ -196,7 +213,7 @@ const useCaptchaPlugin = (key: Type.CaptchaKey) => {
   });
 };
 
-export type { Plugin, PluginInfo, PluginType };
+export type { Plugin, PluginInfo };
 
-export { useRenderHtmlPlugin, mergeRoutePlugins, useCaptchaPlugin };
+export { useRenderHtmlPlugin, mergeRoutePlugins, useCaptchaPlugin, PluginType };
 export default plugins;
diff --git a/ui/src/utils/pluginKit/interface.ts b/ui/src/utils/pluginKit/interface.ts
index d4376764..097fb94f 100644
--- a/ui/src/utils/pluginKit/interface.ts
+++ b/ui/src/utils/pluginKit/interface.ts
@@ -16,12 +16,41 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import { NamedExoticComponent, FC, RefObject } from 'react';
 
-export type PluginType = 'connector' | 'search' | 'editor' | 'captcha';
+import type * as Type from '@/common/interface';
+
+export enum PluginType {
+  Connector = 'connector',
+  Search = 'search',
+  Editor = 'editor',
+  Route = 'route',
+  Captcha = 'captcha',
+}
 
 export interface PluginInfo {
   slug_name: string;
   type: PluginType;
   name?: string;
   description?: string;
+  route?: string;
+}
+
+export interface Plugin {
+  info: PluginInfo;
+  component: NamedExoticComponent | FC;
+  i18nConfig?;
+  hooks?: {
+    useRender?: Array<
+      (element: HTMLElement | RefObject<HTMLElement> | null) => void
+    >;
+    useCaptcha?: (props: { captchaKey: Type.CaptchaKey; commonProps: any }) => {
+      getCaptcha: () => Record<string, any>;
+      check: (t: () => void) => void;
+      handleCaptchaError: (error) => any;
+      close: () => Promise<void>;
+      resolveCaptchaReq: (data) => void;
+    };
+  };
+  activated?: boolean;
 }
diff --git a/ui/src/utils/pluginKit/utils.ts b/ui/src/utils/pluginKit/utils.ts
index 2116e636..26118132 100644
--- a/ui/src/utils/pluginKit/utils.ts
+++ b/ui/src/utils/pluginKit/utils.ts
@@ -17,11 +17,9 @@
  * under the License.
  */
 
-import { NamedExoticComponent, FC } from 'react';
-
 import i18next from 'i18next';
 
-import type * as Type from '@/common/interface';
+import { PluginInfo, Plugin, PluginType } from './interface';
 
 /**
  * This information is to be defined for all components.
@@ -36,38 +34,6 @@ import type * as Type from '@/common/interface';
  */
 
 const I18N_NS = 'plugin';
-
-export type PluginType =
-  | 'connector'
-  | 'search'
-  | 'editor'
-  | 'route'
-  | 'captcha';
-export interface PluginInfo {
-  slug_name: string;
-  type: PluginType;
-  name?: string;
-  description?: string;
-  route?: string;
-}
-
-export interface Plugin {
-  info: PluginInfo;
-  component: NamedExoticComponent | FC;
-  i18nConfig?;
-  hooks?: {
-    useRender?: Array<(element: HTMLElement | null) => void>;
-    useCaptcha?: (props: { captchaKey: Type.CaptchaKey; commonProps: any }) => {
-      getCaptcha: () => Record<string, any>;
-      check: (t: () => void) => void;
-      handleCaptchaError: (error) => any;
-      close: () => Promise<void>;
-      resolveCaptchaReq: (data) => void;
-    };
-  };
-  activated?: boolean;
-}
-
 interface I18nResource {
   [lng: string]: {
     plugin: {
@@ -110,4 +76,6 @@ const getTransKeyPrefix = (info: PluginInfo) => {
   return kp;
 };
 
+export type { Plugin, PluginInfo, PluginType };
+
 export { initI18nResource, getTransNs, getTransKeyPrefix };