Bluesky app fork with some witchin' additions ๐Ÿ’ซ witchsky.app
bluesky fork client
122
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 }