sigit.io/src/utils/mark.ts

146 lines
3.9 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'
import { EMPTY } from './const.ts'
/**
* 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)
return {
mark,
currentValue: signedMark?.value ?? EMPTY,
id: index + 1,
isLast: isLast(index, arr),
isCompleted: !!signedMark?.value
}
})
}
/**
* Returns next incomplete CurrentUserMark if there is one
* @param usersMarks
*/
const findNextIncompleteCurrentUserMark = (
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
const isCurrentValueLast = (
currentUserMarks: CurrentUserMark[],
selectedMark: CurrentUserMark,
selectedMarkValue: string
) => {
const filteredMarks = currentUserMarks.filter(
(mark) => mark.id !== selectedMark.id
)
return (
isCurrentUserMarksComplete(filteredMarks) && selectedMarkValue.length > 0
)
}
const getUpdatedMark = (
selectedMark: CurrentUserMark,
selectedMarkValue: string
): CurrentUserMark => {
return {
...selectedMark,
currentValue: selectedMarkValue,
isCompleted: !!selectedMarkValue,
mark: {
...selectedMark.mark,
value: selectedMarkValue
}
}
}
const findOtherUserMarks = (marks: Mark[], pubkey: string): Mark[] => {
return marks.filter((mark) => mark.npub !== hexToNpub(pubkey))
}
export {
getCurrentUserMarks,
filterMarksByPubkey,
extractMarksFromSignedMeta,
isCurrentUserMarksComplete,
findNextIncompleteCurrentUserMark,
updateMarks,
updateCurrentUserMarks,
isCurrentValueLast,
getUpdatedMark,
findOtherUserMarks
}