forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {msg} from '@lingui/core/macro'
2import {useLingui} from '@lingui/react'
3import {Trans} from '@lingui/react/macro'
4
5import {LANG_DROPDOWN_HITSLOP} from '#/lib/constants'
6import {codeToLanguageName} from '#/locale/helpers'
7import {
8 toPostLanguages,
9 useLanguagePrefs,
10 useLanguagePrefsApi,
11} from '#/state/preferences/languages'
12import {atoms as a, useTheme} from '#/alf'
13import {Button, type ButtonProps} from '#/components/Button'
14import * as Dialog from '#/components/Dialog'
15import {LanguageSelectDialog} from '#/components/dialogs/LanguageSelectDialog'
16import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
17import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe'
18import * as Menu from '#/components/Menu'
19import {Text} from '#/components/Typography'
20
21export function PostLanguageSelect({
22 currentLanguages: currentLanguagesProp,
23 onSelectLanguage,
24}: {
25 currentLanguages?: string[]
26 onSelectLanguage?: (language: string) => void
27}) {
28 const {_} = useLingui()
29 const langPrefs = useLanguagePrefs()
30 const setLangPrefs = useLanguagePrefsApi()
31 const languageDialogControl = Dialog.useDialogControl()
32
33 const dedupedHistory = Array.from(
34 new Set([...langPrefs.postLanguageHistory, langPrefs.postLanguage]),
35 )
36
37 const currentLanguages =
38 currentLanguagesProp ?? toPostLanguages(langPrefs.postLanguage)
39
40 const onSelectLanguages = (languages: string[]) => {
41 let langsString = languages.join(',')
42 if (!langsString) {
43 langsString = langPrefs.primaryLanguage
44 }
45 setLangPrefs.setPostLanguage(langsString)
46 onSelectLanguage?.(langsString)
47 }
48
49 if (
50 dedupedHistory.length === 1 &&
51 dedupedHistory[0] === langPrefs.postLanguage
52 ) {
53 return (
54 <>
55 <LanguageBtn onPress={languageDialogControl.open} />
56 <LanguageSelectDialog
57 titleText={<Trans>Choose post languages</Trans>}
58 subtitleText={
59 <Trans>Select up to 3 languages used in this post</Trans>
60 }
61 control={languageDialogControl}
62 currentLanguages={currentLanguages}
63 onSelectLanguages={onSelectLanguages}
64 maxLanguages={3}
65 />
66 </>
67 )
68 }
69
70 return (
71 <>
72 <Menu.Root>
73 <Menu.Trigger label={_(msg`Select post language`)}>
74 {({props}) => (
75 <LanguageBtn currentLanguages={currentLanguages} {...props} />
76 )}
77 </Menu.Trigger>
78 <Menu.Outer>
79 <Menu.Group>
80 {dedupedHistory.map(historyItem => {
81 const langCodes = historyItem.split(',')
82 const langName = langCodes
83 .map(code => codeToLanguageName(code, langPrefs.appLanguage))
84 .join(' + ')
85 return (
86 <Menu.Item
87 key={historyItem}
88 label={_(msg`Select ${langName}`)}
89 onPress={() => {
90 setLangPrefs.setPostLanguage(historyItem)
91 onSelectLanguage?.(historyItem)
92 }}>
93 <Menu.ItemText>{langName}</Menu.ItemText>
94 <Menu.ItemRadio
95 selected={currentLanguages.includes(historyItem)}
96 />
97 </Menu.Item>
98 )
99 })}
100 </Menu.Group>
101 <Menu.Divider />
102 <Menu.Item
103 label={_(msg`More languages...`)}
104 onPress={languageDialogControl.open}>
105 <Menu.ItemText>
106 <Trans>More languages...</Trans>
107 </Menu.ItemText>
108 <Menu.ItemIcon icon={ChevronRightIcon} />
109 </Menu.Item>
110 </Menu.Outer>
111 </Menu.Root>
112
113 <LanguageSelectDialog
114 titleText={<Trans>Choose post languages</Trans>}
115 subtitleText={<Trans>Select up to 3 languages used in this post</Trans>}
116 control={languageDialogControl}
117 currentLanguages={currentLanguages}
118 onSelectLanguages={onSelectLanguages}
119 maxLanguages={3}
120 />
121 </>
122 )
123}
124
125function LanguageBtn(
126 props: Omit<ButtonProps, 'label' | 'children'> & {
127 currentLanguages?: string[]
128 },
129) {
130 const {_} = useLingui()
131 const langPrefs = useLanguagePrefs()
132 const t = useTheme()
133
134 const postLanguagesPref = toPostLanguages(langPrefs.postLanguage)
135 const currentLanguages = props.currentLanguages ?? postLanguagesPref
136
137 return (
138 <Button
139 testID="selectLangBtn"
140 size="small"
141 hitSlop={LANG_DROPDOWN_HITSLOP}
142 label={_(
143 msg({
144 message: `Post language selection`,
145 comment: `Accessibility label for button that opens dialog to choose post language settings`,
146 }),
147 )}
148 accessibilityHint={_(msg`Opens post language settings`)}
149 style={[a.mr_xs]}
150 {...props}>
151 {({pressed, hovered}) => {
152 const color =
153 pressed || hovered ? t.palette.primary_300 : t.palette.primary_500
154 if (currentLanguages.length > 0) {
155 return (
156 <Text
157 style={[
158 {color},
159 a.font_semi_bold,
160 a.text_sm,
161 a.leading_snug,
162 {maxWidth: 100},
163 ]}
164 numberOfLines={1}>
165 {currentLanguages
166 .map(lang => codeToLanguageName(lang, langPrefs.appLanguage))
167 .join(', ')}
168 </Text>
169 )
170 } else {
171 return <GlobeIcon size="xs" style={{color}} />
172 }
173 }}
174 </Button>
175 )
176}