Dev #2
No files matched your search
@@ -208,7 +208,7 @@ export const App: React.FC = () => {
|
||||
} else {
|
||||
disconnectWebSocket();
|
||||
}
|
||||
}, [user]);
|
||||
}, [user?.id]);
|
||||
|
||||
// Refresh stats on task/doc real-time events
|
||||
useEffect(() => {
|
||||
@@ -253,7 +253,10 @@ export const App: React.FC = () => {
|
||||
target: 'inbox' | 'task' | 'list_item' | 'document' = 'inbox'
|
||||
) => {
|
||||
if (target === 'inbox' && thought.status === 'inbox') {
|
||||
setDeck((prev) => [thought, ...prev]);
|
||||
setDeck((prev) => {
|
||||
if (prev.some((t) => t.id === thought.id)) return prev;
|
||||
return [thought, ...prev];
|
||||
});
|
||||
setStats((prev) => ({ ...prev, inboxCount: prev.inboxCount + 1 }));
|
||||
} else if (target === 'document' && thought.convertedRefId) {
|
||||
setSelectedDocId(thought.convertedRefId);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState, useRef, useMemo } from 'react';
|
||||
import {
|
||||
Check,
|
||||
Plus,
|
||||
@@ -96,7 +96,16 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
loadData();
|
||||
}, [refreshTrigger, selectedListId]);
|
||||
|
||||
// Live-Sync WebSocket listener for tasks
|
||||
const selectedListIdRef = useRef(selectedListId);
|
||||
selectedListIdRef.current = selectedListId;
|
||||
|
||||
const activeNotesTaskIdRef = useRef(activeNotesTaskId);
|
||||
activeNotesTaskIdRef.current = activeNotesTaskId;
|
||||
|
||||
const onRefreshStatsRef = useRef(onRefreshStats);
|
||||
onRefreshStatsRef.current = onRefreshStats;
|
||||
|
||||
// Live-Sync WebSocket listener for tasks (registered once on mount)
|
||||
useEffect(() => {
|
||||
const handleWs = (e: any) => {
|
||||
const msg = e.detail;
|
||||
@@ -113,10 +122,10 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
) {
|
||||
setTasks((prev) => {
|
||||
if (prev.some((t) => t.id === created.id)) return prev;
|
||||
if (selectedListId !== 'all' && created.taskListId !== selectedListId) return prev;
|
||||
if (selectedListIdRef.current !== 'all' && created.taskListId !== selectedListIdRef.current) return prev;
|
||||
return [created, ...prev];
|
||||
});
|
||||
onRefreshStats();
|
||||
onRefreshStatsRef.current();
|
||||
}
|
||||
} else if (msg.event === 'TASK_UPDATED') {
|
||||
const updated = msg.payload as Thought;
|
||||
@@ -129,37 +138,37 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
updated.kanbanStatus ||
|
||||
updated.taskListId ||
|
||||
updated.isCompleted !== undefined) &&
|
||||
(selectedListId === 'all' || updated.taskListId === selectedListId)
|
||||
(selectedListIdRef.current === 'all' || updated.taskListId === selectedListIdRef.current)
|
||||
) {
|
||||
return [updated, ...prev];
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
if (selectedListId !== 'all' && updated.taskListId !== selectedListId) {
|
||||
if (selectedListIdRef.current !== 'all' && updated.taskListId !== selectedListIdRef.current) {
|
||||
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,
|
||||
notes: activeNotesTaskIdRef.current === updated.id ? t.notes : updated.notes,
|
||||
};
|
||||
});
|
||||
});
|
||||
onRefreshStats();
|
||||
onRefreshStatsRef.current();
|
||||
}
|
||||
} 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();
|
||||
onRefreshStatsRef.current();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('mindsift:ws', handleWs);
|
||||
return () => window.removeEventListener('mindsift:ws', handleWs);
|
||||
}, [selectedListId, activeNotesTaskId, onRefreshStats]);
|
||||
}, []);
|
||||
|
||||
const handleToggleDone = async (task: Thought) => {
|
||||
triggerHaptic(15);
|
||||
@@ -400,7 +409,10 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
target: 'task',
|
||||
taskListId: selectedListId === 'all' ? '' : selectedListId,
|
||||
});
|
||||
setTasks((prev) => [created, ...prev]);
|
||||
setTasks((prev) => {
|
||||
if (prev.some((t) => t.id === created.id)) return prev;
|
||||
return [created, ...prev];
|
||||
});
|
||||
onRefreshStats();
|
||||
} catch {
|
||||
loadData();
|
||||
@@ -466,7 +478,18 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const safeTasks = Array.isArray(tasks) ? tasks : [];
|
||||
const safeTasks = useMemo(() => {
|
||||
if (!Array.isArray(tasks)) return [];
|
||||
const seen = new Set<string>();
|
||||
const unique: Thought[] = [];
|
||||
for (const t of tasks) {
|
||||
if (t && t.id && !seen.has(t.id)) {
|
||||
seen.add(t.id);
|
||||
unique.push(t);
|
||||
}
|
||||
}
|
||||
return unique;
|
||||
}, [tasks]);
|
||||
const safeTaskLists = Array.isArray(taskLists) ? taskLists : [];
|
||||
const safeSpaces = Array.isArray(spaces) ? spaces : [];
|
||||
const safeDiscarded = Array.isArray(discarded) ? discarded : [];
|
||||
|
||||
Reference in new issue
Block a user