fix: minor updated the region lasso selection behavior
This commit is contained in:
@@ -94,6 +94,7 @@ const MainContent: React.FC<MainContentProps> = ({
|
|||||||
|
|
||||||
// Refs to track pending updates for verification
|
// Refs to track pending updates for verification
|
||||||
const pendingUpdates = useRef<Map<string, { trackId: string, regionId: string, startBeat: number, length: number }>>(new Map());
|
const pendingUpdates = useRef<Map<string, { trackId: string, regionId: string, startBeat: number, length: number }>>(new Map());
|
||||||
|
const preventEmptyMainContentDeselectRef = useRef(false);
|
||||||
|
|
||||||
// Refs for auto-scroll during playback
|
// Refs for auto-scroll during playback
|
||||||
const mainContentRef = useRef<HTMLDivElement | null>(null);
|
const mainContentRef = useRef<HTMLDivElement | null>(null);
|
||||||
@@ -632,9 +633,18 @@ const MainContent: React.FC<MainContentProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preventEmptyMainContentDeselectRef.current) {
|
||||||
|
preventEmptyMainContentDeselectRef.current = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
handleRegionLassoSelection([], { shiftKey: false });
|
handleRegionLassoSelection([], { shiftKey: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRegionLassoCommit = () => {
|
||||||
|
preventEmptyMainContentDeselectRef.current = true;
|
||||||
|
};
|
||||||
|
|
||||||
// Handle region single click: selection only (no piano roll opening)
|
// Handle region single click: selection only (no piano roll opening)
|
||||||
const handleRegionClick = (regionId: string, options: RegionClickOptions = { shiftKey: false }) => {
|
const handleRegionClick = (regionId: string, options: RegionClickOptions = { shiftKey: false }) => {
|
||||||
if (DEBUG_MODE.MAIN_CONTENT) {
|
if (DEBUG_MODE.MAIN_CONTENT) {
|
||||||
@@ -990,6 +1000,7 @@ const MainContent: React.FC<MainContentProps> = ({
|
|||||||
onRegionUpdated={handleRegionUpdated}
|
onRegionUpdated={handleRegionUpdated}
|
||||||
onRegionClick={handleRegionClick}
|
onRegionClick={handleRegionClick}
|
||||||
onRegionLassoSelection={handleRegionLassoSelection}
|
onRegionLassoSelection={handleRegionLassoSelection}
|
||||||
|
onRegionLassoCommit={handleRegionLassoCommit}
|
||||||
onOpenPianoRoll={handleOpenPianoRoll}
|
onOpenPianoRoll={handleOpenPianoRoll}
|
||||||
onOpenSpectrogram={handleOpenSpectrogram}
|
onOpenSpectrogram={handleOpenSpectrogram}
|
||||||
showHybridButtonForAudio={showHybridButtonForAudio}
|
showHybridButtonForAudio={showHybridButtonForAudio}
|
||||||
|
|||||||
@@ -119,6 +119,17 @@ describe('TrackGridPanel lasso selection', () => {
|
|||||||
expect(onRegionLassoSelection).toHaveBeenCalledWith(['region-b', 'region-a'], { shiftKey: false });
|
expect(onRegionLassoSelection).toHaveBeenCalledWith(['region-b', 'region-a'], { shiftKey: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses the closest intersected region as primary when release is outside all regions', () => {
|
||||||
|
const { container, onRegionLassoSelection } = renderPanel();
|
||||||
|
const firstTrackGrid = container.querySelector('[data-test-id="track-grid-1"]') as HTMLDivElement;
|
||||||
|
|
||||||
|
fireEvent.mouseDown(firstTrackGrid, { clientX: 10, clientY: 10, button: 0 });
|
||||||
|
fireEvent.mouseMove(document, { clientX: 150, clientY: 170 });
|
||||||
|
fireEvent.mouseUp(document, { clientX: 150, clientY: 170 });
|
||||||
|
|
||||||
|
expect(onRegionLassoSelection).toHaveBeenCalledWith(['region-a', 'region-b'], { shiftKey: false });
|
||||||
|
});
|
||||||
|
|
||||||
it('clears selection on a plain empty-space click', () => {
|
it('clears selection on a plain empty-space click', () => {
|
||||||
const { container, onRegionLassoSelection } = renderPanel();
|
const { container, onRegionLassoSelection } = renderPanel();
|
||||||
const firstTrackGrid = container.querySelector('[data-test-id="track-grid-1"]') as HTMLDivElement;
|
const firstTrackGrid = container.querySelector('[data-test-id="track-grid-1"]') as HTMLDivElement;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ interface TrackGridPanelProps {
|
|||||||
onRegionUpdated?: (regionId: string, updates: Partial<RegionUI>, expectedModelUpdates?: { startBeat: number, length: number }) => void;
|
onRegionUpdated?: (regionId: string, updates: Partial<RegionUI>, expectedModelUpdates?: { startBeat: number, length: number }) => void;
|
||||||
onRegionClick?: (regionId: string, options: RegionClickOptions) => void;
|
onRegionClick?: (regionId: string, options: RegionClickOptions) => void;
|
||||||
onRegionLassoSelection?: (regionIds: string[], options: RegionClickOptions) => void;
|
onRegionLassoSelection?: (regionIds: string[], options: RegionClickOptions) => void;
|
||||||
|
onRegionLassoCommit?: () => void;
|
||||||
onOpenPianoRoll?: (regionId: string) => void;
|
onOpenPianoRoll?: (regionId: string) => void;
|
||||||
onOpenSpectrogram?: (regionId: string) => void;
|
onOpenSpectrogram?: (regionId: string) => void;
|
||||||
showHybridButtonForAudio?: boolean;
|
showHybridButtonForAudio?: boolean;
|
||||||
@@ -53,6 +54,7 @@ const TrackGridPanel: React.FC<TrackGridPanelProps> = ({
|
|||||||
onRegionUpdated,
|
onRegionUpdated,
|
||||||
onRegionClick,
|
onRegionClick,
|
||||||
onRegionLassoSelection,
|
onRegionLassoSelection,
|
||||||
|
onRegionLassoCommit,
|
||||||
onOpenPianoRoll,
|
onOpenPianoRoll,
|
||||||
onOpenSpectrogram,
|
onOpenSpectrogram,
|
||||||
showHybridButtonForAudio,
|
showHybridButtonForAudio,
|
||||||
@@ -160,12 +162,36 @@ const TrackGridPanel: React.FC<TrackGridPanelProps> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const intersectedRegionIds = intersectedRegions.map(region => region.id);
|
const intersectedRegionIds = intersectedRegions.map(region => region.id);
|
||||||
if (releaseRegionIndex > -1) {
|
if (intersectedRegionIds.length > 0) {
|
||||||
const [releaseRegionId] = intersectedRegionIds.splice(releaseRegionIndex, 1);
|
const primaryRegionIndex = releaseRegionIndex > -1
|
||||||
intersectedRegionIds.push(releaseRegionId);
|
? releaseRegionIndex
|
||||||
|
: intersectedRegions.reduce((closestIndex, region, index, allRegions) => {
|
||||||
|
const regionLeft = (region.barNumber - 1) * barWidth;
|
||||||
|
const regionRight = regionLeft + (region.length * barWidth);
|
||||||
|
const regionTop = region.trackIndex * 120;
|
||||||
|
const regionBottom = regionTop + 120;
|
||||||
|
const regionCenterX = (regionLeft + regionRight) / 2;
|
||||||
|
const regionCenterY = (regionTop + regionBottom) / 2;
|
||||||
|
const regionDistance = Math.hypot(releasePointX - regionCenterX, releasePointY - regionCenterY);
|
||||||
|
|
||||||
|
const closestRegion = allRegions[closestIndex];
|
||||||
|
const closestLeft = (closestRegion.barNumber - 1) * barWidth;
|
||||||
|
const closestRight = closestLeft + (closestRegion.length * barWidth);
|
||||||
|
const closestTop = closestRegion.trackIndex * 120;
|
||||||
|
const closestBottom = closestTop + 120;
|
||||||
|
const closestCenterX = (closestLeft + closestRight) / 2;
|
||||||
|
const closestCenterY = (closestTop + closestBottom) / 2;
|
||||||
|
const closestDistance = Math.hypot(releasePointX - closestCenterX, releasePointY - closestCenterY);
|
||||||
|
|
||||||
|
return regionDistance < closestDistance ? index : closestIndex;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const [primaryRegionId] = intersectedRegionIds.splice(primaryRegionIndex, 1);
|
||||||
|
intersectedRegionIds.push(primaryRegionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
onRegionLassoSelection?.(intersectedRegionIds, { shiftKey: isLassoShiftPressedRef.current });
|
onRegionLassoSelection?.(intersectedRegionIds, { shiftKey: isLassoShiftPressedRef.current });
|
||||||
|
onRegionLassoCommit?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
isLassoSelectingRef.current = false;
|
isLassoSelectingRef.current = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user