@bbki.ng/site 1.7.16 → 1.8.0

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 (175) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/index.html +2 -2
  3. package/package.json +6 -3
  4. package/public/now.wasm +0 -0
  5. package/src/{app.tsx → blog/app.tsx} +18 -11
  6. package/src/{articles → blog/articles}/celebration.mdx +0 -1
  7. package/src/{articles → blog/articles}/cousin.mdx +1 -1
  8. package/src/{articles → blog/articles}/leaves.mdx +1 -1
  9. package/src/{articles → blog/articles}/liqiu.mdx +0 -1
  10. package/src/{articles → blog/articles}/men-without-women.mdx +3 -3
  11. package/src/{articles → blog/articles}/movie-day.mdx +2 -2
  12. package/src/{articles → blog/articles}/projects.mdx +0 -1
  13. package/src/{articles → blog/articles}/quote.mdx +0 -1
  14. package/src/{articles → blog/articles}/red-gun.mdx +1 -1
  15. package/src/{articles → blog/articles}/rice-noodle.mdx +1 -1
  16. package/src/{articles → blog/articles}/spring-cooldown.mdx +1 -0
  17. package/src/{articles → blog/articles}/spring-rain.mdx +1 -0
  18. package/src/{articles → blog/articles}/woke-up.mdx +1 -1
  19. package/src/{components → blog/components}/Footer.tsx +1 -1
  20. package/src/{components → blog/components}/ImageUploader.tsx +1 -1
  21. package/src/{components → blog/components}/Img_ctx_menu/index.tsx +1 -1
  22. package/src/{components → blog/components}/Spinner.tsx +1 -1
  23. package/src/{components → blog/components}/app_ctx_menu/index.tsx +3 -1
  24. package/src/{components → blog/components}/article/index.tsx +1 -1
  25. package/src/blog/components/plugin/PluginContentPage.tsx +30 -0
  26. package/src/blog/components/plugin/PluginDrawer.tsx +39 -0
  27. package/src/blog/components/plugin/PluginInit.tsx +50 -0
  28. package/src/blog/components/plugin/PluginInputForm.tsx +117 -0
  29. package/src/blog/components/plugin/PluginMenuItem.tsx +67 -0
  30. package/src/blog/components/plugin/PluginRoutes.tsx +13 -0
  31. package/src/blog/components/plugin/PluginsMenuItem.tsx +45 -0
  32. package/src/blog/components/plugin/hooks/useDependencies.ts +63 -0
  33. package/src/blog/components/plugin/hooks/usePluginOutput.tsx +17 -0
  34. package/src/blog/context/bbcontext.tsx +14 -0
  35. package/src/blog/context/global_routes_provider.tsx +38 -0
  36. package/src/blog/demo/PluginDemo.ts +24 -0
  37. package/src/{hooks → blog/hooks}/useLoadingIndicator.ts +1 -1
  38. package/src/{hooks → blog/hooks}/use_file_to_post.ts +1 -1
  39. package/src/{hooks → blog/hooks}/use_posts.ts +1 -1
  40. package/src/{hooks → blog/hooks}/use_projects.ts +1 -1
  41. package/src/{main.tsx → blog/index.tsx} +13 -13
  42. package/src/{main.css → blog/main.css} +10 -0
  43. package/src/{pages → blog/pages}/cover/index.tsx +8 -6
  44. package/src/{pages → blog/pages}/extensions/txt/article.tsx +1 -1
  45. package/src/{pages → blog/pages}/login/index.tsx +1 -1
  46. package/src/blog/plugin/Dependencies.ts +10 -0
  47. package/src/blog/plugin/HostFuncAdapter.ts +28 -0
  48. package/src/blog/plugin/Plugin.ts +122 -0
  49. package/src/blog/plugin/PluginManager.ts +153 -0
  50. package/src/blog/plugin/PluginManagerPayload.ts +3 -0
  51. package/src/index.tsx +4 -0
  52. package/tsconfig.json +1 -1
  53. package/vite.config.js +5 -2
  54. /package/src/{__test__ → blog/__test__}/utils/index.test.ts +0 -0
  55. /package/src/{articles → blog/articles}/anti-logic.mdx +0 -0
  56. /package/src/{articles → blog/articles}/bbking-manual.mdx +0 -0
  57. /package/src/{articles → blog/articles}/black-river.mdx +0 -0
  58. /package/src/{articles → blog/articles}/cloth.mdx +0 -0
  59. /package/src/{articles → blog/articles}/cooking.mdx +0 -0
  60. /package/src/{articles → blog/articles}/cooldown.mdx +0 -0
  61. /package/src/{articles → blog/articles}/fall.mdx +0 -0
  62. /package/src/{articles → blog/articles}/img.mdx +0 -0
  63. /package/src/{articles → blog/articles}/index.ts +0 -0
  64. /package/src/{articles → blog/articles}/loading.mdx +0 -0
  65. /package/src/{articles → blog/articles}/love.mdx +0 -0
  66. /package/src/{articles → blog/articles}/major-cold.mdx +0 -0
  67. /package/src/{articles → blog/articles}/marshroom.mdx +0 -0
  68. /package/src/{articles → blog/articles}/moment.mdx +0 -0
  69. /package/src/{articles → blog/articles}/now.mdx +0 -0
  70. /package/src/{articles → blog/articles}/photos.mdx +0 -0
  71. /package/src/{articles → blog/articles}/pseudo-spring.mdx +0 -0
  72. /package/src/{articles → blog/articles}/travel.mdx +0 -0
  73. /package/src/{articles → blog/articles}/warming-up.mdx +0 -0
  74. /package/src/{articles → blog/articles}/web-burnning.mdx +0 -0
  75. /package/src/{articles → blog/articles}/xwy-and-snowing.mdx +0 -0
  76. /package/src/{articles → blog/articles}/xwy.mdx +0 -0
  77. /package/src/{components → blog/components}/Auth.tsx +0 -0
  78. /package/src/{components → blog/components}/DelayFadeIn/DelayFadeIn.tsx +0 -0
  79. /package/src/{components → blog/components}/Logger.tsx +0 -0
  80. /package/src/{components → blog/components}/Pochacco/Pochacco.tsx +0 -0
  81. /package/src/{components → blog/components}/Pochacco/idle.tsx +0 -0
  82. /package/src/{components → blog/components}/Pochacco/watch.tsx +0 -0
  83. /package/src/{components → blog/components}/app_ctx_menu/LoginMenuItem.tsx +0 -0
  84. /package/src/{components → blog/components}/app_ctx_menu/VersionMenuItem.tsx +0 -0
  85. /package/src/{components → blog/components}/app_ctx_menu/ViewSourceMenuItem.tsx +0 -0
  86. /package/src/{components → blog/components}/article_ctx_menu/index.tsx +0 -0
  87. /package/src/{components → blog/components}/aspect_ratio_box/index.tsx +0 -0
  88. /package/src/{components → blog/components}/blur_cover/index.tsx +0 -0
  89. /package/src/{components → blog/components}/book_list/index.tsx +0 -0
  90. /package/src/{components → blog/components}/comment/index.tsx +0 -0
  91. /package/src/{components → blog/components}/comment/use_cusdis_event.ts +0 -0
  92. /package/src/{components → blog/components}/corner_prompt_box/index.tsx +0 -0
  93. /package/src/{components → blog/components}/disabled_text/index.tsx +0 -0
  94. /package/src/{components → blog/components}/effect-layer/EffectContextProvider.tsx +0 -0
  95. /package/src/{components → blog/components}/effect-layer/EffectLayer.tsx +0 -0
  96. /package/src/{components → blog/components}/effect-layer/effects/grain.frag +0 -0
  97. /package/src/{components → blog/components}/effect-layer/hooks/useRender.ts +0 -0
  98. /package/src/{components → blog/components}/effect-layer/hooks/useResolution.ts +0 -0
  99. /package/src/{components → blog/components}/effect-layer/main.frag +0 -0
  100. /package/src/{components → blog/components}/effect-layer/shader.vert +0 -0
  101. /package/src/{components → blog/components}/effect-layer/shapes/circle.frag +0 -0
  102. /package/src/{components → blog/components}/effect-layer/shapes/heart.frag +0 -0
  103. /package/src/{components → blog/components}/effect-layer/shapes/spiral.frag +0 -0
  104. /package/src/{components → blog/components}/effect-layer/uniforms.ts +0 -0
  105. /package/src/{components → blog/components}/fade_out_cover/index.tsx +0 -0
  106. /package/src/{components → blog/components}/footer/footer_links.ts +0 -0
  107. /package/src/{components → blog/components}/footer/index.tsx +0 -0
  108. /package/src/{components → blog/components}/hotkey_nav/index.tsx +0 -0
  109. /package/src/{components → blog/components}/img_list/index.tsx +0 -0
  110. /package/src/{components → blog/components}/index.tsx +0 -0
  111. /package/src/{components → blog/components}/movie_list/index.tsx +0 -0
  112. /package/src/{components → blog/components}/my_suspense.tsx +0 -0
  113. /package/src/{components → blog/components}/progress_bar/index.tsx +0 -0
  114. /package/src/{components → blog/components}/reload_prompt/index.tsx +0 -0
  115. /package/src/{components → blog/components}/stickers/index.tsx +0 -0
  116. /package/src/{components → blog/components}/table_skeleton/index.tsx +0 -0
  117. /package/src/{components → blog/components}/tags/index.tsx +0 -0
  118. /package/src/{components → blog/components}/video_player/index.tsx +0 -0
  119. /package/src/{components → blog/components}/with_wrapper/index.tsx +0 -0
  120. /package/src/{constants → blog/constants}/cusdis.ts +0 -0
  121. /package/src/{constants → blog/constants}/index.ts +0 -0
  122. /package/src/{constants → blog/constants}/photo_projects.ts +0 -0
  123. /package/src/{constants → blog/constants}/photos.ts +0 -0
  124. /package/src/{constants → blog/constants}/routes.ts +0 -0
  125. /package/src/{constants → blog/constants}/video_logs.ts +0 -0
  126. /package/src/{global_loading_state_provider.tsx → blog/context/global_loading_state_provider.tsx} +0 -0
  127. /package/src/{demo → blog/demo}/DemoBox.tsx +0 -0
  128. /package/src/{demo → blog/demo}/DemoMenu.tsx +0 -0
  129. /package/src/{demo → blog/demo}/ImgDemo.tsx +0 -0
  130. /package/src/{demo → blog/demo}/SpinnerDemo.tsx +0 -0
  131. /package/src/{demo → blog/demo}/Xwy.tsx +0 -0
  132. /package/src/{global → blog/global}/mdx.d.ts +0 -0
  133. /package/src/{hooks → blog/hooks}/index.ts +0 -0
  134. /package/src/{hooks → blog/hooks}/useScrollToTop.ts +0 -0
  135. /package/src/{hooks → blog/hooks}/useTransitionCls.ts +0 -0
  136. /package/src/{hooks → blog/hooks}/use_authed.ts +0 -0
  137. /package/src/{hooks → blog/hooks}/use_authed_fetcher.ts +0 -0
  138. /package/src/{hooks → blog/hooks}/use_del_img.ts +0 -0
  139. /package/src/{hooks → blog/hooks}/use_delete_post.ts +0 -0
  140. /package/src/{hooks → blog/hooks}/use_font_loading.ts +0 -0
  141. /package/src/{hooks → blog/hooks}/use_img_loading.ts +0 -0
  142. /package/src/{hooks → blog/hooks}/use_mouse_position.ts +0 -0
  143. /package/src/{hooks → blog/hooks}/use_pathname.ts +0 -0
  144. /package/src/{hooks → blog/hooks}/use_paths.ts +0 -0
  145. /package/src/{hooks → blog/hooks}/use_post.ts +0 -0
  146. /package/src/{hooks → blog/hooks}/use_role.ts +0 -0
  147. /package/src/{hooks → blog/hooks}/use_route_name.ts +0 -0
  148. /package/src/{hooks → blog/hooks}/use_supa_session.ts +0 -0
  149. /package/src/{hooks → blog/hooks}/use_text_plain_file.ts +0 -0
  150. /package/src/{hooks → blog/hooks}/use_uploader.ts +0 -0
  151. /package/src/{hooks → blog/hooks}/use_video_controls.ts +0 -0
  152. /package/src/{pages → blog/pages}/bot/index.tsx +0 -0
  153. /package/src/{pages → blog/pages}/extensions/png/consts.ts +0 -0
  154. /package/src/{pages → blog/pages}/extensions/png/index.tsx +0 -0
  155. /package/src/{pages → blog/pages}/extensions/png/png_projects.tsx +0 -0
  156. /package/src/{pages → blog/pages}/extensions/txt/consts.ts +0 -0
  157. /package/src/{pages → blog/pages}/extensions/txt/index.tsx +0 -0
  158. /package/src/{pages → blog/pages}/index.tsx +0 -0
  159. /package/src/{pages → blog/pages}/now/index.tsx +0 -0
  160. /package/src/{pages → blog/pages}/tags/index.tsx +0 -0
  161. /package/src/{pages → blog/pages}/tags/tag_result.tsx +0 -0
  162. /package/src/{pages → blog/pages}/upload/index.tsx +0 -0
  163. /package/src/{swr.tsx → blog/swr.tsx} +0 -0
  164. /package/src/{types → blog/types}/articles.ts +0 -0
  165. /package/src/{types → blog/types}/color.ts +0 -0
  166. /package/src/{types → blog/types}/cusdis.ts +0 -0
  167. /package/src/{types → blog/types}/font.ts +0 -0
  168. /package/src/{types → blog/types}/glsl.d.ts +0 -0
  169. /package/src/{types → blog/types}/oss.ts +0 -0
  170. /package/src/{types → blog/types}/path.ts +0 -0
  171. /package/src/{types → blog/types}/photo.ts +0 -0
  172. /package/src/{types → blog/types}/supabase.ts +0 -0
  173. /package/src/{types → blog/types}/upload.ts +0 -0
  174. /package/src/{utils → blog/utils}/index.ts +0 -0
  175. /package/src/{utils → blog/utils}/tags.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @bbki.ng/site
2
2
 
3
+ ## 1.8.0
4
+
3
5
  ## 1.7.16
4
6
 
5
7
  ## 1.7.15
package/index.html CHANGED
@@ -40,8 +40,8 @@
40
40
  </head>
41
41
 
42
42
  <body class="h-full m-0 flex flex-col font-mono">
43
- <div id="root" class="flex-grow noto-serif"></div>
44
- <script type="module" src="/src/main.tsx"></script>
43
+ <div id="blog" class="flex-grow noto-serif"></div>
44
+ <script type="module" src="/src/index.tsx"></script>
45
45
  <script type="module">
46
46
  // Import the functions you need from the SDKs you need
47
47
  import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.3/firebase-app.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/site",
3
- "version": "1.7.16",
3
+ "version": "1.8.0",
4
4
  "description": "code behind bbki.ng",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -16,7 +16,8 @@
16
16
  "url": "git+https://github.com/bbbottle/bbki.ng.git"
17
17
  },
18
18
  "dependencies": {
19
- "@bbki.ng/components": "workspace:2.5.11",
19
+ "@extism/extism": "2.0.0-rc11",
20
+ "@bbki.ng/components": "workspace:2.6.0",
20
21
  "@supabase/supabase-js": "^1.35.4",
21
22
  "classnames": "2.3.1",
22
23
  "react": "^18.0.0",
@@ -25,7 +26,8 @@
25
26
  "react-hotkeys-hook": "^3.4.3",
26
27
  "react-router-dom": "6",
27
28
  "sonner": "1.4.0",
28
- "swr": "^2.2.5"
29
+ "swr": "^2.2.5",
30
+ "vaul": "1.1.2"
29
31
  },
30
32
  "devDependencies": {
31
33
  "@bbki.ng/stylebase": "workspace:0.4.7",
@@ -58,6 +60,7 @@
58
60
  "ts-jest": "^27.1.1",
59
61
  "typescript": "^4.5.4",
60
62
  "vite": "5.0.0",
63
+ "vite-plugin-cross-origin-isolation": "0.1.6",
61
64
  "vite-plugin-glsl": "1.2.1",
62
65
  "vite-plugin-mdx": "^3.5.8",
63
66
  "vite-plugin-pwa": "0.19",
Binary file
@@ -16,16 +16,16 @@ import Txt from "@/pages/extensions/txt";
16
16
  import { usePaths } from "@/hooks";
17
17
  import { Login } from "@/pages/login";
18
18
  import { SWR } from "@/swr";
19
- import {
20
- GlobalLoadingContext,
21
- GlobalLoadingStateProvider,
22
- } from "@/global_loading_state_provider";
19
+ import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
23
20
  import { UploadPage } from "@/pages/upload";
24
21
  import { AppCtxMenu } from "@/components/app_ctx_menu";
25
22
  import { Pochacco, PochaccoPose } from "@/components/Pochacco/Pochacco";
26
23
  import { Role, useRole } from "@/hooks/use_role";
27
- import { EffectContextProvider } from "@/components/effect-layer/EffectContextProvider";
28
24
  import { BotRedirect } from "@/pages/bot";
25
+ import { PluginInit } from "@/components/plugin/PluginInit";
26
+ import { BBContext } from "@/context/bbcontext";
27
+ import { PluginContentPage } from "@/components/plugin/PluginContentPage";
28
+ import { PluginRoutes } from "@/components/plugin/PluginRoutes";
29
29
 
30
30
  const Layout = () => {
31
31
  const { isLoading, isFontLoading } = useContext(GlobalLoadingContext);
@@ -65,9 +65,10 @@ const CoverInMidCol = threeColWrapper(Cover);
65
65
  export const App = () => {
66
66
  return (
67
67
  <SWR>
68
- <EffectContextProvider>
69
- <HotKeyNav>
70
- <GlobalLoadingStateProvider>
68
+ {/*<EffectContextProvider>*/}
69
+ <HotKeyNav>
70
+ <BBContext>
71
+ <PluginInit>
71
72
  <Routes>
72
73
  <Route path="/" element={<Layout />}>
73
74
  <Route index element={<CoverInMidCol />} />
@@ -85,12 +86,18 @@ export const App = () => {
85
86
  <Route path="now" element={<NowInMidCol />} />
86
87
  <Route path="login" element={<LoginInMidCol />} />
87
88
  <Route path="upload" element={<UploadPage />} />
89
+ <Route path="/plugins" element={<PluginRoutes />} />
90
+ <Route
91
+ path="/plugins/:pluginRoute"
92
+ element={<PluginContentPage />}
93
+ />
88
94
  </Route>
89
95
  <Route path="*" element={<NotFound />} />
90
96
  </Routes>
91
- </GlobalLoadingStateProvider>
92
- </HotKeyNav>
93
- </EffectContextProvider>
97
+ </PluginInit>
98
+ </BBContext>
99
+ </HotKeyNav>
100
+ {/*</EffectContextProvider>*/}
94
101
  </SWR>
95
102
  );
96
103
  };
@@ -19,4 +19,3 @@ tags:
19
19
 
20
20
  —— 摘自《夜的命名术》
21
21
  ```
22
-
@@ -12,4 +12,4 @@ tags:
12
12
 
13
13
  种蓄场倒闭,伯父去世,伯母改嫁,堂兄结婚生子、大病入院、妻子失踪。全部发生在这二十年间。「弟弟来你家要把你的菜全吃光了」,二十年前,种蓄场的职员这样逗堂兄玩。晚餐的时候,堂兄用筷子截住我伸出的筷子,不让我夹菜。
14
14
 
15
- 曾经父母宠爱,无忧无虑的堂兄,现在沉默寡言。
15
+ 曾经父母宠爱,无忧无虑的堂兄,现在沉默寡言。
@@ -4,4 +4,4 @@ tags:
4
4
  - 随笔
5
5
  ---
6
6
 
7
- 下班发现洗衣机盖子上有片树叶,应该是窗外飘进来的。
7
+ 下班发现洗衣机盖子上有片树叶,应该是窗外飘进来的。
@@ -5,4 +5,3 @@ tags:
5
5
  ---
6
6
 
7
7
  这个没有参与感的夏天,就像六月的梦,是黑色的。对了,吃过一次西瓜,大面积黑色里,至少还有一小片红。
8
-
@@ -8,9 +8,9 @@ tags:
8
8
 
9
9
  《没有女人的男人们》是村上春树的短篇小说集,书本介绍写的是:「村上返回原点之作,《东京奇谭集》之后时隔九年又一短篇小说集」。「返回原点」也多少有点像在说自己,时隔三年又回到之前离开的城市。一天刚好看完。
10
10
 
11
- | 上午 | 下午 | 晚上 |
12
- |:----|:-----|:----|
13
- | 驾驶我的车 <br /> 昨天 | 独立器官 <br /> 山鲁左德 <br /> 木野 | 恋爱的萨姆沙 |
11
+ | 上午 | 下午 | 晚上 |
12
+ | :--------------------- | :----------------------------------- | :----------- |
13
+ | 驾驶我的车 <br /> 昨天 | 独立器官 <br /> 山鲁左德 <br /> 木野 | 恋爱的萨姆沙 |
14
14
 
15
15
  故事中的男人们,有人妻子过世,有人想满世界流浪,有人是坚定的不婚主义,有人被戴上有颜色的帽子……男男女女,来来去去。短篇小说比起电影好像更任性一点,结局戛然而止也让人也觉得情理之中,根据交代过的信息想象一下男女主接下来的境遇也是一件很有意思的事情。我最喜欢的两篇是《山鲁佐德》和《木野》。前者作为一个故事,故事中又穿插了女主讲述的故事,很有层次感,也很容易被带入女主的玄妙变态、虚实莫辨的回忆或者说是想象中。甚至阅读完都不太想深究她和男主到底是什么关系。此外文中有一段关于胡子的描述,觉得挺好玩,感觉也可以尝试一下:
16
16
 
@@ -8,8 +8,8 @@ tags:
8
8
 
9
9
  **一天计划**,用一天时间在同一个地点做同一件事情。比如写一天代码、看一天书。个人电影节也是「一天计划」的一部分。从之前标记想看的电影清单中随机挑选出五部电影,用一天时间看完。
10
10
 
11
- | 上午 | 下午 | 晚上 |
12
- |:----|:-----|:----|
11
+ | 上午 | 下午 | 晚上 |
12
+ | :--------------------- | :--------------------------- | :------- |
13
13
  | 花火 <br /> 数电影的人 | 不能说的游戏 <br /> 蜂蜜之地 | 尽情游戏 |
14
14
 
15
15
  《花火》整部电影都很沉默冷静,甚至连剧中的枪响也是。可能是浓烈的情感需要大面积的留白去稀释,主角台词不多,却好像什么都已说尽。《数电影的人》是一部记录片,介绍了一群修复电影胶片的人,为电影延续生命。他们有枯燥的工作,有来自同事间互相鼓励和安慰。有意义危机,也有使命感和成就感。我更羡慕的是他们的工作周期,能花很长很长的一段时间慢慢把事情做好,也紧迫也从容。《不能说的游戏》讲述小女孩被熟人性侵后,整个人生受到的影响。电影配乐很欢快,大部分剪辑也是,但看似轻松欢快的节奏,却能让人感受到背后的压抑与主角内心困兽般的反应。这部电影,比起犯人,我更讨厌女主的母亲。《蜂蜜之地》是一部很美的记录片,贫瘠的土地,满眼只能看到岩石灌木和沙砾。相依为命的母女,贪婪的邻居。能够看到一种截然不同的生活方式,已经很心满意足。《尽情游戏》则是一部轻松的喜剧,可能包含了对战争的反思,我更愿意就把它当成一部普通的喜剧。最后其实还有一部德国电影《奇迹》,已经无法看下去,就像很久没有运动,跑完三公里已经到了极限,无法跑完最后一圈。
@@ -6,4 +6,3 @@ headless: True
6
6
  import Png from "@/pages/extensions/png";
7
7
 
8
8
  <Png />
9
-
@@ -11,7 +11,6 @@ tags:
11
11
  \- “我很悲惨,要是你知道我有多悲惨就好了。” \
12
12
  \- “我们能做什么?我们必须过好自己的生活。”
13
13
 
14
-
15
14
  “河流紀事 · 鄧獻誌
16
15
 
17
16
  河流用一生梳理 \
@@ -16,4 +16,4 @@ tags:
16
16
 
17
17
  小男孩掉头要走,老板娘大声问:
18
18
 
19
- “你昨天是不是拿了他那把红色的枪?”
19
+ “你昨天是不是拿了他那把红色的枪?”
@@ -18,4 +18,4 @@ tags:
18
18
 
19
19
  ……
20
20
 
21
- “哎!不是说了要圆粉吗?”
21
+ “哎!不是说了要圆粉吗?”
@@ -4,4 +4,5 @@ tags:
4
4
  - 随笔
5
5
  - 天气
6
6
  ---
7
+
7
8
  最开始只是刮风。重庆刮完台风的第二天,长沙,办公室窗外大风呼号,其声呜咽。工作群登出通告,提醒下班关窗。后边几天气温就回到冬季,并且有断断续续的小雨,不得不再次翻出羽绒服。小河涨水后,关注的钓鱼区 UP 主视频也随之陆续更新。
@@ -4,6 +4,7 @@ tags:
4
4
  - 随笔
5
5
  - 天气
6
6
  ---
7
+
7
8
  在正式进入夏天之前,这里的气温曾突然跌到冬天的水平。然后伴随着清明时节的雨水,慢慢回升。我的作息,已经提前向去年夏末的节奏靠近。要不是疫情,早起后就能很悠闲地去那家粉店。要不是疫情,每个人都能多出很多选择。
8
9
 
9
10
  春天的雨在窗外滴滴答答,好像永远不会停下,雨声比冬天欢快,也许是整体气温让人先放松了下来。
@@ -4,4 +4,4 @@ tags:
4
4
  - 随笔
5
5
  ---
6
6
 
7
- 厨房里,小乌鸦买的火锅底料掉在纯净水瓶上,纯净水瓶掉到地上,这是清早发现的。凌晨只是被惊醒,瞬间不知道自己在哪,有点害怕。
7
+ 厨房里,小乌鸦买的火锅底料掉在纯净水瓶上,纯净水瓶掉到地上,这是清早发现的。凌晨只是被惊醒,瞬间不知道自己在哪,有点害怕。
@@ -2,7 +2,7 @@ import React, { useContext } from "react";
2
2
  import { Link, Tag } from "@bbki.ng/components";
3
3
  import { useLocation } from "react-router-dom";
4
4
  import { usePaths } from "@/hooks";
5
- import { GlobalLoadingContext } from "@/global_loading_state_provider";
5
+ import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
6
6
 
7
7
  export const Footer = () => {
8
8
  const location = useLocation();
@@ -2,7 +2,7 @@ import React, { useContext } from "react";
2
2
  import { DropImage } from "@bbki.ng/components";
3
3
  import { useUploader } from "@/hooks/use_uploader";
4
4
  import { ImageUploaderProps } from "@/types/upload";
5
- import { GlobalLoadingContext } from "@/global_loading_state_provider";
5
+ import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
6
6
  import { Auth } from "@/components/Auth";
7
7
  import { Role } from "@/hooks/use_role";
8
8
  import { useParams } from "react-router-dom";
@@ -13,7 +13,7 @@ import { confirm } from "@/utils";
13
13
  import { ContextMenuSeparator } from "@bbki.ng/components";
14
14
  import { useDelImg } from "@/hooks/use_del_img";
15
15
  import { toast } from "sonner";
16
- import { GlobalLoadingContext } from "@/global_loading_state_provider";
16
+ import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
17
17
 
18
18
  export const ImgCtxMenu = (props: {
19
19
  children: ReactElement;
@@ -1,5 +1,5 @@
1
1
  import React, { useContext, useEffect } from "react";
2
- import { GlobalLoadingContext } from "@/global_loading_state_provider";
2
+ import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
3
3
 
4
4
  export const Spinner = (props: { disableDotIndicator?: boolean }) => {
5
5
  const { disableDotIndicator } = props;
@@ -10,6 +10,7 @@ import {
10
10
  import { LoginMenuItem } from "@/components/app_ctx_menu/LoginMenuItem";
11
11
  import { VersionMenuItem } from "@/components/app_ctx_menu/VersionMenuItem";
12
12
  import { ViewSourceMenuItem } from "@/components/app_ctx_menu/ViewSourceMenuItem";
13
+ import { PluginsMenuItem } from "@/components/plugin/PluginsMenuItem";
13
14
 
14
15
  export const AppCtxMenu = (props: { children: ReactElement }) => {
15
16
  return (
@@ -17,9 +18,10 @@ export const AppCtxMenu = (props: { children: ReactElement }) => {
17
18
  <ContextMenuTrigger>{props.children}</ContextMenuTrigger>
18
19
  <ContextMenuContent className="w-256">
19
20
  <LoginMenuItem />
20
- <ContextMenuSeparator />
21
21
  <VersionMenuItem />
22
22
  <ViewSourceMenuItem />
23
+ <ContextMenuSeparator />
24
+ <PluginsMenuItem />
23
25
  </ContextMenuContent>
24
26
  </ContextMenu>
25
27
  );
@@ -4,7 +4,7 @@ import { ROUTES } from "@/constants";
4
4
  import { DelayFadeIn } from "@/components/DelayFadeIn/DelayFadeIn";
5
5
  import classNames from "classnames";
6
6
 
7
- type ArticlePageProps = {
7
+ export type ArticlePageProps = {
8
8
  tags?: string[];
9
9
  title: string;
10
10
  description?: any;
@@ -0,0 +1,30 @@
1
+ import { ArticlePage, ArticlePageProps } from "@/components/article";
2
+ import React, { memo } from "react";
3
+ import { threeColWrapper } from "@/components/with_wrapper";
4
+ import { useParams } from "react-router-dom";
5
+ import { usePluginOutput } from "@/components/plugin/hooks/usePluginOutput";
6
+ import { PluginManager } from "@/plugin/PluginManager";
7
+
8
+ type PluginContentPageProps = Omit<ArticlePageProps, "children">;
9
+
10
+ const ContentPage = (props: PluginContentPageProps) => {
11
+ const { pluginRoute } = useParams();
12
+
13
+ if (!pluginRoute || !PluginManager.instance) {
14
+ return null;
15
+ }
16
+
17
+ const plugin = PluginManager.instance.getPluginByRoute(pluginRoute);
18
+ if (!plugin) {
19
+ return null;
20
+ }
21
+
22
+ const content = usePluginOutput(plugin.config.id);
23
+ return (
24
+ <ArticlePage {...props} title={plugin?.config.route || ""}>
25
+ <div dangerouslySetInnerHTML={{ __html: content }} />
26
+ </ArticlePage>
27
+ );
28
+ };
29
+
30
+ export const PluginContentPage = threeColWrapper(ContentPage);
@@ -0,0 +1,39 @@
1
+ import { DialogProps, Drawer } from "vaul";
2
+ import React, { ReactNode } from "react";
3
+
4
+ type PluginDrawerProps = {
5
+ children: ReactNode;
6
+ title?: string;
7
+ description?: string;
8
+ } & Pick<DialogProps, "open"> &
9
+ Pick<DialogProps, "onOpenChange">;
10
+
11
+ export const PluginDrawer = (props: PluginDrawerProps) => {
12
+ const { children, title, description, open, onOpenChange } = props;
13
+
14
+ return (
15
+ <Drawer.Root
16
+ direction="bottom"
17
+ open={open}
18
+ onOpenChange={onOpenChange}
19
+ modal={false}
20
+ >
21
+ <Drawer.Portal>
22
+ <Drawer.Content className="bg-gray-100 flex flex-col {/*rounded-t-[10px]*/} mt-24 h-fit fixed bottom-0 left-0 right-0 outline-none border-t border-gray-200">
23
+ <div className="p-4 bg-white {/*rounded-t-[10px]*/} flex-1">
24
+ <div className="mx-auto w-12 h-1.5 flex-shrink-0 rounded-full bg-gray-300 mb-8" />
25
+ <div className="max-w-md mx-auto my-32 p-16">
26
+ <Drawer.Title className="font-medium mb-2 text-zinc-900">
27
+ {title}
28
+ </Drawer.Title>
29
+ <Drawer.Description className="text-zinc-600 mb-2">
30
+ {description}
31
+ </Drawer.Description>
32
+ {children}
33
+ </div>
34
+ </div>
35
+ </Drawer.Content>
36
+ </Drawer.Portal>
37
+ </Drawer.Root>
38
+ );
39
+ };
@@ -0,0 +1,50 @@
1
+ import React, { useCallback, useEffect } from "react";
2
+ import { ReactNode } from "react";
3
+ import { PluginInputForm } from "@/components/plugin/PluginInputForm";
4
+ import { useDependencies } from "@/components/plugin/hooks/useDependencies";
5
+ import { PluginManager } from "@/plugin/PluginManager";
6
+
7
+ export const PluginInit = (props: { children: ReactNode }) => {
8
+ const {
9
+ isPluginFormInputOpen,
10
+ setPluginFormInputOpen,
11
+ pluginInputFormConf,
12
+ formDataResolver,
13
+
14
+ ...dep
15
+ } = useDependencies();
16
+
17
+ useEffect(() => {
18
+ PluginManager.init(dep).then();
19
+ }, []);
20
+
21
+ const onSubmit = useCallback(
22
+ (formData: string) => {
23
+ formDataResolver(formData);
24
+ setPluginFormInputOpen(false);
25
+ },
26
+ [formDataResolver]
27
+ );
28
+
29
+ const onOpenChange = useCallback(
30
+ (o: boolean) => {
31
+ setPluginFormInputOpen(o);
32
+ if (!o) {
33
+ formDataResolver("");
34
+ }
35
+ },
36
+ [formDataResolver]
37
+ );
38
+
39
+ return (
40
+ <>
41
+ {props.children}
42
+ <PluginInputForm
43
+ open={isPluginFormInputOpen}
44
+ onOpenChange={onOpenChange}
45
+ input={pluginInputFormConf}
46
+ onSubmit={onSubmit}
47
+ />
48
+ </>
49
+ );
50
+ };
@@ -0,0 +1,117 @@
1
+ import React from "react";
2
+ import { PluginInput, PluginInputFieldType } from "@/plugin/Plugin";
3
+ import {
4
+ z,
5
+ zodResolver,
6
+ useForm,
7
+ Form,
8
+ FormField,
9
+ FormItem,
10
+ FormLabel,
11
+ Input,
12
+ Button,
13
+ ButtonType,
14
+ FormControl,
15
+ } from "@bbki.ng/components";
16
+ import { PluginDrawer } from "@/components/plugin/PluginDrawer";
17
+ import { DialogProps } from "vaul";
18
+
19
+ type PluginInputFormProps = {
20
+ input: PluginInput;
21
+ onSubmit: (input: string) => void;
22
+ } & Pick<DialogProps, "open"> &
23
+ Pick<DialogProps, "onOpenChange">;
24
+
25
+ const getPluginInputSchema = (input: PluginInput) => {
26
+ const obj: any = {};
27
+ const typeMap = {
28
+ [PluginInputFieldType.String]: z.string().default(""),
29
+ [PluginInputFieldType.Number]: z.number().default(0),
30
+ [PluginInputFieldType.Boolean]: z.boolean().default(false),
31
+ };
32
+
33
+ input.forEach((item) => {
34
+ obj[item.name] = typeMap[item.type];
35
+ });
36
+
37
+ return z.object(obj);
38
+ };
39
+
40
+ const getInputDefaultValue = (type: PluginInputFieldType) => {
41
+ switch (type) {
42
+ case PluginInputFieldType.String:
43
+ return "";
44
+ case PluginInputFieldType.Number:
45
+ return 0;
46
+ case PluginInputFieldType.Boolean:
47
+ return false;
48
+ }
49
+ };
50
+
51
+ const getPluginDefaultInput = (input: PluginInput) => {
52
+ const obj: any = {};
53
+ input.forEach((item) => {
54
+ obj[item.name] = getInputDefaultValue(item.type);
55
+ });
56
+ return obj;
57
+ };
58
+
59
+ const getInputType = (type: PluginInputFieldType) => {
60
+ switch (type) {
61
+ case PluginInputFieldType.String:
62
+ return "text";
63
+ case PluginInputFieldType.Number:
64
+ return "number";
65
+ case PluginInputFieldType.Boolean:
66
+ return "checkbox";
67
+ }
68
+ };
69
+
70
+ export const PluginInputForm = (props: PluginInputFormProps) => {
71
+ const { input, onSubmit, open, onOpenChange } = props;
72
+ const schema = getPluginInputSchema(input);
73
+ const form = useForm<z.infer<typeof schema>>({
74
+ resolver: zodResolver(schema),
75
+ values: getPluginDefaultInput(input),
76
+ });
77
+
78
+ const ok = (data: z.infer<typeof schema>) => {
79
+ onSubmit(JSON.stringify(data));
80
+ };
81
+
82
+ return (
83
+ <PluginDrawer open={open} onOpenChange={onOpenChange}>
84
+ <Form {...form}>
85
+ <form onSubmit={form.handleSubmit(ok)}>
86
+ {input.map((item) => {
87
+ return (
88
+ <FormField
89
+ key={item.name}
90
+ control={form.control}
91
+ render={({ field }) => {
92
+ return (
93
+ <FormItem>
94
+ <FormLabel>{item.name}</FormLabel>
95
+ <FormControl>
96
+ <Input type={getInputType(item.type)} {...field} />
97
+ </FormControl>
98
+ </FormItem>
99
+ );
100
+ }}
101
+ name={item.name}
102
+ />
103
+ );
104
+ })}
105
+ <Button
106
+ className="mt-16"
107
+ onClick={() => {}}
108
+ btnType="submit"
109
+ type={ButtonType.PRIMARY}
110
+ >
111
+ Ok
112
+ </Button>
113
+ </form>
114
+ </Form>
115
+ </PluginDrawer>
116
+ );
117
+ };
@@ -0,0 +1,67 @@
1
+ import React from "react";
2
+ import {
3
+ ContextMenuItem,
4
+ ContextMenuSub,
5
+ ContextMenuSubContent,
6
+ ContextMenuSubTrigger,
7
+ } from "@bbki.ng/components";
8
+ import { PluginConfig, PluginStatus } from "@/plugin/Plugin";
9
+
10
+ type PluginMenuItemProps = {
11
+ plugin: PluginConfig;
12
+ onUninstall: (plugin: PluginConfig) => void;
13
+ onInstall: (plugin: PluginConfig) => void;
14
+ onStop: (plugin: PluginConfig) => void;
15
+ onRun: (plugin: PluginConfig) => void;
16
+ };
17
+
18
+ export const PluginMenuItem = (props: PluginMenuItemProps) => {
19
+ const { plugin, onUninstall, onStop, onRun, onInstall } = props;
20
+ return (
21
+ <ContextMenuSub>
22
+ <ContextMenuSubTrigger inset>
23
+ {plugin.name} v{plugin.version}
24
+ </ContextMenuSubTrigger>
25
+ <ContextMenuSubContent className="w-48">
26
+ {plugin.status !== PluginStatus.Available && (
27
+ <ContextMenuItem
28
+ onClick={() => {
29
+ onUninstall(plugin);
30
+ }}
31
+ >
32
+ uninstall
33
+ </ContextMenuItem>
34
+ )}
35
+ {plugin.status === PluginStatus.Available && (
36
+ <ContextMenuItem
37
+ onClick={() => {
38
+ onInstall(plugin);
39
+ }}
40
+ >
41
+ install
42
+ </ContextMenuItem>
43
+ )}
44
+ {plugin.status === PluginStatus.Running && (
45
+ <ContextMenuItem
46
+ onClick={() => {
47
+ onStop(plugin);
48
+ }}
49
+ >
50
+ stop
51
+ </ContextMenuItem>
52
+ )}
53
+ {(plugin.status === PluginStatus.Installed ||
54
+ plugin.status === PluginStatus.Stopped) &&
55
+ !plugin.route && (
56
+ <ContextMenuItem
57
+ onClick={() => {
58
+ onRun(plugin);
59
+ }}
60
+ >
61
+ run
62
+ </ContextMenuItem>
63
+ )}
64
+ </ContextMenuSubContent>
65
+ </ContextMenuSub>
66
+ );
67
+ };
@@ -0,0 +1,13 @@
1
+ import { threeColWrapper } from "@/components/with_wrapper";
2
+ import { CenterLinkList } from "@/components";
3
+ import React, { useContext } from "react";
4
+ import { GlobalRoutesContext } from "@/context/global_routes_provider";
5
+
6
+ const PluginRoutesContent = () => {
7
+ const globalRouteCtx = useContext(GlobalRoutesContext);
8
+ const routes = globalRouteCtx.globalRoutes;
9
+
10
+ return <CenterLinkList className="select-none" links={routes} title="" />;
11
+ };
12
+
13
+ export const PluginRoutes = threeColWrapper(PluginRoutesContent);