diff options
author | Samuel Newman <mozzius@protonmail.com> | 2025-09-05 18:34:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-09-05 08:34:00 -0700 |
commit | ee3e08393882a9d72ae9cab5f765ed2885c5a98d (patch) | |
tree | a18396cf22b84b22073059922819e278890cc36a | |
parent | 0f089060d2596bf75f141d1d574f14952bca1066 (diff) | |
download | voidsky-ee3e08393882a9d72ae9cab5f765ed2885c5a98d.tar.zst |
Restore quick language select (#8981)
* restore quick language select * rm showCancel * rm margin from thread button * alf composer icons * stop hiding keyboard * use trans
-rw-r--r-- | src/state/persisted/schema.ts | 4 | ||||
-rw-r--r-- | src/view/com/composer/Composer.tsx | 29 | ||||
-rw-r--r-- | src/view/com/composer/select-language/PostLanguageSelect.tsx | 131 | ||||
-rw-r--r-- | src/view/com/composer/select-language/PostLanguageSelectDialog.tsx (renamed from src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx) | 80 |
4 files changed, 154 insertions, 90 deletions
diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts index f840081f3..11204f309 100644 --- a/src/state/persisted/schema.ts +++ b/src/state/persisted/schema.ts @@ -78,8 +78,8 @@ const schema = z.object({ postLanguage: z.string(), /** * The user's post language history, used to pre-populate the post language - * selector in the composer. Within each value, multiple languages are - * separated by values. + * selector in the composer. Within each value, multiple languages are separated + * by commas. * * BCP-47 2-letter language codes without region. */ diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index 20f2549ad..61715a988 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -110,7 +110,6 @@ import {LabelsBtn} from '#/view/com/composer/labels/LabelsBtn' import {Gallery} from '#/view/com/composer/photos/Gallery' import {OpenCameraBtn} from '#/view/com/composer/photos/OpenCameraBtn' import {SelectGifBtn} from '#/view/com/composer/photos/SelectGifBtn' -import {SelectPostLanguagesBtn} from '#/view/com/composer/select-language/SelectPostLanguagesDialog' import {SuggestedLanguage} from '#/view/com/composer/select-language/SuggestedLanguage' // TODO: Prevent naming components that coincide with RN primitives // due to linting false positives @@ -123,14 +122,16 @@ import {Text} from '#/view/com/util/text/Text' import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, native, useTheme, web} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' -import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' -import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji' -import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' +import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfoIcon} from '#/components/icons/CircleInfo' +import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmileIcon} from '#/components/icons/Emoji' +import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/Plus' +import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' import {LazyQuoteEmbed} from '#/components/Post/Embed/LazyQuoteEmbed' import * as Prompt from '#/components/Prompt' import * as Toast from '#/components/Toast' import {Text as NewText} from '#/components/Typography' import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet' +import {PostLanguageSelect} from './select-language/PostLanguageSelect' import { type AssetType, SelectMediaButton, @@ -941,7 +942,7 @@ let ComposerPost = React.memo(function ComposerPost({ }) } }}> - <ButtonIcon icon={X} /> + <ButtonIcon icon={XIcon} /> </Button> <Prompt.Basic control={discardPromptControl} @@ -1430,7 +1431,7 @@ function ComposerFooter({ variant="ghost" shape="round" color="primary"> - <EmojiSmile size="lg" /> + <EmojiSmileIcon size="lg" /> </Button> ) : null} </ToolbarWrapper> @@ -1440,20 +1441,16 @@ function ComposerFooter({ <View style={[a.flex_row, a.align_center, a.justify_between]}> {showAddButton && ( <Button - label={_(msg`Add new post`)} + label={_(msg`Add another post to thread`)} onPress={onAddPost} - style={[a.p_sm, a.m_2xs]} + style={[a.p_sm]} variant="ghost" shape="round" color="primary"> - <FontAwesomeIcon - icon="add" - size={20} - color={t.palette.primary_500} - /> + <PlusIcon size="lg" /> </Button> )} - <SelectPostLanguagesBtn /> + <PostLanguageSelect /> <CharProgress count={post.shortenedGraphemeLength} style={{width: 65}} @@ -1753,7 +1750,7 @@ function ErrorBanner({ t.atoms.bg_contrast_25, ]}> <View style={[a.relative, a.flex_row, a.gap_sm, {paddingRight: 48}]}> - <CircleInfo fill={t.palette.negative_400} /> + <CircleInfoIcon fill={t.palette.negative_400} /> <NewText style={[a.flex_1, a.leading_snug, {paddingTop: 1}]}> {error} </NewText> @@ -1765,7 +1762,7 @@ function ErrorBanner({ shape="round" style={[a.absolute, {top: 0, right: 0}]} onPress={onClearError}> - <ButtonIcon icon={X} /> + <ButtonIcon icon={XIcon} /> </Button> </View> {videoError && videoState.jobId && ( diff --git a/src/view/com/composer/select-language/PostLanguageSelect.tsx b/src/view/com/composer/select-language/PostLanguageSelect.tsx new file mode 100644 index 000000000..6291e8422 --- /dev/null +++ b/src/view/com/composer/select-language/PostLanguageSelect.tsx @@ -0,0 +1,131 @@ +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {LANG_DROPDOWN_HITSLOP} from '#/lib/constants' +import {codeToLanguageName} from '#/locale/helpers' +import { + toPostLanguages, + useLanguagePrefs, + useLanguagePrefsApi, +} from '#/state/preferences/languages' +import {atoms as a, useTheme} from '#/alf' +import {Button, type ButtonProps} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron' +import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe' +import * as Menu from '#/components/Menu' +import {Text} from '#/components/Typography' +import {PostLanguageSelectDialog} from './PostLanguageSelectDialog' + +export function PostLanguageSelect() { + const {_} = useLingui() + const langPrefs = useLanguagePrefs() + const setLangPrefs = useLanguagePrefsApi() + const languageDialogControl = Dialog.useDialogControl() + + const dedupedHistory = Array.from( + new Set([...langPrefs.postLanguageHistory, langPrefs.postLanguage]), + ) + + if ( + dedupedHistory.length === 1 && + dedupedHistory[0] === langPrefs.postLanguage + ) { + return ( + <> + <LanguageBtn onPress={languageDialogControl.open} /> + <PostLanguageSelectDialog control={languageDialogControl} /> + </> + ) + } + + return ( + <> + <Menu.Root> + <Menu.Trigger label={_(msg`Select post language`)}> + {({props}) => <LanguageBtn {...props} />} + </Menu.Trigger> + <Menu.Outer> + <Menu.Group> + {dedupedHistory.map(historyItem => { + const langCodes = historyItem.split(',') + const langName = langCodes + .map(code => codeToLanguageName(code, langPrefs.appLanguage)) + .join(' + ') + return ( + <Menu.Item + key={historyItem} + label={_(msg`Select ${langName}`)} + onPress={() => setLangPrefs.setPostLanguage(historyItem)}> + <Menu.ItemText>{langName}</Menu.ItemText> + <Menu.ItemRadio + selected={historyItem === langPrefs.postLanguage} + /> + </Menu.Item> + ) + })} + </Menu.Group> + <Menu.Divider /> + <Menu.Item + label={_(msg`More languages...`)} + onPress={languageDialogControl.open}> + <Menu.ItemText> + <Trans>More languages...</Trans> + </Menu.ItemText> + <Menu.ItemIcon icon={ChevronRightIcon} /> + </Menu.Item> + </Menu.Outer> + </Menu.Root> + + <PostLanguageSelectDialog control={languageDialogControl} /> + </> + ) +} + +function LanguageBtn(props: Omit<ButtonProps, 'label' | 'children'>) { + const {_} = useLingui() + const langPrefs = useLanguagePrefs() + const t = useTheme() + + const postLanguagesPref = toPostLanguages(langPrefs.postLanguage) + + return ( + <Button + testID="selectLangBtn" + size="small" + hitSlop={LANG_DROPDOWN_HITSLOP} + label={_( + msg({ + message: `Post language selection`, + comment: `Accessibility label for button that opens dialog to choose post language settings`, + }), + )} + accessibilityHint={_(msg`Opens post language settings`)} + style={[a.mr_xs]} + {...props}> + {({pressed, hovered}) => { + const color = + pressed || hovered ? t.palette.primary_300 : t.palette.primary_500 + if (postLanguagesPref.length > 0) { + return ( + <Text + style={[ + {color}, + a.font_bold, + a.text_sm, + a.leading_snug, + {maxWidth: 100}, + ]} + numberOfLines={1}> + {postLanguagesPref + .map(lang => codeToLanguageName(lang, langPrefs.appLanguage)) + .join(', ')} + </Text> + ) + } else { + return <GlobeIcon size="xs" style={{color}} /> + } + }} + </Button> + ) +} diff --git a/src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx b/src/view/com/composer/select-language/PostLanguageSelectDialog.tsx index c8ecc2b89..1137415e6 100644 --- a/src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx +++ b/src/view/com/composer/select-language/PostLanguageSelectDialog.tsx @@ -1,16 +1,13 @@ import {useCallback, useMemo, useState} from 'react' -import {Keyboard, useWindowDimensions, View} from 'react-native' +import {useWindowDimensions, View} from 'react-native' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {LANG_DROPDOWN_HITSLOP} from '#/lib/constants' import {languageName} from '#/locale/helpers' -import {codeToLanguageName} from '#/locale/helpers' import {type Language, LANGUAGES, LANGUAGES_MAP_CODE2} from '#/locale/languages' import {isNative, isWeb} from '#/platform/detection' import { - toPostLanguages, useLanguagePrefs, useLanguagePrefsApi, } from '#/state/preferences/languages' @@ -21,75 +18,14 @@ import {Button, ButtonIcon, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import {SearchInput} from '#/components/forms/SearchInput' import * as Toggle from '#/components/forms/Toggle' -import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe' import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' import {Text} from '#/components/Typography' -export function SelectPostLanguagesBtn() { - const {_} = useLingui() - const langPrefs = useLanguagePrefs() - const t = useTheme() - const control = Dialog.useDialogControl() - - const onPressMore = useCallback(async () => { - if (isNative) { - if (Keyboard.isVisible()) { - Keyboard.dismiss() - } - } - control.open() - }, [control]) - - const postLanguagesPref = toPostLanguages(langPrefs.postLanguage) - - return ( - <> - <Button - testID="selectLangBtn" - onPress={onPressMore} - size="small" - hitSlop={LANG_DROPDOWN_HITSLOP} - label={_( - msg({ - message: `Post language selection`, - comment: `Accessibility label for button that opens dialog to choose post language settings`, - }), - )} - accessibilityHint={_(msg`Opens post language settings`)} - style={[a.mx_md]}> - {({pressed, hovered, focused}) => { - const color = - pressed || hovered || focused - ? t.palette.primary_300 - : t.palette.primary_500 - if (postLanguagesPref.length > 0) { - return ( - <Text - style={[ - {color}, - a.font_bold, - a.text_sm, - a.leading_snug, - {maxWidth: 100}, - ]} - numberOfLines={1}> - {postLanguagesPref - .map(lang => codeToLanguageName(lang, langPrefs.appLanguage)) - .join(', ')} - </Text> - ) - } else { - return <GlobeIcon size="xs" style={{color}} /> - } - }} - </Button> - - <LanguageDialog control={control} /> - </> - ) -} - -function LanguageDialog({control}: {control: Dialog.DialogControlProps}) { +export function PostLanguageSelectDialog({ + control, +}: { + control: Dialog.DialogControlProps +}) { const {height} = useWindowDimensions() const insets = useSafeAreaInsets() @@ -104,13 +40,13 @@ function LanguageDialog({control}: {control: Dialog.DialogControlProps}) { nativeOptions={{minHeight: height - insets.top}}> <Dialog.Handle /> <ErrorBoundary renderError={renderErrorBoundary}> - <PostLanguagesSettingsDialogInner /> + <DialogInner /> </ErrorBoundary> </Dialog.Outer> ) } -export function PostLanguagesSettingsDialogInner() { +export function DialogInner() { const control = Dialog.useDialogContext() const [headerHeight, setHeaderHeight] = useState(0) |