Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / components / hooks / useMyCountry.tsx
bloba43a27b49d7e822be4242d1be27d66b5a79f35a3
1 import { useEffect, useState } from 'react';
3 import { getSilentApi } from '@proton/shared/lib/api/helpers/customConfig';
4 import { getLocation } from '@proton/shared/lib/api/vpn';
5 import { singleCountryTimezoneDatabase } from '@proton/shared/lib/date/singleCountryTimezoneDatabase';
6 import { manualFindTimeZone } from '@proton/shared/lib/date/timezoneDatabase';
7 import { getNaiveCountryCode } from '@proton/shared/lib/i18n/helper';
8 import type { Api, MyLocationResponse } from '@proton/shared/lib/interfaces';
10 import useApi from './useApi';
12 const tryTimezone = (tz: string): string | undefined =>
13     singleCountryTimezoneDatabase[tz as keyof typeof singleCountryTimezoneDatabase];
15 const getCountryFromTimezone = () => {
16     try {
17         const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
19         if (timezone) {
20             return tryTimezone(timezone) || tryTimezone(manualFindTimeZone(timezone));
21         }
22     } catch (e) {
23         // undefined
24     }
27 export const getCountryFromLanguage = () => {
28     const language = navigator.languages.find((language) => /[_-]/.test(language));
29     if (language) {
30         return getNaiveCountryCode(language);
31     }
34 const getStaticState = () => {
35     return (getCountryFromTimezone() || getCountryFromLanguage())?.toUpperCase();
38 const getMyCountry = async (api: Api): Promise<string | undefined> => {
39     // TODO: Have a non-VPN dedicated API for that purpose
40     const value = await api<MyLocationResponse>(getLocation());
41     return value?.Country?.toUpperCase();
44 const state: { initialized: boolean; promise: null | Promise<string | undefined>; value: string | undefined } = {
45     promise: null,
46     value: undefined,
47     initialized: false,
50 const getInitialValue = () => {
51     if (!state.initialized) {
52         state.initialized = true;
53         state.value = getStaticState();
54     }
55     return state.value;
58 const getCountryPromise = (api: Api) => {
59     if (state.promise) {
60         return state.promise;
61     }
62     state.promise = getMyCountry(getSilentApi(api))
63         .then((value) => {
64             state.value = value;
65             return value;
66         })
67         .catch(() => {
68             return undefined;
69         });
70     return state.promise;
73 const useMyCountry = (): string | undefined => {
74     const [country, setMyCountry] = useState<string | undefined>(getInitialValue);
75     const api = useApi();
76     useEffect(() => {
77         if (country) {
78             return;
79         }
80         void getCountryPromise(api).then(setMyCountry);
81     }, []);
82     return country;
85 export default useMyCountry;