From 7d370df36e2354e606cab79170b393ce0226f831 Mon Sep 17 00:00:00 2001 From: Lumi Pakkanen Date: Thu, 16 May 2024 20:11:24 +0300 Subject: [PATCH] Upload scales to a server for sharing ref #456 --- .env.development | 1 + .gitignore | 3 + package.json | 2 +- src/App.vue | 10 +-- src/__tests__/util.spec.ts | 33 ++++++++- src/components/ExporterButtons.vue | 104 ++++++++++++++++++++--------- src/constants.ts | 3 + src/main.ts | 26 ++++++++ src/router/index.ts | 5 ++ src/scale.ts | 33 +++++++++ src/stores/scale.ts | 95 +++++++++++++++++++++++--- src/stores/state.ts | 13 ++-- src/utils.ts | 79 ++++++++++++++++++++++ src/views/LoadScaleView.vue | 65 ++++++++++++++++++ src/views/PreferencesView.vue | 9 +++ src/views/ScaleView.vue | 5 +- src/views/SynthView.vue | 4 +- src/views/VirtualKeyboardView.vue | 4 +- src/views/VirtualQwerty.vue | 4 +- 19 files changed, 436 insertions(+), 62 deletions(-) create mode 100644 .env.development create mode 100644 src/views/LoadScaleView.vue diff --git a/.env.development b/.env.development new file mode 100644 index 00000000..8ba9c0cf --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +VITE_API_URL=http://localhost:17461/ diff --git a/.gitignore b/.gitignore index 78710161..a1040d94 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ coverage *.njsproj *.sln *.sw? + +# Production secrets +.env.production diff --git a/package.json b/package.json index 0475f02e..660897f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scale-workshop", - "version": "3.0.0-beta.27", + "version": "3.0.0-beta.28", "scripts": { "dev": "vite", "build": "run-p type-check \"build-only {@}\" --", diff --git a/src/App.vue b/src/App.vue index 2fcbb06b..ffc9915b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -313,7 +313,7 @@ function typingKeydown(event: CoordinateKeyboardEvent) { let index = scale.scale.baseMidiNote + scale.scale.size * scale.equaveShift + scale.degreeShift if (scale.keyboardMode === 'isomorphic') { - index += x * state.isomorphicHorizontal + (2 - y) * state.isomorphicVertical + index += x * scale.isomorphicHorizontal + (2 - y) * scale.isomorphicVertical } else { if (scale.qwertyMapping.has(event.code)) { // QWERTY mapping incorporates shifts @@ -356,8 +356,8 @@ onMounted(() => { scale.userBaseFrequency = scaleWorkshopOneData.freq scale.autoFrequency = false scale.baseMidiNote = scaleWorkshopOneData.midi - state.isomorphicHorizontal = scaleWorkshopOneData.horizontal - state.isomorphicVertical = scaleWorkshopOneData.vertical + scale.isomorphicHorizontal = scaleWorkshopOneData.horizontal + scale.isomorphicVertical = scaleWorkshopOneData.vertical if (scaleWorkshopOneData.data !== undefined) { const colors = scaleWorkshopOneData.colors ?? '' @@ -394,8 +394,8 @@ onMounted(() => { scale.userBaseFrequency = decodedState.baseFrequency scale.autoFrequency = false scale.baseMidiNote = decodedState.baseMidiNote - state.isomorphicHorizontal = decodedState.isomorphicHorizontal - state.isomorphicVertical = decodedState.isomorphicVertical + scale.isomorphicHorizontal = decodedState.isomorphicHorizontal + scale.isomorphicVertical = decodedState.isomorphicVertical scale.keyboardMode = decodedState.keyboardMode scale.pianoMode = pianoMode scale.equaveShift = decodedState.equaveShift diff --git a/src/__tests__/util.spec.ts b/src/__tests__/util.spec.ts index 0cd95b97..7869a817 100644 --- a/src/__tests__/util.spec.ts +++ b/src/__tests__/util.spec.ts @@ -1,6 +1,13 @@ import { describe, it, expect } from 'vitest' -import { autoKeyColors, formatExponential, formatHertz, gapKeyColors } from '../utils' +import { + autoKeyColors, + encodeUrlSafe64, + formatExponential, + formatHertz, + gapKeyColors, + randomId +} from '../utils' function naiveExponential(x: number, fractionDigits = 3) { if (Math.abs(x) < 10000) { @@ -92,3 +99,27 @@ describe('Gap key color algorithm', () => { ) }) }) + +describe('URL safe number encoder', () => { + it('encodes the whole range', () => { + const expected = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-~' + for (let i = 0; i < 64; ++i) { + expect(encodeUrlSafe64(i)).toBe(expected[i]) + } + }) +}) + +describe('Unique ID generator', () => { + it('produces a short URL-friendly identifier', () => { + const urlSafe = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-~' + const id = randomId() + expect(id).toHaveLength(9) + for (const char of id) { + expect(urlSafe).toContain(char) + } + }) + + it("won't collide with this particular identifier for 30 years", () => { + expect(randomId()).not.toBe('oKh5gWb04') + }) +}) diff --git a/src/components/ExporterButtons.vue b/src/components/ExporterButtons.vue index 64626b9d..b366b91a 100644 --- a/src/components/ExporterButtons.vue +++ b/src/components/ExporterButtons.vue @@ -1,11 +1,11 @@ diff --git a/src/views/VirtualKeyboardView.vue b/src/views/VirtualKeyboardView.vue index 32c99e98..d42ad5fc 100644 --- a/src/views/VirtualKeyboardView.vue +++ b/src/views/VirtualKeyboardView.vue @@ -39,8 +39,8 @@ type NoteOnCallback = (index: number) => NoteOff v-else :baseIndex="baseIndex" :baseMidiNote="scale.scale.baseMidiNote" - :isomorphicHorizontal="state.isomorphicHorizontal" - :isomorphicVertical="state.isomorphicVertical" + :isomorphicHorizontal="scale.isomorphicHorizontal" + :isomorphicVertical="scale.isomorphicVertical" :colorMap="scale.colorForIndex" :noteOn="noteOn" :heldNotes="state.heldNotes" diff --git a/src/views/VirtualQwerty.vue b/src/views/VirtualQwerty.vue index b557e472..abd44f88 100644 --- a/src/views/VirtualQwerty.vue +++ b/src/views/VirtualQwerty.vue @@ -25,12 +25,12 @@ const baseIndex = computed(