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:
@@ -50,6 +50,7 @@ import { UploadModal } from '../upload/UploadModal'
|
||||
import { useSharedFoldersQuery } from '../../hooks/useSharingQueries'
|
||||
import { useAuth } from '../../contexts/AuthContext'
|
||||
import { useFeaturesQuery } from '../../hooks/useFeaturesQuery'
|
||||
import { useScanActivity } from '../../hooks/useScanActivity'
|
||||
|
||||
interface TreeItem {
|
||||
id: string
|
||||
@@ -61,10 +62,15 @@ interface TreeItem {
|
||||
/** For folder rows only: the user-set "hide from views" flag. Drives
|
||||
* the muted styling + eye-off badge + menu item label. */
|
||||
isHidden?: boolean
|
||||
/** For folder rows only: filesystem path. Used to match against the
|
||||
* scan-status `current_folder` so we can show an inline spinner on
|
||||
* the row that's actively being scanned. */
|
||||
path?: string
|
||||
}
|
||||
|
||||
export function LeftSidebar() {
|
||||
const { user, isAdmin, logout } = useAuth()
|
||||
const scanActivity = useScanActivity()
|
||||
const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set(['library', 'folders', 'heaps']))
|
||||
// Inline rename state for source-root rows. Stores the id being edited
|
||||
// and the draft name. Double-click a folder row to start.
|
||||
@@ -405,6 +411,7 @@ export function LeftSidebar() {
|
||||
count: node.photo_count,
|
||||
type: 'folder',
|
||||
isHidden: node.is_hidden,
|
||||
path: node.path,
|
||||
children: node.children.length > 0
|
||||
? node.children.map(folderNodeToTreeItem)
|
||||
: undefined,
|
||||
@@ -628,6 +635,26 @@ export function LeftSidebar() {
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* Activity spinner — shown on the FOLDERS section header
|
||||
* whenever any background scan/processing is happening, and
|
||||
* on a folder row whose path is the one currently being
|
||||
* scanned. Replaces the old bottom-right ScanProgress popup. */}
|
||||
{(() => {
|
||||
const showOnFolders =
|
||||
isSectionHeader && item.id === 'folders' && scanActivity.active
|
||||
const showOnFolderRow =
|
||||
!!item.path &&
|
||||
!!scanActivity.currentFolder &&
|
||||
scanActivity.currentFolder.startsWith(item.path)
|
||||
if (!showOnFolders && !showOnFolderRow) return null
|
||||
return (
|
||||
<span
|
||||
className="ml-1 inline-block h-2.5 w-2.5 flex-shrink-0 animate-spin rounded-full border border-primary/30 border-t-primary"
|
||||
aria-label="Background activity in progress"
|
||||
/>
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Count Badge — fixed-width slot so counts line up in a column
|
||||
* across rows regardless of digit count. Section headers skip
|
||||
* the badge entirely (they're labels, not navigable rows). */}
|
||||
|
||||
Reference in New Issue
Block a user