| 747 | } |
| 748 | |
| 749 | async function deleteTrack(id) { |
| 750 | state.swipedTrackId = null; |
| 751 | try { |
| 752 | await fetch(`/api/jobs/${id}`, { method: "DELETE" }); |
| 753 | } catch (e) { |
| 754 | console.warn("[mobile] delete failed:", e); |
| 755 | } |
| 756 | state.tracks = state.tracks.filter((t) => t.id !== id); |
| 757 | if (!state.tracks.length) state.libState = "empty"; |
| 758 | if (state.current?.id === id) { |
| 759 | if (engine) { engine.destroy(); engine = null; engineTrackId = null; engineReady = false; } |
| 760 | state.current = null; |
| 761 | state.playing = false; |
| 762 | } |
| 763 | toast("Track deleted"); |
| 764 | render(); |
| 765 | } |
| 766 | |
| 767 | // Faders + waveform seek need live pointer drag, so they're wired imperatively |
| 768 | // after each render (the rest of the UI uses click delegation below). |