Skip to content

Commit 9e88aba

Browse files
authored
prevent re-renders in the app provider (#145)
1 parent 3ca1f1f commit 9e88aba

File tree

2 files changed

+212
-176
lines changed

2 files changed

+212
-176
lines changed

packages/hypergraph-react/src/HypergraphAppContext.tsx

Lines changed: 174 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -125,41 +125,44 @@ export function HypergraphAppProvider({
125125
const sessionToken = useSelectorStore(store, (state) => state.context.sessionToken);
126126
const keys = useSelectorStore(store, (state) => state.context.keys);
127127

128-
async function login(signer: Identity.Signer) {
129-
if (!signer) {
130-
return;
131-
}
132-
const address = await signer.getAddress();
133-
if (!address) {
134-
return;
135-
}
136-
const accountId = getAddress(address);
137-
const keys = Identity.loadKeys(storage, accountId);
138-
let authData: {
139-
accountId: Address;
140-
sessionToken: string;
141-
keys: Identity.IdentityKeys;
142-
};
143-
const location = {
144-
host: window.location.host,
145-
origin: window.location.origin,
146-
};
147-
if (!keys && !(await Identity.identityExists(accountId, syncServerUri))) {
148-
authData = await Identity.signup(signer, accountId, syncServerUri, chainId, storage, location);
149-
} else if (keys) {
150-
authData = await Identity.loginWithKeys(keys, accountId, syncServerUri, chainId, storage, location);
151-
} else {
152-
authData = await Identity.loginWithWallet(signer, accountId, syncServerUri, chainId, storage, location);
153-
}
154-
console.log('Identity initialized');
155-
store.send({
156-
...authData,
157-
type: 'setAuth',
158-
});
159-
store.send({ type: 'reset' });
160-
}
128+
const login = useCallback(
129+
async (signer: Identity.Signer) => {
130+
if (!signer) {
131+
return;
132+
}
133+
const address = await signer.getAddress();
134+
if (!address) {
135+
return;
136+
}
137+
const accountId = getAddress(address);
138+
const keys = Identity.loadKeys(storage, accountId);
139+
let authData: {
140+
accountId: Address;
141+
sessionToken: string;
142+
keys: Identity.IdentityKeys;
143+
};
144+
const location = {
145+
host: window.location.host,
146+
origin: window.location.origin,
147+
};
148+
if (!keys && !(await Identity.identityExists(accountId, syncServerUri))) {
149+
authData = await Identity.signup(signer, accountId, syncServerUri, chainId, storage, location);
150+
} else if (keys) {
151+
authData = await Identity.loginWithKeys(keys, accountId, syncServerUri, chainId, storage, location);
152+
} else {
153+
authData = await Identity.loginWithWallet(signer, accountId, syncServerUri, chainId, storage, location);
154+
}
155+
console.log('Identity initialized');
156+
store.send({
157+
...authData,
158+
type: 'setAuth',
159+
});
160+
store.send({ type: 'reset' });
161+
},
162+
[storage, syncServerUri, chainId],
163+
);
161164

162-
function logout() {
165+
const logout = useCallback(() => {
163166
websocketConnection?.close();
164167
setWebsocketConnection(undefined);
165168

@@ -171,7 +174,7 @@ export function HypergraphAppProvider({
171174
Identity.wipeKeys(storage, accountIdToLogout);
172175
Identity.wipeSyncServerSessionToken(storage, accountIdToLogout);
173176
store.send({ type: 'resetAuth' });
174-
}
177+
}, [accountId, storage, websocketConnection]);
175178

176179
const setIdentityAndSessionToken = useCallback(
177180
(account: Identity.Identity & { sessionToken: string }) => {
@@ -508,7 +511,7 @@ export function HypergraphAppProvider({
508511
};
509512
}, [websocketConnection, spaces, accountId, keys?.encryptionPrivateKey, keys?.signaturePrivateKey, syncServerUri]);
510513

511-
const createSpaceForContext = async () => {
514+
const createSpaceForContext = useCallback(async () => {
512515
if (!accountId) {
513516
throw new Error('No account id found');
514517
}
@@ -547,7 +550,14 @@ export function HypergraphAppProvider({
547550
},
548551
} as const satisfies Messages.RequestCreateSpaceEvent;
549552
websocketConnection?.send(Messages.serialize(message));
550-
};
553+
}, [
554+
accountId,
555+
keys?.encryptionPrivateKey,
556+
keys?.encryptionPublicKey,
557+
keys?.signaturePrivateKey,
558+
keys?.signaturePublicKey,
559+
websocketConnection,
560+
]);
551561

552562
const listSpaces = useCallback(() => {
553563
const message: Messages.RequestListSpaces = { type: 'list-spaces' };
@@ -559,49 +569,59 @@ export function HypergraphAppProvider({
559569
websocketConnection?.send(Messages.serialize(message));
560570
}, [websocketConnection]);
561571

562-
const acceptInvitationForContext = async ({
563-
invitation,
564-
}: Readonly<{
565-
invitation: Messages.Invitation;
566-
}>) => {
567-
if (!accountId) {
568-
throw new Error('No account id found');
569-
}
570-
const encryptionPrivateKey = keys?.encryptionPrivateKey;
571-
const encryptionPublicKey = keys?.encryptionPublicKey;
572-
const signaturePrivateKey = keys?.signaturePrivateKey;
573-
const signaturePublicKey = keys?.signaturePublicKey;
574-
if (!encryptionPrivateKey || !encryptionPublicKey || !signaturePrivateKey || !signaturePublicKey) {
575-
throw new Error('Missing keys');
576-
}
577-
const spaceEvent = await Effect.runPromiseExit(
578-
SpaceEvents.acceptInvitation({
579-
author: {
580-
accountId,
581-
signaturePublicKey,
582-
encryptionPublicKey,
583-
signaturePrivateKey,
584-
},
585-
previousEventHash: invitation.previousEventHash,
586-
}),
587-
);
588-
if (Exit.isFailure(spaceEvent)) {
589-
console.error('Failed to accept invitation', spaceEvent);
590-
return;
591-
}
592-
const message: Messages.RequestAcceptInvitationEvent = {
593-
type: 'accept-invitation-event',
594-
event: spaceEvent.value,
595-
spaceId: invitation.spaceId,
596-
};
597-
websocketConnection?.send(Messages.serialize(message));
572+
const acceptInvitationForContext = useCallback(
573+
async ({
574+
invitation,
575+
}: Readonly<{
576+
invitation: Messages.Invitation;
577+
}>) => {
578+
if (!accountId) {
579+
throw new Error('No account id found');
580+
}
581+
const encryptionPrivateKey = keys?.encryptionPrivateKey;
582+
const encryptionPublicKey = keys?.encryptionPublicKey;
583+
const signaturePrivateKey = keys?.signaturePrivateKey;
584+
const signaturePublicKey = keys?.signaturePublicKey;
585+
if (!encryptionPrivateKey || !encryptionPublicKey || !signaturePrivateKey || !signaturePublicKey) {
586+
throw new Error('Missing keys');
587+
}
588+
const spaceEvent = await Effect.runPromiseExit(
589+
SpaceEvents.acceptInvitation({
590+
author: {
591+
accountId,
592+
signaturePublicKey,
593+
encryptionPublicKey,
594+
signaturePrivateKey,
595+
},
596+
previousEventHash: invitation.previousEventHash,
597+
}),
598+
);
599+
if (Exit.isFailure(spaceEvent)) {
600+
console.error('Failed to accept invitation', spaceEvent);
601+
return;
602+
}
603+
const message: Messages.RequestAcceptInvitationEvent = {
604+
type: 'accept-invitation-event',
605+
event: spaceEvent.value,
606+
spaceId: invitation.spaceId,
607+
};
608+
websocketConnection?.send(Messages.serialize(message));
598609

599-
// temporary until we have define a strategy for accepting invitations response
600-
setTimeout(() => {
601-
const message2: Messages.RequestListInvitations = { type: 'list-invitations' };
602-
websocketConnection?.send(Messages.serialize(message2));
603-
}, 1000);
604-
};
610+
// temporary until we have define a strategy for accepting invitations response
611+
setTimeout(() => {
612+
const message2: Messages.RequestListInvitations = { type: 'list-invitations' };
613+
websocketConnection?.send(Messages.serialize(message2));
614+
}, 1000);
615+
},
616+
[
617+
accountId,
618+
keys?.encryptionPrivateKey,
619+
keys?.encryptionPublicKey,
620+
keys?.signaturePrivateKey,
621+
keys?.signaturePublicKey,
622+
websocketConnection,
623+
],
624+
);
605625

606626
const subscribeToSpace = useCallback(
607627
(params: { spaceId: string }) => {
@@ -611,73 +631,84 @@ export function HypergraphAppProvider({
611631
[websocketConnection],
612632
);
613633

614-
const inviteToSpace = async ({
615-
space,
616-
invitee,
617-
}: Readonly<{
618-
space: SpaceStorageEntry;
619-
invitee: {
620-
accountId: string;
621-
};
622-
}>) => {
623-
if (!accountId) {
624-
throw new Error('No account id found');
625-
}
626-
const encryptionPrivateKey = keys?.encryptionPrivateKey;
627-
const encryptionPublicKey = keys?.encryptionPublicKey;
628-
const signaturePrivateKey = keys?.signaturePrivateKey;
629-
const signaturePublicKey = keys?.signaturePublicKey;
630-
if (!encryptionPrivateKey || !encryptionPublicKey || !signaturePrivateKey || !signaturePublicKey) {
631-
throw new Error('Missing keys');
632-
}
633-
if (!encryptionPrivateKey || !encryptionPublicKey || !signaturePrivateKey || !signaturePublicKey) {
634-
throw new Error('Missing keys');
635-
}
636-
if (!space.state) {
637-
console.error('No state found for space');
638-
return;
639-
}
640-
const inviteeWithKeys = await Identity.getVerifiedIdentity(invitee.accountId, syncServerUri);
641-
const spaceEvent = await Effect.runPromiseExit(
642-
SpaceEvents.createInvitation({
643-
author: {
644-
accountId,
645-
signaturePublicKey,
646-
encryptionPublicKey,
647-
signaturePrivateKey,
648-
},
649-
previousEventHash: space.state.lastEventHash,
650-
invitee: inviteeWithKeys,
651-
}),
652-
);
653-
if (Exit.isFailure(spaceEvent)) {
654-
console.error('Failed to create invitation', spaceEvent);
655-
return;
656-
}
634+
const inviteToSpace = useCallback(
635+
async ({
636+
space,
637+
invitee,
638+
}: Readonly<{
639+
space: SpaceStorageEntry;
640+
invitee: {
641+
accountId: string;
642+
};
643+
}>) => {
644+
if (!accountId) {
645+
throw new Error('No account id found');
646+
}
647+
const encryptionPrivateKey = keys?.encryptionPrivateKey;
648+
const encryptionPublicKey = keys?.encryptionPublicKey;
649+
const signaturePrivateKey = keys?.signaturePrivateKey;
650+
const signaturePublicKey = keys?.signaturePublicKey;
651+
if (!encryptionPrivateKey || !encryptionPublicKey || !signaturePrivateKey || !signaturePublicKey) {
652+
throw new Error('Missing keys');
653+
}
654+
if (!encryptionPrivateKey || !encryptionPublicKey || !signaturePrivateKey || !signaturePublicKey) {
655+
throw new Error('Missing keys');
656+
}
657+
if (!space.state) {
658+
console.error('No state found for space');
659+
return;
660+
}
661+
const inviteeWithKeys = await Identity.getVerifiedIdentity(invitee.accountId, syncServerUri);
662+
const spaceEvent = await Effect.runPromiseExit(
663+
SpaceEvents.createInvitation({
664+
author: {
665+
accountId,
666+
signaturePublicKey,
667+
encryptionPublicKey,
668+
signaturePrivateKey,
669+
},
670+
previousEventHash: space.state.lastEventHash,
671+
invitee: inviteeWithKeys,
672+
}),
673+
);
674+
if (Exit.isFailure(spaceEvent)) {
675+
console.error('Failed to create invitation', spaceEvent);
676+
return;
677+
}
657678

658-
const keyBoxes = space.keys.map((key) => {
659-
const keyBox = Key.encryptKey({
660-
key: Utils.hexToBytes(key.key),
661-
publicKey: Utils.hexToBytes(inviteeWithKeys.encryptionPublicKey),
662-
privateKey: Utils.hexToBytes(encryptionPrivateKey),
679+
const keyBoxes = space.keys.map((key) => {
680+
const keyBox = Key.encryptKey({
681+
key: Utils.hexToBytes(key.key),
682+
publicKey: Utils.hexToBytes(inviteeWithKeys.encryptionPublicKey),
683+
privateKey: Utils.hexToBytes(encryptionPrivateKey),
684+
});
685+
return {
686+
id: key.id,
687+
ciphertext: Utils.bytesToHex(keyBox.keyBoxCiphertext),
688+
nonce: Utils.bytesToHex(keyBox.keyBoxNonce),
689+
authorPublicKey: encryptionPublicKey,
690+
accountId: invitee.accountId,
691+
};
663692
});
664-
return {
665-
id: key.id,
666-
ciphertext: Utils.bytesToHex(keyBox.keyBoxCiphertext),
667-
nonce: Utils.bytesToHex(keyBox.keyBoxNonce),
668-
authorPublicKey: encryptionPublicKey,
669-
accountId: invitee.accountId,
670-
};
671-
});
672693

673-
const message: Messages.RequestCreateInvitationEvent = {
674-
type: 'create-invitation-event',
675-
event: spaceEvent.value,
676-
spaceId: space.id,
677-
keyBoxes,
678-
};
679-
websocketConnection?.send(Messages.serialize(message));
680-
};
694+
const message: Messages.RequestCreateInvitationEvent = {
695+
type: 'create-invitation-event',
696+
event: spaceEvent.value,
697+
spaceId: space.id,
698+
keyBoxes,
699+
};
700+
websocketConnection?.send(Messages.serialize(message));
701+
},
702+
[
703+
accountId,
704+
keys?.encryptionPrivateKey,
705+
keys?.encryptionPublicKey,
706+
keys?.signaturePrivateKey,
707+
keys?.signaturePublicKey,
708+
websocketConnection,
709+
syncServerUri,
710+
],
711+
);
681712

682713
const getVerifiedIdentity = useCallback(
683714
(accountId: string) => {

0 commit comments

Comments
 (0)