Port post embeds to new arch (#7408)

* Direct port of embeds to new arch

(cherry picked from commit cc3fa1f6cea396dd9222486c633a508bfee1ecd6)

* Re-org

* Split out ListEmbed and FeedEmbed

* Split out ImageEmbed

* DRY up a bit

* Port over ExternalLinkEmbed

* Port over Player and Gif embeds

* Migrate ComposerReplyTo

* Replace other usages of old post-embeds

* Migrate view contexts

* Copy pasta VideoEmbed

* Copy pasta GifEmbed

* Swap in new file location

* Clean up

* Fix up native

* Add back in correct moderation on List and Feed embeds

* Format

* Prettier

* delete old video utils

* move bandwidth-estimate.ts

* Remove log

* Add LazyQuoteEmbed for composer use

* Clean up unused things

* Remove remaining items

* Prettier

* Fix imports

* Handle nested quotes same as prod

* Add back silenced error handling

* Fix lint

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
Eric Bailey
2025-06-13 12:05:41 -05:00
committed by GitHub
parent ba0f5a9bde
commit 45f0f7eefe
75 changed files with 812 additions and 799 deletions
@@ -0,0 +1,110 @@
import React, {useCallback} from 'react'
import {View} from 'react-native'
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {isSafari, isTouchDevice} from '#/lib/browser'
import {atoms as a} from '#/alf'
import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as UnmuteIcon} from '#/components/icons/Speaker'
import {useVideoVolumeState} from '#/components/Post/Embed/VideoEmbed/VideoVolumeContext'
import {ControlButton} from './ControlButton'
export function VolumeControl({
muted,
changeMuted,
hovered,
onHover,
onEndHover,
drawFocus,
}: {
muted: boolean
changeMuted: (muted: boolean | ((prev: boolean) => boolean)) => void
hovered: boolean
onHover: () => void
onEndHover: () => void
drawFocus: () => void
}) {
const {_} = useLingui()
const [volume, setVolume] = useVideoVolumeState()
const onVolumeChange = useCallback(
(evt: React.ChangeEvent<HTMLInputElement>) => {
drawFocus()
const vol = sliderVolumeToVideoVolume(Number(evt.target.value))
setVolume(vol)
changeMuted(vol === 0)
},
[setVolume, drawFocus, changeMuted],
)
const sliderVolume = muted ? 0 : videoVolumeToSliderVolume(volume)
const isZeroVolume = volume === 0
const onPressMute = useCallback(() => {
drawFocus()
if (isZeroVolume) {
setVolume(1)
changeMuted(false)
} else {
changeMuted(prevMuted => !prevMuted)
}
}, [drawFocus, setVolume, isZeroVolume, changeMuted])
return (
<View
onPointerEnter={onHover}
onPointerLeave={onEndHover}
style={[a.relative]}>
{hovered && !isTouchDevice && (
<Animated.View
entering={FadeIn.duration(100)}
exiting={FadeOut.duration(100)}
style={[a.absolute, a.w_full, {height: 100, bottom: '100%'}]}>
<View
style={[
a.flex_1,
a.mb_xs,
a.px_2xs,
a.py_xs,
{backgroundColor: 'rgba(0, 0, 0, 0.6)'},
a.rounded_xs,
a.align_center,
]}>
<input
type="range"
min={0}
max={100}
value={sliderVolume}
aria-label={_(msg`Volume`)}
style={
// Ridiculous safari hack for old version of safari. Fixed in sonoma beta -h
isSafari ? {height: 92, minHeight: '100%'} : {height: '100%'}
}
onChange={onVolumeChange}
// @ts-expect-error for old versions of firefox, and then re-using it for targeting the CSS -sfn
orient="vertical"
/>
</View>
</Animated.View>
)}
<ControlButton
active={muted || volume === 0}
activeLabel={_(msg({message: `Unmute`, context: 'video'}))}
inactiveLabel={_(msg({message: `Mute`, context: 'video'}))}
activeIcon={MuteIcon}
inactiveIcon={UnmuteIcon}
onPress={onPressMute}
/>
</View>
)
}
function sliderVolumeToVideoVolume(value: number) {
return Math.pow(value / 100, 4)
}
function videoVolumeToSliderVolume(value: number) {
return Math.round(Math.pow(value, 1 / 4) * 100)
}