Skip to content

Commit 80e95aa

Browse files
authored
Merge pull request #62 from celo-tools/contacts
Implement Contacts Feature
2 parents b85db49 + da3db62 commit 80e95aa

60 files changed

Lines changed: 833 additions & 440 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package-electron.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "celo-web-wallet",
3-
"version": "1.3.3",
3+
"version": "1.3.4",
44
"description": "A lightweight web and desktop wallet for the Celo network",
55
"main": "main.js",
66
"keywords": [

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "celo-web-wallet",
3-
"version": "1.3.3",
3+
"version": "1.3.4",
44
"description": "A lightweight web and desktop wallet for the Celo network",
55
"keywords": [
66
"Celo",

src/app/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ import { ExploreValidatorsScreen } from 'src/features/validators/ExploreValidato
3232
import { StakeConfirmationScreen } from 'src/features/validators/StakeConfirmationScreen'
3333
import { StakeFormScreen } from 'src/features/validators/StakeFormScreen'
3434
import { StakeRewardsScreen } from 'src/features/validators/StakeRewardsScreen'
35+
import { AccountsAndContactsScreen } from 'src/features/wallet/accounts/AccountsAndContactsScreen'
3536
import { AccountsNavigator } from 'src/features/wallet/accounts/AccountsNavigator'
3637
import { AddAccountScreen } from 'src/features/wallet/accounts/AddAccountScreen'
3738
import { AddCreateScreen } from 'src/features/wallet/accounts/AddCreateScreen'
3839
import { AddDeriveScreen } from 'src/features/wallet/accounts/AddDeriveScreen'
3940
import { AddImportScreen } from 'src/features/wallet/accounts/AddImportScreen'
4041
import { AddLedgerScreen } from 'src/features/wallet/accounts/AddLedgerScreen'
4142
import { AddSetPasswordScreen } from 'src/features/wallet/accounts/AddSetPasswordScreen'
42-
import { ManageAccountsScreen } from 'src/features/wallet/accounts/ManageAccountsScreen'
4343
import { ViewAccountScreen } from 'src/features/wallet/accounts/ViewAccountScreen'
4444
import { BalanceDetailsScreen } from 'src/features/wallet/balances/BalanceDetailsScreen'
4545
import { WalletConnectStatusBox } from 'src/features/walletConnect/WalletConnectStatusBox'
@@ -93,7 +93,7 @@ export const App = () => {
9393
<Route path="balances" element={<BalanceDetailsScreen />} />
9494
<Route path="account" element={<ViewAccountScreen />} />
9595
<Route path="accounts" element={<AccountsNavigator />}>
96-
<Route path="/" element={<ManageAccountsScreen />} />
96+
<Route path="/" element={<AccountsAndContactsScreen />} />
9797
<Route path="add" element={<AddAccountScreen />} />
9898
<Route path="create" element={<AddCreateScreen />} />
9999
<Route path="derive" element={<AddDeriveScreen />} />

src/app/logout/logout.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { resetContacts } from 'src/features/contacts/contactsSlice'
12
import { fetchExchangeRateActions } from 'src/features/exchange/exchangeRate'
23
import { resetFeed } from 'src/features/feed/feedSlice'
34
import { fetchFeedActions } from 'src/features/feed/fetchFeed'
@@ -33,6 +34,7 @@ export function* logout() {
3334
// Manually putting reset actions to the persisted reducers
3435
// Several attempts at using redux-persist's purge options
3536
// all led to different problems
37+
yield* put(resetContacts())
3638
yield* put(resetSettings())
3739
yield* put(resetValidators())
3840
yield* put(resetFeed())

src/app/rootReducer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { combineReducers } from '@reduxjs/toolkit'
2+
import { persistedContactsReducer } from 'src/features/contacts/contactsSlice'
23
import { exchangeReducer } from 'src/features/exchange/exchangeSlice'
34
import { feedReducer } from 'src/features/feed/feedSlice'
45
import { feeReducer } from 'src/features/fees/feeSlice'
@@ -14,6 +15,7 @@ import { monitoredSagaReducers } from './rootSaga'
1415

1516
export const rootReducer = combineReducers({
1617
wallet: persistedWalletReducer,
18+
contacts: persistedContactsReducer,
1719
feed: feedReducer,
1820
exchange: exchangeReducer,
1921
lock: lockReducer,

src/components/Address.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import { useAddressQrCodeModal } from 'src/features/qr/QrCodeModal'
1111
import { txFlowReset } from 'src/features/txFlow/txFlowSlice'
1212
import { Color } from 'src/styles/Color'
1313
import { Stylesheet } from 'src/styles/types'
14-
import { tryClipboardSet } from 'src/utils/clipboard'
14+
import { validateAddress } from 'src/utils/addresses'
15+
import { useClipboardSet } from 'src/utils/clipboard'
1516
import { chunk, trimToLength } from 'src/utils/string'
1617

1718
type ButtonType = 'send' | 'copy' | 'qrAndCopy'
@@ -26,13 +27,10 @@ interface Props {
2627

2728
export function Address(props: Props) {
2829
const { address, name, hideIdenticon, buttonType, isTransparent } = props
29-
30-
if (!utils.isAddress(address)) {
31-
throw new Error('Invalid address')
32-
}
30+
validateAddress(address, 'Address component')
3331

3432
const onSendButtonClick = useSendToAddress(address)
35-
const onCopyButtonClick = useCopyAddress(address)
33+
const onCopyButtonClick = useClipboardSet(address)
3634
const showQrModal = useAddressQrCodeModal()
3735
const onQrButtonClick = () => {
3836
showQrModal(address)
@@ -123,12 +121,6 @@ export function useSendToAddress(address: string) {
123121
}
124122
}
125123

126-
export function useCopyAddress(address: string) {
127-
return async () => {
128-
await tryClipboardSet(address)
129-
}
130-
}
131-
132124
function getAddressContainerStyle(
133125
hideIdenticon?: boolean,
134126
buttonType?: ButtonType,

src/components/Identicon.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import jazzicon from '@metamask/jazzicon'
2-
import { BigNumber, utils } from 'ethers'
2+
import { BigNumber } from 'ethers'
33
import { PureComponent } from 'react'
44
import { Styles } from 'src/styles/types'
5+
import { isValidAddress, normalizeAddress } from 'src/utils/addresses'
56

67
type Props = {
78
address: string
@@ -10,17 +11,15 @@ type Props = {
1011
}
1112

1213
function addressToSeed(address: string) {
13-
return BigNumber.from(address.slice(0, 8)).toNumber()
14+
return BigNumber.from(normalizeAddress(address).slice(0, 8)).toNumber()
1415
}
1516

1617
export class Identicon extends PureComponent<Props> {
1718
render() {
1819
const { address, size: _size, styles } = this.props
1920
const size = _size ?? 34
2021

21-
if (!address || !utils.isAddress(address)) {
22-
return null
23-
}
22+
if (!isValidAddress(address)) return null
2423

2524
const jazziconResult = jazzicon(size, addressToSeed(address))
2625

src/components/RenameModal.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Button } from 'src/components/buttons/Button'
2+
import { TextInput } from 'src/components/input/TextInput'
3+
import { Box } from 'src/components/layout/Box'
4+
import { modalStyles } from 'src/components/modal/modalStyles'
5+
import { MAX_ACCOUNT_NAME_LENGTH } from 'src/consts'
6+
import { useCustomForm } from 'src/utils/useCustomForm'
7+
import { ErrorState, invalidInput } from 'src/utils/validation'
8+
9+
export interface RenameForm {
10+
newName: string
11+
}
12+
13+
interface Props {
14+
onSubmit: (values: RenameForm) => void
15+
label: string
16+
}
17+
18+
export function RenameAccountModal(props: Props) {
19+
const { onSubmit, label } = props
20+
const { values, errors, handleChange, handleBlur, handleSubmit } = useCustomForm<RenameForm>(
21+
{ newName: '' },
22+
onSubmit,
23+
validateForm
24+
)
25+
26+
return (
27+
<form onSubmit={handleSubmit}>
28+
<Box direction="column" align="center">
29+
<p css={modalStyles.pMargin0}>{`Please set a new name for the ${label}.`}</p>
30+
<TextInput
31+
name="newName"
32+
value={values.newName}
33+
onChange={handleChange}
34+
onBlur={handleBlur}
35+
placeholder="My new name"
36+
autoFocus={true}
37+
width="11em"
38+
margin="1.75em 0 0 0"
39+
{...errors['newName']}
40+
/>
41+
<Button size="s" margin="1.8em 0 0 0" type="submit">
42+
Rename
43+
</Button>
44+
</Box>
45+
</form>
46+
)
47+
}
48+
49+
function validateForm(values: RenameForm): ErrorState {
50+
if (!values.newName) return invalidInput('newName', 'New name is required')
51+
if (values.newName.length > MAX_ACCOUNT_NAME_LENGTH)
52+
return invalidInput('newName', 'New name is too long')
53+
return { isValid: true }
54+
}

src/components/footer/AboutWallet.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@ export function AboutWalletLink({ styles }: { styles: Styles }) {
2828
function AboutWalletModal() {
2929
return (
3030
<Box direction="column" align="center" styles={style.container}>
31-
<p style={style.text}>
32-
The Celo Wallet is a free, open source wallet for the{' '}
33-
<TextLink link="https://celo.org">Celo network</TextLink>. It was created by{' '}
31+
<p css={style.text}>
32+
The Celo Wallet is a free, open source wallet for the Celo network. It was created by{' '}
3433
<TextLink link="https://twitter.com/RossyWrote">J M Rossy</TextLink> and{' '}
3534
<TextLink link="https://www.linkedin.com/in/brianschwalm/">Brian Schwalm</TextLink>.
3635
</p>
37-
<p style={style.text}>
36+
<p css={style.text}>
3837
The source code for the wallet can be found{' '}
3938
<TextLink link="https://github.com/celo-tools/celo-web-wallet">on Github</TextLink> and
4039
includes answers to{' '}
4140
<TextLink link="https://github.com/celo-tools/celo-web-wallet/blob/master/FAQ.md">
4241
Frequently Asked Questions
4342
</TextLink>
44-
.
43+
. For other help, try asking in the{' '}
44+
<TextLink link={config.discordUrl}>Discord chat</TextLink>.
4545
</p>
46-
<p style={style.version}>{`Version: ${config.version}`}</p>
46+
<p css={style.version}>{`Version: ${config.version}`}</p>
4747
</Box>
4848
)
4949
}

src/components/footer/Footer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CopiableAddress } from 'src/components/buttons/CopiableAddress'
22
import { AboutWalletLink } from 'src/components/footer/AboutWallet'
33
import { ConnectionStatusLink } from 'src/components/footer/ConnectionStatus'
4+
import { HelpButton } from 'src/components/footer/Help'
45
import { Box } from 'src/components/layout/Box'
56
import { config } from 'src/config'
67
import { DownloadDesktopButton } from 'src/features/download/DownloadDesktopModal'
@@ -11,7 +12,6 @@ import { Stylesheet } from 'src/styles/types'
1112

1213
export function Footer() {
1314
const isMobile = useIsMobile()
14-
1515
return isMobile ? <FooterMobile /> : <FooterDesktop />
1616
}
1717

@@ -29,9 +29,9 @@ function FooterDesktop() {
2929
<span>-</span>
3030
</>
3131
)}
32-
<ValoraLink />
33-
<span>-</span>
3432
<ViewSourceLink />
33+
<span>-</span>
34+
<HelpButton styles={style.text} />
3535
</Box>
3636
<Box direction="row" align="center">
3737
<CopiableAddress address={address} length="full" styles={style.address} />

0 commit comments

Comments
 (0)