@bbki.ng/site 5.8.11 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/package.json +6 -3
  3. package/src/app/app.tsx +8 -7
  4. package/src/app/components/BaseLayout.tsx +6 -4
  5. package/src/app/components/cover/index.tsx +9 -5
  6. package/src/app/context/bbcontext.tsx +1 -1
  7. package/src/app/index.tsx +18 -1
  8. package/src/types/hostApi.ts +1 -2
  9. package/src/app/context/global_loading_state_provider.tsx +0 -65
  10. package/src/app/hooks/use_global_loading.ts +0 -47
  11. package/src/app/hooks/use_plugin_entries.ts +0 -34
  12. package/src/core/components/SlotComp.tsx +0 -14
  13. package/src/core/const/index.ts +0 -3
  14. package/src/core/context/createPluginCtx.tsx +0 -60
  15. package/src/core/context/index.ts +0 -1
  16. package/src/core/hooks/index.ts +0 -6
  17. package/src/core/hooks/useMiddlewareTransData.ts +0 -13
  18. package/src/core/hooks/useSlotComp.ts +0 -4
  19. package/src/core/hooks/use_plugins.ts +0 -115
  20. package/src/core/plugin-system/bbplugin.ts +0 -15
  21. package/src/core/plugin-system/manifest.ts +0 -56
  22. package/src/core/plugin-system/pluginManager.ts +0 -126
  23. package/src/core/plugin-system/pluginManifestService.ts +0 -97
  24. package/src/core/plugin-system/pluginStore.ts +0 -200
  25. package/src/core/plugin-system/registry.ts +0 -17
  26. package/src/core/plugin-system/services/coreService.ts +0 -75
  27. package/src/core/plugin-system/services/systemUIService.ts +0 -64
  28. package/src/core/shared-service/contract/ICoreService.ts +0 -28
  29. package/src/core/shared-service/contract/IUIService.ts +0 -53
  30. package/src/core/shared-service/factory/createUIService.ts +0 -121
  31. package/src/core/shared-service/factory/createUIServiceReactKit.tsx +0 -149
  32. package/src/core/shared-service/service-proxy.ts +0 -28
  33. package/src/core/shared-service/service-registry.ts +0 -54
  34. package/src/core/utils/eventBus.ts +0 -29
  35. package/src/plugins/blog/components/BlogLink.tsx +0 -11
  36. package/src/plugins/blog/components/BlogSlotCom.tsx +0 -14
  37. package/src/plugins/blog/components/app.tsx +0 -15
  38. package/src/plugins/blog/components/article/index.tsx +0 -51
  39. package/src/plugins/blog/components/index.tsx +0 -10
  40. package/src/plugins/blog/constants/index.ts +0 -1
  41. package/src/plugins/blog/context/index.ts +0 -7
  42. package/src/plugins/blog/hooks/useMiddlewareTransData.ts +0 -14
  43. package/src/plugins/blog/hooks/use_blog_scroll_pos_restoration.ts +0 -89
  44. package/src/plugins/blog/hooks/use_blog_slot_com.ts +0 -5
  45. package/src/plugins/blog/hooks/use_posts.ts +0 -74
  46. package/src/plugins/blog/index.ts +0 -79
  47. package/src/plugins/blog/pages/extensions/txt/article.tsx +0 -42
  48. package/src/plugins/blog/pages/extensions/txt/index.tsx +0 -58
  49. package/src/plugins/blog/services/BlogUIService.ts +0 -27
  50. package/src/plugins/blog/services/IBlogUIService.ts +0 -16
  51. package/src/plugins/extra-cd/index.ts +0 -36
  52. package/src/plugins/extra-entry/components/page.tsx +0 -14
  53. package/src/plugins/extra-entry/index.ts +0 -28
  54. package/src/plugins/fx/components/index.tsx +0 -45
  55. package/src/plugins/fx/context/index.ts +0 -12
  56. package/src/plugins/fx/hooks/useTextEffects.ts +0 -39
  57. package/src/plugins/fx/index.ts +0 -53
  58. package/src/plugins/fx/services/FxService.ts +0 -47
  59. package/src/plugins/fx/services/IFxService.ts +0 -15
  60. package/src/plugins/notification/components/index.tsx +0 -26
  61. package/src/plugins/notification/index.ts +0 -26
  62. package/src/plugins/notification/services/INotificationService.ts +0 -24
  63. package/src/plugins/notification/services/NotificationService.ts +0 -29
  64. package/src/plugins/now/components/NowLink.tsx +0 -7
  65. package/src/plugins/now/components/index.tsx +0 -9
  66. package/src/plugins/now/components/streaming/arrow-down.tsx +0 -26
  67. package/src/plugins/now/components/streaming/index.tsx +0 -99
  68. package/src/plugins/now/components/streaming/useScrollBtnVisibility.ts +0 -28
  69. package/src/plugins/now/context/index.ts +0 -10
  70. package/src/plugins/now/hooks/use_streaming.ts +0 -88
  71. package/src/plugins/now/index.ts +0 -62
  72. package/src/plugins/now/utils/streaming.ts +0 -33
  73. package/src/plugins/sticker/components/StickerCom.tsx +0 -45
  74. package/src/plugins/sticker/const.ts +0 -76
  75. package/src/plugins/sticker/context.ts +0 -7
  76. package/src/plugins/sticker/index.ts +0 -43
  77. package/src/plugins/sticker/types.ts +0 -10
  78. package/src/plugins/store/components/ArrowCom.tsx +0 -34
  79. package/src/plugins/store/components/ArrowSvg.tsx +0 -1133
  80. package/src/plugins/store/components/storeIcon.tsx +0 -16
  81. package/src/plugins/store/components/storePage.tsx +0 -202
  82. package/src/plugins/store/context/index.ts +0 -15
  83. package/src/plugins/store/index.ts +0 -57
  84. package/src/plugins/store/utils/index.ts +0 -26
  85. package/src/plugins/version/index.ts +0 -28
  86. package/src/plugins/xwy/components/XwyLink.tsx +0 -7
  87. package/src/plugins/xwy/components/article.tsx +0 -13
  88. package/src/plugins/xwy/components/logo.tsx +0 -28
  89. package/src/plugins/xwy/const/index.ts +0 -28
  90. package/src/plugins/xwy/index.ts +0 -103
  91. package/src/plugins/xwy/transformers/index.ts +0 -67
  92. package/src/plugins/xwy/types/index.ts +0 -17
  93. package/src/plugins/xwy/utils/index.ts +0 -43
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @bbki.ng/site
2
2
 
3
+ ## 6.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 02b0627: fix style
8
+ - 39f4f29: fix style error
9
+ - 8d26c74: update version color
10
+ - aea84cf: fix style
11
+ - Updated dependencies [39f4f29]
12
+ - Updated dependencies [8d26c74]
13
+ - Updated dependencies [aea84cf]
14
+ - @bbki.ng/plugin-sdk@1.0.1
15
+ - @bbki.ng/plugins@1.0.1
16
+ - @bbki.ng/core@1.0.1
17
+ - @bbki.ng/ui@1.0.1
18
+
19
+ ## 6.0.0
20
+
21
+ ### Major Changes
22
+
23
+ - 7edb536: refactor plugins
24
+
25
+ ### Patch Changes
26
+
27
+ - Updated dependencies [7edb536]
28
+ - @bbki.ng/plugin-sdk@1.0.0
29
+ - @bbki.ng/plugins@1.0.0
30
+ - @bbki.ng/core@1.0.0
31
+ - @bbki.ng/ui@1.0.0
32
+
3
33
  ## 5.8.11
4
34
 
5
35
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/site",
3
- "version": "5.8.11",
3
+ "version": "6.0.1",
4
4
  "description": "code behind bbki.ng",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -15,7 +15,10 @@
15
15
  "react-router-dom": "6",
16
16
  "sonner": "^2.0.7",
17
17
  "swr": "^2.2.5",
18
- "@bbki.ng/ui": "0.2.22"
18
+ "@bbki.ng/core": "1.0.1",
19
+ "@bbki.ng/plugin-sdk": "1.0.1",
20
+ "@bbki.ng/plugins": "1.0.1",
21
+ "@bbki.ng/ui": "1.0.1"
19
22
  },
20
23
  "devDependencies": {
21
24
  "@eslint/compat": "^1.0.0",
@@ -58,7 +61,7 @@
58
61
  "vite-plugin-mdx": "^3.5.8",
59
62
  "vite-plugin-pwa": "0.19",
60
63
  "workbox-window": "^6.3.0",
61
- "@bbki.ng/config": "1.0.9"
64
+ "@bbki.ng/config": "2.0.1"
62
65
  },
63
66
  "author": "bbbottle",
64
67
  "license": "MIT",
package/src/app/app.tsx CHANGED
@@ -1,16 +1,17 @@
1
- import React from 'react';
2
- import { Route, Routes } from 'react-router-dom';
1
+ import { Route, Routes, useNavigate } from 'react-router-dom';
2
+ import { usePlugins, usePluginEntries } from '@bbki.ng/core/react';
3
+ import { IPluginEntry } from '@bbki.ng/plugin-sdk';
3
4
 
4
5
  import { BotRedirect } from '#/app/components/bot';
5
- import { BBContext } from '#/app/context/bbcontext';
6
- import { usePlugins } from '#/core/hooks/use_plugins';
7
6
  import { Cover } from '#/app/components/cover';
7
+ import { BBContext } from '#/app/context/bbcontext';
8
8
  import { SWR } from '#/app/swr';
9
- import { usePluginEntries } from '#/app/hooks/use_plugin_entries';
10
9
  import { BaseLayout } from '#/app/components/BaseLayout';
11
10
 
12
11
  const AppRoutes = () => {
13
- usePlugins();
12
+ const { injectNavigate } = usePlugins();
13
+ const nav = useNavigate();
14
+ injectNavigate(nav);
14
15
 
15
16
  const pluginEntries = usePluginEntries();
16
17
 
@@ -19,7 +20,7 @@ const AppRoutes = () => {
19
20
  <Route path="/" element={<BaseLayout />}>
20
21
  <Route index element={<Cover />} />
21
22
  <Route path="bot" element={<BotRedirect />} />
22
- {pluginEntries?.map(route => {
23
+ {pluginEntries?.map((route: IPluginEntry) => {
23
24
  const Com = route.pageComponent;
24
25
  return <Route key={route.path} path={`${route.path}/*`} element={<Com data={route} />} />;
25
26
  })}
@@ -1,11 +1,13 @@
1
1
  import React, { useContext } from 'react';
2
2
  import { useNavigate, Outlet } from 'react-router-dom';
3
- import { Logo, Nav, Page, Grid, ErrorBoundary, Container } from '@bbki.ng/ui';
3
+ import { Logo } from '@bbki.ng/ui/logo';
4
+ import { Nav } from '@bbki.ng/ui/nav';
5
+ import { Page, ErrorBoundary } from '@bbki.ng/ui/page';
6
+ import { Grid } from '@bbki.ng/ui/grid';
7
+ import { Container } from '@bbki.ng/ui/container';
4
8
 
5
- import { Slot } from '#/core/components/SlotComp';
9
+ import { Slot, GlobalLoadingContext, useMiddlewareTransformedData } from '@bbki.ng/core/react';
6
10
  import { usePaths } from '#/app/hooks/use_paths';
7
- import { GlobalLoadingContext } from '#/app/context/global_loading_state_provider';
8
- import { useMiddlewareTransformedData } from '#/core/hooks/useMiddlewareTransData';
9
11
 
10
12
  export const BaseLayout = () => {
11
13
  const paths = usePaths();
@@ -1,10 +1,14 @@
1
1
  import React from 'react';
2
- import { LinkProps, LinkListProps, LinkList } from '@bbki.ng/ui';
2
+ import type { LinkProps } from '@bbki.ng/ui/link';
3
+ import { LinkList } from '@bbki.ng/ui/list';
4
+ import type { LinkListProps } from '@bbki.ng/ui/list';
3
5
 
4
- import { usePluginEntries } from '#/app/hooks/use_plugin_entries';
5
- import { useMiddlewareTransformedData } from '#/core/hooks/useMiddlewareTransData';
6
- import { Slot } from '#/core/components/SlotComp';
7
- import { useGlobalLoading } from '#/app/hooks/use_global_loading';
6
+ import {
7
+ usePluginEntries,
8
+ useMiddlewareTransformedData,
9
+ Slot,
10
+ useGlobalLoading,
11
+ } from '@bbki.ng/core/react';
8
12
 
9
13
  const CenterLinkList = (props: LinkListProps) => {
10
14
  return (
@@ -1,6 +1,6 @@
1
1
  import React, { ReactNode } from 'react';
2
2
 
3
- import { GlobalLoadingStateProvider } from '#/app/context/global_loading_state_provider';
3
+ import { GlobalLoadingStateProvider } from '@bbki.ng/core/react';
4
4
  import { GlobalRoutesProvider } from '#/app/context/global_routes_provider';
5
5
 
6
6
  export const BBContext = (props: { children: ReactNode }) => {
package/src/app/index.tsx CHANGED
@@ -2,15 +2,32 @@ import React from 'react';
2
2
  import { createRoot } from 'react-dom/client';
3
3
  import { BrowserRouter as Router } from 'react-router-dom';
4
4
 
5
+ import { createPluginRuntime } from '@bbki.ng/core';
6
+ import { PluginRuntimeProvider } from '@bbki.ng/core/react';
7
+ import { builtinPluginModules, FALLBACK_MANIFEST } from '@bbki.ng/plugins';
8
+ import { cfApiFetcher } from '#/app/utils';
9
+ import { getStableDeviceId } from '#/app/utils/fingerprints';
10
+
5
11
  import { App } from './app';
6
12
  import './main.css';
7
13
 
14
+ const runtime = createPluginRuntime({
15
+ fetcher: cfApiFetcher,
16
+ getDeviceId: getStableDeviceId,
17
+ versionHash: typeof GLOBAL_COMMIT_HASH === 'string' ? GLOBAL_COMMIT_HASH : '0000000',
18
+ fallbackManifest: FALLBACK_MANIFEST,
19
+ builtinPluginModules,
20
+ adminPluginIds: new Set(['store']),
21
+ });
22
+
8
23
  export const RenderApp = (ele: Element) => {
9
24
  const root = createRoot(ele);
10
25
  root.render(
11
26
  <React.StrictMode>
12
27
  <Router>
13
- <App />
28
+ <PluginRuntimeProvider runtime={runtime}>
29
+ <App />
30
+ </PluginRuntimeProvider>
14
31
  </Router>
15
32
  </React.StrictMode>
16
33
  );
@@ -1,5 +1,4 @@
1
- import { PluginStore } from '#/core/plugin-system/pluginStore';
2
- import { type ServiceRegistry } from '#/core/shared-service/service-registry';
1
+ import type { PluginStore, ServiceRegistry } from '@bbki.ng/core';
3
2
 
4
3
  export interface IHostContext {
5
4
  store?: PluginStore;
@@ -1,65 +0,0 @@
1
- import React, { createContext, ReactNode, useState, useCallback, useMemo } from 'react';
2
-
3
- type LoadingStates = Map<string, boolean>;
4
-
5
- type LoadingContext = {
6
- isLoading: boolean;
7
- register: (id: string) => void;
8
- setLoading: (id: string, loading: boolean) => void;
9
- unregister: (id: string) => void;
10
- };
11
-
12
- export const GlobalLoadingContext = createContext<LoadingContext>({
13
- isLoading: false,
14
- register: () => {},
15
- setLoading: () => {},
16
- unregister: () => {},
17
- });
18
-
19
- export const GlobalLoadingStateProvider = (props: { children: ReactNode }) => {
20
- const [loadingStates, setLoadingStates] = useState<LoadingStates>(new Map());
21
-
22
- const register = useCallback((id: string) => {
23
- setLoadingStates(prev => {
24
- const next = new Map(prev);
25
- next.set(id, false);
26
- return next;
27
- });
28
- }, []);
29
-
30
- const setLoading = useCallback((id: string, loading: boolean) => {
31
- setLoadingStates(prev => {
32
- const next = new Map(prev);
33
- next.set(id, loading);
34
- return next;
35
- });
36
- }, []);
37
-
38
- const unregister = useCallback((id: string) => {
39
- setLoadingStates(prev => {
40
- const next = new Map(prev);
41
- next.delete(id);
42
- return next;
43
- });
44
- }, []);
45
-
46
- const isLoading = useMemo(() => {
47
- return Array.from(loadingStates.values()).some(Boolean);
48
- }, [loadingStates]);
49
-
50
- const contextValue = useMemo(
51
- () => ({
52
- isLoading,
53
- register,
54
- setLoading,
55
- unregister,
56
- }),
57
- [isLoading, register, setLoading, unregister]
58
- );
59
-
60
- return (
61
- <GlobalLoadingContext.Provider value={contextValue}>
62
- {props.children}
63
- </GlobalLoadingContext.Provider>
64
- );
65
- };
@@ -1,47 +0,0 @@
1
- import { useCallback, useContext, useEffect } from 'react';
2
-
3
- import { GlobalLoadingContext } from '#/app/context/global_loading_state_provider';
4
-
5
- /**
6
- * Hook to register a loading state with the global loading context.
7
- * The global loading state is true if ANY registered loading state is true.
8
- *
9
- * @param id - Unique identifier for this loading state
10
- * @param loading - Whether this specific loading state is active
11
- */
12
- export function useGlobalLoading(
13
- id?: string | undefined,
14
- loading?: boolean | undefined
15
- ): {
16
- isLoading: boolean;
17
- setGlobalLoading: (key: string, loadingFromManual: boolean) => () => void;
18
- } {
19
- const { register, setLoading, unregister, isLoading } = useContext(GlobalLoadingContext);
20
-
21
- useEffect(() => {
22
- if (!id || loading === undefined) return;
23
-
24
- register(id);
25
- setLoading(id, loading);
26
- return () => {
27
- unregister(id);
28
- };
29
- }, [id, loading, register, setLoading, unregister]);
30
-
31
- const setGlobalLoading = useCallback(
32
- (key: string, loadingFromManual: boolean) => {
33
- register(key);
34
- setLoading(key, loadingFromManual);
35
-
36
- return () => {
37
- unregister(key);
38
- };
39
- },
40
- [register, setLoading, unregister]
41
- );
42
-
43
- return {
44
- isLoading,
45
- setGlobalLoading,
46
- };
47
- }
@@ -1,34 +0,0 @@
1
- import { useEffect, useMemo, useState } from 'react';
2
-
3
- import { SystemUIService } from '#/core/plugin-system/services/systemUIService';
4
- import { IPluginEntry } from '#/types/plugin';
5
-
6
- const protectedRoutesSet = new Set<string>(['/bot', '/', 'default']);
7
-
8
- const emptyEntries: Array<IPluginEntry> = [];
9
-
10
- export const usePluginEntries = () => {
11
- const [entries, setEntries] = useState<Array<IPluginEntry>>(() =>
12
- SystemUIService.getInstance().getPluginEntries()
13
- );
14
-
15
- useEffect(() => {
16
- const service = SystemUIService.getInstance();
17
- setEntries(service.getPluginEntries());
18
-
19
- const unsubscribe = service.subscribePluginEntryChange(() => {
20
- setEntries(service.getPluginEntries());
21
- });
22
-
23
- return () => {
24
- unsubscribe();
25
- };
26
- }, []);
27
-
28
- const safeEntries = useMemo(
29
- () => entries?.filter(entry => !protectedRoutesSet.has(entry.path)),
30
- [entries]
31
- );
32
-
33
- return safeEntries ?? emptyEntries;
34
- };
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
-
3
- import { SystemUIService } from '#/core/plugin-system/services/systemUIService';
4
- import { createSlotComponent } from '#/core/shared-service/factory/createUIServiceReactKit';
5
-
6
- import { SystemSlotName } from '../shared-service/contract/IUIService';
7
-
8
- export interface ISlotProps {
9
- name: SystemSlotName;
10
- data?: unknown;
11
- placeholder?: React.ReactNode;
12
- }
13
-
14
- export const Slot = createSlotComponent<SystemSlotName>(SystemUIService.getInstance());
@@ -1,3 +0,0 @@
1
- import { PluginID } from '#/types/plugin';
2
-
3
- export const AdminPluginIDSet: Set<PluginID> = new Set(['store']);
@@ -1,60 +0,0 @@
1
- import React, { createContext, useContext, ComponentType } from 'react';
2
-
3
- import { IComPropsRegisteredToSlot } from '#/types/slots';
4
-
5
- /**
6
- * 创建插件专属的 Context 工具集
7
- */
8
- export function createPluginCtx<T>() {
9
- const Ctx = createContext<T | null>(null);
10
-
11
- /**
12
- * 在组件内部使用,获取插件上下文
13
- * @throws 如果不在 Provider 内会抛出错误
14
- */
15
- const useCtx = (): T => {
16
- const val = useContext(Ctx);
17
- if (!val) {
18
- throw new Error(
19
- 'useCtx must be used within a Plugin Context Provider. ' +
20
- 'Make sure your component is wrapped by withCtx().'
21
- );
22
- }
23
- return val;
24
- };
25
-
26
- /**
27
- * 高阶组件:为组件注入插件上下文
28
- *
29
- * @param picker - 从 IHostContext 中提取需要的值
30
- * @param Component - 基础组件
31
- * @returns 接收 IHostContext 并返回包装后组件的函数
32
- *
33
- * 使用方式:
34
- * const Enhanced = withCtx(picker, BaseComp)(ctx);
35
- * ctx.api.registerSlot('slotName', Enhanced, pluginId);
36
- */
37
- const withCtx = <P extends IComPropsRegisteredToSlot>(
38
- ctx: T,
39
- Component: React.ComponentType<P>
40
- ): ComponentType<P> => {
41
- const WrappedComponent: React.FC<P> = props => {
42
- return (
43
- <Ctx.Provider value={ctx}>
44
- <Component {...props} />
45
- </Ctx.Provider>
46
- );
47
- };
48
-
49
- return WrappedComponent;
50
- };
51
-
52
- return {
53
- /** React Context 对象,通常不需要直接使用 */
54
- Ctx,
55
- /** 在组件内部使用,获取插件上下文 */
56
- useCtx,
57
- /** 高阶组件,用于包装组件并注入 Context */
58
- withCtx,
59
- };
60
- }
@@ -1 +0,0 @@
1
- export { createPluginCtx } from './createPluginCtx';
@@ -1,6 +0,0 @@
1
- export { useSlotComp } from './useSlotComp';
2
- export { useMiddlewareRunner } from './useMiddlewareTransData';
3
- export type {
4
- UseMiddlewareRunnerOptions as UseMiddlewareTransDataOptions,
5
- UseMiddlewareRunnerResult as UseMiddlewareTransDataResult,
6
- } from './useMiddlewareTransData';
@@ -1,13 +0,0 @@
1
- import {
2
- createMiddlewareRunnerHook,
3
- createMiddlewareTransformedDataHook,
4
- } from '#/core/shared-service/factory/createUIServiceReactKit';
5
- import { SystemUIService } from '#/core/plugin-system/services/systemUIService';
6
-
7
- export const useMiddlewareRunner = createMiddlewareRunnerHook(SystemUIService.getInstance());
8
- export const useMiddlewareTransformedData =
9
- createMiddlewareTransformedDataHook(useMiddlewareRunner);
10
- export type {
11
- UseMiddlewareRunnerOptions,
12
- UseMiddlewareRunnerResult,
13
- } from '#/core/shared-service/factory/createUIServiceReactKit';
@@ -1,4 +0,0 @@
1
- import { createSlotHook } from '#/core/shared-service/factory/createUIServiceReactKit';
2
- import { SystemUIService } from '#/core/plugin-system/services/systemUIService';
3
-
4
- export const useSlotComp = createSlotHook(SystemUIService.getInstance());
@@ -1,115 +0,0 @@
1
- import { useEffect, useMemo, useState } from 'react';
2
- import { useNavigate } from 'react-router-dom';
3
-
4
- import { useGlobalLoading } from '#/app/hooks/use_global_loading';
5
- import { pluginManager } from '#/core/plugin-system/pluginManager';
6
- import { PluginID } from '#/types/plugin';
7
-
8
- import { PluginManifestService } from '../plugin-system/pluginManifestService';
9
- import { PluginStore } from '../plugin-system/pluginStore';
10
- import { CoreService } from '../plugin-system/services/coreService';
11
-
12
- const usePluginsLoading = () => {
13
- const { setGlobalLoading, isLoading } = useGlobalLoading();
14
-
15
- useEffect(() => {
16
- CoreService.getInstance().setSiteLoading(isLoading);
17
- }, [isLoading]);
18
-
19
- useEffect(() => {
20
- let unregisters = new Map<string, () => void>();
21
-
22
- const unsubscribe = CoreService.getInstance().subscribePluginLoading(payload => {
23
- unregisters.set(payload.id, setGlobalLoading(payload.id, payload.loading));
24
- });
25
-
26
- return () => {
27
- unsubscribe();
28
- unregisters.forEach(unregister => unregister());
29
- };
30
- }, [setGlobalLoading]);
31
- };
32
-
33
- /**
34
- * 通用插件管理 hook
35
- * 根据传入的插件ID列表加载和卸载插件
36
- *
37
- * @param pluginIds - 要加载的插件ID列表
38
- *
39
- * @example
40
- * usePlugins(['sticker', 'fontstyler']);
41
- */
42
- export const usePlugins = () => {
43
- const [done, setDone] = useState(false);
44
-
45
- const installedPlugins = PluginStore.getInstance().getInstalledPlugins();
46
-
47
- const { setGlobalLoading } = useGlobalLoading();
48
-
49
- const pluginIds: Array<PluginID> = useMemo(
50
- () => [...Array.from(installedPlugins), 'store'],
51
- [installedPlugins]
52
- );
53
-
54
- usePluginsLoading();
55
-
56
- const nav = useNavigate();
57
- CoreService.getInstance().injectNavigate(nav);
58
-
59
- useEffect(() => {
60
- const unregister = setGlobalLoading('plugins', !done);
61
-
62
- return () => {
63
- unregister();
64
- };
65
- }, [done, setGlobalLoading]);
66
-
67
- useEffect(() => {
68
- let cancelled = false;
69
-
70
- PluginManifestService.getInstance()
71
- .fetch()
72
- .then(() => {
73
- if (cancelled) {
74
- return;
75
- }
76
- const loadNext = (index: number) => {
77
- if (cancelled || index >= pluginIds.length) {
78
- if (!cancelled) {
79
- setDone(true);
80
- }
81
- return;
82
- }
83
-
84
- const id = pluginIds[index];
85
- pluginManager
86
- .loadPlugin(id)
87
- .then(() => loadNext(index + 1))
88
- .catch(error => {
89
- if (!cancelled) {
90
- console.error(`Error loading plugin ${id}:`, error);
91
- // 即使某个插件加载失败,也继续加载下一个
92
- loadNext(index + 1);
93
- }
94
- });
95
- };
96
-
97
- loadNext(0);
98
- })
99
- .catch(error => {
100
- if (!cancelled) {
101
- console.error('Error fetching plugin manifest:', error);
102
- }
103
- });
104
-
105
- return () => {
106
- cancelled = true;
107
- // 卸载所有指定的插件
108
- pluginIds.forEach(id => {
109
- pluginManager.disablePlugin(id);
110
- });
111
- };
112
- }, [pluginIds]);
113
-
114
- return done;
115
- };
@@ -1,15 +0,0 @@
1
- import { IHostContext } from '#/types/hostApi';
2
- import { IPlugin, IPluginManifestEntry, PluginID } from '#/types/plugin';
3
-
4
- import { PluginManifestService } from './pluginManifestService';
5
-
6
- export class BBPlugin implements IPlugin {
7
- id: PluginID = 'default';
8
- onInstall?: ((ctx: IHostContext) => void | Promise<void>) | undefined;
9
- onDisable?: (() => Promise<void> | void) | undefined;
10
- onDestroy?: (() => void) | undefined;
11
- onManualInstall?: (() => void) | undefined;
12
- getMeta(): IPluginManifestEntry {
13
- return PluginManifestService.getInstance().getPlugin(this.id) as IPluginManifestEntry;
14
- }
15
- }
@@ -1,56 +0,0 @@
1
- import { IPluginManifestEntry } from '#/types/plugin';
2
-
3
- export const FALLBACK_MANIFEST: Array<IPluginManifestEntry> = [
4
- {
5
- name: '贴纸',
6
- id: 'sticker',
7
- version: '0.1.0',
8
- description: '在页面一些地方显示奇怪的贴纸',
9
- },
10
- {
11
- name: '插件商店',
12
- id: 'store',
13
- version: '0.1.0',
14
- description: '一个管理 bbki.ng 插件的商店',
15
- perm: 'admin',
16
- },
17
- {
18
- name: '最近',
19
- id: 'now',
20
- version: '1.0.0',
21
- description: '显示网站最近更新的版本,以及一些文字动态',
22
- },
23
- {
24
- name: '捷径',
25
- id: 'extra-cd',
26
- version: '0.1.0',
27
- description:
28
- '提供额外的页面跳转链接。例如在标题列表末尾添加一个 "cd ~" 的选项,点击后跳转到主页',
29
- dependencies: ['blog'],
30
- },
31
- {
32
- name: '特效',
33
- id: 'fx',
34
- version: '0.1.0',
35
- description: '提供一些额外的视觉效果。例如版本、设备信息水印,加载状态螺旋线、背景纹理等',
36
- },
37
- {
38
- name: '小乌鸦',
39
- id: 'xwy',
40
- version: '0.1.0',
41
- description: '为小乌鸦合集实现定制功能或者样式的插件',
42
- dependencies: ['blog'],
43
- },
44
- {
45
- name: '博客',
46
- id: 'blog',
47
- version: '0.1.0',
48
- description: '一个简单的博客系统,支持 Markdown 格式的文章',
49
- },
50
- {
51
- name: '通知',
52
- id: 'notification',
53
- version: '0.1.0',
54
- description: '接收通知',
55
- },
56
- ];