[Contacts] Contacts matching flow (#9486)

* 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>
This commit is contained in:
Samuel Newman
2025-12-12 20:32:06 +02:00
committed by GitHub
parent d3a6db4594
commit ad7d49ef8f
98 changed files with 4906 additions and 1079 deletions
+70 -50
View File
@@ -1,3 +1,14 @@
import {type CountryCode as LibPhoneNumberJsCountryCode} from 'libphonenumber-js'
// Exclude Ascension Island and Tristan da Cunha - merged into `SH` in 2009
export type CountryCode = Exclude<LibPhoneNumberJsCountryCode, 'AC' | 'TA'>
/**
* Note: data is from Wikipedia, but some have been removed to match `libphonenumber-js`
* Mostly tiny British overseas territories + Antarctica, all of which
* share codes with a larger country. If you've one of the 10 people from these
* places, you probably know what to do.
*/
export const INTERNATIONAL_TELEPHONE_CODES = {
AD: {
code: '+376',
@@ -34,11 +45,13 @@ export const INTERNATIONAL_TELEPHONE_CODES = {
unicodeFlag: '🇦🇴',
svgFlag: require('../../assets/icons/flags/AO.svg'),
},
AQ: {
code: '+672',
unicodeFlag: '🇦🇶',
svgFlag: require('../../assets/icons/flags/AQ.svg'),
},
// sorry penguins :(
// same as Norfolk Island
// AQ: {
// code: '+672',
// unicodeFlag: '🇦🇶',
// svgFlag: require('../../assets/icons/flags/AQ.svg'),
// },
AR: {
code: '+54',
unicodeFlag: '🇦🇷',
@@ -154,11 +167,12 @@ export const INTERNATIONAL_TELEPHONE_CODES = {
unicodeFlag: '🇧🇹',
svgFlag: require('../../assets/icons/flags/BT.svg'),
},
BV: {
code: '+47',
unicodeFlag: '🇧🇻',
svgFlag: require('../../assets/icons/flags/BV.svg'),
},
// same as Norway
// BV: {
// code: '+47',
// unicodeFlag: '🇧🇻',
// svgFlag: require('../../assets/icons/flags/BV.svg'),
// },
BW: {
code: '+267',
unicodeFlag: '🇧🇼',
@@ -379,11 +393,12 @@ export const INTERNATIONAL_TELEPHONE_CODES = {
unicodeFlag: '🇬🇷',
svgFlag: require('../../assets/icons/flags/GR.svg'),
},
GS: {
code: '+500',
unicodeFlag: '🇬🇸',
svgFlag: require('../../assets/icons/flags/GS.svg'),
},
// same as Falkland Islands
// GS: {
// code: '+500',
// unicodeFlag: '🇬🇸',
// svgFlag: require('../../assets/icons/flags/GS.svg'),
// },
GT: {
code: '+502',
unicodeFlag: '🇬🇹',
@@ -779,11 +794,12 @@ export const INTERNATIONAL_TELEPHONE_CODES = {
unicodeFlag: '🇵🇲',
svgFlag: require('../../assets/icons/flags/PM.svg'),
},
PN: {
code: '+64',
unicodeFlag: '🇵🇳',
svgFlag: require('../../assets/icons/flags/PN.svg'),
},
// same as New Zealand
// PN: {
// code: '+64',
// unicodeFlag: '🇵🇳',
// svgFlag: require('../../assets/icons/flags/PN.svg'),
// },
PR: {
code: '+1',
unicodeFlag: '🇵🇷',
@@ -1199,11 +1215,12 @@ export const INTERNATIONAL_TELEPHONE_CODES = {
unicodeFlag: '🇫🇴',
svgFlag: require('../../assets/icons/flags/FO.svg'),
},
HM: {
code: '+672',
unicodeFlag: '🇭🇲',
svgFlag: require('../../assets/icons/flags/HM.svg'),
},
// same as Norfolk Island
// HM: {
// code: '+672',
// unicodeFlag: '🇭🇲',
// svgFlag: require('../../assets/icons/flags/HM.svg'),
// },
KM: {
code: '+269',
unicodeFlag: '🇰🇲',
@@ -1229,16 +1246,18 @@ export const INTERNATIONAL_TELEPHONE_CODES = {
unicodeFlag: '🇹🇨',
svgFlag: require('../../assets/icons/flags/TC.svg'),
},
TF: {
code: '+672',
unicodeFlag: '🇹🇫',
svgFlag: require('../../assets/icons/flags/TF.svg'),
},
UM: {
code: '+1',
unicodeFlag: '🇺🇲',
svgFlag: require('../../assets/icons/flags/UM.svg'),
},
// same as Norfolk Island
// TF: {
// code: '+672',
// unicodeFlag: '🇹🇫',
// svgFlag: require('../../assets/icons/flags/TF.svg'),
// },
// same as US mainland
// UM: {
// code: '+1',
// unicodeFlag: '🇺🇲',
// svgFlag: require('../../assets/icons/flags/UM.svg'),
// },
VA: {
code: '+39',
unicodeFlag: '🇻🇦',
@@ -1249,25 +1268,26 @@ export const INTERNATIONAL_TELEPHONE_CODES = {
unicodeFlag: '🇽🇰',
svgFlag: require('../../assets/icons/flags/XK.svg'),
},
}
} satisfies Record<
CountryCode,
{
code: string
unicodeFlag: string
svgFlag: any
}
>
const DEFAULT_PHONE_COUNTRY = 'US'
const DEFAULT_PHONE_COUNTRY = 'US' as const
export function getDefaultCountry(location?: {countryCode?: string}) {
export function getDefaultCountry(location?: {
countryCode?: string
}): CountryCode {
const locationCountryCode = location?.countryCode?.toUpperCase()
if (
location?.countryCode &&
location.countryCode.toUpperCase() in INTERNATIONAL_TELEPHONE_CODES
locationCountryCode &&
locationCountryCode in INTERNATIONAL_TELEPHONE_CODES
) {
return location.countryCode.toUpperCase()
return locationCountryCode as CountryCode
}
return DEFAULT_PHONE_COUNTRY
}
export function getPhoneCodeFromCountryCode(countryCode: string) {
const country =
INTERNATIONAL_TELEPHONE_CODES[
countryCode.toUpperCase() as keyof typeof INTERNATIONAL_TELEPHONE_CODES
]
if (!country) throw new Error(`Country ${countryCode} not found`)
return country.code
}