feat: integrate AI-driven selection panel with context-aware text summarization and quiz generation features.

This commit is contained in:
2026-04-26 20:36:08 +02:00
parent 82d726097f
commit 39a9ca5706
25 changed files with 819 additions and 219 deletions
@@ -99,6 +99,10 @@ export function mount(containerId, data, dotNetHelper) {
export function updateData(data) {
if (!simulation || !rootGroup) return;
if (!data || !data.nodes) {
clear();
return;
}
// Keep existing node positions if they match by ID
const oldNodes = new Map(simulation.nodes().map(d => [d.id, d]));
@@ -261,3 +265,14 @@ export function zoomReset() {
}
}
export function clear() {
if (!rootGroup) return;
rootGroup.select(".links-layer").selectAll("path").remove();
rootGroup.select(".nodes-layer").selectAll("g.node-group").remove();
if (badge) badge.style("display", "none");
if (simulation) {
simulation.nodes([]);
simulation.force("link").links([]);
simulation.stop();
}
}
@@ -0,0 +1,41 @@
export function initSelectionListener(dotNetHelper, container) {
if (!container) return;
console.log("[SelectionHandler] Initializing...");
const handleSelection = () => {
const selection = window.getSelection();
const text = selection.toString().trim();
if (text.length > 3) {
const range = selection.getRangeAt(0);
// Look for the closest block-wrapper
let node = range.commonAncestorContainer;
if (node.nodeType !== 1) node = node.parentElement;
const blockNode = node.closest('[id]');
if (blockNode) {
const rect = range.getBoundingClientRect();
console.log("[SelectionHandler] Selection at screen coords:", rect.top, rect.left);
dotNetHelper.invokeMethodAsync('HandleTextSelected',
text,
blockNode.id,
{
Top: rect.top,
Left: rect.left,
Width: rect.width
});
}
} else {
dotNetHelper.invokeMethodAsync('HandleSelectionCleared');
}
};
// Use multiple triggers for maximum reliability
document.addEventListener('selectionchange', handleSelection);
container.addEventListener('mouseup', () => setTimeout(handleSelection, 10));
}