Skip to content

Commit 2c2f7ab

Browse files
committed
fix(web): display attachment badges in notes list and disable WebSocket features
1 parent 01d32f7 commit 2c2f7ab

File tree

6 files changed

+187
-162
lines changed

6 files changed

+187
-162
lines changed

src/components/layout/MainLayout.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ export default function MainLayout() {
7171
setNotes,
7272
refetch,
7373
reinitialize,
74-
webSocket,
74+
// BACKLOG: WebSocket moved to upcoming release
75+
// webSocket,
7576
} = useNotes();
7677

7778
const handleCreateNote = useCallback(
@@ -252,10 +253,11 @@ export default function MainLayout() {
252253
userId,
253254
isNotesPanelOpen: filesPanelOpen,
254255
onToggleNotesPanel: handleToggleNotesPanel,
255-
wsStatus: webSocket.status,
256-
wsIsAuthenticated: webSocket.isAuthenticated,
257-
wsLastSync: webSocket.lastSync,
258-
onWsReconnect: webSocket.reconnect,
256+
// BACKLOG: WebSocket moved to upcoming release
257+
// wsStatus: webSocket.status,
258+
// wsIsAuthenticated: webSocket.isAuthenticated,
259+
// wsLastSync: webSocket.lastSync,
260+
// onWsReconnect: webSocket.reconnect,
259261
};
260262

261263
if (isChecking) {

src/components/notes/NotesPanel/NoteCard.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,13 @@ function NoteCard({
139139
<Codesandbox className="h-3.5 w-3.5 text-purple-500" />
140140
</div>
141141
)}
142-
{note.attachments && note.attachments.length > 0 && (
142+
{((note.attachmentCount && note.attachmentCount > 0) ||
143+
(note.attachments && note.attachments.length > 0)) && (
143144
<div className="flex items-center gap-1 text-xs text-blue-500">
144145
<Paperclip className="h-3.5 w-3.5" />
145-
<span>{note.attachments.length}</span>
146+
<span>
147+
{note.attachmentCount ?? note.attachments?.length ?? 0}
148+
</span>
146149
</div>
147150
)}
148151
<button

src/components/notes/NotesPanel/index.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,16 @@ export default function FilesPanel({
112112

113113
const filterNotes = (notes: Note[], config: FilterConfig): Note[] => {
114114
return notes.filter((note) => {
115-
return !(
116-
(config.showAttachmentsOnly &&
117-
(!note.attachments || note.attachments.length === 0)) ||
118-
(config.showStarredOnly && !note.starred) ||
119-
(config.showHiddenOnly && !note.hidden)
120-
);
115+
const hasAttachments = (note.attachmentCount && note.attachmentCount > 0) ||
116+
(note.attachments && note.attachments.length > 0);
117+
118+
// A note is included if it passes ALL active filters (AND logic)
119+
// Exclude if any active filter condition fails
120+
const excludeByAttachments = config.showAttachmentsOnly && !hasAttachments;
121+
const excludeByStarred = config.showStarredOnly && !note.starred;
122+
const excludeByHidden = config.showHiddenOnly && !note.hidden;
123+
124+
return !(excludeByAttachments || excludeByStarred || excludeByHidden);
121125
});
122126
};
123127

src/hooks/useNotes.ts

Lines changed: 107 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import {
77
hasMasterPassword,
88
isMasterPasswordUnlocked,
99
} from '@/lib/encryption';
10-
import { useWebSocket } from './useWebSocket';
11-
import { useNotesSync } from './useNotesSync';
10+
// BACKLOG: WebSocket functionality moved to upcoming release
11+
// import { useWebSocket } from './useWebSocket';
12+
// import { useNotesSync } from './useNotesSync';
1213
import { useNotesFiltering } from './useNotesFiltering';
1314
import { useNotesOperations } from './useNotesOperations';
1415
import type { Note, Folder, ViewMode } from '@/types/note';
@@ -138,49 +139,50 @@ export function useNotes() {
138139
];
139140
}, []);
140141

141-
const refetchFolders = useCallback(async () => {
142-
try {
143-
const allFolders = await fetchAllFolders();
144-
setFolders(allFolders);
145-
} catch (error) {
146-
secureLogger.error('Failed to refetch folders:', error);
147-
}
148-
}, [fetchAllFolders, setFolders]);
149-
150-
// WebSocket sync handlers
151-
const syncHandlers = useNotesSync({
152-
folders,
153-
selectedFolder,
154-
setNotes,
155-
setFolders,
156-
setSelectedNote,
157-
safeConvertDates,
158-
refetchFolders,
159-
});
160-
161-
// WebSocket integration for real-time sync
142+
// BACKLOG: refetchFolders moved to upcoming release (was used by WebSocket sync)
143+
// const refetchFolders = useCallback(async () => {
144+
// try {
145+
// const allFolders = await fetchAllFolders();
146+
// setFolders(allFolders);
147+
// } catch (error) {
148+
// secureLogger.error('Failed to refetch folders:', error);
149+
// }
150+
// }, [fetchAllFolders, setFolders]);
151+
152+
// BACKLOG: WebSocket sync handlers moved to upcoming release
153+
// const syncHandlers = useNotesSync({
154+
// folders,
155+
// selectedFolder,
156+
// setNotes,
157+
// setFolders,
158+
// setSelectedNote,
159+
// safeConvertDates,
160+
// refetchFolders,
161+
// });
162+
163+
// BACKLOG: WebSocket integration for real-time sync - moved to upcoming release
162164
// Defer connection until after initial data load for better performance
163-
const webSocket = useWebSocket({
164-
autoConnect: false,
165-
...syncHandlers,
166-
onError: useCallback((error: Error | { message?: string }) => {
167-
// Only show connection errors to users if they persist
168-
secureLogger.error('WebSocket connection error', error);
169-
170-
// Don't show transient connection errors during startup
171-
const isStartupError = Date.now() - window.performance.timeOrigin < 10000;
172-
const isConnectionClosed =
173-
error?.message?.includes?.('Connection closed');
174-
175-
if (!isStartupError && !isConnectionClosed) {
176-
setError(`Connection error: ${error.message || 'Unknown error'}`);
177-
}
178-
}, []),
179-
onAuthenticated: useCallback((userId: string) => {
180-
secureLogger.authEvent('login', userId);
181-
setError(null); // Clear any previous connection errors
182-
}, []),
183-
});
165+
// const webSocket = useWebSocket({
166+
// autoConnect: false,
167+
// ...syncHandlers,
168+
// onError: useCallback((error: Error | { message?: string }) => {
169+
// // Only show connection errors to users if they persist
170+
// secureLogger.error('WebSocket connection error', error);
171+
172+
// // Don't show transient connection errors during startup
173+
// const isStartupError = Date.now() - window.performance.timeOrigin < 10000;
174+
// const isConnectionClosed =
175+
// error?.message?.includes?.('Connection closed');
176+
177+
// if (!isStartupError && !isConnectionClosed) {
178+
// setError(`Connection error: ${error.message || 'Unknown error'}`);
179+
// }
180+
// }, []),
181+
// onAuthenticated: useCallback((userId: string) => {
182+
// secureLogger.authEvent('login', userId);
183+
// setError(null); // Clear any previous connection errors
184+
// }, []),
185+
// });
184186

185187
const initializeUser = useCallback(async () => {
186188
try {
@@ -294,11 +296,17 @@ export function useNotes() {
294296

295297
// Defer attachment loading - only add folder data initially
296298
// Attachments will be loaded on-demand when a note is selected
299+
// Preserve attachmentCount from API for displaying badges
297300
const notesWithFolders = allNotes.map((note) => {
298301
const folder = note.folderId
299302
? folderMap.get(note.folderId)
300303
: undefined;
301-
return { ...note, attachments: [], folder };
304+
return {
305+
...note,
306+
attachments: [],
307+
attachmentCount: note.attachmentCount ?? 0,
308+
folder
309+
};
302310
});
303311

304312
setNotes(notesWithFolders);
@@ -348,16 +356,17 @@ export function useNotes() {
348356
}
349357
}, [encryptionReady, clerkUser, loadData]);
350358

359+
// BACKLOG: WebSocket connection moved to upcoming release
351360
// Connect WebSocket after initial data load for better performance
352-
useEffect(() => {
353-
if (!loading && encryptionReady && notes.length > 0 && !webSocket.isConnected) {
354-
// Delay connection slightly to ensure UI has rendered
355-
const timer = setTimeout(() => {
356-
webSocket.connect();
357-
}, 100);
358-
return () => clearTimeout(timer);
359-
}
360-
}, [loading, encryptionReady, notes.length, webSocket]);
361+
// useEffect(() => {
362+
// if (!loading && encryptionReady && notes.length > 0 && !webSocket.isConnected) {
363+
// // Delay connection slightly to ensure UI has rendered
364+
// const timer = setTimeout(() => {
365+
// webSocket.connect();
366+
// }, 100);
367+
// return () => clearTimeout(timer);
368+
// }
369+
// }, [loading, encryptionReady, notes.length, webSocket]);
361370

362371
// Notes filtering
363372
const {
@@ -389,7 +398,7 @@ export function useNotes() {
389398
selectedNote,
390399
selectedFolder,
391400
encryptionReady,
392-
webSocket,
401+
webSocket: null, // BACKLOG: WebSocket removed for upcoming release
393402
setNotes,
394403
setFolders,
395404
setSelectedNote,
@@ -400,23 +409,23 @@ export function useNotes() {
400409
getDescendantIds,
401410
});
402411

403-
// Auto-join selected note for real-time sync
404-
useEffect(() => {
405-
if (selectedNote?.id && webSocket.isAuthenticated) {
406-
// Leave previous note if any
407-
const joinedNotes = webSocket.joinedNotes;
408-
joinedNotes.forEach((noteId) => {
409-
if (noteId !== selectedNote.id) {
410-
webSocket.leaveNote(noteId);
411-
}
412-
});
413-
414-
// Join current note for real-time sync
415-
if (!joinedNotes.includes(selectedNote.id)) {
416-
webSocket.joinNote(selectedNote.id);
417-
}
418-
}
419-
}, [selectedNote?.id, webSocket.isAuthenticated, webSocket]);
412+
// BACKLOG: Auto-join selected note for real-time sync - moved to upcoming release
413+
// useEffect(() => {
414+
// if (selectedNote?.id && webSocket.isAuthenticated) {
415+
// // Leave previous note if any
416+
// const joinedNotes = webSocket.joinedNotes;
417+
// joinedNotes.forEach((noteId) => {
418+
// if (noteId !== selectedNote.id) {
419+
// webSocket.leaveNote(noteId);
420+
// }
421+
// });
422+
423+
// // Join current note for real-time sync
424+
// if (!joinedNotes.includes(selectedNote.id)) {
425+
// webSocket.joinNote(selectedNote.id);
426+
// }
427+
// }
428+
// }, [selectedNote?.id, webSocket.isAuthenticated, webSocket]);
420429

421430
// Auto-select a note when selectedNote becomes null and there are available notes
422431
useEffect(() => {
@@ -567,17 +576,18 @@ export function useNotes() {
567576
const newFolders = await fetchAllFolders();
568577
setFolders(newFolders);
569578

579+
// BACKLOG: WebSocket notification moved to upcoming release
570580
// Send WebSocket notification about folder reordering
571-
if (webSocket.isAuthenticated) {
572-
const reorderedFolder = newFolders.find((f) => f.id === folderId);
573-
if (reorderedFolder) {
574-
webSocket.sendFolderUpdated(
575-
folderId,
576-
{ order: newIndex },
577-
reorderedFolder
578-
);
579-
}
580-
}
581+
// if (webSocket.isAuthenticated) {
582+
// const reorderedFolder = newFolders.find((f) => f.id === folderId);
583+
// if (reorderedFolder) {
584+
// webSocket.sendFolderUpdated(
585+
// folderId,
586+
// { order: newIndex },
587+
// reorderedFolder
588+
// );
589+
// }
590+
// }
581591
} catch (error) {
582592
secureLogger.error('Folder reordering failed', error);
583593
setError('Failed to reorder folders');
@@ -656,20 +666,20 @@ export function useNotes() {
656666
await loadData();
657667
}
658668
},
659-
// WebSocket sync status
660-
webSocket: {
661-
status: webSocket.status,
662-
isConnected: webSocket.isConnected,
663-
isAuthenticated: webSocket.isAuthenticated,
664-
userId: webSocket.userId,
665-
error: webSocket.error,
666-
reconnectAttempts: webSocket.reconnectAttempts,
667-
lastSync: webSocket.lastSync,
668-
joinedNotes: webSocket.joinedNotes,
669-
connect: webSocket.connect,
670-
disconnect: webSocket.disconnect,
671-
reconnect: webSocket.reconnect,
672-
clearError: webSocket.clearError,
673-
},
669+
// BACKLOG: WebSocket sync status moved to upcoming release
670+
// webSocket: {
671+
// status: webSocket.status,
672+
// isConnected: webSocket.isConnected,
673+
// isAuthenticated: webSocket.isAuthenticated,
674+
// userId: webSocket.userId,
675+
// error: webSocket.error,
676+
// reconnectAttempts: webSocket.reconnectAttempts,
677+
// lastSync: webSocket.lastSync,
678+
// joinedNotes: webSocket.joinedNotes,
679+
// connect: webSocket.connect,
680+
// disconnect: webSocket.disconnect,
681+
// reconnect: webSocket.reconnect,
682+
// clearError: webSocket.clearError,
683+
// },
674684
};
675685
}

0 commit comments

Comments
 (0)