Skip to content
This repository has been archived by the owner on Nov 10, 2023. It is now read-only.

Commit

Permalink
Fix: update local safes in sidebar (#3017)
Browse files Browse the repository at this point in the history
  • Loading branch information
katspaugh authored Nov 17, 2021
1 parent bfa665f commit 3bd9b66
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 75 deletions.
30 changes: 17 additions & 13 deletions src/components/SafeListSidebar/SafeList/SafeListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,32 @@ const SafeListItem = ({
const safeRef = useRef<HTMLDivElement>(null)
const nativeCoinSymbol = getNetworkConfigById(networkId)?.network?.nativeCoin?.symbol ?? 'ETH'

useEffect(() => {
if (isCurrentSafe && shouldScrollToSafe) {
safeRef?.current?.scrollIntoView({ behavior: 'smooth' })
}
}, [isCurrentSafe, shouldScrollToSafe])

const handleLoadSafe = (): void => {
onNetworkSwitch?.()
setNetwork(networkId)
onSafeClick()
}

const routesSlug: SafeRouteParams = {
shortName: getShortChainNameById(networkId),
safeAddress: address,
}

const handleOpenSafe = (): void => {
handleLoadSafe()
onSafeClick()
onNetworkSwitch?.()
history.push(generateSafeRoute(SAFE_ROUTES.ASSETS_BALANCES, routesSlug))
}

const handleLoadSafe = (): void => {
onSafeClick()
onNetworkSwitch?.()
history.push(generateSafeRoute(LOAD_SPECIFIC_SAFE_ROUTE, routesSlug))

// Navigating to LOAD_SPECIFIC_SAFE_ROUTE doesn't trigger a network switch
setNetwork(networkId)
}

useEffect(() => {
if (isCurrentSafe && shouldScrollToSafe) {
safeRef?.current?.scrollIntoView({ behavior: 'smooth' })
}
}, [isCurrentSafe, shouldScrollToSafe])

return (
<ListItem button onClick={handleOpenSafe} ref={safeRef}>
<StyledIcon type="check" size="md" color="primary" checked={isCurrentSafe} />
Expand Down
76 changes: 33 additions & 43 deletions src/components/SafeListSidebar/SafeList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@ import ListItem from '@material-ui/core/ListItem'
import styled from 'styled-components'
import makeStyles from '@material-ui/core/styles/makeStyles'
import { Fragment, ReactElement } from 'react'
import { useSelector } from 'react-redux'
import { Text } from '@gnosis.pm/safe-react-components'
import { Link } from 'react-router-dom'

import { setNetwork } from 'src/logic/config/utils'
import { sortedSafeListSelector } from '../selectors'
import { getNetworkId, getNetworks } from 'src/config'
import { SafeRecordWithNames } from 'src/logic/safe/store/selectors'
import Collapse from 'src/components/Collapse'
import SafeListItem from './SafeListItem'
import { isSafeAdded } from 'src/logic/safe/utils/safeInformation'
import useLocalSafes from 'src/logic/safe/hooks/useLocalSafes'
import useOwnerSafes from 'src/logic/safe/hooks/useOwnerSafes'
import { extractSafeAddress, WELCOME_ROUTE } from 'src/routes/routes'
import { checksumAddress } from 'src/utils/checksumAddress'

const MAX_EXPANDED_SAFES = 3

Expand Down Expand Up @@ -65,64 +61,56 @@ type Props = {
onSafeClick: () => void
}

const isNotLoadedViaUrl = ({ loadedViaUrl }: SafeRecordWithNames) => !loadedViaUrl
const isNotLoadedViaUrl = ({ loadedViaUrl }: SafeRecordWithNames) => loadedViaUrl === false

const isSameAddress = (addrA: string, addrB: string): boolean => addrA.toLowerCase() === addrB.toLowerCase()

export const SafeList = ({ onSafeClick }: Props): ReactElement => {
const classes = useStyles()
const networks = getNetworks()
const currentSafeAddress = extractSafeAddress()

const addedSafes = useSelector(sortedSafeListSelector)
.filter(isNotLoadedViaUrl)
.map((loadedSafe) => ({ ...loadedSafe, address: checksumAddress(loadedSafe.address) }))
const ownedSafes = useOwnerSafes()
const localSafes = useLocalSafes()

return (
<StyledList>
{networks.map(({ id, backgroundColor, textColor, label }) => {
const isCurrentNetwork = id === getNetworkId()

const addedSafesOnNetwork = addedSafes.filter((addedSafe) => addedSafe.chainId === id)
const ownedSafesOnNetwork = ownedSafes[id] || []
const localSafesOnNetwork = localSafes[id].filter(isNotLoadedViaUrl).map((localSafe) => ({
...localSafe,
address: checksumAddress(localSafe.address),
}))

const safes = isCurrentNetwork ? addedSafesOnNetwork : localSafesOnNetwork

const shouldExpandOwnedSafes = isCurrentNetwork
? ownedSafesOnNetwork.some((address) => address === currentSafeAddress && !isSafeAdded(addedSafes, address))
: safes.length !== addedSafesOnNetwork.length && ownedSafesOnNetwork.length <= MAX_EXPANDED_SAFES

if (
!isCurrentNetwork &&
!addedSafesOnNetwork.length &&
!ownedSafesOnNetwork.length &&
!localSafesOnNetwork.length
) {
const localSafesOnNetwork = localSafes[id].filter(isNotLoadedViaUrl)

if (!isCurrentNetwork && !ownedSafesOnNetwork.length && !localSafesOnNetwork.length) {
return null
}

let shouldExpandOwnedSafes = false
if (ownedSafesOnNetwork.includes(currentSafeAddress)) {
// Expand the Owned Safes if the current Safe is owned, but not added
shouldExpandOwnedSafes = !localSafesOnNetwork.some(({ address }) =>
isSameAddress(address, currentSafeAddress),
)
} else {
// Expand the Owned Safes if there are no added Safes
shouldExpandOwnedSafes = !localSafesOnNetwork.length && ownedSafesOnNetwork.length <= MAX_EXPANDED_SAFES
}

return (
<Fragment key={id}>
<ListItem selected>
<StyledDot backgroundColor={backgroundColor} textColor={textColor} />
{label}
</ListItem>
<MuiList>
{safes.length > 0 &&
safes.map((safe) => (
<SafeListItem
key={safe.address}
networkId={id}
onNetworkSwitch={() => setNetwork(id)}
onSafeClick={onSafeClick}
shouldScrollToSafe
{...safe}
/>
))}
{localSafesOnNetwork.map((safe) => (
<SafeListItem
key={safe.address}
networkId={id}
onNetworkSwitch={() => setNetwork(id)}
onSafeClick={onSafeClick}
shouldScrollToSafe
{...safe}
/>
))}

{!localSafesOnNetwork.length && !ownedSafesOnNetwork.length && (
<PlaceholderText size="lg" color="placeHolder">
Expand All @@ -142,14 +130,16 @@ export const SafeList = ({ onSafeClick }: Props): ReactElement => {
color="placeHolder"
>{`Safes owned on ${label} (${ownedSafesOnNetwork.length})`}</Text>
}
key={String(shouldExpandOwnedSafes)}
defaultExpanded={shouldExpandOwnedSafes}
>
{ownedSafesOnNetwork.map((address) => {
const isAdded = isSafeAdded(safes, address)
{ownedSafesOnNetwork.map((ownedAddress) => {
const isAdded = localSafesOnNetwork.some(({ address }) => isSameAddress(address, ownedAddress))

return (
<SafeListItem
key={address}
address={address}
key={ownedAddress}
address={ownedAddress}
networkId={id}
onSafeClick={onSafeClick}
showAddSafeLink={!isAdded}
Expand Down
7 changes: 6 additions & 1 deletion src/logic/safe/hooks/useLocalSafes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useEffect, useState } from 'react'
import { useSelector } from 'react-redux'
import { sortedSafeListSelector } from 'src/components/SafeListSidebar/selectors'

import { ETHEREUM_NETWORK } from 'src/config/networks/network.d'
import { SafeRecordWithNames } from '../store/selectors'
Expand All @@ -13,7 +15,10 @@ const getEmptyLocalSafes = (): LocalSafes => {

const useLocalSafes = (): LocalSafes => {
const [localSafes, setLocalSafes] = useState<LocalSafes>(() => getEmptyLocalSafes())
const addedSafes = useSelector(sortedSafeListSelector)
const addedAddresses = addedSafes.map(({ address }) => address).join()

// Reload added Safes from the localStorage when addedAddresses changes
useEffect(() => {
const getLocalSafes = () => {
Object.values(ETHEREUM_NETWORK).forEach(async (id) => {
Expand All @@ -26,7 +31,7 @@ const useLocalSafes = (): LocalSafes => {
}

getLocalSafes()
}, [])
}, [addedAddresses])

return localSafes
}
Expand Down
6 changes: 0 additions & 6 deletions src/logic/safe/utils/safeInformation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import { getSafeInfo as fetchSafeInfo, SafeInfo } from '@gnosis.pm/safe-react-ga

import { Errors, CodedException } from 'src/logic/exceptions/CodedException'
import { getClientGatewayUrl, getNetworkId } from 'src/config'
import { sameAddress } from 'src/logic/wallets/ethAddresses'
import { SafeRecordProps } from '../store/models/safe'
import { SafeRecordWithNames } from '../store/selectors'

const GATEWAY_ERROR = /1337|42/

Expand All @@ -16,6 +13,3 @@ export const getSafeInfo = async (safeAddress: string): Promise<SafeInfo> => {
throw new CodedException(safeNotFound ? Errors._605 : Errors._613, e.message)
}
}

export const isSafeAdded = (addedSafes: SafeRecordWithNames[] | SafeRecordProps[], address: string): boolean =>
addedSafes.some((safe: SafeRecordWithNames | SafeRecordProps) => sameAddress(safe.address, address))
11 changes: 4 additions & 7 deletions src/routes/LoadSafePage/fields/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ import {
} from './loadFields'

export function getLoadSafeName(formValues: LoadSafeFormValues, addressBook: AddressBookMap): string {
let safeAddress = formValues[FIELD_LOAD_SAFE_ADDRESS] || ''
try {
safeAddress = checksumAddress(safeAddress)
} catch (e) {
// ignore error
}
let safeAddress = formValues[FIELD_LOAD_SAFE_ADDRESS]
safeAddress = safeAddress ? checksumAddress(safeAddress) : ''

return (
formValues[FIELD_LOAD_CUSTOM_SAFE_NAME] ||
addressBook[safeAddress]?.name ||
(safeAddress ? addressBook[safeAddress]?.name : '') ||
formValues[FIELD_LOAD_SUGGESTED_SAFE_NAME]
)
}
7 changes: 2 additions & 5 deletions src/utils/storage/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { ImmortalStorage, IndexedDbStore, LocalStorageStore } from 'immortal-db'
import { ImmortalStorage, LocalStorageStore } from 'immortal-db'

import { getNetworkName } from 'src/config'
import { Errors, logError } from 'src/logic/exceptions/CodedException'

// Don't use sessionStorage and cookieStorage
// https://github.com/gruns/ImmortalDB/issues/22
// https://github.com/gruns/ImmortalDB/issues/6
const stores = [IndexedDbStore, LocalStorageStore]
const stores = [LocalStorageStore]
export const storage = new ImmortalStorage(stores)

// We need this to update on run time depending on selected network name
Expand Down

0 comments on commit 3bd9b66

Please sign in to comment.