Skip to content

Maintenance 9.x to master#2635

Merged
sensei-hacker merged 44 commits into
masterfrom
maintenance-9.x
May 24, 2026
Merged

Maintenance 9.x to master#2635
sensei-hacker merged 44 commits into
masterfrom
maintenance-9.x

Conversation

@sensei-hacker
Copy link
Copy Markdown
Member

No description provided.

sensei-hacker and others added 30 commits January 27, 2026 14:52
**Problem:**
When decompiling logic conditions with activator hoisting and a stored
variable map, all spaces between words were being replaced with custom
variable names (e.g., "const min" became "constmin", comments like
"INAV JavaScript Programming" became "INAVminJavaScriptminProgramming").

**Root Cause:**
In decompiler.js applyCustomVariableNames() at line 293, the code was
storing entire objects from hoistedActivatorVars instead of extracting
the varName string:

  const entry = { varName: 'cond1', scopeLcIndex: -1 }

When this object was used in a template literal to build a regex pattern:
  `\\b${entry}\\b` → `\\b[object Object]\\b`

In regex, `[object Object]` is a CHARACTER CLASS that matches any single
character from the set: {o,b,j,e,c,t,space,O}. This caused the regex
pattern `\\b[object Object]\\b` to match spaces between word boundaries,
replacing them with the custom variable name.

**Fix:**
Changed line 293-294 to extract the .varName property:
  - Before: lcIndexToGeneratedName.set(lcIndex, generatedName);
  - After: lcIndexToGeneratedName.set(lcIndex, entry.varName);

This ensures the regex replacement uses the actual variable name string
instead of "[object Object]" character class.

**Files Changed:**
- js/transpiler/transpiler/decompiler.js

**Testing:**
Verified with test cases showing the fix prevents space replacement in
both code and comments.
The motor direction selector (normal/reverse) was only partially
hidden for fixed wing and other non-multirotor platforms because
the jQuery selector targeted the label rather than the container
div. Add an ID to the container and target it directly so the
entire fieldset is hidden.
Replace the split two-panel layout (left: enable/position, right: slot
config) with self-contained collapsible cards in the left panel. Each
card has an enable toggle, preview text, and expand/collapse in the
header, with slot configuration in the card body.

Key changes:
- Split the 28-option flat type dropdown into a 7-option source select
  (None, Text, Icon static/GV/LC, Global Variable, Logic Condition)
  plus a 12-option format select shown only for GV/LC sources
- Progressive disclosure: configured cards expanded with blue border,
  first unconfigured expanded, rest collapsed
- Hidden original type selects preserve save/load compatibility with
  existing fillCustomElementsValues() and customElementGetDataForRow()
- Cards rebuild on every updateFields() call (layout switch, search)
- Right panel custom element section hidden
- Transpose table columns to stacked rows: each slot gets its own row
  with [source select] [value input] side by side
- Visibility select gets its own row at bottom
- Replace table/tr/td structure with flexbox div rows (.ce-slot-row)
- Fix card header preview: generate plain-text summary instead of using
  OSD font characters (FONT.symbol) which render as boxes in HTML
- Fix invisible inputs: add 'settings' class to card body for borders
- Update customElementsInitCallback to use card data-ce-index instead
  of closest('tr').data('row') since table structure is removed
Replace bare number input for Icon (static/GV/LC) with a clickable
preview button that opens a popup grid of all 255 OSD font characters.
User clicks a glyph tile to select it. The selected icon shows as an
inline preview image with its character number.
Unit-converted values like "328.08 ft" (from 100m) and "9842.52 ft"
(from 3000m) showed excessive decimal precision. Add a smartRound()
function that removes unnecessary decimals when rounding changes the
value by less than 1%, and snaps to nearby round numbers (e.g. 999→1000)
when within 0.1%. Applies to all data-unit converted settings inputs
and OSD distance alarm display.
Settings.configureInputs() populates the radio buttons asynchronously via
MSP, but the mixer preset change handler fires synchronously during init,
before those requests complete. As a result updateMotorDirection() read an
unpopulated radio button and always rendered the normal (non-reversed) SVG.

Re-run updateMotorDirection() after settingsPromise resolves so the arrow
reflects the actual FC setting.

Fixes iNavFlight/inav#11316
- Add Angle Hold (mode 16) to flight mode operand types in classic
  programming tab (logicConditionOperantTypes.js). Firmware defines
  LOGIC_CONDITION_OPERAND_FLIGHT_MODE_ANGLEHOLD = 16 but it was missing
  from the UI, preventing users from selecting it as a flight mode operand.

- Add OPERATION_NAMES[56] (Override Min Ground Speed) to inav_constants.js.
  OPERATION.OVERRIDE_MIN_GROUND_SPEED = 56 was present but the human-readable
  name was missing, causing 'unknown_operation_56' in warning messages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On initial tab load, $mixerPreset.trigger('change') calls
updateMotorDirection() synchronously before Settings.configureInputs()
has populated the motor_direction_inverted radio buttons via async MSP
requests. This meant the default (props-in) image was always shown even
when the FC had reversed motor direction configured.

Fix: accept the settingsPromise passed by Settings.processHtml and
re-run updateMotorDirection() once it resolves, so the correct image
is shown after the settings values arrive. The change event handlers
are unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The help icon next to the Use Pilot Logo toggle was placed before the
label in DOM order with float:right and an i18n_title pointing at the
unrelated osd_use_large_pilot_logo_help string. Clicking the icon
toggled the switch and hovering showed the wrong (or no) tooltip,
because the icon sat inside the toggle's visual click area and never
opened Settings.md#osd_use_pilot_logo.

Move the helpicon out after the toggle's label, matching the pattern
used by other working help icons in the configurator (e.g. failsafe
Minimum Distance toggle), and point the tooltip at
osdElement_PILOT_LOGO_HELP, which actually describes osd_use_pilot_logo.

Fixes #2523
osd: fix help link for Use Pilot Logo toggle
Converts .content_toolbar from float: right buttons to a flex container,
giving proper left/right button group separation on firmware_flasher and
cli tabs without inline styles or undefined utility classes.

- .content_toolbar: display flex, justify-content flex-end, padding with box-sizing border-box
- .content_toolbar > div: flex row with gap for button groups
- .toolbar-left: margin-right auto to push sibling group to the right
- cli.html: replace float:left inline style and undefined pull-right class with toolbar-left
- firmware_flasher.html: add toolbar-left to flash group so backup buttons align right

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
handleReconnect() stored reopenTab inconsistently: the boolean=true
path stored the <li> element, while most tab callers passed the <a>
element directly. onValidFirmware then called $('a', reopenTab).trigger()
which finds nothing when reopenTab is already an <a>, so no tab was
navigated to after reconnect.

This left li.tab_landing still marked active from the disconnect phase.
GUI.updateActivatedTab() later re-triggered its click, but allowedTabs
was by then set to connected mode (no 'landing'), producing the
"You need to upgrade your firmware before you can use the Welcome tab"
error.

Fix by normalising reopenTab to always be the <a> element at storage
time in handleReconnect(), covering the boolean path, the element path
(handles both <a> and <li> callers including cliTab.exit), and the
false/null path. onValidFirmware then simply calls .trigger('click')
directly on the stored anchor.
If the user clicks Save while Settings.configureInputs() is still
loading settings asynchronously, some inputs may not yet have their
data-setting-info populated (set only after the FC responds to each
getSetting request). processInput() returns null for such inputs.

Guard against null to skip unpopulated inputs rather than crashing
with "Cannot read properties of null (reading 'setting')".
If an MSP response for a setting is malformed or truncated (e.g.
RangeError reading a uint16 from a too-short DataView), the error
propagated as an uncaught promise rejection and left the input in
the DOM without setting-info.

Catch errors per-setting in configureInputs and remove the input's
container, matching the existing behaviour for settings that don't
exist on the FC.
When getSetting fails (e.g. malformed MSP response), emit a console
error so the problem is visible for diagnosis rather than silently
removing the input from the DOM.

Root cause of the MSPV2_SETTING inconsistency was an LTO bug in the
firmware (fixed in inav/src/main/fc/settings.c). The catch here is
kept as a safety net for unexpected failures, but now surfaces them.
- Replace synchronous recursion with while loop in pickAndSaveSingleInput
  to avoid stack growth when many inputs have null settingPairs
- Add null guard to live change handler to close the same class of bug
  that pickAndSaveSingleInput was fixed for
FC.CONFIG.profile/mixer_profile/battery_profile are reset to -1 by
FC.resetState() on disconnect. The first status poll after reconnect
transitions -1 → actual_value, which was wrongly treated as a runtime
profile change, triggering updateActivatedTab() and re-initializing
the tab while settings were still loading async (causing DataView
out-of-bounds errors on in-flight MSP responses).

Guard against the -1 sentinel so only genuine in-session profile
changes (real_value → different_real_value) reload the tab.
…ab-error

fix: reopen correct tab after Save and Reboot
…ramework-constants

fix: sync JS programming framework constants with firmware
…tion-arrow-on-load

Fix mixer tab motor direction arrow not reflecting Props Out on load
…replacement-bug

Fix JS Programming decompiler: prevent space replacement with variable names
…d-wing

Hide motor direction radio box for non-multirotor platforms
…t-enable-toggle

OSD: Make custom elements UI more intuitive
Advanced Tuning tab always had a latent show/hide bug: processHtml()
checks FC.isAirplane()/isMultirotor() to show the correct section,
but never requested MIXER_CONFIG itself. If platformType was still -1
(the resetState() default), both isAirplane() and isMultirotor() return
false and the else branch renders both sections simultaneously.

Fix by adding an MSPChainer that fetches loadMixerConfig before calling
load_html(), matching the pattern already used in pid_tuning.js and
mixer.js. This ensures platformType is populated with the real FC value
before processHtml() makes visibility decisions.
Add smart rounding for unit-converted display values
…d-on-load

mixer: fix preview image not showing reversed on page load
fixed usb descriptor len mismatch on some chips
Submit foxeer m10q model fix to maintenance-9.x
toolbar: replace float-based layout with flexbox
…ixed-craft-type

fix(advanced-tuning): load mixer config before rendering tab
fix: The Alignment Tool's sliders are not linked to the Value fields
@qodo-code-review
Copy link
Copy Markdown
Contributor

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@github-actions
Copy link
Copy Markdown

Branch Targeting Suggestion

You've targeted the master branch with this PR. Please consider if a version branch might be more appropriate:

  • maintenance-9.x - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.

  • maintenance-10.x - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x

If master is the correct target for this change because it should never be included in any release, no action is needed.


This is an automated suggestion to help route contributions to the appropriate branch.

@sensei-hacker sensei-hacker merged commit 3e5d386 into master May 24, 2026
7 checks passed
@sonarqubecloud
Copy link
Copy Markdown

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.

5 participants