Optimize native tag input

This commit is contained in:
Eric Bailey
2024-03-07 09:55:54 -06:00
parent 8b0e575f64
commit 7693a2e0de
+160 -160
View File
@@ -23,6 +23,16 @@ import {
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import {isInvalidHandle} from '#/lib/strings/handles' import {isInvalidHandle} from '#/lib/strings/handles'
type TagMenuProps = {
control: Dialog.DialogOuterProps['control']
/**
* This should be the sanitized tag value from the facet itself, not the
* "display" value with a leading `#`.
*/
tag: string
authorHandle?: string
}
export function useTagMenuControl() { export function useTagMenuControl() {
return Dialog.useDialogControl() return Dialog.useDialogControl()
} }
@@ -32,15 +42,20 @@ export function TagMenu({
control, control,
tag, tag,
authorHandle, authorHandle,
}: React.PropsWithChildren<{ }: React.PropsWithChildren<TagMenuProps>) {
control: Dialog.DialogOuterProps['control'] return (
/** <>
* This should be the sanitized tag value from the facet itself, not the {children}
* "display" value with a leading `#`.
*/ <Dialog.Outer control={control}>
tag: string <Dialog.Handle />
authorHandle?: string <TagMenuInner control={control} tag={tag} authorHandle={authorHandle} />
}>) { </Dialog.Outer>
</>
)
}
function TagMenuInner({control, tag, authorHandle}: TagMenuProps) {
const {_} = useLingui() const {_} = useLingui()
const t = useTheme() const t = useTheme()
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
@@ -69,36 +84,86 @@ export function TagMenu({
) )
return ( return (
<> <Dialog.Inner label={_(msg`Tag menu: ${displayTag}`)}>
{children} {isPreferencesLoading ? (
<View style={[a.w_full, a.align_center]}>
<Loader size="lg" />
</View>
) : (
<>
<View
style={[
a.rounded_md,
a.border,
a.mb_md,
t.atoms.border_contrast_low,
t.atoms.bg_contrast_25,
]}>
<Link
label={_(msg`Search for all posts with tag ${displayTag}`)}
to={makeSearchLink({query: displayTag})}
onPress={e => {
e.preventDefault()
<Dialog.Outer control={control}> control.close(() => {
<Dialog.Handle /> navigation.push('Hashtag', {
tag: tag.replaceAll('#', '%23'),
})
})
<Dialog.Inner label={_(msg`Tag menu: ${displayTag}`)}> return false
{isPreferencesLoading ? ( }}>
<View style={[a.w_full, a.align_center]}>
<Loader size="lg" />
</View>
) : (
<>
<View <View
style={[ style={[
a.rounded_md, a.w_full,
a.border, a.flex_row,
a.mb_md, a.align_center,
t.atoms.border_contrast_low, a.justify_start,
t.atoms.bg_contrast_25, a.gap_md,
a.px_lg,
a.py_md,
]}> ]}>
<Search size="lg" style={[t.atoms.text_contrast_medium]} />
<Text
numberOfLines={1}
ellipsizeMode="middle"
style={[
a.flex_1,
a.text_md,
a.font_bold,
native({top: 2}),
t.atoms.text_contrast_medium,
]}>
<Trans>
See{' '}
<Text style={[a.text_md, a.font_bold, t.atoms.text]}>
{displayTag}
</Text>{' '}
posts
</Trans>
</Text>
</View>
</Link>
{authorHandle && !isInvalidHandle(authorHandle) && (
<>
<Divider />
<Link <Link
label={_(msg`Search for all posts with tag ${displayTag}`)} label={_(
to={makeSearchLink({query: displayTag})} msg`Search for all posts by @${authorHandle} with tag ${displayTag}`,
)}
to={makeSearchLink({
query: displayTag,
from: authorHandle,
})}
onPress={e => { onPress={e => {
e.preventDefault() e.preventDefault()
control.close(() => { control.close(() => {
navigation.push('Hashtag', { navigation.push('Hashtag', {
tag: tag.replaceAll('#', '%23'), tag: tag.replaceAll('#', '%23'),
author: authorHandle,
}) })
}) })
@@ -114,7 +179,7 @@ export function TagMenu({
a.px_lg, a.px_lg,
a.py_md, a.py_md,
]}> ]}>
<Search size="lg" style={[t.atoms.text_contrast_medium]} /> <Person size="lg" style={[t.atoms.text_contrast_medium]} />
<Text <Text
numberOfLines={1} numberOfLines={1}
ellipsizeMode="middle" ellipsizeMode="middle"
@@ -130,146 +195,81 @@ export function TagMenu({
<Text style={[a.text_md, a.font_bold, t.atoms.text]}> <Text style={[a.text_md, a.font_bold, t.atoms.text]}>
{displayTag} {displayTag}
</Text>{' '} </Text>{' '}
posts posts by this user
</Trans> </Trans>
</Text> </Text>
</View> </View>
</Link> </Link>
</>
)}
{authorHandle && !isInvalidHandle(authorHandle) && ( {preferences ? (
<> <>
<Divider /> <Divider />
<Link <Button
label={_( label={
msg`Search for all posts by @${authorHandle} with tag ${displayTag}`, isMuted
)} ? _(msg`Unmute all ${displayTag} posts`)
to={makeSearchLink({ : _(msg`Mute all ${displayTag} posts`)
query: displayTag, }
from: authorHandle, onPress={() => {
})} control.close(() => {
onPress={e => { if (isMuted) {
e.preventDefault() resetUpsert()
removeMutedWord({
control.close(() => { value: tag,
navigation.push('Hashtag', { targets: ['tag'],
tag: tag.replaceAll('#', '%23'),
author: authorHandle,
})
}) })
} else {
return false resetRemove()
}}> upsertMutedWord([{value: tag, targets: ['tag']}])
<View
style={[
a.w_full,
a.flex_row,
a.align_center,
a.justify_start,
a.gap_md,
a.px_lg,
a.py_md,
]}>
<Person
size="lg"
style={[t.atoms.text_contrast_medium]}
/>
<Text
numberOfLines={1}
ellipsizeMode="middle"
style={[
a.flex_1,
a.text_md,
a.font_bold,
native({top: 2}),
t.atoms.text_contrast_medium,
]}>
<Trans>
See{' '}
<Text
style={[a.text_md, a.font_bold, t.atoms.text]}>
{displayTag}
</Text>{' '}
posts by this user
</Trans>
</Text>
</View>
</Link>
</>
)}
{preferences ? (
<>
<Divider />
<Button
label={
isMuted
? _(msg`Unmute all ${displayTag} posts`)
: _(msg`Mute all ${displayTag} posts`)
} }
onPress={() => { })
control.close(() => { }}>
if (isMuted) { <View
resetUpsert() style={[
removeMutedWord({ a.w_full,
value: tag, a.flex_row,
targets: ['tag'], a.align_center,
}) a.justify_start,
} else { a.gap_md,
resetRemove() a.px_lg,
upsertMutedWord([{value: tag, targets: ['tag']}]) a.py_md,
} ]}>
}) <Mute size="lg" style={[t.atoms.text_contrast_medium]} />
}}> <Text
<View numberOfLines={1}
style={[ ellipsizeMode="middle"
a.w_full, style={[
a.flex_row, a.flex_1,
a.align_center, a.text_md,
a.justify_start, a.font_bold,
a.gap_md, native({top: 2}),
a.px_lg, t.atoms.text_contrast_medium,
a.py_md, ]}>
]}> {isMuted ? _(msg`Unmute`) : _(msg`Mute`)}{' '}
<Mute <Text style={[a.text_md, a.font_bold, t.atoms.text]}>
size="lg" {displayTag}
style={[t.atoms.text_contrast_medium]} </Text>{' '}
/> <Trans>posts</Trans>
<Text </Text>
numberOfLines={1} </View>
ellipsizeMode="middle" </Button>
style={[ </>
a.flex_1, ) : null}
a.text_md, </View>
a.font_bold,
native({top: 2}),
t.atoms.text_contrast_medium,
]}>
{isMuted ? _(msg`Unmute`) : _(msg`Mute`)}{' '}
<Text style={[a.text_md, a.font_bold, t.atoms.text]}>
{displayTag}
</Text>{' '}
<Trans>posts</Trans>
</Text>
</View>
</Button>
</>
) : null}
</View>
<Button <Button
label={_(msg`Close this dialog`)} label={_(msg`Close this dialog`)}
size="small" size="small"
variant="ghost" variant="ghost"
color="secondary" color="secondary"
onPress={() => control.close()}> onPress={() => control.close()}>
<ButtonText>Cancel</ButtonText> <ButtonText>Cancel</ButtonText>
</Button> </Button>
</> </>
)} )}
</Dialog.Inner> </Dialog.Inner>
</Dialog.Outer>
</>
) )
} }