ad7d49ef8f
* add expo-contacts * add expo-sms * update copy * add basic settings screen * state machine, flow screen * phone input screen * otp screen * tweak spacing * resend code logic * add layoutanimationconfig * check availablility in settings screen * get contacts * matches screen * search, temp setup for matches UI * add a bunch of number parsing logic with libphonenumber * cast to looser type * rename sync to find FCF (Find Contacts Flow) * update geolocation hook * nicer design for settings screen * add completed state * up border contrast * update expo deps * add pending spinner * add country whitelist * add empty state screen * drop add more functionality * upload -> import * fix typo * fix permission string * copy updates * rm envelope icon * update sms copy * add inviteinfo component * woke is back * [Contacts] NUXes (#9515) * add a bunch of number parsing logic with libphonenumber * add banner nux * add announcement nux * native only nux * rm shitty animation * move isNative check * [Contacts] Onboarding step (#9489) * add a bunch of number parsing logic with libphonenumber * restructure onboarding to better support dynamic screens * integrate existing flow into onboarding * add intro step * lift state up to allow going back freely * gate onboarding by geo if unsupported country * add done button to standalone flow * [Contacts] Add `contact-match` notification type to feed (#9519) * add a bunch of number parsing logic with libphonenumber * add contact-joined notif type * update string, api package * Update NotificationFeedItem.tsx * Update NotificationFeedItem.tsx * Delete SyncContactsFlow.web.tsx * fix follow back btn for this case * [Contacts] API integration (#9487) * api integration for flow * copy tweak * tweaks after running it * wire up status page * rename toast * use api lib * rm temp code * maybe fix otp error * clear code on error/resend * add 1s delay to verify success * update package versions * Delete SyncContactsFlow.web.tsx * try and fix yarn.lock lint * even woker * fix uppercase friends * surfdude feedback Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * rm log * allow resend on invalid code * Update GetContacts.tsx * overwrite country code if possible * fix Apple's Best Feature * devenv latest * disable bounces * interactive keyboard dismiss * copy changes * national format * allow resending immediately * move success state down a bit * Update FindContactsSettings.tsx * [Contacts] More onboarding changes (#9491) * integrate existing flow into onboarding * refreshed onboarding styles, rm stepper * center content on web * Add back dismiss button for internal onboarding * Import sort --------- Co-authored-by: Eric Bailey <git@esb.lol> * add matches query to shadow * add clockwise arrow * update status design, fix dismiss, fix queries * add metrics * add more comments * Update metrics.ts * refetch both queries on PTR * fix shadow state in matches page * reduce empty space at bottom * show contact info on matches * filter out contacts without numbers at an earlier stage * Error handling ✨ * get notifs working * filter out businesses * rm log * remove TODO from learn more links * try and exclude from web bundle --------- Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> Co-authored-by: Eric Bailey <git@esb.lol>
118 lines
3.2 KiB
TypeScript
118 lines
3.2 KiB
TypeScript
import {Fragment, useMemo} from 'react'
|
|
import {Image} from 'expo-image'
|
|
import {msg} from '@lingui/macro'
|
|
import {useLingui} from '@lingui/react'
|
|
|
|
import {
|
|
type CountryCode,
|
|
getDefaultCountry,
|
|
INTERNATIONAL_TELEPHONE_CODES,
|
|
} from '#/lib/international-telephone-codes'
|
|
import {regionName} from '#/locale/helpers'
|
|
import {isWeb} from '#/platform/detection'
|
|
import {atoms as a, web} from '#/alf'
|
|
import * as Select from '#/components/Select'
|
|
import {useGeolocation} from '#/geolocation'
|
|
|
|
/**
|
|
* Country picker for a phone number input
|
|
*
|
|
* Pro tip: you can use `location?.countryCode` from `useGeolocationStatus()`
|
|
* to set a default value.
|
|
*/
|
|
export function InternationalPhoneCodeSelect({
|
|
value,
|
|
onChange,
|
|
}: {
|
|
value?: CountryCode
|
|
onChange: (value: CountryCode) => void
|
|
}) {
|
|
const {_, i18n} = useLingui()
|
|
const location = useGeolocation()
|
|
|
|
const defaultCountry = useMemo(() => {
|
|
return getDefaultCountry(location)
|
|
}, [location])
|
|
|
|
const items = useMemo(() => {
|
|
return (
|
|
Object.entries(INTERNATIONAL_TELEPHONE_CODES)
|
|
.map(([value, {code, unicodeFlag, svgFlag}]) => {
|
|
const name = regionName(value, i18n.locale)
|
|
|
|
return {
|
|
value,
|
|
name,
|
|
code,
|
|
label: `${name} ${code}`,
|
|
unicodeFlag,
|
|
svgFlag,
|
|
}
|
|
})
|
|
// boost the default value to the top, then sort by name
|
|
.sort((a, b) => {
|
|
if (a.value === defaultCountry) return -1
|
|
if (b.value === defaultCountry) return 1
|
|
return a.name.localeCompare(b.name)
|
|
})
|
|
)
|
|
}, [i18n.locale, defaultCountry])
|
|
|
|
const selected = useMemo(() => {
|
|
return items.find(item => item.value === value)
|
|
}, [value, items])
|
|
|
|
return (
|
|
<Select.Root value={value} onValueChange={onChange as (v: string) => void}>
|
|
<Select.Trigger label={_(msg`Select telephone code`)}>
|
|
<Select.ValueText placeholder="+..." webOverrideValue={selected}>
|
|
{selected => (
|
|
<>
|
|
<Flag {...selected} />
|
|
{selected.code}
|
|
</>
|
|
)}
|
|
</Select.ValueText>
|
|
<Select.Icon />
|
|
</Select.Trigger>
|
|
<Select.Content
|
|
label={_(msg`Country code`)}
|
|
items={items}
|
|
renderItem={item => (
|
|
<Fragment key={item.value}>
|
|
<Select.Item value={item.value} label={item.label}>
|
|
<Select.ItemIndicator />
|
|
<Select.ItemText style={[a.flex_1]} emoji>
|
|
{isWeb ? <Flag {...item} /> : item.unicodeFlag + ' '}
|
|
{item.name}
|
|
</Select.ItemText>
|
|
<Select.ItemText style={[a.text_right]}>
|
|
{' '}
|
|
{item.code}
|
|
</Select.ItemText>
|
|
</Select.Item>
|
|
{item.value === defaultCountry && <Select.Separator />}
|
|
</Fragment>
|
|
)}
|
|
/>
|
|
</Select.Root>
|
|
)
|
|
}
|
|
|
|
function Flag({unicodeFlag, svgFlag}: {unicodeFlag: string; svgFlag: any}) {
|
|
if (isWeb) {
|
|
return (
|
|
<Image
|
|
source={svgFlag}
|
|
style={[
|
|
a.rounded_2xs,
|
|
{height: 13, aspectRatio: 4 / 3, marginRight: 6},
|
|
web({verticalAlign: 'bottom'}),
|
|
]}
|
|
accessibilityIgnoresInvertColors
|
|
/>
|
|
)
|
|
}
|
|
return unicodeFlag + ' '
|
|
}
|