mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-17 19:36:28 +02:00
Add swipe-to-switch-printer and auto-navigate on tag scan
Swiping left/right on the SpoolBuddy touchscreen now cycles through online printers instead of triggering browser navigation. Auto-navigates to dashboard when a new NFC tag is detected on any other page, with edge detection so a persistent tag doesn't block manual navigation.
This commit is contained in:
@@ -20,6 +20,7 @@ All notable changes to Bambuddy will be documented in this file.
|
||||
- **SpoolBuddy Assign-to-AMS Material Mismatch Warnings** — The SpoolBuddy "Assign to AMS" modal now warns when the spool's material or slicer profile doesn't match the target slot's current filament. Shows a confirmation dialog with five warning levels: exact material mismatch, partial material match, profile-only mismatch, and combined material+profile mismatches. Respects the global `disable_filament_warnings` setting. Previously, assigning a spool to an occupied slot proceeded without any validation, matching the behavior already present in the main Assign Spool modal.
|
||||
- **Spool Assignment Changes Sync Across Tabs** — Assigning or unassigning a spool now broadcasts a WebSocket event to all connected clients. Other open browser tabs and the SpoolBuddy frontend update automatically without requiring a page reload.
|
||||
- **SpoolBuddy Auto-Navigate on Tag Scan** — When an NFC tag is detected while the SpoolBuddy UI is on a non-dashboard page (Settings, AMS, Write Tag, etc.), the frontend automatically navigates back to the main dashboard to show the scanned spool. Also wakes the screen if the display was blanked.
|
||||
- **SpoolBuddy Swipe to Switch Printers** — Swiping left/right on the SpoolBuddy touchscreen now cycles through online printers instead of triggering browser back/forward navigation. The selected printer updates in the top bar dropdown. Requires at least two online printers; single-printer setups are unaffected.
|
||||
- **SpoolBuddy System Tab** — Added a "System" tab to SpoolBuddy Settings showing live OS stats from the Raspberry Pi: CPU temperature, core count, load average, memory usage, disk usage, OS distro/kernel/architecture, Python version, and system uptime. Stats are collected by the daemon every heartbeat (10s) using stdlib-only reads from `/proc` and `/sys` — no additional dependencies required. Usage bars turn amber at 70% and red at 90%; CPU temperature is color-coded green/amber/red.
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useQuery, useQueries } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SpoolBuddyTopBar } from './SpoolBuddyTopBar';
|
||||
import { SpoolBuddyBottomNav } from './SpoolBuddyBottomNav';
|
||||
import { SpoolBuddyStatusBar } from './SpoolBuddyStatusBar';
|
||||
import { useSpoolBuddyState } from '../../hooks/useSpoolBuddyState';
|
||||
import { api, spoolbuddyApi } from '../../api/client';
|
||||
import { api, spoolbuddyApi, type Printer } from '../../api/client';
|
||||
import { VirtualKeyboard } from '../VirtualKeyboard';
|
||||
|
||||
export function SpoolBuddyLayout() {
|
||||
@@ -124,6 +124,41 @@ export function SpoolBuddyLayout() {
|
||||
return () => clearInterval(interval);
|
||||
}, [displayBlankTimeout]);
|
||||
|
||||
// Online printers list for swipe-to-switch
|
||||
const { data: printers = [] } = useQuery({
|
||||
queryKey: ['printers'],
|
||||
queryFn: () => api.getPrinters(),
|
||||
});
|
||||
const statusQueries = useQueries({
|
||||
queries: printers.map((printer: Printer) => ({
|
||||
queryKey: ['printerStatus', printer.id],
|
||||
queryFn: () => api.getPrinterStatus(printer.id),
|
||||
refetchInterval: 10000,
|
||||
})),
|
||||
});
|
||||
const onlinePrinters = useMemo(() => {
|
||||
return printers.filter((_: Printer, i: number) => statusQueries[i]?.data?.connected);
|
||||
}, [printers, statusQueries]);
|
||||
|
||||
// Swipe left/right to cycle through online printers
|
||||
const touchStartRef = useRef<{ x: number; y: number } | null>(null);
|
||||
const SWIPE_THRESHOLD = 50;
|
||||
const handleTouchStart = useCallback((e: React.TouchEvent) => {
|
||||
touchStartRef.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
|
||||
}, []);
|
||||
const handleTouchEnd = useCallback((e: React.TouchEvent) => {
|
||||
if (!touchStartRef.current || onlinePrinters.length < 2) return;
|
||||
const dx = e.changedTouches[0].clientX - touchStartRef.current.x;
|
||||
const dy = e.changedTouches[0].clientY - touchStartRef.current.y;
|
||||
touchStartRef.current = null;
|
||||
if (Math.abs(dx) < SWIPE_THRESHOLD || Math.abs(dy) > Math.abs(dx)) return;
|
||||
const currentIdx = onlinePrinters.findIndex((p: Printer) => p.id === selectedPrinterId);
|
||||
const nextIdx = dx < 0
|
||||
? (currentIdx + 1) % onlinePrinters.length // swipe left → next
|
||||
: (currentIdx - 1 + onlinePrinters.length) % onlinePrinters.length; // swipe right → prev
|
||||
setSelectedPrinterId(onlinePrinters[nextIdx].id);
|
||||
}, [onlinePrinters, selectedPrinterId, setSelectedPrinterId]);
|
||||
|
||||
// CSS brightness filter (software dimming)
|
||||
const brightnessStyle = displayBrightness < 100
|
||||
? { filter: `brightness(${displayBrightness / 100})` } as const
|
||||
@@ -133,7 +168,9 @@ export function SpoolBuddyLayout() {
|
||||
<>
|
||||
<div
|
||||
className="w-screen h-screen bg-bambu-dark text-white flex flex-col overflow-hidden"
|
||||
style={brightnessStyle}
|
||||
style={{ ...brightnessStyle, overscrollBehaviorX: 'none' }}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
>
|
||||
<SpoolBuddyTopBar
|
||||
selectedPrinterId={selectedPrinterId}
|
||||
|
||||
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-Bu1bGLqb.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-DRDn9t3d.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CZLTApPU.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user