Skip to content

Commit de37b7f

Browse files
Added ability to render single dot clicks (#235)
* Added ability to render single dot clicks * reduce stroke continuity stage timeout Reduce the amount of time between "separate" stroke detection * reduce stroke distance check
1 parent e102d76 commit de37b7f

File tree

3 files changed

+106
-6
lines changed

3 files changed

+106
-6
lines changed

src/DrawTogether.Actors/Local/StrokeContinuityStage.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class StrokeContinuityStage : GraphStage<
2424
{
2525
private readonly TimeSpan _userInactivityTimeout;
2626
private const string UserInactivityTimeout = "user-inactivity-timeout";
27-
private readonly TimeSpan _strokeDisconnectTimeout = TimeSpan.FromSeconds(1);
27+
private readonly TimeSpan _strokeDisconnectTimeout = TimeSpan.FromMilliseconds(200);
2828

2929
// Shape definition for this stage
3030
public override FlowShape<ImmutableList<LocalPaintProtocol.IPaintSessionMessage>, IEnumerable<ConnectedStroke>>
@@ -161,7 +161,7 @@ private IEnumerable<ConnectedStroke> ProcessBatch(ImmutableList<LocalPaintProtoc
161161
// something unusual happened (e.g., user clicked somewhere else) - no need for continuity
162162
var distance = CalculateDistance(activeInfo.LastPoint, pointsToAdd[0]);
163163

164-
if (distance <= 500.0) // Threshold for what we consider "continuous"
164+
if (distance <= 50.0) // Threshold for what we consider "continuous"
165165
{
166166
// For perfect continuity, replace the first point with the last point from previous stroke
167167
// This ensures there's not even a sub-pixel gap between strokes

src/DrawTogether/Components/Draw/DrawingSurface.razor

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,22 @@
4040

4141
@foreach (var stroke in Strokes)
4242
{
43-
<Curve
44-
Points="@stroke.Value.Points"
45-
Stroke="@stroke.Value.StrokeColor.HexCodeOrColorName"
46-
StrokeWidth="@stroke.Value.StrokeWidth.Value"/>
43+
@if (stroke.Value.Points.Count == 1)
44+
{
45+
<!-- Render single-point strokes as circles (dots) -->
46+
<circle cx="@stroke.Value.Points[0].X"
47+
cy="@stroke.Value.Points[0].Y"
48+
r="@(stroke.Value.StrokeWidth.Value / 2.0)"
49+
fill="@stroke.Value.StrokeColor.HexCodeOrColorName" />
50+
}
51+
else
52+
{
53+
<!-- Render multi-point strokes as curves -->
54+
<Curve
55+
Points="@stroke.Value.Points"
56+
Stroke="@stroke.Value.StrokeColor.HexCodeOrColorName"
57+
StrokeWidth="@stroke.Value.StrokeWidth.Value"/>
58+
}
4759
}
4860
</g>
4961
</svg>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using DrawTogether.Entities;
2+
using DrawTogether.Entities.Drawings;
3+
using DrawTogether.Entities.Users;
4+
using FluentAssertions;
5+
using Xunit;
6+
7+
namespace DrawTogether.Tests;
8+
9+
public class SingleDotStrokeTests
10+
{
11+
[Fact]
12+
public void Should_Detect_Single_Point_Stroke()
13+
{
14+
// Arrange
15+
var strokeId = new StrokeId(1);
16+
var point = new Point(100, 200);
17+
var strokeWidth = new GreaterThanZeroInteger(5);
18+
var color = new Color("#FF0000");
19+
20+
var singlePointStroke = new ConnectedStroke(strokeId)
21+
{
22+
Points = [point],
23+
StrokeWidth = strokeWidth,
24+
StrokeColor = color
25+
};
26+
27+
// Act & Assert
28+
singlePointStroke.Points.Should().HaveCount(1);
29+
singlePointStroke.Points[0].Should().Be(point);
30+
singlePointStroke.StrokeWidth.Should().Be(strokeWidth);
31+
singlePointStroke.StrokeColor.Should().Be(color);
32+
}
33+
34+
[Fact]
35+
public void Should_Distinguish_Single_Point_From_Multi_Point_Strokes()
36+
{
37+
// Arrange
38+
var strokeId1 = new StrokeId(1);
39+
var strokeId2 = new StrokeId(2);
40+
41+
var singlePointStroke = new ConnectedStroke(strokeId1)
42+
{
43+
Points = [new Point(100, 200)],
44+
StrokeWidth = new GreaterThanZeroInteger(3),
45+
StrokeColor = new Color("#00FF00")
46+
};
47+
48+
var multiPointStroke = new ConnectedStroke(strokeId2)
49+
{
50+
Points = [new Point(100, 200), new Point(150, 250)],
51+
StrokeWidth = new GreaterThanZeroInteger(3),
52+
StrokeColor = new Color("#0000FF")
53+
};
54+
55+
// Act & Assert
56+
singlePointStroke.Points.Should().HaveCount(1);
57+
multiPointStroke.Points.Should().HaveCount(2);
58+
59+
// This simulates the rendering logic decision
60+
var shouldRenderAsCircle1 = singlePointStroke.Points.Count == 1;
61+
var shouldRenderAsCircle2 = multiPointStroke.Points.Count == 1;
62+
63+
shouldRenderAsCircle1.Should().BeTrue();
64+
shouldRenderAsCircle2.Should().BeFalse();
65+
}
66+
67+
[Fact]
68+
public void Should_Calculate_Correct_Circle_Radius_For_Single_Point_Stroke()
69+
{
70+
// Arrange
71+
var strokeWidth = new GreaterThanZeroInteger(10);
72+
var expectedRadius = strokeWidth.Value / 2.0;
73+
74+
var singlePointStroke = new ConnectedStroke(new StrokeId(1))
75+
{
76+
Points = [new Point(50, 75)],
77+
StrokeWidth = strokeWidth,
78+
StrokeColor = new Color("#FFFF00")
79+
};
80+
81+
// Act
82+
var actualRadius = singlePointStroke.StrokeWidth.Value / 2.0;
83+
84+
// Assert
85+
actualRadius.Should().Be(expectedRadius);
86+
actualRadius.Should().Be(5.0);
87+
}
88+
}

0 commit comments

Comments
 (0)