import { CurrentUserMark, Mark } from '../types/mark.ts' import { hexToNpub } from './nostr.ts' import { Meta, SignedEventContent } from '../types' import { Event } from 'nostr-tools' /** * Takes in an array of Marks already filtered by User. * Returns an array of CurrentUserMarks with correct values mix-and-matched. * @param marks - default Marks extracted from Meta * @param signedMetaMarks - signed user Marks extracted from DocSignatures */ const getCurrentUserMarks = (marks: Mark[], signedMetaMarks: Mark[]): CurrentUserMark[] => { return marks.map((mark, index, arr) => { const signedMark = signedMetaMarks.find((m) => m.id === mark.id); if (signedMark && !!signedMark.value) { mark.value = signedMark.value } return { mark, isLast: isLast(index, arr), isCompleted: !!mark.value } }) } /** * Returns next incomplete CurrentUserMark if there is one * @param usersMarks */ const findNextCurrentUserMark = (usersMarks: CurrentUserMark[]): CurrentUserMark | undefined => { return usersMarks.find((mark) => !mark.isCompleted); } /** * Returns Marks that are assigned to a specific user * @param marks * @param pubkey */ const filterMarksByPubkey = (marks: Mark[], pubkey: string): Mark[] => { return marks.filter(mark => mark.npub === hexToNpub(pubkey)) } /** * Takes Signed Doc Signatures part of Meta and extracts * all Marks into one flar array, regardless of the user. * @param meta */ const extractMarksFromSignedMeta = (meta: Meta): Mark[] => { return Object.values(meta.docSignatures) .map((val: string) => JSON.parse(val as string)) .map((val: Event) => JSON.parse(val.content)) .flatMap((val: SignedEventContent) => val.marks) } /** * Checks the CurrentUserMarks array that every element in that array has been * marked as complete. * @param currentUserMarks */ const isCurrentUserMarksComplete = (currentUserMarks: CurrentUserMark[]): boolean => { return currentUserMarks.every((mark) => mark.isCompleted) } /** * Inserts an updated mark into an existing array of marks. Returns a copy of the * existing array with a new value inserted * @param marks * @param markToUpdate */ const updateMarks = (marks: Mark[], markToUpdate: Mark): Mark[] => { const indexToUpdate = marks.findIndex(mark => mark.id === markToUpdate.id); return [ ...marks.slice(0, indexToUpdate), markToUpdate, ...marks.slice(indexToUpdate + 1) ] } const updateCurrentUserMarks = (currentUserMarks: CurrentUserMark[], markToUpdate: CurrentUserMark): CurrentUserMark[] => { const indexToUpdate = currentUserMarks.findIndex((m) => m.mark.id === markToUpdate.mark.id) return [ ...currentUserMarks.slice(0, indexToUpdate), markToUpdate, ...currentUserMarks.slice(indexToUpdate + 1) ] } const isLast = (index: number, arr: any[]) => (index === (arr.length -1)) export { getCurrentUserMarks, filterMarksByPubkey, extractMarksFromSignedMeta, isCurrentUserMarksComplete, findNextCurrentUserMark, updateMarks, updateCurrentUserMarks, }