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