Compare commits

...
3 Commits
Author SHA1 Message Date
Bendik Aagaard Lynghaug 47d7f9d2c3 Release 0.3.5
Publish release / publish (push) Successful in 1m27s
Test / test (push) Successful in 22s
2026-08-30 11:40:47 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 12e9fcd609 Gesture widget: ghost path back, for v2 keys only
Test / test (push) Successful in 23s
The relay's ack path is drawn under the stroke when the key's version
nibble is >= 2 (ADR-0014's ordered turning chain decodes to the
stroke itself); a v1 key's blob stays hidden. Safe to ship ahead of
the relay: nothing shows until the relay encodes v2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 11:38:48 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 72674afe05 Gesture widget: stop drawing the decoded ghost path
Test / test (push) Successful in 25s
decode_key's reconstruction is too rough to have value on screen;
the ack's key is kept, its path ignored. Revisit only once the
reconstruction is fixed at the core in redoal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 11:21:20 +02:00
3 changed files with 14 additions and 10 deletions
Generated
+1 -1
View File
@@ -2948,7 +2948,7 @@ dependencies = [
[[package]] [[package]]
name = "portal" name = "portal"
version = "0.3.4" version = "0.3.5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "portal" name = "portal"
version = "0.3.4" version = "0.3.5"
edition = "2021" edition = "2021"
[lib] [lib]
+12 -8
View File
@@ -12,8 +12,10 @@
// //
// When a relay URL is given, the widget also speaks the redoal-relay // When a relay URL is given, the widget also speaks the redoal-relay
// protocol (ADR-0013 in the redoal repo): announce the stroke, receive // protocol (ADR-0013 in the redoal repo): announce the stroke, receive
// an ack carrying the stroke's gesture key + the key's own decoded // an ack carrying the stroke's gesture key plus the key's own decoded
// path ("what the network heard", drawn as a ghost), and receive // path - "what the network heard", drawn as a ghost under the stroke
// when the key is v2 or later (ADR-0014's ordered turning chain; a v1
// key's histogram decode is a blob and stays hidden) - and receive
// echoes of similar strokes other visitors drew, shown as thumbnails. // echoes of similar strokes other visitors drew, shown as thumbnails.
// Everything network is best-effort: no relay, refused connection, or // Everything network is best-effort: no relay, refused connection, or
// a dropped socket all degrade to a plain offline drawing input. // a dropped socket all degrade to a plain offline drawing input.
@@ -26,13 +28,13 @@
const THEMES = { const THEMES = {
dark: { dark: {
stroke: '#8ec2c0', stroke: '#8ec2c0',
ghost: 'rgba(255, 255, 255, 0.28)',
echo: '#8ec2c0', echo: '#8ec2c0',
ghost: 'rgba(255, 255, 255, 0.28)',
}, },
light: { light: {
stroke: '#47807e', stroke: '#47807e',
ghost: 'rgba(29, 29, 27, 0.30)',
echo: '#47807e', echo: '#47807e',
ghost: 'rgba(29, 29, 27, 0.30)',
}, },
}; };
@@ -46,8 +48,8 @@ class GestureWidget {
this.container = container; this.container = container;
this.hidden = hidden || null; this.hidden = hidden || null;
this.relayUrl = relayUrl || ''; this.relayUrl = relayUrl || '';
this.points = [];
this.ghost = null; this.ghost = null;
this.points = [];
this.drawing = false; this.drawing = false;
this.stopped = false; this.stopped = false;
this.ws = null; this.ws = null;
@@ -111,10 +113,10 @@ class GestureWidget {
e.preventDefault(); e.preventDefault();
this.canvas.setPointerCapture(e.pointerId); this.canvas.setPointerCapture(e.pointerId);
// One stroke only - a new pointerdown replaces the old drawing // One stroke only - a new pointerdown replaces the old drawing
// (and any ghost/ambient trails from the previous round). // (and any ghost from the previous round).
this.drawing = true; this.drawing = true;
this.points = [this.pos(e)];
this.ghost = null; this.ghost = null;
this.points = [this.pos(e)];
this.render(); this.render();
} }
@@ -215,7 +217,9 @@ class GestureWidget {
if (this.points.length >= 2) { if (this.points.length >= 2) {
this.setValue({ points: this.normalized(), key: msg.key }); this.setValue({ points: this.normalized(), key: msg.key });
} }
this.ghost = msg.path; // Version nibble is the key's first hex digit.
const version = parseInt((msg.key || '0')[0], 16);
this.ghost = version >= 2 && Array.isArray(msg.path) ? msg.path : null;
this.render(); this.render();
} else if (msg.type === 'echo') { } else if (msg.type === 'echo') {
this.addEchoThumbnail(msg); this.addEchoThumbnail(msg);