Bluesky app fork with some witchin' additions 💫

Add Renew menu for expired mute words (#9883)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

authored by samuel.fm

Claude Opus 4.6 and committed by
GitHub
4ebeb94b b6b36470

+107 -26
+107 -26
src/components/dialogs/MutedWords.tsx
··· 8 8 import { 9 9 usePreferencesQuery, 10 10 useRemoveMutedWordMutation, 11 + useUpdateMutedWordMutation, 11 12 useUpsertMutedWordsMutation, 12 13 } from '#/state/queries/preferences' 13 14 import { ··· 29 30 import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' 30 31 import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' 31 32 import {Loader} from '#/components/Loader' 33 + import * as Menu from '#/components/Menu' 32 34 import * as Prompt from '#/components/Prompt' 33 35 import {Text} from '#/components/Typography' 34 36 import {IS_NATIVE} from '#/env' ··· 421 423 const t = useTheme() 422 424 const {_} = useLingui() 423 425 const {isPending, mutateAsync: removeMutedWord} = useRemoveMutedWordMutation() 426 + const {mutateAsync: updateMutedWord} = useUpdateMutedWordMutation() 424 427 const control = Prompt.usePromptControl() 425 428 const expiryDate = word.expiresAt ? new Date(word.expiresAt) : undefined 426 429 const isExpired = expiryDate && expiryDate < new Date() ··· 430 433 control.close() 431 434 removeMutedWord(word) 432 435 }, [removeMutedWord, word, control]) 436 + 437 + const renew = (days?: number) => { 438 + updateMutedWord({ 439 + ...word, 440 + expiresAt: days 441 + ? new Date(Date.now() + days * ONE_DAY).toISOString() 442 + : undefined, 443 + }) 444 + } 433 445 434 446 return ( 435 447 <> ··· 493 505 </View> 494 506 495 507 {(expiryDate || word.actorTarget === 'exclude-following') && ( 496 - <View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> 497 - <Text 498 - style={[ 499 - a.flex_1, 500 - a.text_xs, 501 - a.leading_snug, 502 - t.atoms.text_contrast_medium, 503 - ]}> 504 - {expiryDate && ( 508 + <View style={[a.flex_1, a.flex_row, a.align_center, a.flex_wrap]}> 509 + {expiryDate && 510 + (isExpired ? ( 505 511 <> 506 - {isExpired ? ( 512 + <Text 513 + style={[ 514 + a.text_xs, 515 + a.leading_snug, 516 + t.atoms.text_contrast_medium, 517 + ]}> 507 518 <Trans>Expired</Trans> 508 - ) : ( 509 - <Trans> 510 - Expires{' '} 511 - {formatDistance(expiryDate, new Date(), { 512 - addSuffix: true, 513 - })} 514 - </Trans> 515 - )} 519 + </Text> 520 + <Text 521 + style={[ 522 + a.text_xs, 523 + a.leading_snug, 524 + t.atoms.text_contrast_medium, 525 + ]}> 526 + {' · '} 527 + </Text> 528 + <Menu.Root> 529 + <Menu.Trigger label={_(msg`Renew mute word`)}> 530 + {({props}) => ( 531 + <Text 532 + {...props} 533 + style={[ 534 + a.text_xs, 535 + a.leading_snug, 536 + a.font_semi_bold, 537 + {color: t.palette.primary_500}, 538 + ]}> 539 + <Trans>Renew</Trans> 540 + </Text> 541 + )} 542 + </Menu.Trigger> 543 + <Menu.Outer> 544 + <Menu.LabelText> 545 + <Trans>Renew duration</Trans> 546 + </Menu.LabelText> 547 + <Menu.Group> 548 + <Menu.Item 549 + label={_(msg`24 hours`)} 550 + onPress={() => renew(1)}> 551 + <Menu.ItemText> 552 + <Trans>24 hours</Trans> 553 + </Menu.ItemText> 554 + </Menu.Item> 555 + <Menu.Item 556 + label={_(msg`7 days`)} 557 + onPress={() => renew(7)}> 558 + <Menu.ItemText> 559 + <Trans>7 days</Trans> 560 + </Menu.ItemText> 561 + </Menu.Item> 562 + <Menu.Item 563 + label={_(msg`30 days`)} 564 + onPress={() => renew(30)}> 565 + <Menu.ItemText> 566 + <Trans>30 days</Trans> 567 + </Menu.ItemText> 568 + </Menu.Item> 569 + <Menu.Item 570 + label={_(msg`Forever`)} 571 + onPress={() => renew()}> 572 + <Menu.ItemText> 573 + <Trans>Forever</Trans> 574 + </Menu.ItemText> 575 + </Menu.Item> 576 + </Menu.Group> 577 + </Menu.Outer> 578 + </Menu.Root> 516 579 </> 517 - )} 518 - {word.actorTarget === 'exclude-following' && ( 519 - <> 520 - {' • '} 521 - <Trans>Excludes users you follow</Trans> 522 - </> 523 - )} 524 - </Text> 580 + ) : ( 581 + <Text 582 + style={[ 583 + a.text_xs, 584 + a.leading_snug, 585 + t.atoms.text_contrast_medium, 586 + ]}> 587 + <Trans> 588 + Expires{' '} 589 + {formatDistance(expiryDate, new Date(), { 590 + addSuffix: true, 591 + })} 592 + </Trans> 593 + </Text> 594 + ))} 595 + {word.actorTarget === 'exclude-following' && ( 596 + <Text 597 + style={[ 598 + a.text_xs, 599 + a.leading_snug, 600 + t.atoms.text_contrast_medium, 601 + ]}> 602 + {expiryDate ? ' · ' : ''} 603 + <Trans>Excludes users you follow</Trans> 604 + </Text> 605 + )} 525 606 </View> 526 607 )} 527 608 </View>