fix immutability errors

This commit is contained in:
Samuel Newman
2025-10-08 17:09:03 +03:00
parent 461f56a342
commit aac898d229
7 changed files with 36 additions and 29 deletions
@@ -16,13 +16,13 @@ export function VideoEmbedInnerWeb({
active, active,
setActive, setActive,
onScreen, onScreen,
lastKnownTime, lastKnownTime: lastKnownTimeRef,
}: { }: {
embed: AppBskyEmbedVideo.View embed: AppBskyEmbedVideo.View
active: boolean active: boolean
setActive: () => void setActive: () => void
onScreen: boolean onScreen: boolean
lastKnownTime: React.MutableRefObject<number | undefined> lastKnownTime: React.RefObject<number | undefined>
}) { }) {
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const videoRef = useRef<HTMLVideoElement>(null) const videoRef = useRef<HTMLVideoElement>(null)
@@ -47,10 +47,10 @@ export function VideoEmbedInnerWeb({
}) })
useEffect(() => { useEffect(() => {
if (lastKnownTime.current && videoRef.current) { if (lastKnownTimeRef.current && videoRef.current) {
videoRef.current.currentTime = lastKnownTime.current videoRef.current.currentTime = lastKnownTimeRef.current
} }
}, [lastKnownTime]) }, [lastKnownTimeRef])
return ( return (
<View <View
@@ -68,7 +68,7 @@ export function VideoEmbedInnerWeb({
muted={!focused} muted={!focused}
aria-labelledby={embed.alt ? figId : undefined} aria-labelledby={embed.alt ? figId : undefined}
onTimeUpdate={e => { onTimeUpdate={e => {
lastKnownTime.current = e.currentTarget.currentTime lastKnownTimeRef.current = e.currentTarget.currentTime
}} }}
/> />
{embed.alt && ( {embed.alt && (
@@ -195,14 +195,15 @@ function DialogInner({guide}: {guide: Follow10ProgressGuide}) {
resultsKey, resultsKey,
]) ])
if ( const isEmpty =
searchText && searchText &&
!isFetchingSearchResults && !isFetchingSearchResults &&
!items.length && !items.length &&
!isSearchResultsError !isSearchResultsError
) {
items.push({type: 'empty', key: 'empty', message: _(msg`No results`)}) const allItems = isEmpty
} ? [{type: 'empty', key: 'empty', message: _(msg`No results`)}]
: items
const renderItems = useCallback( const renderItems = useCallback(
({item, index}: {item: Item; index: number}) => { ({item, index}: {item: Item; index: number}) => {
@@ -260,7 +261,7 @@ function DialogInner({guide}: {guide: Follow10ProgressGuide}) {
return ( return (
<Dialog.InnerFlatList <Dialog.InnerFlatList
ref={listRef} ref={listRef}
data={items} data={allItems}
renderItem={renderItems} renderItem={renderItems}
ListHeaderComponent={listHeader} ListHeaderComponent={listHeader}
stickyHeaderIndices={[0]} stickyHeaderIndices={[0]}
@@ -9,6 +9,7 @@ import {makeProfileLink} from '#/lib/routes/links'
import {listUriToHref} from '#/lib/strings/url-helpers' import {listUriToHref} from '#/lib/strings/url-helpers'
import {isNative} from '#/platform/detection' import {isNative} from '#/platform/detection'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {useTickEveryMinute} from '#/state/shell'
import {atoms as a, useGutters, useTheme} from '#/alf' import {atoms as a, useGutters, useTheme} from '#/alf'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import {InlineLinkText} from '#/components/Link' import {InlineLinkText} from '#/components/Link'
@@ -44,6 +45,7 @@ function ModerationDetailsDialogInner({
const {_} = useLingui() const {_} = useLingui()
const desc = useModerationCauseDescription(modcause) const desc = useModerationCauseDescription(modcause)
const {currentAccount} = useSession() const {currentAccount} = useSession()
const tick = useTickEveryMinute()
const timeDiff = useGetTimeAgo({future: true}) const timeDiff = useGetTimeAgo({future: true})
let name let name
@@ -208,7 +210,7 @@ function ModerationDetailsDialogInner({
t.atoms.text_contrast_medium, t.atoms.text_contrast_medium,
]}> ]}>
<Trans> <Trans>
Expires in {timeDiff(Date.now(), modcause.label.exp)} Expires in {timeDiff(tick, modcause.label.exp)}
</Trans> </Trans>
</Text> </Text>
</View> </View>
+8 -8
View File
@@ -29,19 +29,19 @@ export function useActorAutocompleteQuery(
const moderationOpts = useModerationOpts() const moderationOpts = useModerationOpts()
const agent = useAgent() const agent = useAgent()
prefix = prefix.toLowerCase().trim() let cleanPrefix = prefix.toLowerCase().trim()
if (prefix.endsWith('.')) { if (cleanPrefix.endsWith('.')) {
// Going from "foo" to "foo." should not clear matches. // Going from "foo" to "foo." should not clear matches.
prefix = prefix.slice(0, -1) cleanPrefix = cleanPrefix.slice(0, -1)
} }
return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({ return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({
staleTime: STALE.MINUTES.ONE, staleTime: STALE.MINUTES.ONE,
queryKey: RQKEY(prefix || ''), queryKey: RQKEY(cleanPrefix || ''),
async queryFn() { async queryFn() {
const res = prefix const res = cleanPrefix
? await agent.searchActorsTypeahead({ ? await agent.searchActorsTypeahead({
q: prefix, q: cleanPrefix,
limit: limit || 8, limit: limit || 8,
}) })
: undefined : undefined
@@ -50,12 +50,12 @@ export function useActorAutocompleteQuery(
select: React.useCallback( select: React.useCallback(
(data: AppBskyActorDefs.ProfileViewBasic[]) => { (data: AppBskyActorDefs.ProfileViewBasic[]) => {
return computeSuggestions({ return computeSuggestions({
q: prefix, q: cleanPrefix,
searched: data, searched: data,
moderationOpts: moderationOpts || DEFAULT_MOD_OPTS, moderationOpts: moderationOpts || DEFAULT_MOD_OPTS,
}) })
}, },
[prefix, moderationOpts], [cleanPrefix, moderationOpts],
), ),
placeholderData: maintainData ? keepPreviousData : undefined, placeholderData: maintainData ? keepPreviousData : undefined,
}) })
+1 -1
View File
@@ -331,7 +331,7 @@ export function TabBar({
syncScrollState.set('unsynced') syncScrollState.set('unsynced')
}} }}
onScroll={e => { onScroll={e => {
scrollX.value = Math.round(e.nativeEvent.contentOffset.x) scrollX.set(Math.round(e.nativeEvent.contentOffset.x))
}}> }}>
<Animated.View <Animated.View
onLayout={e => { onLayout={e => {
+7 -4
View File
@@ -226,7 +226,8 @@ let PostFeed = ({
const initialNumToRender = useInitialNumToRender() const initialNumToRender = useInitialNumToRender()
const feedFeedback = useFeedFeedbackContext() const feedFeedback = useFeedFeedbackContext()
const [isPTRing, setIsPTRing] = useState(false) const [isPTRing, setIsPTRing] = useState(false)
const lastFetchRef = useRef<number>(Date.now()) const [firstFetchTime] = useState(() => Date.now())
const lastFetchRef = useRef<number>(firstFetchTime)
const [feedType, feedUriOrActorDid, feedTab] = feed.split('|') const [feedType, feedUriOrActorDid, feedTab] = feed.split('|')
const {gtMobile} = useBreakpoints() const {gtMobile} = useBreakpoints()
const {rightNavVisible} = useLayoutBreakpoints() const {rightNavVisible} = useLayoutBreakpoints()
@@ -263,9 +264,11 @@ let PostFeed = ({
fetchNextPage, fetchNextPage,
} = usePostFeedQuery(feed, feedParams, opts) } = usePostFeedQuery(feed, feedParams, opts)
const lastFetchedAt = data?.pages[0].fetchedAt const lastFetchedAt = data?.pages[0].fetchedAt
if (lastFetchedAt) { useEffect(() => {
lastFetchRef.current = lastFetchedAt if (lastFetchedAt) {
} lastFetchRef.current = lastFetchedAt
}
}, [lastFetchedAt])
const isEmpty = useMemo( const isEmpty = useMemo(
() => !isFetching && !data?.pages?.some(page => page.slices.length), () => !isFetching && !data?.pages?.some(page => page.slices.length),
[isFetching, data], [isFetching, data],
+5 -4
View File
@@ -103,6 +103,8 @@ export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
paddingTop: Math.abs(contentOffset.y), paddingTop: Math.abs(contentOffset.y),
}) })
} }
// @ts-expect-error web only
let dataSet = props.dataSet || {}
if (desktopFixedHeight) { if (desktopFixedHeight) {
if (typeof desktopFixedHeight === 'number') { if (typeof desktopFixedHeight === 'number') {
// @ts-expect-error Web only -prf // @ts-expect-error Web only -prf
@@ -121,10 +123,7 @@ export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
// around this, we set data-stable-gutters which can then be // around this, we set data-stable-gutters which can then be
// styled in our external CSS. // styled in our external CSS.
// -prf // -prf
// @ts-expect-error web only -prf dataSet = {...dataSet, stableGutters: '1'}
props.dataSet = props.dataSet || {}
// @ts-expect-error web only -prf
props.dataSet.stableGutters = '1'
} }
} }
return ( return (
@@ -133,6 +132,8 @@ export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
contentContainerStyle={[styles.contentContainer, contentContainerStyle]} contentContainerStyle={[styles.contentContainer, contentContainerStyle]}
style={style} style={style}
contentOffset={contentOffset} contentOffset={contentOffset}
// @ts-expect-error web only
dataSet={dataSet}
{...props} {...props}
/> />
) )