@bbki.ng/site 1.8.2 → 1.8.3
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 +2 -0
- package/package.json +2 -2
- package/src/blog/app.tsx +1 -2
- package/src/blog/components/article/index.tsx +24 -5
- package/src/blog/components/plugin/PluginInit.tsx +6 -0
- package/src/blog/components/plugin/PluginMenuItem.tsx +5 -2
- package/src/blog/components/plugin/hooks/useDependencies.ts +13 -0
- package/src/blog/components/plugin/hooks/usePluginOutput.tsx +1 -1
- package/src/blog/components/plugin/pluginUI/PluginUI.tsx +34 -0
- package/src/blog/hooks/use_font_loading.ts +1 -1
- package/src/blog/pages/extensions/txt/article.tsx +0 -1
- package/src/blog/plugin/Dependencies.ts +1 -0
- package/src/blog/plugin/Plugin.ts +4 -1
- package/src/blog/plugin/PluginManager.ts +22 -3
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bbki.ng/site",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.3",
|
|
4
4
|
"description": "code behind bbki.ng",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@extism/extism": "2.0.0-rc11",
|
|
20
|
-
"@bbki.ng/components": "workspace:2.6.
|
|
20
|
+
"@bbki.ng/components": "workspace:2.6.2",
|
|
21
21
|
"@supabase/supabase-js": "^1.35.4",
|
|
22
22
|
"classnames": "2.3.1",
|
|
23
23
|
"react": "^18.0.0",
|
package/src/blog/app.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useContext } from "react";
|
|
2
2
|
import { Outlet, Route, Routes } from "react-router-dom";
|
|
3
|
-
import { Nav, NotFound, Page
|
|
3
|
+
import { Nav, NotFound, Page } from "@bbki.ng/components";
|
|
4
4
|
import { HotKeyNav } from "./components";
|
|
5
5
|
import { threeColWrapper } from "@/components/with_wrapper";
|
|
6
6
|
import { Cover } from "./pages";
|
|
@@ -48,7 +48,6 @@ const Layout = () => {
|
|
|
48
48
|
}
|
|
49
49
|
main={<Outlet />}
|
|
50
50
|
/>
|
|
51
|
-
<BlurCover status={isFontLoading ? "show" : "silent"} />
|
|
52
51
|
</>
|
|
53
52
|
);
|
|
54
53
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React, { ReactElement } from "react";
|
|
1
|
+
import React, { ReactElement, useContext, useEffect } from "react";
|
|
2
2
|
import { Tags, Article } from "@bbki.ng/components";
|
|
3
3
|
import { ROUTES } from "@/constants";
|
|
4
|
-
import { DelayFadeIn } from "@/components/DelayFadeIn/DelayFadeIn";
|
|
5
4
|
import classNames from "classnames";
|
|
5
|
+
import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
|
|
6
6
|
|
|
7
7
|
export type ArticlePageProps = {
|
|
8
8
|
tags?: string[];
|
|
@@ -13,8 +13,26 @@ export type ArticlePageProps = {
|
|
|
13
13
|
children: ReactElement;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
const useSafeArticleLoading = (safeSec: number) => {
|
|
17
|
+
const { isLoading, isFontLoading } = useContext(GlobalLoadingContext);
|
|
18
|
+
const [isArticleLoading, setIsArticleLoading] = React.useState(true);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const id = setTimeout(() => {
|
|
22
|
+
setIsArticleLoading(false);
|
|
23
|
+
}, safeSec * 1000);
|
|
24
|
+
|
|
25
|
+
return () => {
|
|
26
|
+
clearTimeout(id);
|
|
27
|
+
};
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
return isLoading || isFontLoading || isArticleLoading;
|
|
31
|
+
};
|
|
32
|
+
|
|
16
33
|
export const ArticlePage = (props: ArticlePageProps) => {
|
|
17
34
|
const { tags: tagNames, title, description, headless } = props;
|
|
35
|
+
const loading = useSafeArticleLoading(0.2);
|
|
18
36
|
const tags = tagNames
|
|
19
37
|
? tagNames.map((t) => ({ children: t, to: `${ROUTES.TAGS}/${t}` }))
|
|
20
38
|
: [];
|
|
@@ -28,15 +46,16 @@ export const ArticlePage = (props: ArticlePageProps) => {
|
|
|
28
46
|
});
|
|
29
47
|
|
|
30
48
|
return (
|
|
31
|
-
|
|
49
|
+
<>
|
|
32
50
|
<Article
|
|
33
51
|
title={title}
|
|
34
52
|
description={description}
|
|
35
53
|
className={props.className}
|
|
54
|
+
loading={loading}
|
|
36
55
|
>
|
|
37
56
|
<article className={articleCls}>{props.children}</article>
|
|
38
57
|
</Article>
|
|
39
|
-
{tagNames && <Tags tags={tags} />}
|
|
40
|
-
|
|
58
|
+
<span className="p-16">{tagNames && <Tags tags={tags} />}</span>
|
|
59
|
+
</>
|
|
41
60
|
);
|
|
42
61
|
};
|
|
@@ -3,6 +3,7 @@ import { ReactNode } from "react";
|
|
|
3
3
|
import { PluginInputForm } from "@/components/plugin/PluginInputForm";
|
|
4
4
|
import { useDependencies } from "@/components/plugin/hooks/useDependencies";
|
|
5
5
|
import { PluginManager } from "@/plugin/PluginManager";
|
|
6
|
+
import PluginUI from "./pluginUI/PluginUI";
|
|
6
7
|
|
|
7
8
|
export const PluginInit = (props: { children: ReactNode }) => {
|
|
8
9
|
const {
|
|
@@ -11,6 +12,8 @@ export const PluginInit = (props: { children: ReactNode }) => {
|
|
|
11
12
|
pluginInputFormConf,
|
|
12
13
|
formDataResolver,
|
|
13
14
|
|
|
15
|
+
pluginUIRef,
|
|
16
|
+
|
|
14
17
|
...dep
|
|
15
18
|
} = useDependencies();
|
|
16
19
|
|
|
@@ -45,6 +48,9 @@ export const PluginInit = (props: { children: ReactNode }) => {
|
|
|
45
48
|
input={pluginInputFormConf}
|
|
46
49
|
onSubmit={onSubmit}
|
|
47
50
|
/>
|
|
51
|
+
<PluginUI
|
|
52
|
+
ref={pluginUIRef}
|
|
53
|
+
/>
|
|
48
54
|
</>
|
|
49
55
|
);
|
|
50
56
|
};
|
|
@@ -19,8 +19,11 @@ export const PluginMenuItem = (props: PluginMenuItemProps) => {
|
|
|
19
19
|
const { plugin, onUninstall, onStop, onRun, onInstall } = props;
|
|
20
20
|
return (
|
|
21
21
|
<ContextMenuSub>
|
|
22
|
-
<ContextMenuSubTrigger
|
|
23
|
-
|
|
22
|
+
<ContextMenuSubTrigger>
|
|
23
|
+
<div className="flex justify-between w-full mr-16">
|
|
24
|
+
<span>{plugin.name}</span>
|
|
25
|
+
<span>v{plugin.version}</span>
|
|
26
|
+
</div>
|
|
24
27
|
</ContextMenuSubTrigger>
|
|
25
28
|
<ContextMenuSubContent className="w-48">
|
|
26
29
|
{plugin.status !== PluginStatus.Available && (
|
|
@@ -13,6 +13,10 @@ interface depHooksRes extends Dependencies {
|
|
|
13
13
|
isPluginFormInputOpen: boolean;
|
|
14
14
|
pluginInputFormConf: PluginInput;
|
|
15
15
|
formDataResolver: inputResolve;
|
|
16
|
+
pluginUIRef: React.MutableRefObject<{
|
|
17
|
+
open: boolean;
|
|
18
|
+
setHtml: (html: string) => void;
|
|
19
|
+
} | null>
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
export const useDependencies = (): depHooksRes => {
|
|
@@ -25,6 +29,8 @@ export const useDependencies = (): depHooksRes => {
|
|
|
25
29
|
|
|
26
30
|
const globalRouteCtx = useContext(GlobalRoutesContext);
|
|
27
31
|
|
|
32
|
+
const pluginUIRef = useRef<{ open: boolean; setHtml: (html: string) => void } | null>(null);
|
|
33
|
+
|
|
28
34
|
return {
|
|
29
35
|
callPlugin: (id, method) => {
|
|
30
36
|
if (!PluginManager.instance) {
|
|
@@ -48,6 +54,12 @@ export const useDependencies = (): depHooksRes => {
|
|
|
48
54
|
position: "bottom-right",
|
|
49
55
|
});
|
|
50
56
|
},
|
|
57
|
+
showUI: (html: string) => {
|
|
58
|
+
if (!pluginUIRef.current) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
pluginUIRef.current.setHtml(html);
|
|
62
|
+
},
|
|
51
63
|
showForm: async (input) => {
|
|
52
64
|
setOpen(true);
|
|
53
65
|
setInput(input);
|
|
@@ -55,6 +67,7 @@ export const useDependencies = (): depHooksRes => {
|
|
|
55
67
|
resolveRef.current = resolve;
|
|
56
68
|
});
|
|
57
69
|
},
|
|
70
|
+
pluginUIRef,
|
|
58
71
|
setPluginFormInputOpen: setOpen,
|
|
59
72
|
isPluginFormInputOpen: open,
|
|
60
73
|
pluginInputFormConf: input,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { useRef, useImperativeHandle, forwardRef } from "react"
|
|
2
|
+
import { PluginDrawer } from "../PluginDrawer"
|
|
3
|
+
|
|
4
|
+
export type PluginUIProps = {
|
|
5
|
+
html?: string,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const PluginUI = (props: PluginUIProps, ref: React.ForwardedRef<{ setHtml: (html: string) => void }>) => {
|
|
9
|
+
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
10
|
+
const [open, setOpen] = React.useState(false);
|
|
11
|
+
const [html, setHtml] = React.useState(props.html);
|
|
12
|
+
|
|
13
|
+
useImperativeHandle(ref, () => ({
|
|
14
|
+
setHtml: (h) => {
|
|
15
|
+
setHtml(h);
|
|
16
|
+
setOpen(true);
|
|
17
|
+
},
|
|
18
|
+
}), []);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<PluginDrawer
|
|
22
|
+
open={open}
|
|
23
|
+
onOpenChange={setOpen}
|
|
24
|
+
>
|
|
25
|
+
<iframe
|
|
26
|
+
sandbox="allow-scripts allow-same-origin"
|
|
27
|
+
ref={iframeRef}
|
|
28
|
+
srcDoc={html}
|
|
29
|
+
/>
|
|
30
|
+
</PluginDrawer>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default forwardRef(PluginUI)
|
|
@@ -3,7 +3,7 @@ import { changeFont } from "@/utils";
|
|
|
3
3
|
import { FontType } from "@/types/font";
|
|
4
4
|
|
|
5
5
|
export const useFontLoading = () => {
|
|
6
|
-
const [isFontLoading, setIsFontLoading] = useState(
|
|
6
|
+
const [isFontLoading, setIsFontLoading] = useState(true);
|
|
7
7
|
|
|
8
8
|
const handleFontLoading = () => {
|
|
9
9
|
setIsFontLoading(true);
|
|
@@ -4,6 +4,7 @@ export interface Dependencies {
|
|
|
4
4
|
toast: (content: string) => void;
|
|
5
5
|
loading: (show: boolean) => void;
|
|
6
6
|
showForm: (input: PluginInput) => Promise<string>;
|
|
7
|
+
showUI: (html: string) => void;
|
|
7
8
|
addRoute: (name: string, to: string) => void;
|
|
8
9
|
removeRoute: (name: string) => void;
|
|
9
10
|
callPlugin: (id: number, method: string) => Promise<any>;
|
|
@@ -16,8 +16,10 @@ export type PluginConfig = {
|
|
|
16
16
|
description: string;
|
|
17
17
|
url: string;
|
|
18
18
|
status: PluginStatus;
|
|
19
|
+
|
|
19
20
|
inputs?: PluginInput;
|
|
20
21
|
route?: string;
|
|
22
|
+
builtIn?: boolean;
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
export enum PluginInputFieldType {
|
|
@@ -83,7 +85,8 @@ export class Plugin {
|
|
|
83
85
|
return JSON.parse(out.text());
|
|
84
86
|
} catch (e) {
|
|
85
87
|
this.config.status = PluginStatus.Stopped;
|
|
86
|
-
|
|
88
|
+
this.dependencies.loading(false);
|
|
89
|
+
return out?.text();
|
|
87
90
|
}
|
|
88
91
|
}
|
|
89
92
|
|
|
@@ -33,6 +33,8 @@ export class PluginManager {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
private async restoreInstalledPlugins() {
|
|
36
|
+
await Promise.all(this.listBuiltIn().map((p) => this.install(p.id)));
|
|
37
|
+
|
|
36
38
|
if (!this._info) {
|
|
37
39
|
return Promise.resolve();
|
|
38
40
|
}
|
|
@@ -61,7 +63,7 @@ export class PluginManager {
|
|
|
61
63
|
window.pm = PluginManager.instance;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
public async install(id: number) {
|
|
66
|
+
public async install(id: number, showToast?: boolean) {
|
|
65
67
|
const config = this.pluginConfigMap.get(id);
|
|
66
68
|
if (!config) {
|
|
67
69
|
this.dependencies.toast("Plugin not found");
|
|
@@ -71,7 +73,10 @@ export class PluginManager {
|
|
|
71
73
|
const plugin = new Plugin(config, this.dependencies);
|
|
72
74
|
await plugin.install();
|
|
73
75
|
this.plugins.set(id, plugin);
|
|
74
|
-
|
|
76
|
+
|
|
77
|
+
if (showToast) {
|
|
78
|
+
this.dependencies.toast("Plugin installed");
|
|
79
|
+
}
|
|
75
80
|
|
|
76
81
|
this.saveInfo();
|
|
77
82
|
}
|
|
@@ -96,7 +101,11 @@ export class PluginManager {
|
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
public listAvailable(): PluginConfig[] {
|
|
99
|
-
return Array.from(this.pluginConfigMap.values());
|
|
104
|
+
return Array.from(this.pluginConfigMap.values()).filter((p) => !p.builtIn);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public listBuiltIn(): PluginConfig[] {
|
|
108
|
+
return Array.from(this.pluginConfigMap.values()).filter((p) => p.builtIn);
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
public getPlugin(id: number) {
|
|
@@ -148,6 +157,16 @@ export class PluginManager {
|
|
|
148
157
|
route: "近况",
|
|
149
158
|
});
|
|
150
159
|
|
|
160
|
+
// this.pluginConfigMap.set(2, {
|
|
161
|
+
// name: "core",
|
|
162
|
+
// id: 2,
|
|
163
|
+
// version: "1.0.0",
|
|
164
|
+
// description: "core",
|
|
165
|
+
// url: "https://zjh-im-res.oss-cn-shenzhen.aliyuncs.com/plugins/reactable.core.wasm",
|
|
166
|
+
// status: 0,
|
|
167
|
+
// builtIn: true,
|
|
168
|
+
// })
|
|
169
|
+
|
|
151
170
|
return this.pluginConfigMap;
|
|
152
171
|
}
|
|
153
172
|
}
|