fix: Memory Echo sans vol de scroll, badge IA sidebar, wizard langue

- Ne plus auto-scroller vers Memory Echo : pastille bas de page + reset scroll au titre
- Badges notes/carnets générés par l’IA dans la sidebar
- Wizard : langue du contenu = langue de la requête ; refresh carnet après création
- Voix : erreurs not-allowed/no-speech moins bruyantes
This commit is contained in:
Antigravity
2026-07-16 17:25:57 +00:00
parent 45297da333
commit 704fed1191
11 changed files with 672 additions and 210 deletions

View File

@@ -0,0 +1,59 @@
/**
* Mise en évidence temporaire des carnets créés via IA (wizard, etc.).
* Les notes ont déjà `autoGenerated` en base ; les carnets n'ont pas ce flag
* → on stocke un repère local (TTL 7 jours) pour les retrouver facilement.
*/
const STORAGE_KEY = 'memento-ai-created-notebooks'
const TTL_MS = 7 * 24 * 60 * 60 * 1000
type Entry = { id: string; at: number }
function readEntries(): Entry[] {
if (typeof window === 'undefined') return []
try {
const raw = localStorage.getItem(STORAGE_KEY)
if (!raw) return []
const parsed = JSON.parse(raw) as Entry[]
if (!Array.isArray(parsed)) return []
const now = Date.now()
return parsed.filter((e) => e?.id && typeof e.at === 'number' && now - e.at < TTL_MS)
} catch {
return []
}
}
function writeEntries(entries: Entry[]) {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(entries.slice(0, 50)))
} catch {
/* quota / private mode */
}
}
/** Marque un carnet comme créé via IA (repère sidebar ~7 jours). */
export function markAiCreatedNotebook(notebookId: string) {
if (!notebookId) return
const now = Date.now()
const next = [{ id: notebookId, at: now }, ...readEntries().filter((e) => e.id !== notebookId)]
writeEntries(next)
if (typeof window !== 'undefined') {
window.dispatchEvent(new CustomEvent('memento-ai-created-changed'))
}
}
export function isAiCreatedNotebook(notebookId: string): boolean {
return readEntries().some((e) => e.id === notebookId)
}
export function listAiCreatedNotebookIds(): Set<string> {
return new Set(readEntries().map((e) => e.id))
}
/** Note créée récemment (pour point « nouveau » optionnel). */
export function isRecentlyCreated(createdAt: Date | string | null | undefined, hours = 48): boolean {
if (!createdAt) return false
const t = typeof createdAt === 'string' ? new Date(createdAt).getTime() : createdAt.getTime()
if (Number.isNaN(t)) return false
return Date.now() - t < hours * 60 * 60 * 1000
}