mirror of
https://github.com/RSSNext/Folo.git
synced 2026-10-17 05:08:13 +08:00
fix(mobile): read device type, onboarding root and player atoms written during mount
jotai 3 subscribes after the mount commit, so a value written in between is missed until the next write. The device type arrives from an async init while the first screens mount, the onboarding check reads routes that screens push from mount effects, and every mounted player control writes the pause flag and playback rate in its own mount effect, so a sibling mounting in the same commit kept stale values. Read them with useAtomValueRawSync. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { jotaiStore } from "@follow/utils"
|
||||
import { useAtomValue } from "jotai"
|
||||
import { useAtomValueRawSync } from "jotai"
|
||||
|
||||
import { appAtoms } from "../app"
|
||||
|
||||
export const useDeviceType = () => {
|
||||
const deviceType = useAtomValue(appAtoms.deviceType)
|
||||
// Set by an async init that can land while the first screens mount
|
||||
const deviceType = useAtomValueRawSync(appAtoms.deviceType)
|
||||
return deviceType
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useIsNewUser, useWhoami } from "@follow/store/user/hooks"
|
||||
import { useAtomValue } from "jotai"
|
||||
import { useAtomValueRawSync } from "jotai"
|
||||
import { selectAtom } from "jotai/utils"
|
||||
import { useEffect, useMemo, useRef } from "react"
|
||||
|
||||
@@ -13,7 +13,7 @@ export function useOnboarding() {
|
||||
const navigation = useNavigation()
|
||||
// The sign-in screen pops to the root shortly after signing in, which would also close an
|
||||
// onboarding presented in the meantime, so it waits until nothing is open over the tabs
|
||||
const isAtRoot = useAtomValue(
|
||||
const isAtRoot = useAtomValueRawSync(
|
||||
useMemo(
|
||||
() => selectAtom(navigation.__dangerous_getCtxValue().routesAtom, (r) => r.length === 0),
|
||||
[navigation],
|
||||
|
||||
@@ -6,7 +6,7 @@ import TrackPlayer, {
|
||||
usePlaybackState,
|
||||
} from "@rntp/player"
|
||||
import { t } from "i18next"
|
||||
import { atom, useAtom } from "jotai"
|
||||
import { atom, useAtomValueRawSync, useSetAtom } from "jotai"
|
||||
import { useCallback, useEffect, useSyncExternalStore } from "react"
|
||||
|
||||
import { PlayerRegistered } from "../initialize/player"
|
||||
@@ -20,7 +20,10 @@ const pausedByUserAtom = atom(false)
|
||||
function usePlaybackStatus() {
|
||||
const playing = useNativeIsPlaying()
|
||||
const playbackState = usePlaybackState()
|
||||
const [pausedByUser, setPausedByUser] = useAtom(pausedByUserAtom)
|
||||
// Every mounted player control resets it in an effect, so a sibling mounting in the same
|
||||
// commit must not keep the value it rendered with
|
||||
const pausedByUser = useAtomValueRawSync(pausedByUserAtom)
|
||||
const setPausedByUser = useSetAtom(pausedByUserAtom)
|
||||
|
||||
useEffect(() => {
|
||||
if (playing) setPausedByUser(false)
|
||||
@@ -159,7 +162,9 @@ export type Rate = (typeof allowedRate)[number]
|
||||
const rateAtom = atom<Rate>(1)
|
||||
|
||||
export function useRate() {
|
||||
const [rate, setRate] = useAtom(rateAtom)
|
||||
// Synced from the native player in a mount effect, see usePlaybackStatus
|
||||
const rate = useAtomValueRawSync(rateAtom)
|
||||
const setRate = useSetAtom(rateAtom)
|
||||
|
||||
useEffect(() => {
|
||||
function getRate() {
|
||||
|
||||
Reference in New Issue
Block a user