feat: implement live-sync for tasks, workspace note sharing, and document locking system
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 53s

This commit is contained in:
sandrodach committed 2026-10-25 02:23:46 +02:00
1 parent dccf1a91e3
commit 84e0b6a4bd
10 files changed
+1773 -110

No files matched your search

@@ -96,6 +96,71 @@ export const TasksView: React.FC<TasksViewProps> = ({
loadData();
}, [refreshTrigger, selectedListId]);
// Live-Sync WebSocket listener for tasks
useEffect(() => {
const handleWs = (e: any) => {
const msg = e.detail;
if (!msg || !msg.event) return;
if (msg.event === 'TASK_CREATED') {
const created = msg.payload as Thought;
if (
created &&
(created.status === 'converted' ||
created.kanbanStatus ||
created.taskListId ||
created.isCompleted !== undefined)
) {
setTasks((prev) => {
if (prev.some((t) => t.id === created.id)) return prev;
if (selectedListId !== 'all' && created.taskListId !== selectedListId) return prev;
return [created, ...prev];
});
onRefreshStats();
}
} else if (msg.event === 'TASK_UPDATED') {
const updated = msg.payload as Thought;
if (updated && updated.id) {
setTasks((prev) => {
const exists = prev.some((t) => t.id === updated.id);
if (!exists) {
if (
(updated.status === 'converted' ||
updated.kanbanStatus ||
updated.taskListId ||
updated.isCompleted !== undefined) &&
(selectedListId === 'all' || updated.taskListId === selectedListId)
) {
return [updated, ...prev];
}
return prev;
}
if (selectedListId !== 'all' && updated.taskListId !== selectedListId) {
return prev.filter((t) => t.id !== updated.id);
}
return prev.map((t) => {
if (t.id !== updated.id) return t;
return {
...updated,
notes: activeNotesTaskId === updated.id ? t.notes : updated.notes,
};
});
});
onRefreshStats();
}
} else if (msg.event === 'TASK_DELETED') {
const deletedId = typeof msg.payload === 'string' ? msg.payload : msg.payload?.id;
if (deletedId) {
setTasks((prev) => prev.filter((t) => t.id !== deletedId));
onRefreshStats();
}
}
};
window.addEventListener('mindsift:ws', handleWs);
return () => window.removeEventListener('mindsift:ws', handleWs);
}, [selectedListId, activeNotesTaskId, onRefreshStats]);
const handleToggleDone = async (task: Thought) => {
triggerHaptic(15);
const nextState = !task.isCompleted;