diff --git a/src/components/ButtonPad/ButtonPad.css b/src/components/ButtonPad/ButtonPad.css index d4a5b6c..20cb356 100644 --- a/src/components/ButtonPad/ButtonPad.css +++ b/src/components/ButtonPad/ButtonPad.css @@ -5,6 +5,7 @@ border-radius: 8px; position: relative; overflow: hidden; + touch-action: manipulation; & canvas { position: absolute; diff --git a/src/components/SampleControls/SampleControls.tsx b/src/components/SampleControls/SampleControls.tsx index 6b99f10..fc490df 100644 --- a/src/components/SampleControls/SampleControls.tsx +++ b/src/components/SampleControls/SampleControls.tsx @@ -1,5 +1,6 @@ import { Component, createSignal } from 'solid-js'; +import { LABEL_CHAR_LIMIT } from 'src/defaults/constants'; import { useObservable } from 'src/hooks/useObservable'; import { SamplerModel } from 'src/models'; import { KnobWrapper } from '../Knob/KnobWrapper'; @@ -23,7 +24,7 @@ export const SampleControls: Component = (props) => { setLabel(e.currentTarget.value)} onKeyUp={(e) => { diff --git a/src/components/SampleExplorer/SampleExplorer.css b/src/components/SampleExplorer/SampleExplorer.css index 86d7a65..ec1db6e 100644 --- a/src/components/SampleExplorer/SampleExplorer.css +++ b/src/components/SampleExplorer/SampleExplorer.css @@ -53,6 +53,7 @@ display: flex; align-items: stretch; transition: background-color 0.15s; + touch-action: manipulation; & div { overflow-x: scroll; diff --git a/src/defaults/constants.ts b/src/defaults/constants.ts index b419e46..21398e2 100644 --- a/src/defaults/constants.ts +++ b/src/defaults/constants.ts @@ -6,3 +6,6 @@ export const DB_CLICK_THRESHOLD = 200; /** The number of samples in a waveform image */ export const WAVEFORM_SIZE = 760; + +/** Maximum Sampler label length */ +export const LABEL_CHAR_LIMIT = 12; diff --git a/src/hooks/useObservable.ts b/src/hooks/useObservable.ts index 6f3da9d..e348630 100644 --- a/src/hooks/useObservable.ts +++ b/src/hooks/useObservable.ts @@ -1,15 +1,15 @@ -import { onMount, createSignal, onCleanup, Accessor } from 'solid-js'; +import { onMount, createSignal, onCleanup, Accessor, Setter } from 'solid-js'; import { Observable, ObservableReadonly } from 'src/utils'; export function useObservable( observable: Observable, -): [Accessor, (value: T) => void]; +): [Accessor, Setter]; export function useObservable( observable: ObservableReadonly, ): [Accessor]; export function useObservable( observable: Observable | ObservableReadonly, -): [Accessor, (value: T) => void] | [T] { +): [Accessor, (v: T) => void] | [Accessor] { const [signal, setSignal] = createSignal(observable.value); const updateFunc = (v: T) => { setSignal(() => v); diff --git a/src/models/SamplerModel.ts b/src/models/SamplerModel.ts index 928e7dc..069231c 100644 --- a/src/models/SamplerModel.ts +++ b/src/models/SamplerModel.ts @@ -1,5 +1,7 @@ +import { LABEL_CHAR_LIMIT } from 'src/defaults/constants'; import { AppStore } from 'src/store'; import { Observable } from 'src/utils'; +import { getFilename } from 'src/utils/getFilename'; export class SamplerModel { public readonly src: Observable; @@ -16,15 +18,20 @@ export class SamplerModel { private readonly _preservePitch = new Observable(false); - private readonly onSrcUpdate = async (src: string) => { - if (!src) { - return; - } + private async updateBuffer(): Promise { const data = await AppStore.instance.getSampleBlob(this.src.value); if (!data) { throw new Error(`Sample '${this.src.value}' not found`); } this._buffer.value = await data.arrayBuffer(); + } + + private readonly onSrcUpdate = async (src: string) => { + this.label.value = getFilename(src).substring(0, LABEL_CHAR_LIMIT); + if (!src) { + return; + } + await this.updateBuffer(); }; private readonly onBufferUpdate = async () => { diff --git a/src/utils/getFilename.ts b/src/utils/getFilename.ts new file mode 100644 index 0000000..34d06bf --- /dev/null +++ b/src/utils/getFilename.ts @@ -0,0 +1,9 @@ +/** + * Get the filename without extension from a full path + * @param path full file path + * @returns + */ +export function getFilename(path: string): string { + const fileWithExt = path.split(/.*[\/|\\]/).at(-1) ?? ''; + return fileWithExt.replace(/\..*$/, ''); +}