Skip to content

Commit

Permalink
Dedupe contacts and prevent contacts with same address being created
Browse files Browse the repository at this point in the history
  • Loading branch information
dgca committed May 31, 2024
1 parent 4210a89 commit 81983c2
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 44 deletions.
136 changes: 93 additions & 43 deletions main/api/contacts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,98 @@ const schema: Schema<{
},
};

export const store = new Store({ schema, name: "contacts" });
class ContactsUtil {
store = new Store({ schema, name: "contacts" });
contactsByAddress: Map<string, Contact> = new Map();

constructor() {
this.init();
}

init() {
const contacts = this.store.get("contacts", []);
const deduped = contacts.filter((contact) => {
if (this.contactsByAddress.has(contact.address)) {
return false;
}
this.contactsByAddress.set(contact.address, contact);
return true;
});
this.store.set("contacts", deduped);
}

getContacts() {
return this.store.get("contacts", []);
}

getContactByAddress(address: string) {
return this.contactsByAddress.get(address) ?? null;
}

addContact({ name, address }: { name: string; address: string }) {
if (this.contactsByAddress.has(address)) {
throw new Error("DUPLICATE_CONTACT_ERROR");
}

const contacts = this.getContacts();

contacts.push({
id: uuidv4(),
name,
address,
order: contacts.length,
});

this.store.set("contacts", contacts);

return contacts;
}

editContact({
id,
name,
address,
}: {
id: string;
name: string;
address: string;
}) {
const contacts = this.getContacts();
const index = contacts.findIndex((contact) => contact.id === id);

if (index > -1) {
contacts[index] = {
id,
name,
address,
order: contacts[index].order,
};
this.store.set("contacts", contacts);
}

return contacts;
}

deleteContact(id: string) {
const contacts = this.getContacts();
const index = contacts.findIndex((contact) => contact.id === id);

if (index > -1) {
const contact = contacts[index];
this.contactsByAddress.delete(contact.address);
contacts.splice(index, 1);
this.store.set("contacts", contacts);
}

return contacts;
}
}

const contactsUtil = new ContactsUtil();

export const contactsRouter = t.router({
getContacts: t.procedure.query(async () => {
return store.get("contacts", []);
return contactsUtil.getContacts();
}),
getContactByAddress: t.procedure
.input(
Expand All @@ -47,11 +134,7 @@ export const contactsRouter = t.router({
}),
)
.query(async (opts) => {
const contacts = store.get("contacts", []);
return (
contacts.find((contact) => contact.address === opts.input.address) ??
null
);
return contactsUtil.getContactByAddress(opts.input.address);
}),
addContact: t.procedure
.input(
Expand All @@ -61,15 +144,7 @@ export const contactsRouter = t.router({
}),
)
.mutation(async (opts) => {
const contacts = store.get("contacts", []);
contacts.push({
id: uuidv4(),
name: opts.input.name,
address: opts.input.address,
order: contacts.length,
});
store.set("contacts", contacts);
return contacts;
return contactsUtil.addContact(opts.input);
}),
editContact: t.procedure
.input(
Expand All @@ -80,22 +155,7 @@ export const contactsRouter = t.router({
}),
)
.mutation(async (opts) => {
const contacts = store.get("contacts", []);
const index = contacts.findIndex(
(contact) => contact.id === opts.input.id,
);

if (index > -1) {
contacts[index] = {
id: opts.input.id,
name: opts.input.name,
address: opts.input.address,
order: contacts[index].order,
};
store.set("contacts", contacts);
}

return contacts;
return contactsUtil.editContact(opts.input);
}),
deleteContact: t.procedure
.input(
Expand All @@ -104,16 +164,6 @@ export const contactsRouter = t.router({
}),
)
.mutation(async (opts) => {
const contacts = store.get("contacts", []);
const index = contacts.findIndex(
(contact) => contact.id === opts.input.id,
);

if (index > -1) {
contacts.splice(index, 1);
store.set("contacts", contacts);
}

return contacts;
return contactsUtil.deleteContact(opts.input.id);
}),
});
10 changes: 9 additions & 1 deletion renderer/components/AddContactModal/AddContactModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ const messages = defineMessages({
address: {
defaultMessage: "Address",
},
duplicateContactError: {
defaultMessage: "A contact with that address already exists.",
},
});

type Props = {
Expand Down Expand Up @@ -83,6 +86,7 @@ export function AddContactModal({ isOpen, onClose }: Props) {
isError,
isSuccess,
reset: resetMutation,
error,
} = trpcReact.addContact.useMutation();

const {
Expand Down Expand Up @@ -150,7 +154,11 @@ export function AddContactModal({ isOpen, onClose }: Props) {
{formatMessage(messages.addContactError)}
</Heading>
<Text fontSize="md">
{formatMessage(messages.somethingWentWrong)}
{formatMessage(
error.message === "DUPLICATE_CONTACT_ERROR"
? messages.duplicateContactError
: messages.somethingWentWrong,
)}
</Text>
</>
)}
Expand Down
3 changes: 3 additions & 0 deletions renderer/intl/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,9 @@
"X+BJ/8": {
"message": "Other Assets"
},
"XIdw3B": {
"message": "A contact with that address already exists."
},
"XLvNHQ": {
"message": "Please write down this recovery phrase and keep it in a safe place. You will need it to recover your account."
},
Expand Down

0 comments on commit 81983c2

Please sign in to comment.