Skip to content

Conversation

@Erics1337
Copy link
Contributor

@Erics1337 Erics1337 commented Dec 5, 2025

Vue Migration Phase 5: Configuration Tab

Description

This PR implements the migration of the critical Configuration tab from legacy jQuery/HTML to a native Vue 3 component. The branch was built from a clean state (based on master) to ensure only essential dependencies were included.

Changes

  • Renamed Tab Logic: Migrated configuration.js to ConfigurationTab.vue.
  • New Component: Added ConfigurationTab.vue handling:
    • System Configuration (Gyro/PID loops)
    • Board Alignment & Sensors
    • Personalization (Craft/Pilot Name)
    • Features & Beepers
  • Infrastructure:
    • Added vue_tab_mounter.js utility for simple Vue tab mounting.
    • Updated main.js to mount ConfigurationTab via the new utility.
    • Registered ConfigurationTab in vue_components.js.

Testing

  • Loading: Checked that board alignment, sensor status, and features load correctly from FC.
  • Saving: verified that settings (custom name, board alignment, features) are saved and persisted after reboot.
  • Styling: Confirmed "Save" button is fixed to the bottom of the viewport.

Summary by CodeRabbit

  • New Features

    • Modern, data-driven Configuration tab UI consolidating system, sensors (including dual-gyro alignment), camera, arming, features, alignment and beeper settings with Save.
  • Refactor

    • Tab lifecycle moved to Vue mounting/unmounting; legacy Configuration implementation and static HTML replaced; Vue tab registry updated and Servos tab registered.
  • Chores

    • Added translation keys for configuration, sensor alignment and gyro calibration help; new sensor-alignment properties added to state.
  • Style

    • Improved alignment and spacing in sensor-alignment inputs.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

Walkthrough

Adds a new Vue single-file Configuration tab component and registers/mounts it (and ServosTab); removes the legacy configuration JS/HTML; updates tab mount/unmount lifecycle and MSP reboot callsite to use GUI.reinitializeConnection(); extends FC sensor-alignment defaults; adds localization keys and minor CSS tweaks.

Changes

Cohort / File(s) Summary
Vue Configuration Tab
src/components/tabs/ConfigurationTab.vue
New Vue SFC implementing the Configuration tab: reactive state, computed visibility flags, handlers for loading/initializing/updating/saving MSP-driven configuration, API-version-aware workflows, lifecycle hooks, watchers, and save action.
Tab Mounting & Registration
src/js/main.js, src/js/vue_components.js, src/js/vue_tab_mounter.js
Register and mount Vue tabs: import/register ConfigurationTab and ServosTab; add unmountVueTab usage before detaching content; set GUI.active_tab = tabName before mounting; removed a String.replaceAll polyfill.
Legacy Module & Template Removal
src/js/tabs/configuration.js, src/tabs/configuration.html
Removed legacy jQuery-driven configuration logic and its HTML template (UI rendering, event wiring, MSP sequencing, exported configuration), replaced by the Vue component.
MSP Helper / Reboot Path
src/js/msp/MSPHelper.js
Switched to default GUI import and replaced direct reinitializeConnection call with GUI.reinitializeConnection() in the EEPROM-reboot path.
FC Sensor Alignment Defaults
src/js/fc.js
Added new sensor alignment properties for additional gyros: gyro_1_align_roll/pitch/yaw, gyro_2_align_roll/pitch/yaw (initialized to 0).
Localization
locales/en/messages.json
Added and updated translation keys used by the new Vue UI (gyro alignment keys, configurationFeatureHelp, configurationSensors, configurationSensorsHelp, configurationSensorAlignmentCustom, configurationGyroCalOnFirstArmHelp, configurationGyroFrequency, etc.).
Styling
src/css/tabs/configuration.less
Adjusted sensor alignment inputs for vertical centering and label spacing (align-items: center; label display:flex + gap).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as ConfigurationTab.vue
    participant GUI
    participant MSP as MSPHelper
    participant FC as FlightController

    User->>UI: Open Configuration tab
    UI->>GUI: set active tab (GUI.active_tab)
    UI->>MSP: Request configuration blocks
    MSP->>FC: Send MSP read requests
    FC-->>MSP: Return configuration data
    MSP-->>UI: Deliver aggregated data
    UI->>UI: Initialize reactive state / UI controls

    User->>UI: Edit settings
    UI->>UI: Update reactive state

    User->>UI: Click Save
    UI->>MSP: Perform version-aware write sequence
    MSP->>FC: Apply writes
    FC-->>MSP: Acks
    MSP-->>UI: Save confirmations
    UI->>MSP: Request EEPROM finalize / reboot
    MSP->>GUI: call GUI.reinitializeConnection()
    GUI->>FC: reinitialize connection
    UI-->>User: Show save result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Extra attention:
    • src/components/tabs/ConfigurationTab.vue — MSP sequencing, version-guard logic, watchers, and the large public reactive API surface.
    • Tab lifecycle: src/js/main.js and src/js/vue_tab_mounter.js — ensure correct mount/unmount ordering and no resource leaks.
    • Parity/behavior: verify save/read sequences match removed legacy src/js/tabs/configuration.js flows.

Possibly related PRs

Suggested labels

RN: UI

Suggested reviewers

  • haslinghuis
  • VitroidFPV
  • nerdCopter

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main objective of the PR: migrating the Configuration tab from legacy code to Vue 3.
Description check ✅ Passed The description provides a structured overview with the PR objective, changes made, and testing performed, following the repository's guidelines.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
src/js/vue_components.js (1)

9-11: Consider removing redundant global component registration.

ConfigurationTab is registered both in VueTabComponents (for dynamic mounting via mountVueTab) and as a global component via app.component(). Since Vue tab components are mounted directly through createApp + h(TabComponent) in vue_tab_mounter.js, the global registration at line 22 is unnecessary.

         app.component("BatteryIcon", BatteryIcon);
         app.component("PortPicker", PortPicker);
-        app.component("ConfigurationTab", ConfigurationTab);
     },

Also applies to: 22-22

src/js/vue_tab_mounter.js (1)

71-77: Consider using Vue's nextTick for more idiomatic behavior.

Using setTimeout(..., 0) works but Vue's nextTick is the idiomatic way to defer execution until after the DOM updates.

+import { createApp, h, nextTick } from "vue";
-import { createApp, h } from "vue";
     // Reset tab switch flag and call content ready callback after next tick
-    setTimeout(() => {
+    nextTick(() => {
         GUI.tab_switch_in_progress = false;
         if (contentReadyCallback) {
             contentReadyCallback();
         }
-    }, 0);
+    });
src/components/tabs/ConfigurationTab.vue (2)

557-570: Add curly braces to early-return statements for consistency.

SonarCloud is flagging missing curly braces after if conditions. While functionally correct, adding braces improves readability and prevents potential maintenance issues.

 const featuresList = computed(() => {
-    if (!FC.FEATURE_CONFIG?.features?._features) return [];
+    if (!FC.FEATURE_CONFIG?.features?._features) {
+        return [];
+    }
     return FC.FEATURE_CONFIG.features._features;
 });

 const beepersList = computed(() => {
-    if (!FC.BEEPER_CONFIG?.beepers?._beepers) return [];
+    if (!FC.BEEPER_CONFIG?.beepers?._beepers) {
+        return [];
+    }
     return FC.BEEPER_CONFIG.beepers._beepers;
 });

 const dshotBeaconConditionsList = computed(() => {
-    if (!FC.BEEPER_CONFIG?.dshotBeaconConditions?._beepers) return [];
+    if (!FC.BEEPER_CONFIG?.dshotBeaconConditions?._beepers) {
+        return [];
+    }
     return FC.BEEPER_CONFIG.dshotBeaconConditions._beepers;
 });

Apply similar changes to functions at lines 575-590, 592-613, 615-634.


837-889: Incomplete save functionality - TODO needs implementation.

The saveConfig function only writes values to the FC objects but doesn't actually send MSP commands to persist changes to the flight controller. The TODO at line 888 indicates this is intentional, but this should be tracked.

Would you like me to help implement the MSP save chain? The legacy configuration.js likely has the pattern of chained MSP.send() calls that should be replicated here. This is essential for the tab to function correctly.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between caebd08 and 67d2505.

📒 Files selected for processing (4)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/js/main.js (2 hunks)
  • src/js/vue_components.js (2 hunks)
  • src/js/vue_tab_mounter.js (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/js/main.js
  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-10T18:26:10.136Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🧬 Code graph analysis (3)
src/js/main.js (1)
src/js/vue_tab_mounter.js (1)
  • mountVueTab (31-80)
src/js/vue_tab_mounter.js (3)
src/js/main.js (2)
  • tabName (139-139)
  • tabName (173-173)
src/js/vue_components.js (2)
  • VueTabComponents (9-11)
  • VueTabComponents (9-11)
src/js/gui.js (1)
  • GUI (473-473)
src/js/vue_components.js (2)
src/components/init.js (1)
  • app (60-64)
src/js/vue_loader.js (1)
  • app (42-42)
🪛 GitHub Actions: Deployment (PR and Push)
src/components/tabs/ConfigurationTab.vue

[error] 1-1: Build failed: Could not resolve '../../js/msp/mspHelper' from 'src/components/tabs/ConfigurationTab.vue' (vite-plugin-pwa:build).

🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 622-622: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 593-593: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[failure] 558-558: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[failure] 576-576: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727


[failure] 616-616: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727


[failure] 776-776: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[warning] 392-392: Add "" headers to this "

".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdg&open=AZrw8w-eZYszuChvcCdg&pullRequest=4727


[failure] 563-563: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727


[failure] 568-568: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[warning] 888-888: Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdr&open=AZrw8w-eZYszuChvcCdr&pullRequest=4727


[failure] 581-581: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727


[failure] 599-599: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727

🔇 Additional comments (4)
src/js/main.js (1)

290-292: LGTM - Vue tab mounting integration looks correct.

The configuration tab now uses mountVueTab which properly handles the Vue component lifecycle, i18n setup, and the content_ready callback. This is consistent with the new Vue-based tab mounting pattern introduced in this PR.

src/js/vue_tab_mounter.js (1)

31-80: LGTM - Well-structured Vue tab mounting utility.

The mounting logic correctly:

  • Validates component existence and DOM container
  • Cleans up previous Vue app instances before mounting new ones
  • Sets up i18n via i18next-vue
  • Provides the global betaflight model to the component tree
  • Handles the content ready callback
src/components/tabs/ConfigurationTab.vue (2)

775-782: Bitmask usage with << 0 is intentional for flag constants.

SonarCloud flags 1 << 0 suggesting Math.trunc instead, but this is a false positive. The bitshift operators here are intentionally creating bitmask constants for gyro detection flags. This pattern is common and correct.


521-521: Critical: Verify build failure due to import path resolution.

The pipeline reports that import mspHelper from "../../js/msp/mspHelper" cannot be resolved. Check the actual file location and naming in the src/js/msp/ directory—the file may have different casing (e.g., MSPHelper.js) or be located elsewhere.

@Erics1337
Copy link
Contributor Author

Still working this

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (3)
src/components/tabs/ConfigurationTab.vue (3)

783-784: Remove duplicate function call.

updateGyroDenom(FC.CONFIG.sampleRateHz) is called twice consecutively, which is redundant.

             // Gyro Frequency Logic
             updateGyroDenom(FC.CONFIG.sampleRateHz);
-            updateGyroDenom(FC.CONFIG.sampleRateHz);
             updatePidDenomOptions();

392-423: Add table headers for accessibility.

The features table lacks <th> elements, which is an accessibility concern for screen readers.

Refer to the previous review comment for the complete solution involving adding a visually-hidden <thead> with proper column headers.


582-582: showOtherSensors should be computed.

showOtherSensors is initialized as ref(false) but never updated, so the "Other Features" section (line 346) will never be visible even when mag declination, rangefinder, or optical flow should be shown.

Convert it to a computed property:

-        const showOtherSensors = ref(false);
         const showMagDeclination = ref(false);
         const showRangefinder = ref(false);
         const showOpticalFlow = ref(false);
+        const showOtherSensors = computed(() => 
+            showMagDeclination.value || showRangefinder.value || showOpticalFlow.value
+        );
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67d2505 and 4954e30.

📒 Files selected for processing (1)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-10T18:26:10.136Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🪛 GitHub Actions: Deployment (PR and Push)
src/components/tabs/ConfigurationTab.vue

[error] 1-1: Build failed: Could not resolve "../../js/msp/mspHelper" from ConfigurationTab.vue during build. This prevents the production bundle from being generated.

🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 665-665: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 624-624: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727


[failure] 619-619: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727


[warning] 392-392: Add "" headers to this "

".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdg&open=AZrw8w-eZYszuChvcCdg&pullRequest=4727


[failure] 601-601: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[failure] 642-642: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727


[warning] 931-931: Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdr&open=AZrw8w-eZYszuChvcCdr&pullRequest=4727


[failure] 611-611: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[failure] 636-636: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[failure] 819-819: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[failure] 659-659: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727


[failure] 606-606: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/components/tabs/ConfigurationTab.vue (1)

392-423: Add a header row (<th>) to the features table for accessibility.

The features table still has only <tbody>/<tr>/<td> cells, so screen readers can’t associate cells with column headers. As previously noted, consider adding a visually hidden header row with <th scope="col"> cells describing each column (enabled, name, description, help), and a .visually-hidden CSS class if you don’t want visible headers.

🧹 Nitpick comments (3)
src/js/msp/MSPHelper.js (1)

2934-2954: EEPROM write still depends solely on the MSP_EEPROM_WRITE callback; consider adding a timeout-based reboot fallback.

writeConfiguration only calls GUI.tab_switch_cleanup(() => GUI.reinitializeConnection()) from inside the MSP_EEPROM_WRITE callback. On BLE (Android), prior analysis showed this ACK can be lost when status polls keep hammering the MSP queue, leaving the UI stuck and never rebooting. Based on learnings, it would be safer to:

  • Stop periodic MSP traffic before sending MSP_EEPROM_WRITE (e.g., GUI.interval_kill_all() and MSP.callbacks_cleanup()), and
  • Add a short timeout fallback (≈3 s) that triggers GUI.reinitializeConnection() even if the EEPROM ACK never arrives.

This keeps the Save & Reboot flow robust on slower links while preserving the existing callback semantics. Based on learnings, this was the recommended mitigation for BLE timeouts.

src/js/main.js (1)

16-16: Vue configuration tab mounting looks correct; optional: rely on a single unmount path.

The configuration tab now uses mountVueTab("configuration", content_ready), consistent with other Vue tabs, and the explicit unmountVueTab() in the tab switch cleanup safely clears any previous Vue app.

Note that mountVueTab itself already calls unmountVueTab() and clears #content, so the extra unmount in main.js is redundant. You can keep it for explicitness or remove it to centralize tab teardown in vue_tab_mounter.js.

Also applies to: 215-216, 290-292

src/components/tabs/ConfigurationTab.vue (1)

885-991: Delegate reboot behavior to writeConfiguration(true) instead of duplicating it here.

saveConfig pushes all FC fields back into the model, then:

mspHelper.writeConfiguration(false, () => {
    GUI.tab_switch_cleanup(() => {
        reinitializeConnection();
    });
});

However, MspHelper.prototype.writeConfiguration already has explicit support for the reboot flow when reboot is true (including calling GUI.tab_switch_cleanup and GUI.reinitializeConnection). Duplicating that behavior here:

  • Fragments the Save & Reboot logic across two places, and
  • Makes it harder to apply cross‑cutting fixes (e.g., improving robustness around MSP_EEPROM_WRITE ACK timing as per the BLE learnings).

You can simplify and centralize the reboot behavior by letting writeConfiguration own it:

-                // Save to EEPROM and Reboot
-                mspHelper.writeConfiguration(false, () => {
-                   GUI.tab_switch_cleanup(() => {
-                        reinitializeConnection();
-                   });
-                });
+                // Save to EEPROM and reboot using the shared helper logic
+                mspHelper.writeConfiguration(true);

Any additional post‑reboot work specific to this tab can be added via an optional callback, but the core “save to EEPROM, reboot, and reconnect” flow should remain in one place.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4954e30 and 27e7308.

📒 Files selected for processing (6)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/js/main.js (4 hunks)
  • src/js/msp/MSPHelper.js (2 hunks)
  • src/js/serial_backend.js (4 hunks)
  • src/js/vue_components.js (2 hunks)
  • src/js/vue_tab_mounter.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/js/vue_components.js
  • src/js/vue_tab_mounter.js
🧰 Additional context used
🧠 Learnings (20)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.
📚 Learning: 2025-10-25T21:16:32.474Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4379
File: src/js/protocols/TauriSerial.js:203-259
Timestamp: 2025-10-25T21:16:32.474Z
Learning: In TauriSerial (src/js/protocols/TauriSerial.js), the requestPermissionDevice() method is not needed and not invoked. Tauri automatically discovers serial devices through the constructor's loadDevices() and startDeviceMonitoring() calls, bypassing the browser permission model that WebSerial requires. Devices are auto-detected via a 1-second polling interval without user permission prompts.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-27T19:36:13.733Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/tabs/pid_tuning.js:80-82
Timestamp: 2025-08-27T19:36:13.733Z
Learning: MSP_STATUS_EX calls in serial_backend.js and setup.js are intentionally unguarded because they are used for status fetching on page load to initialize profiles and are safe to call on older firmware versions. Only conditional/optional MSP_STATUS_EX usage (like in pid_tuning.js) needs version gating to API_VERSION_25_12.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-06-19T22:13:09.136Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4521
File: src/js/protocols/WebSerial.js:148-151
Timestamp: 2025-06-19T22:13:09.136Z
Learning: In WebSerial.js, there's a timing issue where the cached `this.ports` array doesn't immediately reflect newly permitted devices after `requestPermissionDevice()` completes. The `getDevices()` method needs to refresh the device list from the browser API to return accurate data immediately following a permission request and user acceptance.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-22T16:43:20.901Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4576
File: src/js/port_usage.js:17-23
Timestamp: 2025-08-22T16:43:20.901Z
Learning: In betaflight-configurator, the serial facade architecture requires accessing metrics like bitrate, bytesReceived, and bytesSent from serial._protocol rather than the top-level serial object. This change maintains compatibility with existing port utilization calculations that have been stable for over 11 years.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-11-28T22:41:59.374Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4714
File: src/js/protocols/CapacitorBluetooth.js:135-143
Timestamp: 2025-11-28T22:41:59.374Z
Learning: In betaflight-configurator, WebSerial.js uses a constant path "serial" for all devices, and CapacitorBluetooth.js uses constant path "bluetooth", consistent with the single-device-at-a-time workflow. WebBluetooth.js uses counter-based paths (bluetooth_${counter}), but that's specific to its implementation. The path strategy varies by protocol based on their specific requirements.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-12-01T17:38:41.581Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:38:41.581Z
Learning: On BLE (Android) Save & Reboot, status pull intervals continue during MSP_EEPROM_WRITE, overwhelming the MSP queue and causing the EEPROM ack to time out so reinitializeConnection never runs. Solution: before EEPROM write, call GUI.interval_kill_all() and MSP.callbacks_cleanup(), and add a 3s fallback to proceed to reboot if the ack is missed.

Applied to files:

  • src/js/serial_backend.js
  • src/components/tabs/ConfigurationTab.vue
  • src/js/msp/MSPHelper.js
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • src/js/msp/MSPHelper.js
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • src/js/main.js
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-10T18:26:10.136Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🧬 Code graph analysis (3)
src/js/serial_backend.js (2)
src/js/data_storage.js (1)
  • CONFIGURATOR (8-39)
src/js/gui.js (1)
  • GUI (473-473)
src/js/main.js (1)
src/js/vue_tab_mounter.js (2)
  • unmountVueTab (88-93)
  • mountVueTab (31-83)
src/js/msp/MSPHelper.js (1)
src/js/gui.js (1)
  • GUI (473-473)
🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 614-614: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[failure] 663-663: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727


[failure] 627-627: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727


[failure] 604-604: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[failure] 609-609: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727


[failure] 640-640: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[warning] 392-392: Add "" headers to this "

".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdg&open=AZrw8w-eZYszuChvcCdg&pullRequest=4727


[failure] 823-823: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[failure] 646-646: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727


[failure] 669-669: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 622-622: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (5)
src/js/msp/MSPHelper.js (1)

17-17: Restore TABS import to avoid runtime error in MSP_SET_REBOOT failure path.

TABS is still referenced in the unsupported‑message branch (TABS.onboard_logging.mscRebootFailedCallback()), but line 17 now imports only the default GUI. This will throw a ReferenceError the first time an unsupported MSP_SET_REBOOT is reported.

Consider re‑adding the named export alongside the default:

-import GUI from "../gui";
+import GUI, { TABS } from "../gui";
src/components/tabs/ConfigurationTab.vue (3)

584-585: MAG alignment dropdown visibility needs verification

showMagAlign is initialized to false and appears to never be set, which would prevent users from accessing the magnetometer alignment control. If confirmed, this should be driven by real state (sensor presence and API version) to match legacy behavior where MAG alignment was conditionally shown based on firmware capabilities.


33-42: Gyro sync denominator select is effectively disabled (showGyroSyncDenom never set).

The gyro sync denominator <select class="gyroSyncDenom"> is wrapped in v-show="showGyroSyncDenom", but showGyroSyncDenom is a ref(false) and is never updated. As a result, pidAdvancedConfig.gyro_sync_denom is loaded and saved but cannot be changed from the UI.

If the intent is to mirror the legacy behavior (hide only when there is no gyro or sample rate is unknown), you could set this flag in initializeUI():

        const gyroFrequencyDisplay = ref("");
-        const showGyroSyncDenom = ref(false);
+        const showGyroSyncDenom = ref(false);
...
        const initializeUI = () => {
            // Populate Reactive State
            pidAdvancedConfig.gyro_sync_denom = FC.PID_ADVANCED_CONFIG.gyro_sync_denom;
            pidAdvancedConfig.pid_process_denom = FC.PID_ADVANCED_CONFIG.pid_process_denom;

            ...
            // Gyro Frequency Logic
            updateGyroDenom(FC.CONFIG.sampleRateHz);
+           showGyroSyncDenom.value = FC.CONFIG.sampleRateHz > 0;

Adjust the condition as needed to match the old configuration tab's visibility rules. Also applies to lines 707-709 and 786-790.


541-545: Verify code structure and initialization of sensorConfig and showOtherSensors in ConfigurationTab.vue

The review identifies three potential issues with the Configuration Tab component:

  1. The sensorConfig reactive object is missing sonar_hardware and opticalflow_hardware properties that are bound in the template
  2. The showOtherSensors ref is initialized as false and never updated, preventing the entire "Other Features/Sensors" section from rendering
  3. When API >= 1.47, sonar and optical flow type lists are populated but current hardware values from FC.SENSOR_CONFIG are never copied into sensorConfig, causing dropdowns to lose existing configuration

The proposed fixes suggest adding the missing properties to sensorConfig, making showOtherSensors a computed value derived from its sub-section visibility flags, and initializing sonar/optical hardware values from FC.SENSOR_CONFIG in the API >= 1.47 branch.

Manual verification needed at the specified lines to confirm these issues exist and assess the impact on sonar/rangefinder and optical flow sensor configuration handling.

src/js/serial_backend.js (1)

62-71: Fix operator precedence in auto‑connect condition so reboot window respects other safeguards.

The condition in the port-handler:auto-select-serial-device handler is parsed as (A && B && C && D && E && F) || G due to && binding tighter than ||. This allows connectDisconnect() to fire during the reboot window even if autoConnect is disabled, the active tab is CLI/firmware flasher, or a connection is already in progress.

Wrap the timestamp checks to gate the reboot window by the other conditions:

         if (
             !GUI.connected_to &&
             !GUI.connecting_to &&
             !["cli", "firmware_flasher"].includes(GUI.active_tab) &&
             PortHandler.portPicker.autoConnect &&
             !isCliOnlyMode() &&
-            (connectionTimestamp === null || connectionTimestamp > 0) ||
-            (Date.now() - rebootTimestamp <= REBOOT_CONNECT_MAX_TIME_MS)
+            ((connectionTimestamp === null || connectionTimestamp > 0) ||
+                Date.now() - rebootTimestamp <= REBOOT_CONNECT_MAX_TIME_MS)
         ) {
             connectDisconnect();
         }

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/components/tabs/ConfigurationTab.vue (1)

392-423: Add header row with <th> cells for the features table.

This table still has only <td> cells and no column headers, which breaks accessibility and keeps the Sonar warning open. Add a <thead> with one <th> per column (checkbox, name, short label, help/description), using scope="col" or a visually hidden header row if you want to preserve the current visual layout.

🧹 Nitpick comments (1)
src/components/tabs/ConfigurationTab.vue (1)

603-617: Address Sonar “Expected { after 'if' condition” by adding braces.

Several single-line if statements here (e.g., the guard clauses in featuresList, beepersList, dshotBeaconConditionsList, and the early returns in toggleFeature, toggleBeeper, toggleDshotCondition) are written without braces, which Sonar flags as failures.

To satisfy the rule and avoid future foot‑guns, wrap these in blocks, e.g.:

-const featuresList = computed(() => {
-    if (!FC.FEATURE_CONFIG?.features?._features) return [];
-    return FC.FEATURE_CONFIG.features._features;
-});
+const featuresList = computed(() => {
+    if (!FC.FEATURE_CONFIG?.features?._features) {
+        return [];
+    }
+    return FC.FEATURE_CONFIG.features._features;
+});

and similarly for the other guard ifs.

Also applies to: 620-627, 639-647, 662-670

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 27e7308 and 0f43e38.

📒 Files selected for processing (1)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-01T17:38:41.581Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:38:41.581Z
Learning: On BLE (Android) Save & Reboot, status pull intervals continue during MSP_EEPROM_WRITE, overwhelming the MSP queue and causing the EEPROM ack to time out so reinitializeConnection never runs. Solution: before EEPROM write, call GUI.interval_kill_all() and MSP.callbacks_cleanup(), and add a 3s fallback to proceed to reboot if the ack is missed.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 640-640: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[failure] 627-627: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727


[failure] 669-669: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 646-646: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727


[failure] 823-823: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[warning] 392-392: Add "" headers to this "

".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdg&open=AZrw8w-eZYszuChvcCdg&pullRequest=4727


[failure] 663-663: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727


[failure] 604-604: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[failure] 622-622: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727


[failure] 614-614: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[failure] 609-609: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (1)
src/components/tabs/ConfigurationTab.vue (1)

885-991: Save chain wiring looks consistent with legacy behavior.

The save path updates FC structures, issues the expected MSP_SET_* commands (feature, beeper, board alignment, arming, sensor, sensor alignment, names, RX, advanced, compass), then delegates EEPROM write + reboot to mspHelper.writeConfiguration, including GUI.tab_switch_cleanup and reconnection. This aligns with the established pattern and should avoid the BLE/Android EEPROM‑ack issues noted elsewhere, assuming other tabs use the same helper.

@Erics1337 Erics1337 force-pushed the vue-tab-config branch 2 times, most recently from 1e01c2c to 6aaa3a6 Compare December 7, 2025 21:15
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (4)
src/components/tabs/ConfigurationTab.vue (4)

391-422: Add table headers for accessibility.

The features table lacks <thead> elements with <th> headers, which is an accessibility concern. Screen readers need column headers to map cells correctly.

 <table class="features-table">
+    <thead class="visually-hidden">
+        <tr>
+            <th scope="col">{{ $t("configurationFeatureEnabled") }}</th>
+            <th scope="col">{{ $t("configurationFeatureName") }}</th>
+            <th scope="col">{{ $t("configurationFeatureDescription") }}</th>
+        </tr>
+    </thead>
     <tbody>

Add a CSS class for visually-hidden headers if needed:

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border: 0;
}

582-582: Make showOtherSensors a computed property.

showOtherSensors is initialized as ref(false) and never updated, so the "Other Sensors" card (line 345) will never be visible even when mag declination, rangefinder, or optical flow should be shown.

-const showOtherSensors = ref(false);
+const showOtherSensors = computed(() => 
+    showMagDeclination.value || showRangefinder.value || showOpticalFlow.value
+);

This automatically shows the card when any of its child sections are visible.


579-581: Set showMagAlign visibility based on API version and sensor presence.

showMagAlign is initialized to false and never updated in initializeUI(), so the MAG alignment dropdown (lines 331-338) will never be visible.

Based on learnings, MAG alignment should be shown for API >= 1.47 when a magnetometer is detected. Add logic in initializeUI():

 // Mag Declination
 if (have_sensor(FC.CONFIG.activeSensors, "mag") && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
     showMagDeclination.value = true;
     magDeclination.value = FC.COMPASS_CONFIG.mag_declination;
+    
+    // Show MAG alignment for API 1.47+
+    if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+        showMagAlign.value = true;
+    }
 } else {
     showMagDeclination.value = false;
+    showMagAlign.value = false;
 }

Based on learnings, as per coding guidelines, ...

Also applies to: 833-838


538-542: Initialize sonar and optical flow hardware fields.

The sensorConfig reactive object is missing sonar_hardware and opticalflow_hardware fields, but the template (lines 360, 370) binds to them and saveConfig() (lines 930-931) writes them back to FC. This will cause the dropdowns to start with undefined values and potentially overwrite valid FC configuration.

 const sensorConfig = reactive({
     acc_hardware: 0,
     baro_hardware: 0,
     mag_hardware: 0,
+    sonar_hardware: 0,
+    opticalflow_hardware: 0,
 });

Also add initialization in initializeUI() around line 766:

 sensorConfig.acc_hardware = FC.SENSOR_CONFIG.acc_hardware;
 sensorConfig.baro_hardware = FC.SENSOR_CONFIG.baro_hardware;
 sensorConfig.mag_hardware = FC.SENSOR_CONFIG.mag_hardware;
+sensorConfig.sonar_hardware = FC.SENSOR_CONFIG.sonar_hardware || 0;
+sensorConfig.opticalflow_hardware = FC.SENSOR_CONFIG.opticalflow_hardware || 0;
🧹 Nitpick comments (2)
src/components/tabs/ConfigurationTab.vue (2)

705-706: Remove or implement gyro sync denominator control.

showGyroSyncDenom is hardcoded to false (line 706) and the gyro sync denom dropdown (lines 35-40) is never shown, making it dead code. The PR author may intend to complete this feature later.

Since this is work-in-progress, consider:

  • Implement the show/hide logic if gyro sync denom should be user-configurable
  • Remove the dead code (dropdown + ref) if this feature is not needed

820-826: Prefer Math.trunc over bitshift operator.

The bitshift operator << 0 on line 820 is flagged by static analysis. While this works, Math.trunc() is clearer and more maintainable.

 const GYRO_DETECTION_FLAGS = {
-    DETECTED_GYRO_1: 1 << 0,
-    DETECTED_GYRO_2: 1 << 1,
-    DETECTED_DUAL_GYROS: 1 << 7,
+    DETECTED_GYRO_1: Math.trunc(1 << 0),
+    DETECTED_GYRO_2: Math.trunc(1 << 1),
+    DETECTED_DUAL_GYROS: Math.trunc(1 << 7),
 };

Actually, the bitshift itself is fine for flag definitions. The linter may be concerned about implicit integer conversion elsewhere. You can safely ignore this if the flags work correctly.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f43e38 and 0024d96.

📒 Files selected for processing (6)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/js/main.js (3 hunks)
  • src/js/msp/MSPHelper.js (2 hunks)
  • src/js/serial_backend.js (4 hunks)
  • src/js/vue_components.js (2 hunks)
  • src/js/vue_tab_mounter.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/js/vue_tab_mounter.js
  • src/js/msp/MSPHelper.js
🧰 Additional context used
🧠 Learnings (21)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/js/main.js
  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-10T18:26:10.136Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.

Applied to files:

  • src/js/vue_components.js
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-10-25T21:16:32.474Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4379
File: src/js/protocols/TauriSerial.js:203-259
Timestamp: 2025-10-25T21:16:32.474Z
Learning: In TauriSerial (src/js/protocols/TauriSerial.js), the requestPermissionDevice() method is not needed and not invoked. Tauri automatically discovers serial devices through the constructor's loadDevices() and startDeviceMonitoring() calls, bypassing the browser permission model that WebSerial requires. Devices are auto-detected via a 1-second polling interval without user permission prompts.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-06-19T22:13:09.136Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4521
File: src/js/protocols/WebSerial.js:148-151
Timestamp: 2025-06-19T22:13:09.136Z
Learning: In WebSerial.js, there's a timing issue where the cached `this.ports` array doesn't immediately reflect newly permitted devices after `requestPermissionDevice()` completes. The `getDevices()` method needs to refresh the device list from the browser API to return accurate data immediately following a permission request and user acceptance.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-11-28T22:41:59.374Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4714
File: src/js/protocols/CapacitorBluetooth.js:135-143
Timestamp: 2025-11-28T22:41:59.374Z
Learning: In betaflight-configurator, WebSerial.js uses a constant path "serial" for all devices, and CapacitorBluetooth.js uses constant path "bluetooth", consistent with the single-device-at-a-time workflow. WebBluetooth.js uses counter-based paths (bluetooth_${counter}), but that's specific to its implementation. The path strategy varies by protocol based on their specific requirements.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-27T19:36:13.733Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/tabs/pid_tuning.js:80-82
Timestamp: 2025-08-27T19:36:13.733Z
Learning: MSP_STATUS_EX calls in serial_backend.js and setup.js are intentionally unguarded because they are used for status fetching on page load to initialize profiles and are safe to call on older firmware versions. Only conditional/optional MSP_STATUS_EX usage (like in pid_tuning.js) needs version gating to API_VERSION_25_12.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-22T16:43:20.901Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4576
File: src/js/port_usage.js:17-23
Timestamp: 2025-08-22T16:43:20.901Z
Learning: In betaflight-configurator, the serial facade architecture requires accessing metrics like bitrate, bytesReceived, and bytesSent from serial._protocol rather than the top-level serial object. This change maintains compatibility with existing port utilization calculations that have been stable for over 11 years.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-12-01T17:38:41.581Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:38:41.581Z
Learning: On BLE (Android) Save & Reboot, status pull intervals continue during MSP_EEPROM_WRITE, overwhelming the MSP queue and causing the EEPROM ack to time out so reinitializeConnection never runs. Solution: before EEPROM write, call GUI.interval_kill_all() and MSP.callbacks_cleanup(), and add a 3s fallback to proceed to reboot if the ack is missed.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🧬 Code graph analysis (2)
src/js/main.js (1)
src/js/vue_tab_mounter.js (2)
  • unmountVueTab (88-93)
  • mountVueTab (31-83)
src/js/vue_components.js (2)
src/components/init.js (1)
  • app (60-64)
src/js/vue_loader.js (1)
  • app (42-42)
🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 637-637: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[failure] 601-601: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[failure] 666-666: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 619-619: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727


[failure] 611-611: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[failure] 660-660: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727


[failure] 624-624: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727


[warning] 391-391: Add "" headers to this "

".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdg&open=AZrw8w-eZYszuChvcCdg&pullRequest=4727


[warning] 442-442: Add "

" headers to this "".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZr6qGM3VcdC4SjUxZEA&open=AZr6qGM3VcdC4SjUxZEA&pullRequest=4727


[failure] 820-820: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[failure] 606-606: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727


[failure] 643-643: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: deploy
🔇 Additional comments (10)
src/js/serial_backend.js (4)

605-605: LGTM - reboot timestamp cleanup.

Resetting rebootTimestamp to 0 after a successful connection properly clears the reboot state, preventing stale reboot windows from affecting future connection attempts.


806-820: LGTM - explicit connection invalidation during reboot.

Setting CONFIGURATOR.connectionValid = false before sending the reboot command ensures the reboot dialog will wait for reconnection rather than proceeding prematurely. This aligns with the broader reboot handling improvements in this PR.


920-920: LGTM - GUI namespace exposure for cross-module access.

Exposing reinitializeConnection on the GUI object allows MSPHelper.js to invoke the reboot flow without creating circular dependencies. This is a cleaner approach than the previous direct import.


63-74: Verify the refactored auto-connect condition logic requires access to the full codebase context.

The auto-connect condition at lines 63-74 has been restructured with an OR branch for reboot-timestamp gating. The new structure separates reboot reconnection into its own condition that appears to bypass the safety checks in the first branch (connected_to, connecting_to, active_tab, autoConnect, isCliOnlyMode, connectionTimestamp).

To confirm this is intentional and safe, verification requires examining:

  • How rebootTimestamp is set and cleared throughout the file
  • Whether bypassing the other safety gates during the reboot window (within REBOOT_CONNECT_MAX_TIME_MS) is the intended behavior
  • Edge cases where the system enters the reboot window but the normal connection guards should still apply

Without access to the full codebase context, the refactoring cannot be definitively verified as correct.

src/js/vue_components.js (2)

10-18: LGTM - standard Vue component registration.

The ConfigurationTab component is properly imported and registered in the VueTabComponents mapping, following the same pattern as other tab components (HelpTab, LandingTab, OptionsTab).


33-33: LGTM - global component registration.

The ConfigurationTab is correctly registered globally in the BetaflightComponents plugin, making it available throughout the Vue application.

src/js/main.js (3)

16-16: LGTM - unmountVueTab import.

Adding the unmountVueTab import enables proper cleanup of Vue tab instances during tab switching.


213-214: LGTM - proper Vue tab cleanup.

Calling unmountVueTab() before clearing content ensures the previous Vue tab app is properly unmounted, preventing memory leaks and ensuring clean transitions between tabs.


288-290: LGTM - configuration tab Vue migration.

The configuration tab now uses mountVueTab("configuration", content_ready) instead of the legacy dynamic import pattern, completing the migration to Vue 3 for this tab.

src/components/tabs/ConfigurationTab.vue (1)

518-519: Verify import paths are correct.

The imports reference mspHelper from MSPHelper.js and reinitializeConnection from serial_backend.js. Confirm these exports exist and are accessible from the component's location.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (5)
src/components/tabs/ConfigurationTab.vue (5)

33-42: gyro_sync_denom select is permanently hidden

showGyroSyncDenom is initialized as ref(false) but never updated, so the <select class="gyroSyncDenom"> is always hidden and users can’t adjust pidAdvancedConfig.gyro_sync_denom, even though you load and save it.

Consider enabling the control based on the presence of the field (or the legacy conditions in configuration.js), e.g. in initializeUI():

 const initializeUI = () => {
     // Populate Reactive State
     pidAdvancedConfig.gyro_sync_denom = FC.PID_ADVANCED_CONFIG.gyro_sync_denom;
     pidAdvancedConfig.pid_process_denom = FC.PID_ADVANCED_CONFIG.pid_process_denom;
+    showGyroSyncDenom.value = typeof FC.PID_ADVANCED_CONFIG.gyro_sync_denom !== "undefined";

This restores the ability to configure gyro_sync_denom while keeping the select hidden on firmware that doesn’t expose it.

Also applies to: 704-707, 761-787


330-381: MAG alignment and “Other Sensors” card never become visible

Two related visibility issues:

  1. showMagAlign is a ref(false) and is never set to true, so the MAG alignment <select> (lines 331–338) is never displayed, even when a MAG is present and API ≥ 1.47. Legacy behavior was to hide MAG alignment only for older APIs. Based on learnings about API‑gated MAG alignment, you likely want something like inside initializeUI():
-        const magDeclination = ref(0);
+        const magDeclination = ref(0);
         ...
-        const showMagAlign = ref(false);
+        const showMagAlign = ref(false);
         ...
 const initializeUI = () => {
     ...
+    const hasMag = have_sensor(FC.CONFIG.activeSensors, "mag");
+    if (hasMag && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+        showMagAlign.value = true;
+    } else {
+        showMagAlign.value = false;
+    }
  1. showOtherSensors is a plain ref(false) and never updated, but the entire “Other Sensors” box (lines 344–379) is gated on it. Even when showMagDeclination, showRangefinder, or showOpticalFlow are set to true in initializeUI(), the card remains hidden.

A simple fix is to make showOtherSensors a computed:

-        const showOtherSensors = ref(false);
+        const showOtherSensors = computed(
+            () => showMagDeclination.value || showRangefinder.value || showOpticalFlow.value,
+        );

This matches the intended behavior: the card appears whenever at least one of its controls is relevant.

Also applies to: 574-585, 832-849


538-542: Initialize sonar/optical flow hardware fields to avoid clobbering FC state

sensorConfig only defines acc_hardware, baro_hardware, and mag_hardware, but the template and save logic also use sensorConfig.sonar_hardware and sensorConfig.opticalflow_hardware:

  • Rangefinder / optical flow dropdowns (v-model.number="sensorConfig.sonar_hardware" and .opticalflow_hardware).
  • saveConfig() writes them back to FC.SENSOR_CONFIG for API ≥ 1.47.

Because these fields are never initialized from FC.SENSOR_CONFIG, they start as undefined and will overwrite the controller’s configuration with undefined (or an unintended default) on save if the user doesn’t touch the selects.

Recommend:

-        const sensorConfig = reactive({
-            acc_hardware: 0,
-            baro_hardware: 0,
-            mag_hardware: 0,
-        });
+        const sensorConfig = reactive({
+            acc_hardware: 0,
+            baro_hardware: 0,
+            mag_hardware: 0,
+            sonar_hardware: 0,
+            opticalflow_hardware: 0,
+        });

and in initializeUI():

     sensorConfig.acc_hardware = FC.SENSOR_CONFIG.acc_hardware;
     sensorConfig.baro_hardware = FC.SENSOR_CONFIG.baro_hardware;
     sensorConfig.mag_hardware = FC.SENSOR_CONFIG.mag_hardware;
+    if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+        sensorConfig.sonar_hardware = FC.SENSOR_CONFIG.sonar_hardware;
+        sensorConfig.opticalflow_hardware = FC.SENSOR_CONFIG.opticalflow_hardware;
+    }

This keeps the UI and FC state in sync and avoids accidental clobbering.

Also applies to: 586-587, 840-848, 929-932


391-422: Add accessible column headers to the features table

The features table currently has only <tbody>/<tr>/<td> cells and no <th> headers, which is flagged by SonarCloud and harms accessibility for screen‑reader users.

Consider adding a visually hidden header row so layout stays unchanged but headers exist semantically, e.g.:

-            <table class="features-table">
-                <tbody>
+            <table class="features-table">
+                <thead class="visually-hidden">
+                    <tr>
+                        <th scope="col">{{ $t("configurationFeatureEnabled") }}</th>
+                        <th scope="col">{{ $t("configurationFeatureName") }}</th>
+                        <th scope="col">{{ $t("configurationFeatureDescription") }}</th>
+                        <th scope="col">{{ $t("configurationFeatureHelp") }}</th>
+                    </tr>
+                </thead>
+                <tbody>

and define a .visually-hidden utility class in CSS if not already present.


442-469: Add semantic <th> headers to DShot beacon conditions table

The DShot beacon conditions table has an empty <thead> with no <th> elements, so it still fails accessibility checks and gives no column labels to assistive technologies.

You can mirror the features‑table pattern and add headers matching the three columns:

-            <table class="dshot-beacon-table">
-                <thead>
-                    <tr>
-                        <!-- Header removed as no legacy key exists for 'Beacon Activation Conditions' -->
-                    </tr>
-                </thead>
+            <table class="dshot-beacon-table">
+                <thead class="visually-hidden">
+                    <tr>
+                        <th scope="col">{{ $t("configurationEnabled") }}</th>
+                        <th scope="col">{{ $t("configurationCondition") }}</th>
+                        <th scope="col">{{ $t("configurationDescription") }}</th>
+                    </tr>
+                </thead>

Reusing the same .visually-hidden helper keeps the visual design while satisfying accessibility and SonarCloud.

🧹 Nitpick comments (2)
src/js/serial_backend.js (2)

62-71: Reboot auto‑reconnect path ignores autoConnect / tab guards

The OR branch Date.now() - rebootTimestamp <= REBOOT_CONNECT_MAX_TIME_MS bypasses PortHandler.portPicker.autoConnect, GUI.active_tab and isCliOnlyMode() checks, so within the reboot window any port-handler:auto-select-serial-device event will call connectDisconnect() even if auto‑connect is disabled or the user is on CLI/firmware_flasher. That also conflicts a bit with showRebootDialog()’s noSerialReconnect logic, which assumes no auto‑reconnect when autoConnect is false.

Consider folding the reboot window into the guarded branch instead of as a separate OR (or at least gating it on autoConnect) so reboot reconnect behavior stays consistent with the user’s auto‑connect setting and active tab.


788-820: Harden Bluetooth port detection and virtual‑mode reboot UX

Two small points here:

  1. const currentPort = PortHandler.portPicker.selectedPort; is later used as currentPort.startsWith("bluetooth"). Elsewhere (connectDisconnect) you treat selectedPort as either a string or an object with a .path (hence the optional chaining). To avoid a possible TypeError if some protocols set selectedPort to an object, it would be safer to guard the check, e.g.:
-    if (currentPort.startsWith("bluetooth")) {
+    if (typeof currentPort === "string" && currentPort.startsWith("bluetooth")) {
  1. For CONFIGURATOR.virtualMode === true and !PortHandler.portPicker.autoConnect, the function runs the full reboot dialog flow even though there is no real reboot. If that’s not intentional, you may want an early return after connectDisconnect() in the virtual‑mode branch as well.

The new CONFIGURATOR.connectionValid = false; and GUI.reinitializeConnection = reinitializeConnection; wiring look good and align with the new reboot dialog behavior.

Also applies to: 919-920

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0024d96 and 6aaa3a6.

📒 Files selected for processing (6)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/js/main.js (3 hunks)
  • src/js/msp/MSPHelper.js (2 hunks)
  • src/js/serial_backend.js (4 hunks)
  • src/js/vue_components.js (2 hunks)
  • src/js/vue_tab_mounter.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/js/vue_tab_mounter.js
  • src/js/main.js
  • src/js/msp/MSPHelper.js
  • src/js/vue_components.js
🧰 Additional context used
🧠 Learnings (20)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
📚 Learning: 2025-10-25T21:16:32.474Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4379
File: src/js/protocols/TauriSerial.js:203-259
Timestamp: 2025-10-25T21:16:32.474Z
Learning: In TauriSerial (src/js/protocols/TauriSerial.js), the requestPermissionDevice() method is not needed and not invoked. Tauri automatically discovers serial devices through the constructor's loadDevices() and startDeviceMonitoring() calls, bypassing the browser permission model that WebSerial requires. Devices are auto-detected via a 1-second polling interval without user permission prompts.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-06-19T22:13:09.136Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4521
File: src/js/protocols/WebSerial.js:148-151
Timestamp: 2025-06-19T22:13:09.136Z
Learning: In WebSerial.js, there's a timing issue where the cached `this.ports` array doesn't immediately reflect newly permitted devices after `requestPermissionDevice()` completes. The `getDevices()` method needs to refresh the device list from the browser API to return accurate data immediately following a permission request and user acceptance.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-11-28T22:41:59.374Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4714
File: src/js/protocols/CapacitorBluetooth.js:135-143
Timestamp: 2025-11-28T22:41:59.374Z
Learning: In betaflight-configurator, WebSerial.js uses a constant path "serial" for all devices, and CapacitorBluetooth.js uses constant path "bluetooth", consistent with the single-device-at-a-time workflow. WebBluetooth.js uses counter-based paths (bluetooth_${counter}), but that's specific to its implementation. The path strategy varies by protocol based on their specific requirements.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-27T19:36:13.733Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/tabs/pid_tuning.js:80-82
Timestamp: 2025-08-27T19:36:13.733Z
Learning: MSP_STATUS_EX calls in serial_backend.js and setup.js are intentionally unguarded because they are used for status fetching on page load to initialize profiles and are safe to call on older firmware versions. Only conditional/optional MSP_STATUS_EX usage (like in pid_tuning.js) needs version gating to API_VERSION_25_12.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-22T16:43:20.901Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4576
File: src/js/port_usage.js:17-23
Timestamp: 2025-08-22T16:43:20.901Z
Learning: In betaflight-configurator, the serial facade architecture requires accessing metrics like bitrate, bytesReceived, and bytesSent from serial._protocol rather than the top-level serial object. This change maintains compatibility with existing port utilization calculations that have been stable for over 11 years.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-12-01T17:38:41.581Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:38:41.581Z
Learning: On BLE (Android) Save & Reboot, status pull intervals continue during MSP_EEPROM_WRITE, overwhelming the MSP queue and causing the EEPROM ack to time out so reinitializeConnection never runs. Solution: before EEPROM write, call GUI.interval_kill_all() and MSP.callbacks_cleanup(), and add a 3s fallback to proceed to reboot if the ack is missed.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🧬 Code graph analysis (1)
src/js/serial_backend.js (3)
src/js/gui.js (1)
  • GUI (473-473)
src/js/port_handler.js (1)
  • PortHandler (16-50)
src/js/data_storage.js (1)
  • CONFIGURATOR (8-39)
🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 666-666: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 611-611: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[failure] 643-643: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727


[failure] 660-660: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727


[failure] 820-820: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[failure] 606-606: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727


[failure] 619-619: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727


[warning] 391-391: Add "" headers to this "

".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdg&open=AZrw8w-eZYszuChvcCdg&pullRequest=4727


[failure] 601-601: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[failure] 637-637: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[warning] 442-442: Add "

" headers to this "".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZr6qGM3VcdC4SjUxZEA&open=AZr6qGM3VcdC4SjUxZEA&pullRequest=4727


[failure] 624-624: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: deploy
🔇 Additional comments (1)
src/components/tabs/ConfigurationTab.vue (1)

512-528: Save chain and reboot wiring look solid

The overall load/save pipeline (MSP_* reads in loadConfig(), MSP_* SET calls plus mspHelper.writeConfiguration() and reinitializeConnection() in saveConfig()) is consistent with the legacy configuration.js behavior and correctly gates name handling on API_VERSION_1_45/1_46/1_47. Exposing everything via setup() and using mspHelper.crunch() for payload construction also keeps MSP handling centralized.

No issues here from a correctness perspective.

Also applies to: 882-988

- Convert Configuration tab to Vue component
- Rebase from master
- Fix 'Save and Reboot' modal race condition
- Fix localization key mismatches and restore legacy keys
- Improve accessibility for DShot beacon table
- Code cleanup and import fixes
@haslinghuis
Copy link
Member

Just merged servos PR - please rebase again

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/components/tabs/ConfigurationTab.vue (2)

538-542: “Other Sensors” card is never shown and sonar/optical flow fields are never initialized.

  • showOtherSensors is a plain ref(false) and is never updated, but the entire “Other Sensors” box is gated by v-if="showOtherSensors". Even when showMagDeclination, showRangefinder, or showOpticalFlow are set to true, the panel remains hidden.
  • sensorConfig only declares acc_hardware, baro_hardware, and mag_hardware, yet the template and saveConfig() read/write sensorConfig.sonar_hardware and sensorConfig.opticalflow_hardware. These properties are never initialized from FC.SENSOR_CONFIG, so the selects don’t reflect the current FC state before saving.

This means rangefinder/optical flow options both start from an undefined state and are effectively unreachable due to the showOtherSensors gate.

I suggest:

  • Extend sensorConfig and initialize from FC:
-        const sensorConfig = reactive({
-            acc_hardware: 0,
-            baro_hardware: 0,
-            mag_hardware: 0,
-        });
+        const sensorConfig = reactive({
+            acc_hardware: 0,
+            baro_hardware: 0,
+            mag_hardware: 0,
+            sonar_hardware: 0,
+            opticalflow_hardware: 0,
+        });
             sensorConfig.acc_hardware = FC.SENSOR_CONFIG.acc_hardware;
             sensorConfig.baro_hardware = FC.SENSOR_CONFIG.baro_hardware;
             sensorConfig.mag_hardware = FC.SENSOR_CONFIG.mag_hardware;
+            sensorConfig.sonar_hardware = FC.SENSOR_CONFIG.sonar_hardware;
+            sensorConfig.opticalflow_hardware = FC.SENSOR_CONFIG.opticalflow_hardware;
  • Make showOtherSensors a computed OR of the three feature flags, instead of a dead ref:
-        const showMagDeclination = ref(false);
-        const showRangefinder = ref(false);
-        const showOpticalFlow = ref(false);
+        const showMagDeclination = ref(false);
+        const showRangefinder = ref(false);
+        const showOpticalFlow = ref(false);
@@
-        const showOtherSensors = ref(false);
+        const showOtherSensors = computed(
+            () => showMagDeclination.value || showRangefinder.value || showOpticalFlow.value,
+        );

This matches the intended behavior from the legacy tab where the “Other Sensors” card is shown whenever at least one of mag declination, rangefinder, or optical flow is available.

Also applies to: 581-586, 344-379, 840-848, 925-932


574-575: MAG alignment dropdown is permanently hidden; align it with legacy version gating.

showMagAlign is initialized to false and never updated, so the MAG alignment <select> guarded by v-if="showMagAlign" never appears, even when a magnetometer is present. Based on the legacy configuration.js behavior and learnings, MAG alignment should be:

  • Hidden for API versions below 1.47.
  • Shown when a mag sensor is present for API ≥ 1.47. (Per learnings, .mag_align_box hiding is only intentional for older APIs.)

You can fix this in initializeUI():

             // Mag Declination
             if (have_sensor(FC.CONFIG.activeSensors, "mag") && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
                 showMagDeclination.value = true;
                 magDeclination.value = FC.COMPASS_CONFIG.mag_declination;
             } else {
                 showMagDeclination.value = false;
             }
+
+            // MAG alignment (API >= 1.47 only)
+            if (have_sensor(FC.CONFIG.activeSensors, "mag") && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+                showMagAlign.value = true;
+            } else {
+                showMagAlign.value = false;
+            }

This keeps the MAG alignment UI hidden on older APIs while restoring it where it should be available.

Also applies to: 581-585, 330-338, 832-838

🧹 Nitpick comments (4)
src/js/serial_backend.js (1)

38-41: Clean up redundant connectionTimestamp check and unused constant.

connectionTimestamp === null || connectionTimestamp > 0 is always true given current assignments (null or Date.now()), so it doesn’t gate auto‑connect at all, and REBOOT_GRACE_PERIOD_MS is now unused. Consider either wiring these into real grace‑period logic or removing them to avoid confusion.

Also applies to: 62-71

src/js/main.js (1)

16-17: Tab switch cleanup for Vue tabs is correct and safe.

Calling unmountVueTab() before clearing #content ensures Vue tab instances are properly destroyed when switching to non‑Vue tabs, and routing "configuration" through mountVueTab("configuration", ...) aligns it with the other Vue‑based tabs. The extra unmount inside mountVueTab is redundant but harmless.

Also applies to: 211-215, 227-263, 288-290

src/components/tabs/ConfigurationTab.vue (2)

600-678: Add braces around short if statements to satisfy Sonar and reduce risk.

Helpers like isFeatureEnabled, toggleFeature, isBeeperEnabled, toggleBeeper, isDshotConditionEnabled, and toggleDshotCondition all use one-line if statements without braces, which is exactly what SonarCloud is flagging (“Expected { after 'if' condition”). While functionally correct, this pattern is brittle.

Consider updating them, e.g.:

-        const isFeatureEnabled = (feature) => {
-            if (!FC.FEATURE_CONFIG?.features) return false;
-            return bit_check(FC.FEATURE_CONFIG.features._featureMask, feature.bit);
-        };
+        const isFeatureEnabled = (feature) => {
+            if (!FC.FEATURE_CONFIG?.features) {
+                return false;
+            }
+            return bit_check(FC.FEATURE_CONFIG.features._featureMask, feature.bit);
+        };

Apply the same style to the other guards (if (!FC.FEATURE_CONFIG?.features) return;, if (!FC.BEEPER_CONFIG?.beepers) return false;, etc.) so they’re consistent and clear.


512-519: Consider using GUI.reinitializeConnection instead of importing from serial_backend.

Now that serial_backend.js assigns GUI.reinitializeConnection = reinitializeConnection, the component could call GUI.reinitializeConnection() directly instead of importing reinitializeConnection from "../../js/serial_backend". That would:

  • Reduce direct coupling between the Vue tab and the serial backend module.
  • Centralize the reboot entry point on the GUI facade, consistent with the change already made in MSPHelper.

This is purely structural; current behavior is correct either way.

Also applies to: 978-983

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 491a0fd and 4a4a56a.

📒 Files selected for processing (6)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/js/main.js (3 hunks)
  • src/js/msp/MSPHelper.js (2 hunks)
  • src/js/serial_backend.js (4 hunks)
  • src/js/vue_components.js (2 hunks)
  • src/js/vue_tab_mounter.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/js/vue_tab_mounter.js
  • src/js/msp/MSPHelper.js
🧰 Additional context used
🧠 Learnings (21)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
📚 Learning: 2025-09-10T18:26:10.136Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.

Applied to files:

  • src/js/vue_components.js
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/js/vue_components.js
  • src/js/main.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/js/vue_components.js
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-10-25T21:16:32.474Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4379
File: src/js/protocols/TauriSerial.js:203-259
Timestamp: 2025-10-25T21:16:32.474Z
Learning: In TauriSerial (src/js/protocols/TauriSerial.js), the requestPermissionDevice() method is not needed and not invoked. Tauri automatically discovers serial devices through the constructor's loadDevices() and startDeviceMonitoring() calls, bypassing the browser permission model that WebSerial requires. Devices are auto-detected via a 1-second polling interval without user permission prompts.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-27T19:36:13.733Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/tabs/pid_tuning.js:80-82
Timestamp: 2025-08-27T19:36:13.733Z
Learning: MSP_STATUS_EX calls in serial_backend.js and setup.js are intentionally unguarded because they are used for status fetching on page load to initialize profiles and are safe to call on older firmware versions. Only conditional/optional MSP_STATUS_EX usage (like in pid_tuning.js) needs version gating to API_VERSION_25_12.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-11-28T22:41:59.374Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4714
File: src/js/protocols/CapacitorBluetooth.js:135-143
Timestamp: 2025-11-28T22:41:59.374Z
Learning: In betaflight-configurator, WebSerial.js uses a constant path "serial" for all devices, and CapacitorBluetooth.js uses constant path "bluetooth", consistent with the single-device-at-a-time workflow. WebBluetooth.js uses counter-based paths (bluetooth_${counter}), but that's specific to its implementation. The path strategy varies by protocol based on their specific requirements.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-08-22T16:43:20.901Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4576
File: src/js/port_usage.js:17-23
Timestamp: 2025-08-22T16:43:20.901Z
Learning: In betaflight-configurator, the serial facade architecture requires accessing metrics like bitrate, bytesReceived, and bytesSent from serial._protocol rather than the top-level serial object. This change maintains compatibility with existing port utilization calculations that have been stable for over 11 years.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-06-19T22:13:09.136Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4521
File: src/js/protocols/WebSerial.js:148-151
Timestamp: 2025-06-19T22:13:09.136Z
Learning: In WebSerial.js, there's a timing issue where the cached `this.ports` array doesn't immediately reflect newly permitted devices after `requestPermissionDevice()` completes. The `getDevices()` method needs to refresh the device list from the browser API to return accurate data immediately following a permission request and user acceptance.

Applied to files:

  • src/js/serial_backend.js
📚 Learning: 2025-12-01T17:38:41.581Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:38:41.581Z
Learning: On BLE (Android) Save & Reboot, status pull intervals continue during MSP_EEPROM_WRITE, overwhelming the MSP queue and causing the EEPROM ack to time out so reinitializeConnection never runs. Solution: before EEPROM write, call GUI.interval_kill_all() and MSP.callbacks_cleanup(), and add a 3s fallback to proceed to reboot if the ack is missed.

Applied to files:

  • src/js/serial_backend.js
🧬 Code graph analysis (3)
src/js/vue_components.js (2)
src/components/init.js (1)
  • app (60-64)
src/js/vue_loader.js (1)
  • app (42-42)
src/js/main.js (1)
src/js/vue_tab_mounter.js (2)
  • unmountVueTab (88-93)
  • mountVueTab (31-83)
src/js/serial_backend.js (3)
src/js/gui.js (1)
  • GUI (473-473)
src/js/port_handler.js (1)
  • PortHandler (16-50)
src/js/data_storage.js (1)
  • CONFIGURATOR (8-39)
🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 666-666: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 643-643: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727


[failure] 619-619: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727


[failure] 624-624: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727


[failure] 601-601: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[warning] 391-391: Add "" headers to this "

".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdg&open=AZrw8w-eZYszuChvcCdg&pullRequest=4727


[failure] 611-611: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[failure] 606-606: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727


[failure] 820-820: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[failure] 637-637: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[warning] 442-442: Add "

" headers to this "".

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZr6qGM3VcdC4SjUxZEA&open=AZr6qGM3VcdC4SjUxZEA&pullRequest=4727


[failure] 660-660: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: deploy
🔇 Additional comments (2)
src/js/serial_backend.js (1)

577-606: Reboot reconnection flow and GUI export look consistent.

Resetting CONFIGURATOR.connectionValid to false before showing the reboot dialog, using a reboot timestamp window for reconnect attempts, clearing rebootTimestamp in finishOpen, and exposing GUI.reinitializeConnection together form a coherent Save‑&‑Reboot path that should behave well across protocols. I don’t see functional issues in this flow.

Also applies to: 788-819, 919-920

src/js/vue_components.js (1)

11-20: Configuration tab registration matches existing Vue tab pattern.

Importing ConfigurationTab and wiring it into both VueTabComponents and the global component registry is consistent with the other tabs and should make mountVueTab("configuration", ...) work as intended.

Also applies to: 31-37

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/components/tabs/ConfigurationTab.vue (1)

430-431: Add missing locale keys for "Other Sensors" section.

The template references configurationOtherFeatures (line 430) and configurationOtherFeaturesHelp (line 431), but these keys need to be added to locales/en/messages.json.

Add the following entries to locales/en/messages.json:

"configurationOtherFeatures": {
    "message": "Other Sensors"
},
"configurationOtherFeaturesHelp": {
    "message": "Configure additional sensors like rangefinder and optical flow."
}

Based on maintainer feedback in past review comments.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b46d212 and 76812cf.

📒 Files selected for processing (2)
  • locales/en/messages.json (4 hunks)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • locales/en/messages.json
🧰 Additional context used
🧠 Learnings (19)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:08:55.679Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-02T07:45:48.606Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: deploy
🔇 Additional comments (2)
src/components/tabs/ConfigurationTab.vue (2)

319-330: Use consistent conditional pattern.

The showGyroToUse logic is correct (showing for API < 1.47), but the <template v-if="showGyroToUse"> wrapper is inconsistent with the pattern used elsewhere in this component (lines 114, 173, 186, 333, 346, 360, etc.), where v-if is applied directly to the element when conditionally rendering a single block.

Apply this diff to match the established pattern:

-                                <div class="col-span-1">
-                                    <!-- GYRO ALIGNMENT -->
-                                    <div class="select" v-if="showGyroToUse">
+                                <div class="col-span-1" v-if="showGyroToUse">
+                                    <!-- GYRO ALIGNMENT -->
+                                    <div class="select">
                                         <select v-model.number="sensorAlignment.gyro_to_use">
                                             <option value="0">{{ $t("configurationSensorGyroToUseFirst") }}</option>
                                             <option value="1" v-if="hasSecondGyro">
                                                 {{ $t("configurationSensorGyroToUseSecond") }}
                                             </option>
                                             <option value="2" v-if="hasDualGyros">
                                                 {{ $t("configurationSensorGyroToUseBoth") }}
                                             </option>
                                         </select>
                                         <span>{{ $t("configurationSensorGyroToUse") }}</span>
                                     </div>
                                 </div>
-                                <div class="col-span-1">
+                                <div class="col-span-1" v-if="!showGyroToUse">

Wait, that's not quite right. Let me re-examine the structure. Lines 316-331 are:

  • Line 316: <div class="grid-row col2">
  • Line 317: <div class="col-span-1"> (first column)
  • Line 319: <div class="select" v-if="showGyroToUse"> (gyro_to_use dropdown)
  • Line 330: </div> (close col-span-1)
  • Line 332: <div class="col-span-1"> (second column with gyro1/gyro2/mag alignments)

Actually, looking more carefully, the col-span-1 contains only the gyro_to_use select when showGyroToUse is true, otherwise it's empty. So moving v-if to the parent div makes sense.

Actually, wait - I need to look at the actual structure more carefully. Let me trace through lines 316-423:

  • 316: <div class="grid-row col2"> - start 2-column grid
  • 317-331: <div class="col-span-1"> - LEFT column
    • 319-329: gyro_to_use select with v-if="showGyroToUse"
  • 332-422: <div class="col-span-1"> - RIGHT column
    • 333-344: gyro_1_align select with v-if="showGyro1Align"
    • 346-357: gyro_2_align select with v-if="showGyro2Align"
    • 360-421: mag alignment section with v-if="showMagAlign"
  • 423: </div> close grid-row

So the LEFT column contains only the gyro_to_use selector, and the RIGHT column contains gyro1/gyro2/mag alignment dropdowns.

The pattern inconsistency is that line 319 uses <div class="select" v-if="showGyroToUse"> which is fine, but it's the ONLY child of the col-span-1 div. Other similar cases in the file put v-if directly on the element.

Actually, I think the current code is fine. The issue mentioned in past comments was about which has been removed. The current code has

which is consistent with the pattern.

Let me re-check... yes, the past comment said to change to

, and that's already been done. So this is resolved.

[actions]
No comment needed - already resolved.

[scratchpad_end] -->

⛔ Skipped due to learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

333-356: Add "Default" option to gyro alignment dropdowns if value 0 is supported.

If FC.SENSOR_ALIGNMENT.gyro_1_align or gyro_2_align can be set to 0 (representing default/board alignment), the gyro dropdowns should include a "Default" option at value 0, matching the pattern used in the mag alignment dropdown. Currently, these dropdowns start at value 1, which would cause misalignment between the stored value (0) and the displayed selection if this case occurs.

…t for Gyro 1 and Gyro 2, and remove the gyro sync denom UI.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
locales/en/messages.json (3)

1417-1419: Add a short description for the new configurationFeatureHelp key (Crowdin context).
This is a generic label (“Help”) and may get reused; adding context helps translators later.

 "configurationFeatureHelp": {
-    "message": "Help"
+    "message": "Help",
+    "description": "Column header / label for help text in the Configuration tab features table"
 },

1543-1566: Avoid duplicating “Roll/Pitch/Yaw Degrees” strings; reference the existing board-alignment labels.
Right now these new gyro1/gyro2 keys duplicate the same English literal 6 times; using $t(...) keeps them consistent and reduces translator surface.

 "configurationGyro1AlignmentRoll": {
-    "message": "Roll Degrees",
+    "message": "$t(configurationBoardAlignmentRoll.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro1AlignmentPitch": {
-    "message": "Pitch Degrees",
+    "message": "$t(configurationBoardAlignmentPitch.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro1AlignmentYaw": {
-    "message": "Yaw Degrees",
+    "message": "$t(configurationBoardAlignmentYaw.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro2AlignmentRoll": {
-    "message": "Roll Degrees",
+    "message": "$t(configurationBoardAlignmentRoll.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro2AlignmentPitch": {
-    "message": "Pitch Degrees",
+    "message": "$t(configurationBoardAlignmentPitch.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro2AlignmentYaw": {
-    "message": "Yaw Degrees",
+    "message": "$t(configurationBoardAlignmentYaw.message)",
     "description": "Don't translate!!!"
 },

1603-1606: Consider adding description for configurationSensorAlignmentCustom (UI option label).
Small translation-context win.

 "configurationSensorAlignmentCustom": {
-    "message": "Custom"
+    "message": "Custom",
+    "description": "Dropdown option label for selecting a custom sensor alignment"
 },
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 76812cf and cd5ccd0.

📒 Files selected for processing (4)
  • locales/en/messages.json (5 hunks)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/css/tabs/configuration.less (1 hunks)
  • src/js/fc.js (1 hunks)
🧰 Additional context used
🧠 Learnings (19)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • src/css/tabs/configuration.less
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • locales/en/messages.json
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • locales/en/messages.json
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • locales/en/messages.json
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • locales/en/messages.json
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • src/css/tabs/configuration.less
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:08:55.679Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-02T07:45:48.606Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • locales/en/messages.json
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • locales/en/messages.json
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
  • locales/en/messages.json
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🔇 Additional comments (4)
src/css/tabs/configuration.less (1)

28-36: LGTM - Clean vertical alignment improvements.

The flexbox-based vertical centering and gap spacing improve the sensor alignment UI layout. These changes are consistent with modern CSS practices and the broader Vue 3 migration.

src/js/fc.js (1)

484-489: Remove undefined custom gyro alignment fields or implement complete MSP protocol support.

The six new custom alignment fields (gyro_1_align_roll, gyro_1_align_pitch, gyro_1_align_yaw, gyro_2_align_roll, gyro_2_align_pitch, gyro_2_align_yaw) have critical issues:

  1. No MSP serialization: These fields are not included in the MSP_SENSOR_ALIGNMENT protocol handlers (MSPHelper.js). For API < 1.47, only gyro_to_use, gyro_1_align, and gyro_2_align are serialized. For API >= 1.47, the protocol was redesigned to handle gyro_enable_mask and mag_align_* fields instead.

  2. Dead UI code: ConfigurationTab.vue displays custom alignment inputs (lines 349, 363, 377, 410, 424, 438) but these inputs are hidden for API >= 1.47 (showGyro1Align is explicitly set to false at line 1103). For API < 1.47, the custom alignment feature isn't supported by firmware.

  3. Data inconsistency: The fields are saved unconditionally in ConfigurationTab.vue (lines 1207-1212) but never persisted to firmware due to missing MSP support.

Either remove these fields and their UI bindings, or implement complete MSP protocol support including firmware serialization in both API version branches.

⛔ Skipped due to learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/tabs/pid_tuning.js:80-82
Timestamp: 2025-08-27T19:36:13.733Z
Learning: MSP_STATUS_EX calls in serial_backend.js and setup.js are intentionally unguarded because they are used for status fetching on page load to initialize profiles and are safe to call on older firmware versions. Only conditional/optional MSP_STATUS_EX usage (like in pid_tuning.js) needs version gating to API_VERSION_25_12.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.
locales/en/messages.json (2)

1450-1455: configurationOtherFeatures text change looks like it resolves the prior “Other Features” ambiguity.
Switching to “Other Sensors” aligns better with the section purpose and addresses the older duplicate-label concern.


1637-1639: configurationGyroCalOnFirstArmHelp copy looks good; consider keeping help-text style consistent (sentence casing/length).
No functional concerns—just ensure it matches other help strings’ tone/format in the same tab.

Comment on lines 1169 to 1170
FC.PID_ADVANCED_CONFIG.pid_process_denom = pidAdvancedConfig.pid_process_denom;
FC.PID_ADVANCED_CONFIG.pid_process_denom = pidAdvancedConfig.pid_process_denom;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove duplicate assignment.

Line 1170 duplicates the assignment from line 1169, which is a copy/paste error.

Apply this diff:

                 FC.PID_ADVANCED_CONFIG.pid_process_denom = pidAdvancedConfig.pid_process_denom;
-                FC.PID_ADVANCED_CONFIG.pid_process_denom = pidAdvancedConfig.pid_process_denom;

                 FC.SENSOR_CONFIG.acc_hardware = sensorConfig.acc_hardware;
🤖 Prompt for AI Agents
In src/components/tabs/ConfigurationTab.vue around lines 1169 to 1170, there is
a duplicate assignment of FC.PID_ADVANCED_CONFIG.pid_process_denom =
pidAdvancedConfig.pid_process_denom on line 1170; remove the redundant second
assignment so the property is only set once.

Comment on lines 783 to 787
return (
(semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_47) &&
(showGyroToUse.value || showGyro1Align.value || showGyro2Align.value)) ||
showMagAlign.value
);
Copy link
Member

Choose a reason for hiding this comment

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

showMagAlign.value would never be true - as it needs to be checked against semver.gte 1.47

…andling from Configuration tab, and fix duplicate PID setting.
@github-actions
Copy link
Contributor

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
src/components/tabs/ConfigurationTab.vue (1)

327-358: Gyro “Custom” option has no custom roll/pitch/yaw inputs (regression vs earlier review).
The gyro alignment selects include “Custom” (value 9), but there’s no way to enter the custom R/P/Y values for gyro1/gyro2. This breaks the feature. This is the same class of issue previously flagged on older commits.

At minimum, mirror the mag alignment “Custom” block for gyro1 and gyro2, and add/initialize/persist the corresponding reactive fields (names should match whatever FC.SENSOR_ALIGNMENT expects for gyro custom alignment).

Also applies to: 658-666, 970-1001, 1097-1106

🧹 Nitpick comments (3)
src/components/tabs/ConfigurationTab.vue (3)

911-1027: initializeUI() is doing too much; split by concern to avoid future bugs (Sonar complexity).
This function already tripped cognitive-complexity limits; it’s also where version-gating and state initialization can subtly break (e.g., the auto_disarm_delay issue).

Suggested splits: initNames(), initArming(), initAlignment(), initSensorHardware(), initBeepersAndFeatures(), initOtherSensors().


859-909: Consider cancellation/guarding async loadConfig() when leaving the tab.
If a user switches tabs mid-load, the MSP chain can still resolve and call initializeUI() / GUI.switchery() after unmount, which tends to create hard-to-debug UI artifacts.

Typical pattern: let cancelled = false; onUnmounted(() => { cancelled = true; }); and early-return before mutating UI.

Also applies to: 1173-1181


1060-1171: Prevent double-save / concurrent writes.
The Save button stays enabled and saveConfig() doesn’t guard against reentry; double-clicks can queue multiple MSP writes + writeConfiguration() calls.

Add an isSaving ref, disable the button while saving, and early-return if already saving.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd5ccd0 and aa2c8b3.

📒 Files selected for processing (2)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/js/fc.js (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/js/fc.js
🧰 Additional context used
🧠 Learnings (19)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:08:55.679Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-02T07:45:48.606Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
🪛 GitHub Check: SonarCloud Code Analysis
src/components/tabs/ConfigurationTab.vue

[failure] 711-711: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdh&open=AZrw8w-eZYszuChvcCdh&pullRequest=4727


[failure] 741-741: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdl&open=AZrw8w-eZYszuChvcCdl&pullRequest=4727


[failure] 812-812: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZsZQPp0qlf51wHR1tHb&open=AZsZQPp0qlf51wHR1tHb&pullRequest=4727


[failure] 772-772: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZsLQnxnsk1xgbiq8K-Y&open=AZsLQnxnsk1xgbiq8K-Y&pullRequest=4727


[failure] 736-736: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdk&open=AZrw8w-eZYszuChvcCdk&pullRequest=4727


[failure] 716-716: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdi&open=AZrw8w-eZYszuChvcCdi&pullRequest=4727


[failure] 802-802: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdp&open=AZrw8w-eZYszuChvcCdp&pullRequest=4727


[failure] 760-760: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdn&open=AZrw8w-eZYszuChvcCdn&pullRequest=4727


[failure] 911-911: Refactor this function to reduce its Cognitive Complexity from 20 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZsLQnxnsk1xgbiq8K-a&open=AZsLQnxnsk1xgbiq8K-a&pullRequest=4727


[failure] 985-985: Use Math.trunc instead of << 0.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdq&open=AZrw8w-eZYszuChvcCdq&pullRequest=4727


[failure] 822-822: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZsZQPp0qlf51wHR1tHc&open=AZsZQPp0qlf51wHR1tHc&pullRequest=4727


[failure] 730-730: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZsLQnxnsk1xgbiq8K-X&open=AZsLQnxnsk1xgbiq8K-X&pullRequest=4727


[failure] 721-721: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdj&open=AZrw8w-eZYszuChvcCdj&pullRequest=4727


[failure] 796-796: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdo&open=AZrw8w-eZYszuChvcCdo&pullRequest=4727


[failure] 754-754: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZrw8w-eZYszuChvcCdm&open=AZrw8w-eZYszuChvcCdm&pullRequest=4727


[failure] 784-784: Expected { after 'if' condition.

See more on https://sonarcloud.io/project/issues?id=betaflight_betaflight-configurator&issues=AZsLQnxnsk1xgbiq8K-Z&open=AZsLQnxnsk1xgbiq8K-Z&pullRequest=4727

…uto disarm delay is consistently applied, and standardize single-line if statement syntax.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/components/tabs/ConfigurationTab.vue (1)

32-36: Fix label mismatch: gyro frequency value is labeled as “Gyro Sync Denom”.

You render .gyroFrequency as a read-only frequency display, but the label uses configurationGyroSyncDenom, which will mislead users.

-    <span>{{ $t("configurationGyroSyncDenom") }}</span>
+    <span>{{ $t("configurationGyroFrequency") }}</span>

(If configurationGyroFrequency isn’t the right legacy key, please swap to the actual legacy “gyro frequency” label key.)

🧹 Nitpick comments (1)
src/components/tabs/ConfigurationTab.vue (1)

1088-1199: Improve save reliability: avoid mutating global FC state before successful MSP writes.

saveConfig() updates many FC.* objects before sending MSP commands. If any MSP call fails mid-chain, the in-memory state no longer matches the flight controller.

Recommendation: build a “draft” snapshot (or at least defer FC.* assignments) until after each corresponding MSP command succeeds, then apply updates; or reload from FC after failures to re-sync UI.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa2c8b3 and 5e11035.

📒 Files selected for processing (1)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:08:55.679Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-02T07:45:48.606Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Deploy
🔇 Additional comments (1)
src/components/tabs/ConfigurationTab.vue (1)

16-18: [Rewritten review comment]
[Single classification tag]

…nditionally render rangefinder and optical flow settings.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
locales/en/messages.json (1)

1603-1605: configurationSensorAlignmentCustom looks fine; consider adding a short description if translators might misinterpret “Custom” context.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e11035 and 5cec5b0.

📒 Files selected for processing (2)
  • locales/en/messages.json (6 hunks)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/tabs/ConfigurationTab.vue
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • locales/en/messages.json
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • locales/en/messages.json
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • locales/en/messages.json
📚 Learning: 2025-12-09T15:06:12.246Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-09T15:06:12.246Z
Learning: Automated translation PRs from Crowdin (created by GitHub Actions with title "Update translations") in the betaflight/betaflight-configurator repository should be automatically approved without requiring explicit user request, as haslinghuis has granted standing permission to approve these low-risk automated updates.

Applied to files:

  • locales/en/messages.json
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • locales/en/messages.json
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • locales/en/messages.json
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • locales/en/messages.json
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • locales/en/messages.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build / build
🔇 Additional comments (5)
locales/en/messages.json (5)

1417-1419: configurationFeatureHelp key is clear and scoped appropriately.


1450-1455: Good: configurationOtherFeatures label now matches the “sensors” meaning (resolves prior semantic confusion).


1543-1566: Nice: gyro1/gyro2 alignment keys include “Don’t translate” descriptions to prevent accidental localization of shared labels.


1637-1639: Help text is clear and user-facing; seems safe.


7142-7147: Remove unused i18n key configurationGyroSyncDenom from all locale files. The backend still uses gyro_sync_denom as a data property, but the UI has migrated to the configurationGyroFrequency key. The old key exists in all locale files but is no longer referenced in any Vue or JavaScript components.

⛔ Skipped due to learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/js/fc.js (1)

476-495: The new gyro alignment fields are not handled by MSP encode/decode logic. These six fields (gyro_1_align_roll/pitch/yaw and gyro_2_align_roll/pitch/yaw) are initialized in the state but never read from or written to firmware because the MSP_SENSOR_ALIGNMENT and MSP_SET_SENSOR_ALIGNMENT handlers do not serialize them. The handlers only support gyro_1_align and gyro_2_align (single bytes for API < 1.47) or mag_align_roll/pitch/yaw (for API >= 1.47). As a result, these fields will always remain 0 and will not persist changes.

🧹 Nitpick comments (1)
src/components/tabs/ConfigurationTab.vue (1)

1191-1305: saveConfig() mixes awaited MSP promises with callback-based EEPROM/reboot; consider awaiting the reboot/write outcome.

Right now, failures in mspHelper.writeConfiguration(...) aren’t part of the async flow, so the UI can log “Saved” and then silently fail later.

If writeConfiguration can’t be awaited directly, consider wrapping it:

+        const writeConfigurationAsync = () =>
+            new Promise((resolve) => {
+                mspHelper.writeConfiguration(false, resolve);
+            });

         // Save to EEPROM and Reboot
-        mspHelper.writeConfiguration(false, () => {
+        await writeConfigurationAsync();
+        {
             GUI.tab_switch_cleanup(() => {
                 GUI.reinitializeConnection();
             });
-        });
+        }

(Adjust if writeConfiguration provides error callbacks / status; the main point is keeping the save chain observable/awaitable.)

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cec5b0 and 79d2e30.

📒 Files selected for processing (2)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
  • src/js/fc.js (1 hunks)
🧰 Additional context used
🧠 Learnings (20)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-14T20:22:03.568Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-14T20:22:03.568Z
Learning: In betaflight-configurator's msp.js, the bluetooth CRC bypass check at line 266 uses serial.protocol === "bluetooth". When protocol names are unified to "ble", this check must be updated to serial.protocol === "ble".

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:08:55.679Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-02T07:45:48.606Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build / build
🔇 Additional comments (1)
src/components/tabs/ConfigurationTab.vue (1)

1256-1273: No action needed. The MSP_SET_SENSOR_ALIGNMENT transmission is properly version-gated through mspHelper.crunch(), which conditionally sends different payloads based on API version: for API 1.47+, it sends gyro_enable_mask and mag_align_* fields; for older versions, it sends gyro_to_use and gyro_1_align/gyro_2_align. The promise call itself is unconditional, but the actual MSP payload respects firmware version compatibility.

…dering and refine beeper row visibility logic.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/components/tabs/ConfigurationTab.vue (1)

708-708: Critical: Invalid semver package import.

Line 708 imports semver but package.json only declares semver-min as a dependency. This will fail at build/runtime with a module resolution error. The import should use the installed package:

-import semver from "semver";
+import semver from "semver-min";

Note: semver and semver-min may have different APIs, so verify all semver method calls are compatible with semver-min.

Based on past review comments.

🧹 Nitpick comments (1)
src/components/tabs/ConfigurationTab.vue (1)

17-17: Be careful with v-html + i18n content (XSS surface).

The template uses v-html with i18n keys at multiple locations. While this is likely an existing configurator pattern, ensure these specific keys (configurationFeaturesHelp, configurationLoopTimeHelp, feature* keys) contain only trusted, non-user-controlled HTML to prevent XSS vulnerabilities.

Also applies to: 30-30, 228-228, 231-231

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79d2e30 and dff3a81.

📒 Files selected for processing (1)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
🧰 Additional context used
🧠 Learnings (20)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-14T20:22:03.568Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-14T20:22:03.568Z
Learning: In betaflight-configurator's msp.js, the bluetooth CRC bypass check at line 266 uses serial.protocol === "bluetooth". When protocol names are unified to "ble", this check must be updated to serial.protocol === "ble".

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:08:55.679Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-02T07:45:48.606Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build / build

@haslinghuis
Copy link
Member

@Erics1337

mag align works again 👍

  • label is wrong
  • css

Picture would say more

image

…date localization keys, change semver import, and add configuration styles.
@github-actions
Copy link
Contributor

🎉 Do you want to test this code? 🎉

⚠️ CAUTION: The build may be unstable and result in corrupted configurations or data loss. Use only for testing! ⚠️

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
locales/en/messages.json (2)

1417-1419: Add a description for configurationFeatureHelp to guide translators/tools.
Other keys nearby often include description; adding one helps keep intent clear (esp. if this is a column header vs a tooltip label).

 "configurationFeatureHelp": {
-    "message": "Help"
+    "message": "Help",
+    "description": "Column header for feature help / details."
 },

1543-1566: Reduce duplication: reuse existing “Don’t translate” references instead of repeating literal strings.
These are identical to board alignment labels already present; referencing the existing keys reduces drift risk if wording ever changes.

 "configurationGyro1AlignmentRoll": {
-    "message": "Roll Degrees",
+    "message": "$t(configurationBoardAlignmentRoll.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro1AlignmentPitch": {
-    "message": "Pitch Degrees",
+    "message": "$t(configurationBoardAlignmentPitch.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro1AlignmentYaw": {
-    "message": "Yaw Degrees",
+    "message": "$t(configurationBoardAlignmentYaw.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro2AlignmentRoll": {
-    "message": "Roll Degrees",
+    "message": "$t(configurationBoardAlignmentRoll.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro2AlignmentPitch": {
-    "message": "Pitch Degrees",
+    "message": "$t(configurationBoardAlignmentPitch.message)",
     "description": "Don't translate!!!"
 },
 "configurationGyro2AlignmentYaw": {
-    "message": "Yaw Degrees",
+    "message": "$t(configurationBoardAlignmentYaw.message)",
     "description": "Don't translate!!!"
 },
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dff3a81 and 951c214.

📒 Files selected for processing (2)
  • locales/en/messages.json (6 hunks)
  • src/components/tabs/ConfigurationTab.vue (1 hunks)
🧰 Additional context used
🧠 Learnings (23)
📓 Common learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.
📚 Learning: 2025-09-15T15:19:47.087Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Applied to files:

  • locales/en/messages.json
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-26T11:37:09.758Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.

Applied to files:

  • locales/en/messages.json
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-11T19:10:56.992Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.

Applied to files:

  • locales/en/messages.json
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-20T20:26:40.338Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Applied to files:

  • locales/en/messages.json
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:41:44.286Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Applied to files:

  • locales/en/messages.json
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-19T20:42:20.332Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Applied to files:

  • locales/en/messages.json
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-27T22:06:49.210Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Applied to files:

  • locales/en/messages.json
  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-22T22:43:45.415Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-20T12:35:49.283Z
Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T13:43:10.231Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 4516
File: src/js/tabs/osd.js:3544-3559
Timestamp: 2025-06-14T13:43:10.231Z
Learning: In the Betaflight Configurator OSD positioning feature (src/js/tabs/osd.js), the elementWidth and elementHeight calculations use limits.maxX - limits.minX and limits.maxY - limits.minY without adding 1. While adding 1 would be mathematically correct for inclusive bounds, it causes visual centering issues where elements appear off-center. The current calculation produces better visual centering results, so the +1 correction should be avoided to maintain proper visual alignment.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-14T20:22:03.568Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-14T20:22:03.568Z
Learning: In betaflight-configurator's msp.js, the bluetooth CRC bypass check at line 266 uses serial.protocol === "bluetooth". When protocol names are unified to "ble", this check must be updated to serial.protocol === "ble".

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-14T20:43:11.565Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4727
File: src/components/tabs/ConfigurationTab.vue:697-710
Timestamp: 2025-12-14T20:43:11.565Z
Learning: In betaflight-configurator, the project consistently uses the import pattern 'import semver from "semver"' for semver, even though semver is not explicitly listed in package.json. This is a valid, project-wide pattern to follow across source files that import semver (e.g., in Vue components). Apply this import style consistently in Vue files and other JS/TS source files in the repository; ensure the semver package is available as a transitive dependency at build time and that this usage remains compatible with the project’s module resolution. If needed, verify that this import aligns with the bundler/tsconfig settings used in the repo.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-13T15:13:10.214Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:07:26.353Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-05-24T15:12:50.241Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-08-27T22:08:55.679Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-02T07:45:48.606Z
Learnt from: blckmn
Repo: betaflight/betaflight-configurator PR: 4583
File: src/js/tabs/firmware_flasher.js:949-961
Timestamp: 2025-09-02T07:45:48.606Z
Learning: In src/js/tabs/firmware_flasher.js, the config file loading code path after firmware loading (in the load_file click handler) cannot be reached when UF2 firmware is loaded, according to the maintainer blckmn. This code is maintained for backward compatibility with unified target settings and will be refactored in a future PR.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-12-01T17:09:13.412Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-12-01T17:09:13.412Z
Learning: In betaflight-configurator’s CapacitorBluetooth.js, native plugin listeners (notification, services, connectionState) must be attached exactly once per app lifetime. Re-attaching them during writes/connect cycles leads to duplicate handlers, increased JS workload, MSP queue pressure, and can prevent the MSP_EEPROM_WRITE callback from firing (so reinitializeConnection is not reached). Implement an idempotent _attachNativeListenersOnce() guard.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-11-24T15:07:25.227Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4706
File: src/js/protocols/CapacitorSerial.js:47-47
Timestamp: 2025-11-24T15:07:25.227Z
Learning: In betaflight-configurator's CapacitorSerial protocol (src/js/protocols/CapacitorSerial.js), the fire-and-forget this.loadDevices() call in the constructor is intentional background pre-loading. The actual critical device list loading for UI population is orchestrated by port_handler.js via serial.getDevices("serial"), which properly awaits CapacitorSerial.getDevices() → loadDevices() in a complete async chain. The constructor's async call does not cause race conditions.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-09T20:02:33.475Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4597
File: src/js/utils/common.js:95-127
Timestamp: 2025-09-09T20:02:33.475Z
Learning: In the Betaflight Configurator codebase, the Chromium v140 compatibility issue with sortSelect was resolved by rewriting the implementation to use native DOM APIs (Array.from, select.options, select.remove, select.add) instead of jQuery DOM manipulation methods (this.children, this.empty().append). The fix still performs DOM operations but avoids the specific jQuery methods that were causing issues in Chromium v140.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-09-10T18:26:10.136Z
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
📚 Learning: 2025-06-14T17:00:57.882Z
Learnt from: syahmizul
Repo: betaflight/betaflight-configurator PR: 0
File: :0-0
Timestamp: 2025-06-14T17:00:57.882Z
Learning: Static analysis tool errors (like Biome, ESLint, Ruff, etc.) are typically required fixes in pull requests, not optional suggestions. These are usually flagged as "Changes requested" and must be resolved before the PR can be merged.

Applied to files:

  • src/components/tabs/ConfigurationTab.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Deploy
🔇 Additional comments (5)
locales/en/messages.json (4)

1450-1455: Nice improvement: sensors section now has a dedicated label/help.
This looks like it resolves the earlier “Other Features” vs sensors labeling ambiguity cleanly.


1603-1606: configurationSensorAlignmentCustom: LGTM.
Consistent with existing “Default” option and reads well in UI.


1637-1639: configurationGyroCalOnFirstArmHelp: wording is clear and user-focused.
No concerns.


7142-7147: Remove the unused configurationGyroSyncDenom key entirely.

configurationGyroSyncDenom exists in all locale files but is never referenced in source code. Only configurationGyroFrequency is actively used in ConfigurationTab.vue. Delete configurationGyroSyncDenom from locales/en/messages.json; Crowdin will handle removal from translated locales via the normal sync process.

⛔ Skipped due to learnings
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4490
File: locales/en/messages.json:1534-1545
Timestamp: 2025-05-26T11:37:09.758Z
Learning: In the Betaflight Configurator repository, only English messages should be added directly to `locales/en/messages.json`; other language translations are handled via Crowdin automation and should not be manually updated in PRs.
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4567
File: locales/en/messages.json:7724-7728
Timestamp: 2025-08-11T19:10:56.992Z
Learning: In the Betaflight Configurator project, only English language entries are added directly to locales/en/messages.json. Translations for other languages are handled through an outsourced process and should not be suggested as part of code reviews.
src/components/tabs/ConfigurationTab.vue (1)

1-1383: LGTM! Well-structured Vue 3 Configuration tab implementation.

This is a comprehensive Vue 3 migration of the Configuration tab with proper:

  • Composition API usage with reactive state and computed properties
  • API version-aware conditional rendering for firmware compatibility
  • Complete MSP command chain for loading and saving configuration
  • Accessibility features (table headers, ARIA labels)
  • Error handling and user feedback

The component correctly handles the complex configuration UI including system settings, personalization, board/sensor alignment, features, beepers, and hardware detection across different API versions.

import { i18n } from "../../js/localization";
import { sensorTypes } from "../../js/sensor_types"; // Import for dropdown lists
import { have_sensor } from "../../js/sensor_helpers";
import semver from "semver-min";
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 14, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Update semver import to match project pattern.

The import uses "semver-min" but per maintainer feedback and established codebase patterns, the project consistently uses import semver from "semver" throughout (20+ files). The semver package is available as a transitive dependency.

Based on learnings and maintainer clarification.

Apply this diff:

-import semver from "semver-min";
+import semver from "semver";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import semver from "semver-min";
import semver from "semver";
🤖 Prompt for AI Agents
In src/components/tabs/ConfigurationTab.vue around line 708, the file imports
semver using "semver-min" which is inconsistent with the project convention;
change the import to use "semver" instead. Update the import statement to import
semver from "semver" and ensure no other references need adjustment; run a quick
search/compile to confirm the transitive dependency resolves correctly.

Copy link
Member

Choose a reason for hiding this comment

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

@Erics1337 see previous interaction with @coderabbitai - as suggestion was wrong.

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for semver imports in the codebase to determine the actual pattern
echo "=== Searching for 'import semver from \"semver\"' ==="
rg -n 'import semver from ["\x27]semver["\x27]' --type=js --type=vue

echo -e "\n=== Searching for 'import semver from \"semver-min\"' ==="
rg -n 'import semver from ["\x27]semver-min["\x27]' --type=js --type=vue

echo -e "\n=== Searching for any semver imports ==="
rg -n 'import.*semver' --type=js --type=vue | head -30

Length of output: 234


🏁 Script executed:

#!/bin/bash
# Search for semver imports without type restrictions
echo "=== Searching for 'import semver from \"semver\"' ==="
rg -n 'import semver from ["\x27]semver["\x27]' -g '*.js' -g '*.vue'

echo -e "\n=== Searching for 'import semver from \"semver-min\"' ==="
rg -n 'import semver from ["\x27]semver-min["\x27]' -g '*.js' -g '*.vue'

echo -e "\n=== All semver imports ==="
rg -n 'import.*semver' -g '*.js' -g '*.vue' | head -40

Length of output: 2846


🏁 Script executed:

#!/bin/bash
# Check the motors.js file to see if there's any context about why it uses semver-min
echo "=== Checking motors.js around the semver import ==="
sed -n '15,25p' src/js/tabs/motors.js

echo -e "\n=== Check if there are any comments or recent changes related to semver-min ==="
rg -B2 -A2 'semver-min' -g '*.js' -g '*.vue'

Length of output: 1296


@haslinghuis, I've searched the codebase and found:

Current usage patterns:

  • import semver from "semver" - used in 20+ files including:

    • src/js/fc.js, src/js/serial_backend.js, src/js/msp/MSPHelper.js
    • All tabs: setup.js, sensors.js, pid_tuning.js, receiver.js, failsafe.js, gps.js, led_strip.js, osd.js, onboard_logging.js, firmware_flasher.js
    • src/components/tabs/PortsTab.vue (another Vue tab)
    • And many more utilities and core files
  • import semver from "semver-min" - used in only 2 files:

    • src/components/tabs/ConfigurationTab.vue (this file)
    • src/js/tabs/motors.js

Regarding the learning:
There's a learning (from you, in this PR, timestamp 2025-12-14T20:43:11.565Z) that states: "import semver from 'semver' is the standard import pattern used throughout the codebase" and that it's "an established and accepted pattern in the project."

Could you clarify:

  1. Should ConfigurationTab.vue keep "semver-min" for a specific reason?
  2. Should I update the learning if "semver-min" is actually the correct pattern?
  3. Does motors.js also need to be addressed in a future change?

I want to ensure the documentation accurately reflects the project's conventions.


🧠 Learnings used
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4727
File: src/components/tabs/ConfigurationTab.vue:697-710
Timestamp: 2025-12-14T20:43:11.565Z
Learning: In betaflight-configurator, `import semver from "semver"` is the standard import pattern used throughout the codebase, even though semver is not explicitly listed in package.json. The semver package is available as a transitive dependency and this import works correctly in production. This is an established and accepted pattern in the project.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Copy link
Member

Choose a reason for hiding this comment

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

@coderabbitai import semver from "semver" is correct

Copy link
Contributor

Choose a reason for hiding this comment

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

@haslinghuis, thank you for confirming! Based on your confirmation and the codebase analysis:

Required change in this file:
The import on line 708 should be updated from:

import semver from "semver-min";

to:

import semver from "semver";

Additional finding:
During the search, I found that src/js/tabs/motors.js also uses import semver from "semver-min" and should likely be updated in a separate change to maintain consistency with the rest of the codebase (20+ files using the correct pattern).

The existing learning correctly documents this convention, so no update to the knowledge base is needed.


🧠 Learnings used
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4727
File: src/components/tabs/ConfigurationTab.vue:697-710
Timestamp: 2025-12-14T20:43:11.565Z
Learning: In betaflight-configurator, `import semver from "semver"` is the standard import pattern used throughout the codebase, even though semver is not explicitly listed in package.json. The semver package is available as a transitive dependency and this import works correctly in production. This is an established and accepted pattern in the project.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Copy link
Member

Choose a reason for hiding this comment

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

@coderabbitai - interesting - if min version works on motor tab, it should work on other tabs too - as tabs are being migrated to use Vue components now.

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check package.json for semver-related dependencies and aliases
echo "=== Checking package.json for semver dependencies ==="
cat package.json | jq '.dependencies, .devDependencies' | grep -i semver

echo -e "\n=== Check if semver-min is defined anywhere in package files ==="
rg -n 'semver-min' package.json package-lock.json 2>/dev/null | head -20

echo -e "\n=== Find all Vue component tabs ==="
fd -e vue -p 'src/components/tabs/'

echo -e "\n=== Check semver imports in all Vue tab components ==="
fd -e vue -p 'src/components/tabs/' --exec rg -n 'import.*semver' {}

echo -e "\n=== Check if there's a vite or webpack alias configuration ==="
rg -n 'semver' vite.config.js webpack.config.js 2>/dev/null

Length of output: 658


🏁 Script executed:

#!/bin/bash
# Check what ServosTab uses
echo "=== Check ServosTab.vue semver import ==="
rg -n 'import.*semver' src/components/tabs/ServosTab.vue

echo -e "\n=== Check motors.js (legacy tab) semver import ==="
rg -n 'import.*semver' src/js/tabs/motors.js

echo -e "\n=== Summary: All semver imports across Vue tabs ==="
for file in src/components/tabs/*.vue; do
    result=$(rg 'import.*semver' "$file" 2>/dev/null)
    if [ -n "$result" ]; then
        echo "File: $file"
        echo "$result"
        echo ""
    fi
done

Length of output: 332


@haslinghuis, you raise an excellent point! Here's what I found:

Current state across the codebase:

📦 Package dependency:

  • semver-min is explicitly listed in package.json as "semver-min": "^0.7.2"

Vue tabs (newly migrated):

  • ✅ ConfigurationTab.vue: import semver from "semver-min"
  • ❌ PortsTab.vue: import semver from "semver" (uses transitive dependency)
  • ⚪ ServosTab.vue: doesn't import semver

Legacy tabs:

  • ❌ motors.js: import semver from "semver-min"
  • ✅ 20+ other legacy tabs: import semver from "semver" (transitive dependency)

The pattern is currently inconsistent, even among Vue tabs. Since both work (one as explicit dependency, one as transitive), we should standardize.

Question for you:
Should we establish "semver-min" as the standard for Vue component tabs going forward (since it's already in package.json and motors.js uses it)? If so, I should:

  1. Keep ConfigurationTab.vue as-is with "semver-min"
  2. Update the existing learning to reflect that Vue tabs use "semver-min" while legacy tabs can use either
  3. Potentially update PortsTab.vue in a future change for consistency

Or would you prefer to keep "semver" as the standard and remove the semver-min dependency eventually?


🧠 Learnings used
Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4611
File: src/tabs/configuration.html:247-249
Timestamp: 2025-09-15T15:19:47.087Z
Learning: In the Betaflight Configurator's configuration.html, duplicate "not found" elements using the same i18n key (like configurationSensorGyroToUseNotFound) may be intentionally placed in different UI sections that are conditionally displayed based on firmware version. The old gyro alignment section (.gyro_alignment_inputs_notfound) is used for older firmware, while the new gyro enable section (.gyro_notfound) is used for firmware 1.47+.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4532
File: src/js/VirtualFC.js:234-234
Timestamp: 2025-06-27T22:06:49.210Z
Learning: In the betaflight-configurator codebase, the VirtualFC.js AUX_CONFIG array must stay synchronized with the betaflight firmware's msp_box.c definitions to ensure proper auxiliary mode functionality. Changes to mode names should follow the firmware source code even if it potentially breaks backward compatibility with saved presets.

Learnt from: mituritsyn
Repo: betaflight/betaflight-configurator PR: 4526
File: src/js/gui.js:43-43
Timestamp: 2025-06-20T12:35:49.283Z
Learning: In the Betaflight Configurator codebase, tabs in `defaultCloudBuildTabOptions` are conditionally displayed based on firmware build options. The logic in `serial_backend.js` checks `FC.CONFIG.buildOptions` and only adds tabs to `GUI.allowedTabs` if the firmware was built with support for that feature.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4708
File: locales/en/messages.json:7721-7729
Timestamp: 2025-11-20T20:26:40.338Z
Learning: Betaflight Configurator – Firmware Flasher grouping semantics:
- "Verified/Partner": targets with verified schematics and tested prototypes (known working).
- "Unsupported": vendor/community-supplied targets that did not go through the verification program.
- "Legacy": legacy targets kept for existing users.
These labels surface in src/js/tabs/firmware_flasher.js via i18n keys:
firmwareFlasherOptionLabelVerifiedPartner, firmwareFlasherOptionLabelVendorCommunity, firmwareFlasherOptionLabelLegacy. Only English text should be updated directly in locales/en/messages.json; other locales are managed externally.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4577
File: src/js/tabs/configuration.js:580-590
Timestamp: 2025-08-22T22:43:45.415Z
Learning: In src/js/tabs/configuration.js, hiding the entire .mag_align_box for API versions < 1.47 is intentional behavior because these MAG alignment options were not present or have changed significantly between API versions. The code has been reorganized for better maintenance.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:42:20.332Z
Learning: Complex MSP duplicate handling fixes in Betaflight Configurator can cause infinite loading messages when changing tabs due to disruption of the callback resolution mechanism. Simple code-only duplicate detection (using this.callbacks.some((instance) => instance.code === code)) is the safer approach that preserves tab switching functionality.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4485
File: src/js/sensor_types.js:96-99
Timestamp: 2025-05-24T15:12:50.241Z
Learning: In src/js/sensor_types.js, the sonar element selection UI is only displayed when firmware version >= API_VERSION_1_47, so sonar sensor types can be added directly to the static elements array without requiring additional version guards.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/data_storage.js:9-9
Timestamp: 2025-08-27T22:07:26.353Z
Learning: In the betaflight-configurator CalVer refactoring, the generateVirtualApiVersions function in src/js/utils/common.js works correctly despite the apparent mathematical issue with bounds logic where compareVersions.minor() returns different ranges for API_VERSION_MAX_SUPPORTED (25.12.0) vs API_VERSION_ACCEPTED (1.44.0).

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4727
File: src/components/tabs/ConfigurationTab.vue:697-710
Timestamp: 2025-12-14T20:43:11.565Z
Learning: In betaflight-configurator, `import semver from "semver"` is the standard import pattern used throughout the codebase, even though semver is not explicitly listed in package.json. The semver package is available as a transitive dependency and this import works correctly in production. This is an established and accepted pattern in the project.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4579
File: src/js/utils/compareVersions.js:3-17
Timestamp: 2025-08-27T22:08:55.679Z
Learning: In betaflight-configurator's compareVersions utility (src/js/utils/compareVersions.js), the behavior of treating non-numeric segments as NaN -> 0 is intentional by design, not a bug that needs fixing.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4510
File: src/js/msp.js:384-391
Timestamp: 2025-09-19T20:41:44.286Z
Learning: When fixing MSP duplicate handling in Betaflight Configurator, avoid complex changes to callback resolution mechanisms as they can break tab switching functionality. Simple duplicate detection based on code and payload size is safer than complex requestKey-based approaches.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4601
File: package.json:125-125
Timestamp: 2025-09-10T18:26:10.136Z
Learning: In betaflight-configurator, dependency updates are handled incrementally - Vue dependencies are updated separately from Vite dependencies for better isolation and maintainability.

Learnt from: haslinghuis
Repo: betaflight/betaflight-configurator PR: 4569
File: src/js/tabs/receiver.js:957-960
Timestamp: 2025-08-13T15:13:10.214Z
Learning: In src/js/tabs/receiver.js, the updateInterpolationView() function already contains logic to hide ".rcSmoothing-feedforward-cutoff" when FC.RX_CONFIG.rcSmoothingFeedforwardCutoff === 0, which handles the API ≥ 1.47 case since feedforward cutoff isn't initialized from DOM for newer APIs.

@sonarqubecloud
Copy link

@haslinghuis
Copy link
Member

Will test with a dual gyro board.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants