Add Renew menu for expired mute words (#9883)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-02-16 13:30:07 +00:00
committed by GitHub
parent b6b364700e
commit 4ebeb94b41
+107 -26
View File
@@ -8,6 +8,7 @@ import {logger} from '#/logger'
import { import {
usePreferencesQuery, usePreferencesQuery,
useRemoveMutedWordMutation, useRemoveMutedWordMutation,
useUpdateMutedWordMutation,
useUpsertMutedWordsMutation, useUpsertMutedWordsMutation,
} from '#/state/queries/preferences' } from '#/state/queries/preferences'
import { import {
@@ -29,6 +30,7 @@ import {PageText_Stroke2_Corner0_Rounded as PageText} from '#/components/icons/P
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import * as Menu from '#/components/Menu'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {IS_NATIVE} from '#/env' import {IS_NATIVE} from '#/env'
@@ -421,6 +423,7 @@ function MutedWordRow({
const t = useTheme() const t = useTheme()
const {_} = useLingui() const {_} = useLingui()
const {isPending, mutateAsync: removeMutedWord} = useRemoveMutedWordMutation() const {isPending, mutateAsync: removeMutedWord} = useRemoveMutedWordMutation()
const {mutateAsync: updateMutedWord} = useUpdateMutedWordMutation()
const control = Prompt.usePromptControl() const control = Prompt.usePromptControl()
const expiryDate = word.expiresAt ? new Date(word.expiresAt) : undefined const expiryDate = word.expiresAt ? new Date(word.expiresAt) : undefined
const isExpired = expiryDate && expiryDate < new Date() const isExpired = expiryDate && expiryDate < new Date()
@@ -431,6 +434,15 @@ function MutedWordRow({
removeMutedWord(word) removeMutedWord(word)
}, [removeMutedWord, word, control]) }, [removeMutedWord, word, control])
const renew = (days?: number) => {
updateMutedWord({
...word,
expiresAt: days
? new Date(Date.now() + days * ONE_DAY).toISOString()
: undefined,
})
}
return ( return (
<> <>
<Prompt.Basic <Prompt.Basic
@@ -493,35 +505,104 @@ function MutedWordRow({
</View> </View>
{(expiryDate || word.actorTarget === 'exclude-following') && ( {(expiryDate || word.actorTarget === 'exclude-following') && (
<View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> <View style={[a.flex_1, a.flex_row, a.align_center, a.flex_wrap]}>
<Text {expiryDate &&
style={[ (isExpired ? (
a.flex_1,
a.text_xs,
a.leading_snug,
t.atoms.text_contrast_medium,
]}>
{expiryDate && (
<> <>
{isExpired ? ( <Text
style={[
a.text_xs,
a.leading_snug,
t.atoms.text_contrast_medium,
]}>
<Trans>Expired</Trans> <Trans>Expired</Trans>
) : ( </Text>
<Trans> <Text
Expires{' '} style={[
{formatDistance(expiryDate, new Date(), { a.text_xs,
addSuffix: true, a.leading_snug,
})} t.atoms.text_contrast_medium,
</Trans> ]}>
)} {' · '}
</Text>
<Menu.Root>
<Menu.Trigger label={_(msg`Renew mute word`)}>
{({props}) => (
<Text
{...props}
style={[
a.text_xs,
a.leading_snug,
a.font_semi_bold,
{color: t.palette.primary_500},
]}>
<Trans>Renew</Trans>
</Text>
)}
</Menu.Trigger>
<Menu.Outer>
<Menu.LabelText>
<Trans>Renew duration</Trans>
</Menu.LabelText>
<Menu.Group>
<Menu.Item
label={_(msg`24 hours`)}
onPress={() => renew(1)}>
<Menu.ItemText>
<Trans>24 hours</Trans>
</Menu.ItemText>
</Menu.Item>
<Menu.Item
label={_(msg`7 days`)}
onPress={() => renew(7)}>
<Menu.ItemText>
<Trans>7 days</Trans>
</Menu.ItemText>
</Menu.Item>
<Menu.Item
label={_(msg`30 days`)}
onPress={() => renew(30)}>
<Menu.ItemText>
<Trans>30 days</Trans>
</Menu.ItemText>
</Menu.Item>
<Menu.Item
label={_(msg`Forever`)}
onPress={() => renew()}>
<Menu.ItemText>
<Trans>Forever</Trans>
</Menu.ItemText>
</Menu.Item>
</Menu.Group>
</Menu.Outer>
</Menu.Root>
</> </>
)} ) : (
{word.actorTarget === 'exclude-following' && ( <Text
<> style={[
{' '} a.text_xs,
<Trans>Excludes users you follow</Trans> a.leading_snug,
</> t.atoms.text_contrast_medium,
)} ]}>
</Text> <Trans>
Expires{' '}
{formatDistance(expiryDate, new Date(), {
addSuffix: true,
})}
</Trans>
</Text>
))}
{word.actorTarget === 'exclude-following' && (
<Text
style={[
a.text_xs,
a.leading_snug,
t.atoms.text_contrast_medium,
]}>
{expiryDate ? ' · ' : ''}
<Trans>Excludes users you follow</Trans>
</Text>
)}
</View> </View>
)} )}
</View> </View>