feat: add handwritten cues to text exhibits

This commit is contained in:
2026-08-14 18:30:31 +02:00
parent b39d2efa75
commit ffa81284df
4 changed files with 24 additions and 5 deletions
+10 -2
View File
@@ -69,7 +69,7 @@ export function exhibitWidget(type: EvidenceType) {
return exhibitWidgetRegistry[type] || exhibitWidgetRegistry.note
}
type DocumentWidgetProps = { document: CaseDocument; source: string }
type DocumentWidgetProps = { document: CaseDocument; source: string; onMemoryCue?: (cue: string) => void }
export type DocumentWidgetDefinition = {
label: string
Preview: ComponentType<DocumentWidgetProps>
@@ -82,6 +82,14 @@ function ImagePreview({ document, source }: DocumentWidgetProps) {
function GenericPreview({ document }: DocumentWidgetProps) {
return <div><ImageIcon size={35}/><small>{document.kind}</small></div>
}
function TextPreview({ document, onMemoryCue }: DocumentWidgetProps) {
const excerpt = document.body.filter(Boolean).slice(0, 2).join(' ')
return <div className="text-document-preview">
<p className="text-source-excerpt">{excerpt || document.title}</p>
<textarea aria-label={`Memory cue for ${document.title}`} maxLength={48} placeholder="WRITE A MEMORY CUE…" value={document.metadata.memory_cue || ''}
onPointerDown={event => event.stopPropagation()} onClick={event => event.stopPropagation()} onDoubleClick={event => event.stopPropagation()} onChange={event => onMemoryCue?.(event.target.value)}/>
</div>
}
function ImageAsset({ document, source }: DocumentWidgetProps) {
return <img className="document-image" src={source} alt={document.fileName || document.title}/>
}
@@ -96,7 +104,7 @@ const genericDocument = (label: string): DocumentWidgetDefinition => ({ label, P
export const documentWidgetRegistry: Record<SourceFileType, DocumentWidgetDefinition> = {
image: { label: 'Image', Preview: ImagePreview, Asset: ImageAsset },
pdf: { label: 'PDF', Preview: GenericPreview, Asset: FrameAsset },
text: { label: 'Text document', Preview: GenericPreview, Asset: FrameAsset },
text: { label: 'Text document', Preview: TextPreview, Asset: FrameAsset },
web_capture: genericDocument('Web capture'),
email: genericDocument('Email'),
article: genericDocument('Article'),