feat: persist piano roll zoom level into project; fixed an issue in the horizontal auto-scrolling logic in piano roll window

This commit is contained in:
Xiaohan-Tian
2026-05-18 22:21:00 -07:00
parent 97dad696b2
commit a0fe283ab5
15 changed files with 321 additions and 22 deletions
@@ -10,6 +10,7 @@ import { upgradeToV8 } from './upgradeToV8';
import { upgradeToV9 } from './upgradeToV9';
import { upgradeToV10 } from './upgradeToV10';
import { upgradeToV11 } from './upgradeToV11';
import { upgradeToV12 } from './upgradeToV12';
/**
* Upgrade the given project to the latest structure version, one version at a time.
@@ -73,6 +74,10 @@ export function upgradeProjectToLatest(project: KGProject): KGProject {
workingProject = upgradeToV11(workingProject);
break;
}
case 12: {
workingProject = upgradeToV12(workingProject);
break;
}
default: {
// If an upgrader is missing, throw to prevent loading incompatible structures
throw new Error(`No upgrader found for project structure version ${nextVersion}`);
@@ -26,7 +26,7 @@ describe('upgradeToV10', () => {
const upgraded = upgradeProjectToLatest(project);
expect(upgraded.getProjectStructureVersion()).toBe(11);
expect(upgraded.getProjectStructureVersion()).toBe(KGProject.CURRENT_PROJECT_STRUCTURE_VERSION);
expect(upgraded.getTracks()[0].getVolumeAutomation()).toHaveLength(1);
});
});
@@ -38,7 +38,7 @@ describe('upgradeToV11', () => {
const upgraded = upgradeProjectToLatest(project);
expect(upgraded.getProjectStructureVersion()).toBe(11);
expect(upgraded.getProjectStructureVersion()).toBe(KGProject.CURRENT_PROJECT_STRUCTURE_VERSION);
expect(upgraded.getTracks()[0].getMuted()).toBe(false);
expect(upgraded.getTracks()[0].getSolo()).toBe(false);
});
@@ -0,0 +1,39 @@
import { describe, expect, it } from 'vitest';
import { KGProject } from '../KGProject';
import { upgradeProjectToLatest } from './KGProjectUpgrader';
import { upgradeToV12 } from './upgradeToV12';
describe('upgradeToV12', () => {
it('initializes missing zoom levels to 1', () => {
const project = new KGProject('Legacy', 32, 0, 125, undefined, undefined, undefined, undefined, [0, 0], 1, [], 11);
delete (project as unknown as { barWidthMultiplier?: unknown }).barWidthMultiplier;
delete (project as unknown as { pianoRollZoom?: unknown }).pianoRollZoom;
upgradeToV12(project);
expect(project.getBarWidthMultiplier()).toBe(1);
expect(project.getPianoRollZoom()).toBe(1);
expect(project.getProjectStructureVersion()).toBe(12);
});
it('preserves existing zoom levels', () => {
const project = new KGProject('Legacy', 32, 0, 125, undefined, undefined, undefined, undefined, [0, 0], 4, [], 11, 6);
upgradeToV12(project);
expect(project.getBarWidthMultiplier()).toBe(4);
expect(project.getPianoRollZoom()).toBe(6);
});
it('upgrades legacy projects through the main upgrader path', () => {
const project = new KGProject('Legacy', 32, 0, 125, undefined, undefined, undefined, undefined, [0, 0], 1, [], 11);
delete (project as unknown as { barWidthMultiplier?: unknown }).barWidthMultiplier;
delete (project as unknown as { pianoRollZoom?: unknown }).pianoRollZoom;
const upgraded = upgradeProjectToLatest(project);
expect(upgraded.getProjectStructureVersion()).toBe(KGProject.CURRENT_PROJECT_STRUCTURE_VERSION);
expect(upgraded.getBarWidthMultiplier()).toBe(1);
expect(upgraded.getPianoRollZoom()).toBe(1);
});
});
+23
View File
@@ -0,0 +1,23 @@
import { KGProject } from '../KGProject';
function isValidZoomLevel(value: unknown): value is number {
return typeof value === 'number' && Number.isFinite(value) && value > 0;
}
export function upgradeToV12(project: KGProject): KGProject {
try {
const barWidthMultiplier = project.getBarWidthMultiplier?.();
if (!isValidZoomLevel(barWidthMultiplier)) {
project.setBarWidthMultiplier(1);
}
const pianoRollZoom = project.getPianoRollZoom?.();
if (!isValidZoomLevel(pianoRollZoom)) {
project.setPianoRollZoom(1);
}
} finally {
project.setProjectStructureVersion(12);
}
return project;
}
@@ -57,7 +57,7 @@ describe('upgradeToV8', () => {
const upgraded = upgradeProjectToLatest(project);
expect(upgraded.getProjectStructureVersion()).toBe(11);
expect(upgraded.getProjectStructureVersion()).toBe(KGProject.CURRENT_PROJECT_STRUCTURE_VERSION);
expect((upgraded.getTracks()[0].getRegions()[0] as KGMidiRegion).getPitchBends()).toEqual([]);
expect((upgraded.getTracks()[0].getRegions()[0] as KGMidiRegion).getControllerEventsByType()).toHaveLength(128);
});