@bbki.ng/site 5.8.8 → 5.8.10
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.
- package/CHANGELOG.md +14 -0
- package/package.json +2 -2
- package/src/core/hooks/use_plugins.ts +4 -0
- package/src/core/plugin-system/bbplugin.ts +1 -0
- package/src/core/plugin-system/pluginManager.ts +6 -1
- package/src/core/plugin-system/pluginStore.ts +5 -2
- package/src/core/plugin-system/services/coreService.ts +19 -0
- package/src/core/shared-service/contract/ICoreService.ts +5 -0
- package/src/core/shared-service/service-proxy.ts +3 -1
- package/src/plugins/blog/components/BlogLink.tsx +11 -0
- package/src/plugins/blog/index.ts +13 -0
- package/src/plugins/fx/components/index.tsx +10 -4
- package/src/plugins/fx/hooks/useTextEffects.ts +39 -0
- package/src/plugins/fx/index.ts +11 -0
- package/src/plugins/fx/services/FxService.ts +47 -0
- package/src/plugins/fx/services/IFxService.ts +15 -0
- package/src/plugins/notification/components/index.tsx +4 -0
- package/src/plugins/notification/services/INotificationService.ts +9 -4
- package/src/plugins/notification/services/NotificationService.ts +1 -0
- package/src/plugins/now/components/NowLink.tsx +7 -0
- package/src/plugins/now/index.ts +16 -0
- package/src/plugins/sticker/components/StickerCom.tsx +4 -4
- package/src/plugins/sticker/index.ts +1 -1
- package/src/plugins/store/components/storePage.tsx +4 -6
- package/src/plugins/store/context/index.ts +1 -1
- package/src/plugins/xwy/components/XwyLink.tsx +7 -0
- package/src/plugins/xwy/index.ts +16 -0
- package/src/types/plugin.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @bbki.ng/site
|
|
2
2
|
|
|
3
|
+
## 5.8.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 28580cc: update manual install prompt
|
|
8
|
+
|
|
9
|
+
## 5.8.9
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 1485cfd: update sticker
|
|
14
|
+
- Updated dependencies [1485cfd]
|
|
15
|
+
- @bbki.ng/ui@0.2.21
|
|
16
|
+
|
|
3
17
|
## 5.8.8
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bbki.ng/site",
|
|
3
|
-
"version": "5.8.
|
|
3
|
+
"version": "5.8.10",
|
|
4
4
|
"description": "code behind bbki.ng",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"react-router-dom": "6",
|
|
16
16
|
"sonner": "^2.0.7",
|
|
17
17
|
"swr": "^2.2.5",
|
|
18
|
-
"@bbki.ng/ui": "0.2.
|
|
18
|
+
"@bbki.ng/ui": "0.2.21"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@eslint/compat": "^1.0.0",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { useNavigate } from 'react-router-dom';
|
|
2
3
|
|
|
3
4
|
import { useGlobalLoading } from '#/app/hooks/use_global_loading';
|
|
4
5
|
import { pluginManager } from '#/core/plugin-system/pluginManager';
|
|
@@ -52,6 +53,9 @@ export const usePlugins = () => {
|
|
|
52
53
|
|
|
53
54
|
usePluginsLoading();
|
|
54
55
|
|
|
56
|
+
const nav = useNavigate();
|
|
57
|
+
CoreService.getInstance().injectNavigate(nav);
|
|
58
|
+
|
|
55
59
|
useEffect(() => {
|
|
56
60
|
const unregister = setGlobalLoading('plugins', !done);
|
|
57
61
|
|
|
@@ -8,6 +8,7 @@ export class BBPlugin implements IPlugin {
|
|
|
8
8
|
onInstall?: ((ctx: IHostContext) => void | Promise<void>) | undefined;
|
|
9
9
|
onDisable?: (() => Promise<void> | void) | undefined;
|
|
10
10
|
onDestroy?: (() => void) | undefined;
|
|
11
|
+
onManualInstall?: (() => void) | undefined;
|
|
11
12
|
getMeta(): IPluginManifestEntry {
|
|
12
13
|
return PluginManifestService.getInstance().getPlugin(this.id) as IPluginManifestEntry;
|
|
13
14
|
}
|
|
@@ -43,7 +43,7 @@ class PluginManager {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// enable abort ctrl
|
|
46
|
-
async loadPlugin(pluginId: PluginID) {
|
|
46
|
+
async loadPlugin(pluginId: PluginID): Promise<IPlugin | undefined> {
|
|
47
47
|
if (this.activePlugins.has(pluginId)) {
|
|
48
48
|
console.warn(`Plugin ${pluginId} is already loaded.`);
|
|
49
49
|
return;
|
|
@@ -88,6 +88,7 @@ class PluginManager {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
this.activePlugins.set(pluginId, p);
|
|
91
|
+
return p;
|
|
91
92
|
} catch (error) {
|
|
92
93
|
console.error(`Failed to load plugin ${pluginId}:`, error);
|
|
93
94
|
} finally {
|
|
@@ -96,6 +97,10 @@ class PluginManager {
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
getPlugin(pluginId: PluginID): IPlugin | undefined {
|
|
101
|
+
return this.activePlugins.get(pluginId);
|
|
102
|
+
}
|
|
103
|
+
|
|
99
104
|
async disablePlugin(pluginId: PluginID) {
|
|
100
105
|
const plugin = this.activePlugins.get(pluginId);
|
|
101
106
|
if (!plugin) {
|
|
@@ -164,7 +164,7 @@ export class PluginStore {
|
|
|
164
164
|
};
|
|
165
165
|
};
|
|
166
166
|
|
|
167
|
-
installPlugin: (id: PluginID) => Promise<boolean> = async id => {
|
|
167
|
+
installPlugin: (id: PluginID, manual?: boolean) => Promise<boolean> = async (id, manual) => {
|
|
168
168
|
if (!this.checkDep(id)) {
|
|
169
169
|
// throw new Error(`Cannot install plugin ${id} due to missing dependencies`);
|
|
170
170
|
console.warn(`Cannot install plugin ${id} due to missing dependencies`);
|
|
@@ -172,7 +172,10 @@ export class PluginStore {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
try {
|
|
175
|
-
await pluginManager.loadPlugin(id);
|
|
175
|
+
const plugin = await pluginManager.loadPlugin(id);
|
|
176
|
+
if (manual && plugin?.onManualInstall) {
|
|
177
|
+
plugin.onManualInstall();
|
|
178
|
+
}
|
|
176
179
|
this.installedSet.add(id);
|
|
177
180
|
this.stringify();
|
|
178
181
|
return true;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Fetcher } from 'swr';
|
|
2
|
+
import { NavigateFunction } from 'react-router-dom';
|
|
2
3
|
|
|
3
4
|
import { getStableDeviceId } from '#/app/utils/fingerprints';
|
|
4
5
|
import { cfApiFetcher } from '#/app/utils';
|
|
@@ -13,9 +14,27 @@ export class CoreService implements ICoreService {
|
|
|
13
14
|
private constructor() {}
|
|
14
15
|
|
|
15
16
|
private bus = createEventBus<PluginEvents>();
|
|
17
|
+
private navigate?: NavigateFunction;
|
|
16
18
|
|
|
17
19
|
getDeviceId = getStableDeviceId;
|
|
18
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
|
+
|
|
19
38
|
getVersionHash() {
|
|
20
39
|
const hashStr: string = typeof GLOBAL_COMMIT_HASH === 'string' ? GLOBAL_COMMIT_HASH : '0000000';
|
|
21
40
|
return hashStr;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Fetcher } from 'swr';
|
|
2
|
+
import { NavigateFunction } from 'react-router-dom';
|
|
2
3
|
|
|
3
4
|
import { FingerprintData } from '#/app/utils/fingerprints';
|
|
4
5
|
import { PluginID } from '#/types/plugin';
|
|
@@ -19,5 +20,9 @@ export interface ICoreService {
|
|
|
19
20
|
subscribePluginUninstall(listener: (payload: PluginID) => void): () => void;
|
|
20
21
|
notifyPluginUninstall(id: PluginID): void;
|
|
21
22
|
|
|
23
|
+
injectNavigate: (nav: NavigateFunction) => void;
|
|
24
|
+
|
|
25
|
+
open: (url: string, options?: { newTab?: boolean }) => void;
|
|
26
|
+
|
|
22
27
|
fetch: Fetcher;
|
|
23
28
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ServiceIdentifierMap, ServiceRegistry } from '#/core/shared-service/service-registry';
|
|
2
2
|
|
|
3
|
+
const empty = {};
|
|
4
|
+
|
|
3
5
|
// core/ServiceProxy.ts
|
|
4
6
|
export function createServiceProxy<T extends object, K extends keyof ServiceIdentifierMap>(
|
|
5
7
|
serviceId: K,
|
|
@@ -14,7 +16,7 @@ export function createServiceProxy<T extends object, K extends keyof ServiceIden
|
|
|
14
16
|
console.warn(
|
|
15
17
|
`[System] Service ${serviceId} is currently unavailable. Call to ${String(prop)} ignored.`
|
|
16
18
|
);
|
|
17
|
-
return
|
|
19
|
+
return empty;
|
|
18
20
|
};
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -5,6 +5,7 @@ import { IHostContext } from '#/types/hostApi';
|
|
|
5
5
|
import { PluginID } from '#/types/plugin';
|
|
6
6
|
|
|
7
7
|
import { BlogPageApp } from './components/app';
|
|
8
|
+
import { BlogLink } from './components/BlogLink';
|
|
8
9
|
import { BlogContext } from './context';
|
|
9
10
|
import { BlogUIService } from './services/BlogUIService';
|
|
10
11
|
|
|
@@ -51,6 +52,18 @@ export class BlogPlugin extends BBPlugin {
|
|
|
51
52
|
);
|
|
52
53
|
};
|
|
53
54
|
|
|
55
|
+
override onManualInstall = () => {
|
|
56
|
+
this.promptToOpen();
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
private promptToOpen = () => {
|
|
60
|
+
const notificationService = this._serviceRegistry?.get('notification');
|
|
61
|
+
notificationService?.notify({
|
|
62
|
+
message: '安装成功.',
|
|
63
|
+
action: BlogLink,
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
54
67
|
override onDestroy?: (() => void) | undefined = () => {
|
|
55
68
|
BlogUIService.getInstance().unregisterAllByPluginId(this.id);
|
|
56
69
|
this._serviceRegistry?.unregister('blog:uiService');
|
|
@@ -4,6 +4,7 @@ import { EffectLayer, grain, paper, spiral, watermark, Effect } from '@bbki.ng/u
|
|
|
4
4
|
import { IComPropsRegisteredToSlot } from '#/types/slots';
|
|
5
5
|
|
|
6
6
|
import { FxContext } from '../context';
|
|
7
|
+
import { useTextEffects } from '../hooks/useTextEffects';
|
|
7
8
|
|
|
8
9
|
const useLoadingState = () => {
|
|
9
10
|
const ctx = FxContext.useCtx();
|
|
@@ -25,15 +26,20 @@ export const FxCom = (_: IComPropsRegisteredToSlot) => {
|
|
|
25
26
|
const deviceId = ctx.deviceId;
|
|
26
27
|
const isLoading = useLoadingState();
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
const textEffects = useTextEffects();
|
|
29
30
|
|
|
30
31
|
const effects: Effect[] = useMemo(() => {
|
|
31
32
|
const wmLines = [hashStr];
|
|
32
33
|
if (deviceId) wmLines.push(deviceId);
|
|
33
|
-
wmLines.push('hello world');
|
|
34
34
|
|
|
35
|
-
return [
|
|
36
|
-
|
|
35
|
+
return [
|
|
36
|
+
grain(),
|
|
37
|
+
paper(),
|
|
38
|
+
spiral({ active: isLoading }),
|
|
39
|
+
watermark({ lines: wmLines }),
|
|
40
|
+
...textEffects,
|
|
41
|
+
];
|
|
42
|
+
}, [isLoading, deviceId, hashStr, textEffects]);
|
|
37
43
|
|
|
38
44
|
return <EffectLayer effects={effects} />;
|
|
39
45
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { drawText } from '@bbki.ng/ui';
|
|
3
|
+
|
|
4
|
+
import { DrawTextConfig } from '../services/IFxService';
|
|
5
|
+
import { FxService } from '../services/FxService';
|
|
6
|
+
|
|
7
|
+
const empty = {};
|
|
8
|
+
|
|
9
|
+
export const useTextEffects = () => {
|
|
10
|
+
const fxServiceInst = FxService.getInstance();
|
|
11
|
+
const [fxMap, setFxMap] = useState<Record<string, DrawTextConfig>>(empty);
|
|
12
|
+
const [v, setVersion] = useState(0); // 用于强制更新组件
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const drawTextUnsub = fxServiceInst.subscribeDrawText(config => {
|
|
16
|
+
setFxMap(prev => ({ ...prev, [config.id]: config }));
|
|
17
|
+
setVersion(v => v + 1); // 强制更新组件以应用新的文本效果
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const clearTextUnsub = fxServiceInst.subscribeClearText(id => {
|
|
21
|
+
setFxMap(prev => {
|
|
22
|
+
const newMap = { ...prev };
|
|
23
|
+
delete newMap[id];
|
|
24
|
+
return newMap;
|
|
25
|
+
});
|
|
26
|
+
setVersion(v => v + 1); // 强制更新组件以移除文本效果
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return () => {
|
|
30
|
+
drawTextUnsub();
|
|
31
|
+
clearTextUnsub();
|
|
32
|
+
};
|
|
33
|
+
}, [fxServiceInst]);
|
|
34
|
+
|
|
35
|
+
return useMemo(() => {
|
|
36
|
+
console.log("fx text's snapshot version:", v);
|
|
37
|
+
return Object.values(fxMap).map(drawText);
|
|
38
|
+
}, [fxMap, v]);
|
|
39
|
+
};
|
package/src/plugins/fx/index.ts
CHANGED
|
@@ -4,11 +4,16 @@ import { PluginID } from '#/types/plugin';
|
|
|
4
4
|
|
|
5
5
|
import { FxCom } from './components';
|
|
6
6
|
import { FxContext } from './context';
|
|
7
|
+
import { FxService } from './services/FxService';
|
|
7
8
|
|
|
8
9
|
class FxPlugin extends BBPlugin {
|
|
9
10
|
id: PluginID = 'fx';
|
|
10
11
|
|
|
12
|
+
private _ctx: IHostContext | null = null;
|
|
13
|
+
|
|
11
14
|
override onInstall = async (ctx: IHostContext) => {
|
|
15
|
+
this._ctx = ctx;
|
|
16
|
+
|
|
12
17
|
const coreService = ctx.service.get('core:baseService');
|
|
13
18
|
|
|
14
19
|
if (!coreService) {
|
|
@@ -22,6 +27,8 @@ class FxPlugin extends BBPlugin {
|
|
|
22
27
|
return;
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
ctx.service.register('fx:service', FxService.getInstance());
|
|
31
|
+
|
|
25
32
|
systemUIService.registerSlot(
|
|
26
33
|
'pageFooter',
|
|
27
34
|
FxContext.withCtx(
|
|
@@ -37,6 +44,10 @@ class FxPlugin extends BBPlugin {
|
|
|
37
44
|
this.id
|
|
38
45
|
);
|
|
39
46
|
};
|
|
47
|
+
|
|
48
|
+
override onDestroy?: (() => void) | undefined = () => {
|
|
49
|
+
this._ctx?.service.unregister('fx:service');
|
|
50
|
+
};
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
export default new FxPlugin();
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createEventBus } from '#/core/utils/eventBus';
|
|
2
|
+
|
|
3
|
+
import { DrawTextConfig, IFxService } from './IFxService';
|
|
4
|
+
|
|
5
|
+
export type DrawTextEvent = {
|
|
6
|
+
'fx:drawText': DrawTextConfig & { id: string };
|
|
7
|
+
'fx:clearText': string; // id of the text to clear
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class FxService implements IFxService {
|
|
11
|
+
private bus = createEventBus<DrawTextEvent>();
|
|
12
|
+
|
|
13
|
+
private configs: Array<DrawTextConfig & { id: string }> = [];
|
|
14
|
+
|
|
15
|
+
drawText: (c: DrawTextConfig) => () => void = (opts: DrawTextConfig) => {
|
|
16
|
+
const id = `${Date.now()}-${Math.random()}`;
|
|
17
|
+
|
|
18
|
+
const fullConfig = { ...opts, id };
|
|
19
|
+
|
|
20
|
+
this.configs.push(fullConfig);
|
|
21
|
+
|
|
22
|
+
this.bus.emit('fx:drawText', fullConfig);
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
25
|
+
this.configs = this.configs.filter(c => c.id !== id);
|
|
26
|
+
// Emit an empty config to signal clearing the text
|
|
27
|
+
this.bus.emit('fx:clearText', id);
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
subscribeDrawText(listener: (payload: DrawTextEvent['fx:drawText']) => void) {
|
|
32
|
+
return this.bus.on('fx:drawText', listener);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
subscribeClearText(listener: (payload: DrawTextEvent['fx:clearText']) => void) {
|
|
36
|
+
return this.bus.on('fx:clearText', listener);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private static instance: FxService | null = null;
|
|
40
|
+
|
|
41
|
+
static getInstance(): FxService {
|
|
42
|
+
if (!FxService.instance) {
|
|
43
|
+
FxService.instance = new FxService();
|
|
44
|
+
}
|
|
45
|
+
return FxService.instance;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DrawTextEffect } from '@bbki.ng/ui';
|
|
2
|
+
|
|
3
|
+
declare module '#/core/shared-service/service-registry' {
|
|
4
|
+
interface ServiceIdentifierMap {
|
|
5
|
+
'fx:service': IFxService;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type DrawTextConfig = Omit<DrawTextEffect, 'clear' | 'type'>;
|
|
10
|
+
|
|
11
|
+
export interface IFxService {
|
|
12
|
+
drawText: (opts: DrawTextConfig) => () => void;
|
|
13
|
+
subscribeDrawText: (listener: (payload: DrawTextConfig & { id: string }) => void) => () => void;
|
|
14
|
+
subscribeClearText: (listener: (payload: string) => void) => () => void;
|
|
15
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { ToastT } from 'sonner';
|
|
3
|
+
|
|
1
4
|
declare module '#/core/shared-service/service-registry' {
|
|
2
5
|
interface ServiceIdentifierMap {
|
|
3
6
|
notification: INotificationService;
|
|
@@ -6,10 +9,12 @@ declare module '#/core/shared-service/service-registry' {
|
|
|
6
9
|
|
|
7
10
|
export type NotificationType = 'toast' | 'banner' | 'modal';
|
|
8
11
|
|
|
9
|
-
export interface INotificationOptions
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
export interface INotificationOptions extends Omit<
|
|
13
|
+
ToastT,
|
|
14
|
+
'message' | 'id' | 'type' | 'title' | 'jsx' | 'delete' | 'promise'
|
|
15
|
+
> {
|
|
16
|
+
uiType?: NotificationType;
|
|
17
|
+
message: (() => React.ReactNode) | React.ReactNode;
|
|
13
18
|
duration?: number; // 持续时间,单位为毫秒,默认为4000ms
|
|
14
19
|
}
|
|
15
20
|
|
package/src/plugins/now/index.ts
CHANGED
|
@@ -3,13 +3,17 @@ import { IHostContext } from '#/types/hostApi';
|
|
|
3
3
|
import { PluginID } from '#/types/plugin';
|
|
4
4
|
|
|
5
5
|
import { pageNow } from './components';
|
|
6
|
+
import { NowLink } from './components/NowLink';
|
|
6
7
|
import { NowCtx } from './context';
|
|
7
8
|
|
|
8
9
|
export class NowPlugin extends BBPlugin {
|
|
9
10
|
id: PluginID = 'now';
|
|
10
11
|
|
|
12
|
+
private _serviceRegistry?: IHostContext['service'];
|
|
13
|
+
|
|
11
14
|
override onInstall = async (ctx: IHostContext): Promise<void> => {
|
|
12
15
|
const systemUIService = ctx.service.get('core:uiService');
|
|
16
|
+
this._serviceRegistry = ctx.service;
|
|
13
17
|
if (!systemUIService) {
|
|
14
18
|
console.warn(`[${this.id}] core:uiService not found, cannot register entry`);
|
|
15
19
|
return;
|
|
@@ -41,6 +45,18 @@ export class NowPlugin extends BBPlugin {
|
|
|
41
45
|
this.id
|
|
42
46
|
);
|
|
43
47
|
};
|
|
48
|
+
|
|
49
|
+
override onManualInstall = () => {
|
|
50
|
+
this.promptToOpen();
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
private promptToOpen = () => {
|
|
54
|
+
const notificationService = this._serviceRegistry?.get('notification');
|
|
55
|
+
notificationService?.notify({
|
|
56
|
+
message: '安装成功.',
|
|
57
|
+
action: NowLink,
|
|
58
|
+
});
|
|
59
|
+
};
|
|
44
60
|
}
|
|
45
61
|
|
|
46
62
|
export default new NowPlugin();
|
|
@@ -12,11 +12,11 @@ export const StickerCom = ({ data }: IComPropsRegisteredToSlot) => {
|
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const lastPath = paths[paths.length - 1];
|
|
15
|
+
// const lastPath = paths[paths.length - 1];
|
|
16
16
|
|
|
17
|
-
if (lastPath.name !== '~') {
|
|
18
|
-
|
|
19
|
-
}
|
|
17
|
+
// if (lastPath.name !== '~') {
|
|
18
|
+
// return null;
|
|
19
|
+
// }
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
22
|
<div className="fixed bottom-32 left-16">
|
|
@@ -77,18 +77,16 @@ export const StorePage = (_: IComPropsRegisteredToSlot) => {
|
|
|
77
77
|
setError(null);
|
|
78
78
|
|
|
79
79
|
try {
|
|
80
|
-
const success = await install(id);
|
|
80
|
+
const success = await install(id, true);
|
|
81
81
|
if (success) {
|
|
82
82
|
await refreshList();
|
|
83
83
|
} else {
|
|
84
84
|
notificationService.notify({
|
|
85
|
-
level: 'error',
|
|
86
85
|
message: `安装插件失败,依赖缺失或其他错误`,
|
|
87
86
|
});
|
|
88
87
|
}
|
|
89
88
|
} catch (err) {
|
|
90
89
|
notificationService.notify({
|
|
91
|
-
level: 'error',
|
|
92
90
|
message: `安装插件失败: ${err instanceof Error ? err.message : String(err)}`,
|
|
93
91
|
});
|
|
94
92
|
} finally {
|
|
@@ -118,9 +116,9 @@ export const StorePage = (_: IComPropsRegisteredToSlot) => {
|
|
|
118
116
|
const headerRenderer = useCallback(() => {
|
|
119
117
|
return (
|
|
120
118
|
<>
|
|
121
|
-
<Table.HCell
|
|
122
|
-
<Table.HCell style={{ width: 'unset', maxWidth: 'unset' }}
|
|
123
|
-
<Table.HCell style={{ textAlign: 'right' }}
|
|
119
|
+
<Table.HCell>功能清单</Table.HCell>
|
|
120
|
+
<Table.HCell style={{ width: 'unset', maxWidth: 'unset' }}> </Table.HCell>
|
|
121
|
+
<Table.HCell style={{ textAlign: 'right' }}> </Table.HCell>
|
|
124
122
|
</>
|
|
125
123
|
);
|
|
126
124
|
}, []);
|
|
@@ -3,7 +3,7 @@ import { NotificationService } from '#/plugins/notification/services/Notificatio
|
|
|
3
3
|
import { IPluginStoreEntry, PluginID } from '#/types/plugin';
|
|
4
4
|
|
|
5
5
|
export interface IStoreCtx {
|
|
6
|
-
install: (pid: PluginID) => Promise<boolean>;
|
|
6
|
+
install: (pid: PluginID, manual?: boolean) => Promise<boolean>;
|
|
7
7
|
uninstall: (pid: PluginID) => Promise<void>;
|
|
8
8
|
isInstalled: (pid: PluginID) => boolean;
|
|
9
9
|
list: () => Promise<Array<IPluginStoreEntry>> | Array<IPluginStoreEntry>;
|
package/src/plugins/xwy/index.ts
CHANGED
|
@@ -12,14 +12,18 @@ import {
|
|
|
12
12
|
transformPostContent,
|
|
13
13
|
pinTitle,
|
|
14
14
|
} from './transformers';
|
|
15
|
+
import { XwyLink } from './components/XwyLink';
|
|
15
16
|
|
|
16
17
|
class XwyPlugin extends BBPlugin {
|
|
17
18
|
id: PluginID = 'xwy';
|
|
18
19
|
|
|
19
20
|
private loadedFonts = new Set<string>();
|
|
20
21
|
|
|
22
|
+
private _serviceRegistry?: IHostContext['service'];
|
|
23
|
+
|
|
21
24
|
override onInstall = (ctx: IHostContext) => {
|
|
22
25
|
// add font loading listener
|
|
26
|
+
this._serviceRegistry = ctx.service;
|
|
23
27
|
this.initFontLoadingListener();
|
|
24
28
|
|
|
25
29
|
// 加载所有需要的字体文件
|
|
@@ -64,6 +68,18 @@ class XwyPlugin extends BBPlugin {
|
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
70
|
|
|
71
|
+
override onManualInstall = () => {
|
|
72
|
+
this.promptToOpen();
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
private promptToOpen = () => {
|
|
76
|
+
const notificationService = this._serviceRegistry?.get('notification');
|
|
77
|
+
notificationService?.notify({
|
|
78
|
+
message: '安装成功.',
|
|
79
|
+
action: XwyLink,
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
67
83
|
private initFontLoadingListener() {
|
|
68
84
|
// listen font loading status and add class to body for styling
|
|
69
85
|
console.log('Initializing font loading listener');
|
package/src/types/plugin.ts
CHANGED