feat: 8 AI providers, rich text editor, agent notifications, UI contrast & font settings
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 1m25s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 1m25s
- Add DeepSeek, OpenRouter, Mistral, Z.AI, LM Studio as AI providers with editable model names via Combobox in admin settings - Fix OpenRouter broken by normalizeProvider bug in config.ts - Convert agent-created notes from Markdown to HTML (TipTap rich text) - Add Notification model + in-app notifications for agent results - Agent notification click opens the created note directly - Add note count display on notebook and inbox headers - Fix checklist toggle in card view (persist state via localCheckItems) - Add checklist creation option in tabs/list view (dropdown on + button) - Fix image description ENOENT error with HTTP fallback - Improve UI contrast across all themes (input, border, checkbox visibility) - Add font family setting (Inter vs System Default) in Appearance settings - Fix CSS font-sans variable conflict (removed dead Geist references) - Update README with new features and 8 providers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { useSearchParams, useRouter } from 'next/navigation'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Note } from '@/lib/types'
|
||||
import { getAllNotes, searchNotes, enableNoteHistory } from '@/app/actions/notes'
|
||||
import { getAllNotes, searchNotes, enableNoteHistory, getNoteById } from '@/app/actions/notes'
|
||||
import { NoteInput } from '@/components/note-input'
|
||||
import { NotesMainSection, type NotesViewMode } from '@/components/notes-main-section'
|
||||
import { NotesViewToggle } from '@/components/notes-view-toggle'
|
||||
@@ -165,6 +165,33 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
|
||||
|
||||
useReminderCheck(notes)
|
||||
|
||||
// Handle ?openNote=ID — open a note from a notification click
|
||||
useEffect(() => {
|
||||
const openNoteId = searchParams.get('openNote')
|
||||
if (!openNoteId) return
|
||||
|
||||
const openNote = async () => {
|
||||
// Try to find the note in current state first
|
||||
const existing = notes.find(n => n.id === openNoteId)
|
||||
if (existing) {
|
||||
setEditingNote({ note: existing, readOnly: false })
|
||||
} else {
|
||||
// Fetch from server
|
||||
const fetched = await getNoteById(openNoteId)
|
||||
if (fetched) {
|
||||
setEditingNote({ note: fetched, readOnly: false })
|
||||
}
|
||||
}
|
||||
// Clean URL — remove openNote param
|
||||
const params = new URLSearchParams(searchParams.toString())
|
||||
params.delete('openNote')
|
||||
router.replace(params.toString() ? `/?${params.toString()}` : '/', { scroll: false })
|
||||
}
|
||||
|
||||
openNote()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [searchParams])
|
||||
|
||||
// Listen for global label deletion and immediately update local state
|
||||
useEffect(() => {
|
||||
const handler = (e: Event) => {
|
||||
@@ -321,6 +348,7 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
|
||||
})()}
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold text-gray-900 dark:text-white tracking-tight">{currentNotebook.name}</h1>
|
||||
<span className="text-sm font-medium text-muted-foreground mt-2">({notes.length})</span>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<NotesViewToggle mode={notesViewMode} onModeChange={setNotesViewMode} />
|
||||
@@ -351,6 +379,7 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
|
||||
<FileText className="w-8 h-8 text-primary" />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold text-gray-900 dark:text-white tracking-tight">{t('notes.title')}</h1>
|
||||
<span className="text-sm font-medium text-muted-foreground mt-2">{notes.length} {notes.length === 1 ? (t('notes.note') || 'note') : (t('notes.notes') || 'notes')}</span>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<NotesViewToggle mode={notesViewMode} onModeChange={setNotesViewMode} />
|
||||
|
||||
Reference in New Issue
Block a user