stacker.news/components/share.js

159 lines
4.4 KiB
JavaScript
Raw Normal View History

2023-07-24 18:35:05 +00:00
import Dropdown from 'react-bootstrap/Dropdown'
2022-12-19 22:27:52 +00:00
import ShareIcon from '../svgs/share-fill.svg'
import copy from 'clipboard-copy'
import useCrossposter from './use-crossposter'
import { useMutation, gql } from '@apollo/client'
2022-12-19 22:27:52 +00:00
import { useMe } from './me'
import { useToast } from './toast'
import { SSR } from '../lib/constants'
2023-12-19 22:01:48 +00:00
import { callWithTimeout } from '../lib/nostr'
2024-01-18 01:02:59 +00:00
import { commentSubTreeRootId } from '../lib/item'
import { useRouter } from 'next/router'
2023-12-15 18:10:29 +00:00
const referrurl = (ipath, me) => {
const path = `${ipath}${me ? `/r/${me.name}` : ''}`
if (!SSR) {
return `${window.location.protocol}//${window.location.host}${path}`
}
return `https://stacker.news${path}`
}
2022-12-19 22:27:52 +00:00
2023-12-15 18:10:29 +00:00
export default function Share ({ path, title, className = '' }) {
2022-12-19 22:27:52 +00:00
const me = useMe()
const toaster = useToast()
2023-12-15 18:10:29 +00:00
const url = referrurl(path, me)
return !SSR && navigator?.share
2022-12-19 22:27:52 +00:00
? (
2023-07-24 18:35:05 +00:00
<div className='ms-auto pointer d-flex align-items-center'>
2022-12-19 22:27:52 +00:00
<ShareIcon
2023-05-01 20:58:30 +00:00
width={20} height={20}
2023-12-15 18:10:29 +00:00
className={`mx-2 fill-grey theme ${className}`}
onClick={async () => {
try {
await navigator.share({
2023-12-15 18:10:29 +00:00
title: title || '',
2022-12-19 22:27:52 +00:00
text: '',
url
})
toaster.success('link shared')
} catch (err) {
console.error(err)
2022-12-19 22:27:52 +00:00
}
}}
/>
</div>)
: (
2023-07-24 18:35:05 +00:00
<Dropdown align='end' className='ms-auto pointer d-flex align-items-center' as='span'>
2022-12-19 22:27:52 +00:00
<Dropdown.Toggle variant='success' id='dropdown-basic' as='a'>
2023-12-15 18:10:29 +00:00
<ShareIcon width={20} height={20} className={`mx-2 fill-grey theme ${className}`} />
2022-12-19 22:27:52 +00:00
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item
onClick={async () => {
try {
await copy(url)
toaster.success('link copied')
} catch (err) {
console.error(err)
toaster.danger('failed to copy link')
}
2022-12-19 22:27:52 +00:00
}}
>
copy link
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>)
}
export function CopyLinkDropdownItem ({ item }) {
const me = useMe()
const toaster = useToast()
2024-01-18 01:02:59 +00:00
const router = useRouter()
let url = referrurl(`/items/${item.id}`, me)
// if this is a comment and we're not directly on the comment page
// link to the comment in context
if (item.parentId && !router.asPath.includes(`/items/${item.id}`)) {
const rootId = commentSubTreeRootId(item)
url = referrurl(`/items/${rootId}`, me) + `?commentId=${item.id}`
}
return (
<Dropdown.Item
onClick={async () => {
try {
if (navigator.share) {
await navigator.share({
title: item.title || '',
text: '',
url
})
} else {
await copy(url)
}
toaster.success('link copied')
} catch (err) {
console.error(err)
toaster.danger('failed to copy link')
}
}}
>
copy link
</Dropdown.Item>
)
}
2023-12-15 18:10:29 +00:00
export function CrosspostDropdownItem ({ item }) {
const crossposter = useCrossposter()
const toaster = useToast()
const [updateNoteId] = useMutation(
gql`
mutation updateNoteId($id: ID!, $noteId: String!) {
updateNoteId(id: $id, noteId: $noteId) {
id
noteId
}
}`
)
return (
<Dropdown.Item
onClick={async () => {
try {
const pubkey = await callWithTimeout(() => window.nostr.getPublicKey(), 5000)
if (!pubkey) {
throw new Error('not available')
}
} catch (e) {
toaster.danger(`Nostr extension error: ${e.message}`)
return
}
try {
if (item?.id) {
const crosspostResult = await crossposter({ ...item })
const noteId = crosspostResult?.noteId
if (noteId) {
await updateNoteId({
variables: {
id: item.id,
noteId
}
})
}
toaster.success('Crosspost successful')
} else {
toaster.warning('Item ID not available')
}
} catch (e) {
console.error(e)
toaster.danger('Crosspost failed')
}
}}
>
crosspost to nostr
</Dropdown.Item>
)
}