diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx
index 8b50ae681f..fa9b73f54b 100644
--- a/src/components/App/index.tsx
+++ b/src/components/App/index.tsx
@@ -11,7 +11,7 @@ import ErrorIcon from 'src/assets/icons/error.svg'
import InfoIcon from 'src/assets/icons/info.svg'
import AppLayout from 'src/components/AppLayout'
-import SafeListSidebarProvider, { SafeListSidebarContext } from 'src/components/SafeListSidebar'
+import { SafeListSidebar, SafeListSidebarContext } from 'src/components/SafeListSidebar'
import CookiesBanner from 'src/components/CookiesBanner'
import Notifier from 'src/components/Notifier'
import Backdrop from 'src/components/layout/Backdrop'
@@ -159,9 +159,9 @@ const App: React.FC = ({ children }) => {
}
const WrapperAppWithSidebar: React.FC = ({ children }) => (
-
+
{children}
-
+
)
export default WrapperAppWithSidebar
diff --git a/src/components/SafeListSidebar/SafeList/AddresWrapper.tsx b/src/components/SafeListSidebar/SafeList/AddressWrapper.tsx
similarity index 85%
rename from src/components/SafeListSidebar/SafeList/AddresWrapper.tsx
rename to src/components/SafeListSidebar/SafeList/AddressWrapper.tsx
index 8bf621a3df..f21874aa3e 100644
--- a/src/components/SafeListSidebar/SafeList/AddresWrapper.tsx
+++ b/src/components/SafeListSidebar/SafeList/AddressWrapper.tsx
@@ -6,9 +6,10 @@ import { sameAddress } from 'src/logic/wallets/ethAddresses'
import DefaultBadge from './DefaultBadge'
import { SafeRecordProps } from 'src/logic/safe/store/models/safe'
import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe'
-import { SetDefaultSafe } from 'src/logic/safe/store/actions/setDefaultSafe'
+import setDefaultSafe from 'src/logic/safe/store/actions/setDefaultSafe'
import { makeStyles } from '@material-ui/core/styles'
import { getNetworkInfo } from 'src/config'
+import { useDispatch } from 'react-redux'
const StyledButtonLink = styled(ButtonLink)`
visibility: hidden;
@@ -46,14 +47,18 @@ const useStyles = makeStyles({
type Props = {
safe: SafeRecordProps
defaultSafe: DefaultSafe
- setDefaultSafe: SetDefaultSafe
}
const { nativeCoin } = getNetworkInfo()
export const AddressWrapper = (props: Props): React.ReactElement => {
const classes = useStyles()
- const { safe, defaultSafe, setDefaultSafe } = props
+ const { safe, defaultSafe } = props
+ const dispatch = useDispatch()
+
+ const setDefaultSafeAction = (safeAddress: string) => {
+ dispatch(setDefaultSafe(safeAddress))
+ }
return (
@@ -68,7 +73,7 @@ export const AddressWrapper = (props: Props): React.ReactElement => {
className="safeListMakeDefaultButton"
textSize="sm"
onClick={() => {
- setDefaultSafe(safe.address)
+ setDefaultSafeAction(safe.address)
}}
color="primary"
>
diff --git a/src/components/SafeListSidebar/SafeList/index.tsx b/src/components/SafeListSidebar/SafeList/index.tsx
index 57b60238da..3a664d56a2 100644
--- a/src/components/SafeListSidebar/SafeList/index.tsx
+++ b/src/components/SafeListSidebar/SafeList/index.tsx
@@ -6,12 +6,11 @@ import * as React from 'react'
import styled from 'styled-components'
import { SafeRecord } from 'src/logic/safe/store/models/safe'
import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe'
-import { SetDefaultSafe } from 'src/logic/safe/store/actions/setDefaultSafe'
import Hairline from 'src/components/layout/Hairline'
import Link from 'src/components/layout/Link'
import { sameAddress } from 'src/logic/wallets/ethAddresses'
import { SAFELIST_ADDRESS } from 'src/routes/routes'
-import { AddressWrapper } from './AddresWrapper'
+import { AddressWrapper } from 'src/components/SafeListSidebar/SafeList/AddressWrapper'
export const SIDEBAR_SAFELIST_ROW_TESTID = 'SIDEBAR_SAFELIST_ROW_TESTID'
const StyledIcon = styled(Icon)`
@@ -46,10 +45,9 @@ type Props = {
defaultSafe: DefaultSafe
safes: SafeRecord[]
onSafeClick: () => void
- setDefaultSafe: SetDefaultSafe
}
-const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe }: Props): React.ReactElement => {
+export const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes }: Props): React.ReactElement => {
const classes = useStyles()
return (
@@ -67,7 +65,7 @@ const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe
) : (
placeholder
)}
-
+
@@ -76,5 +74,3 @@ const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe
)
}
-
-export default SafeList
diff --git a/src/components/SafeListSidebar/index.tsx b/src/components/SafeListSidebar/index.tsx
index 8aeeb77b3f..9846f170c0 100644
--- a/src/components/SafeListSidebar/index.tsx
+++ b/src/components/SafeListSidebar/index.tsx
@@ -1,10 +1,10 @@
-import React, { useEffect, useMemo, useState } from 'react'
+import React, { useEffect, useMemo, useState, ReactElement } from 'react'
import Drawer from '@material-ui/core/Drawer'
import SearchIcon from '@material-ui/icons/Search'
import SearchBar from 'material-ui-search-bar'
-import { connect } from 'react-redux'
+import { useSelector } from 'react-redux'
-import SafeList from './SafeList'
+import { SafeList } from './SafeList'
import { sortedSafeListSelector } from './selectors'
import useSidebarStyles from './style'
@@ -15,11 +15,9 @@ import Hairline from 'src/components/layout/Hairline'
import Link from 'src/components/layout/Link'
import Row from 'src/components/layout/Row'
import { WELCOME_ADDRESS } from 'src/routes/routes'
-import setDefaultSafe from 'src/logic/safe/store/actions/setDefaultSafe'
import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics'
import { defaultSafeSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
-import { AppReduxState } from 'src/store'
export const SafeListSidebarContext = React.createContext({
isOpen: false,
@@ -34,9 +32,17 @@ const filterBy = (filter, safes) =>
safe.name.toLowerCase().includes(filter.toLowerCase()),
)
-const SafeListSidebar = ({ children, currentSafe, defaultSafe, safes, setDefaultSafeAction }) => {
+type Props = {
+ children: ReactElement
+}
+
+export const SafeListSidebar = ({ children }: Props): ReactElement => {
const [isOpen, setIsOpen] = useState(false)
const [filter, setFilter] = useState('')
+ const safes = useSelector(sortedSafeListSelector)
+ const defaultSafe = useSelector(defaultSafeSelector)
+ const currentSafe = useSelector(safeParamAddressFromStateSelector)
+
const classes = useSidebarStyles()
const { trackEvent } = useAnalytics()
@@ -118,19 +124,9 @@ const SafeListSidebar = ({ children, currentSafe, defaultSafe, safes, setDefault
defaultSafe={defaultSafe}
onSafeClick={toggleSidebar}
safes={filteredSafes}
- setDefaultSafe={setDefaultSafeAction}
/>
{children}
)
}
-
-export default connect(
- (state: AppReduxState) => ({
- safes: sortedSafeListSelector(state),
- defaultSafe: defaultSafeSelector(state),
- currentSafe: safeParamAddressFromStateSelector(state),
- }),
- { setDefaultSafeAction: setDefaultSafe },
-)(SafeListSidebar)
diff --git a/src/logic/safe/store/actions/removeLocalSafe.ts b/src/logic/safe/store/actions/removeLocalSafe.ts
new file mode 100644
index 0000000000..64bd42847d
--- /dev/null
+++ b/src/logic/safe/store/actions/removeLocalSafe.ts
@@ -0,0 +1,11 @@
+import { Action, Dispatch } from 'redux'
+import { loadStoredSafes } from 'src/logic/safe/utils'
+import removeSafe from 'src/logic/safe/store/actions/removeSafe'
+
+export const removeLocalSafe = (safeAddress: string) => async (dispatch: Dispatch): Promise
=> {
+ const storedSafes = await loadStoredSafes()
+ if (storedSafes) {
+ delete storedSafes[safeAddress]
+ }
+ dispatch(removeSafe(safeAddress))
+}
diff --git a/src/logic/safe/store/reducer/safe.ts b/src/logic/safe/store/reducer/safe.ts
index 5381b38a79..b5997f68f9 100644
--- a/src/logic/safe/store/reducer/safe.ts
+++ b/src/logic/safe/store/reducer/safe.ts
@@ -126,7 +126,14 @@ export default handleActions(
[REMOVE_SAFE]: (state: SafeReducerMap, action) => {
const safeAddress = action.payload
- return state.deleteIn(['safes', safeAddress])
+ const currentDefaultSafe = state.get('defaultSafe')
+
+ let newState = state.deleteIn(['safes', safeAddress])
+ if (sameAddress(safeAddress, currentDefaultSafe)) {
+ newState = newState.set('defaultSafe', DEFAULT_SAFE_INITIAL_STATE)
+ }
+
+ return newState
},
[ADD_SAFE_OWNER]: (state: SafeReducerMap, action) => {
const { ownerAddress, ownerName, safeAddress } = action.payload
diff --git a/src/routes/open/components/Layout.tsx b/src/routes/open/components/Layout.tsx
index 45385f05e4..2bce38460e 100644
--- a/src/routes/open/components/Layout.tsx
+++ b/src/routes/open/components/Layout.tsx
@@ -17,7 +17,7 @@ import {
getOwnerAddressBy,
getOwnerNameBy,
} from 'src/routes/open/components/fields'
-import Welcome from 'src/routes/welcome/components/Layout'
+import { WelcomeLayout } from 'src/routes/welcome/components/index'
import { history } from 'src/store'
import { secondary, sm } from 'src/theme/variables'
import { networkSelector, providerNameSelector, userAccountSelector } from 'src/logic/wallets/store/selectors'
@@ -138,7 +138,7 @@ export const Layout = (props: LayoutProps): React.ReactElement => {
) : (
-
+
)}
>
)
diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx
index 26157c4b2d..914da3c25c 100644
--- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx
+++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx
@@ -40,17 +40,18 @@ type OwnProps = {
selectedOwnerName: string
}
-const EditOwnerComponent = ({ isOpen, onClose, ownerAddress, selectedOwnerName }: OwnProps): React.ReactElement => {
+export const EditOwnerModal = ({ isOpen, onClose, ownerAddress, selectedOwnerName }: OwnProps): React.ReactElement => {
const classes = useStyles()
const dispatch = useDispatch()
- const safeAddress = useSelector(safeParamAddressFromStateSelector) as string
- const handleSubmit = (values) => {
- const { ownerName } = values
-
- dispatch(editSafeOwner({ safeAddress, ownerAddress, ownerName }))
- dispatch(addOrUpdateAddressBookEntry(makeAddressBookEntry({ address: ownerAddress, name: ownerName })))
- dispatch(enqueueSnackbar(NOTIFICATIONS.OWNER_NAME_CHANGE_EXECUTED_MSG))
+ const safeAddress = useSelector(safeParamAddressFromStateSelector)
+ const handleSubmit = ({ ownerName }: { ownerName: string }): void => {
+ // Update the value only if the ownerName really changed
+ if (ownerName !== selectedOwnerName) {
+ dispatch(editSafeOwner({ safeAddress, ownerAddress, ownerName }))
+ dispatch(addOrUpdateAddressBookEntry(makeAddressBookEntry({ address: ownerAddress, name: ownerName })))
+ dispatch(enqueueSnackbar(NOTIFICATIONS.OWNER_NAME_CHANGE_EXECUTED_MSG))
+ }
onClose()
}
@@ -71,54 +72,56 @@ const EditOwnerComponent = ({ isOpen, onClose, ownerAddress, selectedOwnerName }
-
- {() => (
- <>
-
-
-
-
-
-
-
-
- {ownerAddress}
-
-
-
-
+
+ {(...args) => {
+ const pristine = args[2].pristine
+ return (
+ <>
+
+
+
+
+
+
+
+
+ {ownerAddress}
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
- >
- )}
+ >
+ )
+ }}
)
}
-
-export default EditOwnerComponent
diff --git a/src/routes/safe/components/Settings/ManageOwners/index.tsx b/src/routes/safe/components/Settings/ManageOwners/index.tsx
index be55767adb..df255ca53e 100644
--- a/src/routes/safe/components/Settings/ManageOwners/index.tsx
+++ b/src/routes/safe/components/Settings/ManageOwners/index.tsx
@@ -9,7 +9,7 @@ import { List } from 'immutable'
import RemoveOwnerIcon from '../assets/icons/bin.svg'
import AddOwnerModal from './AddOwnerModal'
-import EditOwnerModal from './EditOwnerModal'
+import { EditOwnerModal } from './EditOwnerModal'
import OwnerAddressTableCell from './OwnerAddressTableCell'
import RemoveOwnerModal from './RemoveOwnerModal'
import ReplaceOwnerModal from './ReplaceOwnerModal'
diff --git a/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx b/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx
index 5524ecd31d..4d2f8b728a 100644
--- a/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx
+++ b/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx
@@ -18,9 +18,16 @@ import Hairline from 'src/components/layout/Hairline'
import Link from 'src/components/layout/Link'
import Paragraph from 'src/components/layout/Paragraph'
import Row from 'src/components/layout/Row'
-import removeSafe from 'src/logic/safe/store/actions/removeSafe'
-import { safeNameSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
+import {
+ defaultSafeSelector,
+ safeNameSelector,
+ safeParamAddressFromStateSelector,
+} from 'src/logic/safe/store/selectors'
import { md, secondary } from 'src/theme/variables'
+import { WELCOME_ADDRESS } from 'src/routes/routes'
+import { removeLocalSafe } from 'src/logic/safe/store/actions/removeLocalSafe'
+import { sameAddress } from 'src/logic/wallets/ethAddresses'
+import { saveDefaultSafe } from 'src/logic/safe/utils'
const openIconStyle = {
height: md,
@@ -29,14 +36,33 @@ const openIconStyle = {
const useStyles = makeStyles(styles)
-const RemoveSafeComponent = ({ isOpen, onClose }) => {
+type RemoveSafeModalProps = {
+ isOpen: boolean
+ onClose: () => void
+}
+
+export const RemoveSafeModal = ({ isOpen, onClose }: RemoveSafeModalProps): React.ReactElement => {
const classes = useStyles()
- const safeAddress = useSelector(safeParamAddressFromStateSelector) as string
+ const safeAddress = useSelector(safeParamAddressFromStateSelector)
const safeName = useSelector(safeNameSelector)
+ const defaultSafe = useSelector(defaultSafeSelector)
const dispatch = useDispatch()
const explorerInfo = getExplorerInfo(safeAddress)
const { url } = explorerInfo()
+ const onRemoveSafeHandler = async () => {
+ await dispatch(removeLocalSafe(safeAddress))
+ if (sameAddress(safeAddress, defaultSafe)) {
+ await saveDefaultSafe('')
+ }
+
+ onClose()
+ // using native redirect in order to avoid problems in several components
+ // trying to access references of the removed safe.
+ const relativePath = window.location.href.split('/#/')[0]
+ window.location.href = `${relativePath}/#/${WELCOME_ADDRESS}`
+ }
+
return (
{
)
}
-
-export const RemoveSafeModal = RemoveSafeComponent
diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx
index 123f8559da..da836962fd 100644
--- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx
+++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx
@@ -105,7 +105,7 @@ const ExpandedSafeTx = ({ cancelTx, tx }: ExpandedSafeTxProps): ReactElement =>
const thresholdReached = !isIncomingTx && threshold <= tx.confirmations.size
const canExecute = !isIncomingTx && nonce === tx.nonce
- const cancelThresholdReached = !!cancelTx && threshold <= cancelTx.confirmations.size
+ const cancelThresholdReached = !!cancelTx && threshold <= cancelTx.confirmations?.size
const canExecuteCancel = nonce === tx.nonce
const openRejectModal = () => {
diff --git a/src/routes/welcome/components/Layout.tsx b/src/routes/welcome/components/index.tsx
similarity index 94%
rename from src/routes/welcome/components/Layout.tsx
rename to src/routes/welcome/components/index.tsx
index 84d2b652e9..4407421c3d 100644
--- a/src/routes/welcome/components/Layout.tsx
+++ b/src/routes/welcome/components/index.tsx
@@ -16,6 +16,8 @@ import Link from 'src/components/layout/Link'
import Block from 'src/components/layout/Block'
import { LOAD_ADDRESS, OPEN_ADDRESS } from 'src/routes/routes'
import { onConnectButtonClick } from 'src/components/ConnectButton'
+import { useSelector } from 'react-redux'
+import { providerNameSelector } from 'src/logic/wallets/store/selectors'
const Wrapper = styled.div`
display: flex;
@@ -67,10 +69,10 @@ const StyledButtonLink = styled(ButtonLink)`
type Props = {
isOldMultisigMigration?: boolean
- provider: any
}
-const Welcome = ({ isOldMultisigMigration, provider }: Props): React.ReactElement => {
+export const WelcomeLayout = ({ isOldMultisigMigration }: Props): React.ReactElement => {
+ const provider = useSelector(providerNameSelector)
return (
{/* Title */}
@@ -125,7 +127,7 @@ const Welcome = ({ isOldMultisigMigration, provider }: Props): React.ReactElemen
color="primary"
variant="contained"
onClick={onConnectButtonClick}
- disabled={provider}
+ disabled={!!provider}
data-testid="connect-btn"
>
@@ -187,5 +189,3 @@ const Welcome = ({ isOldMultisigMigration, provider }: Props): React.ReactElemen
)
}
-
-export default Welcome
diff --git a/src/routes/welcome/container/index.tsx b/src/routes/welcome/container/index.tsx
index ba090dee8c..be5874feb4 100644
--- a/src/routes/welcome/container/index.tsx
+++ b/src/routes/welcome/container/index.tsx
@@ -1,16 +1,12 @@
-import * as React from 'react'
-import { connect } from 'react-redux'
-
-import Layout from '../components/Layout'
-
-import selector from './selector'
+import React, { ReactElement } from 'react'
+import { WelcomeLayout } from 'src/routes/welcome/components'
import Page from 'src/components/layout/Page'
-const Welcome = ({ provider }) => (
+const Welcome = (): ReactElement => (
-
+
)
-export default connect(selector)(Welcome)
+export default Welcome
diff --git a/src/routes/welcome/container/selector.ts b/src/routes/welcome/container/selector.ts
deleted file mode 100644
index bc2d05cee2..0000000000
--- a/src/routes/welcome/container/selector.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { createStructuredSelector } from 'reselect'
-
-import { providerNameSelector } from 'src/logic/wallets/store/selectors'
-
-export default createStructuredSelector({
- provider: providerNameSelector,
-})