|
@@ -6,9 +6,11 @@
|
|
|
import BankBar from "./lib/BankBar.svelte";
|
|
import BankBar from "./lib/BankBar.svelte";
|
|
|
import ConfirmModal from "./lib/ConfirmModal.svelte";
|
|
import ConfirmModal from "./lib/ConfirmModal.svelte";
|
|
|
import PadPanel from "./lib/PadPanel.svelte";
|
|
import PadPanel from "./lib/PadPanel.svelte";
|
|
|
|
|
+ import PadPicker from "./lib/PadPicker.svelte";
|
|
|
|
|
+ import { transfer, transferKind } from "./lib/pads";
|
|
|
import SequencePanel from "./lib/SequencePanel.svelte";
|
|
import SequencePanel from "./lib/SequencePanel.svelte";
|
|
|
import SlotGrid, { type Cell } from "./lib/SlotGrid.svelte";
|
|
import SlotGrid, { type Cell } from "./lib/SlotGrid.svelte";
|
|
|
- import { app, exportFolder, exportZip, listen, message, newProject, refresh, run, ui, type Tab } from "./lib/store.svelte";
|
|
|
|
|
|
|
+ import { app, exportFolder, exportZip, listen, loadProject, message, newProject, refresh, run, ui, type Tab } from "./lib/store.svelte";
|
|
|
import { BANKS, PER_BANK, bars, gridSlots, tuneText } from "./lib/slots";
|
|
import { BANKS, PER_BANK, bars, gridSlots, tuneText } from "./lib/slots";
|
|
|
|
|
|
|
|
onMount(() => {
|
|
onMount(() => {
|
|
@@ -38,13 +40,13 @@
|
|
|
st
|
|
st
|
|
|
? gridSlots(ui.padBank).map((slot) => {
|
|
? gridSlots(ui.padBank).map((slot) => {
|
|
|
const p = pads[slot];
|
|
const p = pads[slot];
|
|
|
- const badges = [tuneText(p.coarse, p.fine), p.muteGroup ? "M" + p.muteGroup : ""].filter(Boolean);
|
|
|
|
|
|
|
+ const badges = [tuneText(p.coarse, p.fine), p.muteGroup ? "M" + p.muteGroup : "", p.hasNotes ? "notes" : ""].filter(Boolean);
|
|
|
return {
|
|
return {
|
|
|
slot,
|
|
slot,
|
|
|
label: p.label,
|
|
label: p.label,
|
|
|
name: p.name,
|
|
name: p.name,
|
|
|
meta: p.file ? badges.join(" · ") : "",
|
|
meta: p.file ? badges.join(" · ") : "",
|
|
|
- aria: `Pad ${p.label}, ${p.file || "empty"}`,
|
|
|
|
|
|
|
+ aria: `Pad ${p.label}, ${p.file || "empty"}${p.hasNotes ? ", has recorded notes" : ""}`,
|
|
|
};
|
|
};
|
|
|
})
|
|
})
|
|
|
: [],
|
|
: [],
|
|
@@ -79,6 +81,11 @@
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // A pad dropped on another: move, swap onto a filled pad, Alt to copy.
|
|
|
|
|
+ function dropPad(from: number, to: number, copy: boolean) {
|
|
|
|
|
+ transfer(transferKind(pads[from], pads[to], copy), from, to);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
async function rename(e: Event & { currentTarget: HTMLInputElement }) {
|
|
async function rename(e: Event & { currentTarget: HTMLInputElement }) {
|
|
|
const input = e.currentTarget;
|
|
const input = e.currentTarget;
|
|
|
const name = input.value;
|
|
const name = input.value;
|
|
@@ -109,7 +116,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
<div class="actions">
|
|
<div class="actions">
|
|
|
<button type="button" class="btn" onclick={newProject}>New</button>
|
|
<button type="button" class="btn" onclick={newProject}>New</button>
|
|
|
- <button type="button" class="btn" disabled>Load</button>
|
|
|
|
|
|
|
+ <button type="button" class="btn" onclick={loadProject}>Load</button>
|
|
|
<button type="button" class="btn" onclick={exportZip}>Export zip</button>
|
|
<button type="button" class="btn" onclick={exportZip}>Export zip</button>
|
|
|
<button type="button" class="btn primary" onclick={exportFolder}>Export to folder</button>
|
|
<button type="button" class="btn primary" onclick={exportFolder}>Export to folder</button>
|
|
|
</div>
|
|
</div>
|
|
@@ -144,9 +151,10 @@
|
|
|
ui.padBank = b;
|
|
ui.padBank = b;
|
|
|
ui.padSlot = b * PER_BANK;
|
|
ui.padSlot = b * PER_BANK;
|
|
|
}}
|
|
}}
|
|
|
|
|
+ ondragbank={(b) => (ui.padBank = b)}
|
|
|
/>
|
|
/>
|
|
|
- <SlotGrid cells={padCells} selected={ui.padSlot} onpick={pickPad} dropTarget />
|
|
|
|
|
- <p class="hint grid-hint">Click a pad to select and hear it. Drop a WAV file on any pad to assign it. (Dragging pads to move, swap and copy them comes in M6.)</p>
|
|
|
|
|
|
|
+ <SlotGrid cells={padCells} selected={ui.padSlot} onpick={pickPad} dropTarget ondroppad={dropPad} />
|
|
|
|
|
+ <p class="hint grid-hint">Click a pad to select and hear it. Drag a pad to move it, drag onto a filled pad to swap, hold Alt while dragging to copy. Drag over a bank letter to reach another bank. Drop a WAV file on any pad to assign it.</p>
|
|
|
</section>
|
|
</section>
|
|
|
<PadPanel pad={pads[ui.padSlot]} limits={st.limits} />
|
|
<PadPanel pad={pads[ui.padSlot]} limits={st.limits} />
|
|
|
</div>
|
|
</div>
|
|
@@ -187,6 +195,9 @@
|
|
|
{#if ui.aboutOpen}
|
|
{#if ui.aboutOpen}
|
|
|
<AboutModal onclose={() => (ui.aboutOpen = false)} />
|
|
<AboutModal onclose={() => (ui.aboutOpen = false)} />
|
|
|
{/if}
|
|
{/if}
|
|
|
|
|
+ {#if ui.picker && st}
|
|
|
|
|
+ <PadPicker picker={ui.picker} pads={pads} onclose={() => (ui.picker = null)} />
|
|
|
|
|
+ {/if}
|
|
|
{#if ui.confirm}
|
|
{#if ui.confirm}
|
|
|
<ConfirmModal c={ui.confirm} />
|
|
<ConfirmModal c={ui.confirm} />
|
|
|
{/if}
|
|
{/if}
|