* feat(protobufs): sync to firmware-current and consume workspace package
Sync the vendored .proto sources to firmware-current (v2.7.25+48), regenerate the v2 TS bindings, and consume the workspace @meshtastic/protobufs (workspace:*) in place of the stale JSR 2.7.20 — finishing the monorepo migration (core was already workspace:*).
Includes the one required breaking-change fix: admin nodedb_reset changed int32 to bool, so resetNodes() now sends value: true.
* build(protobufs): vendor generated bindings for workspace consumers
The package is consumed via workspace:* — its exports point at the TS source, which imports ./dist/meshtastic/*_pb.ts — so the generated output must exist at build time. CI builds web/core with no codegen step and the runners have no buf CLI, so the bindings are vendored here (kept gitignored; lint/format skip them). Regenerate with: pnpm --filter @meshtastic/protobufs gen
* fix(protobufs): clean script removes the actual generated output dir
buf writes bindings to packages/ts/dist, but clean was removing a non-existent root dist — so it never cleaned stale output. Addresses Copilot review feedback.
* refactor: move web app packages/web -> apps/web
Aligns the web app with the apps/web layout (matching the Vercel web-test Root Directory and the SDK-migration direction). Pure directory move plus root config: pnpm-workspace (adds apps/*), vitest projects, root tsconfig reference, and the pr/release-web/nightly workflows. vercel.json moved with the app. Build + 36 validation tests green.
* feat: config fields, module pages, key verification, telemetry capture
Incorporates the firmware-current feature work onto the protobuf foundation: new config fields (Display message bubbles; LoRa fem_lna_mode + serial_hal_only; Telemetry air_quality_screen_enabled); 4 new ModuleConfig pages (TrafficManagement, StatusMessage, TAK, RemoteHardware); the manual Key Verification flow (sendKeyVerification + ClientNotificationDialog stages + Verify Key button); live telemetry capture (nodeDB addDeviceMetrics) and admin hardening (toggleMutedNode, graceful PortNum default); plus the sdk-preview ConfigEditor demo and store/config tests. Build + lint + format + 131 tests green.
* chore: drop #1062 (unsaved-change-detection) to match upstream revert
#1062 was merged to main by accident (per @danditomaso) and is being reverted. Reverse-applied its diff here via 3-way so #1097 stays consistent with where main is headed, while keeping the feature changes layered on the same files (deviceStore/changeRegistry). Build + 131 tests + lint + format green.
* fix(nodes): clean up SNR display in node table and map popup
SNR is a ratio measured in dB, not dBm (which is absolute power); the
node table and map popup both mislabeled it and crammed three values
together: '0dBm/50%/50raw'. The trailing '%/raw' pair was the same
heuristic ((snr+10)*5) shown twice — once clamped, once not.
Render SNR in dB rounded to one decimal, color-coded by a 0-100%
signal-quality heuristic (green/yellow/red), with the quality percentage
as a muted secondary. Drop the redundant raw value. Adds unit.db; this
matches the existing SNRTooltip, which already renders dB.
Add getRadioConfigChangeCount() and getDeviceConfigChangeCount() for individual setting sections. This resolves displaying the count of unsaved changes on the wrong sidebar item.
Add normalizeBytes and call it from the Security page so that unset Admin Keys do not trigger unsaved changes when updating the page.
The Position page uses useMemo which does not clear rhfState.isDirty. Remove the rhfState.isDirty from hasPending to address it.
* fix: use correct JSR specifier for @meshtastic/protobufs
Pin pnpm version in CI workflows, remove unused .npmrc, and fix the
protobufs dependency specifier to use the full JSR format.
* updating lock file
* debug fix
* tried removing and re-adding protobuf package
* updating pnpm version
* moar fixes
* add npmrc back
* update lock file
* feat(ui): add SNR, RSSI, hops, MQTT info for messages
* review fixes
* zeros for new fields
* Move label under the message
---------
Co-authored-by: Pmmlabs <meshtastic@pmmlabs.ru>
* chore: remove unused logo SVG files
* feat: add interactive fixed position picker with map interface
- Created new FixedPositionPicker component with clickable map for setting device coordinates
- Added form field type for fixed position picker that appears when fixedPosition toggle is enabled
- Implemented position request functionality to retrieve current device location
* feat: display altitude unit based on user's display settings
- Added dynamic altitude unit (Meters/Feet) that respects the user's imperial/metric display preference
- Updated altitude field description to show the appropriate unit instead of hardcoded "Meters"
* refactor: replace any type with MapLayerMouseEvent in map click handler
* refactor: improve accessibility and code quality in FixedPositionPicker
- Replace hardcoded IDs with useId() hook for proper accessibility
- Use Number.isNaN() instead of isNaN() for more reliable type checking
- Add radix parameter to parseInt() and remove unnecessary fragment wrapper
* refactor: simplify fixed position picker integration
- Removed dedicated FixedPositionPicker form field type in favor of toggle's additionalContent prop
- Moved FixedPositionPicker to render conditionally within toggle field instead of as separate dynamic field
- Streamlined form field types by eliminating FixedPositionPickerFieldProps
* style: format code with consistent line breaks and import ordering
* refactor: simplify fixed position picker container styling
* feat: disable fixed position toggle when GPS is enabled
* refactor: use ComponentRef instead of ElementRef in Switch component
* refactor: replace interactive map picker with inline coordinate fields for fixed position
- Removed FixedPositionPicker component with map interface
- Added latitude, longitude, and altitude fields directly to position form
- Moved coordinate validation into PositionValidationSchema with proper min/max bounds
- Updated translation strings to include coordinate ranges and improved altitude description
- Coordinates now sent via setFixedPosition admin message on form submit when fixedPosition is enabled
* refactor: simplify toggle field by removing additionalContent prop and unused field spreading
- Removed additionalContent prop and its JSDoc documentation from ToggleFieldProps
- Removed rendering of additionalContent below toggle switch
- Cleaned up Controller render function by removing unused rest spread operator
- Renamed field destructuring to controllerField for clarity
* refactor: improve fixed position handling and add position broadcast request
- Restructure onSubmit to save config before sending admin message
- Add position broadcast request after setting fixed position to immediately update display
- Add comprehensive debug logging throughout submission flow
- Extract coordinate exclusion logic earlier in submission process for clarity
- Add 1 second delay before requesting position broadcast to allow fixed position processing
* feat: add max length constraint to latitude and longitude fields
- Set fieldLength.max to 10 for both latitude and longitude inputs
- Prevents excessive decimal precision while maintaining 7 decimal places (±1.1cm accuracy)
Fixed typo 'languagePickeer' to 'languagePicker' in DeviceInfoPanel and corrected responsive width class from 'md:w-6' to 'md:w-5/6' in Connections page description.
This caused {{shortName}} and {{longName}} to appear unformatted in the
exported key files:
``` === MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===
Private Key: <censored>
Public Key: <censored>
=== END OF KEYS === ```
The fix simply replicates the behaviour used elsewhere in
PKIIBackupDialog.