fix(mobile): stop full scene-list refetch on back-navigation (perf)
Returning to the Scenes list from a scene caused a full reload + phone load spike (report 5df48551). Cause: invalidateQueries(['scenes']) in SceneDetail/Player/Performer/Studio handlers — including the silent auto-enrich-thumbnail that fires on opening any thumbnail-less scene — forces react-query to refetch EVERY loaded page of the infinite list. Added refetchType:'none' to all ['scenes'] invalidations: marks stale without refetching the active list, which refreshes on pull-to-refresh / filter change instead. Scene detail (['scene', id]) still updates immediately. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c524b43fa3
commit
b0e15935c6
5 changed files with 18 additions and 8 deletions
|
|
@ -16,6 +16,13 @@ export type ChangelogEntry = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CHANGELOG: ChangelogEntry[] = [
|
export const CHANGELOG: ChangelogEntry[] = [
|
||||||
|
{
|
||||||
|
id: '2026-06-20',
|
||||||
|
date: 'June 2026',
|
||||||
|
items: [
|
||||||
|
'Going back to the list from a scene no longer reloads everything or slows the phone.',
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: '2026-06-19',
|
id: '2026-06-19',
|
||||||
date: 'June 2026',
|
date: 'June 2026',
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ export function PerformerScenesScreen() {
|
||||||
const blacklistMutation = useMutation({
|
const blacklistMutation = useMutation({
|
||||||
mutationFn: () => client.addBlacklist('performer', id),
|
mutationFn: () => client.addBlacklist('performer', id),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
queryClient.invalidateQueries({ queryKey: ['performer-scenes', id] });
|
queryClient.invalidateQueries({ queryKey: ['performer-scenes', id] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['performer-movies', id] });
|
queryClient.invalidateQueries({ queryKey: ['performer-movies', id] });
|
||||||
navigation.goBack();
|
navigation.goBack();
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,10 @@ function useMarkSourceBroken(params: RouteParams) {
|
||||||
await client.markPlaybackDead(params.sceneId, params.playbackId);
|
await client.markPlaybackDead(params.sceneId, params.playbackId);
|
||||||
queryClient.invalidateQueries({ queryKey: ['scene', params.sceneId] });
|
queryClient.invalidateQueries({ queryKey: ['scene', params.sceneId] });
|
||||||
}
|
}
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
// refetchType:'none' — oznacz stale bez wymuszania refetcha całej infinite-listy
|
||||||
|
// (po powrocie do Scenes powodowało przeładowanie wszystkich stron = obciążenie,
|
||||||
|
// bug-report 5df48551). Lista odświeży się przy pull-to-refresh / zmianie filtra.
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
} catch {
|
} catch {
|
||||||
// best-effort — i tak wracamy; źródło zostanie do następnej próby
|
// best-effort — i tak wracamy; źródło zostanie do następnej próby
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ export function SceneDetailScreen() {
|
||||||
mutationFn: () => (isFav ? client.removeSceneFavorite(id) : client.addSceneFavorite(id)),
|
mutationFn: () => (isFav ? client.removeSceneFavorite(id) : client.addSceneFavorite(id)),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['scene', id] });
|
queryClient.invalidateQueries({ queryKey: ['scene', id] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ export function SceneDetailScreen() {
|
||||||
onSuccess: (out) => {
|
onSuccess: (out) => {
|
||||||
if (out.thumbnail_url) {
|
if (out.thumbnail_url) {
|
||||||
queryClient.invalidateQueries({ queryKey: ['scene', id] });
|
queryClient.invalidateQueries({ queryKey: ['scene', id] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -126,7 +126,7 @@ export function SceneDetailScreen() {
|
||||||
mutationFn: () => client.enrichSceneThumbnail(id, true),
|
mutationFn: () => client.enrichSceneThumbnail(id, true),
|
||||||
onSuccess: (out) => {
|
onSuccess: (out) => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['scene', id] });
|
queryClient.invalidateQueries({ queryKey: ['scene', id] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
'Thumbnail',
|
'Thumbnail',
|
||||||
out.thumbnail_url ? 'Refreshed from the source page.' : 'Could not fetch a fresh thumbnail.',
|
out.thumbnail_url ? 'Refreshed from the source page.' : 'Could not fetch a fresh thumbnail.',
|
||||||
|
|
@ -697,7 +697,7 @@ function PlaybackButton({
|
||||||
'The tube removed this video. We marked the source, you won\'t see it again.',
|
'The tube removed this video. We marked the source, you won\'t see it again.',
|
||||||
);
|
);
|
||||||
queryClient.invalidateQueries({ queryKey: ['scene', sceneId] });
|
queryClient.invalidateQueries({ queryKey: ['scene', sceneId] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 503 = transient extraction failure (hoster chwilowo niedostępny, network
|
// 503 = transient extraction failure (hoster chwilowo niedostępny, network
|
||||||
|
|
@ -789,7 +789,7 @@ function PlaybackButton({
|
||||||
try {
|
try {
|
||||||
await client.markPlaybackDead(sceneId, source.id);
|
await client.markPlaybackDead(sceneId, source.id);
|
||||||
queryClient.invalidateQueries({ queryKey: ['scene', sceneId] });
|
queryClient.invalidateQueries({ queryKey: ['scene', sceneId] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Alert.alert('Failed', e instanceof Error ? e.message : String(e));
|
Alert.alert('Failed', e instanceof Error ? e.message : String(e));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export function StudioScenesScreen() {
|
||||||
const blacklistMutation = useMutation({
|
const blacklistMutation = useMutation({
|
||||||
mutationFn: () => client.addBlacklist('studio', studioId),
|
mutationFn: () => client.addBlacklist('studio', studioId),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
queryClient.invalidateQueries({ queryKey: ['scenes'], refetchType: 'none' });
|
||||||
queryClient.invalidateQueries({ queryKey: ['studio-scenes', slug] });
|
queryClient.invalidateQueries({ queryKey: ['studio-scenes', slug] });
|
||||||
navigation.goBack();
|
navigation.goBack();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue