From c3030965f95a24bfc9b7c454e10b51bf41f70d57 Mon Sep 17 00:00:00 2001 From: AndyMac4321 <76612952+AndyMac4321@users.noreply.github.com> Date: Tue, 15 Apr 2025 01:18:49 -0700 Subject: [PATCH 1/7] Feature Combine Scores Adds Score selection on each score. Once 2 scores are selected enables the Combine Scores button. The scores selected are then combined into one score. Combines name, composer, staves and secondTimings. Texts are not combined and only first score will retain texts. Harmonies are not combined.(yet) Order of selection determines order of scores combined. --- src/Scores/scores.ts | 111 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 4 deletions(-) diff --git a/src/Scores/scores.ts b/src/Scores/scores.ts index abfabd96..ebdf8b39 100644 --- a/src/Scores/scores.ts +++ b/src/Scores/scores.ts @@ -36,11 +36,13 @@ const auth = new Auth({ apiKey: apiToken }); const db = new Database({ projectId: 'pipe-score', auth }); -type ScoreRef = { path: string }; +type ScoreRef = { name: string; path: string }; type FileInput = HTMLInputElement & { files: FileList }; -function getName(score: Document | ScoreRef | SavedScore | DeprecatedSavedScore) { +function getName( + score: Document | ScoreRef | SavedScore | DeprecatedSavedScore +) { const defaultName = 'Empty Score'; if ((score as DeprecatedSavedScore).name) { return (score as DeprecatedSavedScore).name || defaultName; @@ -67,10 +69,35 @@ function setName( s.tunes[0].name = name; } } +function getComposer( + score: Document | ScoreRef | SavedScore +) { + const defaultName = 'Composer'; + const sscore = score as SavedScore; + const composer = sscore.tunes?.[0]?.composer; + + if (typeof composer === 'string') { + return composer || defaultName; + } + + return composer.text || defaultName; +} +function setComposer( + score: Document | ScoreRef | SavedScore , + composer: string +) { + const s = score as SavedScore | DeprecatedSavedScore; + if (scoreHasStavesNotTunes(s)) { + s.name = composer; + } else if (s.tunes[0]) { + s.tunes[0].composer = composer; + } +} class ScoresList { loading = true; scores: ScoreRef[] = []; + selected: ScoreRef[] = []; oninit() { onUserChange(auth, (user) => { @@ -151,7 +178,46 @@ class ScoresList { this.refreshScores(); } } + async updateSelection(scoreRef: ScoreRef, checked: boolean) { + if (checked) { + this.selected.push(scoreRef); + } else { + let index = this.selected.indexOf(scoreRef); + if (index > -1) { + this.selected.splice(index, 1); + } + } + m.redraw(); + } + async combineScores() { + this.loading = true; + try { + const scores: SavedScore[] = []; + for (const score of this.selected) { + scores.push( + (await db.ref(`scores${score.path}`).get()) as unknown as SavedScore + ); + } + setName(scores[0], `(Combined)${getName(scores[0])}`); + for (let i = 1; i < scores.length; i++) { + setName(scores[0], `${getName(scores[0])} - ${getName(scores[i])}`); + setComposer(scores[0], `${getComposer(scores[0])} - ${getComposer(scores[i])}`); + for (const stave of scores[i].tunes[0].staves) { + scores[0].tunes[0].staves.push(stave); + } + for (const secondTiming of scores[i].secondTimings) { + scores[0].secondTimings.push(secondTiming); + } + } + await db.ref(`scores/${userId}/scores`).add(scores[0]); + } catch (e) { + console.log(e); + alert(`Error combining scores: ${(e as Error).name}`); + } + this.selected = []; + this.refreshScores(); + } async refreshScores() { const collection = await db.ref(`scores/${userId}/scores`).list({ pageSize: 1000, @@ -175,6 +241,24 @@ class ScoresList { `/pipescore${score.path.replace('/scores/', '/')}`; return [ + m('p', 'Selected Scores:'), + m('table', [ + ...this.selected.map((score) => + m('tr', [ + m('td.td-name', m('a', { href: path(score) }, getName(score))), + ]) + ), + m('tr', [ + m( + 'button.edit', + { + onclick: () => this.combineScores(), + disabled: this.selected.length < 2, + }, + 'Combine Scores' + ), + ]), + ]), m('p', 'Scores:'), this.scores.length === 0 ? m('p', 'You have no scores.') : null, m('table', [ @@ -191,7 +275,11 @@ class ScoresList { ), m( 'td', - m('button.rename', { onclick: () => this.rename(score) }, 'Rename') + m( + 'button.rename', + { onclick: () => this.rename(score) }, + 'Rename' + ) ), m( 'td', @@ -203,7 +291,22 @@ class ScoresList { ), m( 'td', - m('button.delete', { onclick: () => this.delete(score) }, 'Delete') + m( + 'button.delete', + { onclick: () => this.delete(score) }, + 'Delete' + ) + ), + m( + 'td', + m('input', { + type: 'checkbox', + onchange: (e: InputEvent) => + this.updateSelection( + score, + Boolean((e.target as HTMLInputElement).checked) + ), + }) ), ]) ), From 78a9d976740d83043d84981e2cf8509c134b5e89 Mon Sep 17 00:00:00 2001 From: AndyMac4321 <76612952+AndyMac4321@users.noreply.github.com> Date: Tue, 15 Apr 2025 01:51:49 -0700 Subject: [PATCH 2/7] Combines at Tune element Adds Score selection on each score in list. Once 2 scores are selected enables the Combine Scores button. The scores selected are then combined into one score. Combines name of each score into first score, adds tunes from subsequent scores to first score. Order of selection determines order of scores combined. --- src/Scores/scores.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Scores/scores.ts b/src/Scores/scores.ts index ebdf8b39..643af37e 100644 --- a/src/Scores/scores.ts +++ b/src/Scores/scores.ts @@ -201,13 +201,7 @@ class ScoresList { setName(scores[0], `(Combined)${getName(scores[0])}`); for (let i = 1; i < scores.length; i++) { setName(scores[0], `${getName(scores[0])} - ${getName(scores[i])}`); - setComposer(scores[0], `${getComposer(scores[0])} - ${getComposer(scores[i])}`); - for (const stave of scores[i].tunes[0].staves) { - scores[0].tunes[0].staves.push(stave); - } - for (const secondTiming of scores[i].secondTimings) { - scores[0].secondTimings.push(secondTiming); - } + scores[0].tunes.push(scores[i].tunes[0]); } await db.ref(`scores/${userId}/scores`).add(scores[0]); @@ -250,7 +244,7 @@ class ScoresList { ), m('tr', [ m( - 'button.edit', + 'button.combine', { onclick: () => this.combineScores(), disabled: this.selected.length < 2, From 2ced1e096745c00fa1724e2aec24d785861b9bf0 Mon Sep 17 00:00:00 2001 From: AndyMac4321 <76612952+AndyMac4321@users.noreply.github.com> Date: Tue, 15 Apr 2025 03:04:01 -0700 Subject: [PATCH 3/7] Fix table structure fix table structure --- src/Scores/scores.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Scores/scores.ts b/src/Scores/scores.ts index 643af37e..9b166ef2 100644 --- a/src/Scores/scores.ts +++ b/src/Scores/scores.ts @@ -244,12 +244,15 @@ class ScoresList { ), m('tr', [ m( - 'button.combine', - { - onclick: () => this.combineScores(), - disabled: this.selected.length < 2, - }, - 'Combine Scores' + 'td', + m( + 'button.combine', + { + onclick: () => this.combineScores(), + disabled: this.selected.length < 2, + }, + 'Combine Scores' + ), ), ]), ]), From 51517629aab36d466a17c6839ba1c100c6b0aad9 Mon Sep 17 00:00:00 2001 From: AndyMac4321 <76612952+AndyMac4321@users.noreply.github.com> Date: Tue, 15 Apr 2025 03:27:27 -0700 Subject: [PATCH 4/7] Removed unused code Removed unused code --- .gitignore | 4 ++++ src/Scores/scores.ts | 29 ++++------------------------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 5410f6c2..dbadbc5f 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ tsserver.log __pycache__ .DS_Store +.vscode +*.aup3-shm +*.aup3-wal +*.aup3 \ No newline at end of file diff --git a/src/Scores/scores.ts b/src/Scores/scores.ts index 9b166ef2..ed1bde08 100644 --- a/src/Scores/scores.ts +++ b/src/Scores/scores.ts @@ -69,31 +69,6 @@ function setName( s.tunes[0].name = name; } } -function getComposer( - score: Document | ScoreRef | SavedScore -) { - const defaultName = 'Composer'; - const sscore = score as SavedScore; - const composer = sscore.tunes?.[0]?.composer; - - if (typeof composer === 'string') { - return composer || defaultName; - } - - return composer.text || defaultName; -} - -function setComposer( - score: Document | ScoreRef | SavedScore , - composer: string -) { - const s = score as SavedScore | DeprecatedSavedScore; - if (scoreHasStavesNotTunes(s)) { - s.name = composer; - } else if (s.tunes[0]) { - s.tunes[0].composer = composer; - } -} class ScoresList { loading = true; scores: ScoreRef[] = []; @@ -202,6 +177,10 @@ class ScoresList { for (let i = 1; i < scores.length; i++) { setName(scores[0], `${getName(scores[0])} - ${getName(scores[i])}`); scores[0].tunes.push(scores[i].tunes[0]); + for(const secondTiming of scores[i].secondTimings) + { + scores[0].secondTimings.push(secondTiming); + } } await db.ref(`scores/${userId}/scores`).add(scores[0]); From a55a6e7730d0dba9d19d8d7c23fb1ea47ed23edc Mon Sep 17 00:00:00 2001 From: AndyMac4321 <76612952+AndyMac4321@users.noreply.github.com> Date: Tue, 15 Apr 2025 03:52:51 -0700 Subject: [PATCH 5/7] Update todo.md Marked Importing tunes into other scores as done Slightly different implementation Combining multiple scores into a single score/document --- todo.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/todo.md b/todo.md index b918a7c5..94d3797d 100644 --- a/todo.md +++ b/todo.md @@ -13,11 +13,12 @@ - [x] View-only mode for mobile - [ ] Note in docs about keyboard-based - [x] Fix harmony playback -- [ ] Importing tunes into other scores +- [x] Importing tunes into other scores/ Combining multiple scores into a single score/document - [ ] Count ins - [ ] Password change - [ ] Chanter playback - [ ] Metronome while playing +- [ ] Allow for people other than who entered the tune to play it back. ## Bugs to fix From 646bd92fe4930cccb7116e43d14ff66e71726804 Mon Sep 17 00:00:00 2001 From: AndyMac4321 <76612952+AndyMac4321@users.noreply.github.com> Date: Tue, 15 Apr 2025 04:13:02 -0700 Subject: [PATCH 6/7] Cleanup Test/Lint etc Pretty format Lint --- src/Scores/scores.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Scores/scores.ts b/src/Scores/scores.ts index ed1bde08..469503fb 100644 --- a/src/Scores/scores.ts +++ b/src/Scores/scores.ts @@ -177,13 +177,11 @@ class ScoresList { for (let i = 1; i < scores.length; i++) { setName(scores[0], `${getName(scores[0])} - ${getName(scores[i])}`); scores[0].tunes.push(scores[i].tunes[0]); - for(const secondTiming of scores[i].secondTimings) - { + for (const secondTiming of scores[i].secondTimings) { scores[0].secondTimings.push(secondTiming); } } await db.ref(`scores/${userId}/scores`).add(scores[0]); - } catch (e) { console.log(e); alert(`Error combining scores: ${(e as Error).name}`); @@ -231,7 +229,7 @@ class ScoresList { disabled: this.selected.length < 2, }, 'Combine Scores' - ), + ) ), ]), ]), From aad39aa675b339f6658057e04511f076538036de Mon Sep 17 00:00:00 2001 From: AndyMac4321 <76612952+AndyMac4321@users.noreply.github.com> Date: Tue, 15 Apr 2025 04:49:54 -0700 Subject: [PATCH 7/7] Update scores.ts Fixed issue with sticky checkboxes --- src/Scores/scores.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Scores/scores.ts b/src/Scores/scores.ts index 469503fb..50d71c65 100644 --- a/src/Scores/scores.ts +++ b/src/Scores/scores.ts @@ -186,10 +186,10 @@ class ScoresList { console.log(e); alert(`Error combining scores: ${(e as Error).name}`); } - this.selected = []; this.refreshScores(); } async refreshScores() { + this.selected = []; const collection = await db.ref(`scores/${userId}/scores`).list({ pageSize: 1000, }); @@ -275,6 +275,7 @@ class ScoresList { 'td', m('input', { type: 'checkbox', + checked: this.selected.indexOf(score) != -1, onchange: (e: InputEvent) => this.updateSelection( score,