ui: rework selection/heap visuals, contextual shortcut hints, inline scan activity
- Selection now reads as a blue ring + tint with a springy scale-down, hover stays a subtle gray ring so keyboard-driven and mouse-driven states are tellable apart. - Heap membership is signalled with a green tint only (no badge, no ring, no scale). - Discard/restore is optimistic and non-yanking: photos stay in the grid greyed out until the next reload, X toggles based on the current state, and the same treatment applies in preview. - Filmstrip mirrors the grid styling (selection blue, heap green, discarded grey). - Preview close restores the LAST viewed photo as the focused/selected one in the grid. - Right sidebar collapses on view change and re-opens when a photo is in focus; Esc clears active selection so the panel collapses too. - Keyboard hints panel is context-aware (grid / preview / discarded section), collapsible with H, persisted, and rendered inside the preview column above the filmstrip. - "Pick (P)" renamed to "Select (S)" everywhere. - Needs review moved into the Flag pill dropdown. - Fixed vertical videos overflowing the preview column (min-h-0). - Replaced the bottom-right ScanProgress popover with an inline spinner next to the FOLDERS sidebar header (and on the specific folder row being scanned). ScanProgress is now a headless invalidator; useScanActivity exposes the live status. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Timeline } from './components/timeline/Timeline'
|
||||
import { DuplicatesView } from './components/duplicates/DuplicatesView'
|
||||
import { MapView } from './components/map/MapView'
|
||||
@@ -29,8 +29,24 @@ function MainApp() {
|
||||
const [leftSidebarOpen, setLeftSidebarOpen] = useState(true)
|
||||
const [rightSidebarOpen, setRightSidebarOpen] = useState(true)
|
||||
const viewMode = usePhotoStore((state) => state.viewMode)
|
||||
const activePhotoId = usePhotoStore((state) => state.activePhotoId)
|
||||
const currentSection = useFilterStore((s) => s.currentSection)
|
||||
|
||||
// Close the metadata panel when the user switches between sections so
|
||||
// it doesn't carry over a now-irrelevant selection. It re-opens once a
|
||||
// photo gains focus in the new section (effect below).
|
||||
const prevSectionRef = useRef(currentSection)
|
||||
useEffect(() => {
|
||||
if (prevSectionRef.current !== currentSection) {
|
||||
prevSectionRef.current = currentSection
|
||||
setRightSidebarOpen(false)
|
||||
}
|
||||
}, [currentSection])
|
||||
|
||||
useEffect(() => {
|
||||
setRightSidebarOpen(!!activePhotoId)
|
||||
}, [activePhotoId])
|
||||
|
||||
// Bidirectional sync of filter store with URL query params.
|
||||
useFilterUrlSync()
|
||||
|
||||
@@ -101,7 +117,7 @@ function MainApp() {
|
||||
<Timeline />
|
||||
)}
|
||||
</div>
|
||||
{!isSettings && <KeyboardHints />}
|
||||
{!isSettings && viewMode !== 'preview' && <KeyboardHints />}
|
||||
</div>
|
||||
|
||||
{/* Right Sidebar */}
|
||||
|
||||
Reference in New Issue
Block a user