mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
Fix AMS slot modal infinite scroll loop on Windows
Inline callback refs on preset buttons called scrollIntoView on every re-render, creating a scroll → re-render → scrollIntoView loop on Windows. Replace with a useEffect + data attribute approach that only scrolls when the selected preset actually changes.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useMemo, useEffect, useCallback } from 'react';
|
||||
import { useState, useMemo, useEffect, useCallback, useRef } from 'react';
|
||||
import { useQuery, useMutation } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { X, Loader2, Settings2, ChevronDown, CheckCircle2, RotateCcw } from 'lucide-react';
|
||||
@@ -242,6 +242,7 @@ export function ConfigureAmsSlotModal({
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [showSuccess, setShowSuccess] = useState(false);
|
||||
const [showExtendedColors, setShowExtendedColors] = useState(false);
|
||||
const scrolledToRef = useRef<string>('');
|
||||
|
||||
// Fetch cloud settings (gracefully handle 401 when logged out)
|
||||
const { data: cloudSettings, isLoading: settingsLoading, isError: cloudError } = useQuery({
|
||||
@@ -735,6 +736,7 @@ export function ConfigureAmsSlotModal({
|
||||
setColorInput('');
|
||||
setSearchQuery('');
|
||||
setShowSuccess(false);
|
||||
scrolledToRef.current = '';
|
||||
}
|
||||
}, [isOpen, slotInfo.savedPresetId, slotInfo.trayInfoIdx, slotInfo.trayColor, cloudSettings?.filament]);
|
||||
|
||||
@@ -770,6 +772,17 @@ export function ConfigureAmsSlotModal({
|
||||
}
|
||||
}, [isOpen, handleKeyDown]);
|
||||
|
||||
// Scroll selected preset into view only when the selection changes (not on every render).
|
||||
// Inline callback refs cause scrollIntoView to fire every render, which on Windows
|
||||
// creates an infinite scroll loop due to scroll → re-render → scrollIntoView cycles.
|
||||
useEffect(() => {
|
||||
if (selectedPresetId && selectedPresetId !== scrolledToRef.current) {
|
||||
scrolledToRef.current = selectedPresetId;
|
||||
const el = document.querySelector(`[data-preset-id="${CSS.escape(selectedPresetId)}"]`);
|
||||
el?.scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
}, [selectedPresetId]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const isLoading = (settingsLoading && !cloudError) || localLoading || builtinLoading || kprofilesLoading;
|
||||
@@ -889,9 +902,7 @@ export function ConfigureAmsSlotModal({
|
||||
filteredPresets.map((preset) => (
|
||||
<button
|
||||
key={preset.id}
|
||||
ref={selectedPresetId === preset.id ? (el) => {
|
||||
el?.scrollIntoView({ block: 'nearest' });
|
||||
} : undefined}
|
||||
data-preset-id={preset.id}
|
||||
onClick={() => setSelectedPresetId(preset.id)}
|
||||
className={`w-full p-2 rounded-lg border text-left transition-colors ${
|
||||
selectedPresetId === preset.id
|
||||
@@ -1126,9 +1137,7 @@ export function ConfigureAmsSlotModal({
|
||||
filteredPresets.map((preset) => (
|
||||
<button
|
||||
key={preset.id}
|
||||
ref={selectedPresetId === preset.id ? (el) => {
|
||||
el?.scrollIntoView({ block: 'nearest' });
|
||||
} : undefined}
|
||||
data-preset-id={preset.id}
|
||||
onClick={() => setSelectedPresetId(preset.id)}
|
||||
className={`w-full p-2 rounded-lg border text-left transition-colors ${
|
||||
selectedPresetId === preset.id
|
||||
|
||||
Reference in New Issue
Block a user