1
1
import { ActionButton , MotionButtonBase } from "@follow/components/ui/button/index.js"
2
2
import { RootPortal } from "@follow/components/ui/portal/index.js"
3
+ import { useMeasure } from "@follow/hooks"
3
4
import { IN_ELECTRON } from "@follow/shared/constants"
4
5
import type { MediaModel } from "@follow/shared/hono"
5
6
import { stopPropagation } from "@follow/utils/dom"
@@ -153,6 +154,7 @@ export const PreviewMediaContent: FC<{
153
154
height = { media [ 0 ] . height }
154
155
width = { media [ 0 ] . width }
155
156
blurhash = { media [ 0 ] . blurhash }
157
+ haveSideContent = { ! ! children }
156
158
/>
157
159
) }
158
160
</ Wrapper >
@@ -262,6 +264,7 @@ export const PreviewMediaContent: FC<{
262
264
height = { med . height }
263
265
width = { med . width }
264
266
blurhash = { med . blurhash }
267
+ haveSideContent = { ! ! children }
265
268
/>
266
269
) }
267
270
</ SwiperSlide >
@@ -271,14 +274,19 @@ export const PreviewMediaContent: FC<{
271
274
)
272
275
}
273
276
277
+ function parseNumber ( value : string | number | undefined ) {
278
+ return typeof value === "string" ? Number . parseInt ( value ) : value
279
+ }
280
+
274
281
const FallbackableImage : FC <
275
282
Omit < React . ImgHTMLAttributes < HTMLImageElement > , "src" > & {
276
283
src : string
277
284
containerClassName ?: string
278
285
fallbackUrl ?: string
279
286
blurhash ?: string
287
+ haveSideContent ?: boolean
280
288
}
281
- > = ( { src, onError, fallbackUrl, containerClassName, blurhash, ...props } ) => {
289
+ > = ( { src, onError, fallbackUrl, containerClassName, blurhash, haveSideContent , ...props } ) => {
282
290
const [ currentSrc , setCurrentSrc ] = useState ( ( ) => replaceImgUrlIfNeed ( src ) )
283
291
const [ isAllError , setIsAllError ] = useState ( false )
284
292
@@ -318,38 +326,54 @@ const FallbackableImage: FC<
318
326
}
319
327
} , [ currentSrc , currentState , fallbackUrl , src ] )
320
328
321
- const height = Number . parseInt ( props . height as string )
322
- const width = Number . parseInt ( props . width as string )
329
+ const height = parseNumber ( props . height )
330
+ const width = parseNumber ( props . width )
323
331
324
332
const { height : windowHeight , width : windowWidth } = useWindowSize ( )
325
333
// px-20 pb-8 pt-10
326
334
// wrapper side content w-[400px]
327
335
const maxContainerHeight = windowHeight - 32 - 40
328
- const maxContainerWidth = windowWidth - 80 - 80 - 400
336
+ const maxContainerWidth = windowWidth - 80 - 80 - ( haveSideContent ? 400 : 0 )
337
+
338
+ const [ scale , setScale ] = useState ( 1 )
329
339
330
- const wrapperClass = cn ( "relative !max-h-full" , width <= height && "!h-full" )
340
+ const wrapperClass = cn ( "relative !max-h-full" , width && height && width <= height && "!h-full" )
331
341
const wrapperStyle : React . CSSProperties = {
332
342
width :
333
343
width && height && width > height
334
344
? `${ Math . min ( maxContainerHeight * ( width / height ) , width ) } px`
335
345
: undefined ,
336
- maxWidth : width > height ? `${ maxContainerWidth } px` : undefined ,
346
+ maxWidth : width && height && width > height ? `${ maxContainerWidth } px` : undefined ,
337
347
}
338
348
349
+ const [ ref , { width : imgWidth } ] = useMeasure ( )
350
+
339
351
return (
340
352
< div
341
353
className = { cn ( "center flex size-full flex-col" , containerClassName ) }
342
354
onClick = { stopPropagation }
343
355
>
344
356
{ ! isAllError && (
345
- < TransformWrapper wheel = { { step : 1 } } >
357
+ < TransformWrapper
358
+ wheel = { { step : 1 } }
359
+ onZoom = { ( e ) => {
360
+ setScale ( e . state . scale )
361
+ } }
362
+ >
346
363
< TransformComponent
347
364
wrapperClass = { wrapperClass }
348
- wrapperStyle = { wrapperStyle }
365
+ wrapperStyle = { {
366
+ ...wrapperStyle ,
367
+ minWidth :
368
+ scale > 1 && ! haveSideContent
369
+ ? `${ Math . min ( maxContainerWidth / 2 , scale * imgWidth ) } px`
370
+ : undefined ,
371
+ } }
349
372
contentClass = { wrapperClass }
350
373
contentStyle = { wrapperStyle }
351
374
>
352
375
< img
376
+ ref = { ref }
353
377
data-blurhash = { blurhash }
354
378
src = { currentSrc }
355
379
onLoad = { ( ) => setIsLoading ( false ) }
@@ -358,7 +382,7 @@ const FallbackableImage: FC<
358
382
width = { props . width }
359
383
{ ...props }
360
384
className = { cn (
361
- "transition-opacity duration-700" ,
385
+ "mx-auto transition-opacity duration-700" ,
362
386
isLoading ? "opacity-0" : "opacity-100" ,
363
387
props . className ,
364
388
) }
0 commit comments