sigit.io/src/utils/mark.ts

99 lines
3.0 KiB
TypeScript
Raw Normal View History

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 = <T>(index: number, arr: T[]) => (index === (arr.length -1))
export {
getCurrentUserMarks,
filterMarksByPubkey,
extractMarksFromSignedMeta,
isCurrentUserMarksComplete,
findNextCurrentUserMark,
updateMarks,
updateCurrentUserMarks,
}