feat(02-03): build transport UI and waveform canvas

- Replace timeline placeholder with waveform canvas + playback cursor
- Replace transport placeholder with full transport bar controls
- Add play/pause/stop buttons, seek slider, time display, audio path input
- Add drawWaveform(), loadWaveform(), updatePosition(), formatTime() to app.js
- Dispatch msg.type=tick to updatePosition in handleMessage
- Wire transport buttons via WebSocket commands
- Add transport/waveform styles to style.css using existing CSS variables
- Deploy via ~/bin/deploy.sh
This commit is contained in:
Claude
2026-04-06 13:14:05 +00:00
parent da474d978d
commit 148f16ba5e
3 changed files with 264 additions and 5 deletions

View File

@@ -247,3 +247,93 @@ button:hover {
color: #ff3333;
border: none;
}
/* Transport controls */
.transport-controls {
display: flex;
gap: 4px;
align-items: center;
}
.transport-btn {
background: var(--bg-panel);
color: var(--accent);
border: 1px solid var(--border-dim);
padding: 4px 10px;
font-family: var(--font-mono);
font-size: 0.85rem;
cursor: pointer;
min-width: 36px;
text-align: center;
}
.transport-btn:hover {
background: var(--accent);
color: var(--bg-primary);
border-color: var(--accent);
}
.transport-time {
font-family: var(--font-mono);
font-size: 0.85rem;
white-space: nowrap;
min-width: 120px;
}
.transport-seek {
flex: 1;
display: flex;
align-items: center;
}
.seek-slider {
width: 100%;
accent-color: var(--accent);
cursor: pointer;
}
.transport-file {
display: flex;
gap: 4px;
align-items: center;
}
.audio-path-input {
background: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--border-dim);
padding: 4px 8px;
font-family: var(--font-mono);
font-size: 0.8rem;
width: 200px;
}
.audio-path-input:focus {
border-color: var(--accent);
outline: none;
}
/* Transport bar layout override */
.transport-bar {
gap: 12px;
padding: 6px 12px;
}
/* Waveform */
.waveform-container {
background: var(--bg-primary);
border: none;
overflow: hidden;
}
.playback-cursor {
position: absolute;
top: 0;
left: 0;
width: 2px;
height: 100%;
background: var(--accent);
pointer-events: none;
transition: left 0.1s linear;
z-index: 10;
}