Ver Fonte

Fix archive card button overlap at narrow viewport widths (#641)

  The "Reprint" and "Schedule" buttons at the bottom of archive cards
  overlapped when the browser was narrower than the card grid expected
  (e.g. half-screen on a 2K monitor). The text labels used a viewport-
  based sm: breakpoint that didn't account for actual card width.

  Added overflow-hidden to the flex buttons and truncate to the text
  spans so labels clip with ellipsis instead of bleeding into neighbors.
maziggy há 2 meses atrás
pai
commit
ea07a0ab8e

+ 1 - 0
CHANGELOG.md

@@ -24,6 +24,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **SD Card Error After FTP Upload** ([#645](https://github.com/maziggy/bambuddy/issues/645)) — After printing one file, subsequent prints could fail with `0500-C010 "MicroSD Card read/write exception"` until Bambuddy was restarted. The FTP upload used `transfercmd()` for A1 compatibility but skipped reading the server's 226 "Transfer complete" response, leaving the SD card file write unconfirmed. The print command was sent via MQTT before the printer's FTP server had finished flushing the file to disk. Now waits for the 226 confirmation after each upload (with a 60-second timeout for slower models like H2D). Reported by @lanfi89, confirmed by @Bademeister89.
 - **SD Card Error After FTP Upload** ([#645](https://github.com/maziggy/bambuddy/issues/645)) — After printing one file, subsequent prints could fail with `0500-C010 "MicroSD Card read/write exception"` until Bambuddy was restarted. The FTP upload used `transfercmd()` for A1 compatibility but skipped reading the server's 226 "Transfer complete" response, leaving the SD card file write unconfirmed. The print command was sent via MQTT before the printer's FTP server had finished flushing the file to disk. Now waits for the 226 confirmation after each upload (with a 60-second timeout for slower models like H2D). Reported by @lanfi89, confirmed by @Bademeister89.
 - **P2S Shows Carbon Rod Maintenance Tasks** ([#640](https://github.com/maziggy/bambuddy/issues/640)) — The P2S was incorrectly classified as a carbon rod printer, showing "Lubricate Carbon Rods" and "Clean Carbon Rods" maintenance tasks. The P2S uses hardened steel linear shafts, not carbon fiber rods. Added a new `steel_rod` motion system category and "Lubricate Steel Rods" / "Clean Steel Rods" maintenance tasks specific to the P2S. X1/P1 series continue to show carbon rod tasks; A1/H2 series continue to show linear rail tasks. Reported by @maziggy.
 - **P2S Shows Carbon Rod Maintenance Tasks** ([#640](https://github.com/maziggy/bambuddy/issues/640)) — The P2S was incorrectly classified as a carbon rod printer, showing "Lubricate Carbon Rods" and "Clean Carbon Rods" maintenance tasks. The P2S uses hardened steel linear shafts, not carbon fiber rods. Added a new `steel_rod` motion system category and "Lubricate Steel Rods" / "Clean Steel Rods" maintenance tasks specific to the P2S. X1/P1 series continue to show carbon rod tasks; A1/H2 series continue to show linear rail tasks. Reported by @maziggy.
 - **Dispatch Toast Stuck After Second Print** — The print dispatch progress toast ("Starting prints…") stayed visible forever after the second print dispatch in a session. The dedup guard (`lastDispatchSummaryRef`) that prevents duplicate completion toasts was never reset between batches, so every single-printer dispatch produced the same summary key (`"first-complete:1:0"`). The first print completed normally, but subsequent completions matched the stale ref and skipped creating the done toast — leaving the progress toast stuck in "Processing" state with no way to dismiss except a page reload. Now resets the dedup guard whenever the dispatch toast is dismissed (auto-dismiss timeout, cleanup events) and when a new batch starts.
 - **Dispatch Toast Stuck After Second Print** — The print dispatch progress toast ("Starting prints…") stayed visible forever after the second print dispatch in a session. The dedup guard (`lastDispatchSummaryRef`) that prevents duplicate completion toasts was never reset between batches, so every single-printer dispatch produced the same summary key (`"first-complete:1:0"`). The first print completed normally, but subsequent completions matched the stale ref and skipped creating the done toast — leaving the progress toast stuck in "Processing" state with no way to dismiss except a page reload. Now resets the dedup guard whenever the dispatch toast is dismissed (auto-dismiss timeout, cleanup events) and when a new batch starts.
+- **Archive Card Buttons Overlapping at Narrow Widths** ([#641](https://github.com/maziggy/bambuddy/issues/641)) — The "Reprint" and "Schedule" buttons at the bottom of archive cards overlapped when the browser window was narrower than the card grid expected (e.g. snapped to half-screen on a 2K monitor). The button text labels used a viewport-based `sm:` breakpoint that didn't account for actual card width. Added `overflow-hidden` to the flex buttons and `truncate` to the text spans so labels clip cleanly with ellipsis instead of bleeding into adjacent buttons. Reported by rsocko@outlook.com, confirmed by @dsmitty166.
 
 
 
 
 ## [0.2.2b2] - 2026-03-06
 ## [0.2.2b2] - 2026-03-06

+ 6 - 6
frontend/src/pages/ArchivesPage.tsx

@@ -1032,24 +1032,24 @@ function ArchiveCard({
               <Button
               <Button
                 variant="primary"
                 variant="primary"
                 size="sm"
                 size="sm"
-                className="flex-1 min-w-0"
+                className="flex-1 min-w-0 overflow-hidden"
                 onClick={() => setShowReprint(true)}
                 onClick={() => setShowReprint(true)}
                 disabled={!archive.file_path || !canModify('archives', 'reprint', archive.created_by_id)}
                 disabled={!archive.file_path || !canModify('archives', 'reprint', archive.created_by_id)}
                 title={!archive.file_path ? t('archives.card.noFileForReprint') : !canModify('archives', 'reprint', archive.created_by_id) ? t('archives.card.noPermissionReprint') : undefined}
                 title={!archive.file_path ? t('archives.card.noFileForReprint') : !canModify('archives', 'reprint', archive.created_by_id) ? t('archives.card.noPermissionReprint') : undefined}
               >
               >
                 <Printer className="w-3 h-3 flex-shrink-0" />
                 <Printer className="w-3 h-3 flex-shrink-0" />
-                <span className="hidden sm:inline">{t('archives.card.reprint')}</span>
+                <span className="hidden sm:inline truncate">{t('archives.card.reprint')}</span>
               </Button>
               </Button>
               <Button
               <Button
                 variant="secondary"
                 variant="secondary"
                 size="sm"
                 size="sm"
-                className="flex-1 min-w-0"
+                className="flex-1 min-w-0 overflow-hidden"
                 onClick={() => setShowSchedule(true)}
                 onClick={() => setShowSchedule(true)}
                 disabled={!archive.file_path || !hasPermission('queue:create')}
                 disabled={!archive.file_path || !hasPermission('queue:create')}
                 title={!archive.file_path ? t('archives.card.noFileForReprint') : !hasPermission('queue:create') ? t('archives.permission.noAddToQueue') : t('archives.card.schedulePrint')}
                 title={!archive.file_path ? t('archives.card.noFileForReprint') : !hasPermission('queue:create') ? t('archives.permission.noAddToQueue') : t('archives.card.schedulePrint')}
               >
               >
                 <Calendar className="w-3 h-3 flex-shrink-0" />
                 <Calendar className="w-3 h-3 flex-shrink-0" />
-                <span className="hidden sm:inline">{t('archives.card.schedule')}</span>
+                <span className="hidden sm:inline truncate">{t('archives.card.schedule')}</span>
               </Button>
               </Button>
               <Button
               <Button
                 variant="secondary"
                 variant="secondary"
@@ -1069,7 +1069,7 @@ function ArchiveCard({
             <Button
             <Button
               variant="primary"
               variant="primary"
               size="sm"
               size="sm"
-              className="flex-1 min-w-0"
+              className="flex-1 min-w-0 overflow-hidden"
               onClick={() => {
               onClick={() => {
                 const filename = archive.print_name || archive.filename || 'model';
                 const filename = archive.print_name || archive.filename || 'model';
                 openInSlicerWithToken(archive.id, filename, 'file', preferredSlicer);
                 openInSlicerWithToken(archive.id, filename, 'file', preferredSlicer);
@@ -1077,7 +1077,7 @@ function ArchiveCard({
               title={t('archives.card.openInBambuStudioToSlice')}
               title={t('archives.card.openInBambuStudioToSlice')}
             >
             >
               <ExternalLink className="w-3 h-3 flex-shrink-0" />
               <ExternalLink className="w-3 h-3 flex-shrink-0" />
-              <span className="hidden sm:inline">{t('archives.card.slice')}</span>
+              <span className="hidden sm:inline truncate">{t('archives.card.slice')}</span>
             </Button>
             </Button>
           )}
           )}
           <Button
           <Button

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
static/assets/index-BmG2qPP8.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-C4tUDnR9.js"></script>
+    <script type="module" crossorigin src="/assets/index-BmG2qPP8.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-BoLtXYT2.css">
     <link rel="stylesheet" crossorigin href="/assets/index-BoLtXYT2.css">
   </head>
   </head>
   <body>
   <body>

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