forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {type LocationGeocodedAddress} from 'expo-location'
2
3import {IS_ANDROID} from '#/env'
4import {logger} from '#/geolocation/logger'
5import {type Geolocation} from '#/geolocation/types'
6
7/**
8 * Maps full US region names to their short codes.
9 *
10 * Context: in some cases, like on Android, we get the full region name instead
11 * of the short code. We may need to expand this in the future to other
12 * countries, hence the prefix.
13 */
14export const USRegionNameToRegionCode: {
15 [regionName: string]: string
16} = {
17 Alabama: 'AL',
18 Alaska: 'AK',
19 Arizona: 'AZ',
20 Arkansas: 'AR',
21 California: 'CA',
22 Colorado: 'CO',
23 Connecticut: 'CT',
24 Delaware: 'DE',
25 Florida: 'FL',
26 Georgia: 'GA',
27 Hawaii: 'HI',
28 Idaho: 'ID',
29 Illinois: 'IL',
30 Indiana: 'IN',
31 Iowa: 'IA',
32 Kansas: 'KS',
33 Kentucky: 'KY',
34 Louisiana: 'LA',
35 Maine: 'ME',
36 Maryland: 'MD',
37 Massachusetts: 'MA',
38 Michigan: 'MI',
39 Minnesota: 'MN',
40 Mississippi: 'MS',
41 Missouri: 'MO',
42 Montana: 'MT',
43 Nebraska: 'NE',
44 Nevada: 'NV',
45 ['New Hampshire']: 'NH',
46 ['New Jersey']: 'NJ',
47 ['New Mexico']: 'NM',
48 ['New York']: 'NY',
49 ['North Carolina']: 'NC',
50 ['North Dakota']: 'ND',
51 Ohio: 'OH',
52 Oklahoma: 'OK',
53 Oregon: 'OR',
54 Pennsylvania: 'PA',
55 ['Rhode Island']: 'RI',
56 ['South Carolina']: 'SC',
57 ['South Dakota']: 'SD',
58 Tennessee: 'TN',
59 Texas: 'TX',
60 Utah: 'UT',
61 Vermont: 'VT',
62 Virginia: 'VA',
63 Washington: 'WA',
64 ['West Virginia']: 'WV',
65 Wisconsin: 'WI',
66 Wyoming: 'WY',
67}
68
69/**
70 * Normalizes a `LocationGeocodedAddress` into a `Geolocation`.
71 *
72 * We don't want or care about the full location data, so we trim it down and
73 * normalize certain fields, like region, into the format we need.
74 */
75export function normalizeDeviceLocation(
76 location: LocationGeocodedAddress,
77): Geolocation {
78 let {isoCountryCode, region} = location
79 let regionCode: string | undefined = region ?? undefined
80
81 /*
82 * Android doesn't give us ISO 3166-2 short codes. We need these for US
83 */
84 if (IS_ANDROID) {
85 if (region && isoCountryCode === 'US') {
86 /*
87 * We need short codes for US states. If we can't remap it, just drop it
88 * entirely for now.
89 */
90 regionCode = USRegionNameToRegionCode[region] ?? undefined
91 } else {
92 /*
93 * Outside the US, we don't need regionCodes for now, so just drop it.
94 */
95 regionCode = undefined
96 }
97 }
98
99 return {
100 countryCode: isoCountryCode ?? undefined,
101 regionCode,
102 }
103}
104
105/**
106 * Combines precise location data with the geolocation config fetched from the
107 * IP service, with preference to the precise data.
108 */
109export function mergeGeolocations(
110 device?: Geolocation,
111 geolocationService?: Geolocation,
112): Geolocation {
113 let geolocation: Geolocation = {
114 countryCode: geolocationService?.countryCode ?? undefined,
115 regionCode: geolocationService?.regionCode ?? undefined,
116 }
117 // prefer GPS
118 if (device?.countryCode) {
119 geolocation = device
120 }
121 logger.debug('merged geolocation data', {
122 device,
123 service: geolocationService,
124 merged: geolocation,
125 })
126 return geolocation
127}