forked from PolkaGate/extension
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: separate all the context into a individual file (PolkaGate#…
- Loading branch information
1 parent
47cd15a
commit db877b9
Showing
20 changed files
with
608 additions
and
300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
packages/extension-ui/src/Popup/contexts/AccountAssetProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import type { SavedAssets } from '@polkadot/extension-polkagate/hooks/useAssetsBalances'; | ||
|
||
import React, { useContext, useEffect, useState } from 'react'; | ||
|
||
import { AccountContext, AccountsAssetsContext, AlertContext, GenesisHashOptionsContext, UserAddedChainContext, WorkerContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
import { setStorage } from '@polkadot/extension-polkagate/src/components/Loading'; | ||
import useAssetsBalances, { ASSETS_NAME_IN_STORAGE } from '@polkadot/extension-polkagate/src/hooks/useAssetsBalances'; | ||
import useNFT from '@polkadot/extension-polkagate/src/hooks/useNFT'; | ||
|
||
export default function AccountAssetProvider ({ children }: { children: React.ReactNode }) { | ||
const { accounts } = useContext(AccountContext); | ||
const genesisHashOptions = useContext(GenesisHashOptionsContext); | ||
const { setAlerts } = useContext(AlertContext); | ||
const userAddedChainCtx = useContext(UserAddedChainContext); | ||
const worker = useContext(WorkerContext); | ||
|
||
const [accountsAssets, setAccountsAssets] = useState<SavedAssets | null | undefined>(); | ||
|
||
const assetsOnChains = useAssetsBalances(accounts, setAlerts, genesisHashOptions, userAddedChainCtx, worker); | ||
|
||
useNFT(accounts); | ||
|
||
useEffect(() => { | ||
assetsOnChains && setAccountsAssets({ ...assetsOnChains }); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [assetsOnChains?.timeStamp]); | ||
|
||
useEffect(() => { | ||
/** remove forgotten accounts from assetChains if any */ | ||
if (accounts && assetsOnChains?.balances) { | ||
Object.keys(assetsOnChains.balances).forEach((_address) => { | ||
const found = accounts.find(({ address }) => address === _address); | ||
|
||
if (!found) { | ||
delete assetsOnChains.balances[_address]; | ||
setStorage(ASSETS_NAME_IN_STORAGE, assetsOnChains, true).catch(console.error); | ||
} | ||
}); | ||
} | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [accounts?.length, assetsOnChains?.timeStamp]); | ||
|
||
return ( | ||
<AccountsAssetsContext.Provider value={{ accountsAssets, setAccountsAssets }}> | ||
{children} | ||
</AccountsAssetsContext.Provider> | ||
); | ||
} |
32 changes: 32 additions & 0 deletions
32
packages/extension-ui/src/Popup/contexts/AccountIconThemeProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import type { IconTheme } from '@polkadot/react-identicon/types'; | ||
|
||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { AccountIconThemeContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
import { getStorage, watchStorage } from '@polkadot/extension-polkagate/src/components/Loading'; | ||
import { DEFAULT_ACCOUNT_ICON_THEME } from '@polkadot/extension-polkagate/src/util/constants'; | ||
|
||
export default function AccountIconThemeProvider ({ children }: { children: React.ReactNode }) { | ||
const [accountIconTheme, setAccountIconTheme] = useState<IconTheme>(DEFAULT_ACCOUNT_ICON_THEME); | ||
|
||
useEffect(() => { | ||
getStorage('iconTheme') | ||
.then((maybeTheme) => setAccountIconTheme((maybeTheme as IconTheme | undefined) || DEFAULT_ACCOUNT_ICON_THEME)) | ||
.catch(console.error); | ||
|
||
const unsubscribe = watchStorage('iconTheme', setAccountIconTheme); | ||
|
||
return () => { | ||
unsubscribe(); | ||
}; | ||
}, []); | ||
|
||
return ( | ||
<AccountIconThemeContext.Provider value={{ accountIconTheme, setAccountIconTheme }}> | ||
{children} | ||
</AccountIconThemeContext.Provider> | ||
); | ||
} |
75 changes: 75 additions & 0 deletions
75
packages/extension-ui/src/Popup/contexts/AccountProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import type { AccountJson, AccountsContext } from '@polkadot/extension-base/background/types'; | ||
|
||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { canDerive } from '@polkadot/extension-base/utils'; | ||
import { AccountContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
import { getStorage, type LoginInfo, updateStorage } from '@polkadot/extension-polkagate/src/components/Loading'; | ||
import { subscribeAccounts } from '@polkadot/extension-polkagate/src/messaging'; | ||
import { buildHierarchy } from '@polkadot/extension-polkagate/src/util/buildHierarchy'; | ||
|
||
function initAccountContext (accounts: AccountJson[]): AccountsContext { | ||
const hierarchy = buildHierarchy(accounts); | ||
const master = hierarchy.find(({ isExternal, type }) => !isExternal && canDerive(type)); | ||
|
||
return { | ||
accounts, | ||
hierarchy, | ||
master | ||
}; | ||
} | ||
|
||
export default function AccountProvider ({ children }: { children: React.ReactNode }) { | ||
const [accounts, setAccounts] = useState<null | AccountJson[]>(null); | ||
const [accountCtx, setAccountCtx] = useState<AccountsContext>({ accounts: [], hierarchy: [] }); | ||
const [loginInfo, setLoginInfo] = useState<LoginInfo>(); | ||
|
||
useEffect(() => { | ||
subscribeAccounts(setAccounts).catch(console.log); | ||
}, []); | ||
|
||
useEffect(() => { | ||
const fetchLoginInfo = async () => { | ||
chrome.storage.onChanged.addListener(function (changes, areaName) { | ||
if (areaName === 'local' && 'loginInfo' in changes) { | ||
const newValue = changes['loginInfo'].newValue as LoginInfo; | ||
|
||
setLoginInfo(newValue); | ||
} | ||
}); | ||
const info = await getStorage('loginInfo') as LoginInfo; | ||
|
||
setLoginInfo(info); | ||
}; | ||
|
||
fetchLoginInfo().catch(console.error); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (!loginInfo) { | ||
return; | ||
} | ||
|
||
if (loginInfo.status !== 'forgot') { | ||
setAccountCtx(initAccountContext(accounts || [])); | ||
} else if (loginInfo.status === 'forgot') { | ||
setAccountCtx(initAccountContext([])); | ||
const addresses = accounts?.map((account) => account.address); | ||
|
||
updateStorage('loginInfo', { addressesToForget: addresses }).catch(console.error); | ||
} | ||
}, [accounts, loginInfo]); | ||
|
||
if (!accounts) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<AccountContext.Provider value={accountCtx}> | ||
{children} | ||
</AccountContext.Provider> | ||
); | ||
} |
20 changes: 20 additions & 0 deletions
20
packages/extension-ui/src/Popup/contexts/ActionProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import React, { useCallback } from 'react'; | ||
|
||
import { ActionContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
|
||
export default function ActionProvider ({ children }: { children: React.ReactNode }) { | ||
const onAction = useCallback((to?: string): void => { | ||
if (to) { | ||
window.location.hash = to; | ||
} | ||
}, []); | ||
|
||
return ( | ||
<ActionContext.Provider value={onAction}> | ||
{children} | ||
</ActionContext.Provider> | ||
); | ||
} |
18 changes: 18 additions & 0 deletions
18
packages/extension-ui/src/Popup/contexts/AlertProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import type { AlertType } from '@polkadot/extension-polkagate/util/types'; | ||
|
||
import React, { useState } from 'react'; | ||
|
||
import { AlertContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
|
||
export default function AlertProvider ({ children }: { children: React.ReactNode }) { | ||
const [alerts, setAlerts] = useState<AlertType[]>([]); | ||
|
||
return ( | ||
<AlertContext.Provider value={{ alerts, setAlerts }}> | ||
{children} | ||
</AlertContext.Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import type { APIs } from '@polkadot/extension-polkagate/util/types'; | ||
|
||
import React, { useState } from 'react'; | ||
|
||
import { APIContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
|
||
export default function ApiProvider ({ children }: { children: React.ReactNode }) { | ||
const [apis, setApis] = useState<APIs>({}); | ||
|
||
const updateApis = React.useCallback((change: APIs) => { | ||
setApis(change); | ||
}, []); | ||
|
||
return ( | ||
<APIContext.Provider value={{ apis, setIt: updateApis }}> | ||
{children} | ||
</APIContext.Provider> | ||
); | ||
} |
61 changes: 61 additions & 0 deletions
61
packages/extension-ui/src/Popup/contexts/CurrencyProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import type { CurrencyItemType } from '@polkadot/extension-polkagate/src/fullscreen/homeFullScreen/partials/Currency'; | ||
import type { Prices, PricesInCurrencies } from '@polkadot/extension-polkagate/src/util/types'; | ||
|
||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { CurrencyContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
import { getStorage, setStorage } from '@polkadot/extension-polkagate/src/components/Loading'; | ||
import usePriceIds from '@polkadot/extension-polkagate/src/hooks/usePriceIds'; | ||
import { isPriceUpToDate } from '@polkadot/extension-polkagate/src/hooks/usePrices'; | ||
import { getPrices } from '@polkadot/extension-polkagate/src/util/api'; | ||
|
||
interface CurrencyProviderProps { | ||
children: React.ReactNode; | ||
} | ||
|
||
export default function CurrencyProvider ({ children }: CurrencyProviderProps) { | ||
const priceIds = usePriceIds(); | ||
|
||
const [currency, setCurrency] = useState<CurrencyItemType>(); | ||
const isFetchingPricesRef = React.useRef(false); | ||
|
||
useEffect(() => { | ||
if (priceIds && currency?.code && !isFetchingPricesRef.current) { | ||
isFetchingPricesRef.current = true; | ||
|
||
getStorage('pricesInCurrencies') | ||
.then((res) => { | ||
const savedPricesInCurrencies = (res || {}) as PricesInCurrencies; | ||
const maybeSavedPriceInCurrentCurrencyCode = savedPricesInCurrencies[currency.code]; | ||
|
||
if (maybeSavedPriceInCurrentCurrencyCode && isPriceUpToDate(maybeSavedPriceInCurrentCurrencyCode.date)) { | ||
/** price in the selected currency is already updated hence no need to fetch again */ | ||
// TODO: FixMe: what if users change selected chainS during price validity period? | ||
return; | ||
} | ||
|
||
getPrices(priceIds, currency.code.toLowerCase()) | ||
.then((newPrices) => { | ||
delete (newPrices as Prices).currencyCode; | ||
savedPricesInCurrencies[currency.code] = newPrices; | ||
setStorage('pricesInCurrencies', savedPricesInCurrencies) | ||
.catch(console.error); | ||
}) | ||
.catch(console.error); | ||
}) | ||
.catch(console.error) | ||
.finally(() => { | ||
isFetchingPricesRef.current = false; | ||
}); | ||
} | ||
}, [currency?.code, priceIds]); | ||
|
||
return ( | ||
<CurrencyContext.Provider value={{ currency, setCurrency }}> | ||
{children} | ||
</CurrencyContext.Provider> | ||
); | ||
} |
22 changes: 22 additions & 0 deletions
22
packages/extension-ui/src/Popup/contexts/FetchingProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import type { Fetching } from '@polkadot/extension-polkagate/util/types'; | ||
|
||
import React, { useCallback, useState } from 'react'; | ||
|
||
import { FetchingContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
|
||
export default function FetchingProvider ({ children }: { children: React.ReactNode }) { | ||
const [fetching, setFetching] = useState<Fetching>({}); | ||
|
||
const set = useCallback((change: Fetching) => { | ||
setFetching(change); | ||
}, []); | ||
|
||
return ( | ||
<FetchingContext.Provider value={{ fetching, set }}> | ||
{children} | ||
</FetchingContext.Provider> | ||
); | ||
} |
17 changes: 17 additions & 0 deletions
17
packages/extension-ui/src/Popup/contexts/GenesisHashOptionsProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import React from 'react'; | ||
|
||
import { GenesisHashOptionsContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
import useGenesisHashOptions from '@polkadot/extension-polkagate/src/hooks/useGenesisHashOptions'; | ||
|
||
export default function GenesisHashOptionsProvider ({ children }: { children: React.ReactNode }) { | ||
const genesisHashOptionsCtx = useGenesisHashOptions(); | ||
|
||
return ( | ||
<GenesisHashOptionsContext.Provider value={genesisHashOptionsCtx}> | ||
{children} | ||
</GenesisHashOptionsContext.Provider> | ||
); | ||
} |
49 changes: 49 additions & 0 deletions
49
packages/extension-ui/src/Popup/contexts/MediaProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import React, { useContext, useEffect, useState } from 'react'; | ||
|
||
import { MediaContext, SettingsContext } from '@polkadot/extension-polkagate/src/components/contexts'; | ||
|
||
interface MediaProviderProps { | ||
children: React.ReactNode; | ||
} | ||
|
||
// Request permission for video, based on access we can hide/show import | ||
async function requestMediaAccess (cameraOn: boolean): Promise<boolean> { | ||
if (!cameraOn) { | ||
return false; | ||
} | ||
|
||
try { | ||
await navigator.mediaDevices.getUserMedia({ video: true }); | ||
|
||
return true; | ||
} catch (error) { | ||
console.error('Permission for video declined', (error as Error).message); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
export default function MediaProvider ({ children }: MediaProviderProps) { | ||
const settings = useContext(SettingsContext); | ||
const [cameraOn, setCameraOn] = useState(settings.camera === 'on'); | ||
const [mediaAllowed, setMediaAllowed] = useState(false); | ||
|
||
useEffect(() => { | ||
setCameraOn(settings.camera === 'on'); | ||
}, [settings.camera]); | ||
|
||
useEffect(() => { | ||
requestMediaAccess(cameraOn) | ||
.then(setMediaAllowed) | ||
.catch(console.error); | ||
}, [cameraOn]); | ||
|
||
return ( | ||
<MediaContext.Provider value={cameraOn && mediaAllowed}> | ||
{children} | ||
</MediaContext.Provider> | ||
); | ||
} |
Oops, something went wrong.