feat: don't retain accepted language suggestion after finishing or exiting post (#8886)
* feat: don't retain accepted language suggestion after finishing or exiting post * fix: rebase fixes * fix: rebase fixes * chore: lint
This commit is contained in:
committed by
Eric Bailey
parent
6d85fe05d1
commit
c6768452fb
@@ -71,7 +71,7 @@ const schema = z.object({
|
||||
contentLanguages: z.array(z.string()),
|
||||
/**
|
||||
* The language(s) the user is currently posting in, configured within the
|
||||
* composer. Multiple languages are psearate by commas.
|
||||
* composer. Multiple languages are separated by commas.
|
||||
*
|
||||
* BCP-47 2-letter language code without region.
|
||||
*/
|
||||
|
||||
@@ -156,6 +156,10 @@ export function toPostLanguages(postLanguage: string): string[] {
|
||||
return postLanguage.split(',').filter(Boolean)
|
||||
}
|
||||
|
||||
export function fromPostLanguages(languages: string[]): string {
|
||||
return languages.filter(Boolean).join(',')
|
||||
}
|
||||
|
||||
export function hasPostLanguage(postLanguage: string, code2: string): boolean {
|
||||
return toPostLanguages(postLanguage).includes(code2)
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ import {
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {useRequireAltTextEnabled} from '#/state/preferences'
|
||||
import {
|
||||
fromPostLanguages,
|
||||
toPostLanguages,
|
||||
useLanguagePrefs,
|
||||
useLanguagePrefsApi,
|
||||
@@ -196,6 +197,25 @@ export const ComposePost = ({
|
||||
const [isPublishing, setIsPublishing] = useState(false)
|
||||
const [publishingStage, setPublishingStage] = useState('')
|
||||
const [error, setError] = useState('')
|
||||
const [acceptedLanguageSuggestion, setAcceptedLanguageSuggestion] = useState<
|
||||
string | null
|
||||
>(null)
|
||||
|
||||
// NOTE(@elijaharita): if a temporary language suggestion has been accepted,
|
||||
// show that as the post language instead of the one from langPrefs.
|
||||
const currentLanguages = useMemo(
|
||||
() =>
|
||||
acceptedLanguageSuggestion
|
||||
? [acceptedLanguageSuggestion]
|
||||
: toPostLanguages(langPrefs.postLanguage),
|
||||
[acceptedLanguageSuggestion, langPrefs.postLanguage],
|
||||
)
|
||||
|
||||
// This effect clears the temporary language suggestion if the post language
|
||||
// is manually changed, so the user doesn't get stuck with the suggestion.
|
||||
useEffect(() => {
|
||||
setAcceptedLanguageSuggestion(null)
|
||||
}, [langPrefs.postLanguage])
|
||||
|
||||
const [composerState, composerDispatch] = useReducer(
|
||||
composerReducer,
|
||||
@@ -414,7 +434,7 @@ export const ComposePost = ({
|
||||
thread,
|
||||
replyTo: replyTo?.uri,
|
||||
onStateChange: setPublishingStage,
|
||||
langs: toPostLanguages(langPrefs.postLanguage),
|
||||
langs: currentLanguages,
|
||||
})
|
||||
).uris[0]
|
||||
|
||||
@@ -490,7 +510,7 @@ export const ComposePost = ({
|
||||
isPartOfThread: thread.posts.length > 1,
|
||||
hasLink: !!post.embed.link,
|
||||
hasQuote: !!post.embed.quote,
|
||||
langs: langPrefs.postLanguage,
|
||||
langs: fromPostLanguages(currentLanguages),
|
||||
logContext: 'Composer',
|
||||
})
|
||||
index++
|
||||
@@ -557,7 +577,7 @@ export const ComposePost = ({
|
||||
thread,
|
||||
canPost,
|
||||
isPublishing,
|
||||
langPrefs.postLanguage,
|
||||
currentLanguages,
|
||||
onClose,
|
||||
onPost,
|
||||
onPostSuccess,
|
||||
@@ -656,6 +676,8 @@ export const ComposePost = ({
|
||||
text={activePost.richtext.text}
|
||||
// NOTE(@elijaharita): currently just choosing the first language if any exists
|
||||
replyToLanguage={replyTo?.langs?.[0]}
|
||||
currentLanguages={currentLanguages}
|
||||
onChange={setAcceptedLanguageSuggestion}
|
||||
/>
|
||||
<ComposerPills
|
||||
isReply={!!replyTo}
|
||||
@@ -678,6 +700,7 @@ export const ComposePost = ({
|
||||
type: 'add_post',
|
||||
})
|
||||
}}
|
||||
currentLanguages={currentLanguages}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
@@ -1289,6 +1312,7 @@ function ComposerFooter({
|
||||
onEmojiButtonPress,
|
||||
onSelectVideo,
|
||||
onAddPost,
|
||||
currentLanguages,
|
||||
}: {
|
||||
post: PostDraft
|
||||
dispatch: (action: PostAction) => void
|
||||
@@ -1297,6 +1321,7 @@ function ComposerFooter({
|
||||
onError: (error: string) => void
|
||||
onSelectVideo: (postId: string, asset: ImagePickerAsset) => void
|
||||
onAddPost: () => void
|
||||
currentLanguages: string[]
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
@@ -1450,7 +1475,7 @@ function ComposerFooter({
|
||||
<PlusIcon size="lg" />
|
||||
</Button>
|
||||
)}
|
||||
<PostLanguageSelect />
|
||||
<PostLanguageSelect currentLanguages={currentLanguages} />
|
||||
<CharProgress
|
||||
count={post.shortenedGraphemeLength}
|
||||
style={{width: 65}}
|
||||
|
||||
@@ -17,7 +17,11 @@ import * as Menu from '#/components/Menu'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {PostLanguageSelectDialog} from './PostLanguageSelectDialog'
|
||||
|
||||
export function PostLanguageSelect() {
|
||||
export function PostLanguageSelect({
|
||||
currentLanguages: currentLanguagesProp,
|
||||
}: {
|
||||
currentLanguages?: string[]
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const setLangPrefs = useLanguagePrefsApi()
|
||||
@@ -27,6 +31,9 @@ export function PostLanguageSelect() {
|
||||
new Set([...langPrefs.postLanguageHistory, langPrefs.postLanguage]),
|
||||
)
|
||||
|
||||
const currentLanguages =
|
||||
currentLanguagesProp ?? toPostLanguages(langPrefs.postLanguage)
|
||||
|
||||
if (
|
||||
dedupedHistory.length === 1 &&
|
||||
dedupedHistory[0] === langPrefs.postLanguage
|
||||
@@ -34,7 +41,10 @@ export function PostLanguageSelect() {
|
||||
return (
|
||||
<>
|
||||
<LanguageBtn onPress={languageDialogControl.open} />
|
||||
<PostLanguageSelectDialog control={languageDialogControl} />
|
||||
<PostLanguageSelectDialog
|
||||
control={languageDialogControl}
|
||||
currentLanguages={currentLanguages}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -43,7 +53,9 @@ export function PostLanguageSelect() {
|
||||
<>
|
||||
<Menu.Root>
|
||||
<Menu.Trigger label={_(msg`Select post language`)}>
|
||||
{({props}) => <LanguageBtn {...props} />}
|
||||
{({props}) => (
|
||||
<LanguageBtn currentLanguages={currentLanguages} {...props} />
|
||||
)}
|
||||
</Menu.Trigger>
|
||||
<Menu.Outer>
|
||||
<Menu.Group>
|
||||
@@ -59,7 +71,7 @@ export function PostLanguageSelect() {
|
||||
onPress={() => setLangPrefs.setPostLanguage(historyItem)}>
|
||||
<Menu.ItemText>{langName}</Menu.ItemText>
|
||||
<Menu.ItemRadio
|
||||
selected={historyItem === langPrefs.postLanguage}
|
||||
selected={currentLanguages.includes(historyItem)}
|
||||
/>
|
||||
</Menu.Item>
|
||||
)
|
||||
@@ -77,17 +89,25 @@ export function PostLanguageSelect() {
|
||||
</Menu.Outer>
|
||||
</Menu.Root>
|
||||
|
||||
<PostLanguageSelectDialog control={languageDialogControl} />
|
||||
<PostLanguageSelectDialog
|
||||
control={languageDialogControl}
|
||||
currentLanguages={currentLanguages}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function LanguageBtn(props: Omit<ButtonProps, 'label' | 'children'>) {
|
||||
function LanguageBtn(
|
||||
props: Omit<ButtonProps, 'label' | 'children'> & {
|
||||
currentLanguages?: string[]
|
||||
},
|
||||
) {
|
||||
const {_} = useLingui()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const t = useTheme()
|
||||
|
||||
const postLanguagesPref = toPostLanguages(langPrefs.postLanguage)
|
||||
const currentLanguages = props.currentLanguages ?? postLanguagesPref
|
||||
|
||||
return (
|
||||
<Button
|
||||
@@ -106,7 +126,7 @@ function LanguageBtn(props: Omit<ButtonProps, 'label' | 'children'>) {
|
||||
{({pressed, hovered}) => {
|
||||
const color =
|
||||
pressed || hovered ? t.palette.primary_300 : t.palette.primary_500
|
||||
if (postLanguagesPref.length > 0) {
|
||||
if (currentLanguages.length > 0) {
|
||||
return (
|
||||
<Text
|
||||
style={[
|
||||
@@ -117,7 +137,7 @@ function LanguageBtn(props: Omit<ButtonProps, 'label' | 'children'>) {
|
||||
{maxWidth: 100},
|
||||
]}
|
||||
numberOfLines={1}>
|
||||
{postLanguagesPref
|
||||
{currentLanguages
|
||||
.map(lang => codeToLanguageName(lang, langPrefs.appLanguage))
|
||||
.join(', ')}
|
||||
</Text>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {languageName} 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'
|
||||
@@ -22,8 +23,12 @@ import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Ti
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function PostLanguageSelectDialog({
|
||||
/** Optionally can be passed to show different values than what is saved in
|
||||
* langPrefs. */
|
||||
currentLanguages,
|
||||
control,
|
||||
}: {
|
||||
currentLanguages?: string[]
|
||||
control: Dialog.DialogControlProps
|
||||
}) {
|
||||
const {height} = useWindowDimensions()
|
||||
@@ -40,13 +45,13 @@ export function PostLanguageSelectDialog({
|
||||
nativeOptions={{minHeight: height - insets.top}}>
|
||||
<Dialog.Handle />
|
||||
<ErrorBoundary renderError={renderErrorBoundary}>
|
||||
<DialogInner />
|
||||
<DialogInner currentLanguages={currentLanguages} />
|
||||
</ErrorBoundary>
|
||||
</Dialog.Outer>
|
||||
)
|
||||
}
|
||||
|
||||
export function DialogInner() {
|
||||
export function DialogInner({currentLanguages}: {currentLanguages?: string[]}) {
|
||||
const control = Dialog.useDialogContext()
|
||||
const [headerHeight, setHeaderHeight] = useState(0)
|
||||
|
||||
@@ -63,8 +68,11 @@ export function DialogInner() {
|
||||
}, [])
|
||||
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const postLanguagesPref =
|
||||
currentLanguages ?? toPostLanguages(langPrefs.postLanguage)
|
||||
|
||||
const [checkedLanguagesCode2, setCheckedLanguagesCode2] = useState<string[]>(
|
||||
langPrefs.postLanguage.split(',') || [langPrefs.primaryLanguage],
|
||||
postLanguagesPref || [langPrefs.primaryLanguage],
|
||||
)
|
||||
const [search, setSearch] = useState('')
|
||||
|
||||
|
||||
@@ -6,11 +6,7 @@ import {useLingui} from '@lingui/react'
|
||||
import lande from 'lande'
|
||||
|
||||
import {code3ToCode2Strict, codeToLanguageName} from '#/locale/helpers'
|
||||
import {
|
||||
toPostLanguages,
|
||||
useLanguagePrefs,
|
||||
useLanguagePrefsApi,
|
||||
} from '#/state/preferences/languages'
|
||||
import {useLanguagePrefs} from '#/state/preferences/languages'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import {Earth_Stroke2_Corner2_Rounded as EarthIcon} from '#/components/icons/Globe'
|
||||
@@ -23,16 +19,19 @@ const cancelIdle = globalThis.cancelIdleCallback || clearTimeout
|
||||
export function SuggestedLanguage({
|
||||
text,
|
||||
replyToLanguage: replyToLanguageProp,
|
||||
currentLanguages,
|
||||
onChange,
|
||||
}: {
|
||||
text: string
|
||||
replyToLanguage?: string
|
||||
currentLanguages: string[]
|
||||
onChange: (language: string | null) => void
|
||||
}) {
|
||||
const replyToLanguage = cleanUpLanguage(replyToLanguageProp)
|
||||
const [suggestedLanguage, setSuggestedLanguage] = useState<
|
||||
string | undefined
|
||||
>(text.length === 0 ? replyToLanguage : undefined)
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const setLangPrefs = useLanguagePrefsApi()
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
|
||||
@@ -60,10 +59,7 @@ export function SuggestedLanguage({
|
||||
return () => cancelIdle(idle)
|
||||
}, [text, replyToLanguage])
|
||||
|
||||
if (
|
||||
suggestedLanguage &&
|
||||
!toPostLanguages(langPrefs.postLanguage).includes(suggestedLanguage)
|
||||
) {
|
||||
if (suggestedLanguage && !currentLanguages.includes(suggestedLanguage)) {
|
||||
const suggestedLanguageName = codeToLanguageName(
|
||||
suggestedLanguage,
|
||||
langPrefs.appLanguage,
|
||||
@@ -96,7 +92,7 @@ export function SuggestedLanguage({
|
||||
color="secondary"
|
||||
size="small"
|
||||
variant="solid"
|
||||
onPress={() => setLangPrefs.setPostLanguage(suggestedLanguage)}
|
||||
onPress={() => onChange(suggestedLanguage)}
|
||||
label={_(msg`Change post language to ${suggestedLanguageName}`)}>
|
||||
<ButtonText>
|
||||
<Trans>Yes</Trans>
|
||||
|
||||
Reference in New Issue
Block a user