Tags menu/muted words improvements (#3002)

* Fix translations

* Handle loooong words

* Truncate on desktop web, revert mobile changes

* Break the words

* Small enough for mobile web

* Fix alignment on mobile web

* Clarify
zio/stable
Eric Bailey 2024-02-27 16:04:49 -06:00 committed by GitHub
parent 6717f8f11e
commit 978bcc1ba9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 53 additions and 11 deletions

View File

@ -12,6 +12,8 @@ import {
useUpsertMutedWordsMutation, useUpsertMutedWordsMutation,
useRemoveMutedWordMutation, useRemoveMutedWordMutation,
} from '#/state/queries/preferences' } from '#/state/queries/preferences'
import {enforceLen} from '#/lib/strings/helpers'
import {web} from '#/alf'
export function useTagMenuControl() {} export function useTagMenuControl() {}
@ -40,11 +42,12 @@ export function TagMenu({
)) && )) &&
!(optimisticRemove?.value === sanitizedTag), !(optimisticRemove?.value === sanitizedTag),
) )
const truncatedTag = enforceLen(tag, 15, true, 'middle')
const dropdownItems = React.useMemo(() => { const dropdownItems = React.useMemo(() => {
return [ return [
{ {
label: _(msg`See ${tag} posts`), label: _(msg`See ${truncatedTag} posts`),
onPress() { onPress() {
navigation.navigate('Search', { navigation.navigate('Search', {
q: tag, q: tag,
@ -61,7 +64,7 @@ export function TagMenu({
}, },
authorHandle && authorHandle &&
!isInvalidHandle(authorHandle) && { !isInvalidHandle(authorHandle) && {
label: _(msg`See ${tag} posts by this user`), label: _(msg`See ${truncatedTag} posts by user`),
onPress() { onPress() {
navigation.navigate({ navigation.navigate({
name: 'Search', name: 'Search',
@ -83,7 +86,9 @@ export function TagMenu({
label: 'separator', label: 'separator',
}, },
preferences && { preferences && {
label: isMuted ? _(msg`Unmute ${tag}`) : _(msg`Mute ${tag}`), label: isMuted
? _(msg`Unmute ${truncatedTag}`)
: _(msg`Mute ${truncatedTag}`),
onPress() { onPress() {
if (isMuted) { if (isMuted) {
removeMutedWord({value: sanitizedTag, targets: ['tag']}) removeMutedWord({value: sanitizedTag, targets: ['tag']})
@ -108,6 +113,7 @@ export function TagMenu({
navigation, navigation,
preferences, preferences,
tag, tag,
truncatedTag,
sanitizedTag, sanitizedTag,
upsertMutedWord, upsertMutedWord,
removeMutedWord, removeMutedWord,
@ -119,7 +125,10 @@ export function TagMenu({
accessibilityLabel={_(msg`Click here to open tag menu for ${tag}`)} accessibilityLabel={_(msg`Click here to open tag menu for ${tag}`)}
accessibilityHint="" accessibilityHint=""
// @ts-ignore // @ts-ignore
items={dropdownItems}> items={dropdownItems}
triggerStyle={web({
textAlign: 'left',
})}>
{children} {children}
</NativeDropdown> </NativeDropdown>
</EventStopper> </EventStopper>

View File

@ -10,7 +10,7 @@ import {
useRemoveMutedWordMutation, useRemoveMutedWordMutation,
} from '#/state/queries/preferences' } from '#/state/queries/preferences'
import {isNative} from '#/platform/detection' import {isNative} from '#/platform/detection'
import {atoms as a, useTheme, useBreakpoints, ViewStyleProp} from '#/alf' import {atoms as a, useTheme, useBreakpoints, ViewStyleProp, web} from '#/alf'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
@ -260,9 +260,21 @@ function MutedWordRow({
a.align_center, a.align_center,
a.justify_between, a.justify_between,
a.rounded_md, a.rounded_md,
a.gap_md,
style, style,
]}> ]}>
<Text style={[a.font_bold, t.atoms.text_contrast_high]}> <Text
style={[
a.flex_1,
a.leading_snug,
a.w_full,
a.font_bold,
t.atoms.text_contrast_high,
web({
overflowWrap: 'break-word',
wordBreak: 'break-word',
}),
]}>
{word.value} {word.value}
</Text> </Text>

View File

@ -8,10 +8,27 @@ export function pluralize(n: number, base: string, plural?: string): string {
return base + 's' return base + 's'
} }
export function enforceLen(str: string, len: number, ellipsis = false): string { export function enforceLen(
str: string,
len: number,
ellipsis = false,
mode: 'end' | 'middle' = 'end',
): string {
str = str || '' str = str || ''
if (str.length > len) { if (str.length > len) {
return str.slice(0, len) + (ellipsis ? '...' : '') if (ellipsis) {
if (mode === 'end') {
return str.slice(0, len) + '…'
} else if (mode === 'middle') {
const half = Math.floor(len / 2)
return str.slice(0, half) + '…' + str.slice(-half)
} else {
// fallback
return str.slice(0, len)
}
} else {
return str.slice(0, len)
}
} }
return str return str
} }

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import * as DropdownMenu from 'zeego/dropdown-menu' import * as DropdownMenu from 'zeego/dropdown-menu'
import {Pressable, StyleSheet, Platform, View} from 'react-native' import {Pressable, StyleSheet, Platform, View, ViewStyle} from 'react-native'
import {IconProp} from '@fortawesome/fontawesome-svg-core' import {IconProp} from '@fortawesome/fontawesome-svg-core'
import {MenuItemCommonProps} from 'zeego/lib/typescript/menu' import {MenuItemCommonProps} from 'zeego/lib/typescript/menu'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
@ -151,6 +151,7 @@ type Props = {
testID?: string testID?: string
accessibilityLabel?: string accessibilityLabel?: string
accessibilityHint?: string accessibilityHint?: string
triggerStyle?: ViewStyle
} }
/* The `NativeDropdown` function uses native iOS and Android dropdown menus. /* The `NativeDropdown` function uses native iOS and Android dropdown menus.

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import * as DropdownMenu from '@radix-ui/react-dropdown-menu' import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import {Pressable, StyleSheet, View, Text} from 'react-native' import {Pressable, StyleSheet, View, Text, ViewStyle} from 'react-native'
import {IconProp} from '@fortawesome/fontawesome-svg-core' import {IconProp} from '@fortawesome/fontawesome-svg-core'
import {MenuItemCommonProps} from 'zeego/lib/typescript/menu' import {MenuItemCommonProps} from 'zeego/lib/typescript/menu'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
@ -53,6 +53,7 @@ type Props = {
testID?: string testID?: string
accessibilityLabel?: string accessibilityLabel?: string
accessibilityHint?: string accessibilityHint?: string
triggerStyle?: ViewStyle
} }
export function NativeDropdown({ export function NativeDropdown({
@ -61,6 +62,7 @@ export function NativeDropdown({
testID, testID,
accessibilityLabel, accessibilityLabel,
accessibilityHint, accessibilityHint,
triggerStyle,
}: React.PropsWithChildren<Props>) { }: React.PropsWithChildren<Props>) {
const pal = usePalette('default') const pal = usePalette('default')
const theme = useTheme() const theme = useTheme()
@ -120,7 +122,8 @@ export function NativeDropdown({
accessibilityLabel={accessibilityLabel} accessibilityLabel={accessibilityLabel}
accessibilityHint={accessibilityHint} accessibilityHint={accessibilityHint}
onPress={() => setOpen(o => !o)} onPress={() => setOpen(o => !o)}
hitSlop={HITSLOP_10}> hitSlop={HITSLOP_10}
style={triggerStyle}>
{children} {children}
</Pressable> </Pressable>
</DropdownMenu.Trigger> </DropdownMenu.Trigger>