Remove QR sharing; README accuracy pass
Drop the QR-code share button, its external-service warning banner/CSS, and the api.qrserver.com handler — sharing is now copy/open link only, so the app makes no external requests at all. README: remove QR references and the Deploy section, refresh Features/sounds/dynamics/swing, list the 808/909 voices, and note which acoustic voices use CC0 samples. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
06986e83aa
commit
3213c6afe4
2 changed files with 19 additions and 33 deletions
40
README.md
40
README.md
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
A browser **polymetric groove trainer / metronome** — and the design mockup for a
|
||||
Raspberry Pi Pico hardware build. Stack as many "meter lanes" as you like; each is
|
||||
its own little metronome with a grouping, subdivision, drum voice and per-beat
|
||||
pattern. Layering lanes produces polymeter and true ratio polyrhythm.
|
||||
its own little metronome with a grouping, subdivision, drum voice and a per-step
|
||||
pattern with accents. Layering lanes produces polymeter and true ratio polyrhythm.
|
||||
|
||||
**Live:** https://metronome.varasys.io
|
||||
|
||||
|
|
@ -18,17 +18,18 @@ the browser may not persist `localStorage` between sessions, so use **Export all
|
|||
|
||||
## Features
|
||||
|
||||
- **Meter lanes** — grouping (odd meters), subdivision, a synthesized drum/percussion voice, per‑beat
|
||||
on/off pattern (rests), mute, live measure counter.
|
||||
- **Meter lanes** — grouping (odd meters), subdivision (incl. swing), a drum/percussion
|
||||
voice, per‑**step dynamics** (accent / normal / ghost / mute), mute, live measure counter.
|
||||
- **Sounds** — a sampled acoustic kit plus synthesized **808 / 909** and electronic voices;
|
||||
click each pad to set its dynamics; pick a *swing* subdivision for a triplet feel.
|
||||
- **Polyrhythm** — a per‑lane *poly* toggle fits a lane's beats evenly into lane 1's
|
||||
bar (e.g. 5‑over‑4, 3‑over‑2).
|
||||
- **Practice** — gap/mute trainer (play N / mute M bars) and a tempo ramp with a
|
||||
start BPM and signed step.
|
||||
- **Set lists** — named, ordered lists of saved setups; click an item to load it
|
||||
(it switches live if you're already playing), **N** loads the next; each play is
|
||||
- **Set lists** — named, ordered lists of saved setups; **cue** across lists and commit
|
||||
on a bar/beat boundary with no audible gap (see **Live performance**); each play is
|
||||
logged for cross‑day comparison.
|
||||
- **Sharing** — copy a link to your current settings or a whole set list (with an
|
||||
optional QR generated by an external service).
|
||||
- **Sharing** — copy a link to your current settings or a whole set list.
|
||||
- **Theming** — System / Light / Dark.
|
||||
|
||||
## The share language
|
||||
|
|
@ -61,10 +62,12 @@ Tokens are joined with `;`. `tr` and `rmp` are omitted when off.
|
|||
<sound> : <grouping> [ / <sub> ] [ = <pattern> ] [ ~ ] [ ! ]
|
||||
```
|
||||
|
||||
- **sound** — one of:
|
||||
`beep`, `kick`, `snare`, `rim`, `clap`, `hatClosed`, `hatOpen`, `ride`, `crash`,
|
||||
`tomLow`, `tomMid`, `tomHigh`, `tambourine`, `cowbell`, `woodblock`, `claves`,
|
||||
`jamblock` (unknown → `beep`).
|
||||
- **sound** — the acoustic kit: `beep`, `kick`, `snare`, `rim`, `clap`, `hatClosed`,
|
||||
`hatOpen`, `ride`, `crash`, `tomLow`, `tomMid`, `tomHigh`, `tambourine`, `cowbell`,
|
||||
`woodblock`, `claves`, `jamblock` (kick / snare / closed‑hat / crash play embedded
|
||||
CC0 samples, the rest are synthesized); plus synthesized drum machines —
|
||||
`kick808 snare808 clap808 hat808 openHat808 cowbell808 tom808` and
|
||||
`kick909 snare909 clap909 hat909 ride909 crash909`. Unknown → `beep`.
|
||||
- **grouping** — beats per bar, optionally grouped for odd meters: `4`, `3`,
|
||||
`2+2+3`. Groups get a visual divider; accents are per‑step (see `=pattern`).
|
||||
- **`/sub`** — subdivision: `1` quarter (default), `2` eighth, `3` triplet,
|
||||
|
|
@ -74,7 +77,7 @@ Tokens are joined with `;`. `tr` and `rmp` are omitted when off.
|
|||
- **`=pattern`** — per‑**step dynamics**, one char per pad: **`X`** accent, **`x`**
|
||||
normal, **`g`** ghost (soft), **`.`** mute (rest). Length = beats per bar × `sub`. Omit to get the
|
||||
default — the first step of **each beat** accented, the rest normal (click a pad in
|
||||
the UI to cycle accent → normal → mute). e.g. `4=.X.X` accents the backbeat (2 & 4);
|
||||
the UI to cycle accent → normal → ghost → mute). e.g. `4=.X.X` accents the backbeat (2 & 4);
|
||||
`4/2s` is swung eighths with the default accents. (Legacy `x`/`.` on/off patterns and
|
||||
short beat‑count patterns still parse.)
|
||||
- **`~`** — polyrhythm: fit this lane's beats evenly into **lane 1's** bar.
|
||||
|
|
@ -107,10 +110,7 @@ clears the hash so a refresh won't re‑import.
|
|||
|
||||
In the set‑list panel's **⋯** menu:
|
||||
- **Share settings link** / **Share set‑list link** open a dialog with the link to
|
||||
**Copy** or **Open**.
|
||||
- **QR ↗** opens a third‑party QR service (api.qrserver.com) with the link in its
|
||||
URL so you can scan it on a phone. A banner warns you it's external — confirm the
|
||||
QR decodes to the shown link before trusting it. (No QR is generated locally.)
|
||||
**Copy** or **Open**. The link encodes everything in the URL — nothing is uploaded.
|
||||
- **Export all / Import file** back up your set lists and practice log as a JSON
|
||||
file (a legacy `presets` field is included for backward compatibility).
|
||||
|
||||
|
|
@ -162,12 +162,6 @@ Cut a release with `./release.sh [X.Y.Z]` — the optional arg bumps & commits
|
|||
`VERSION`; it then tags the current commit `v<VERSION>` (requires a clean tree).
|
||||
Push the tag, then deploy.
|
||||
|
||||
## Deploy
|
||||
|
||||
`./deploy.sh` copies `index.html` (version‑stamped) into the Caddy
|
||||
web root and smoke‑tests the live URL. No restart needed (`file_server` picks up
|
||||
changes immediately).
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|
|
|
|||
12
index.html
12
index.html
|
|
@ -189,8 +189,6 @@
|
|||
.overlay { position:fixed; inset:0; background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center; z-index:80; }
|
||||
.overlay[hidden] { display:none; }
|
||||
.overlay-box { background:var(--panel-2); border:1px solid var(--edge); border-radius:14px; padding:16px 20px; width:380px; max-width:92vw; box-shadow:0 20px 60px rgba(0,0,0,.6); }
|
||||
.ext-banner { font-size:11px; color:#3a2f10; background:#ffe2a8; border:1px solid #d9a441; border-radius:8px; padding:8px 10px; margin-top:10px; line-height:1.35; }
|
||||
.ext-banner[hidden] { display:none; }
|
||||
#shareUrl { width:100%; resize:vertical; background:var(--panel); color:var(--txt); border:1px solid var(--edge); border-radius:8px; padding:8px; font-family:"Courier New",monospace; font-size:12px; }
|
||||
.help-about { margin-top:14px; padding-top:12px; border-top:1px solid var(--edge); font-size:12px; color:var(--muted); line-height:1.45; }
|
||||
.help-about p { margin:0 0 8px; }
|
||||
|
|
@ -371,14 +369,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Share dialog: copyable link + QR code -->
|
||||
<!-- Share dialog: copyable link -->
|
||||
<div id="shareOverlay" class="overlay" hidden>
|
||||
<div class="overlay-box">
|
||||
<div class="tray-head"><h2 id="shareTitle" style="margin:0">Share</h2><button class="x" id="shareClose" title="close" style="margin-left:0">✕</button></div>
|
||||
<textarea id="shareUrl" readonly rows="3"></textarea>
|
||||
<div class="btnrow" style="margin-top:8px"><button id="shareCopy">Copy link</button><button id="shareOpen">Open ↗</button><button id="shareQrExt">QR ↗</button></div>
|
||||
<div class="btnrow" style="margin-top:8px"><button id="shareCopy">Copy link</button><button id="shareOpen">Open ↗</button></div>
|
||||
<div class="hint" id="shareNote"></div>
|
||||
<div class="ext-banner" id="shareExtBanner" hidden>⚠ “QR ↗” opens an external site (api.qrserver.com) with this link embedded in its URL. It is a third party — after scanning, confirm the QR decodes to the link above before trusting it.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -1204,7 +1201,6 @@ function openShare(title, url, note) {
|
|||
$("shareTitle").textContent = title;
|
||||
$("shareUrl").value = url;
|
||||
$("shareNote").textContent = note || "";
|
||||
$("shareExtBanner").hidden = true; // reset the external-QR warning
|
||||
$("shareOverlay").hidden = false;
|
||||
}
|
||||
function shareSettings() { openShare("Share settings", shareLink("p=" + currentPatch()), "Encodes tempo, lanes & practice settings."); }
|
||||
|
|
@ -1434,10 +1430,6 @@ $("shareClose").addEventListener("click", () => $("shareOverlay").hidden = true)
|
|||
$("shareOverlay").addEventListener("click", (e) => { if (e.target.id === "shareOverlay") $("shareOverlay").hidden = true; });
|
||||
$("shareCopy").addEventListener("click", async () => { try { await navigator.clipboard.writeText($("shareUrl").value); const b = $("shareCopy"); b.textContent = "Copied!"; setTimeout(() => b.textContent = "Copy link", 1200); } catch (e) { $("shareUrl").select(); } });
|
||||
$("shareOpen").addEventListener("click", () => window.open($("shareUrl").value, "_blank"));
|
||||
$("shareQrExt").addEventListener("click", () => {
|
||||
$("shareExtBanner").hidden = false; // warn that we're handing the link to a third party
|
||||
window.open("https://api.qrserver.com/v1/create-qr-code/?size=320x320&data=" + encodeURIComponent($("shareUrl").value), "_blank", "noopener");
|
||||
});
|
||||
window.addEventListener("keydown", (e) => {
|
||||
const t = e.target, tag = t ? t.tagName : "", type = (t && t.type ? String(t.type) : "").toLowerCase();
|
||||
// Text entry is sacred — never hijack typing in a text field.
|
||||
|
|
|
|||
Loading…
Reference in a new issue