diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts
index f840081f3d..11204f3090 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 20f2549add..61715a988a 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({
})
}
}}>
-
+
-
+
) : null}
@@ -1440,20 +1441,16 @@ function ComposerFooter({
{showAddButton && (
)}
-
+
-
+
{error}
@@ -1765,7 +1762,7 @@ function ErrorBanner({
shape="round"
style={[a.absolute, {top: 0, right: 0}]}
onPress={onClearError}>
-
+
{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 0000000000..6291e84224
--- /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 (
+ <>
+
+
+ >
+ )
+ }
+
+ return (
+ <>
+
+
+ {({props}) => }
+
+
+
+ {dedupedHistory.map(historyItem => {
+ const langCodes = historyItem.split(',')
+ const langName = langCodes
+ .map(code => codeToLanguageName(code, langPrefs.appLanguage))
+ .join(' + ')
+ return (
+ setLangPrefs.setPostLanguage(historyItem)}>
+ {langName}
+
+
+ )
+ })}
+
+
+
+
+ More languages...
+
+
+
+
+
+
+
+ >
+ )
+}
+
+function LanguageBtn(props: Omit) {
+ const {_} = useLingui()
+ const langPrefs = useLanguagePrefs()
+ const t = useTheme()
+
+ const postLanguagesPref = toPostLanguages(langPrefs.postLanguage)
+
+ return (
+
+ )
+}
diff --git a/src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx b/src/view/com/composer/select-language/PostLanguageSelectDialog.tsx
similarity index 81%
rename from src/view/com/composer/select-language/SelectPostLanguagesDialog.tsx
rename to src/view/com/composer/select-language/PostLanguageSelectDialog.tsx
index c8ecc2b89b..1137415e63 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 (
- <>
-
-
-
- >
- )
-}
-
-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}}>
-
+
)
}
-export function PostLanguagesSettingsDialogInner() {
+export function DialogInner() {
const control = Dialog.useDialogContext()
const [headerHeight, setHeaderHeight] = useState(0)