Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
scripts/build-installer.ps1 both read it from here, so releasing is a reviewed change
to this line rather than an edit in a pipeline variable group.
-->
<VersionPrefix>0.9.5</VersionPrefix>
<VersionPrefix>1.0.0</VersionPrefix>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
6 changes: 3 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ The delivery chain works end to end: a merge to `main` builds, signs, and publis
pre-release to GitHub Releases, and one approval promotes that same build to a release.
<https://whiteboard.sqlbi.com> reads its download links from the release manifest
deployed beside it and needs no edit per release. The current product version is `VersionPrefix` in `Directory.Build.props`
(0.9.5). Identity version for the Store package is `VersionPrefix.0` (`0.9.5.0`).
(1.0.0). Identity version for the Store package is `VersionPrefix.0` (`1.0.0.0`).

What 1.0 was waiting on is in the product: Preferences, `.wimport`, Explorer and VS Code
previews, the public documentation site, and Finger drawing (default when no pen is
What 1.0 was waiting on shipped during 0.9.x: Preferences, `.wimport`, Explorer and VS
Code previews, the public documentation site, and Finger drawing (default when no pen is
detected). The Store listing was submitted by hand on 20 August 2026 for 0.9.2.

No numbered work remains. The video teaser is recorded and served from the landing page
Expand Down
23 changes: 19 additions & 4 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,26 @@ rendition, so the limit is far away at this site's traffic.

---

## 20. The version is 1.0.0

**Implemented.**

The open question was never the number, it was what had to be true before it stopped
being 0.x. That turned out to be product rather than pipeline: Preferences, `.wimport`,
the Explorer and VS Code previews, the documentation site, and Finger drawing. All of
them shipped during 0.9.x, and no numbered work was left behind them.

Nothing about delivery changes with it. A merge still publishes a pre-release, promotion
is still an approval on that same run, and the Store still takes the MSIX from it — so
1.0.0 reaches people by the path 0.9.5 already proved, which is the reason the number
could be treated as a statement about the product rather than an event in the pipeline.

The Store carries `1.0.0.0` as its identity version, and winget continues from whatever
version its first submission settles on.

---

## Open questions

- Whether 1.0.0 is declared, and on what. `VersionPrefix` in `Directory.Build.props`
reads `0.9.5`, the released channel has been published since `0.9.0`, and `0.9.2` is
the version live in the Store. Nothing is blocked on the number; what is open is
what has to be true before it stops being 0.x.
- arm64 is not built; add it if Surface devices matter for a pen application.
- The brand mark is placeholder-grade (decision 12).
6 changes: 3 additions & 3 deletions site/guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ <h3>Explain code</h3>

<section class="story">
<h3>Talk to the room</h3>
<p>The laser pointer is for the projector, not for the file. <span class="ui">Preferences</span> control the timing, not the shape: how long the trail stays fully visible after you lift, and how long it then takes to fade away. A pen in the air shows a small high-contrast hover dot; the dot disappears on contact so it never sits under the nib. A physical mouse keeps a normal arrow.</p>
<p>The laser pointer is for the projector, not for the file. <span class="ui">Preferences</span> control how long the trail stays fully visible after you lift, how long it then takes to fade away, and how much a light touch is thinned out — a pen reports very little pressure on a quick tap, and the heavier trail weights keep that tap as readable as a firm stroke. A pen in the air shows a small high-contrast hover dot; the dot disappears on contact so it never sits under the nib. With the laser selected that hover dot is the laser itself, halo and all, and it draws a short comet as you move: the faster you sweep, the longer the comet, so the room can follow the pointer before you have touched anything. A physical mouse keeps a normal arrow.</p>

<figure class="fig">
<div class="figbox">
Expand Down Expand Up @@ -655,7 +655,7 @@ <h3 id="ink">Ink and tools</h3>
<div class="toolrow">
<svg class="glyph" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="m15.87 2.67 4.97 4.97c.88.88.88 2.3 0 3.18l-8.68 8.68h6.1c.37 0 .69.28.74.65v.1c0 .38-.28.7-.64.74l-.1.01H9.83a2.24 2.24 0 0 1-1.71-.65l-4.97-4.97a2.25 2.25 0 0 1 0-3.18l9.53-9.53c.88-.88 2.3-.88 3.18 0Zm-10.16 9.1-1.49 1.49c-.3.29-.3.76 0 1.06l4.97 4.96c.15.15.34.22.53.22h.07a.75.75 0 0 0 .46-.22l1.49-1.48-6.03-6.03Zm8.04-8.04L6.77 10.7l6.03 6.03 6.98-6.98c.29-.3.29-.77 0-1.06L14.8 3.73a.75.75 0 0 0-1.06 0Z"/></svg>
<span class="name">Eraser</span>
<span class="role">Removes whole strokes. The eraser end of a pen does the same.</span>
<span class="role">Removes whole strokes. The eraser end of a pen does the same, and hovering with it draws a dashed square around what a tap would clear.</span>
</div>
<div class="toolrow">
<svg class="glyph" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M15.28 6.03c-.3.3-.77.3-1.06 0l-1.47-1.47v3.69a.75.75 0 0 1-1.5 0V4.56L9.78 6.03a.75.75 0 0 1-1.06-1.06l2.75-2.75a.75.75 0 0 1 1.06 0l2.75 2.75c.3.3.3.77 0 1.06Zm-9.25 8.19a.75.75 0 1 1-1.06 1.06l-2.75-2.75a.75.75 0 0 1 0-1.06l2.75-2.75a.75.75 0 0 1 1.06 1.06l-1.47 1.47h3.69a.75.75 0 0 1 0 1.5H4.56l1.47 1.47Zm11.94 1.06a.75.75 0 0 1 0-1.06l1.47-1.47h-3.69a.75.75 0 0 1 0-1.5h3.69l-1.47-1.47a.75.75 0 0 1 1.06-1.06l2.75 2.75a.75.75 0 0 1 0 1.06l-2.75 2.75c-.3.3-.77.3-1.06 0Zm-2.69 2.69a.75.75 0 0 0-1.06 0l-1.47 1.47v-3.69a.75.75 0 0 0-1.5 0v3.69l-1.47-1.47a.75.75 0 0 0-1.06 1.06l2.75 2.75a.75.75 0 0 0 1.06 0l2.75-2.75c.3-.3.3-.77 0-1.06Z"/></svg>
Expand Down Expand Up @@ -901,7 +901,7 @@ <h3>The command strip</h3>
</figure>

<h3>Preferences</h3>
<p><span class="ui">Help → Preferences</span> is a searchable list: which monitor to open on, start full screen, finger drawing, snippet format order, laser trail timing, toolbar placement, and the daily new-version check. <span class="ui">Help → About</span> shows the version. New settings are more rows in Preferences, not a new dialog.</p>
<p><span class="ui">Help → Preferences</span> is a searchable list: which monitor to open on, start full screen, finger drawing, snippet format order, laser trail timing and weight, toolbar placement, and the daily new-version check. <span class="ui">Help → About</span> shows the version. New settings are more rows in Preferences, not a new dialog.</p>

<figure class="fig">
<div class="figbox">
Expand Down
2 changes: 1 addition & 1 deletion site/shortcuts.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ <h2><span class="secico" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"
<div class="keyrow"><span><kbd class="gesture">View → Canvas only</kbd></span><span class="act">Hide the title and tabs, keep this window’s size and place. <kbd>Ctrl</kbd><span class="plus">+</span><kbd>F11</kbd>.</span></div>
<div class="keyrow"><span><kbd class="gesture">View → Bring to front</kbd></span><span class="act">Put the selected image, text, or LiveView above everything else, with its linked strokes. Letter <kbd>B</kbd> when the View strip is open.</span></div>
<div class="keyrow"><span><kbd class="gesture">View → Send to back</kbd></span><span class="act">Put the selected container behind everything else. Letter <kbd>S</kbd> when the View strip is open. Strokes cannot be reordered on their own.</span></div>
<div class="keyrow"><span><kbd class="gesture">Help → Preferences</kbd></span><span class="act">Searchable settings: startup monitor, full screen, finger drawing, snippet format order, laser trail, toolbar, update checks (not on a Microsoft Store install).</span></div>
<div class="keyrow"><span><kbd class="gesture">Help → Preferences</kbd></span><span class="act">Searchable settings: startup monitor, full screen, finger drawing, snippet format order, laser trail timing and weight, toolbar, update checks (not on a Microsoft Store install).</span></div>
<div class="keyrow"><span><kbd class="gesture">View → LiveView</kbd></span><span class="act">Capture an application window or display as a container.</span></div>
<div class="keyrow"><span><kbd class="gesture">View → Freeze</kbd></span><span class="act">Freeze or resume the selected live feed. Resume uses a play icon.</span></div>
<div class="keyrow"><span><kbd class="gesture">View → Disconnect</kbd></span><span class="act">Release the capture target. The last frame stays. Reconnect is then the only way back to a live feed.</span></div>
Expand Down
58 changes: 58 additions & 0 deletions src/SQLBI.Whiteboard.Core/Settings/LaserSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ public enum LaserHoldMode
PerStroke = 1,
}

/// <summary>
/// How much a light touch is thinned out. The pen reports very little pressure
/// on a quick tap, which at <see cref="LaserTrailWeight.Light"/> draws a line
/// thin enough to miss on a projector. The heavier settings raise the floor
/// without changing what a firm stroke looks like.
/// </summary>
public enum LaserTrailWeight
{
Light = 0,
Medium = 1,
Bold = 2,
}

public sealed class LaserSettings
{
public const double DefaultHoldSeconds = 2;
Expand All @@ -15,12 +28,52 @@ public sealed class LaserSettings
public const double MinimumFadeSeconds = 0.05;
public const double MaximumFadeSeconds = 10;

/// <summary>
/// The widest the trail is drawn, at full pressure. Shared with the width
/// floors below so that a preview of a weight cannot drift from the trail
/// that weight actually produces.
/// </summary>
public const double MaximumTrailWidth = 9;

public const uint TrailArgb = 0xFFE11D48;

public static byte TrailRed => (byte)((TrailArgb >> 16) & 0xFF);

public static byte TrailGreen => (byte)((TrailArgb >> 8) & 0xFF);

public static byte TrailBlue => (byte)(TrailArgb & 0xFF);

public double HoldSeconds { get; set; } = DefaultHoldSeconds;

public double FadeSeconds { get; set; } = DefaultFadeSeconds;

public LaserHoldMode HoldMode { get; set; } = LaserHoldMode.Shared;

public LaserTrailWeight TrailWeight { get; set; } = LaserTrailWeight.Light;

/// <summary>
/// The narrowest the trail is ever drawn, whatever the pressure. The widest
/// is the same for every weight, so raising this compresses the range from
/// the bottom rather than making a firm stroke heavier.
/// </summary>
public static double MinimumTrailWidthFor(LaserTrailWeight weight) => weight switch
{
LaserTrailWeight.Bold => 4,
LaserTrailWeight.Medium => 2.5,
_ => 1.2,
};

/// <summary>
/// The opacity a trail keeps at the lightest touch, as a fraction of the
/// opacity a full-pressure stroke gets.
/// </summary>
public static double MinimumTrailOpacityFor(LaserTrailWeight weight) => weight switch
{
LaserTrailWeight.Bold => 0.85,
LaserTrailWeight.Medium => 0.7,
_ => 0.55,
};

public static LaserSettings Normalize(LaserSettings? settings)
{
var result = settings ?? new LaserSettings();
Expand All @@ -39,6 +92,11 @@ public static LaserSettings Normalize(LaserSettings? settings)
result.HoldMode = LaserHoldMode.Shared;
}

if (!Enum.IsDefined(result.TrailWeight))
{
result.TrailWeight = LaserTrailWeight.Light;
}

return result;
}

Expand Down
Loading