feat: improvements

This commit is contained in:
2026-03-15 22:08:31 +01:00
parent 4d673ab556
commit 45c387c9e6
12 changed files with 598 additions and 420 deletions

View File

@@ -68,6 +68,7 @@ import { getLogosContent, setLogosContent } from './recollectionStore'
import { toast } from 'sonner'
import { NewRecollectionDialog } from '@/app/kosmos/NewRecollectionDialog'
import { RecollectionsPageBackground } from './RecollectionsPageBackground'
import { RenameRecollectionDialog } from './RenameRecollectionDialog'
import type { Recollection } from '@/app/kosmos/types'
const PAGE_SIZE_OPTIONS = [10, 25, 50] as const
@@ -269,8 +270,6 @@ export function RecollectionsPage() {
const [sortKey, setSortKey] = useState<SortKey>('lastEdited')
const [sortDir, setSortDir] = useState<SortDir>('desc')
const [renameTarget, setRenameTarget] = useState<Recollection | null>(null)
const [renameValue, setRenameValue] = useState('')
const renameInputRef = React.useRef<HTMLInputElement>(null)
const [deleteTarget, setDeleteTarget] = useState<Recollection | null>(null)
const [duplicateTarget, setDuplicateTarget] = useState<Recollection | null>(null)
const [duplicateName, setDuplicateName] = useState('')
@@ -321,16 +320,8 @@ export function RecollectionsPage() {
const handleRenameOpen = useCallback((recollection: Recollection) => {
setRenameTarget(recollection)
setRenameValue(recollection.name)
}, [])
React.useEffect(() => {
if (renameTarget) {
const t = setTimeout(() => renameInputRef.current?.focus(), 0)
return () => clearTimeout(t)
}
}, [renameTarget])
React.useEffect(() => {
if (duplicateTarget) {
const t = setTimeout(() => duplicateInputRef.current?.focus(), 0)
@@ -338,14 +329,6 @@ export function RecollectionsPage() {
}
}, [duplicateTarget])
const handleRenameSubmit = useCallback(() => {
if (renameTarget && renameValue.trim()) {
renameRecollection(renameTarget.id, renameValue.trim())
setRenameTarget(null)
setRenameValue('')
}
}, [renameTarget, renameValue, renameRecollection])
const handleDeleteOpen = useCallback((recollection: Recollection) => {
setDeleteTarget(recollection)
}, [])
@@ -929,37 +912,17 @@ export function RecollectionsPage() {
)}
</div>
{/* Rename dialog */}
<Dialog open={!!renameTarget} onOpenChange={(open) => !open && setRenameTarget(null)}>
<DialogContent onCloseAutoFocus={(e) => e.preventDefault()}>
<DialogHeader>
<DialogTitle>Rename recollection</DialogTitle>
<DialogDescription>Enter a new name for this recollection.</DialogDescription>
</DialogHeader>
<Input
ref={renameInputRef}
value={renameValue}
onChange={(e) => setRenameValue(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') handleRenameSubmit()
if (e.key === 'Escape') setRenameTarget(null)
}}
placeholder="Recollection name"
aria-label="Recollection name"
/>
{renameTarget && renameValue.trim() && sorted.some((p) => p.id !== renameTarget.id && p.name.toLowerCase() === renameValue.trim().toLowerCase()) && (
<p className="text-xs text-amber-600 dark:text-amber-500">An recollection with this name already exists.</p>
)}
<DialogFooter>
<Button variant="outline" onClick={() => setRenameTarget(null)}>
Cancel
</Button>
<Button onClick={handleRenameSubmit} disabled={!renameValue.trim()}>
Save
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<RenameRecollectionDialog
open={!!renameTarget}
onOpenChange={(open) => !open && setRenameTarget(null)}
recollectionId={renameTarget?.id ?? ''}
initialName={renameTarget?.name ?? ''}
recollections={sorted}
onRename={(id, newName) => {
renameRecollection(id, newName)
setRenameTarget(null)
}}
/>
{/* Duplicate dialog */}
<Dialog open={!!duplicateTarget} onOpenChange={(open) => { if (!open) { setDuplicateTarget(null); setDuplicateName('') } }}>