diff --git a/memento-note/components/home-client.tsx b/memento-note/components/home-client.tsx index a2f5076..a4d61f9 100644 --- a/memento-note/components/home-client.tsx +++ b/memento-note/components/home-client.tsx @@ -318,6 +318,8 @@ export function HomeClient({ } setNotes((prevNotes) => { + if (prevNotes.some((n) => n.id === note.id)) return prevNotes + const notebookFilter = searchParams.get('notebook') const labelFilter = searchParams.get('labels')?.split(',').filter(Boolean) || [] const colorFilter = searchParams.get('color') @@ -630,12 +632,16 @@ export function HomeClient({ removeNoteFromList(detail.noteId) setPinnedNotes(prev => prev.filter(n => n.id !== detail.noteId)) } else if (detail.type === 'created' && detail.note) { - setNotes(prev => [detail.note, ...prev]) + setNotes((prev) => { + if (prev.some((n) => n.id === detail.note.id)) return prev + if (filterNotesForCurrentView([detail.note]).length === 0) return prev + return [detail.note, ...prev] + }) } } window.addEventListener(NOTE_CHANGE_EVENT, onNoteChange) return () => window.removeEventListener(NOTE_CHANGE_EVENT, onNoteChange) - }, [patchNoteInList]) + }, [patchNoteInList, filterNotesForCurrentView]) const handleGridReorder = useCallback( async (orderedIds: string[]) => { @@ -787,7 +793,12 @@ export function HomeClient({ // Apply sort order to notes const sortedNotes = useMemo(() => { - let sorted = [...notes] + const seen = new Set() + let sorted = notes.filter((n) => { + if (seen.has(n.id)) return false + seen.add(n.id) + return true + }) if (sortOrder === 'newest') sorted.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) if (sortOrder === 'oldest') sorted.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) if (sortOrder === 'alpha') sorted.sort((a, b) => (a.title || '').localeCompare(b.title || '')) diff --git a/memento-note/components/rich-text-editor.tsx b/memento-note/components/rich-text-editor.tsx index 27c78ec..cbcb591 100644 --- a/memento-note/components/rich-text-editor.tsx +++ b/memento-note/components/rich-text-editor.tsx @@ -61,8 +61,7 @@ import { applyClipRtlDirection } from '@/lib/editor/apply-clip-rtl-direction' import { NOTE_REQUEST_SAVE_EVENT } from '@/lib/note-change-sync' import { openNotePeek } from '@/lib/note-peek-sync' import { useAiConsent } from '@/components/legal/ai-consent-provider' -import type { Editor } from '@tiptap/core' -import type { EditorState } from '@tiptap/pm/state' +import { isTextSelection, type Editor } from '@tiptap/core' import { Bold, Italic, Underline as UnderlineIcon, Strikethrough, Code, Heading1, Heading2, Heading3, List, ListOrdered, CheckSquare, @@ -75,7 +74,7 @@ import { } from 'lucide-react' import { cn } from '@/lib/utils' import { toast } from 'sonner' -import { NodeSelection } from '@tiptap/pm/state' +import { AllSelection, NodeSelection } from '@tiptap/pm/state' export interface RichTextEditorHandle { getEditor: () => Editor | null @@ -1403,17 +1402,25 @@ export const RichTextEditor = forwardRef document.body, - zIndex: 99999, - fallbackPlacements: ['bottom', 'top'] + appendTo={() => document.body} + shouldShow={({ editor: e, state, from, to, view, element }) => { + if (!e.isEditable || e.isActive('codeBlock')) return false + + const { selection } = state + if (selection instanceof AllSelection) return false + if (selection instanceof NodeSelection) { + return selection.node.type.name === 'image' } - } as any)} - shouldShow={({ editor: e, state }: { editor: Editor; state: EditorState }) => { - const { from, to } = state.selection - const isImage = e.isActive('image') - return (from !== to && !e.isActive('codeBlock')) || isImage + if (!isTextSelection(selection) || selection.empty) return false + + const selectedText = state.doc.textBetween(from, to) + if (!selectedText.length) return false + + // setContent à l’ouverture sélectionne parfois tout le document + const docSize = state.doc.content.size + if (docSize > 4 && from <= 1 && to >= docSize - 1) return false + + return view.hasFocus() || element.contains(document.activeElement) }} >