@bbki.ng/site 5.4.22 → 5.4.25
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 +22 -0
- package/index.html +12 -19
- package/package.json +5 -8
- package/src/blog/app.tsx +21 -33
- package/src/blog/components/article/index.tsx +8 -17
- package/src/blog/components/index.tsx +0 -6
- package/src/blog/components/share/share-btn.tsx +5 -8
- package/src/blog/constants/index.ts +1 -16
- package/src/blog/constants/routes.ts +12 -22
- package/src/blog/context/bbcontext.tsx +7 -7
- package/src/blog/hooks/index.ts +3 -18
- package/src/blog/hooks/use_dynamic_logo.tsx +6 -11
- package/src/blog/hooks/use_posts.ts +19 -10
- package/src/blog/hooks/use_role.ts +9 -14
- package/src/blog/hooks/use_streaming.ts +2 -2
- package/src/blog/index.tsx +5 -11
- package/src/blog/pages/cover/index.tsx +0 -1
- package/src/blog/pages/extensions/txt/article.tsx +7 -21
- package/src/blog/pages/extensions/txt/index.tsx +2 -17
- package/src/blog/pages/login/index.tsx +18 -42
- package/src/blog/pages/streaming/index.tsx +28 -28
- package/src/blog/swr.tsx +4 -7
- package/src/blog/utils/index.ts +9 -172
- package/vite.config.js +2 -1
- package/src/blog/articles/anti-logic.mdx +0 -61
- package/src/blog/articles/bbking-manual.mdx +0 -7
- package/src/blog/articles/black-river.mdx +0 -8
- package/src/blog/articles/celebration.mdx +0 -21
- package/src/blog/articles/cloth.mdx +0 -11
- package/src/blog/articles/cooking.mdx +0 -7
- package/src/blog/articles/cooldown.mdx +0 -12
- package/src/blog/articles/cousin.mdx +0 -15
- package/src/blog/articles/fall.mdx +0 -8
- package/src/blog/articles/img.mdx +0 -104
- package/src/blog/articles/leaves.mdx +0 -7
- package/src/blog/articles/liqiu.mdx +0 -7
- package/src/blog/articles/loading.mdx +0 -144
- package/src/blog/articles/love.mdx +0 -19
- package/src/blog/articles/major-cold.mdx +0 -14
- package/src/blog/articles/marshroom.mdx +0 -17
- package/src/blog/articles/men-without-women.mdx +0 -19
- package/src/blog/articles/moment.mdx +0 -9
- package/src/blog/articles/movie-day.mdx +0 -15
- package/src/blog/articles/photos.mdx +0 -13
- package/src/blog/articles/projects.mdx +0 -8
- package/src/blog/articles/pseudo-spring.mdx +0 -7
- package/src/blog/articles/quote.mdx +0 -26
- package/src/blog/articles/red-gun.mdx +0 -19
- package/src/blog/articles/rice-noodle.mdx +0 -21
- package/src/blog/articles/spring-cooldown.mdx +0 -8
- package/src/blog/articles/spring-rain.mdx +0 -10
- package/src/blog/articles/travel.mdx +0 -22
- package/src/blog/articles/warming-up.mdx +0 -10
- package/src/blog/articles/web-burnning.mdx +0 -10
- package/src/blog/articles/woke-up.mdx +0 -7
- package/src/blog/articles/xwy-and-snowing.mdx +0 -13
- package/src/blog/articles/xwy.mdx +0 -9
- package/src/blog/components/ImageUploader.tsx +0 -55
- package/src/blog/components/Img_ctx_menu/index.tsx +0 -67
- package/src/blog/components/Logger.tsx +0 -9
- package/src/blog/components/Pochacco/Pochacco.tsx +0 -29
- package/src/blog/components/Pochacco/idle.tsx +0 -31
- package/src/blog/components/Pochacco/watch.tsx +0 -28
- package/src/blog/components/Version.tsx +0 -14
- package/src/blog/components/app_ctx_menu/LoginMenuItem.tsx +0 -72
- package/src/blog/components/app_ctx_menu/PostMenuItem.tsx +0 -22
- package/src/blog/components/app_ctx_menu/VersionMenuItem.tsx +0 -13
- package/src/blog/components/app_ctx_menu/ViewSourceMenuItem.tsx +0 -34
- package/src/blog/components/app_ctx_menu/index.tsx +0 -35
- package/src/blog/components/article_ctx_menu/index.tsx +0 -58
- package/src/blog/components/blur_cover/index.tsx +0 -28
- package/src/blog/components/hotkey_nav/index.tsx +0 -51
- package/src/blog/components/progress_bar/index.tsx +0 -31
- package/src/blog/components/reaction/emojis.tsx +0 -143
- package/src/blog/components/reaction/oh_reaction.tsx +0 -105
- package/src/blog/components/reload_prompt/index.tsx +0 -51
- package/src/blog/components/tags/index.tsx +0 -52
- package/src/blog/hooks/useLoadingIndicator.ts +0 -12
- package/src/blog/hooks/useScrollToTop.ts +0 -24
- package/src/blog/hooks/useTransitionCls.ts +0 -36
- package/src/blog/hooks/use_authed.ts +0 -7
- package/src/blog/hooks/use_authed_fetcher.ts +0 -9
- package/src/blog/hooks/use_authed_string_post.ts +0 -42
- package/src/blog/hooks/use_clipboard_content.ts +0 -21
- package/src/blog/hooks/use_clipboard_to_post.ts +0 -48
- package/src/blog/hooks/use_del_img.ts +0 -22
- package/src/blog/hooks/use_delete_post.ts +0 -22
- package/src/blog/hooks/use_file_to_post.ts +0 -38
- package/src/blog/hooks/use_img_loading.ts +0 -16
- package/src/blog/hooks/use_post.ts +0 -26
- package/src/blog/hooks/use_projects.ts +0 -67
- package/src/blog/hooks/use_route_name.ts +0 -7
- package/src/blog/hooks/use_shared_string_to_post.ts +0 -23
- package/src/blog/hooks/use_supa_session.ts +0 -32
- package/src/blog/hooks/use_text_plain_file.ts +0 -36
- package/src/blog/hooks/use_uploader.ts +0 -34
- package/src/blog/hooks/use_video_controls.ts +0 -71
- package/src/blog/types/supabase.ts +0 -12
- package/src/blog/types/upload.ts +0 -16
- package/src/blog/utils/tags.ts +0 -21
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { PochaccoProps } from "@/components/Pochacco/Pochacco";
|
|
3
|
-
|
|
4
|
-
export const Watch = (props: PochaccoProps) => (
|
|
5
|
-
<svg
|
|
6
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
-
version="1.0"
|
|
8
|
-
width={props.size || 48}
|
|
9
|
-
height={props.size || 48}
|
|
10
|
-
viewBox="0 0 128.000000 128.000000"
|
|
11
|
-
preserveAspectRatio="xMidYMid meet"
|
|
12
|
-
>
|
|
13
|
-
<g
|
|
14
|
-
transform="translate(0.000000,128.000000) scale(0.100000,-0.100000)"
|
|
15
|
-
fill="#000000"
|
|
16
|
-
stroke="none"
|
|
17
|
-
>
|
|
18
|
-
<path d="M1090 1111 c0 -39 -1 -41 -42 -52 -24 -7 -68 -11 -98 -9 -90 4 -105 3 -133 -4 -15 -3 -27 -12 -27 -20 0 -10 15 -12 68 -8 53 3 76 0 103 -13 47 -25 78 -50 106 -87 22 -31 23 -39 23 -210 l0 -178 -25 0 c-36 0 -99 -34 -151 -82 -39 -36 -50 -41 -108 -45 -62 -5 -66 -4 -95 25 -21 21 -31 40 -31 61 0 22 -5 31 -16 31 -14 0 -16 -8 -11 -45 8 -79 52 -108 155 -106 59 1 62 0 62 -23 0 -15 12 -35 32 -51 28 -24 38 -26 78 -21 25 3 57 15 72 26 15 11 29 20 32 20 3 0 7 -44 8 -97 4 -144 22 -122 31 37 8 158 8 141 -1 559 -5 245 -10 325 -19 329 -9 2 -13 -9 -13 -37z m-20 -101 c0 -5 -4 -10 -9 -10 -6 0 -13 5 -16 10 -3 6 1 10 9 10 9 0 16 -4 16 -10z m21 -520 c23 -13 25 -50 3 -96 -14 -28 -19 -32 -35 -24 -19 11 -69 78 -69 93 0 8 56 36 73 37 5 0 17 -5 28 -10z" />
|
|
19
|
-
<path d="M760 1091 c-14 -27 -13 -51 3 -51 17 0 69 54 60 63 -13 14 -53 6 -63 -12z" />
|
|
20
|
-
<path d="M647 1053 c-18 -17 -5 -33 28 -33 39 0 46 14 16 30 -23 12 -35 13 -44 3z" />
|
|
21
|
-
<path d="M599 1000 c-5 -29 -2 -33 27 -35 46 -4 65 11 40 30 -22 17 -65 20 -67 5z" />
|
|
22
|
-
<path d="M607 932 c-9 -10 -27 -42 -40 -72 -14 -30 -43 -77 -66 -105 -58 -70 -83 -126 -89 -201 -4 -57 -3 -64 13 -64 28 0 101 82 118 131 l15 44 20 -45 c27 -60 46 -85 60 -76 8 5 2 26 -19 69 -54 106 -49 238 11 292 23 21 26 45 7 45 -8 0 -21 -8 -30 -18z m-117 -261 c0 -12 -20 -25 -27 -18 -7 7 6 27 18 27 5 0 9 -4 9 -9z m30 -11 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m-60 -59 c0 -6 -4 -13 -10 -16 -5 -3 -10 1 -10 9 0 9 5 16 10 16 6 0 10 -4 10 -9z" />
|
|
23
|
-
<path d="M1020 726 c0 -28 12 -46 30 -46 25 0 33 16 20 40 -12 23 -50 27 -50 6z" />
|
|
24
|
-
<path d="M920 615 c-28 -33 13 -61 44 -29 20 20 20 30 0 38 -23 9 -30 8 -44 -9z" />
|
|
25
|
-
<path d="M770 586 c0 -26 24 -51 40 -41 14 8 13 38 -2 53 -19 19 -38 14 -38 -12z" />
|
|
26
|
-
</g>
|
|
27
|
-
</svg>
|
|
28
|
-
);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Tag } from "@bbki.ng/components";
|
|
2
|
-
import React from "react";
|
|
3
|
-
|
|
4
|
-
export const Version = ({ className }: { className?: string }) => {
|
|
5
|
-
// @ts-ignore
|
|
6
|
-
const appVer = GLOBAL_BBKING_VERSION;
|
|
7
|
-
const tagUrl = `https://github.com/bbbottle/bottle/releases/tag/@bbki.ng/site@${appVer}`;
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<Tag to={tagUrl} external prefix="v" className={className}>
|
|
11
|
-
{appVer}
|
|
12
|
-
</Tag>
|
|
13
|
-
);
|
|
14
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { useAuthed } from "@/hooks/use_authed";
|
|
2
|
-
import { useSupabaseSession } from "@/hooks/use_supa_session";
|
|
3
|
-
import {
|
|
4
|
-
ContextMenuItem,
|
|
5
|
-
ContextMenuLabel,
|
|
6
|
-
ContextMenuShortcut,
|
|
7
|
-
Link,
|
|
8
|
-
} from "@bbki.ng/components";
|
|
9
|
-
import React from "react";
|
|
10
|
-
import { useNavigate } from "react-router-dom";
|
|
11
|
-
import { supabase } from "@/constants";
|
|
12
|
-
import { toast } from "sonner";
|
|
13
|
-
import { confirm } from "@/utils";
|
|
14
|
-
|
|
15
|
-
export const LoginMenuItem = () => {
|
|
16
|
-
const sess = useSupabaseSession();
|
|
17
|
-
const nav = useNavigate();
|
|
18
|
-
|
|
19
|
-
if (sess?.user != null) {
|
|
20
|
-
return (
|
|
21
|
-
<ContextMenuItem
|
|
22
|
-
onClick={() => {
|
|
23
|
-
confirm("确定退出登录吗?", () => {
|
|
24
|
-
supabase.auth.signOut().then(() => {
|
|
25
|
-
toast.success("已退出登录", {
|
|
26
|
-
position: "bottom-right",
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
}}
|
|
31
|
-
>
|
|
32
|
-
{sess?.user?.user_metadata && (
|
|
33
|
-
<img
|
|
34
|
-
src={sess?.user?.user_metadata.avatar_url}
|
|
35
|
-
alt="avatar"
|
|
36
|
-
style={{ width: 16, height: 16 }}
|
|
37
|
-
className="mr-8"
|
|
38
|
-
crossOrigin="anonymous"
|
|
39
|
-
/>
|
|
40
|
-
)}
|
|
41
|
-
{sess?.user?.email ?? ""}
|
|
42
|
-
</ContextMenuItem>
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<ContextMenuItem
|
|
48
|
-
onClick={() => {
|
|
49
|
-
nav("/login");
|
|
50
|
-
}}
|
|
51
|
-
>
|
|
52
|
-
<svg
|
|
53
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
54
|
-
width="16"
|
|
55
|
-
height="16"
|
|
56
|
-
viewBox="0 0 24 24"
|
|
57
|
-
fill="none"
|
|
58
|
-
stroke="currentColor"
|
|
59
|
-
strokeWidth="2"
|
|
60
|
-
strokeLinecap="round"
|
|
61
|
-
strokeLinejoin="round"
|
|
62
|
-
className="feather feather-log-in mr-8"
|
|
63
|
-
>
|
|
64
|
-
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
|
65
|
-
<polyline points="10 17 15 12 10 7"></polyline>
|
|
66
|
-
<line x1="15" y1="12" x2="3" y2="12"></line>
|
|
67
|
-
</svg>
|
|
68
|
-
login
|
|
69
|
-
<ContextMenuShortcut className="mr-1">l</ContextMenuShortcut>
|
|
70
|
-
</ContextMenuItem>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ContextMenuItem } from "@bbki.ng/components";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import {useAuthedStringPost} from "@/hooks/use_authed_string_post";
|
|
4
|
-
|
|
5
|
-
export const PostMenuItem = () => {
|
|
6
|
-
|
|
7
|
-
const post = useAuthedStringPost();
|
|
8
|
-
|
|
9
|
-
const postFromClipboard = () => {
|
|
10
|
-
navigator.clipboard
|
|
11
|
-
.readText()
|
|
12
|
-
.then(post);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<ContextMenuItem onClick={postFromClipboard}
|
|
17
|
-
inset
|
|
18
|
-
>
|
|
19
|
-
post from clipboard
|
|
20
|
-
</ContextMenuItem>
|
|
21
|
-
);
|
|
22
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { ContextMenuItem, Tag } from "@bbki.ng/components";
|
|
2
|
-
import React from "react";
|
|
3
|
-
|
|
4
|
-
export const VersionMenuItem = () => {
|
|
5
|
-
// @ts-ignore
|
|
6
|
-
const appVer = GLOBAL_BBKING_VERSION;
|
|
7
|
-
|
|
8
|
-
return (
|
|
9
|
-
<ContextMenuItem inset disabled>
|
|
10
|
-
v{appVer}
|
|
11
|
-
</ContextMenuItem>
|
|
12
|
-
);
|
|
13
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { ContextMenuItem, ContextMenuShortcut } from "@bbki.ng/components";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { GITHUB_REPO_ADDRESS } from "@/constants";
|
|
4
|
-
|
|
5
|
-
export const ViewSourceMenuItem = () => {
|
|
6
|
-
// @ts-ignore
|
|
7
|
-
const appVer = GLOBAL_BBKING_VERSION;
|
|
8
|
-
return (
|
|
9
|
-
<ContextMenuItem
|
|
10
|
-
onClick={() => {
|
|
11
|
-
// open tagUrl in new tab
|
|
12
|
-
window.open(GITHUB_REPO_ADDRESS, "_blank");
|
|
13
|
-
}}
|
|
14
|
-
>
|
|
15
|
-
<svg
|
|
16
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
-
width="16"
|
|
18
|
-
height="16"
|
|
19
|
-
viewBox="0 0 24 24"
|
|
20
|
-
fill="none"
|
|
21
|
-
stroke="currentColor"
|
|
22
|
-
strokeWidth="2"
|
|
23
|
-
strokeLinecap="round"
|
|
24
|
-
strokeLinejoin="round"
|
|
25
|
-
className="feather feather-code mr-8"
|
|
26
|
-
>
|
|
27
|
-
<polyline points="16 18 22 12 16 6"></polyline>
|
|
28
|
-
<polyline points="8 6 2 12 8 18"></polyline>
|
|
29
|
-
</svg>
|
|
30
|
-
v{appVer}
|
|
31
|
-
<ContextMenuShortcut className="mr-1">s</ContextMenuShortcut>
|
|
32
|
-
</ContextMenuItem>
|
|
33
|
-
);
|
|
34
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import React, { ReactElement, useEffect } from "react";
|
|
2
|
-
import {
|
|
3
|
-
ContextMenu,
|
|
4
|
-
ContextMenuContent,
|
|
5
|
-
ContextMenuTrigger,
|
|
6
|
-
ContextMenuSeparator,
|
|
7
|
-
ContextMenuShortcut,
|
|
8
|
-
ContextMenuItem,
|
|
9
|
-
} from "@bbki.ng/components";
|
|
10
|
-
import { LoginMenuItem } from "@/components/app_ctx_menu/LoginMenuItem";
|
|
11
|
-
import { ViewSourceMenuItem } from "@/components/app_ctx_menu/ViewSourceMenuItem";
|
|
12
|
-
import { PostMenuItem } from "@/components/app_ctx_menu/PostMenuItem";
|
|
13
|
-
import { useAuthed } from "@/hooks/use_authed";
|
|
14
|
-
|
|
15
|
-
export const AppCtxMenu = (props: { children: ReactElement }) => {
|
|
16
|
-
const [showPluginEntry, setShowPluginEntry] = React.useState(false);
|
|
17
|
-
|
|
18
|
-
const showEntry = () => {
|
|
19
|
-
setShowPluginEntry(true);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const isKing = useAuthed();
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<ContextMenu>
|
|
26
|
-
<ContextMenuTrigger>{props.children}</ContextMenuTrigger>
|
|
27
|
-
<ContextMenuContent className="">
|
|
28
|
-
<LoginMenuItem />
|
|
29
|
-
<ViewSourceMenuItem />
|
|
30
|
-
{isKing && <PostMenuItem />}
|
|
31
|
-
{/*{showPluginEntry && <PluginsMenuItem />}*/}
|
|
32
|
-
</ContextMenuContent>
|
|
33
|
-
</ContextMenu>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import React, { ReactElement, useCallback } from "react";
|
|
2
|
-
import { useAuthed } from "@/hooks/use_authed";
|
|
3
|
-
import {
|
|
4
|
-
ContextMenu,
|
|
5
|
-
ContextMenuContent,
|
|
6
|
-
ContextMenuTrigger,
|
|
7
|
-
ContextMenuItem,
|
|
8
|
-
} from "@bbki.ng/components";
|
|
9
|
-
import { useNavigate, useParams } from "react-router-dom";
|
|
10
|
-
import { useDelPost } from "@/hooks/use_delete_post";
|
|
11
|
-
import { toast } from "sonner";
|
|
12
|
-
import { confirm } from "@/utils";
|
|
13
|
-
import { useLoadingIndicator } from "@/hooks/useLoadingIndicator";
|
|
14
|
-
|
|
15
|
-
export const ArticleCtxMenu = (props: { children: ReactElement }) => {
|
|
16
|
-
const auth = useAuthed();
|
|
17
|
-
const del = useDelPost();
|
|
18
|
-
const routeParams = useParams();
|
|
19
|
-
const nav = useNavigate();
|
|
20
|
-
const title = routeParams.title;
|
|
21
|
-
const dot = useLoadingIndicator();
|
|
22
|
-
|
|
23
|
-
if (!auth) {
|
|
24
|
-
return props.children;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (title == null || title === "") {
|
|
28
|
-
return props.children;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const doDel = useCallback(() => {
|
|
32
|
-
dot.setVisibility(true);
|
|
33
|
-
del(title)
|
|
34
|
-
.then(() => {
|
|
35
|
-
toast.success("删除成功", {
|
|
36
|
-
position: "bottom-right",
|
|
37
|
-
});
|
|
38
|
-
dot.setVisibility(false);
|
|
39
|
-
nav("/blog");
|
|
40
|
-
})
|
|
41
|
-
.catch(console.log);
|
|
42
|
-
}, [title]);
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<ContextMenu>
|
|
46
|
-
<ContextMenuTrigger>{props.children}</ContextMenuTrigger>
|
|
47
|
-
<ContextMenuContent>
|
|
48
|
-
<ContextMenuItem
|
|
49
|
-
onClick={() => {
|
|
50
|
-
confirm("确认删除?", doDel);
|
|
51
|
-
}}
|
|
52
|
-
>
|
|
53
|
-
remove
|
|
54
|
-
</ContextMenuItem>
|
|
55
|
-
</ContextMenuContent>
|
|
56
|
-
</ContextMenu>
|
|
57
|
-
);
|
|
58
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import classnames from "classnames";
|
|
3
|
-
import { TextColors } from "@/types/color";
|
|
4
|
-
|
|
5
|
-
type blurCoverProps = {
|
|
6
|
-
textColor?: TextColors;
|
|
7
|
-
className?: string;
|
|
8
|
-
children: any;
|
|
9
|
-
height?: number;
|
|
10
|
-
visibleOnHover?: boolean;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const BlurCover = (props: blurCoverProps) => {
|
|
14
|
-
const { textColor, children, className, height = 50, visibleOnHover } = props;
|
|
15
|
-
const cls = classnames(
|
|
16
|
-
className,
|
|
17
|
-
textColor,
|
|
18
|
-
"blur-cover",
|
|
19
|
-
"absolute",
|
|
20
|
-
"w-full",
|
|
21
|
-
"flex items-center justify-center"
|
|
22
|
-
);
|
|
23
|
-
return (
|
|
24
|
-
<div className={cls} style={{ height }}>
|
|
25
|
-
{children}
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { useNavigate } from "react-router-dom";
|
|
2
|
-
import { useHotkeys } from "react-hotkeys-hook";
|
|
3
|
-
import { GITHUB_REPO_ADDRESS, ROUTES } from "@/constants";
|
|
4
|
-
|
|
5
|
-
enum HotKeys {
|
|
6
|
-
i = "i",
|
|
7
|
-
e = "e",
|
|
8
|
-
c = "c",
|
|
9
|
-
t = "t",
|
|
10
|
-
p = "p",
|
|
11
|
-
a = "a",
|
|
12
|
-
f = "f",
|
|
13
|
-
b = "b",
|
|
14
|
-
h = "h",
|
|
15
|
-
s = "s",
|
|
16
|
-
l = "l",
|
|
17
|
-
T = "shift+t",
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const KEY_ROUTES = [
|
|
21
|
-
{ key: HotKeys.i, route: ROUTES.INDEX },
|
|
22
|
-
{ key: HotKeys.c, route: ROUTES.CONTENT },
|
|
23
|
-
{ key: HotKeys.h, route: ROUTES.HELP },
|
|
24
|
-
{ key: HotKeys.t, route: ROUTES.TAGS },
|
|
25
|
-
{ key: HotKeys.l, route: ROUTES.LOGIN },
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
export const HotKeyNav = (props: any) => {
|
|
29
|
-
const nav = useNavigate();
|
|
30
|
-
const goto = (path: string) => {
|
|
31
|
-
nav(path);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
useHotkeys(HotKeys.b, () => {
|
|
35
|
-
nav(-1);
|
|
36
|
-
});
|
|
37
|
-
useHotkeys(HotKeys.f, () => {
|
|
38
|
-
nav(1);
|
|
39
|
-
});
|
|
40
|
-
useHotkeys(HotKeys.s, () => {
|
|
41
|
-
window.open(GITHUB_REPO_ADDRESS);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
KEY_ROUTES.map(({ key, route }) => {
|
|
45
|
-
useHotkeys(key, () => {
|
|
46
|
-
goto(route);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
return props.children;
|
|
51
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import classnames from "classnames";
|
|
3
|
-
import { BgColors } from "@/types/color";
|
|
4
|
-
import { floatNumberToPercentageString } from "@/utils";
|
|
5
|
-
|
|
6
|
-
type progressBarProps = {
|
|
7
|
-
bgColor?: BgColors;
|
|
8
|
-
fgColor?: BgColors;
|
|
9
|
-
height?: number;
|
|
10
|
-
progress: number;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const ProgressBar = (props: progressBarProps) => {
|
|
14
|
-
const {
|
|
15
|
-
height = 2,
|
|
16
|
-
fgColor = BgColors.BLUE,
|
|
17
|
-
bgColor = BgColors.GRAY,
|
|
18
|
-
progress,
|
|
19
|
-
} = props;
|
|
20
|
-
|
|
21
|
-
const wrapperCls = classnames("w-full", "text-left", bgColor);
|
|
22
|
-
const innerBarCls = classnames("h-full", fgColor);
|
|
23
|
-
return (
|
|
24
|
-
<div className={wrapperCls} style={{ height }}>
|
|
25
|
-
<div
|
|
26
|
-
className={innerBarCls}
|
|
27
|
-
style={{ width: floatNumberToPercentageString(progress) }}
|
|
28
|
-
/>
|
|
29
|
-
</div>
|
|
30
|
-
);
|
|
31
|
-
};
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { ReactNode } from "react";
|
|
3
|
-
|
|
4
|
-
const HEART_SIZE = 12;
|
|
5
|
-
|
|
6
|
-
export interface ReactionEmojiPair {
|
|
7
|
-
on: ReactNode;
|
|
8
|
-
off: ReactNode;
|
|
9
|
-
val: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const heart = (
|
|
13
|
-
<svg
|
|
14
|
-
data-testid="geist-icon"
|
|
15
|
-
height={HEART_SIZE}
|
|
16
|
-
width={HEART_SIZE}
|
|
17
|
-
stroke-linejoin="round"
|
|
18
|
-
viewBox="0 0 16 16"
|
|
19
|
-
>
|
|
20
|
-
<path
|
|
21
|
-
fill-rule="evenodd"
|
|
22
|
-
clip-rule="evenodd"
|
|
23
|
-
d="M7.06463 3.20474C5.79164 1.93175 3.72772 1.93175 2.45474 3.20474C1.18175 4.47773 1.18175 6.54166 2.45474 7.81465L8 13.3599L13.5453 7.81465C14.8182 6.54166 14.8182 4.47773 13.5453 3.20474C12.2723 1.93175 10.2084 1.93175 8.93537 3.20474L8.53033 3.60979L8 4.14012L7.46967 3.60979L7.06463 3.20474ZM8 2.02321C6.13348 0.286219 3.21165 0.326509 1.39408 2.14408C-0.464694 4.00286 -0.464691 7.01653 1.39408 8.87531L7.46967 14.9509L8 15.4812L8.53033 14.9509L14.6059 8.87531C16.4647 7.01653 16.4647 4.00286 14.6059 2.14408C12.7884 0.326509 9.86653 0.286221 8 2.02321Z"
|
|
24
|
-
fill="currentColor"
|
|
25
|
-
></path>
|
|
26
|
-
</svg>
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
const heartFill = (
|
|
30
|
-
<svg
|
|
31
|
-
data-testid="geist-icon"
|
|
32
|
-
height={HEART_SIZE}
|
|
33
|
-
width={HEART_SIZE}
|
|
34
|
-
stroke-linejoin="round"
|
|
35
|
-
className="text-red-400"
|
|
36
|
-
viewBox={`0 0 16 16`}
|
|
37
|
-
>
|
|
38
|
-
<path
|
|
39
|
-
d="M1.39408 2.14408C3.21165 0.326509 6.13348 0.286219 8 2.02321C9.86652 0.286221 12.7884 0.326509 14.6059 2.14408C16.4647 4.00286 16.4647 7.01653 14.6059 8.87531L8 15.4812L1.39408 8.87531C-0.464691 7.01653 -0.464694 4.00286 1.39408 2.14408Z"
|
|
40
|
-
fill="currentColor"
|
|
41
|
-
></path>
|
|
42
|
-
</svg>
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const happyFace = (
|
|
46
|
-
<svg
|
|
47
|
-
data-testid="geist-icon"
|
|
48
|
-
stroke-linejoin="round"
|
|
49
|
-
height={HEART_SIZE}
|
|
50
|
-
width={HEART_SIZE}
|
|
51
|
-
viewBox="0 0 16 16"
|
|
52
|
-
>
|
|
53
|
-
<path
|
|
54
|
-
fill-rule="evenodd"
|
|
55
|
-
clip-rule="evenodd"
|
|
56
|
-
d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM11.5249 10.8478L11.8727 10.3286L10.8342 9.6329L10.4863 10.1522C9.94904 10.9543 9.0363 11.4802 8.00098 11.4802C6.96759 11.4802 6.05634 10.9563 5.51863 10.1567L5.16986 9.63804L4.13259 10.3356L4.48137 10.8542C5.2414 11.9844 6.53398 12.7302 8.00098 12.7302C9.47073 12.7302 10.7654 11.9816 11.5249 10.8478ZM6.75 6.75C6.75 7.30228 6.30228 7.75 5.75 7.75C5.19772 7.75 4.75 7.30228 4.75 6.75C4.75 6.19772 5.19772 5.75 5.75 5.75C6.30228 5.75 6.75 6.19772 6.75 6.75ZM10.25 7.75C10.8023 7.75 11.25 7.30228 11.25 6.75C11.25 6.19772 10.8023 5.75 10.25 5.75C9.69771 5.75 9.25 6.19772 9.25 6.75C9.25 7.30228 9.69771 7.75 10.25 7.75Z"
|
|
57
|
-
fill="currentColor"
|
|
58
|
-
></path>
|
|
59
|
-
</svg>
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
const smileFace = (
|
|
63
|
-
<svg
|
|
64
|
-
height={HEART_SIZE}
|
|
65
|
-
width={HEART_SIZE}
|
|
66
|
-
data-testid="geist-icon"
|
|
67
|
-
className="text-gray-400"
|
|
68
|
-
stroke-linejoin="round"
|
|
69
|
-
viewBox="0 0 16 16"
|
|
70
|
-
>
|
|
71
|
-
<path
|
|
72
|
-
fill-rule="evenodd"
|
|
73
|
-
clip-rule="evenodd"
|
|
74
|
-
d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM4.5 8.97498H3.875V9.59998C3.875 11.4747 5.81046 12.8637 7.99817 12.8637C10.1879 12.8637 12.125 11.4832 12.125 9.59998V8.97498H11.5H4.5ZM7.99817 11.6137C6.59406 11.6137 5.63842 10.9482 5.28118 10.225H10.7202C10.3641 10.9504 9.40797 11.6137 7.99817 11.6137Z"
|
|
75
|
-
fill="currentColor"
|
|
76
|
-
></path>
|
|
77
|
-
<path
|
|
78
|
-
fill-rule="evenodd"
|
|
79
|
-
clip-rule="evenodd"
|
|
80
|
-
d="M6.15295 4.92093L5.375 3.5L4.59705 4.92093L3 5.21885L4.11625 6.39495L3.90717 8L5.375 7.30593L6.84283 8L6.63375 6.39495L7.75 5.21885L6.15295 4.92093ZM11.403 4.92093L10.625 3.5L9.84705 4.92093L8.25 5.21885L9.36625 6.39495L9.15717 8L10.625 7.30593L12.0928 8L11.8837 6.39495L13 5.21885L11.403 4.92093Z"
|
|
81
|
-
fill="var(--ds-amber-800)"
|
|
82
|
-
></path>
|
|
83
|
-
</svg>
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const unhappyFace = (
|
|
87
|
-
<svg
|
|
88
|
-
data-testid="geist-icon"
|
|
89
|
-
stroke-linejoin="round"
|
|
90
|
-
viewBox="0 0 16 16"
|
|
91
|
-
height={HEART_SIZE}
|
|
92
|
-
width={HEART_SIZE}
|
|
93
|
-
>
|
|
94
|
-
<path
|
|
95
|
-
fill-rule="evenodd"
|
|
96
|
-
clip-rule="evenodd"
|
|
97
|
-
d="M14.5 8C14.5 11.5899 11.5899 14.5 8 14.5C4.41015 14.5 1.5 11.5899 1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8ZM16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM5.75 7.75C6.30228 7.75 6.75 7.30228 6.75 6.75C6.75 6.19772 6.30228 5.75 5.75 5.75C5.19772 5.75 4.75 6.19772 4.75 6.75C4.75 7.30228 5.19772 7.75 5.75 7.75ZM11.25 6.75C11.25 7.30228 10.8023 7.75 10.25 7.75C9.69771 7.75 9.25 7.30228 9.25 6.75C9.25 6.19772 9.69771 5.75 10.25 5.75C10.8023 5.75 11.25 6.19772 11.25 6.75ZM11.5249 11.2622L11.8727 11.7814L10.8342 12.4771L10.4863 11.9578C9.94904 11.1557 9.0363 10.6298 8.00098 10.6298C6.96759 10.6298 6.05634 11.1537 5.51863 11.9533L5.16986 12.4719L4.13259 11.7744L4.48137 11.2558C5.2414 10.1256 6.53398 9.37982 8.00098 9.37982C9.47073 9.37982 10.7654 10.1284 11.5249 11.2622Z"
|
|
98
|
-
fill="currentColor"
|
|
99
|
-
></path>
|
|
100
|
-
</svg>
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const sadFace = (
|
|
104
|
-
<svg
|
|
105
|
-
data-testid="geist-icon"
|
|
106
|
-
stroke-linejoin="round"
|
|
107
|
-
height={HEART_SIZE}
|
|
108
|
-
width={HEART_SIZE}
|
|
109
|
-
viewBox="0 0 16 16"
|
|
110
|
-
className="text-gray-400"
|
|
111
|
-
>
|
|
112
|
-
<path
|
|
113
|
-
fill-rule="evenodd"
|
|
114
|
-
clip-rule="evenodd"
|
|
115
|
-
d="M4 9V16H5.5V9H4ZM12 9V16H10.5V9H12Z"
|
|
116
|
-
fill="var(--ds-blue-700)"
|
|
117
|
-
></path>
|
|
118
|
-
<path
|
|
119
|
-
fill-rule="evenodd"
|
|
120
|
-
clip-rule="evenodd"
|
|
121
|
-
d="M1.5 8C1.5 4.41015 4.41015 1.5 8 1.5C11.5899 1.5 14.5 4.41015 14.5 8C14.5 9.57941 13.9367 11.0273 13 12.1536V14.2454C14.8289 12.7793 16 10.5264 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 10.5264 1.17107 12.7793 3 14.2454V12.1536C2.06332 11.0273 1.5 9.57941 1.5 8ZM8 14.5C8.51627 14.5 9.01848 14.4398 9.5 14.3261V15.8596C9.01412 15.9518 8.51269 16 8 16C7.48731 16 6.98588 15.9518 6.5 15.8596V14.3261C6.98152 14.4398 7.48373 14.5 8 14.5ZM3.78568 8.36533C4.15863 7.98474 4.67623 7.75 5.25 7.75C5.82377 7.75 6.34137 7.98474 6.71432 8.36533L7.78568 7.31548C7.14222 6.65884 6.24318 6.25 5.25 6.25C4.25682 6.25 3.35778 6.65884 2.71432 7.31548L3.78568 8.36533ZM10.75 7.75C10.1762 7.75 9.65863 7.98474 9.28568 8.36533L8.21432 7.31548C8.85778 6.65884 9.75682 6.25 10.75 6.25C11.7432 6.25 12.6422 6.65884 13.2857 7.31548L12.2143 8.36533C11.8414 7.98474 11.3238 7.75 10.75 7.75ZM6.25 12H9.75C9.75 11.0335 8.9665 10.25 8 10.25C7.0335 10.25 6.25 11.0335 6.25 12Z"
|
|
122
|
-
fill="currentColor"
|
|
123
|
-
></path>
|
|
124
|
-
</svg>
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
export const hearts: ReactionEmojiPair = {
|
|
128
|
-
on: heartFill,
|
|
129
|
-
off: heart,
|
|
130
|
-
val: "❤️",
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export const faces: ReactionEmojiPair = {
|
|
134
|
-
on: smileFace,
|
|
135
|
-
off: happyFace,
|
|
136
|
-
val: "🙂",
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export const sadFaces: ReactionEmojiPair = {
|
|
140
|
-
on: sadFace,
|
|
141
|
-
off: unhappyFace,
|
|
142
|
-
val: "😞",
|
|
143
|
-
};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
ReactNode,
|
|
3
|
-
useContext,
|
|
4
|
-
useEffect,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from "react";
|
|
8
|
-
import { GlobalLoadingContext } from "@/context/global_loading_state_provider";
|
|
9
|
-
import { BlinkDot, Button, ButtonType } from "@bbki.ng/components";
|
|
10
|
-
import { faces, hearts, ReactionEmojiPair, sadFaces } from "./emojis";
|
|
11
|
-
import { ShareBtn } from "../share/share-btn";
|
|
12
|
-
|
|
13
|
-
declare global {
|
|
14
|
-
namespace JSX {
|
|
15
|
-
interface IntrinsicElements {
|
|
16
|
-
"open-heart": React.DetailedHTMLProps<
|
|
17
|
-
React.HTMLAttributes<HTMLElement> & {
|
|
18
|
-
href?: string;
|
|
19
|
-
emoji?: string;
|
|
20
|
-
ariaDisabled?: boolean;
|
|
21
|
-
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
22
|
-
},
|
|
23
|
-
HTMLElement
|
|
24
|
-
>;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const useHeartSent = (val: string) => {
|
|
30
|
-
const [sent, setSent] = useState(false);
|
|
31
|
-
const { setIsLoading } = useContext(GlobalLoadingContext);
|
|
32
|
-
|
|
33
|
-
const handleSent = (evt: Event) => {
|
|
34
|
-
const targetVal = (evt.target as HTMLElement).getAttribute("emoji");
|
|
35
|
-
|
|
36
|
-
if (targetVal == val) setSent(true);
|
|
37
|
-
setIsLoading(false);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
addEventListener("open-heart", handleSent);
|
|
42
|
-
|
|
43
|
-
return () => {
|
|
44
|
-
removeEventListener("open-heart", handleSent);
|
|
45
|
-
};
|
|
46
|
-
}, []);
|
|
47
|
-
|
|
48
|
-
return sent;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const OpenHeartReaction = (props: {
|
|
52
|
-
title: string;
|
|
53
|
-
emojiPair: ReactionEmojiPair;
|
|
54
|
-
}) => {
|
|
55
|
-
const { title, emojiPair = hearts } = props;
|
|
56
|
-
const sent = useHeartSent(emojiPair.val);
|
|
57
|
-
|
|
58
|
-
const { setIsLoading } = useContext(GlobalLoadingContext);
|
|
59
|
-
|
|
60
|
-
const ohRef = useRef<HTMLElement>(null);
|
|
61
|
-
|
|
62
|
-
const pressed = () => ohRef.current?.getAttribute("aria-pressed");
|
|
63
|
-
|
|
64
|
-
const handleHeartClick = () => {
|
|
65
|
-
if (sent || pressed()) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
setIsLoading(true);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<open-heart
|
|
74
|
-
ref={ohRef}
|
|
75
|
-
href={`https://oh.bbki.ng/?id=${title}`}
|
|
76
|
-
emoji={emojiPair.val}
|
|
77
|
-
>
|
|
78
|
-
<Button
|
|
79
|
-
size="small"
|
|
80
|
-
type={ButtonType.GHOST}
|
|
81
|
-
className="text-gray-400 hover:text-gray-600 transition-colors ease-in duration-200"
|
|
82
|
-
onClick={handleHeartClick}
|
|
83
|
-
>
|
|
84
|
-
{sent || pressed() ? emojiPair.on : emojiPair.off}
|
|
85
|
-
</Button>
|
|
86
|
-
</open-heart>
|
|
87
|
-
);
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const Reaction = (props: { title: string; url: string }) => {
|
|
91
|
-
return (
|
|
92
|
-
<div className="flex items-center">
|
|
93
|
-
<OpenHeartReaction title={props.title} emojiPair={hearts} />
|
|
94
|
-
<OpenHeartReaction title={props.title} emojiPair={faces} />
|
|
95
|
-
<OpenHeartReaction title={props.title} emojiPair={sadFaces} />
|
|
96
|
-
|
|
97
|
-
<ShareBtn
|
|
98
|
-
shareInfo={{
|
|
99
|
-
title: props.title,
|
|
100
|
-
url: props.url,
|
|
101
|
-
}}
|
|
102
|
-
/>
|
|
103
|
-
</div>
|
|
104
|
-
);
|
|
105
|
-
};
|