mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 19:21:33 +02:00
1. Timelapse viewer default speed changed to 2x
- frontend/src/components/TimelapseViewer.tsx:17 - Changed from 0.5 to 2
2. Archive page: hide failed prints filter with persistence
- Added hideFailed state initialized from localStorage.getItem('archiveHideFailed')
- Added localStorage persistence via useEffect
- Added "Hide Failed" toggle button (red styling when active) next to the Favorites button
- Filter is automatically bypassed when viewing the "Failed Prints" collection
- "Reset" button also clears this filter
The filter state persists across page refreshes and browser sessions via localStorage.
This commit is contained in:
@@ -14,7 +14,7 @@ const SPEED_OPTIONS = [0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4];
|
||||
export function TimelapseViewer({ src, title, downloadFilename, onClose }: TimelapseViewerProps) {
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const [isPlaying, setIsPlaying] = useState(true);
|
||||
const [playbackRate, setPlaybackRate] = useState(0.5); // Default to 0.5x for timelapse
|
||||
const [playbackRate, setPlaybackRate] = useState(2); // Default to 2x for timelapse
|
||||
const [currentTime, setCurrentTime] = useState(0);
|
||||
const [duration, setDuration] = useState(0);
|
||||
|
||||
|
||||
@@ -932,6 +932,7 @@ export function ArchivesPage() {
|
||||
const [filterColors, setFilterColors] = useState<Set<string>>(new Set());
|
||||
const [colorFilterMode, setColorFilterMode] = useState<'or' | 'and'>('or');
|
||||
const [filterFavorites, setFilterFavorites] = useState(false);
|
||||
const [hideFailed, setHideFailed] = useState(() => localStorage.getItem('archiveHideFailed') === 'true');
|
||||
const [filterTag, setFilterTag] = useState<string | null>(null);
|
||||
const [showUpload, setShowUpload] = useState(false);
|
||||
const [uploadFiles, setUploadFiles] = useState<File[]>([]);
|
||||
@@ -977,6 +978,11 @@ export function ArchivesPage() {
|
||||
},
|
||||
});
|
||||
|
||||
// Persist hideFailed filter to localStorage
|
||||
useEffect(() => {
|
||||
localStorage.setItem('archiveHideFailed', hideFailed.toString());
|
||||
}, [hideFailed]);
|
||||
|
||||
const printerMap = new Map(printers?.map((p) => [p.id, p.name]) || []);
|
||||
|
||||
// Extract unique materials and colors from archives
|
||||
@@ -1037,11 +1043,14 @@ export function ArchivesPage() {
|
||||
// Favorites filter (only apply if not using favorites collection)
|
||||
const matchesFavorites = collection === 'favorites' || !filterFavorites || a.is_favorite;
|
||||
|
||||
// Hide failed filter (don't apply when viewing failed collection)
|
||||
const matchesHideFailed = collection === 'failed' || !hideFailed || a.status !== 'failed';
|
||||
|
||||
// Tag filter
|
||||
const archiveTags = a.tags?.split(',').map(t => t.trim()) || [];
|
||||
const matchesTag = !filterTag || archiveTags.includes(filterTag);
|
||||
|
||||
return matchesCollection && matchesSearch && matchesMaterial && matchesColor && matchesFavorites && matchesTag;
|
||||
return matchesCollection && matchesSearch && matchesMaterial && matchesColor && matchesFavorites && matchesHideFailed && matchesTag;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
switch (sortBy) {
|
||||
@@ -1108,10 +1117,11 @@ export function ArchivesPage() {
|
||||
setFilterPrinter(null);
|
||||
setFilterMaterial(null);
|
||||
setFilterFavorites(false);
|
||||
setHideFailed(false);
|
||||
setFilterTag(null);
|
||||
};
|
||||
|
||||
const hasTopFilters = search || filterPrinter || filterMaterial || filterFavorites || filterTag;
|
||||
const hasTopFilters = search || filterPrinter || filterMaterial || filterFavorites || hideFailed || filterTag;
|
||||
|
||||
// Drag & drop handlers for page-wide upload
|
||||
const handleDragOver = useCallback((e: React.DragEvent) => {
|
||||
@@ -1434,6 +1444,18 @@ export function ArchivesPage() {
|
||||
<Star className={`w-4 h-4 ${filterFavorites ? 'fill-yellow-400' : ''}`} />
|
||||
<span className="text-sm hidden md:inline">Favorites</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setHideFailed(!hideFailed)}
|
||||
className={`flex items-center gap-2 px-3 py-2 rounded-lg border transition-colors flex-shrink-0 ${
|
||||
hideFailed
|
||||
? 'bg-red-500/20 border-red-500 text-red-400'
|
||||
: 'bg-bambu-dark border-bambu-dark-tertiary text-bambu-gray hover:text-white'
|
||||
}`}
|
||||
title={hideFailed ? 'Show failed prints' : 'Hide failed prints'}
|
||||
>
|
||||
<AlertCircle className={`w-4 h-4 ${hideFailed ? '' : ''}`} />
|
||||
<span className="text-sm hidden md:inline">Hide Failed</span>
|
||||
</button>
|
||||
{uniqueTags.length > 0 && (
|
||||
<div className="flex items-center gap-2 flex-shrink-0">
|
||||
<Tag className="w-4 h-4 text-bambu-gray hidden md:block" />
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -23,7 +23,7 @@
|
||||
|
||||
<!-- Splash screens for iOS -->
|
||||
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
||||
<script type="module" crossorigin src="/assets/index-DTaTSFw4.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-BJKxvS2L.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CbCN6LSA.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user