Files
cinny/src/app/hooks/useUserNotes.ts
T

49 lines
1.5 KiB
TypeScript
Raw Normal View History

import { useCallback } from 'react';
import { useMatrixClient } from './useMatrixClient';
import { createAccountDataListStore } from './createAccountDataListStore';
const NOTES_KEY = 'io.lotus.user_notes';
export const USER_NOTE_MAX_LENGTH = 500;
type UserNotesContent = Record<string, string>;
// Shared, concurrency-safe store. See createAccountDataListStore for why the
// snapshot + write queue must be module-scoped (writes are serialized to avoid
// lost updates, since setAccountData replaces the whole content with no merge).
//
// Notes are a flat Record<userId, note> rather than a wrapped list, so `read`
// and `write` pass the content through unchanged.
const notesStore = createAccountDataListStore<UserNotesContent, UserNotesContent>({
eventType: NOTES_KEY,
read: (content) => content ?? {},
write: (notes) => notes,
});
export function useUserNotes(): {
getNote: (userId: string) => string;
setNote: (userId: string, note: string) => Promise<void>;
} {
const mx = useMatrixClient();
const notes = notesStore.useValue(mx);
const getNote = useCallback((userId: string) => notes[userId] ?? '', [notes]);
const setNote = useCallback(
(userId: string, note: string) => {
const trimmed = note.trim().slice(0, USER_NOTE_MAX_LENGTH);
return notesStore.enqueueWrite(mx, (current) => {
const updated = { ...current };
if (trimmed) {
updated[userId] = trimmed;
} else {
delete updated[userId];
}
return updated;
});
},
[mx],
);
return { getNote, setNote };
}