fix: condition management improvements

- fix state issues adding new conditions on chromium
- append to bottom and scoll if overflow
This commit is contained in:
Sam Chau
2025-02-09 16:26:24 +10:30
parent df767b940f
commit 80d388fdc6

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, {useCallback, useRef, useEffect} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {InfoIcon} from 'lucide-react'; import {InfoIcon} from 'lucide-react';
import {usePatterns} from '@hooks/usePatterns'; import {usePatterns} from '@hooks/usePatterns';
@@ -8,60 +8,113 @@ import AddButton from '@ui/DataBar/AddButton';
const FormatConditionsTab = ({conditions, onConditionsChange}) => { const FormatConditionsTab = ({conditions, onConditionsChange}) => {
const {patterns, isLoading, error} = usePatterns(); const {patterns, isLoading, error} = usePatterns();
const scrollContainerRef = useRef(null);
const previousConditionsLength = useRef(conditions.length);
const handleAddCondition = () => { // Effect to handle scrolling when conditions are added
onConditionsChange([createCondition(), ...conditions]); useEffect(() => {
}; if (conditions.length > previousConditionsLength.current) {
// Scroll to bottom with smooth animation
const handleConditionChange = (index, updatedCondition) => { scrollContainerRef.current?.scrollTo({
const newConditions = [...conditions]; top: scrollContainerRef.current.scrollHeight,
newConditions[index] = updatedCondition; behavior: 'smooth'
onConditionsChange(newConditions); });
};
const handleConditionDelete = index => {
onConditionsChange(conditions.filter((_, i) => i !== index));
};
const handleMoveUp = index => {
if (index > 0) {
const newConditions = [...conditions];
[newConditions[index - 1], newConditions[index]] = [
newConditions[index],
newConditions[index - 1]
];
onConditionsChange(newConditions);
} }
}; previousConditionsLength.current = conditions.length;
}, [conditions.length]);
const handleMoveDown = index => { // Memoized handler for adding conditions
if (index < conditions.length - 1) { const handleAddCondition = useCallback(() => {
const newConditions = [...conditions]; const newCondition = createCondition();
[newConditions[index], newConditions[index + 1]] = [ // Append to end and create a new array reference
newConditions[index + 1], onConditionsChange(currentConditions => [
newConditions[index] ...currentConditions,
]; newCondition
onConditionsChange(newConditions); ]);
} }, [onConditionsChange]);
};
const handleMoveToTop = index => { // Memoized handler for condition updates
if (index > 0) { const handleConditionChange = useCallback(
const newConditions = [...conditions]; (index, updatedCondition) => {
const [movedCondition] = newConditions.splice(index, 1); onConditionsChange(currentConditions => {
newConditions.unshift(movedCondition); const newConditions = [...currentConditions];
onConditionsChange(newConditions); newConditions[index] = {...updatedCondition}; // Create new reference
} return newConditions;
}; });
},
[onConditionsChange]
);
const handleMoveToBottom = index => { // Memoized handler for condition deletion
if (index < conditions.length - 1) { const handleConditionDelete = useCallback(
const newConditions = [...conditions]; index => {
const [movedCondition] = newConditions.splice(index, 1); onConditionsChange(currentConditions =>
newConditions.push(movedCondition); currentConditions.filter((_, i) => i !== index)
onConditionsChange(newConditions); );
} },
}; [onConditionsChange]
);
// Memoized movement handlers
const handleMoveUp = useCallback(
index => {
if (index > 0) {
onConditionsChange(currentConditions => {
const newConditions = [...currentConditions];
[newConditions[index - 1], newConditions[index]] = [
{...newConditions[index]},
{...newConditions[index - 1]}
];
return newConditions;
});
}
},
[onConditionsChange]
);
const handleMoveDown = useCallback(
index => {
onConditionsChange(currentConditions => {
if (index < currentConditions.length - 1) {
const newConditions = [...currentConditions];
[newConditions[index], newConditions[index + 1]] = [
{...newConditions[index + 1]},
{...newConditions[index]}
];
return newConditions;
}
return currentConditions;
});
},
[onConditionsChange]
);
const handleMoveToTop = useCallback(
index => {
if (index > 0) {
onConditionsChange(currentConditions => {
const newConditions = [...currentConditions];
const [movedCondition] = newConditions.splice(index, 1);
return [{...movedCondition}, ...newConditions];
});
}
},
[onConditionsChange]
);
const handleMoveToBottom = useCallback(
index => {
onConditionsChange(currentConditions => {
if (index < currentConditions.length - 1) {
const newConditions = [...currentConditions];
const [movedCondition] = newConditions.splice(index, 1);
return [...newConditions, {...movedCondition}];
}
return currentConditions;
});
},
[onConditionsChange]
);
if (isLoading) { if (isLoading) {
return ( return (
@@ -85,14 +138,8 @@ const FormatConditionsTab = ({conditions, onConditionsChange}) => {
return ( return (
<div className='h-full flex flex-col space-y-4'> <div className='h-full flex flex-col space-y-4'>
{/* Header Section */}
<div className='flex items-center gap-4 h-16'> <div className='flex items-center gap-4 h-16'>
{/* Info Alert */} <div className='flex-1 flex items-center gap-2 px-3 py-2 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-md'>
<div
className='flex-1 flex items-center gap-2 px-3 py-2
bg-blue-50 dark:bg-blue-900/20
border border-blue-200 dark:border-blue-800
rounded-md'>
<InfoIcon className='h-4 w-4 text-blue-600 dark:text-blue-400 flex-shrink-0' /> <InfoIcon className='h-4 w-4 text-blue-600 dark:text-blue-400 flex-shrink-0' />
<p className='text-sm text-blue-700 dark:text-blue-300'> <p className='text-sm text-blue-700 dark:text-blue-300'>
Define matching rules using required and negated Define matching rules using required and negated
@@ -100,17 +147,16 @@ const FormatConditionsTab = ({conditions, onConditionsChange}) => {
releases. releases.
</p> </p>
</div> </div>
{/* Add Button */}
<AddButton onClick={handleAddCondition} label='Add Condition' /> <AddButton onClick={handleAddCondition} label='Add Condition' />
</div> </div>
{/* Scrollable Conditions List */} <div
<div className='flex-1 overflow-y-auto min-h-0 scrollable pr-2'> ref={scrollContainerRef}
className='flex-1 overflow-y-auto min-h-0 scrollable pr-2'>
<div className='space-y-3 pb-4'> <div className='space-y-3 pb-4'>
{conditions.map((condition, index) => ( {conditions.map((condition, index) => (
<ConditionCard <ConditionCard
key={index} key={`condition-${index}`}
condition={condition} condition={condition}
onChange={updatedCondition => onChange={updatedCondition =>
handleConditionChange(index, updatedCondition) handleConditionChange(index, updatedCondition)