Skip to content

Commit 9b53db0

Browse files
committed
fix: some styles
Signed-off-by: Innei <[email protected]>
1 parent 184f652 commit 9b53db0

File tree

5 files changed

+117
-54
lines changed

5 files changed

+117
-54
lines changed

src/atoms/hooks/viewport.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { useAtomValue } from 'jotai'
33
import { selectAtom } from 'jotai/utils'
44
import type { ExtractAtomValue } from 'jotai'
55

6+
import { jotaiStore } from '~/lib/store'
7+
68
import { viewportAtom } from '../viewport'
79

810
export const useViewport = <T>(
@@ -17,9 +19,12 @@ export const useViewport = <T>(
1719

1820
export const useIsMobile = () =>
1921
useViewport(
20-
useCallback(
21-
(v: ExtractAtomValue<typeof viewportAtom>) =>
22-
(v.sm || v.md || !v.sm) && !v.lg,
23-
[],
24-
),
22+
useCallback((v: ExtractAtomValue<typeof viewportAtom>) => isMobile(v), []),
2523
)
24+
25+
const isMobile = (v: ExtractAtomValue<typeof viewportAtom>) =>
26+
(v.sm || v.md || !v.sm) && !v.lg
27+
export const currentIsMobile = () => {
28+
const v = jotaiStore.get(viewportAtom)
29+
return isMobile(v)
30+
}

src/components/layout/footer/GatewayInfo.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export const GatewayInfo = () => {
9595
<FloatPopover
9696
asChild
9797
placement="top"
98+
trigger="both"
9899
offset={10}
99100
triggerElement={
100101
<span key={count} className="cursor-pointer">

src/components/ui/image/ZoomedImage.tsx

+87-35
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
'use client'
22

3-
import { forwardRef, useCallback, useMemo, useRef, useState } from 'react'
3+
import { forwardRef, memo, useCallback, useMemo, useRef, useState } from 'react'
44
import clsx from 'clsx'
55
import { useIsomorphicLayoutEffect } from 'foxact/use-isomorphic-layout-effect'
66
import mediumZoom from 'medium-zoom'
77
import Image from 'next/image'
88
import { tv } from 'tailwind-variants'
99
import type { Zoom } from 'medium-zoom'
10-
import type { FC, ReactNode } from 'react'
10+
import type {
11+
AnimationEventHandler,
12+
DetailedHTMLProps,
13+
FC,
14+
ImgHTMLAttributes,
15+
ReactNode,
16+
} from 'react'
1117

18+
import { useIsMobile } from '~/atoms/hooks'
1219
import { LazyLoad } from '~/components/common/Lazyload'
1320
import { useIsUnMounted } from '~/hooks/common/use-is-unmounted'
1421
import { isDev, isServerSide } from '~/lib/env'
@@ -67,7 +74,7 @@ export const ImageLazy: Component<TImageProps & BaseImageProps> = ({
6774
const [zoomer_] = useState(() => {
6875
if (isServerSide) return null!
6976
if (zoomer) return zoomer
70-
const zoom = mediumZoom(undefined)
77+
const zoom = mediumZoom(undefined, {})
7178
zoomer = zoom
7279
return zoom
7380
})
@@ -86,6 +93,7 @@ export const ImageLazy: Component<TImageProps & BaseImageProps> = ({
8693
[isUnmount],
8794
)
8895
const imageRef = useRef<HTMLImageElement>(null)
96+
const isMobile = useIsMobile()
8997
useIsomorphicLayoutEffect(() => {
9098
if (imageLoadStatus !== ImageLoadStatus.Loaded) {
9199
return
@@ -95,15 +103,50 @@ export const ImageLazy: Component<TImageProps & BaseImageProps> = ({
95103
}
96104
const $image = imageRef.current
97105

106+
if (!$image) return
107+
if (isMobile) {
108+
$image.onclick = () => {
109+
// NOTE: document 上的 click 可以用 stopImmediatePropagation 阻止
110+
// e.stopImmediatePropagation()
111+
window.open(src)
112+
}
113+
return () => {
114+
$image.onclick = null
115+
}
116+
}
117+
98118
if ($image) {
99119
zoomer_.attach($image)
100120

101121
return () => {
102122
zoomer_.detach($image)
103123
}
104124
}
105-
}, [zoom, zoomer_, imageLoadStatus])
125+
}, [zoom, zoomer_, imageLoadStatus, isMobile])
106126

127+
const handleOnLoad = useCallback(() => {
128+
setImageLoadStatusSafe(ImageLoadStatus.Loaded)
129+
}, [setImageLoadStatusSafe])
130+
const handleError = useCallback(
131+
() => setImageLoadStatusSafe(ImageLoadStatus.Error),
132+
[setImageLoadStatusSafe],
133+
)
134+
const handleOnAnimationEnd: AnimationEventHandler<HTMLImageElement> =
135+
useCallback((e) => {
136+
if (ImageLoadStatus.Loaded) {
137+
;(e.target as HTMLElement).classList.remove(
138+
imageStyles[ImageLoadStatus.Loaded],
139+
)
140+
}
141+
}, [])
142+
const imageClassName = useMemo(
143+
() =>
144+
styles({
145+
status: imageLoadStatus,
146+
className: clsx(imageStyles[ImageLoadStatus.Loaded], className),
147+
}),
148+
[className, imageLoadStatus],
149+
)
107150
return (
108151
<figure>
109152
<span className="relative flex justify-center" data-hide-print>
@@ -130,21 +173,10 @@ export const ImageLazy: Component<TImageProps & BaseImageProps> = ({
130173
title={title}
131174
alt={alt || title || ''}
132175
ref={imageRef}
133-
onLoad={() => {
134-
setImageLoadStatusSafe(ImageLoadStatus.Loaded)
135-
}}
136-
onError={() => setImageLoadStatusSafe(ImageLoadStatus.Error)}
137-
className={styles({
138-
status: imageLoadStatus,
139-
className: clsx(imageStyles[ImageLoadStatus.Loaded], className),
140-
})}
141-
onAnimationEnd={(e: Event) => {
142-
if (ImageLoadStatus.Loaded) {
143-
;(e.target as HTMLElement).classList.remove(
144-
imageStyles[ImageLoadStatus.Loaded],
145-
)
146-
}
147-
}}
176+
onLoad={handleOnLoad}
177+
onError={handleError}
178+
className={imageClassName}
179+
onAnimationEnd={handleOnAnimationEnd}
148180
/>
149181
</LazyLoad>
150182
</span>
@@ -256,21 +288,41 @@ const NoFixedPlaceholder = ({ accent }: { accent?: string }) => {
256288
)
257289
}
258290

259-
const OptimizedImage: FC<any> = forwardRef(({ src, alt, ...rest }, ref) => {
260-
const { height, width } = useMarkdownImageRecord(src!) || rest
261-
if (!height || !width) return <img alt={alt} src={src} ref={ref} {...rest} />
262-
return (
263-
<Image
264-
alt={alt || ''}
265-
fetchPriority="high"
266-
priority
267-
src={src!}
268-
{...rest}
269-
height={+height}
270-
width={+width}
271-
ref={ref as any}
272-
/>
273-
)
274-
})
291+
const OptimizedImage = memo(
292+
forwardRef<
293+
HTMLImageElement,
294+
DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>
295+
>(({ src, alt, ...rest }, ref) => {
296+
const { height, width } = useMarkdownImageRecord(src!) || rest
297+
const hasDim = !!(height && width)
298+
299+
const ImageEl = (
300+
<img data-zoom-src={src} alt={alt} src={src} ref={ref} {...rest} />
301+
)
302+
return (
303+
<>
304+
{hasDim ? (
305+
<>
306+
{/* @ts-expect-error */}
307+
<Image
308+
alt={alt || ''}
309+
fetchPriority="high"
310+
priority
311+
src={src!}
312+
{...rest}
313+
height={+height}
314+
width={+width}
315+
/>
316+
<div className="absolute inset-0 flex justify-center opacity-0">
317+
{ImageEl}
318+
</div>
319+
</>
320+
) : (
321+
ImageEl
322+
)}
323+
</>
324+
)
325+
}),
326+
)
275327

276328
OptimizedImage.displayName = 'OptimizedImage'
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createElement, useId } from 'react'
22
import type { DOMAttributes } from 'react'
33

4+
import { useIsClient } from '~/hooks/common/use-is-client'
45
import { springScrollToElement } from '~/lib/scroller'
56

67
interface HeadingProps {
@@ -15,6 +16,8 @@ export const MHeader = (props: HeadingProps) => {
1516

1617
const rid = useId()
1718

19+
const isClient = useIsClient()
20+
1821
const nextId = `${rid}${id}`
1922
return createElement<DOMAttributes<HTMLHeadingElement>, HTMLHeadingElement>(
2023
`h${level}`,
@@ -27,19 +30,21 @@ export const MHeader = (props: HeadingProps) => {
2730
null,
2831
<>
2932
<span>{children}</span>
30-
<span
31-
className="ml-2 inline-flex cursor-pointer select-none text-accent opacity-0 transition-opacity duration-200 center group-hover:opacity-100"
32-
role="button"
33-
tabIndex={0}
34-
aria-hidden
35-
onClick={() => {
36-
const state = history.state
37-
history.replaceState(state, '', `#${nextId}`)
38-
springScrollToElement(document.getElementById(nextId)!, -100)
39-
}}
40-
>
41-
<i className="icon-[mingcute--hashtag-line]" />
42-
</span>
33+
{isClient && (
34+
<span
35+
className="ml-2 inline-flex cursor-pointer select-none text-accent opacity-0 transition-opacity duration-200 center group-hover:opacity-100"
36+
role="button"
37+
tabIndex={0}
38+
aria-hidden
39+
onClick={() => {
40+
const state = history.state
41+
history.replaceState(state, '', `#${nextId}`)
42+
springScrollToElement(document.getElementById(nextId)!, -100)
43+
}}
44+
>
45+
<i className="icon-[mingcute--hashtag-line]" />
46+
</span>
47+
)}
4348
</>,
4449
)
4550
}

src/components/ui/rich-link/Favicon.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export const Favicon: Component<FaviconProps> = (props) => {
112112
return (
113113
<span
114114
className={clsxm(
115-
'mr-1 inline-flex [&_svg]:inline [&_svg]:!h-[0.8rem]',
115+
'mr-1 inline-flex [&_svg]:inline [&_svg]:!h-[0.8em]',
116116
className,
117117
)}
118118
>

0 commit comments

Comments
 (0)