UI Stabilization: Global color theme updates (#75B2D6), AI Assistant styling refactor, and navigation fixes

This commit is contained in:
Antigravity
2026-05-09 12:58:16 +00:00
parent 1446463f04
commit 60a3fe5453
47 changed files with 3585 additions and 2149 deletions

View File

@@ -107,16 +107,15 @@ export function NoteInlineEditor({
const { data: session } = useSession()
const [aiAssistantEnabled, setAiAssistantEnabled] = useState(true)
const [autoLabelingEnabled, setAutoLabelingEnabled] = useState(true)
const [autoSaveEnabled, setAutoSaveEnabled] = useState(true)
useEffect(() => {
if (session?.user?.id) {
const userId = session.user.id
import('@/app/actions/ai-settings').then(({ getAISettings }) => {
getAISettings(userId).then(settings => {
setAiAssistantEnabled(settings.paragraphRefactor !== false)
setAutoLabelingEnabled(settings.autoLabeling !== false)
}).catch(err => console.error("Failed to fetch AI settings", err))
})
getAISettings(session.user.id).then((settings) => {
setAiAssistantEnabled(settings.paragraphRefactor !== false)
setAutoLabelingEnabled(settings.autoLabeling !== false)
setAutoSaveEnabled(settings.autoSave !== false)
}).catch(err => console.error("Failed to fetch AI settings", err))
}
}, [session?.user?.id])
const { labels: globalLabels, addLabel } = useNotebooks()
@@ -207,6 +206,10 @@ export function NoteInlineEditor({
// ── Auto-save (1.5 s debounce, skipContentTimestamp) ─────────────────────
const scheduleSave = useCallback(() => {
if (!autoSaveEnabled) {
setIsDirty(true)
return
}
setIsDirty(true)
clearTimeout(saveTimerRef.current)
saveTimerRef.current = setTimeout(async () => {
@@ -567,10 +570,11 @@ export function NoteInlineEditor({
)}
{previousContent !== null && (
<Button variant="ghost" size="icon" className="h-8 w-8 text-amber-500 hover:text-amber-600"
<Button variant="ghost" size="sm" className="h-8 gap-1.5 px-2 text-amber-600 hover:text-amber-700 hover:bg-amber-50 dark:hover:bg-amber-950/30 font-medium"
title={t('ai.undoAI') }
onClick={() => { changeContent(previousContent); setPreviousContent(null); scheduleSave(); toast.info(t('ai.undoApplied') ) }}>
<RotateCcw className="h-3.5 w-3.5" />
<span className="text-[11px]">{t('general.undo') || 'Annuler'}</span>
</Button>
)}
</div>
@@ -601,7 +605,31 @@ export function NoteInlineEditor({
{isSaving ? (
<><Loader2 className="h-3 w-3 animate-spin" /> {t('notes.saving')}</>
) : isDirty ? (
<><span className="h-1.5 w-1.5 rounded-full bg-amber-400" /> {t('notes.dirtyStatus')}</>
!autoSaveEnabled ? (
<Button
variant="ghost"
size="sm"
className="h-6 px-2 text-[11px] text-amber-600 hover:text-amber-700 hover:bg-amber-50 dark:hover:bg-amber-950/30"
onClick={() => {
setIsSaving(true)
saveInline(note.id, { title, content, checkItems, type: noteType, isMarkdown: showMarkdownPreview && noteType === 'markdown' })
.then(() => {
setIsSaving(false)
setIsDirty(false)
toast.success(t('notes.savedStatus'))
})
.catch(() => {
setIsSaving(false)
toast.error(t('general.error'))
})
}}
>
<span className="h-1.5 w-1.5 rounded-full bg-amber-400 mr-1.5" />
{t('notes.saveNow') || 'Enregistrer'}
</Button>
) : (
<><span className="h-1.5 w-1.5 rounded-full bg-amber-400" /> {t('notes.dirtyStatus')}</>
)
) : (
<><Check className="h-3 w-3 text-emerald-500" /> {t('notes.savedStatus')}</>
)}
@@ -707,13 +735,22 @@ export function NoteInlineEditor({
<div className="flex flex-1 flex-col overflow-y-auto px-6 py-5">
{/* Title */}
<div className="group relative flex items-start gap-2 shrink-0 mb-1">
<input
type="text"
<textarea
dir="auto"
className="flex-1 bg-transparent text-xl font-semibold tracking-tight text-foreground outline-none placeholder:text-muted-foreground/40"
rows={1}
className="flex-1 bg-transparent text-xl font-semibold tracking-tight text-foreground outline-none placeholder:text-muted-foreground/40 resize-none overflow-hidden min-h-[1.5em]"
placeholder={t('notes.titlePlaceholder') || 'Titre…'}
value={title}
onChange={(e) => { changeTitle(e.target.value); scheduleSave() }}
onChange={(e) => {
changeTitle(e.target.value);
scheduleSave();
e.target.style.height = 'auto';
e.target.style.height = e.target.scrollHeight + 'px';
}}
onFocus={(e) => {
e.target.style.height = 'auto';
e.target.style.height = e.target.scrollHeight + 'px';
}}
/>
{!title && content.trim().split(/\s+/).filter(Boolean).length >= 5 && (
<button type="button"
@@ -920,9 +957,20 @@ export function NoteInlineEditor({
noteImages={allImages}
noteId={note.id}
onApplyToNote={(newContent) => {
setPreviousContent(content)
const current = content
setPreviousContent(current)
changeContent(newContent)
scheduleSave()
toast.success(t('ai.appliedToNote') || 'Applied to note', {
action: {
label: t('general.undo') || 'Undo',
onClick: () => {
changeContent(current)
setPreviousContent(null)
scheduleSave()
}
}
})
}}
onUndoLastAction={previousContent !== null ? () => {
changeContent(previousContent)