Skip to content

Commit

Permalink
Merge pull request #6 from nikgraf/store-document-name
Browse files Browse the repository at this point in the history
store document name
  • Loading branch information
nikgraf committed Jun 6, 2024
2 parents abd2222 + 99c5101 commit ee05595
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 23 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,17 @@ TODO better version where the token is also never exposed to the network so not

## Todos

- allow to delete list (needs a tombstone)
- deploy to production
- invitation links should expire after 2 days
- UI for invitations links

- figure out how author keys are managed (tabs in serenity and possible change in secsync)
- add retry for locker in case write fails (invalid clock)
- store the list name locally (also with unsynced changes)
- use expo-secure-store for the sessionKey
- encrypt MMKV storage on iOS and Android

- allow to delete list (needs a tombstone and properly cleanup local stores)
- allow to create lists locally

- allow to sync lists in the background
- fix websocket session auth in secsync
31 changes: 20 additions & 11 deletions apps/app/src/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CreateListForm } from "../components/createListForm";
import { Logout } from "../components/logout";
import { useLocker } from "../hooks/useLocker";
import { decryptString } from "../utils/decryptString";
import { documentNameStorage } from "../utils/documentStorage";
import { trpc } from "../utils/trpc";

const Lists: React.FC = () => {
Expand All @@ -27,6 +28,12 @@ const Lists: React.FC = () => {
const documentsQuery = trpc.documents.useQuery(undefined, {
refetchInterval: 5000,
});
let keys = documentNameStorage.getAllKeys();
if (documentsQuery.data) {
const remoteDocumentIds = documentsQuery.data.map((doc) => doc.id);
// merge remote and local keys and deduplicate them
keys = Array.from(new Set([...keys, ...remoteDocumentIds]));
}

return (
<View>
Expand All @@ -44,23 +51,25 @@ const Lists: React.FC = () => {
<CreateListForm />

<View className="flex flex-col gap-2 pt-4">
{documentsQuery.data?.map((doc) => {
if (!locker.content[`document:${doc.id}`]) {
{keys.map((docId) => {
if (!locker.content[`document:${docId}`]) {
return null;
}
const documentKey = sodium.from_base64(
locker.content[`document:${doc.id}`]
locker.content[`document:${docId}`]
);

const name = decryptString({
ciphertext: doc.nameCiphertext,
commitment: doc.nameCommitment,
nonce: doc.nameNonce,
key: documentKey,
});
const doc = documentsQuery.data?.find((doc) => doc.id === docId);
const name = doc
? decryptString({
ciphertext: doc.nameCiphertext,
commitment: doc.nameCommitment,
nonce: doc.nameNonce,
key: documentKey,
})
: documentNameStorage.getString(docId);

return (
<Link href={`/list/${doc.id}`} key={doc.id} asChild>
<Link href={`/list/${docId}`} key={docId} asChild>
<Card className="flex flex-col items-start gap-2 rounded-lg border p-5 text-left text-xl transition-all hover:bg-accent">
<Text>{name}</Text>
</Card>
Expand Down
2 changes: 2 additions & 0 deletions apps/app/src/components/createListForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { generateId } from "secsync";
import { Button } from "~/components/ui/button";
import { Text } from "~/components/ui/text";
import { useLocker } from "../hooks/useLocker";
import { documentNameStorage } from "../utils/documentStorage";
import { encryptString } from "../utils/encryptString";
import { trpc } from "../utils/trpc";

Expand Down Expand Up @@ -57,6 +58,7 @@ export const CreateListForm: React.FC = () => {
documentId: document.id,
value: sodium.to_base64(key),
});
documentNameStorage.set(document.id, "");

router.navigate({
pathname: `/list/[documentId]`,
Expand Down
32 changes: 22 additions & 10 deletions apps/app/src/components/updateDocumentNameForm.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useQueryClient } from "@tanstack/react-query";
import { getQueryKey } from "@trpc/react-query";
import { useEffect, useState } from "react";
import { View } from "react-native";
import { Alert, View } from "react-native";
import { Input } from "~/components/ui/input";
import { decryptString } from "../utils/decryptString";
import { documentNameStorage } from "../utils/documentStorage";
import { encryptString } from "../utils/encryptString";
import { trpc } from "../utils/trpc";

Expand All @@ -13,9 +14,13 @@ type Props = {
};

export const UpdateDocumentNameForm = ({ documentId, documentKey }: Props) => {
const [name, setName] = useState("");
const [name, setName] = useState(() => {
return documentNameStorage.getString(documentId) || "";
});

const getDocumentQuery = trpc.getDocument.useQuery(documentId);
const getDocumentQuery = trpc.getDocument.useQuery(documentId, {
refetchInterval: 5000,
});
const updateDocumentMutation = trpc.updateDocument.useMutation();
const queryClient = useQueryClient();

Expand All @@ -33,16 +38,24 @@ export const UpdateDocumentNameForm = ({ documentId, documentKey }: Props) => {
}, [getDocumentQuery.data?.nameCiphertext]);

const updateName = async (name: string) => {
documentNameStorage.set(documentId, name);
const { ciphertext, nonce, commitment } = encryptString({
value: name,
key: documentKey,
});
updateDocumentMutation.mutate({
id: documentId,
nameCiphertext: ciphertext,
nameNonce: nonce,
nameCommitment: commitment,
});
updateDocumentMutation.mutate(
{
id: documentId,
nameCiphertext: ciphertext,
nameNonce: nonce,
nameCommitment: commitment,
},
{
onError: () => {
Alert.alert("Failed to update the list name on the server.");
},
}
);
const documentsQueryKey = getQueryKey(trpc.documents, undefined, "query");
queryClient.invalidateQueries({
queryKey: [documentsQueryKey],
Expand All @@ -52,7 +65,6 @@ export const UpdateDocumentNameForm = ({ documentId, documentKey }: Props) => {
return (
<View>
<Input
// required TODO
className="border border-slate-300 p-2 rounded"
placeholder="List name"
autoComplete="off"
Expand Down
4 changes: 4 additions & 0 deletions apps/app/src/utils/documentStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ export const documentStorage = new MMKV({
id: `document-storage`,
});

export const documentNameStorage = new MMKV({
id: `document-name-storage`,
});

export const documentPendingChangesStorage = new MMKV({
id: `document-pending-changes-storage`,
});

0 comments on commit ee05595

Please sign in to comment.