fix: note en double au retour et barre Gras/Italique à l’ouverture
Ne plus réinjecter une note déjà dans la liste, et n’afficher le menu de formatage que sur une vraie sélection de texte. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -318,6 +318,8 @@ export function HomeClient({
|
|||||||
}
|
}
|
||||||
|
|
||||||
setNotes((prevNotes) => {
|
setNotes((prevNotes) => {
|
||||||
|
if (prevNotes.some((n) => n.id === note.id)) return prevNotes
|
||||||
|
|
||||||
const notebookFilter = searchParams.get('notebook')
|
const notebookFilter = searchParams.get('notebook')
|
||||||
const labelFilter = searchParams.get('labels')?.split(',').filter(Boolean) || []
|
const labelFilter = searchParams.get('labels')?.split(',').filter(Boolean) || []
|
||||||
const colorFilter = searchParams.get('color')
|
const colorFilter = searchParams.get('color')
|
||||||
@@ -630,12 +632,16 @@ export function HomeClient({
|
|||||||
removeNoteFromList(detail.noteId)
|
removeNoteFromList(detail.noteId)
|
||||||
setPinnedNotes(prev => prev.filter(n => n.id !== detail.noteId))
|
setPinnedNotes(prev => prev.filter(n => n.id !== detail.noteId))
|
||||||
} else if (detail.type === 'created' && detail.note) {
|
} 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)
|
window.addEventListener(NOTE_CHANGE_EVENT, onNoteChange)
|
||||||
return () => window.removeEventListener(NOTE_CHANGE_EVENT, onNoteChange)
|
return () => window.removeEventListener(NOTE_CHANGE_EVENT, onNoteChange)
|
||||||
}, [patchNoteInList])
|
}, [patchNoteInList, filterNotesForCurrentView])
|
||||||
|
|
||||||
const handleGridReorder = useCallback(
|
const handleGridReorder = useCallback(
|
||||||
async (orderedIds: string[]) => {
|
async (orderedIds: string[]) => {
|
||||||
@@ -787,7 +793,12 @@ export function HomeClient({
|
|||||||
|
|
||||||
// Apply sort order to notes
|
// Apply sort order to notes
|
||||||
const sortedNotes = useMemo(() => {
|
const sortedNotes = useMemo(() => {
|
||||||
let sorted = [...notes]
|
const seen = new Set<string>()
|
||||||
|
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 === '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 === '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 || ''))
|
if (sortOrder === 'alpha') sorted.sort((a, b) => (a.title || '').localeCompare(b.title || ''))
|
||||||
|
|||||||
@@ -61,8 +61,7 @@ import { applyClipRtlDirection } from '@/lib/editor/apply-clip-rtl-direction'
|
|||||||
import { NOTE_REQUEST_SAVE_EVENT } from '@/lib/note-change-sync'
|
import { NOTE_REQUEST_SAVE_EVENT } from '@/lib/note-change-sync'
|
||||||
import { openNotePeek } from '@/lib/note-peek-sync'
|
import { openNotePeek } from '@/lib/note-peek-sync'
|
||||||
import { useAiConsent } from '@/components/legal/ai-consent-provider'
|
import { useAiConsent } from '@/components/legal/ai-consent-provider'
|
||||||
import type { Editor } from '@tiptap/core'
|
import { isTextSelection, type Editor } from '@tiptap/core'
|
||||||
import type { EditorState } from '@tiptap/pm/state'
|
|
||||||
import {
|
import {
|
||||||
Bold, Italic, Underline as UnderlineIcon, Strikethrough, Code,
|
Bold, Italic, Underline as UnderlineIcon, Strikethrough, Code,
|
||||||
Heading1, Heading2, Heading3, List, ListOrdered, CheckSquare,
|
Heading1, Heading2, Heading3, List, ListOrdered, CheckSquare,
|
||||||
@@ -75,7 +74,7 @@ import {
|
|||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { NodeSelection } from '@tiptap/pm/state'
|
import { AllSelection, NodeSelection } from '@tiptap/pm/state'
|
||||||
|
|
||||||
export interface RichTextEditorHandle {
|
export interface RichTextEditorHandle {
|
||||||
getEditor: () => Editor | null
|
getEditor: () => Editor | null
|
||||||
@@ -1403,17 +1402,25 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
|
|||||||
<BubbleMenu
|
<BubbleMenu
|
||||||
editor={editor}
|
editor={editor}
|
||||||
className="notion-bubble-menu"
|
className="notion-bubble-menu"
|
||||||
{...({
|
appendTo={() => document.body}
|
||||||
tippyOptions: {
|
shouldShow={({ editor: e, state, from, to, view, element }) => {
|
||||||
appendTo: () => document.body,
|
if (!e.isEditable || e.isActive('codeBlock')) return false
|
||||||
zIndex: 99999,
|
|
||||||
fallbackPlacements: ['bottom', 'top']
|
const { selection } = state
|
||||||
|
if (selection instanceof AllSelection) return false
|
||||||
|
if (selection instanceof NodeSelection) {
|
||||||
|
return selection.node.type.name === 'image'
|
||||||
}
|
}
|
||||||
} as any)}
|
if (!isTextSelection(selection) || selection.empty) return false
|
||||||
shouldShow={({ editor: e, state }: { editor: Editor; state: EditorState }) => {
|
|
||||||
const { from, to } = state.selection
|
const selectedText = state.doc.textBetween(from, to)
|
||||||
const isImage = e.isActive('image')
|
if (!selectedText.length) return false
|
||||||
return (from !== to && !e.isActive('codeBlock')) || isImage
|
|
||||||
|
// 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)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BubbleToolbar editor={editor} onSuggestCharts={handleOpenChartSuggestions} />
|
<BubbleToolbar editor={editor} onSuggestCharts={handleOpenChartSuggestions} />
|
||||||
|
|||||||
Reference in New Issue
Block a user