Skip to content

Commit

Permalink
feat: moved container to be based on useEffect()
Browse files Browse the repository at this point in the history
  • Loading branch information
JesseLiii committed Jul 23, 2024
1 parent a93e5e2 commit 139e2f6
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 46 deletions.
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "^1.0.0",
"lodash": "^4.17.21",
"lucide-react": "^0.365.0",
"rangy": "^1.3.1",
"react": "^18.2.0",
Expand All @@ -31,6 +32,7 @@
"devDependencies": {
"@crxjs/vite-plugin": "^2.0.0-beta.23",
"@types/chrome": "^0.0.266",
"@types/lodash": "^4.17.7",
"@types/node": "^20.12.4",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
Expand Down
100 changes: 54 additions & 46 deletions src/scripts/highlighter/HighlighterApp.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';

import ActionBar from '@/scripts/highlighter/components/ActionBar/ActionBar';
import { Highlight } from '@/scripts/highlighter/components/Highlight';
Expand All @@ -10,6 +10,7 @@ import {
getMarkerPosition,
getSelectedText,
} from '@/scripts/highlighter/utils/markerUtils';
import { isEqual } from 'lodash';

const HighlighterApp = () => {
const initialHighlights: { [key: string]: HighlightData } = {};
Expand All @@ -25,6 +26,8 @@ const HighlighterApp = () => {
}[];
}>({});

const prevHighlightsRef = useRef<typeof highlights>({});

const [markerPosition, setMarkerPosition] = useState<
MarkerPosition | { display: 'none' }
>({ display: 'none' });
Expand Down Expand Up @@ -57,27 +60,52 @@ const HighlighterApp = () => {
};
}, []);

useEffect(() => {
const newContainers: typeof highlightContainers = {
...highlightContainers,
};
let hasChanges = false;

Object.entries(highlights).forEach(([uuid, highlightData]) => {
const prevHighlight = prevHighlightsRef.current[uuid];
if (
!prevHighlight ||
!isEqual(prevHighlight.matching, highlightData.matching)
) {
const containers = createHighlightElement(highlightData);
if (containers) {
newContainers[uuid] = containers.map((range) => ({
range,
uuid,
}));
hasChanges = true;
}
}
});

// Remove containers for deleted highlights
Object.keys(highlightContainers).forEach((uuid) => {
if (!highlights[uuid]) {
delete newContainers[uuid];
hasChanges = true;
}
});

if (hasChanges) {
setHighlightContainers(newContainers);
}

prevHighlightsRef.current = highlights;
}, [highlights]);

const handleEditHighlight = (highlightData: HighlightData) => {
setHighlights((prevHighlights) => ({
...prevHighlights,
[highlightData.uuid]: highlightData,
}));
// setHighlightContainers((prev) => {
// const newMap = new Map(prev);
// if (newMap.has(highlightData.uuid)) {
// const container = newMap.get(highlightData.uuid);
// if (container) {
// newMap.set(highlightData.uuid, {
// ...container,
// highlightData,
// });
// }
// }
// return newMap;
// });
};

const handleHighlight = (openNotes: boolean = false) => {
const handleHighlight = () => {
const userSelection = window.getSelection();
if (userSelection) {
const highlightData = extractHighlightData(userSelection);
Expand All @@ -86,29 +114,23 @@ const HighlighterApp = () => {
...highlights,
[highlightData.uuid]: highlightData,
});
const containers = createHighlightElement(highlightData);
setHighlightContainers((prev) => {
const newContainers = { ...prev };
if (!newContainers[highlightData.uuid]) {
newContainers[highlightData.uuid] = [];
}
containers?.forEach((range, index) => {
newContainers[highlightData.uuid].push({
range: range,
uuid: highlightData.uuid,
notesOpen:
openNotes && index === containers.length - 1, // Open notes for the first container if openNotes is true
});
});
return newContainers;
});
}
window.getSelection()?.empty();
}
};

const handleAddNote = () => {
handleHighlight(true); // Pass true to open notes for the new highlight
const userSelection = window.getSelection();
if (userSelection) {
const highlightData = extractHighlightData(userSelection);
if (highlightData) {
setHighlights({
...highlights,
[highlightData.uuid]: highlightData,
});
}
window.getSelection()?.empty();
}
};

const handleClose = () => {
Expand All @@ -124,20 +146,6 @@ const HighlighterApp = () => {
...prevHighlights,
[highlightData.uuid]: { ...highlightData, rating },
}));
const containers = createHighlightElement(highlightData);
setHighlightContainers((prev) => {
const newContainers = { ...prev };
if (!newContainers[highlightData.uuid]) {
newContainers[highlightData.uuid] = [];
}
containers?.forEach((range) => {
newContainers[highlightData.uuid].push({
range: range,
uuid: highlightData.uuid,
});
});
return newContainers;
});
}
window.getSelection()?.empty();
}
Expand Down
103 changes: 103 additions & 0 deletions src/scripts/highlighter/utils/createHighlight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,106 @@ const createHighlight = {
};

export const createHighlightElement = createHighlight[strategy];

export const checkOverlap = (
existing: HighlightData,
newHighlight: HighlightData
): boolean => {
const existingStart = existing.matching.textPosition.start;
const existingEnd = existing.matching.textPosition.end;
const newStart = newHighlight.matching.textPosition.start;
const newEnd = newHighlight.matching.textPosition.end;

return (
(newStart >= existingStart && newStart <= existingEnd) ||
(newEnd >= existingStart && newEnd <= existingEnd) ||
(newStart <= existingStart && newEnd >= existingEnd)
);
};

export const extendHighlight = (
existing: HighlightData,
newHighlight: HighlightData
): HighlightData => {
const start = Math.min(
existing.matching.textPosition.start,
newHighlight.matching.textPosition.start
);
const end = Math.max(
existing.matching.textPosition.end,
newHighlight.matching.textPosition.end
);

// Determine which highlight starts first
const [firstHighlight, secondHighlight] =
existing.matching.textPosition.start <
newHighlight.matching.textPosition.start
? [existing, newHighlight]
: [newHighlight, existing];

// Calculate the overlap
const overlapStart = Math.max(
firstHighlight.matching.textPosition.start,
secondHighlight.matching.textPosition.start
);
const overlapEnd = Math.min(
firstHighlight.matching.textPosition.end,
secondHighlight.matching.textPosition.end
);

// Construct the merged body
let mergedBody = firstHighlight.matching.body;

if (overlapStart > firstHighlight.matching.textPosition.start) {
// If there's non-overlapping content at the start of the second highlight
mergedBody += secondHighlight.matching.body.slice(
0,
overlapStart - secondHighlight.matching.textPosition.start
);
}

if (overlapEnd < secondHighlight.matching.textPosition.end) {
// If there's non-overlapping content at the end of the second highlight
mergedBody += secondHighlight.matching.body.slice(
overlapEnd - secondHighlight.matching.textPosition.start
);
}

return {
...existing,
matching: {
...existing.matching,
body: mergedBody,
textPosition: { start, end },
rangeSelector: {
startOffset: Math.min(
existing.matching.rangeSelector.startOffset,
newHighlight.matching.rangeSelector.startOffset
),
endOffset: Math.max(
existing.matching.rangeSelector.endOffset,
newHighlight.matching.rangeSelector.endOffset
),
startContainer:
start === existing.matching.textPosition.start
? existing.matching.rangeSelector.startContainer
: newHighlight.matching.rangeSelector.startContainer,
endContainer:
end === existing.matching.textPosition.end
? existing.matching.rangeSelector.endContainer
: newHighlight.matching.rangeSelector.endContainer,
},
surroundingText: {
prefix:
start === existing.matching.textPosition.start
? existing.matching.surroundingText.prefix
: newHighlight.matching.surroundingText.prefix,
suffix:
end === existing.matching.textPosition.end
? existing.matching.surroundingText.suffix
: newHighlight.matching.surroundingText.suffix,
},
},
updatedAt: new Date(),
};
};

0 comments on commit 139e2f6

Please sign in to comment.