mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-06 21:35:52 +08:00
feat(Link): add hyperlink tooltips (#9620)
This commit is contained in:
parent
e222ba5459
commit
2dbe9c1e0e
65
src/renderer/src/pages/home/Markdown/Hyperlink.tsx
Normal file
65
src/renderer/src/pages/home/Markdown/Hyperlink.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import Favicon from '@renderer/components/Icons/FallbackFavicon'
|
||||||
|
import { Popover } from 'antd'
|
||||||
|
import React, { memo, useMemo } from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
interface HyperLinkProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
href: string
|
||||||
|
}
|
||||||
|
const Hyperlink: React.FC<HyperLinkProps> = ({ children, href }) => {
|
||||||
|
const link = useMemo(() => {
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(href)
|
||||||
|
} catch {
|
||||||
|
return href
|
||||||
|
}
|
||||||
|
}, [href])
|
||||||
|
|
||||||
|
const hostname = useMemo(() => {
|
||||||
|
try {
|
||||||
|
return new URL(link).hostname
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}, [link])
|
||||||
|
|
||||||
|
if (!href) return children
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
arrow={false}
|
||||||
|
content={
|
||||||
|
<StyledHyperLink>
|
||||||
|
{hostname && <Favicon hostname={hostname} alt={link} />}
|
||||||
|
<span>{link}</span>
|
||||||
|
</StyledHyperLink>
|
||||||
|
}
|
||||||
|
placement="top"
|
||||||
|
color="var(--color-background)"
|
||||||
|
styles={{
|
||||||
|
body: {
|
||||||
|
border: '1px solid var(--color-border)',
|
||||||
|
padding: '12px',
|
||||||
|
borderRadius: '8px'
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{children}
|
||||||
|
</Popover>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const StyledHyperLink = styled.div`
|
||||||
|
color: var(--color-text);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
span {
|
||||||
|
max-width: min(400px, 70vw);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default memo(Hyperlink)
|
||||||
@ -3,6 +3,7 @@ import React from 'react'
|
|||||||
import type { Node } from 'unist'
|
import type { Node } from 'unist'
|
||||||
|
|
||||||
import CitationTooltip from './CitationTooltip'
|
import CitationTooltip from './CitationTooltip'
|
||||||
|
import Hyperlink from './Hyperlink'
|
||||||
|
|
||||||
interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||||
node?: Omit<Node, 'type'>
|
node?: Omit<Node, 'type'>
|
||||||
@ -44,12 +45,14 @@ const Link: React.FC<LinkProps> = (props) => {
|
|||||||
|
|
||||||
// 普通链接
|
// 普通链接
|
||||||
return (
|
return (
|
||||||
<a
|
<Hyperlink href={props.href || ''}>
|
||||||
{...omit(props, ['node', 'citationData'])}
|
<a
|
||||||
target="_blank"
|
{...omit(props, ['node', 'citationData'])}
|
||||||
rel="noreferrer"
|
target="_blank"
|
||||||
onClick={(e) => e.stopPropagation()}
|
rel="noreferrer"
|
||||||
/>
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
</Hyperlink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user