ソースを参照

fix(printers): Escape closes the Build Plate Check result as soon as it appears (the listener that knows the result is attached in the same render)

maziggy 1 日 前
親
コミット
16633dd27a

+ 1 - 0
CHANGELOG.md

@@ -168,6 +168,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **The frontend build no longer warns about `path` and `crypto` being externalized for the STEP previewer (#2976)** — `occt-import-js`, the Emscripten build behind STEP previews, requires both modules, but only inside its `ENVIRONMENT_IS_NODE` branches; in the browser it loads its `.wasm` from the URL the preview worker passes and draws randomness from `crypto.getRandomValues`. Vite still externalized both and printed two warnings on every build. `vite.config.ts` now drops exactly those two warnings for that one package through `build.rolldownOptions.onLog`, so an externalization anywhere else, or of any other module, still shows.
 
 ### Fixed
+- **Escape closes the Build Plate Check result as soon as it appears** — Pressed in the moment the result opened, Escape could be ignored, so the window stayed open and a chamber light the check had turned on stayed on until it was closed another way.
 - **The Printers page sent hundreds of requests on a print farm, and every page asked for each printer's status** — Each printer card fetched its own status, slot presets, AMS labels, power plug, action buttons, sensor readings, firmware check and queue, one request per printer. With 59 printers that was about 550 requests when the page opened, which the server worked through one behind the other, so cards took 5 to 20 seconds to fill. The sidebar, the camera wall and other pages also fetched every printer's status one by one.
   - **Now batched:** requests for the same kind of data that arrive within a few milliseconds go out as one request, so the Printers page sends about one request per kind of data however many printers there are. The cards' own refresh timers are unchanged, including the 30-second status poll, and they too are combined into one request each round.
   - **Same answers:** each combined request returns exactly what the per-printer one did, with the same permissions and printer access. Refreshing a single printer after an action, or a page that shows one printer, still sends the per-printer request.

+ 24 - 0
frontend/src/__tests__/pages/PrintersPagePlateCheckWiring.test.tsx

@@ -193,6 +193,30 @@ describe('PrintersPage plate check: chamber light handling', () => {
     await waitFor(() => expect(sent).toEqual([light(true), check, light(false)]));
   });
 
+  it('Escape pressed the moment the result shows still closes it', async () => {
+    const user = userEvent.setup();
+    const sent = setup({ lightOn: false });
+    // Pressed from the DOM change itself: before React's passive effects of
+    // that render could run, as on a busy machine.
+    const pressed = { done: false };
+    const observer = new MutationObserver(() => {
+      if (!pressed.done && screen.queryByText('Build Plate Check')) {
+        pressed.done = true;
+        fireEvent.keyDown(window, { key: 'Escape' });
+      }
+    });
+    observer.observe(document.body, { childList: true, subtree: true });
+
+    try {
+      await openCheck(user);
+      await waitFor(() => expect(pressed.done).toBe(true), LIGHT_WAIT);
+      await waitFor(() => expect(screen.queryByText('Build Plate Check')).toBeNull());
+      await waitFor(() => expect(sent).toEqual([light(true), check, light(false)]));
+    } finally {
+      observer.disconnect();
+    }
+  });
+
   it('light already on: no chamber-light request on open or on close', async () => {
     const user = userEvent.setup();
     const sent = setup({ lightOn: true });

+ 5 - 2
frontend/src/pages/PrintersPage.tsx

@@ -3369,8 +3369,11 @@ function PrinterCard({
     }
   };
 
-  // Close plate check modal on Escape key
-  useEffect(() => {
+  // Close plate check modal on Escape key. A layout effect, so the listener
+  // that knows about the result is in place as soon as the modal is shown: an
+  // Escape pressed before a passive effect ran met the listener from before,
+  // which ignored it.
+  useLayoutEffect(() => {
     const handleEscape = (e: KeyboardEvent) => {
       if (e.key === 'Escape' && plateCheckResult) {
         closePlateCheckModal();

ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/ArchivesPage-qAGPxrkf.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/CameraPage-C143eDq2.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/FileManagerPage-zsHE-xsP.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/InventoryPage-C7FFNhHO.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/ModelSourcesPage-DflSG-D1.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/PhotoGalleryModal-C_Xhip96.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/PrintersPage-tMhyexvK.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/SettingsPage-DNJNTK0v.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/SliceModal-BTbRUyHc.js


ファイルの差分が大きいため隠しています
+ 1 - 1
static/assets/SpoolBuddySettingsPage-3IaQBKH0.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/index-C0j9bTzR.js


ファイルの差分が大きいため隠しています
+ 0 - 0
static/assets/locationSensorDefaults-DBy-XPP5.js


+ 1 - 1
static/index.html

@@ -26,7 +26,7 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-DkfTgrpJ.js"></script>
+    <script type="module" crossorigin src="/assets/index-C0j9bTzR.js"></script>
     <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-aKtaBQYM.js">
     <link rel="modulepreload" crossorigin href="/assets/client-DSw2TdH4.js">
     <link rel="modulepreload" crossorigin href="/assets/react-dom-PmRWqOqI.js">

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません