Skip to content

Commit 2dee845

Browse files
authoredSep 18, 2022
Add share button (#31)
* fix: Update package.json * feat(share-button): Add share button in place of homepage link * fix: Hot fix tests * refactor(share-button): Remove email link option via disable feature flag
1 parent 372a170 commit 2dee845

File tree

8 files changed

+127
-14
lines changed

8 files changed

+127
-14
lines changed
 

‎components/ShareButton.tsx

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { EnvelopeIcon, ExportIcon, IconButton, LinkIcon, Menu, Popover, Position, ShareIcon, toaster } from "evergreen-ui"
2+
import { option } from "fp-ts";
3+
import { pipe } from "fp-ts/lib/function";
4+
import { useEffect, useState } from "react";
5+
import { Package } from "../api/domain";
6+
7+
type Props = {
8+
package: Package
9+
}
10+
11+
const FEATURE_FLAG_EMAIL_LINK = false;
12+
13+
export const ShareButton = (props: Props) => {
14+
const [url, setUrl] = useState<string | undefined>(undefined);
15+
const [canShare, setCanShare] = useState<boolean | undefined>(undefined);
16+
17+
const onClick = () => pipe(
18+
url,
19+
option.fromNullable,
20+
option.fold(
21+
() => toaster.warning("Unable to share package", {id: "toaster-share-unable"}),
22+
u => navigator.share({
23+
title: props.package.title,
24+
text: props.package.description,
25+
url: u
26+
})
27+
)
28+
);
29+
30+
const onCopyLink = () => pipe(
31+
url,
32+
option.fromNullable,
33+
option.fold(
34+
() => toaster.warning("Unable to copy link to the clipboard", {id: "toaster-link-copy-unable"}),
35+
u => navigator.clipboard
36+
.writeText(u)
37+
.then(() => toaster.success("Link copied to the clipboard!", {
38+
id: "toaster-link-copy-success"
39+
}))
40+
)
41+
)
42+
43+
const onEmailLink = () => pipe(
44+
url,
45+
option.fromNullable,
46+
option.fold(
47+
() => toaster.warning("Unable to share link via email", {id: "toaster-link-email-unable"}),
48+
u => {
49+
const subject = `Check out Espanso's ${props.package.title} package!`
50+
const body = `Hello,
51+
I just found out "${props.package.title}", an Espanso package you might be interested into.
52+
53+
Check it out at ${u}
54+
`;
55+
document.location = encodeURI(`mailto:?subject=${subject}&body=${body}`);
56+
},
57+
)
58+
)
59+
60+
useEffect(() => {
61+
setCanShare(typeof navigator.share === "function");
62+
setUrl(`${window.location.hostname}${window.location.pathname}${window.location.search}`);
63+
}, []);
64+
65+
const linkShareLayout = <Popover
66+
position={Position.BOTTOM_RIGHT}
67+
content={
68+
<Menu>
69+
<Menu.Group>
70+
<Menu.Item
71+
icon={LinkIcon}
72+
onSelect={onCopyLink}>
73+
Copy Link
74+
</Menu.Item>
75+
{FEATURE_FLAG_EMAIL_LINK ?? <Menu.Item
76+
icon={EnvelopeIcon}
77+
onSelect={onEmailLink}>
78+
Email Link
79+
</Menu.Item>}
80+
</Menu.Group>
81+
</Menu>}>
82+
<IconButton icon={ExportIcon} appearance="minimal"/>
83+
</Popover>
84+
85+
const webShareAPILayout = <IconButton
86+
icon={ShareIcon}
87+
appearance="minimal"
88+
onClick={onClick}/>
89+
90+
return canShare ? webShareAPILayout : linkShareLayout;
91+
}

‎components/icons/GithubIcon.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { espansoTheme } from "../EspansoThemeProvider";
2+
3+
type Props = {
4+
size: number;
5+
}
6+
7+
export const GithubIcon = (props: Props) =>
8+
<svg
9+
xmlns="http://www.w3.org/2000/svg"
10+
width={props.size}
11+
height={props.size}
12+
viewBox="0 0 24 24"
13+
fill={espansoTheme.colors.gray700}>
14+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
15+
</svg>

‎components/icons/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./GithubIcon";

‎components/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ export * from "./BetaBanner";
1212
export * from "./Footer";
1313
export * from "./SearchBar";
1414
export * from "./NextjsLink";
15+
export * from "./ShareButton";
16+
export * from "./icons";

‎components/layout/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from "./ContentRow";
22
export * from "./Stack";
33
export * from "./useTabs";
4+
export * from "./useResponsive";

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"scripts": {
3939
"clean-cache": "rm -rf .cache",
4040
"prebuild": "yarn clean-cache",
41-
"predev": "yarn clen-cache",
41+
"predev": "yarn clean-cache",
4242
"dev": "next dev",
4343
"build": "next build",
4444
"postbuild": "next-sitemap",

‎pages/[packageName]/v/[version].tsx

+14-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
Paragraph,
1313
Position,
1414
SelectMenu,
15-
ShareIcon,
1615
SideSheet,
1716
Text,
1817
} from "evergreen-ui";
@@ -55,12 +54,15 @@ import {
5554
Footer,
5655
MDXRenderer,
5756
Navbar,
57+
NextjsLink,
5858
Stack,
5959
TabProps,
6060
TagBadgeGroup,
6161
useTabs,
62+
useResponsive,
63+
ShareButton,
64+
GithubIcon
6265
} from "../../../components";
63-
import { useResponsive } from "../../../components/layout/useResponsive";
6466
import { splitLines } from "../../../api/utils"
6567

6668
export type Props = {
@@ -267,19 +269,20 @@ const VersionedPackagePage = (props: Props) => {
267269

268270
<Pane flexGrow={1} />
269271
<Stack units={1} alignItems="center">
272+
<ShareButton package={currentRepo.package}/>
270273
{pipe(
271274
currentRepo.manifest.homepage,
272-
option.map((homepage) => (
273-
<IconButton
274-
icon={ShareIcon}
275-
appearance="minimal"
276-
onClick={() => {
277-
window.open(homepage, "_blank");
278-
}}
279-
/>
280-
)),
275+
option.map(url =>
276+
<NextjsLink href={url} external>
277+
<IconButton
278+
icon={GithubIcon}
279+
iconSize={18}
280+
appearance="minimal"
281+
color={espansoTheme.colors.gray700}/>
282+
</NextjsLink>),
281283
option.toNullable
282284
)}
285+
283286

284287
{pipe(
285288
currentVersion,

‎test/api/packagesIndex.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ describe("packagesIndex API", () => {
2424
author: "author",
2525
description: "description",
2626
title: "title",
27-
version: "x.x.x",
27+
version: "0.0.1",
2828
archive_url: "archive_url",
2929
archive_sha256_url: "archive_sha256_url"
3030
}
@@ -34,7 +34,7 @@ describe("packagesIndex API", () => {
3434
author: "author",
3535
description: "description",
3636
title: "title",
37-
version: "x.x.x",
37+
version: "0.0.1",
3838
tags: [
3939
"tag1",
4040
"tag2",

0 commit comments

Comments
 (0)
Please sign in to comment.