From 1764731953f6f20739aa974d52b4e7d9eefc69ea Mon Sep 17 00:00:00 2001 From: Cyberflow Date: Wed, 1 Jul 2026 10:14:19 +0300 Subject: [PATCH] refactor: remove harmony A hotkey --- CHANGELOG.md | 2 +- JammLab/ContentView.swift | 2 -- JammLab/Utilities/AppHotkey.swift | 9 -------- .../AudioPlayerViewModel+Notes.swift | 4 ---- JammLabTests/TimelineProjectLogicTests.swift | 21 +++++++------------ JammLabTests/ViewModelLifecycleTests.swift | 4 ++-- 6 files changed, 11 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9177544..ff01a06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ development artifact builds use `vMAJOR.MINOR.PATCH-dev.N`. - Added boxed Region start labels to Notation in the timeline track and Notation window. - Added beat slash notation to Notation measures in the timeline track and Notation window. - Added a synced Notation window that opens from the View menu or the Notation track context menu, showing the full chart in a notebook-style layout while sharing harmony editing with the timeline track. -- Added a MusicXML-ready notation track MVP with synced staff measures, persisted harmony editing, snapped `A`-key insertion, adaptive measure fitting, and editable project key/mode selectors backed by auto-detected tonal metadata. +- Added a MusicXML-ready notation track MVP with synced staff measures, persisted harmony editing, adaptive measure fitting, and editable project key/mode selectors backed by auto-detected tonal metadata. - Fixed Notation key and time signature alignment for keys without accidentals and removed gaps between Notation window systems. - Fixed key-signature accidentals on the Notation track so sharps and flats render on the correct staff positions. diff --git a/JammLab/ContentView.swift b/JammLab/ContentView.swift index ec4c92e..84d3002 100644 --- a/JammLab/ContentView.swift +++ b/JammLab/ContentView.swift @@ -189,8 +189,6 @@ struct ContentView: View { viewModel.setLoopEndAtCurrentTime() case .addNote: viewModel.addNoteAtCurrentTime() - case .addHarmonyAtPlaybackMarker: - viewModel.requestAddHarmonyAtPlaybackMarker() case .addTempoTimeSignatureMarker: beginAddingTempoTimeSignatureMarker(at: viewModel.currentTime) case .setBeatOne: diff --git a/JammLab/Utilities/AppHotkey.swift b/JammLab/Utilities/AppHotkey.swift index 6834b2e..f12a218 100644 --- a/JammLab/Utilities/AppHotkey.swift +++ b/JammLab/Utilities/AppHotkey.swift @@ -7,7 +7,6 @@ enum AppHotkey: CaseIterable, Hashable { case setLoopStart case setLoopEnd case addNote - case addHarmonyAtPlaybackMarker case addTempoTimeSignatureMarker case setBeatOne case toggleClick @@ -53,8 +52,6 @@ enum AppHotkey: CaseIterable, Hashable { self = .setLoopEnd case 46: self = .addNote - case 0: - self = .addHarmonyAtPlaybackMarker case 11: self = .setBeatOne case 8: @@ -76,8 +73,6 @@ enum AppHotkey: CaseIterable, Hashable { return "]" case .addNote: return "M" - case .addHarmonyAtPlaybackMarker: - return "A" case .addTempoTimeSignatureMarker: return "Shift+C" case .setBeatOne: @@ -105,8 +100,6 @@ enum AppHotkey: CaseIterable, Hashable { return "Set Loop End" case .addNote: return "Add Marker" - case .addHarmonyAtPlaybackMarker: - return "Add Harmony" case .addTempoTimeSignatureMarker: return "Add Tempo / Time Signature Marker" case .setBeatOne: @@ -134,8 +127,6 @@ enum AppHotkey: CaseIterable, Hashable { return "Move loop end to the current playback position." case .addNote: return "Add a timecoded note at the current playback position." - case .addHarmonyAtPlaybackMarker: - return "Open a harmony editor at the position marker, snapped to the Notation track resolution." case .addTempoTimeSignatureMarker: return "Add a tempo or time signature change marker at the current playback position." case .setBeatOne: diff --git a/JammLab/ViewModels/AudioPlayerViewModel+Notes.swift b/JammLab/ViewModels/AudioPlayerViewModel+Notes.swift index 639f34a..f4b9b66 100644 --- a/JammLab/ViewModels/AudioPlayerViewModel+Notes.swift +++ b/JammLab/ViewModels/AudioPlayerViewModel+Notes.swift @@ -38,10 +38,6 @@ extension AudioPlayerViewModel { harmonyInputResolutionDenominator = HarmonyInputResolution.normalizedDenominator(denominator) } - func requestAddHarmonyAtPlaybackMarker() { - requestAddHarmony(at: playbackMarkerTime) - } - func requestAddHarmony(at time: TimeInterval) { guard duration > 0, let placement = harmonyPlacement(for: time, resolution: currentHarmonyInputResolution) diff --git a/JammLabTests/TimelineProjectLogicTests.swift b/JammLabTests/TimelineProjectLogicTests.swift index 17b4c76..1a2281c 100644 --- a/JammLabTests/TimelineProjectLogicTests.swift +++ b/JammLabTests/TimelineProjectLogicTests.swift @@ -610,8 +610,13 @@ final class TimelineProjectLogicTests: XCTestCase { ) } - func testAppHotkeyRecognizesAForHarmonyAtPlaybackMarker() throws { - let event = try XCTUnwrap(NSEvent.keyEvent( + func testAppHotkeyDoesNotExposeHarmonyShortcutMetadata() { + XCTAssertFalse(AppHotkey.allCases.contains { $0.key == "A" }) + XCTAssertFalse(AppHotkey.allCases.contains { $0.title == "Add Harmony" }) + } + + func testAppHotkeyDoesNotRecognizeAOrHForHarmony() throws { + let aEvent = try XCTUnwrap(NSEvent.keyEvent( with: .keyDown, location: .zero, modifierFlags: [], @@ -623,17 +628,6 @@ final class TimelineProjectLogicTests: XCTestCase { isARepeat: false, keyCode: 0 )) - - XCTAssertEqual(AppHotkey(event: event), .addHarmonyAtPlaybackMarker) - XCTAssertEqual(AppHotkey.addHarmonyAtPlaybackMarker.key, "A") - XCTAssertEqual(AppHotkey.addHarmonyAtPlaybackMarker.title, "Add Harmony") - XCTAssertEqual( - AppHotkey.addHarmonyAtPlaybackMarker.detail, - "Open a harmony editor at the position marker, snapped to the Notation track resolution." - ) - } - - func testAppHotkeyDoesNotRecognizeHOrModifiedAForHarmony() throws { let hEvent = try XCTUnwrap(NSEvent.keyEvent( with: .keyDown, location: .zero, @@ -671,6 +665,7 @@ final class TimelineProjectLogicTests: XCTestCase { keyCode: 0 )) + XCTAssertNil(AppHotkey(event: aEvent)) XCTAssertNil(AppHotkey(event: hEvent)) XCTAssertNil(AppHotkey(event: commandAEvent)) XCTAssertNil(AppHotkey(event: shiftAEvent)) diff --git a/JammLabTests/ViewModelLifecycleTests.swift b/JammLabTests/ViewModelLifecycleTests.swift index cd4b91a..a90756e 100644 --- a/JammLabTests/ViewModelLifecycleTests.swift +++ b/JammLabTests/ViewModelLifecycleTests.swift @@ -139,7 +139,7 @@ final class ViewModelLifecycleTests: XCTestCase { } @MainActor - func testRequestAddHarmonyAtPlaybackMarkerUsesNotationResolutionSnapWhilePlaying() throws { + func testRequestAddHarmonyAtTimeUsesNotationResolutionSnapWhilePlaying() throws { let engine = MockPlaybackEngine() engine.isLoaded = true let viewModel = AudioPlayerViewModel(playbackEngine: engine) @@ -155,7 +155,7 @@ final class ViewModelLifecycleTests: XCTestCase { XCTAssertEqual(viewModel.playbackMarkerTime, 1.26, accuracy: 0.0001) XCTAssertEqual(viewModel.currentTime, 3.0, accuracy: 0.0001) - viewModel.requestAddHarmonyAtPlaybackMarker() + viewModel.requestAddHarmony(at: 1.26) let request = try XCTUnwrap(viewModel.pendingHarmonyEditorRequest) XCTAssertEqual(request.time, 1.5, accuracy: 0.0001)