Commit 8230c266 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Determine most recent highlighted annotation by its updated date

parent 962f69eb
......@@ -187,6 +187,7 @@ export default function ThreadList({ threads }: ThreadListProps) {
const store = useSidebarStore();
const editing = store.countDrafts() > 0;
const highlightedAnnotations = store.highlightedAnnotations();
const allAnnotations = store.allAnnotations();
// Get the `$tag` of the most recently created unsaved annotation.
const newAnnotationTag = (() => {
......@@ -211,20 +212,32 @@ export default function ThreadList({ threads }: ThreadListProps) {
}
}, [store, newAnnotationTag]);
const mostRecentlyHighlightedAnnotationId = useMemo(
// If multiple highlighted annotations exist, assume that the last one in
// the list is the most recent.
() => highlightedAnnotations[highlightedAnnotations.length - 1],
[highlightedAnnotations],
const mostRecentHighlightedAnnotationId = useMemo(() => {
const highlightedAnnos = allAnnotations.filter(
anno => anno.id && highlightedAnnotations.includes(anno.id),
);
// Get the annotation with most recent updated field, which contains a
// date in ISO format. This means their alphabetical and chronological
// orders match.
const mostRecentHighlightedAnnotation =
highlightedAnnos.reduce<Annotation | null>(
(mostRecent, current) =>
!mostRecent || mostRecent.updated < current.updated
? current
: mostRecent,
null,
);
return mostRecentHighlightedAnnotation?.id;
}, [allAnnotations, highlightedAnnotations]);
// Scroll to the most recently highlighted annotation, unless creating/editing
// another annotation
useEffect(() => {
if (!editing && mostRecentlyHighlightedAnnotationId) {
setScrollToId(mostRecentlyHighlightedAnnotationId);
if (!editing && mostRecentHighlightedAnnotationId) {
setScrollToId(mostRecentHighlightedAnnotationId);
}
}, [editing, mostRecentlyHighlightedAnnotationId]);
}, [editing, mostRecentHighlightedAnnotationId]);
// Effect to scroll a particular thread into view. This is mainly used to
// scroll a newly created annotation into view.
......
......@@ -57,6 +57,7 @@ describe('ThreadList', () => {
unsavedAnnotations: sinon.stub().returns([]),
countDrafts: sinon.stub().returns(0),
highlightedAnnotations: sinon.stub().returns([]),
allAnnotations: sinon.stub().returns([]),
};
fakeTopThread = {
......@@ -193,13 +194,65 @@ describe('ThreadList', () => {
assert.notCalled(fakeScrollTop);
});
it('should set the scroll container `scrollTop` to first highlighted annotation', () => {
fakeStore.highlightedAnnotations.returns(['t2', 't3']);
[
{
annotationUpdates: {
t2: '2024-01-01T10:40:00',
t3: '2024-01-01T10:41:00', // Most recent
t4: '2024-01-01T10:39:00',
},
// The most recent highlighted annotation is the third.
// At default height (200) should be at 400px.
expectedScrollTop: 400,
},
{
annotationUpdates: {
t1: '2024-01-01T10:42:00', // Most recent
t3: '2024-01-01T10:39:00',
t4: '2024-01-01T10:39:00',
},
// The most recent highlighted annotation is the first.
// At default height (200) should be at 0px.
expectedScrollTop: 0,
},
{
annotationUpdates: {
t1: '2024-01-01T10:42:00',
t3: '2024-01-01T10:39:00',
t4: '2024-01-01T10:51:00', // Most recent
},
// The most recent highlighted annotation is the fourth.
// At default height (200) should be at 600px.
expectedScrollTop: 600,
},
{
annotationUpdates: {
t1: '2024-01-01T10:42:00',
t3: '2024-01-01T10:39:00',
t2: '2024-01-01T10:51:00', // Most recent
},
// The most recent highlighted annotation is the second.
// At default height (200) should be at 200px.
expectedScrollTop: 200,
},
].forEach(({ annotationUpdates, expectedScrollTop }) => {
it('should set the scroll container `scrollTop` to most recent highlighted annotation', () => {
fakeStore.highlightedAnnotations.returns(
Object.keys(annotationUpdates),
);
fakeStore.allAnnotations.returns([
{}, // Discarded
{ id: 't1', updated: annotationUpdates.t1 },
{ id: 't2', updated: annotationUpdates.t2 },
{ id: 't3', updated: annotationUpdates.t3 },
{ id: 't4', updated: annotationUpdates.t4 },
{ id: 't5', updated: annotationUpdates.t5 },
]);
createComponent();
// The last highlighted annotation is the third in the collection of
// threads. At default height (200) should be at 400px.
assert.calledWith(fakeScrollTop, 400);
assert.calledWith(fakeScrollTop, expectedScrollTop);
});
});
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment