Ver Fonte

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.

maziggy há 5 meses atrás
pai
commit
f5cec45dbf

+ 1 - 1
frontend/src/components/TimelapseViewer.tsx

@@ -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) {
 export function TimelapseViewer({ src, title, downloadFilename, onClose }: TimelapseViewerProps) {
   const videoRef = useRef<HTMLVideoElement>(null);
   const videoRef = useRef<HTMLVideoElement>(null);
   const [isPlaying, setIsPlaying] = useState(true);
   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 [currentTime, setCurrentTime] = useState(0);
   const [duration, setDuration] = useState(0);
   const [duration, setDuration] = useState(0);
 
 

+ 24 - 2
frontend/src/pages/ArchivesPage.tsx

@@ -932,6 +932,7 @@ export function ArchivesPage() {
   const [filterColors, setFilterColors] = useState<Set<string>>(new Set());
   const [filterColors, setFilterColors] = useState<Set<string>>(new Set());
   const [colorFilterMode, setColorFilterMode] = useState<'or' | 'and'>('or');
   const [colorFilterMode, setColorFilterMode] = useState<'or' | 'and'>('or');
   const [filterFavorites, setFilterFavorites] = useState(false);
   const [filterFavorites, setFilterFavorites] = useState(false);
+  const [hideFailed, setHideFailed] = useState(() => localStorage.getItem('archiveHideFailed') === 'true');
   const [filterTag, setFilterTag] = useState<string | null>(null);
   const [filterTag, setFilterTag] = useState<string | null>(null);
   const [showUpload, setShowUpload] = useState(false);
   const [showUpload, setShowUpload] = useState(false);
   const [uploadFiles, setUploadFiles] = useState<File[]>([]);
   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]) || []);
   const printerMap = new Map(printers?.map((p) => [p.id, p.name]) || []);
 
 
   // Extract unique materials and colors from archives
   // Extract unique materials and colors from archives
@@ -1037,11 +1043,14 @@ export function ArchivesPage() {
       // Favorites filter (only apply if not using favorites collection)
       // Favorites filter (only apply if not using favorites collection)
       const matchesFavorites = collection === 'favorites' || !filterFavorites || a.is_favorite;
       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
       // Tag filter
       const archiveTags = a.tags?.split(',').map(t => t.trim()) || [];
       const archiveTags = a.tags?.split(',').map(t => t.trim()) || [];
       const matchesTag = !filterTag || archiveTags.includes(filterTag);
       const matchesTag = !filterTag || archiveTags.includes(filterTag);
 
 
-      return matchesCollection && matchesSearch && matchesMaterial && matchesColor && matchesFavorites && matchesTag;
+      return matchesCollection && matchesSearch && matchesMaterial && matchesColor && matchesFavorites && matchesHideFailed && matchesTag;
     })
     })
     .sort((a, b) => {
     .sort((a, b) => {
       switch (sortBy) {
       switch (sortBy) {
@@ -1108,10 +1117,11 @@ export function ArchivesPage() {
     setFilterPrinter(null);
     setFilterPrinter(null);
     setFilterMaterial(null);
     setFilterMaterial(null);
     setFilterFavorites(false);
     setFilterFavorites(false);
+    setHideFailed(false);
     setFilterTag(null);
     setFilterTag(null);
   };
   };
 
 
-  const hasTopFilters = search || filterPrinter || filterMaterial || filterFavorites || filterTag;
+  const hasTopFilters = search || filterPrinter || filterMaterial || filterFavorites || hideFailed || filterTag;
 
 
   // Drag & drop handlers for page-wide upload
   // Drag & drop handlers for page-wide upload
   const handleDragOver = useCallback((e: React.DragEvent) => {
   const handleDragOver = useCallback((e: React.DragEvent) => {
@@ -1434,6 +1444,18 @@ export function ArchivesPage() {
               <Star className={`w-4 h-4 ${filterFavorites ? 'fill-yellow-400' : ''}`} />
               <Star className={`w-4 h-4 ${filterFavorites ? 'fill-yellow-400' : ''}`} />
               <span className="text-sm hidden md:inline">Favorites</span>
               <span className="text-sm hidden md:inline">Favorites</span>
             </button>
             </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 && (
             {uniqueTags.length > 0 && (
               <div className="flex items-center gap-2 flex-shrink-0">
               <div className="flex items-center gap-2 flex-shrink-0">
                 <Tag className="w-4 h-4 text-bambu-gray hidden md:block" />
                 <Tag className="w-4 h-4 text-bambu-gray hidden md:block" />

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
static/assets/index-BJKxvS2L.js


+ 1 - 1
static/index.html

@@ -23,7 +23,7 @@
 
 
     <!-- Splash screens for iOS -->
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
     <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">
     <link rel="stylesheet" crossorigin href="/assets/index-CbCN6LSA.css">
   </head>
   </head>
   <body>
   <body>

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff