Bluesky app fork with some witchin' additions ๐Ÿ’ซ
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

attempt to fix preferences disappearing ๐Ÿ’ฅ๐Ÿ’ฅ๐Ÿ’ฅ

xan.lol 7753fdaf 95d22729

+157 -26
+157 -26
src/state/queries/preferences/index.ts
··· 5 5 type BskyPreferences, 6 6 type LabelPreference, 7 7 } from '@atproto/api' 8 + import {TID} from '@atproto/common-web' 8 9 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query' 9 10 10 11 import {PROD_DEFAULT_FEED} from '#/lib/constants' ··· 94 95 } 95 96 } 96 97 return data 98 + } 99 + 100 + type PreferencesMutationContext = { 101 + previousPreferences: UsePreferencesQueryResponse | undefined 102 + } 103 + 104 + function updateCachedPreferences( 105 + queryClient: ReturnType<typeof useQueryClient>, 106 + updater: (data: UsePreferencesQueryResponse) => UsePreferencesQueryResponse, 107 + ) { 108 + queryClient.setQueryData<UsePreferencesQueryResponse | undefined>( 109 + preferencesQueryKey, 110 + previous => (previous ? updater(previous) : previous), 111 + ) 112 + } 113 + 114 + async function mutateCachedPreferences( 115 + queryClient: ReturnType<typeof useQueryClient>, 116 + updater: (data: UsePreferencesQueryResponse) => UsePreferencesQueryResponse, 117 + ): Promise<PreferencesMutationContext> { 118 + await queryClient.cancelQueries({queryKey: preferencesQueryKey}) 119 + const previousPreferences = 120 + queryClient.getQueryData<UsePreferencesQueryResponse>(preferencesQueryKey) 121 + updateCachedPreferences(queryClient, updater) 122 + return {previousPreferences} 123 + } 124 + 125 + function restoreCachedPreferences( 126 + queryClient: ReturnType<typeof useQueryClient>, 127 + context: PreferencesMutationContext | undefined, 128 + ) { 129 + if (!context) return 130 + queryClient.setQueryData(preferencesQueryKey, context.previousPreferences) 131 + } 132 + 133 + function refetchPreferences(queryClient: ReturnType<typeof useQueryClient>) { 134 + void queryClient.invalidateQueries({ 135 + queryKey: preferencesQueryKey, 136 + }) 97 137 } 98 138 99 139 export function usePreferencesQuery() { ··· 275 315 const queryClient = useQueryClient() 276 316 const agent = useAgent() 277 317 278 - return useMutation<void, unknown, AppBskyActorDefs.SavedFeed[]>({ 318 + return useMutation< 319 + void, 320 + unknown, 321 + AppBskyActorDefs.SavedFeed[], 322 + PreferencesMutationContext 323 + >({ 324 + onMutate: savedFeeds => 325 + mutateCachedPreferences(queryClient, data => ({ 326 + ...data, 327 + savedFeeds, 328 + })), 329 + onError: (_error, _savedFeeds, context) => { 330 + restoreCachedPreferences(queryClient, context) 331 + }, 332 + onSettled: () => { 333 + refetchPreferences(queryClient) 334 + }, 279 335 mutationFn: async savedFeeds => { 280 336 await agent.overwriteSavedFeeds(savedFeeds) 281 - // triggers a refetch 282 - await queryClient.invalidateQueries({ 283 - queryKey: preferencesQueryKey, 284 - }) 285 337 }, 286 338 }) 287 339 } ··· 293 345 return useMutation< 294 346 void, 295 347 unknown, 296 - Pick<AppBskyActorDefs.SavedFeed, 'type' | 'value' | 'pinned'>[] 348 + Pick<AppBskyActorDefs.SavedFeed, 'type' | 'value' | 'pinned'>[], 349 + PreferencesMutationContext 297 350 >({ 351 + onMutate: savedFeeds => 352 + mutateCachedPreferences(queryClient, data => ({ 353 + ...data, 354 + savedFeeds: data.savedFeeds.concat( 355 + savedFeeds.map(savedFeed => ({ 356 + ...savedFeed, 357 + id: TID.nextStr(), 358 + })), 359 + ), 360 + })), 361 + onError: (_error, _savedFeeds, context) => { 362 + restoreCachedPreferences(queryClient, context) 363 + }, 364 + onSettled: () => { 365 + refetchPreferences(queryClient) 366 + }, 298 367 mutationFn: async savedFeeds => { 299 368 await agent.addSavedFeeds(savedFeeds) 300 - // triggers a refetch 301 - await queryClient.invalidateQueries({ 302 - queryKey: preferencesQueryKey, 303 - }) 304 369 }, 305 370 }) 306 371 } ··· 309 374 const queryClient = useQueryClient() 310 375 const agent = useAgent() 311 376 312 - return useMutation<void, unknown, Pick<AppBskyActorDefs.SavedFeed, 'id'>>({ 377 + return useMutation< 378 + void, 379 + unknown, 380 + Pick<AppBskyActorDefs.SavedFeed, 'id'>, 381 + PreferencesMutationContext 382 + >({ 383 + onMutate: savedFeed => 384 + mutateCachedPreferences(queryClient, data => ({ 385 + ...data, 386 + savedFeeds: data.savedFeeds.filter(feed => feed.id !== savedFeed.id), 387 + })), 388 + onError: (_error, _savedFeed, context) => { 389 + restoreCachedPreferences(queryClient, context) 390 + }, 391 + onSettled: () => { 392 + refetchPreferences(queryClient) 393 + }, 313 394 mutationFn: async savedFeed => { 314 395 await agent.removeSavedFeeds([savedFeed.id]) 315 - // triggers a refetch 316 - await queryClient.invalidateQueries({ 317 - queryKey: preferencesQueryKey, 318 - }) 319 396 }, 320 397 }) 321 398 } ··· 324 401 const queryClient = useQueryClient() 325 402 const agent = useAgent() 326 403 327 - return useMutation({ 404 + return useMutation< 405 + void, 406 + unknown, 407 + { 408 + forYouFeedConfig: AppBskyActorDefs.SavedFeed | undefined 409 + discoverFeedConfig: AppBskyActorDefs.SavedFeed | undefined 410 + }, 411 + PreferencesMutationContext 412 + >({ 413 + onMutate: ({forYouFeedConfig, discoverFeedConfig}) => 414 + mutateCachedPreferences(queryClient, data => { 415 + let savedFeeds = data.savedFeeds 416 + 417 + if (forYouFeedConfig) { 418 + savedFeeds = savedFeeds.filter( 419 + feed => feed.id !== forYouFeedConfig.id, 420 + ) 421 + } 422 + 423 + if (!discoverFeedConfig) { 424 + savedFeeds = savedFeeds.concat({ 425 + type: 'feed', 426 + value: PROD_DEFAULT_FEED('whats-hot'), 427 + pinned: true, 428 + id: TID.nextStr(), 429 + }) 430 + } else { 431 + savedFeeds = savedFeeds.map(feed => 432 + feed.id === discoverFeedConfig.id ? {...feed, pinned: true} : feed, 433 + ) 434 + } 435 + 436 + return { 437 + ...data, 438 + savedFeeds, 439 + } 440 + }), 441 + onError: (_error, _variables, context) => { 442 + restoreCachedPreferences(queryClient, context) 443 + }, 444 + onSettled: () => { 445 + refetchPreferences(queryClient) 446 + }, 328 447 mutationFn: async ({ 329 448 forYouFeedConfig, 330 449 discoverFeedConfig, ··· 351 470 }, 352 471 ]) 353 472 } 354 - // triggers a refetch 355 - await queryClient.invalidateQueries({ 356 - queryKey: preferencesQueryKey, 357 - }) 358 473 }, 359 474 }) 360 475 } ··· 363 478 const queryClient = useQueryClient() 364 479 const agent = useAgent() 365 480 366 - return useMutation<void, unknown, AppBskyActorDefs.SavedFeed[]>({ 481 + return useMutation< 482 + void, 483 + unknown, 484 + AppBskyActorDefs.SavedFeed[], 485 + PreferencesMutationContext 486 + >({ 487 + onMutate: feeds => 488 + mutateCachedPreferences(queryClient, data => { 489 + const nextById = new Map(feeds.map(feed => [feed.id, feed])) 490 + return { 491 + ...data, 492 + savedFeeds: data.savedFeeds.map( 493 + feed => nextById.get(feed.id) ?? feed, 494 + ), 495 + } 496 + }), 497 + onError: (_error, _feeds, context) => { 498 + restoreCachedPreferences(queryClient, context) 499 + }, 500 + onSettled: () => { 501 + refetchPreferences(queryClient) 502 + }, 367 503 mutationFn: async feeds => { 368 504 await agent.updateSavedFeeds(feeds) 369 - 370 - // triggers a refetch 371 - await queryClient.invalidateQueries({ 372 - queryKey: preferencesQueryKey, 373 - }) 374 505 }, 375 506 }) 376 507 }