You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DelayTimerToggle scaled up ~25% for touchscreen legibility: button
hit area 32×32 → 40×40, icon canvas 24×24 → 30×30. Geometries stay
authored against the 24-viewport — the Path now uses Stretch="Uniform" with explicit Width="30" Height="30" so the
existing clock-face / arc constants render at the new size and the
stroke renders proportionally bolder. iconText font size 10 → 13.
The "Timer" caption in UIPrelimSettings (Step 1 + Step 4) now
carries FontSize="14" FontWeight="SemiBold" with a 4 px top margin
so it reads at glance distance.
UIReportScrollViewer gains PanningMode="VerticalOnly" so the
report body pans by finger drag, not just mouse wheel.
StepCardNavigator no longer enables IsManipulationEnabled on its
root grid or wires the Manipulation* event pipeline. Touch swipes
still work via Windows' touch→mouse promotion against the existing Swipe_Mouse* handlers; removing the manipulation container unblocks
taps on descendant controls inside a StepCard that don't have their
own touch handlers (the SegmentedToggle RadioButtons and the inner Button in DelayTimerToggle), which previously had their touches
captured by the manipulation pipeline.
UpdateWindow release notes now show the markdown changelog body
instead of "Release notes: <url>". Added GHReleaseTracker.GetReleaseByTagAsync(tag) and a regex-parser in MainApp that extracts owner/repo/tag from the manifest entry's notesUrl (HTML release-page URL), then fetches the release body
anonymously through the GitHub Releases API. Falls back to the
previous "Release notes: " line on parse/fetch failure (rate
limit, offline, schema drift). One launch-time fetch fits well
inside the 60 req/hr anonymous rate limit.
Removed the redundant sp.WriteCmd("BK") in UIEvaluation.btnMeasure_Click
for AROM mode. Check_CurrentUI already sets the motor to RL when
AROM is selected, and after 0a7a5cf the in-line BK was actively
wrong for the page's current convention.
Fixed
Wrapper buttons (ImageButton, ActionButton, IconButton, IconToggleButton) no longer double-fire on touch. Touch hardware
that emits parallel WM_LBUTTON alongside WM_TOUCH (common on
Windows touchscreens) caused both the manual click raised from TouchUp AND the inner Button.Click from the mouse-promoted
message to fire, raising the outer Click event twice. On the eval
Start/Stop ImageButton this flipped IsPressed back to its
starting value, so the icon/text never swapped on touch even though
the underlying handler ran. Each wrapper now guards its inner click
handler so the mouse-promoted call following a touch is suppressed
(cleared on the next Input-priority dispatch). IconToggleButton
additionally hooks PreviewMouseLeftButtonUp so ButtonBase.OnClick
doesn't toggle IsChecked a second time after the touch path has
manually swapped it; the touch handler now sets IsChecked before
raising Toggle so subscribers reading EmgPlotBtn.IsChecked / ModePlotBtn.IsChecked see the new state.
UICoverFlow.Load_GameList crashed with NullReferenceException on
the foreach (var game in gameLibrary) when the user added or
deleted a game from UIGameLib on a fresh launch — UICoverFlow's gameLibrary field is only wired in Load_GameProtocol, which
doesn't run until the user first enters the Game task. Null-guard Refresh_GameList and Load_GameList; keep IsChanged = true when
bailing so the pending refresh resolves once Load_GameLibrary
eventually runs.
UIGameLib.btnAddGame_Click / btnDeleteGame_Click could fire
before Initialize_Variables wired mainApp, NRE-ing on mainApp.uiGames.IsChanged = true. Adds EnsureReady() (refreshes
the local MainApp.GameLibrary reference and null-checks mainApp)
at the top of every mutation handler; toggleDisplay_Changed
null-guards mainApp directly since it fires from the per-item IsChecked binding during initial materialization, before Initialize_Gamelist runs. btnDeleteGame_Click also captures the
target GameInfo from the row's Tag up front instead of
round-tripping through lstGames.SelectedItem — the
dispatcher-pumping MessageBox.Show could otherwise null out the
selection mid-handler.
UIGameLib could operate on a stale MainApp.GameLibrary
reference: Initialize_Settings reassigns the static field to a new ObservableCollection AFTER uiGameLib_Loaded has captured the
original empty one. Subsequent adds/removes mutated the orphan
collection while Save_GameLibrary persisted the live one,
silently losing entries on disk. SyncGameLibraryRef() re-fetches
the current static reference and rebinds lstGames.ItemsSource
whenever the instance changes.
AR01BleClient.WriteToCsv crashed with ArgumentNullException when
the data-saving state was toggled quickly enough that evalTrialsFile
/ prelimSummaryFile was still null (or had been cleared by a
Stop/disconnect) at the moment a record was queued. The existing catch (IOException) didn't cover argument exceptions, so the
throw escaped and killed the app. Early-out with a BleLogger line
when fileName is null/empty or the records collection is null;
also catches UnauthorizedAccessException so a read-only attribute
or AV lock on the data file is never session-fatal.