@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
@@ -1,126 +0,0 @@
1
- import { IHostContext } from '#/types/hostApi';
2
- import { IPlugin, PluginID, PluginPerm } from '#/types/plugin';
3
-
4
- import { AdminPluginIDSet } from '../const';
5
- import { ServiceRegistry } from '../shared-service/service-registry';
6
-
7
- import { PluginStore } from './pluginStore';
8
- import { CoreService } from './services/coreService';
9
- import { SystemUIService } from './services/systemUIService';
10
-
11
- const pluginModules = import.meta.glob('../../plugins/*/index.ts');
12
-
13
- class PluginManager {
14
- private activePlugins: Map<string, IPlugin> = new Map();
15
-
16
- private constructor() {
17
- ServiceRegistry.getInstance().register('core:baseService', CoreService.getInstance());
18
- ServiceRegistry.getInstance().register('core:uiService', SystemUIService.getInstance());
19
- }
20
-
21
- private static instance: PluginManager;
22
-
23
- private createHostContext(perm: PluginPerm = 'guest'): IHostContext {
24
- const adminCtx =
25
- perm === 'admin'
26
- ? {
27
- store: PluginStore.getInstance(),
28
- }
29
- : {};
30
- return {
31
- ...adminCtx,
32
- service: ServiceRegistry.getInstance(),
33
- };
34
- }
35
-
36
- private loading = new Set<string>();
37
-
38
- static getInstance() {
39
- if (!PluginManager.instance) {
40
- PluginManager.instance = new PluginManager();
41
- }
42
- return PluginManager.instance;
43
- }
44
-
45
- // enable abort ctrl
46
- async loadPlugin(pluginId: PluginID): Promise<IPlugin | undefined> {
47
- if (this.activePlugins.has(pluginId)) {
48
- console.warn(`Plugin ${pluginId} is already loaded.`);
49
- return;
50
- }
51
-
52
- if (this.loading.has(pluginId)) {
53
- console.warn(`Plugin ${pluginId} is loading...`);
54
- return;
55
- }
56
-
57
- // try load plugin
58
- this.loading.add(pluginId);
59
- CoreService.getInstance().setLoading(pluginId, true);
60
-
61
- const modulePath = `../../plugins/${pluginId}/index.ts`;
62
- const moduleLoader = pluginModules[modulePath];
63
- if (!moduleLoader) {
64
- console.error(`Plugin ${pluginId} not found in registry`);
65
-
66
- this.loading.delete(pluginId);
67
- CoreService.getInstance().setLoading(pluginId, false);
68
-
69
- return;
70
- }
71
-
72
- try {
73
- const module = (await moduleLoader()) as {
74
- default: IPlugin;
75
- };
76
-
77
- const p: IPlugin = module.default;
78
-
79
- const perm = p.getMeta().perm || 'guest';
80
- if (perm === 'admin' && !AdminPluginIDSet.has(pluginId)) {
81
- throw new Error(`Plugin ${pluginId} requires admin permission, but it's not trusted.`);
82
- }
83
-
84
- const ctx = this.createHostContext(perm);
85
-
86
- if (p.onInstall) {
87
- await p.onInstall(ctx);
88
- }
89
-
90
- this.activePlugins.set(pluginId, p);
91
- return p;
92
- } catch (error) {
93
- console.error(`Failed to load plugin ${pluginId}:`, error);
94
- } finally {
95
- this.loading.delete(pluginId);
96
- CoreService.getInstance().setLoading(pluginId, false);
97
- }
98
- }
99
-
100
- getPlugin(pluginId: PluginID): IPlugin | undefined {
101
- return this.activePlugins.get(pluginId);
102
- }
103
-
104
- async disablePlugin(pluginId: PluginID) {
105
- const plugin = this.activePlugins.get(pluginId);
106
- if (!plugin) {
107
- console.warn(`Plugin ${pluginId} is not loaded.`);
108
- return;
109
- }
110
-
111
- if (plugin.onDisable) {
112
- await plugin.onDisable();
113
- }
114
-
115
- if (plugin.onDestroy) {
116
- plugin.onDestroy();
117
- }
118
-
119
- this.activePlugins.delete(pluginId);
120
-
121
- SystemUIService.getInstance().unregisterAllByPluginId(plugin.id);
122
- CoreService.getInstance().notifyPluginUninstall(plugin.id);
123
- }
124
- }
125
-
126
- export const pluginManager = PluginManager.getInstance();
@@ -1,97 +0,0 @@
1
- import { cfApiFetcher } from '#/app/utils';
2
- import { FALLBACK_MANIFEST } from '#/core/plugin-system/manifest';
3
- import { IPluginManifestEntry, PluginID } from '#/types/plugin';
4
-
5
- // const KnownPluginIDSet = new Set<string>(FALLBACK_MANIFEST.map(entry => entry.id));
6
-
7
- interface PluginsApiResponse {
8
- status: string;
9
- data: Array<{
10
- id: string;
11
- name: string;
12
- version: string;
13
- description?: string;
14
- perm?: string;
15
- icon?: string;
16
- dependencies?: Array<PluginID>;
17
- }>;
18
- }
19
-
20
- class PluginManifestService {
21
- private static instance: PluginManifestService;
22
-
23
- private manifestMap: Map<string, IPluginManifestEntry> = new Map();
24
-
25
- private fetched = false;
26
-
27
- private fetchPromise: Promise<void> | null = null;
28
-
29
- private constructor() {
30
- this.initWithFallback();
31
- }
32
-
33
- private initWithFallback = () => {
34
- this.manifestMap = new Map(FALLBACK_MANIFEST.map(entry => [entry.id, entry]));
35
- };
36
-
37
- async fetch(): Promise<void> {
38
- if (this.fetched) {
39
- return;
40
- }
41
- if (this.fetchPromise) {
42
- return this.fetchPromise;
43
- }
44
-
45
- this.fetchPromise = (async () => {
46
- try {
47
- const res = await cfApiFetcher<PluginsApiResponse>('plugins');
48
- if (res.status === 'success' && Array.isArray(res.data)) {
49
- const validated = res.data
50
- .map((item): IPluginManifestEntry | null => {
51
- return {
52
- id: item.id as PluginID,
53
- name: item.name,
54
- version: item.version,
55
- description: item.description,
56
- perm: (item.perm as 'guest' | 'admin' | undefined) || 'guest',
57
- icon: item.icon,
58
- dependencies: item.dependencies || [],
59
- };
60
- })
61
- .filter((item): item is IPluginManifestEntry => item !== null);
62
-
63
- this.manifestMap = new Map(validated.map(entry => [entry.id, entry]));
64
- }
65
- this.fetched = true;
66
- } catch (error) {
67
- console.error('[PluginManifestService] Failed to fetch manifest:', error);
68
- // Keep fallback data
69
- }
70
- })();
71
-
72
- return this.fetchPromise;
73
- }
74
-
75
- getPlugin(id: string): IPluginManifestEntry | undefined {
76
- return this.manifestMap.get(id);
77
- }
78
-
79
- getAllPlugins(): IPluginManifestEntry[] {
80
- return Array.from(this.manifestMap.values());
81
- }
82
-
83
- reset(): void {
84
- this.fetched = false;
85
- this.fetchPromise = null;
86
- this.initWithFallback();
87
- }
88
-
89
- static getInstance() {
90
- if (!PluginManifestService.instance) {
91
- PluginManifestService.instance = new PluginManifestService();
92
- }
93
- return PluginManifestService.instance;
94
- }
95
- }
96
-
97
- export { PluginManifestService };
@@ -1,200 +0,0 @@
1
- import { IPluginStoreEntry, PluginID } from '#/types/plugin';
2
-
3
- import { pluginManager } from './pluginManager';
4
- import { PluginManifestService } from './pluginManifestService';
5
-
6
- export class PluginStore {
7
- private static instance: PluginStore;
8
-
9
- private installedSet: Set<PluginID> = new Set();
10
-
11
- private constructor() {
12
- this.parse();
13
- }
14
-
15
- // TODO: check circular dependency when install plugin, and also check if all dependencies are installed before install a plugin
16
- private checkDep = (id: PluginID): boolean => {
17
- const manifest = PluginManifestService.getInstance().getPlugin(id);
18
- if (!manifest) {
19
- console.warn(`[PluginStore] Manifest not found for plugin: ${id}`);
20
- return false;
21
- }
22
-
23
- if (!manifest.dependencies || manifest.dependencies.length === 0) {
24
- return true;
25
- }
26
-
27
- for (const depId of manifest.dependencies) {
28
- if (!this.isPluginInstalled(depId)) {
29
- console.warn(`[PluginStore] Dependency ${depId} for plugin ${id} is not installed`);
30
- return false;
31
- }
32
- }
33
-
34
- return true;
35
- };
36
-
37
- private parse = () => {
38
- this.installedSet.clear();
39
- const installedPluginsStr = localStorage.getItem('installed_plugins');
40
- if (installedPluginsStr) {
41
- try {
42
- const entries = JSON.parse(installedPluginsStr) as Array<PluginID>;
43
- entries.forEach(id => this.installedSet.add(id));
44
- } catch (e) {
45
- console.error('Failed to parse installed plugins from localStorage', e);
46
- }
47
- }
48
-
49
- try {
50
- this.ensureRightOrder(this.installedSet);
51
- } catch (error) {
52
- console.error('Failed to ensure correct plugin load order:', error);
53
- }
54
-
55
- return this.installedSet;
56
- };
57
-
58
- private buildDependencyGraph = (ids: Set<PluginID>): Map<PluginID, PluginID[]> => {
59
- const graph = new Map<PluginID, PluginID[]>();
60
- const manifest = PluginManifestService.getInstance().getAllPlugins();
61
-
62
- ids.forEach(id => {
63
- graph.set(id, []);
64
- });
65
-
66
- manifest.forEach(plugin => {
67
- if (ids.has(plugin.id)) {
68
- const deps = plugin.dependencies || [];
69
- deps.forEach(dep => {
70
- if (ids.has(dep)) {
71
- if (!graph.has(dep)) {
72
- graph.set(dep, []);
73
- }
74
- graph.get(dep)!.push(plugin.id);
75
- }
76
- });
77
- }
78
- });
79
-
80
- return graph;
81
- };
82
-
83
- private topologicalSortKahn = (graph: Map<PluginID, PluginID[]>): PluginID[] => {
84
- const inDegree = new Map<PluginID, number>();
85
- graph.forEach((deps, plugin) => {
86
- if (!inDegree.has(plugin)) {
87
- inDegree.set(plugin, 0);
88
- }
89
- deps.forEach(dep => {
90
- inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
91
- });
92
- });
93
-
94
- const queue: PluginID[] = [];
95
- inDegree.forEach((degree, plugin) => {
96
- if (degree === 0) {
97
- queue.push(plugin);
98
- }
99
- });
100
-
101
- const loadOrder: PluginID[] = [];
102
- while (queue.length > 0) {
103
- const current = queue.shift()!;
104
- loadOrder.push(current);
105
-
106
- const deps = graph.get(current) || [];
107
- deps.forEach(dep => {
108
- inDegree.set(dep, inDegree.get(dep)! - 1);
109
- if (inDegree.get(dep) === 0) {
110
- queue.push(dep);
111
- }
112
- });
113
- }
114
-
115
- if (loadOrder.length !== graph.size) {
116
- throw new Error('Circular dependency detected among plugins');
117
- }
118
-
119
- return loadOrder;
120
- };
121
-
122
- private ensureRightOrder = (ids: Set<PluginID>) => {
123
- const graph = this.buildDependencyGraph(ids);
124
- const loadOrder = this.topologicalSortKahn(graph);
125
-
126
- // write back to installedSet in the correct order without create a new Set to preserve reference
127
- if (loadOrder.length === ids.size) {
128
- this.installedSet.clear();
129
- loadOrder.forEach(id => this.installedSet.add(id));
130
- }
131
- };
132
-
133
- private stringify = () => {
134
- localStorage.setItem('installed_plugins', JSON.stringify(Array.from(this.installedSet)));
135
- };
136
-
137
- getInstalledPlugins: () => Set<PluginID> = () => {
138
- return this.parse();
139
- };
140
-
141
- async getAllPlugins(): Promise<Array<IPluginStoreEntry>> {
142
- const installedPlugins = this.getInstalledPlugins();
143
- await PluginManifestService.getInstance().fetch();
144
- const manifest = PluginManifestService.getInstance().getAllPlugins();
145
- return manifest.map(plugin => ({
146
- ...plugin,
147
- enabled: installedPlugins.has(plugin.id),
148
- }));
149
- }
150
-
151
- isPluginInstalled: (id: PluginID) => boolean = id => {
152
- return this.getInstalledPlugins().has(id);
153
- };
154
-
155
- getPlugin: (id: PluginID) => IPluginStoreEntry | undefined = id => {
156
- const manifest = PluginManifestService.getInstance().getPlugin(id);
157
- if (!manifest) {
158
- return undefined;
159
- }
160
-
161
- return {
162
- ...manifest,
163
- enabled: this.isPluginInstalled(id),
164
- };
165
- };
166
-
167
- installPlugin: (id: PluginID, manual?: boolean) => Promise<boolean> = async (id, manual) => {
168
- if (!this.checkDep(id)) {
169
- // throw new Error(`Cannot install plugin ${id} due to missing dependencies`);
170
- console.warn(`Cannot install plugin ${id} due to missing dependencies`);
171
- return false;
172
- }
173
-
174
- try {
175
- const plugin = await pluginManager.loadPlugin(id);
176
- if (manual && plugin?.onManualInstall) {
177
- plugin.onManualInstall();
178
- }
179
- this.installedSet.add(id);
180
- this.stringify();
181
- return true;
182
- } catch (error) {
183
- console.error(`Failed to install plugin ${id}:`, error);
184
- return false;
185
- }
186
- };
187
-
188
- disablePlugin: (id: PluginID) => Promise<void> = async id => {
189
- await pluginManager.disablePlugin(id);
190
- this.installedSet.delete(id);
191
- this.stringify();
192
- };
193
-
194
- static getInstance() {
195
- if (!PluginStore.instance) {
196
- PluginStore.instance = new PluginStore();
197
- }
198
- return PluginStore.instance;
199
- }
200
- }
@@ -1,17 +0,0 @@
1
- import React from 'react';
2
-
3
- import type { IComPropsRegisteredToSlot } from '#/types/slots';
4
-
5
- export interface ISlotEntry {
6
- id: string;
7
- component: React.ComponentType<IComPropsRegisteredToSlot>;
8
- pluginId: string;
9
- weight: number;
10
- }
11
-
12
- export interface IMiddlewareEntry<T> {
13
- id: string;
14
- fn: (data: T) => Promise<T> | T;
15
- pluginId: string;
16
- weight?: number;
17
- }
@@ -1,75 +0,0 @@
1
- import { Fetcher } from 'swr';
2
- import { NavigateFunction } from 'react-router-dom';
3
-
4
- import { getStableDeviceId } from '#/app/utils/fingerprints';
5
- import { cfApiFetcher } from '#/app/utils';
6
- import { PluginEvents, PluginID } from '#/types/plugin';
7
-
8
- import { ICoreService } from '../../shared-service/contract/ICoreService';
9
- import { createEventBus } from '../../utils/eventBus';
10
-
11
- export class CoreService implements ICoreService {
12
- private static instance: CoreService;
13
-
14
- private constructor() {}
15
-
16
- private bus = createEventBus<PluginEvents>();
17
- private navigate?: NavigateFunction;
18
-
19
- getDeviceId = getStableDeviceId;
20
-
21
- injectNavigate(nav: NavigateFunction) {
22
- this.navigate = nav;
23
- }
24
-
25
- open = (url: string, options?: { newTab?: boolean }) => {
26
- // use navigate
27
- if (this.navigate) {
28
- this.navigate(url);
29
- } else {
30
- if (options?.newTab) {
31
- window.open(url, '_blank');
32
- } else {
33
- window.location.href = url;
34
- }
35
- }
36
- };
37
-
38
- getVersionHash() {
39
- const hashStr: string = typeof GLOBAL_COMMIT_HASH === 'string' ? GLOBAL_COMMIT_HASH : '0000000';
40
- return hashStr;
41
- }
42
-
43
- setLoading(id: PluginID, loading: boolean): void {
44
- this.bus.emit('plugin:loading:changed', { id, loading });
45
- }
46
-
47
- subscribePluginLoading(listener: (payload: PluginEvents['plugin:loading:changed']) => void) {
48
- return this.bus.on('plugin:loading:changed', listener);
49
- }
50
-
51
- subscribePluginUninstall(listener: (payload: PluginEvents['plugin:uninstall']) => void) {
52
- return this.bus.on('plugin:uninstall', listener);
53
- }
54
-
55
- notifyPluginUninstall(id: PluginID): void {
56
- this.bus.emit('plugin:uninstall', id);
57
- }
58
-
59
- subscribeLoadingChange(listener: (payload: boolean) => void): () => void {
60
- return this.bus.on('site:loading:changed', listener);
61
- }
62
-
63
- setSiteLoading(loading: boolean) {
64
- this.bus.emit('site:loading:changed', loading);
65
- }
66
-
67
- fetch: Fetcher = cfApiFetcher;
68
-
69
- static getInstance(): CoreService {
70
- if (!CoreService.instance) {
71
- CoreService.instance = new CoreService();
72
- }
73
- return CoreService.instance;
74
- }
75
- }
@@ -1,64 +0,0 @@
1
- import { createUIService } from '#/core/shared-service/factory/createUIService';
2
- import { createEventBus } from '#/core/utils/eventBus';
3
- import {
4
- ISystemUIService,
5
- SystemDataHookPoint,
6
- SystemSlotName,
7
- } from '#/core/shared-service/contract/IUIService';
8
- import { IPluginEntry, PluginID } from '#/types/plugin';
9
-
10
- const baseService = createUIService<SystemSlotName, SystemDataHookPoint>('system');
11
-
12
- export class SystemUIService implements ISystemUIService {
13
- private static instance: SystemUIService;
14
-
15
- private pluginEntries = new Map<string, IPluginEntry & { pluginId: PluginID }>();
16
-
17
- private entryBus = createEventBus<{ pluginEntriesChanged: void }>();
18
-
19
- private constructor() {}
20
-
21
- static getInstance(): SystemUIService {
22
- if (!SystemUIService.instance) {
23
- SystemUIService.instance = new SystemUIService();
24
- }
25
- return SystemUIService.instance;
26
- }
27
-
28
- registerSlot = baseService.registerSlot.bind(baseService);
29
- registerMiddleware = baseService.registerMiddleware.bind(baseService);
30
- getSlotEntries = baseService.getSlotEntries.bind(baseService);
31
- getComponents = baseService.getComponents.bind(baseService);
32
- subscribeSlotChange = baseService.subscribeSlotChange.bind(baseService);
33
- subscribeMiddlewareChange = baseService.subscribeMiddlewareChange.bind(baseService);
34
- runMiddlewares = baseService.runMiddlewares.bind(baseService);
35
-
36
- registerPluginEntry: (entry: IPluginEntry, id: PluginID) => void = (entry, id) => {
37
- this.pluginEntries.set(entry.path, { ...entry, pluginId: id });
38
- this.entryBus.emit('pluginEntriesChanged', undefined);
39
- };
40
-
41
- getPluginEntries = (): Array<IPluginEntry & { pluginId: PluginID }> => {
42
- return Array.from(this.pluginEntries.values());
43
- };
44
-
45
- subscribePluginEntryChange = (listener: () => void): (() => void) => {
46
- return this.entryBus.on('pluginEntriesChanged', listener);
47
- };
48
-
49
- unregisterAllByPluginId: (pluginId: string) => void = pluginId => {
50
- baseService.unregisterAllByPluginId(pluginId);
51
-
52
- let changed = false;
53
- this.pluginEntries.forEach((entry, path) => {
54
- if (entry.pluginId === pluginId) {
55
- this.pluginEntries.delete(path);
56
- changed = true;
57
- }
58
- });
59
-
60
- if (changed) {
61
- this.entryBus.emit('pluginEntriesChanged', undefined);
62
- }
63
- };
64
- }
@@ -1,28 +0,0 @@
1
- import { Fetcher } from 'swr';
2
- import { NavigateFunction } from 'react-router-dom';
3
-
4
- import { FingerprintData } from '#/app/utils/fingerprints';
5
- import { PluginID } from '#/types/plugin';
6
-
7
- declare module '#/core/shared-service/service-registry' {
8
- interface ServiceIdentifierMap {
9
- 'core:baseService': ICoreService;
10
- }
11
- }
12
-
13
- export interface ICoreService {
14
- getVersionHash(): Promise<string> | string;
15
- getDeviceId(): Promise<{ id: string; fp: FingerprintData }>;
16
-
17
- setLoading(id: string, loading: boolean): void;
18
- subscribeLoadingChange(listener: (payload: boolean) => void): () => void;
19
-
20
- subscribePluginUninstall(listener: (payload: PluginID) => void): () => void;
21
- notifyPluginUninstall(id: PluginID): void;
22
-
23
- injectNavigate: (nav: NavigateFunction) => void;
24
-
25
- open: (url: string, options?: { newTab?: boolean }) => void;
26
-
27
- fetch: Fetcher;
28
- }
@@ -1,53 +0,0 @@
1
- import type React from 'react';
2
-
3
- import type { ISlotEntry } from '#/core/plugin-system/registry';
4
- import { IPluginEntry, PluginID } from '#/types/plugin';
5
- import { IComPropsRegisteredToSlot } from '#/types/slots';
6
-
7
- declare module '#/core/shared-service/service-registry' {
8
- interface ServiceIdentifierMap {
9
- 'core:uiService': ISystemUIService;
10
- }
11
- }
12
-
13
- export interface IBaseUIService<T extends string, K extends string> {
14
- registerMiddleware: <S>(
15
- hookPoint: K,
16
- fn: (data: S) => Promise<S> | S,
17
- pluginId: PluginID,
18
- weight?: number
19
- ) => void;
20
-
21
- registerSlot: (
22
- slotName: T,
23
- component: React.ComponentType<IComPropsRegisteredToSlot>,
24
- pluginId: PluginID,
25
- weight?: number
26
- ) => void;
27
-
28
- unregisterAllByPluginId(pluginId: string): void;
29
-
30
- getSlotEntries(slotName: T): ISlotEntry[];
31
-
32
- getComponents(slotName: T): React.ComponentType<IComPropsRegisteredToSlot>[];
33
-
34
- subscribeSlotChange(listener: () => void): () => void;
35
-
36
- subscribeMiddlewareChange(listener: (point: K) => void): () => void;
37
-
38
- runMiddlewares: <S>(point: K, data: S) => Promise<S>;
39
- }
40
-
41
- export type SystemSlotName =
42
- | 'leftCol'
43
- | 'rightCol'
44
- | 'logo'
45
- | 'pageFooter'
46
- | 'nav-right'
47
- | 'centerEntryArea';
48
-
49
- export type SystemDataHookPoint = 'transformBreadcrumbPath' | 'transformEntryLink';
50
-
51
- export interface ISystemUIService extends IBaseUIService<SystemSlotName, SystemDataHookPoint> {
52
- registerPluginEntry: (entry: IPluginEntry, id: PluginID) => void;
53
- }