Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion frontend/src/components/Media/ChronologicalGallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { groupImagesByYearMonthFromMetadata } from '@/utils/dateUtils';
import { setCurrentViewIndex } from '@/features/imageSlice';
import { MediaView } from './MediaView';
import { selectIsImageViewOpen } from '@/features/imageSelectors';
import { useSidebar } from '@/components/ui/sidebar';

export type MonthMarker = {
offset: number;
Expand Down Expand Up @@ -34,6 +35,11 @@ export const ChronologicalGallery = ({
const monthHeaderRefs = useRef<Map<string, HTMLDivElement | null>>(new Map());
const galleryRef = useRef<HTMLDivElement>(null);
const isImageViewOpen = useSelector(selectIsImageViewOpen);
const { open: sidebarOpen } = useSidebar();

// Adjust grid minmax based on sidebar state
// When sidebar is collapsed, reduce min size to fit more images per row
const gridMinSize = sidebarOpen ? '224px' : '200px';

// Optimized grouping with proper date handling
const grouped = useMemo(
Expand Down Expand Up @@ -157,7 +163,12 @@ export const ChronologicalGallery = ({
</div>

{/* Images Grid */}
<div className="grid grid-cols-[repeat(auto-fill,_minmax(224px,_1fr))] gap-4 p-2">
<div
className="grid gap-4 p-2 transition-all duration-300"
style={{
gridTemplateColumns: `repeat(auto-fill, minmax(${gridMinSize}, 1fr))`
}}
>
{imgs.map((img) => {
const chronologicalIndex =
imageIndexMap.get(img.id) ?? -1;
Expand Down
67 changes: 62 additions & 5 deletions frontend/src/components/Navigation/Sidebar/AppSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
SidebarMenuButton,
SidebarMenuItem,
SidebarSeparator,
useSidebar,
} from '@/components/ui/sidebar';
import {
Bolt,
Expand All @@ -16,15 +17,40 @@
Video,
BookImage,
ClockFading,
ChevronLeft,
} from 'lucide-react';
import { useLocation, Link } from 'react-router';
import { ROUTES } from '@/constants/routes';
import { getVersion } from '@tauri-apps/api/app';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip';

export function AppSidebar() {
const location = useLocation();
const [version, setVersion] = useState<string>('1.0.0');
const { open, setOpen, toggleSidebar } = useSidebar();

Check warning on line 37 in frontend/src/components/Navigation/Sidebar/AppSidebar.tsx

View workflow job for this annotation

GitHub Actions / Linting

'setOpen' is assigned a value but never used

// Load collapsed state from localStorage on mount
useEffect(() => {
const savedState = localStorage.getItem('sidebar-open');
if (savedState !== null) {
const shouldBeOpen = savedState === 'true';
if (open !== shouldBeOpen) {
toggleSidebar();
}
}
}, []);

// Save collapsed state to localStorage whenever it changes
useEffect(() => {
localStorage.setItem('sidebar-open', String(open));
}, [open]);

useEffect(() => {
getVersion().then((version) => {
Expand Down Expand Up @@ -59,7 +85,7 @@
<Sidebar
variant="sidebar"
collapsible="icon"
className="border-border/40 border-r shadow-sm"
className="border-border/40 border-r shadow-sm transition-all duration-300 ease-in-out"
>
<SidebarHeader className="flex justify-center py-3">
<div className="text-lg font-semibold">.</div>
Expand All @@ -73,7 +99,7 @@
asChild
isActive={isActive(item.path)}
tooltip={item.name}
className="rounded-sm"
className="rounded-sm transition-all duration-200"
>
<Link to={item.path} className="flex items-center gap-3">
<item.icon className="h-5 w-5" />
Expand All @@ -85,9 +111,40 @@
</SidebarMenu>
</SidebarContent>
<SidebarFooter className="border-border/40 mt-auto border-t py-4">
<div className="text-muted-foreground space-y-1 px-4 text-xs">
<div className="font-medium">PictoPy v{version}</div>
<div>© 2025 PictoPy</div>
<div className="space-y-3">
<div
className={`text-muted-foreground space-y-1 px-4 text-xs transition-all duration-300 ${
open
? 'opacity-100 translate-x-0'
: 'opacity-0 -translate-x-2 pointer-events-none absolute'
}`}
>
<div className="font-medium whitespace-nowrap">PictoPy v{version}</div>
<div className="whitespace-nowrap">© 2025 PictoPy</div>
</div>
<div className={`flex transition-all duration-300 ${open ? 'justify-end px-4' : 'justify-center'}`}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
onClick={toggleSidebar}
className="h-8 w-8 transition-transform duration-300 ease-in-out hover:bg-accent"
>
<ChevronLeft
className={`h-5 w-5 transition-transform duration-300 ease-in-out ${
!open ? 'rotate-180' : ''
}`}
/>
</Button>
</TooltipTrigger>
<TooltipContent side="right">
<p>{open ? 'Collapse sidebar' : 'Expand sidebar'}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</div>
</SidebarFooter>
</Sidebar>
Expand Down
Loading