Bluesky app fork with some witchin' additions 💫

Debounce thread preferences on leading edge, reduce to 2s (#9851)

* debounce on leading edge, reduce to 2s

* flush debounce on leave screen

* simplify by using useMutation properly

authored by samuel.fm and committed by

GitHub a25bc8f2 177a6e50

+39 -19
+9 -1
src/state/queries/preferences/index.ts
··· 200 200 }) 201 201 } 202 202 203 - export function useSetThreadViewPreferencesMutation() { 203 + export function useSetThreadViewPreferencesMutation({ 204 + onSuccess, 205 + onError, 206 + }: { 207 + onSuccess?: (data: void, variables: Partial<ThreadViewPreferences>) => void 208 + onError?: (error: unknown) => void 209 + }) { 204 210 const queryClient = useQueryClient() 205 211 const agent = useAgent() 206 212 ··· 212 218 queryKey: preferencesQueryKey, 213 219 }) 214 220 }, 221 + onSuccess, 222 + onError, 215 223 }) 216 224 } 217 225
+30 -18
src/state/queries/preferences/useThreadPreferences.ts
··· 1 1 import {useCallback, useMemo, useRef, useState} from 'react' 2 2 import {type AppBskyUnspeccedGetPostThreadV2} from '@atproto/api' 3 + import {useFocusEffect} from '@react-navigation/native' 3 4 import debounce from 'lodash.debounce' 4 5 5 6 import {useCallOnce} from '#/lib/once' ··· 70 71 } 71 72 72 73 const userUpdatedPrefs = useRef(false) 73 - const [isSaving, setIsSaving] = useState(false) 74 - const {mutateAsync} = useSetThreadViewPreferencesMutation() 74 + const {mutate, isPending: isSaving} = useSetThreadViewPreferencesMutation({ 75 + onSuccess: (_data, prefs) => { 76 + ax.metric('thread:preferences:update', { 77 + sort: prefs.sort, 78 + view: prefs.lab_treeViewEnabled ? 'tree' : 'linear', 79 + }) 80 + }, 81 + onError: err => { 82 + ax.logger.error('useThreadPreferences failed to save', { 83 + safeMessage: err, 84 + }) 85 + }, 86 + }) 75 87 const savePrefs = useMemo(() => { 76 - return debounce(async (prefs: ThreadViewPreferences) => { 77 - try { 78 - setIsSaving(true) 79 - await mutateAsync(prefs) 80 - ax.metric('thread:preferences:update', { 81 - sort: prefs.sort, 82 - view: prefs.lab_treeViewEnabled ? 'tree' : 'linear', 83 - }) 84 - } catch (e) { 85 - ax.logger.error('useThreadPreferences failed to save', { 86 - safeMessage: e, 87 - }) 88 - } finally { 89 - setIsSaving(false) 88 + return debounce( 89 + (prefs: ThreadViewPreferences) => { 90 + mutate(prefs) 91 + }, 92 + 2e3, 93 + {leading: true, trailing: true}, 94 + ) 95 + }, [mutate]) 96 + 97 + // flush on leave screen 98 + useFocusEffect( 99 + useCallback(() => { 100 + return () => { 101 + void savePrefs.flush() 90 102 } 91 - }, 4e3) 92 - }, [mutateAsync]) 103 + }, [savePrefs]), 104 + ) 93 105 94 106 if (save && userUpdatedPrefs.current) { 95 107 savePrefs({