Skip to content

Commit 7cdc0e7

Browse files
committed
feat: note side share
Signed-off-by: Innei <[email protected]>
1 parent dffd250 commit 7cdc0e7

File tree

4 files changed

+47
-10
lines changed

4 files changed

+47
-10
lines changed

src/components/common/ToastCard.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { useId } from 'react'
12
import clsx from 'clsx'
3+
import { motion } from 'framer-motion'
24
import type { FC } from 'react'
35
import type { ToastProps, TypeOptions } from 'react-toastify/dist/types'
46

@@ -21,9 +23,11 @@ export const ToastCard: FC<{
2123
closeToast?: () => void
2224
}> = (props) => {
2325
const { iconElement, message, closeToast } = props
24-
26+
const id = useId()
2527
return (
26-
<div
28+
<motion.div
29+
layoutId={id}
30+
layout="position"
2731
className={clsx(
2832
'relative w-full overflow-hidden rounded-xl shadow-out-sm',
2933
'my-4 mr-4 px-4 py-5',
@@ -42,6 +46,6 @@ export const ToastCard: FC<{
4246
>
4347
<i className="icon-[mingcute--close-fill] p-2" />
4448
</MotionButtonBase>
45-
</div>
49+
</motion.div>
4650
)
4751
}

src/components/layout/header/internal/UserAuth.tsx

+3-7
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,16 @@ import {
1212
useUser,
1313
} from '@clerk/nextjs'
1414

15-
import { appConfig } from '~/app.config'
1615
import { GitHubBrandIcon } from '~/components/icons/platform/GitHubBrandIcon'
1716
import { GoogleBrandIcon } from '~/components/icons/platform/GoogleBrandIcon'
1817
import { MailIcon } from '~/components/icons/platform/MailIcon'
1918
import { UserArrowLeftIcon } from '~/components/icons/user-arrow-left'
2019
import { FloatPopover } from '~/components/ui/float-popover'
20+
import { urlBuilder } from '~/lib/url-builder'
2121
import { clsxm } from '~/utils/helper'
2222

2323
import { HeaderActionButton } from './HeaderActionButton'
2424

25-
function url(path = '') {
26-
return new URL(path, appConfig.site.url)
27-
}
28-
2925
export function UserAuth() {
3026
const pathname = usePathname()
3127

@@ -35,7 +31,7 @@ export function UserAuth() {
3531
<div className="pointer-events-auto flex h-10 w-full items-center justify-center">
3632
<div className="relative">
3733
<UserButton
38-
afterSignOutUrl={url(pathname).href}
34+
afterSignOutUrl={urlBuilder(pathname).href}
3935
appearance={{
4036
elements: {
4137
logoBox: 'w-9 h-9 ring-2 ring-white/20 rounded-full',
@@ -96,7 +92,7 @@ const UserAuthFromIcon: Component = ({ className }) => {
9692
const TriggerComponent = () => {
9793
const pathname = usePathname()
9894
return (
99-
<SignInButton mode="modal" redirectUrl={url(pathname).href}>
95+
<SignInButton mode="modal" redirectUrl={urlBuilder(pathname).href}>
10096
<HeaderActionButton>
10197
<UserArrowLeftIcon className="h-4 w-4" />
10298
</HeaderActionButton>

src/components/widgets/note/NoteActionAside.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@ import type { NoteWrappedPayload } from '@mx-space/api-client'
77

88
import { MotionButtonBase } from '~/components/ui/button'
99
import { microReboundPreset } from '~/constants/spring'
10+
import { useIsClient } from '~/hooks/common/use-is-client'
1011
import { useNoteData } from '~/hooks/data/use-note'
1112
import { toast } from '~/lib/toast'
13+
import { urlBuilder } from '~/lib/url-builder'
14+
import { useAggregationData } from '~/providers/root/aggregation-data-provider'
1215
import { queries } from '~/queries/definition'
1316
import { apiClient } from '~/utils/request'
1417

1518
export const NoteActionAside = () => {
1619
return (
1720
<div className="absolute bottom-0 max-h-[300px] flex-col space-y-4">
1821
<LikeButton />
22+
<ShareButton />
1923
</div>
2024
)
2125
}
@@ -67,3 +71,31 @@ const LikeButton = () => {
6771
</MotionButtonBase>
6872
)
6973
}
74+
75+
const ShareButton = () => {
76+
const hasShare = 'share' in navigator
77+
const isClient = useIsClient()
78+
const note = useNoteData()
79+
const aggregation = useAggregationData()
80+
if (!isClient) return null
81+
if (!note) return null
82+
83+
if (!hasShare) {
84+
return null
85+
}
86+
if (!aggregation) return null
87+
return (
88+
<MotionButtonBase
89+
className="flex flex-col space-y-2"
90+
onClick={() => {
91+
navigator.share({
92+
title: note.title,
93+
text: note.text,
94+
url: urlBuilder(`/notes/${note.nid}`).href,
95+
})
96+
}}
97+
>
98+
<i className="icon-[mingcute--share-forward-fill] text-[24px] opacity-80 duration-200 hover:text-uk-cyan-light hover:opacity-100" />
99+
</MotionButtonBase>
100+
)
101+
}

src/lib/url-builder.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { appConfig } from '~/app.config'
2+
3+
export function urlBuilder(path = '') {
4+
return new URL(path, appConfig.site.url)
5+
}

0 commit comments

Comments
 (0)