Skip to content

Commit

Permalink
move progression string state to URL
Browse files Browse the repository at this point in the history
  • Loading branch information
marginalhours committed Nov 26, 2023
1 parent fd2356a commit 128da47
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 64 deletions.
18 changes: 13 additions & 5 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
import {
tonic,
progression,
chords,
randomizeApp,
randomizeTonic,
randomizeProgression,
setTonic,
previousProgression,
nextProgression
nextProgression,
trySetProgressionFromURL
} from './progressionStore';
import { relativeChordToString } from '$lib/music/relativeChord';
import Chevron from './Chevron.svelte';
Expand All @@ -21,6 +21,14 @@
e.preventDefault();
}
};
const onHashChange = () => {
trySetProgressionFromURL();
};
const onLoad = () => {
trySetProgressionFromURL();
};
</script>

<svelte:head>
Expand All @@ -46,8 +54,8 @@
<h1>Ukulele Chord Progressions</h1>
</section>
<section class="fretting-section">
{#each $chords as _, index}
<ChordPanel tonic={$tonic} chord={$chords[index]} relativeChord={$progression[index]} />
{#each $progression as relativeChord}
<ChordPanel tonic={$tonic} {relativeChord} />
{/each}
</section>
<section class="progression-section">
Expand Down Expand Up @@ -95,7 +103,7 @@
</section>
</main>

<svelte:window on:keydown={onKeyDown} />
<svelte:window on:keydown={onKeyDown} on:hashchange={onHashChange} on:load={onLoad} />

<style>
main {
Expand Down
8 changes: 4 additions & 4 deletions src/routes/ChordPanel.svelte
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<script lang="ts">
import ChordDiagram from './ChordDiagram.svelte';
import { relativeChordToString, type RelativeChord } from '../lib/music/relativeChord';
import { type Chord, flatAwareChordToString } from '../lib/music/chords';
import { type Chord, flatAwareChordToString, intervalToChord } from '../lib/music/chords';
import Chevron from './Chevron.svelte';
import type { PitchWithFlats } from '../lib/music/types';
import { getFrettingsForChord } from '$lib/frettings';
import { getFrettingsForChord } from '../lib/frettings';
export let tonic: PitchWithFlats;
export let relativeChord: RelativeChord;
export let chord: Chord;
const resetOffset = (_: Chord) => 0;
$: availableFrettings = getFrettingsForChord(chord);
$: frettingOffset = resetOffset(chord);
$: chord = intervalToChord(tonic, relativeChord);
const onPreviousFretting = () => {
frettingOffset = (availableFrettings.length + frettingOffset - 1) % availableFrettings.length;
Expand All @@ -36,7 +36,7 @@
VIII: '#9b5fe0'
};
$: backgroundColor = BACKGROUNDS[relativeChord.number];
$: backgroundColor = BACKGROUNDS[relativeChord?.number];
</script>

<div class="chord-panel-wrapper">
Expand Down
96 changes: 41 additions & 55 deletions src/routes/progressionStore.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,43 @@
import { writable, derived } from 'svelte/store';
import { chooseWithout } from '../lib/utilities';
import {
progression as $,
progressionFromString,
type RelativeChord
} from '../lib/music/relativeChord';
import { pitches, type Pitch, type PitchWithFlats, pitchesWithFlats } from '../lib/music/types';
import { progressionFromString, type RelativeChord } from '../lib/music/relativeChord';
import { type Pitch, type PitchWithFlats, pitchesWithFlats } from '../lib/music/types';
import { intervalToChord } from '../lib/music/chords';
import { getFrettingsForChord } from '../lib/frettings';
import { browser } from '$app/environment';

const progressions = [
$`I-vi-IV-V`, // 1950s do-wop
$`vi-IV-I-V`, // 4 chords
$`I-V-vi-IV`, // the other 4 chords
$`I-V-vi-iii-IV-I-IV-V`, // hey pachelbel,
$`ii-V-I-vi`,
$`I-III7-IV-iv`, //
$`I-IIIdim-IV-V7`,
$`III7-vi-iv-I`,
$`i-iv-V7`, // spooky
$`I-III-IV-iv`, // creep
$`I-VI7-II7-V-I`, // circus cadence
$`IV-ii-v-I`, // more minor,
$`v-ii-IV-I`, // ditto but moved around
$`i7-IV-bVII-v`,
$`i-V7-i-bVII-bIII-bVII-i`, // La Follia
$`i-iv-bVI-V`,
$`i-V7-v7-IV-bVI-bIII-IV-V7`, // hotel california
$`I-Imaj7-I7-IV-V6-VI7-ii-V`
`I-vi-IV-V`, // 1950s do-wop
`I-III7-IV-iv`, //
`vi-IV-I-V`, // 4 chords
`I-V-vi-IV`, // the other 4 chords
`I-V-vi-iii-IV-I-IV-V`, // hey pachelbel,
`ii-V-I-vi`,
`I-IIIdim-IV-V7`,
`III7-vi-iv-I`,
`i-iv-V7`, // spooky
`I-III-IV-iv`, // creep
`I-VI7-II7-V-I`, // circus cadence
`IV-ii-v-I`, // more minor,
`v-ii-IV-I`, // ditto but moved around
`i7-IV-bVII-v`,
`i-V7-i-bVII-bIII-bVII-i`, // La Follia
`i-iv-bVI-V`,
`i-V7-v7-IV-bVI-bIII-IV-V7`, // hotel california
`I-Imaj7-I7-IV-V6-VI7-ii-V`
];

// G-G5-D-Adim7(no3)-Adim7-Em-A-D-D75 This sounds good

const tonic = writable<PitchWithFlats>('C');
const progressionIndex = writable<number>(0);

/**
* Update progression based on index... unless there's a location hash,
* in which case use that.
*/
const progression = derived([progressionIndex], ([$progressionIndex]) => {
return hasProgressionInUrlHash() ? progressionFromURLHash() : progressions[$progressionIndex];
});

const chords = derived([tonic, progression], ([$tonic, $progression]) =>
$progression.map((interval) => intervalToChord($tonic, interval))
);
// In fact this is mostly backed by the URL which is nice because hackable
const progression = writable<RelativeChord[]>(progressionFromString(progressions[0]));

const frettings = derived([chords], ([$chords]) => {
return $chords.map(getFrettingsForChord);
progressionIndex.subscribe((index) => {
if (browser) {
window.location.hash = progressions[index];
}
});

// Mutators
Expand All @@ -58,17 +46,11 @@ const setTonic = (newTonic: Pitch) => {
tonic.set(newTonic);
};

const randomizeApp = () => {
randomizeTonic();
randomizeProgression();
};

const randomizeTonic = () => {
tonic.update((current) => chooseWithout(pitchesWithFlats, current));
};

const randomizeProgression = () => {
resetURLHashProgression();
progressionIndex.update((current) =>
chooseWithout(
progressions.map((_, index) => index),
Expand All @@ -78,24 +60,33 @@ const randomizeProgression = () => {
};

const previousProgression = () => {
resetURLHashProgression();
progressionIndex.update((current) => (progressions.length + current - 1) % progressions.length);
};

const nextProgression = () => {
resetURLHashProgression();
progressionIndex.update((current) => (progressions.length + current + 1) % progressions.length);
};

const randomizeApp = () => {
randomizeTonic();
randomizeProgression();
};

// URL hash utilities

const trySetProgressionFromURL = () => {
if (hasProgressionInUrlHash()) {
progression.set(progressionFromURLHash());
}
};

const hasProgressionInUrlHash = () => {
if (!(browser && window.location.hash)) {
return false;
}

try {
const _ = $`${window.location.hash.substring(1)}`;
const _ = progressionFromString(window.location.hash.substring(1));
} catch (err) {
return false;
}
Expand All @@ -107,19 +98,14 @@ const progressionFromURLHash = () => {
return progressionFromString(window.location.hash.substring(1));
};

const resetURLHashProgression = () => {
window.location.hash = '';
};

export {
tonic,
progression,
chords,
frettings,
setTonic,
randomizeApp,
randomizeTonic,
randomizeProgression,
previousProgression,
nextProgression
nextProgression,
trySetProgressionFromURL,
randomizeApp
};

0 comments on commit 128da47

Please sign in to comment.