Skip to content

Width: stepper, NAWS diagnostics, honor high MinColumns (font floor + WebView min-font)#13

Merged
HarryCordewener merged 3 commits into
masterfrom
feat/width-stepper-and-naws-logging
Jul 1, 2026
Merged

Width: stepper, NAWS diagnostics, honor high MinColumns (font floor + WebView min-font)#13
HarryCordewener merged 3 commits into
masterfrom
feat/width-stepper-and-naws-logging

Conversation

@HarryCordewener

@HarryCordewener HarryCordewener commented Jul 1, 2026

Copy link
Copy Markdown
Member

1. Min columns: slider → stepper

The slider was hard to set precisely on a phone. Replaced with a typeable / value / + stepper (range 20–500, clamped). Max text size stays a slider.

2. Diagnostic logging

measureGrid returns the values it fits against, and SessionScreen logs a NAWS fit: … line at Information → the on-device log (exportable via Settings → Export log): clientW, contentW, padX, advanceRatio, fontPx, targetCols, actualColsThatFit, reportedCols(NAWS), rows, vScroll.

3. Fix: 90-column width wrapped (diagnosed from the exported log)

The log showed minCols=90 contentW=376 fontPx=6 actualColsThatFit=104 fits=True — yet it wrapped. Two bugs:

  1. Font floored at 6px. Fitting 90 columns in 376px needs ~6–7px, but the closed-loop fit was clamped at 6px and stopped short, so 90 didn't fit. Lowered the floor to 4px so the font can shrink enough to honor a high MinColumns on a narrow screen.
  2. actualColsThatFit used the linear advance ratio (sampled at 100px). Glyph advance is proportionally larger at tiny sizes (hinting), so it over-counted (104 at 6px when ~78 truly fit) — which is why it wrongly reported fits=True. measureGrid now measures the real advance at the fitted size and reports the honest count; cols (NAWS) = min(targetCols, whatActuallyFits), so it never advertises more than is visible and the client never double-wraps.

Verified (at ~device width)

  • 90 → fits at ~6.7px, actualCols=90, no wrap.
  • 78 (default) → 7.7px, comfortable.
  • 200 (impossible legibly) → floors at 4px and honestly reports 150 (server wraps to that; no client wrap).
  • Web + Android build clean; UI bUnit 47/47; stepper works; NAWS fit: line emits.

🤖 Generated with Claude Code

1. Min columns is now a typeable −/value/+ stepper instead of a slider — far
   easier to set an exact width on a phone. Range widened to 20–500 (clamped on
   every change). Max text size stays a slider.

2. Added diagnostic logging around the column-fit math so wrap issues can be
   traced from the exported log. measureGrid now returns the values it bases its
   decision on (clientW, contentW, padX, advanceRatio, fitted fontPx, targetCols,
   and actualColsThatFit — the count that genuinely fits at the fitted font), and
   SessionScreen logs them at Information (captured by FileLoggerProvider -> the
   on-device log). When actualColsThatFit < targetCols, the advertised width
   can't be shown and lines wrap — now visible in the log with fontPx (vs the 6px
   floor) and contentW (vs clientW, showing scrollbar/inset loss).

Verified: Web + Android build clean; UI bUnit 47/47; stepper works in the Web
preview (buttons adjust, old slider gone); the "NAWS fit: ..." line is emitted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHCRc5CJ6595iMzEgYYdQp
Copilot AI review requested due to automatic review settings July 1, 2026 01:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves layout settings usability by replacing the Min columns slider with a numeric stepper, and adds richer NAWS/column-fit diagnostics by returning measurement details from measureGrid and logging them from SessionScreen for exportable on-device troubleshooting.

Changes:

  • Replace Min columns slider with a typeable − / value / + stepper (range 20–500) and update/add bUnit tests.
  • Extend measureGrid JS interop to return diagnostic metrics (actual cols that fit, padding, widths, scrollbar presence, etc.).
  • Log NAWS fit diagnostics from SessionScreen to support wrap/fit issue investigation via exported device logs.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/SharpClient.UI.Tests/SettingsViewTests.cs Updates Min columns UI tests for the new stepper and adds button-adjustment coverage.
src/SharpClient.UI/wwwroot/sc-interop.js Adds computed diagnostic fields to measureGrid output for downstream logging.
src/SharpClient.UI/wwwroot/app.css Introduces styling for the new stepper control.
src/SharpClient.UI/Components/SettingsView.razor Replaces the Min columns slider with a stepper and clamps user input.
src/SharpClient.UI/Components/SessionScreen.razor Injects ILogger and logs NAWS fit diagnostics based on measureGrid results.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +117 to +127
// Diagnostics for column/wrap issues — captured to the on-device log (FileLoggerProvider) so it
// can be exported. actualCols < targetCols means the advertised width can't be shown and lines
// wrap; compare fontPx against the 6px floor and contentW against clientW (scrollbar/inset loss).
Logger.LogInformation(
"NAWS fit: minCols(setting)={MinColumns} maxFont(cap)={Cap} probeW={ProbeWidth} probeH={ProbeHeight} " +
"clientW={ClientW} contentW={ContentW} padX={PadX} advanceRatio={AdvanceRatio} fontPx={FontPx} " +
"targetCols={TargetCols} actualColsThatFit={ActualCols} reportedCols(NAWS)={Cols} rows={Rows} vScroll={VScroll} fits={Fits}",
Settings.MinColumns, cap, widthPx, heightPx,
grid.ClientW, grid.ContentW, grid.PadX, grid.AdvanceRatio, grid.FontPx,
grid.TargetCols, grid.ActualCols, grid.Cols, grid.Rows, grid.VScroll,
grid.ActualCols >= grid.TargetCols);
Comment on lines +109 to +111
// Typeable/stepped bounds for Min columns. Wider than the old 60–120 slider so unusual widths
// are reachable; the value is clamped on every change.
private const int MinColumnsMin = 20;
Comment on lines +173 to +175
const advancePx = advanceRatio * fontPx;
const actualCols = advancePx > 0 ? Math.floor(contentW / advancePx) : 0;
const vscroll = element.scrollHeight > element.clientHeight;
…rap)

Diagnosis from the exported device log: at MinColumns=90 on a 384px screen
(contentW=376), the font floored at 6px and 90 still wrapped, yet the log said
actualColsThatFit=104/fits=True. Two bugs:

1. The min-font floor was 6px. Fitting 90 columns in 376px needs ~5.9–6.9px;
   the closed-loop fit was clamped at 6px and stopped short, so 90 didn't fit
   and wrapped. Lowered the floor to 4px (passed from SessionScreen) so the font
   can shrink enough to honor a high MinColumns on a narrow screen.

2. actualColsThatFit was computed with the LINEAR advanceRatio (sampled at
   100px). Glyph advance is proportionally larger at tiny sizes (hinting), so it
   over-counted (104 at 6px when ~78 truly fit) — which is why the diagnostic
   wrongly said it fit. measureGrid now measures the REAL advance at the fitted
   size and reports the honest column count; the returned cols (NAWS) is
   min(targetCols, whatActuallyFits), so it never advertises more than is
   visible and the client never double-wraps.

Verified at ~device width: MinColumns 90 now fits at ~6.7px with no wrap
(actualCols 90); 78 stays comfortable at 7.7px; an extreme 200 floors at 4px and
honestly reports 150 (server wraps to that, no client wrap). Web + Android build
clean; UI bUnit 47/47.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHCRc5CJ6595iMzEgYYdQp
@HarryCordewener HarryCordewener changed the title Width setting: number stepper + NAWS fit diagnostics logging Width stepper, NAWS diagnostics, and honor high MinColumns (fix 90-col wrap) Jul 1, 2026
Follow-up to the honest-column reporting: on device, NAWS was pinned at ~78 for
any Min columns >= ~79. Root cause is the Android WebView MinimumFontSize /
MinimumLogicalFontSize (both default 8px): the terminal fits the font down to a
few px to pack e.g. 90 columns onto a 376px-wide screen, but the WebView clamped
that to 8px, so only ~78 columns actually fit — and measureGrid (now honest)
correctly reported ~78, hence the pin.

Drop both floors to 1px on the BlazorWebView's Android WebView (next to the
insets bridge). The fitted sub-8px size now renders for real, so 90 columns fit
(~6.5px) and NAWS reports 90. measureGrid still measures the real rendered
advance and reports only what fits, so a genuinely-too-large value degrades
gracefully instead of wrapping. Android-only change; builds clean.

The existing "NAWS fit: …" log will confirm on the next export: with the clamp
gone, fontPx drops below 8 and actualColsThatFit rises to the requested value.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHCRc5CJ6595iMzEgYYdQp
@HarryCordewener HarryCordewener changed the title Width stepper, NAWS diagnostics, and honor high MinColumns (fix 90-col wrap) Width: stepper, NAWS diagnostics, honor high MinColumns (font floor + WebView min-font) Jul 1, 2026
@HarryCordewener
HarryCordewener merged commit 9d87e72 into master Jul 1, 2026
2 checks passed
@HarryCordewener
HarryCordewener deleted the feat/width-stepper-and-naws-logging branch July 6, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants