feat(plugin): Render plugins based on plugin status

This commit is contained in:
robin 2023-09-21 16:11:33 +08:00
parent 467721631a
commit 6e45e3e6d9
6 changed files with 48 additions and 3 deletions

View File

@ -598,3 +598,8 @@ export interface NotificationConfig {
all_new_question_for_following_tags: NotificationConfigItem[];
inbox: NotificationConfigItem[];
}
export interface ActivatedPlugin {
name: string;
slug_name: string;
}

View File

@ -27,7 +27,7 @@ const Index: FC<Props> = ({
...props
}) => {
const pluginSlice: Plugin[] = [];
const plugins = PluginKit.getPlugins();
const plugins = PluginKit.getPlugins().filter((plugin) => plugin.activated);
plugins.forEach((plugin) => {
if (type && slug_name) {
@ -50,6 +50,10 @@ const Index: FC<Props> = ({
* ps: Logic such as version compatibility determination can be placed here
*/
if (pluginSlice.length === 0) {
return null;
}
if (type === 'editor') {
const nodes = React.Children.map(children, (child, index) => {
if (index === 15) {

View File

@ -19,8 +19,10 @@ import {
useQueryQuestionByTitle,
getTagsBySlugName,
saveQuestionWidthAnaser,
useEditorPlugins,
} from '@/services';
import { handleFormError, SaveDraft, storageExpires } from '@/utils';
import pluginKit from '@/utils/pluginKit';
import { pathFactory } from '@/router/pathFactory';
import SearchQuestion from './components/SearchQuestion';
@ -104,6 +106,8 @@ const Ask = () => {
const saveCaptcha = useCaptchaModal('question');
const editCaptcha = useCaptchaModal('edit');
const plugins = useEditorPlugins();
pluginKit.activatePlugins(plugins.data || []);
const removeDraft = () => {
saveDraft.save.cancel();

View File

@ -11,13 +11,14 @@ import { useTranslation } from 'react-i18next';
import { Pagination, CustomSidebar } from '@/components';
import { loggedUserInfoStore, toastStore } from '@/stores';
import { scrollToElementTop, scrollToDocTop } from '@/utils';
import pluginKit from '@/utils/pluginKit';
import { usePageTags, usePageUsers } from '@/hooks';
import type {
ListResult,
QuestionDetailRes,
AnswerItem,
} from '@/common/interface';
import { questionDetail, getAnswers } from '@/services';
import { questionDetail, getAnswers, useEditorPlugins } from '@/services';
import {
Question,
@ -61,6 +62,8 @@ const Index = () => {
const isLogged = Boolean(userInfo?.access_token);
const loggedUserRank = userInfo?.rank;
const { state: locationState } = useLocation();
const plugins = useEditorPlugins();
pluginKit.activatePlugins(plugins.data || []);
useEffect(() => {
if (locationState?.isReview) {

View File

@ -73,3 +73,17 @@ export const putInviteUser = (
...imgCode,
});
};
export const useEditorPlugins = () => {
const apiUrl = '/answer/api/v1/editor/tools';
const { data, error } = useSWR<Type.ActivatedPlugin[], Error>(
apiUrl,
request.instance.get,
);
return {
data,
isLoading: !data && !error,
error,
};
};

View File

@ -2,6 +2,7 @@ import { NamedExoticComponent, FC } from 'react';
import builtin from '@/plugins/builtin';
import * as allPlugins from '@/plugins';
import type * as Type from '@/common/interface';
import { initI18nResource } from './utils';
@ -32,6 +33,7 @@ export interface Plugin {
hooks?: {
useRender?: Array<(element: HTMLElement | null) => void>;
};
activated?: boolean;
}
class Plugins {
@ -85,6 +87,18 @@ class Plugins {
this.plugins.push(plugin);
}
activatePlugins(activatedPlugins: Type.ActivatedPlugin[]) {
this.plugins.forEach((plugin) => {
const { slug_name } = plugin.info;
const activatedPlugin = activatedPlugins.find(
(p) => p.slug_name === slug_name,
);
if (activatedPlugin) {
plugin.activated = true;
}
});
}
getPlugin(slug_name: string) {
return this.plugins.find((p) => p.info.slug_name === slug_name);
}
@ -99,12 +113,13 @@ const plugins = new Plugins();
const useRenderHtmlPlugin = (element: HTMLElement | null) => {
plugins
.getPlugins()
.filter((plugin) => plugin.hooks?.useRender)
.filter((plugin) => plugin.activated && plugin.hooks?.useRender)
.forEach((plugin) => {
plugin.hooks?.useRender?.forEach((hook) => {
hook(element);
});
});
};
export { useRenderHtmlPlugin };
export default plugins;