178 Commits
Author SHA1 Message Date
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
011ede9966 chore(deps-dev): bump publint from 0.3.18 to 0.3.21 (#1112)
Bumps [publint](https://github.com/publint/publint/tree/HEAD/packages/publint) from 0.3.18 to 0.3.21.
- [Release notes](https://github.com/publint/publint/releases)
- [Changelog](https://github.com/publint/publint/blob/master/packages/publint/CHANGELOG.md)
- [Commits](https://github.com/publint/publint/commits/publint@0.3.21/packages/publint)

---
updated-dependencies:
- dependency-name: publint
  dependency-version: 0.3.21
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 16:54:11 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
eaf6f3d593 chore(deps-dev): bump tar from 7.5.11 to 7.5.16 (#1104)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.11 to 7.5.16.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.11...v7.5.16)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.16
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 16:38:08 -04:00
Ben MeadorsandGitHub 6b298d1648 fix(infra): use apps/web paths in Containerfile after monorepo move (#1110)
The Release Web workflow builds the Docker image with the repo root as
context (file: ./apps/web/infra/Containerfile), but the Containerfile's
ADD/COPY still referenced ./packages/web/dist and
./packages/web/infra/default.conf. After #1097 moved the web app to
apps/web, those paths no longer exist, so buildx failed with
'"/packages/web/infra/default.conf": not found'.

Point both at ./apps/web/. Verified with a local multi-stage docker
build against the apps/web build output.
2026-06-15 15:26:26 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f9e6d69ae6 chore(deps): bump @radix-ui/react-menubar from 1.1.16 to 1.1.17 (#1101)
Bumps [@radix-ui/react-menubar](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/menubar) from 1.1.16 to 1.1.17.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/menubar/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/menubar)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-menubar"
  dependency-version: 1.1.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 15:58:05 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7f48db7ddb chore(deps): bump @radix-ui/react-accordion from 1.2.12 to 1.2.13 (#1103)
Bumps [@radix-ui/react-accordion](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/accordion) from 1.2.12 to 1.2.13.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/accordion/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/accordion)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-accordion"
  dependency-version: 1.2.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 15:57:19 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b0ff5f50bf chore(deps): bump vite from 7.3.2 to 7.3.5 (#1105)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.3.2 to 7.3.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.5/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 15:25:17 -04:00
AustinandGitHub a0cda099e7 Dependabot: Group react packages together (#1106)
Same as we do in meshtastic/meshtastic
2026-06-15 13:55:43 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a9c52b8667 chore(deps): bump i18next from 25.8.17 to 26.3.1 (#1094)
Bumps [i18next](https://github.com/i18next/i18next) from 25.8.17 to 26.3.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v25.8.17...v26.3.1)

---
updated-dependencies:
- dependency-name: i18next
  dependency-version: 26.3.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 14:44:40 -04:00
Ben MeadorsandGitHub bbe9a0d5cd feat(protobufs): sync to firmware-current and consume workspace package (#1097)
* 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.
2026-06-15 13:23:28 -05:00
Dan DitomasoandGitHub 7a8529b841 Revert "fix(settings): fix unsaved change detection for non-admin-message con…" (#1100)
This reverts commit 87043f35cb.
2026-06-14 20:03:50 -04:00
fullburnenandGitHub 87043f35cb fix(settings): fix unsaved change detection for non-admin-message config items (#1062)
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.
2026-06-13 21:34:45 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
90f8219f8d chore(deps): bump react-hook-form from 7.71.2 to 7.78.0 (#1093)
Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.71.2 to 7.78.0.
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.71.2...v7.78.0)

---
updated-dependencies:
- dependency-name: react-hook-form
  dependency-version: 7.78.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-13 21:33:30 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0d08f872b9 chore(deps): bump @radix-ui/react-collapsible from 1.1.12 to 1.1.13 (#1092)
Bumps [@radix-ui/react-collapsible](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/collapsible) from 1.1.12 to 1.1.13.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/collapsible/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/collapsible)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-collapsible"
  dependency-version: 1.1.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-13 21:32:54 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a364c91f25 chore(deps): bump @bufbuild/protobuf from 2.11.0 to 2.12.0 (#1095)
Bumps [@bufbuild/protobuf](https://github.com/bufbuild/protobuf-es/tree/HEAD/packages/protobuf) from 2.11.0 to 2.12.0.
- [Release notes](https://github.com/bufbuild/protobuf-es/releases)
- [Commits](https://github.com/bufbuild/protobuf-es/commits/v2.12.0/packages/protobuf)

---
updated-dependencies:
- dependency-name: "@bufbuild/protobuf"
  dependency-version: 2.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-13 21:32:40 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ca0355c700 chore(deps): bump the tanstack group across 1 directory with 5 updates (#1084)
Bumps the tanstack group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@tanstack/react-router](https://github.com/TanStack/router/tree/HEAD/packages/react-router) | `1.166.7` | `1.170.15` |
| [@tanstack/react-router-devtools](https://github.com/TanStack/router/tree/HEAD/packages/react-router-devtools) | `1.166.7` | `1.167.0` |
| [@tanstack/router-cli](https://github.com/TanStack/router/tree/HEAD/packages/router-cli) | `1.166.7` | `1.167.17` |
| [@tanstack/router-devtools](https://github.com/TanStack/router/tree/HEAD/packages/router-devtools) | `1.166.7` | `1.167.0` |
| [@tanstack/router-plugin](https://github.com/TanStack/router/tree/HEAD/packages/router-plugin) | `1.166.7` | `1.168.18` |



Updates `@tanstack/react-router` from 1.166.7 to 1.170.15
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router@1.170.15/packages/react-router)

Updates `@tanstack/react-router-devtools` from 1.166.7 to 1.167.0
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router-devtools/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router-devtools@1.167.0/packages/react-router-devtools)

Updates `@tanstack/router-cli` from 1.166.7 to 1.167.17
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/router-cli/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/router-cli@1.167.17/packages/router-cli)

Updates `@tanstack/router-devtools` from 1.166.7 to 1.167.0
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/router-devtools/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/router-devtools@1.167.0/packages/router-devtools)

Updates `@tanstack/router-plugin` from 1.166.7 to 1.168.18
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/router-plugin/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/router-plugin@1.168.18/packages/router-plugin)

---
updated-dependencies:
- dependency-name: "@tanstack/react-router"
  dependency-version: 1.170.11
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: tanstack
- dependency-name: "@tanstack/react-router-devtools"
  dependency-version: 1.167.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: tanstack
- dependency-name: "@tanstack/router-cli"
  dependency-version: 1.167.13
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: tanstack
- dependency-name: "@tanstack/router-devtools"
  dependency-version: 1.167.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: tanstack
- dependency-name: "@tanstack/router-plugin"
  dependency-version: 1.168.14
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: tanstack
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 21:22:32 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4118887cda chore(deps): bump react-i18next from 16.5.6 to 17.0.8 (#1085)
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 16.5.6 to 17.0.8.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v16.5.6...v17.0.8)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-version: 17.0.8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 21:22:03 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3be19bb7a4 chore(deps): bump lucide-react from 0.545.0 to 1.17.0 (#1086)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.545.0 to 1.17.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.17.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 21:16:12 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fbbfac6e5c chore(deps): bump vite-plugin-pwa from 1.2.0 to 1.3.0 (#1087)
Bumps [vite-plugin-pwa](https://github.com/vite-pwa/vite-plugin-pwa) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/vite-pwa/vite-plugin-pwa/releases)
- [Commits](https://github.com/vite-pwa/vite-plugin-pwa/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: vite-plugin-pwa
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 21:15:37 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
bdee96fe97 chore(deps-dev): bump vite-plugin-static-copy from 3.2.0 to 4.1.1 (#1088)
Bumps [vite-plugin-static-copy](https://github.com/sapphi-red/vite-plugin-static-copy) from 3.2.0 to 4.1.1.
- [Release notes](https://github.com/sapphi-red/vite-plugin-static-copy/releases)
- [Changelog](https://github.com/sapphi-red/vite-plugin-static-copy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sapphi-red/vite-plugin-static-copy/compare/vite-plugin-static-copy@3.2.0...vite-plugin-static-copy@4.1.1)

---
updated-dependencies:
- dependency-name: vite-plugin-static-copy
  dependency-version: 4.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 21:09:49 -04:00
AustinandGitHub 70edffeeae JSR migrations for pnpm 11 (#1090)
JSR is now integrated into pnpm since version 10.9
Should fix issues resolving JSR dependencies during "pnpm test"
2026-06-12 12:51:48 -04:00
AustinandGitHub 569c990575 Correct typo in excluded directories list in CI workflow (#1089)
Should fix CI errors when merging to `main`
2026-06-12 12:27:51 -04:00
AustinandGitHub 20dbcf06c1 Update pnpm to v11 (#1080)
Also remove version references in Actions so that the packageManager version can be used
2026-06-12 11:22:15 -04:00
AustinandGitHub e0d4504bca Add group for @tanstack packages in dependabot configuration (#1083)
Force all @tanstack dependencies to update together.
2026-06-07 20:29:34 -04:00
AustinandGitHub 0060a01824 Revert "chore(deps): bump @tanstack/react-router-devtools (#1072)" (#1082)
This reverts commit af499556bb.
2026-06-07 20:29:09 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
dbf7f5b18d chore(deps): bump i18next-http-backend from 3.0.5 to 4.0.0 (#1069)
Bumps [i18next-http-backend](https://github.com/i18next/i18next-http-backend) from 3.0.5 to 4.0.0.
- [Changelog](https://github.com/i18next/i18next-http-backend/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-http-backend/compare/v3.0.5...v4.0.0)

---
updated-dependencies:
- dependency-name: i18next-http-backend
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 18:11:13 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
25e70512ce chore(deps): bump immer from 10.2.0 to 11.1.8 (#1070)
Bumps [immer](https://github.com/immerjs/immer) from 10.2.0 to 11.1.8.
- [Release notes](https://github.com/immerjs/immer/releases)
- [Commits](https://github.com/immerjs/immer/compare/v10.2.0...v11.1.8)

---
updated-dependencies:
- dependency-name: immer
  dependency-version: 11.1.8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 18:09:38 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
af499556bb chore(deps): bump @tanstack/react-router-devtools (#1072)
Bumps [@tanstack/react-router-devtools](https://github.com/TanStack/router/tree/HEAD/packages/react-router-devtools) from 1.166.7 to 1.167.0.
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router-devtools/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router-devtools@1.167.0/packages/react-router-devtools)

---
updated-dependencies:
- dependency-name: "@tanstack/react-router-devtools"
  dependency-version: 1.167.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 18:09:06 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
dc3da4c9d8 chore(deps-dev): bump vitest from 3.2.4 to 4.1.8 (#1073)
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 3.2.4 to 4.1.8.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 4.1.8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 18:08:40 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d492e1d4f2 chore(deps): bump docker/setup-buildx-action from 3 to 4 (#1079)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:58:31 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fa902e6fb8 chore(deps): bump pnpm/action-setup from 4 to 6 (#1075)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 4 to 6.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v4...v6)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:56:41 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d35ccdf7a6 chore(deps): bump docker/login-action from 3 to 4 (#1077)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:55:23 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
801e70f201 chore(deps): bump docker/metadata-action from 5 to 6 (#1078)
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:54:51 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
24ec09dd43 chore(deps): bump docker/setup-qemu-action from 3 to 4 (#1076)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:54:18 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
22d125a750 chore(deps): bump actions/checkout from 4 to 6 (#1074)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:53:20 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
28029ba17f chore(deps): bump softprops/action-gh-release from 2 to 3 (#1067)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:46:37 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
79f936c310 chore(deps): bump actions/setup-node from 4 to 6 (#1065)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:46:00 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8cd8b0bf01 chore(deps): bump actions/download-artifact from 4 to 8 (#1066)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 8.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v8)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:45:31 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d6172fd6dd chore(deps): bump docker/build-push-action from 6 to 7 (#1064)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:44:56 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
cd5cb28132 chore(deps): bump actions/upload-artifact from 4 to 7 (#1068)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 17:42:44 -04:00
AustinandGitHub 78f11dd0ee Initial dependabot config (#1063) 2026-06-07 17:39:24 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
379c8773dc chore(deps): bump js-cookie from 3.0.5 to 3.0.7 (#1058)
Bumps [js-cookie](https://github.com/js-cookie/js-cookie) from 3.0.5 to 3.0.7.
- [Release notes](https://github.com/js-cookie/js-cookie/releases)
- [Commits](https://github.com/js-cookie/js-cookie/compare/v3.0.5...v3.0.7)

---
updated-dependencies:
- dependency-name: js-cookie
  dependency-version: 3.0.7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-26 21:27:19 -04:00
NIKOLYA PRODIGYandGitHub 2f78b64dfd fix(nodes): correct singular hop label in connection status (#1055) 2026-05-26 21:26:20 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9a4820523f chore(deps): bump @babel/plugin-transform-modules-systemjs (#1056)
Bumps [@babel/plugin-transform-modules-systemjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-systemjs) from 7.29.0 to 7.29.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.4/packages/babel-plugin-transform-modules-systemjs)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-modules-systemjs"
  dependency-version: 7.29.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-26 21:24:31 -04:00
CopilotGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>garthvh
356b8a2331 Add .github/copilot-instructions.md with Meshtastic design standards (#1053)
Agent-Logs-Url: https://github.com/meshtastic/web/sessions/cf1d1394-bc72-4314-b0d5-03120457d4dc

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com>
2026-05-04 21:02:41 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
cf1ab96c93 chore(deps): bump i18next-http-backend from 3.0.2 to 3.0.5 (#1048)
Bumps [i18next-http-backend](https://github.com/i18next/i18next-http-backend) from 3.0.2 to 3.0.5.
- [Changelog](https://github.com/i18next/i18next-http-backend/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-http-backend/compare/v3.0.2...v3.0.5)

---
updated-dependencies:
- dependency-name: i18next-http-backend
  dependency-version: 3.0.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-25 20:52:53 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
28d36dde31 chore(deps): bump vite from 7.3.1 to 7.3.2 (#1049)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.3.1 to 7.3.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-25 20:51:50 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9998c82ba0 chore(deps-dev): bump happy-dom from 20.8.3 to 20.8.9 (#1036)
Bumps [happy-dom](https://github.com/capricorn86/happy-dom) from 20.8.3 to 20.8.9.
- [Release notes](https://github.com/capricorn86/happy-dom/releases)
- [Commits](https://github.com/capricorn86/happy-dom/compare/v20.8.3...v20.8.9)

---
updated-dependencies:
- dependency-name: happy-dom
  dependency-version: 20.8.9
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-24 18:51:31 +02:00
6535c96e81 chore(i18n): improve ru-RU translation consistency (#1026)
Co-authored-by: Dan Ditomaso <dan.ditomaso@gmail.com>
2026-03-16 21:35:36 -04:00
mammuthusandGitHub 080cce1bf0 fix(i18n): correct HTTPS typo (#1014) 2026-03-16 21:26:57 -04:00
Dan DitomasoandGitHub 3c1c23c1b9 fix: use correct JSR specifier for @meshtastic/protobufs (#1028)
* 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
2026-03-16 21:25:38 -04:00
Dan DitomasoandGitHub c729d3b25e fix: resolve lint warnings/errors and apply formatting (#1024)
* fix: resolve lint warnings/errors and apply formatting

Fix 10 oxlint issues (2 errors, 8 warnings):
- Remove unused catch parameters in Security.tsx and ImportDialog.tsx
- Remove stray expression in Generator.tsx
- Add eslint-disable for debounced useCallback in FilterControl.tsx
- Remove unnecessary deps (resolveDB, store) in bindStoreToDevice.ts
- Prefix unused variant param in AppSidebar.tsx
- Memoize tabs arrays in DeviceConfig, RadioConfig, ModuleConfig
- Fix channels type in RadioConfig TabItem

Also applies oxfmt formatting across all files.

* updating lock file

* update protobuf package

* fix: regenerate pnpm-lock.yaml and exclude jsr protobufs from minimumReleaseAge

* prevented http card from always being polled

* updated pnpm config fiile

* updated actions

* removed biome config and lint system leftovers

* updating protobuf package
2026-03-11 21:54:25 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a90df07ebe chore(deps-dev): bump tar from 7.5.7 to 7.5.11 (#1027)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.7 to 7.5.11.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.7...v7.5.11)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.11
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 21:14:29 -04:00
Dan DitomasoandGitHub 0579ec523e chore: remove protobufs git submodule (#1025) 2026-03-10 21:18:30 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9ebee7a8f4 chore(deps): bump rollup from 2.79.2 to 2.80.0 (#1017)
Bumps [rollup](https://github.com/rollup/rollup) from 2.79.2 to 2.80.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/v2.80.0/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.79.2...v2.80.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 2.80.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-04 21:32:21 -05:00
Dan DitomasoandGitHub 2b03bce0d5 restored logo (#1018) 2026-03-04 21:31:51 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
948146ddc8 chore(deps-dev): bump tar from 7.5.1 to 7.5.7 (#1008)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.1 to 7.5.7.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.1...v7.5.7)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.7
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-11 15:59:14 -05:00
ce06bc4128 fix: include long turbo modem preset (#1003)
Co-authored-by: Warp <agent@warp.dev>
2026-02-11 15:09:45 -05:00
Dan DitomasoandGitHub 765e4afe4d fix channel importing bug (#1005) 2026-02-11 12:27:17 -05:00
WesselandGitHub 0108494bd8 Channel bandwidth is kHz, not MHz (#983) 2025-12-08 23:03:41 -05:00
rj-xyandGitHub 3ecea59da8 Update README with Buf CLI installation instructions (#981)
Added instructions for installing the Buf CLI.
2025-12-04 22:59:37 -05:00
Dan DitomasoandGitHub 0b2fdb6439 Revert "feat(ui): add SNR, RSSI, hops info for messages (#963)" (#974)
This reverts commit 020e9d6b63.
2025-12-02 10:10:19 -05:00
94220e729b feat(map): add heatmap layer (#969)
* feat: add heatmap layer

* Update packages/web/src/components/PageComponents/Map/Layers/HeatmapLayer.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/PageComponents/Map/Tools/MapLayerTool.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/pages/Map/index.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/pages/Map/index.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/PageComponents/Map/Layers/HeatmapLayer.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* lint/formatting fixes

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-28 19:58:05 -05:00
020e9d6b63 feat(ui): add SNR, RSSI, hops info for messages (#963)
* 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>
2025-11-27 15:42:11 -05:00
Kamil DzieniszewskiandGitHub 6a7be99a6a feat: add fixed position coordinate picker (#909)
* 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)
2025-11-27 15:40:57 -05:00
5debdb4689 fix(ui): add "never" i18n string, fix "Favorite" tooltip (#965)
* fix(ui): add "never" i18n string, fix "Favorite" tooltip

* format

* format

---------

Co-authored-by: Pmmlabs <meshtastic@pmmlabs.ru>
2025-11-27 15:40:41 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
057043864f chore(deps-dev): bump happy-dom from 20.0.0 to 20.0.2 (#968)
Bumps [happy-dom](https://github.com/capricorn86/happy-dom) from 20.0.0 to 20.0.2.
- [Release notes](https://github.com/capricorn86/happy-dom/releases)
- [Commits](https://github.com/capricorn86/happy-dom/compare/v20.0.0...v20.0.2)

---
updated-dependencies:
- dependency-name: happy-dom
  dependency-version: 20.0.2
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-27 14:59:28 -05:00
Kamil DzieniszewskiandGitHub 8918603f96 fix(ui): correct typo in languagePicker key and adjust description width (#961)
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.
2025-11-24 21:02:28 -05:00
68cea2e858 chore(i18n): New Crowdin Translations by GitHub Action (#962)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-11-22 20:54:06 -05:00
06cc266acd fix(ui): removed internet hosted fonts from app (#955)
* fix(ui): removed internet hosted fonts from app

* Update packages/web/src/components/generic/Mono.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/UI/Typography/Code.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* removed unsupported font extention

* formatter fix

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-19 17:52:26 -05:00
zeoandGitHub 295755ec4c fix: interpolate longName and shortName in PKI backup download (#959)
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.
2025-11-18 18:04:40 -05:00
b99057df69 chore(i18n): New Crowdin Translations by GitHub Action (#958)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-11-17 21:28:28 -05:00
390b46f026 fix(ui): add language switcher to connections page (#954)
* fix(ui): add language switcher to connections page

* desciption length fix

* Update packages/web/src/pages/Connections/index.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* add new language picker key

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-13 13:06:20 -05:00
jsacristandGitHub 94d51912e6 feat: add devcontainer (#953) 2025-11-13 12:37:11 -05:00
Dan DitomasoandGitHub ac28fbc53d fix: removed duplicate images (#951) 2025-11-12 11:20:53 -05:00
648a9c3640 refactor: device connection logic, added nonce to get config only (#946)
* refactor: device connection logic, added nonce to get config only on connect.

* Update packages/web/src/core/services/MeshService.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/pages/Connections/useConnections.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* code review fixes

* fixes from code review

* ui fixes

* refactored meshService, moved code into deviceStore. Fixed some connnection issues

* formatting fixes

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-11 20:56:22 -05:00
Dan DitomasoandGitHub 7f21b3b531 Add 'packages/web' to excluded directories (#947) 2025-11-09 20:45:24 -05:00
d1597ce00f chore(i18n): New Crowdin Translations by GitHub Action (#941)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-11-09 20:38:31 -05:00
0c8fcec23d fix(i18n): Correct 'disconnected' typo in connections.json (#943)
* fix(i18n): Correct 'disconnected' typo in connections.json

* fix(i18n): Correct typo 'checkConnetion' to 'checkConnection'

* Fix(i18n): Correct typo in connection test description

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-11-09 20:38:18 -05:00
Dan DitomasoandGitHub 2e03b4a413 fix(ui): fix add connection dialog typo (#938) 2025-11-06 12:41:04 -05:00
a00cb2098b feat(ui): match avatar color other platforms (#933)
* feat(ui): match avatar color other platforms

* Update packages/web/src/components/UI/Avatar.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/DeviceInfoPanel.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-05 21:53:55 -05:00
Dan DitomasoandGitHub 6aeaed988e feat(docker): add arm v7 support (#934) 2025-11-05 21:53:41 -05:00
Dan DitomasoandGitHub 7c9013a217 fix(connection): support port on HTTP connection (#935) 2025-11-05 21:53:26 -05:00
Dan DitomasoandGitHub ab0308701c fix(connections): ensure connections reflect actual status. (#930) 2025-11-04 16:09:30 -05:00
e13d543e73 chore(i18n): New Crowdin Translations by GitHub Action (#924)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-11-04 15:23:20 -05:00
Dan DitomasoandGitHub d8ad0efcdf fix(config): update change registry channel value (#929)
* fix(config): update change registry channel value

* format/linting
2025-11-04 15:12:35 -05:00
Dan DitomasoandGitHub 2e60af1e29 fix(ci): add ui library to excluded list (#928) 2025-11-03 21:59:40 -05:00
Dan DitomasoGitHubCopilotgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Crowdin BotKamil DzieniszewskiAzarattumBen Allfree
1af1295b8f feat(connections): Add connections page (replaces new device dialog) (#919)
* feat(conn): add connection screen and logic

* fixes from code review

* force https

* code review fixes

* add http for self testing

* enable deviceStore persistance

* added translations

* disabled feature flag

* i18n updates

* chore: add new folders to biome config (#910)

* chore(i18n): New Crowdin Translations by GitHub Action (#908)

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>

* fix: use correct deprecated GPS coordinate format enum (#917)

The Config_DisplayConfig_GpsCoordinateFormat export doesn't exist in the protobufs package. The correct export is Config_DisplayConfig_DeprecatedGpsCoordinateFormat, which matches what's used in the validation schema.

Added TODO comment explaining that this field is deprecated since protobufs 2.7.4 and should be migrated to DeviceUIConfig.gps_format when DeviceUI settings are implemented.

* style: fix line wrapping for GPS coordinate format enum (#918)

- Split long enum reference across multiple lines to improve code readability
- Maintains consistent code formatting standards without changing functionality

* fix(core): ensure core package works in browser (#923)

* fix(core): ensure core package works in browser

* style(core): revert new line removal

* fix: add @serialport/bindings-cpp to onlyBuiltDependencies (#914)

* feat(ui): Add UI library (#900)

* feat: scaffold UI library

* Update packages/ui/src/components/theme-provider.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* add lock file

* lint/formatting fixes

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* formatting/linting fixes

* fixed some paring logic

* fixed connection issue with serial

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Kamil Dzieniszewski <kamil.dzieniszewski@gmail.com>
Co-authored-by: Azarattum <43073346+Azarattum@users.noreply.github.com>
Co-authored-by: Ben Allfree <ben@benallfree.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-03 20:24:24 -05:00
Dan DitomasoandGitHub a1a646983e fix: added skelton loader for message items (#927) 2025-11-03 19:08:53 -05:00
4386854e9d feat(ui): Add UI library (#900)
* feat: scaffold UI library

* Update packages/ui/src/components/theme-provider.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* add lock file

* lint/formatting fixes

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-31 14:37:34 -04:00
Ben AllfreeandGitHub e821a65dd4 fix: add @serialport/bindings-cpp to onlyBuiltDependencies (#914) 2025-10-31 14:37:11 -04:00
AzarattumandGitHub 3392c9db08 fix(core): ensure core package works in browser (#923)
* fix(core): ensure core package works in browser

* style(core): revert new line removal
2025-10-31 11:58:42 -04:00
Dan DitomasoandGitHub e53edfb00f feat(state): enable deviceStore persistance (#922) 2025-10-31 08:26:21 -04:00
Kamil DzieniszewskiandGitHub 1df63bb84b style: fix line wrapping for GPS coordinate format enum (#918)
- Split long enum reference across multiple lines to improve code readability
- Maintains consistent code formatting standards without changing functionality
2025-10-29 10:17:38 -04:00
Kamil DzieniszewskiandGitHub 679f7986cc fix: use correct deprecated GPS coordinate format enum (#917)
The Config_DisplayConfig_GpsCoordinateFormat export doesn't exist in the protobufs package. The correct export is Config_DisplayConfig_DeprecatedGpsCoordinateFormat, which matches what's used in the validation schema.

Added TODO comment explaining that this field is deprecated since protobufs 2.7.4 and should be migrated to DeviceUIConfig.gps_format when DeviceUI settings are implemented.
2025-10-29 10:12:04 -04:00
f375911c4a chore(i18n): New Crowdin Translations by GitHub Action (#908)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-10-28 11:19:36 -04:00
Dan DitomasoandGitHub 68ad535259 chore: add new folders to biome config (#910) 2025-10-28 01:54:06 -04:00
0cf677c8d5 Feat(config): Align settings menu to match android/ios (#906)
* feat: aligned settings menu to match android/ios

* updated sidebar text size.

* Update packages/web/public/i18n/locales/en/config.json

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/public/i18n/locales/en/config.json

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/PageComponents/Settings/User.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/PageComponents/ModuleConfig/Telemetry.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* linting/formatting fixes

* fixed formatting issue

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-24 13:31:22 -04:00
WesselandGitHub ff02b1455d Fix description for historyReturnWindow (#907)
It's not number of records but the time window...
2025-10-24 13:31:07 -04:00
cdad811295 Persists device and app stores across sessions (#860)
* Persistence for device and app data

* esphemeral -> ephemeral

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* devices -> app

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Additional waypoint methods, update mock, update tests

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-23 17:27:41 -04:00
fc1e327b74 Update inactive issue workflow schedule and settings (#905)
* Update inactive issue workflow schedule and settings

* Update .github/workflows/inactive-issue.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-23 15:52:36 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
af2fac1465 chore(deps): bump vite from 7.1.9 to 7.1.11 (#903)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.9 to 7.1.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.11
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-23 12:29:39 -04:00
Dan DitomasoandGitHub 15daa0270c feat(ci): add CI workflow to automatically close issue after 60 days (#897)
* feat(ci): add CI workflow to automatically close issue after 60 days

* run once pe github issue to run once per day
2025-10-22 19:39:10 -04:00
Dan DitomasoandGitHub 80c9306db3 feat(i18n): add fr localization support (#902)
* feat: add fr support

* fix(i18n): ensure langs are sorted before being displayed.
2025-10-21 19:42:56 -04:00
c3f073a380 Update readme with new widgets (#901)
* chore: add new widgets to readme

* add docs url

* Update README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-21 14:31:28 -04:00
fe35376450 chore(i18n): New Crowdin Translations by GitHub Action (#899)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-10-21 08:39:30 -04:00
64d1f0f7aa fix(ui): logic on waypoint layer component caused 0 to be shown in UI (#896)
* fix(ui): logic on waypoint layer component caused 0 to be shown in UI

* Update packages/web/src/components/PageComponents/Map/Popups/WaypointDetail.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-17 21:28:17 -04:00
a61bb2dfb6 fix(actions): improve main to stable release workflow (#895)
* fix(actions): improve main to stable release workflow

* Update .github/workflows/update-stable-from-master.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update .github/workflows/update-stable-from-master.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-17 10:06:17 -04:00
acfa7d2269 Add badge indicator on layers icon. (#894)
* feat: indicate number of layers enabled.

* Update packages/web/src/components/PageComponents/Map/Tools/MapLayerTool.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: reduced code duplication in layers component

* fixed unread message bubble

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-16 09:56:32 -04:00
Dan DitomasoGitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Copilotdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8f62fb7877 Show nodes on right sidebar on app load (#892)
* fix: show nodes on right sidebar on app load

* chore: update protobuf version to latest (#890)

* chore(deps-dev): bump happy-dom from 19.0.2 to 20.0.0 (#891)

Bumps [happy-dom](https://github.com/capricorn86/happy-dom) from 19.0.2 to 20.0.0.
- [Release notes](https://github.com/capricorn86/happy-dom/releases)
- [Commits](https://github.com/capricorn86/happy-dom/compare/v19.0.2...v20.0.0)

---
updated-dependencies:
- dependency-name: happy-dom
  dependency-version: 20.0.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update packages/web/src/core/stores/nodeDBStore/index.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-15 22:02:45 -04:00
Dan DitomasoandGitHub 94409dd8e1 Refactor CI workflow to remove Deno and add exclusions (#893)
* Refactor CI workflow to remove Deno and add exclusions

Removed Deno setup and caching from CI workflow. Added exclusion logic for specific package directories during the build process.

* Update excluded directories in CI workflow

Added 'packages/transport-deno' to the excluded directories.

* Refactor CI workflow for pnpm and build process
2025-10-15 21:57:44 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ac25326d24 chore(deps-dev): bump happy-dom from 19.0.2 to 20.0.0 (#891)
Bumps [happy-dom](https://github.com/capricorn86/happy-dom) from 19.0.2 to 20.0.0.
- [Release notes](https://github.com/capricorn86/happy-dom/releases)
- [Commits](https://github.com/capricorn86/happy-dom/compare/v19.0.2...v20.0.0)

---
updated-dependencies:
- dependency-name: happy-dom
  dependency-version: 20.0.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-15 16:14:02 -04:00
Dan DitomasoandGitHub 34bdbe4709 chore: update protobuf version to latest (#890) 2025-10-15 10:23:08 -04:00
Dan DitomasoandGitHub 8d98aca496 fix: updated module paths (#889) 2025-10-14 17:14:49 -04:00
Dan DitomasoandGitHub ec9ad1d309 fix: remove buf schema registry from workflow (#888) 2025-10-14 15:24:41 -04:00
Dan DitomasoandGitHub a97195c57e moar fixes (#887) 2025-10-14 14:29:43 -04:00
Dan DitomasoandGitHub 22a1d92191 Fix/more protobuf fixes (#886)
* fix: add pnpm to protobuf workflow

* fix: fixing pnpm issue
2025-10-14 13:43:34 -04:00
Dan DitomasoandGitHub 35596249b4 fix: add pnpm to protobuf workflow (#885) 2025-10-14 13:00:54 -04:00
Dan DitomasoandGitHub 566c588377 Fix protobuf github workflow (#884)
* fix: protobuf workflow

* update workflow name

* fixes
2025-10-14 10:44:33 -04:00
Dan DitomasoandGitHub 9ab49d1431 Add protobufs repo as git submodule (#882)
* feat: add protobufs git submodule

* fixes

* fixed publishing issue

* fixed lockfile
2025-10-14 08:54:55 -04:00
Kamil DzieniszewskiandGitHub f5a7132421 Update README.md (#881)
* Update README.md

* chore: rename CONTRIBUTIONS.md to CONTRIBUTING.md

- Rename packages/web/CONTRIBUTIONS.md to CONTRIBUTING.md to follow standard open source naming convention
- Update reference in packages/web/README.md to point to the renamed file
2025-10-14 07:12:03 -04:00
c66b315623 Restored user's node to ui (messages/node list) (#878)
* fix: restored own node to ui

* Update packages/web/src/pages/Messages.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/core/stores/nodeDBStore/index.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-11 10:07:56 -04:00
Dan DitomasoandGitHub 76ba4e917e fix: removed en-GB from fallback (#879) 2025-10-11 10:07:40 -04:00
d0da79bf56 chore(i18n): New Crowdin Translations by GitHub Action (#873)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-10-06 22:45:04 -04:00
Dan DitomasoandGitHub 66bf3f1578 Update web dependencies (#876)
* chore: update web depdencies

* update lock file

* chore: add lock file
2025-10-06 22:44:46 -04:00
6a358883f9 chore(i18n): New Crowdin Translations by GitHub Action (#868)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-09-29 22:19:38 -04:00
Dan DitomasoandGitHub 86622f83d0 Add minimumReleaseAge to pnpm-workspace.yaml (#865)
* Add minimumReleaseAge to pnpm-workspace.yaml

This is an important addition to protect our software from any sort of supply chain attack. This feature was recently released in pnpm 10.17.x

* Add minimumReleaseAgeExclude to pnpm-workspace.yaml

Allow our own packages to be installed without any freshness check.
2025-09-26 18:34:20 -04:00
66c3945bc4 chore(i18n): New Crowdin Translations by GitHub Action (#863)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-09-22 08:59:35 -04:00
Nullvoid3771andGitHub 38cb002ce8 Update nightly.yml (#864)
+echo "all_tags=nightly ${IMMUTABLE}" >> "$GITHUB_OUTPUT"
2025-09-21 19:18:22 -04:00
36443fd838 Map improvements - node and neighbor display (#850)
* Improves map node and neighbor display

Updates the map page to enhance the visualization of nodes, waypoints, and neighbor connections.

Adds a map layer tool for toggling the visibility of direct/remote neighbors and position precision indicators.

Introduces clustering to improve map readability when multiple nodes share the exact same location.

Adds SNR lines to visually represent network connections between nodes

Co-Authored-By: jamon <jamon@users.noreply.github.com>

* Clean up

* Update packages/web/src/components/generic/TimeAgo.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/PageComponents/Map/Layers/SNRLayer.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Improve dark mode and expires field

* Review fixes

Co-Authored-By: Dan Ditomaso <dan.ditomaso@gmail.com>

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
Co-authored-by: jamon <jamon@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Dan Ditomaso <dan.ditomaso@gmail.com>
2025-09-18 08:13:34 -04:00
8cc451546d Command Menu improvements (#857)
* Add dialogs for reset and clear actions + clear stores

* Catch failures

* Improve tests, don't reset store on failure

* Remove unnecessary i18n string

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-09-18 08:13:19 -04:00
1bdd923365 Do not unregister form (#856)
Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-09-17 18:34:19 +02:00
d5610de826 Update @bufbuild/protobuf to version 2.8.0 for web as well (#852)
Bumped @bufbuild/protobuf dependency from 2.6.0 to 2.8.0 in packages/web. Updated pnpm-lock.yaml accordingly to use the new version.

Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-09-14 21:32:00 -04:00
aaf85943a8 Address new linting rules (#851)
Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-09-14 21:31:47 -04:00
Dan DitomasoandGitHub 37ad0ac9eb removed all_tags from workflow (#854) 2025-09-14 21:27:05 -04:00
Dan DitomasoandGitHub eb2791e206 Fix for nightly release (#853)
* fix: removed commas in tag name

* removed `all_tags` from workflow
2025-09-14 15:10:56 -04:00
119cde65c7 chore(i18n): New Crowdin Translations by GitHub Action (#849)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-09-14 14:51:12 -04:00
cb66c22974 Fixes to github actions for latest tag (#848)
* fix: ensure latest tag works

* update release workflow as well

* Update .github/workflows/nightly.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-13 16:07:13 -04:00
Henri BergiusandGitHub 96c5d0d86f Create PR instead of trying to push to protected branch (#842) 2025-09-13 15:56:01 -04:00
Dan DitomasoandGitHub 2d98f57b65 fix: update-lock-file (#847) 2025-09-13 11:54:21 -04:00
3e2fe721d3 Improvements to node filtering and storage (#839)
* Improves node filtering and voltage display

Ensures voltage values are always displayed as positive.

Enhances node filtering logic to handle unknown or undefined values, preventing nodes from being unexpectedly hidden.

Updates UI labels for clarity.

Improves Nodes page responsiveness by debouncing node updates and optimizing selector usage, preventing unnecessary re-renders.

Adds validation warnings for key conflicts between nodes.

* Update packages/web/src/core/stores/nodeDBStore/nodeDBStore.test.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/core/stores/nodeDBStore/nodeValidation.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Revert copilot suggestion

* Review changes

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-12 17:21:13 +02:00
Dan DitomasoandGitHub 52fd2f712c chore: update web deps (#845)
* chore: update web deps

* Bumped library package version (#843)

* chore: bumped package versions

* removed jsr file
2025-09-11 22:41:56 -04:00
Dan DitomasoandGitHub ad6b9f470f Bumped library package version (#843)
* chore: bumped package versions

* removed jsr file
2025-09-11 22:14:32 -04:00
765f672bf5 Improve the nightly and release workflow (#836)
* fix: improve the nightly and release workflow

* Update .github/workflows/nightly.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix from code review

* add type module to node-serial

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-11 15:34:04 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
67a5d75283 chore(deps): bump vite from 7.1.1 to 7.1.5 (#841)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.1 to 7.1.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-11 14:05:55 -04:00
Henri BergiusandGitHub 4ff010e14b Get protobufs directly from NPM (#840)
* Get protobufs directly from NPM

* Bump dep

* Update lockfile too
2025-09-11 11:13:45 -04:00
1214b6ecf6 Allow default overrideFrequency (#838)
* Allow overrideFrequency == 0
* Fix typo

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-09-10 20:33:32 +02:00
Dan DitomasoandGitHub aababb8075 Dialog abstraction using DialogWrapper (#830)
* feat: add dialog abstraction system

* removed unneeded file

* fix formatting

* linting fixes
2025-09-10 13:56:45 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3b0406c5af chore(deps): bump vite from 7.1.1 to 7.1.5 (#837)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.1 to 7.1.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-10 13:56:12 -04:00
6772f066ee chore(i18n): New Crowdin Translations by GitHub Action (#835)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-09-07 21:10:35 -04:00
Dan DitomasoandGitHub d8df40816f fix: added directive to remove service worker (#834) 2025-09-07 13:14:24 -04:00
f9bd61af49 Fixed overrideFrequency Input Constraints (#801)
* Fixed overrideFrequency to properly allow for floats with a minimum of 410 MHz and maximum of 930 MHz. Added 3 decimal point check.

* Removed duplicate error message in FormInput.tsx

* Added error message for overrideFrequency in several locales

* Simplified check and reverted translated languages to English besides German. Also fixed a typo in src/components/UI/Input.tsx.

* Let i18n handle fallback + linting

---------

Co-authored-by: philon- <jeremy@gallant.se>
2025-09-04 18:22:06 -04:00
Henri BergiusandGitHub bcdda8b751 Connection robustness improvements (#813)
* Clear heartbeat and queue when disconnected

* Give clearer error in case configure fails due to a lost connection. Used to throw 'Packet does not exist'

* If the queue processing error is due to a lost connection, throw it instead of looping endlessly

* In case we send a disconnection event we don't need to also throw

* Catch heartbeat errors

* Also handle invalid state errors

* Handle socket timeouts

* Log heartbeat failures

* Make linter happy

* Transform stream being a singleton prevented reconnection attempts

* Adapt tests to not using singleton

* Aborting already ends the connection
2025-09-04 13:08:05 -04:00
dcb44d27fe Persistent message store (#814)
* Fix default filter behaviour

* Persist message store

* messageStore tests, node PKI validation

Implement node validation and improve merging logic

- Added `validateIncomingNode` function to validate new nodes against existing nodes, checking for public key conflicts and ensuring proper handling of node updates.
- Updated `nodeDBFactory` to utilize the new validation function when adding nodes.
- Enhanced `getNodes` method to optionally include the current node in the results.
- Removed the `mergeNodeInfo` utility as its functionality is now integrated into the validation and merging process.
- Updated tests to cover new validation logic and ensure correct behavior during node addition and merging.
- Cleaned up unused utility functions related to key comparison.

* refactor: reuse eviction logic for message and node stores

* Update format, move hooks

* Improve test performance

* Update imports

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
Co-authored-by: Dan Ditomaso <dan.ditomaso@gmail.com>
2025-09-03 21:00:48 -04:00
Dan DitomasoandGitHub 799283fd46 fix: added latest tag, added conditionals if prerelease (#832) 2025-09-03 17:09:54 -04:00
Dan DitomasoandGitHub d0f4939a4d Added lint rule to enforce importing with extensions (#831)
* fix: added lint rule to enforce importing with extentions

* fix test import path

* added import file extentions
2025-09-03 17:07:00 -04:00
d66f10e715 Fix rename seperator again (#828)
* Reapply "Seperator -> Separator (#823)" (#827)

This reverts commit e421eb4244.

* Rename new seperator

* Update packages/web/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/Dialog/RebootDialog.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/components/PageComponents/Map/NodeDetail.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/web/src/pages/Dashboard/index.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
Co-authored-by: Dan Ditomaso <dan.ditomaso@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-02 22:02:36 -04:00
Dan DitomasoandGitHub e421eb4244 Revert "Seperator -> Separator (#823)" (#827)
This reverts commit 3582499a3c.
2025-09-02 09:41:48 -04:00
ce16bf5aa4 Chat message date display (#824)
* Date handling

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-01 23:00:05 -04:00
3582499a3c Seperator -> Separator (#823)
Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-09-01 21:57:51 -04:00
1946000d14 New channel config (#807)
* Channel config rework

Add staged channel config with tabbed UI, import/export workflow, and global form state refactor

* Improve import dialog config comparison and UI labels

* Review fixes

* Improve state handling

* Fix default filter behaviour

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-09-01 09:07:34 -04:00
01fa030ef9 Fix default filter behaviour (#820)
Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-08-31 21:44:22 -04:00
90cf136b8c Update test format (#821)
* Lint tests, format JSON

* Update test formatting

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-08-31 21:30:11 -04:00
Dan DitomasoandGitHub ee131c3681 fix: added working directory to build step (#819) 2025-08-31 16:22:43 -04:00
85accf7c25 chore(i18n): New Crowdin Translations by GitHub Action (#815)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-08-31 16:05:23 -04:00
Jeremy GallantandGitHub 91426a89e5 Lint tests, format JSON (#818) 2025-08-31 16:04:34 -04:00
Dan DitomasoandGitHub d7e492cdc9 fix: removed comma from tag name (#817) 2025-08-31 13:09:50 -04:00
Dan DitomasoandGitHub c5cad1dca6 fix incorrect usage of tags (#811) 2025-08-28 20:56:54 -04:00
Henri BergiusandGitHub 85aa7a37b9 Methods for setting/removing fixed position (#802)
* Method for setting fixed position

* Implement removeFixedPosition

* Fix formatting
2025-08-27 18:46:14 -04:00
Henri BergiusandGitHub b87fad23d8 Catch packet decoding errors (#809)
* Catch decoding errors, refs #808

* Catch packet handling errors

* Add missing type
2025-08-25 16:59:35 -04:00
68ec7ee5d8 Persistent nodedb (#780)
* Refactor  and consolitdate store imports

- Created a new index file in the core stores directory to export all stores from a single module.
- Updated imports to use consolidated store exports.

* Remove unnecessary import

* Update imports

* First steps to persist nodeDB

* Use named exports

* Change store import after merge

* Persistent nodeDB initial work

* Key mishmatch warning, new serialization handler

* Minor copilot changes

* Add NODEDB_RETENTION_NUM

* Updated tests

* Refactor PKI mismatch logic

* Clear persisted db on reset

* Only persist on featureFlag

* Mock featureFlag in tests

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
2025-08-24 09:23:20 -04:00
e33463b371 chore(i18n): New Crowdin Translations by GitHub Action (#806)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-08-23 20:45:31 -04:00
Jeremy GallantandGitHub d4b80cf90b Re-add toaster component (#804) 2025-08-23 20:45:22 -04:00
d7e32e9b03 Add transport status events (#790)
* Transport status events

Add symbol docs
Emit transport status events
Transport test suite

* Review fixes

* Remove core dependency

* HTTP transport use AbortSignal, error handling in TransportNode

* Improve stream handling

* Update packages/transport-web-serial/src/transport.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix linting

---------

Co-authored-by: philon- <philon-@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-23 20:44:03 -04:00
449fb3ac36 Added feature flags system (#803)
* added feature flag system

* Update packages/web/src/core/services/featureFlags.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* remove process.env

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-22 13:47:24 -04:00
Dan DitomasoandGitHub 1de92cd2e9 Replace workspace formatter/linting tool (#799)
* replaced workspace formatter/linting tool

* format / linting fixes
2025-08-22 12:30:05 -04:00
Dan DitomasoandGitHub fdd3e7f971 re-order package steps (#798) 2025-08-20 12:19:26 -04:00
Dan DitomasoandGitHub 6eece7172a bumped web-serial version (#797) 2025-08-20 11:53:12 -04:00
Ben MeadorsandGitHub 5b2c25d8ee Try-fix webserial disconnect not actually disconnecting (#796)
* Try-fix webserial disconnects

* Instantiate abort controller on new connection
2025-08-20 11:01:17 -04:00
991 changed files with 102717 additions and 33678 deletions
+13
View File
@@ -0,0 +1,13 @@
{
"name": "meshtastic-web",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm",
"features": {
"ghcr.io/r3dpoint/devcontainer-features/tailwindcss-standalone-cli:1": {
"version": "latest"
},
"ghcr.io/devcontainers-extra/features/pnpm:2": {
"version": "latest"
}
}
}
-12
View File
@@ -1,12 +0,0 @@
#!/bin/sh
if [ "$SKIP_SIMPLE_GIT_HOOKS" = "1" ]; then
echo "[INFO] SKIP_SIMPLE_GIT_HOOKS is set to 1, skipping hook."
exit 0
fi
if [ -f "$SIMPLE_GIT_HOOKS_RC" ]; then
. "$SIMPLE_GIT_HOOKS_RC"
fi
# cd packages/web && bun run lint && bun run format
+3
View File
@@ -0,0 +1,3 @@
## Design Standards
All UI must comply with the [Meshtastic Client Design Standards](https://raw.githubusercontent.com/meshtastic/design/refs/heads/master/standards/meshtastic_design_standards_latest.md). Fetch and review this document before making any UI changes.
+21
View File
@@ -0,0 +1,21 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
cooldown:
default-days: 3 # 1 day after pnpm's cutoff, prevent a race
groups:
tanstack:
patterns:
- "@tanstack/*"
react-ecosystem:
patterns:
- react
- react-dom
- "@types/react*"
+47 -38
View File
@@ -14,55 +14,64 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: latest
uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: pnpm
cache-dependency-path: '**/pnpm-lock.yaml'
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
- name: Prewarm & Install (workspace)
run: |
set -euo pipefail
pnpm fetch
pnpm install --frozen-lockfile --offline
- name: Cache Deno dependencies
uses: actions/cache@v4
with:
path: ~/.cache/deno
key: ${{ runner.os }}-deno-${{ hashFiles('**/deno.lock', '**/package.json') }}
restore-keys: |
${{ runner.os }}-deno-
- name: Cache pnpm dependencies
uses: actions/cache@v4
with:
path: |
~/.pnpm-store
packages/web/node_modules
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
- name: Build All Packages
- name: Build All Packages (with exclusions)
shell: bash
run: |
set -euo pipefail
for pkg_dir in packages/*/; do
pkg_dir=${pkg_dir%/} # Remove trailing slash
echo "🔍 Inspecting $pkg_dir..."
# List packages to exclude (full paths under repo root)
EXCLUDED_DIRS=("packages/protobufs" "packages/transport-deno" "packages/ui" "packages/web")
if [[ -f "$pkg_dir/package.json" ]] && [[ "$pkg_dir" != "packages/web" ]]; then
echo "🔧 Building with pnpm: $pkg_dir"
(cd "$pkg_dir" && pnpm install --frozen-lockfile && pnpm run build:npm)
else
echo "⚠️ Skipping $pkg_dir (web package or no package.json)"
is_excluded() {
local dir="$1"
for ex in "${EXCLUDED_DIRS[@]}"; do
if [[ "$dir" == "$ex" ]]; then
return 0
fi
done
return 1
}
for pkg_dir in packages/*/; do
pkg_dir="${pkg_dir%/}" # trim trailing slash
# Must be a directory with a package.json
if [[ ! -f "$pkg_dir/package.json" ]]; then
echo "⚠️ Skipping $pkg_dir (no package.json)"
continue
fi
# Allow for exclusions
if is_excluded "$pkg_dir"; then
echo "🚫 Skipping $pkg_dir (excluded)"
continue
fi
# Optionally skip Deno-first packages automatically
if [[ -f "$pkg_dir/deno.json" || -f "$pkg_dir/deno.jsonc" ]]; then
echo "🦕 Skipping $pkg_dir (deno project)"
continue
fi
echo "🔧 Building: $pkg_dir"
# No per-package install needed; workspace install already done
pnpm -C "$pkg_dir" run build:npm
done
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Download translations with Crowdin
uses: crowdin/github-action@v2
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Upload sources with Crowdin
uses: crowdin/github-action@v2
@@ -9,7 +9,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Upload translations with Crowdin
uses: crowdin/github-action@v2
+24
View File
@@ -0,0 +1,24 @@
name: Close inactive issues
on:
schedule:
- cron: "0 */4 * * *" # every 4 hours
workflow_dispatch: # allow manual runs
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: 60
days-before-issue-close: 14
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 60 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
days-before-pr-stale: -1
days-before-pr-close: -1
only-issue-labels: "Bug"
remove-stale-when-updated: true
+39 -29
View File
@@ -3,7 +3,7 @@ name: Nightly Release
on:
schedule:
- cron: "0 5 * * *" # 05:00 UTC daily
workflow_dispatch: {} # allow manual runs too
workflow_dispatch: {} # allow manual runs too
permissions:
contents: read
@@ -18,19 +18,17 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: latest
uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: pnpm
cache-dependency-path: '**/pnpm-lock.yaml'
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies (root)
run: pnpm install --frozen-lockfile
@@ -39,21 +37,21 @@ jobs:
run: pnpm run test
- name: Build web package
working-directory: packages/web
working-directory: apps/web
run: pnpm run build
- name: Package output
working-directory: packages/web
working-directory: apps/web
run: pnpm run package
- name: Upload compressed build (artifact)
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: web-build-nightly
path: packages/web/dist/build.tar
path: apps/web/dist/build.tar
if-no-files-found: error
- name: Determine nightly tag
- name: Compute tags and labels
id: meta
shell: bash
env:
@@ -61,48 +59,60 @@ jobs:
run: |
set -euo pipefail
DATE="$(date -u +%Y%m%d)"
ISO_CREATED="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
SHORTSHA="$(git rev-parse --short=12 HEAD)"
# Try to use latest release tag if it exists; fallback to package version; else date
LATEST_TAG="$(gh release view --json tagName --jq .tagName 2>/dev/null || true)"
if [ -z "$LATEST_TAG" ] && [ -f packages/web/package.json ]; then
LATEST_TAG="v$(jq -r .version packages/web/package.json)"
if [ -z "$LATEST_TAG" ] && [ -f apps/web/package.json ]; then
LATEST_TAG="v$(jq -r .version apps/web/package.json)"
fi
if [ -n "$LATEST_TAG" ] && [ "$LATEST_TAG" != "vnull" ]; then
TAG="nightly-${LATEST_TAG}-${SHORTSHA}"
if [ -n "${LATEST_TAG:-}" ] && [ "$LATEST_TAG" != "vnull" ]; then
IMMUTABLE="nightly-${LATEST_TAG}-${SHORTSHA}"
else
TAG="nightly-${DATE}-${SHORTSHA}"
IMMUTABLE="nightly-${DATE}-${SHORTSHA}"
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "tags=nightly, $TAG" >> "$GITHUB_OUTPUT"
echo "Resolved nightly tags: nightly, $TAG"
# Outputs
echo "moving_tag=nightly" >> "$GITHUB_OUTPUT"
echo "immutable_tag=${IMMUTABLE}" >> "$GITHUB_OUTPUT"
echo "all_tags=nightly ${IMMUTABLE}" >> "$GITHUB_OUTPUT"
echo "created=${ISO_CREATED}" >> "$GITHUB_OUTPUT"
echo "Resolved tags: nightly and ${IMMUTABLE}"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Build Container Image (multi-arch)
id: build-container
uses: redhat-actions/buildah-build@v2
with:
containerfiles: |
./packages/web/infra/Containerfile
./apps/web/infra/Containerfile
image: ${{ env.REGISTRY_IMAGE }}
tags: ${{ steps.meta.outputs.tags }}
tags: |
${{ steps.meta.outputs.moving_tag }}
${{ steps.meta.outputs.immutable_tag }}
oci: true
platforms: linux/amd64, linux/arm64
platforms: linux/amd64,linux/arm64,linux/arm/v7
labels: |
org.opencontainers.image.source=${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ github.run_id }}
org.opencontainers.image.created=${{ steps.meta.outputs.created }}
- name: Push To GHCR
id: push-to-registry
uses: redhat-actions/push-to-registry@v2
with:
image: ${{ steps.build-container.outputs.image }}
tags: ${{ steps.build-container.outputs.tags }}
# Push the same tags used at build time:
tags: ${{ steps.meta.outputs.all_tags }}
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Print image URL
run: echo "Image pushed to ${{ steps.push-to-registry.outputs.registry-paths }}"
- name: Print image URLs
run: |
echo "Moving tag: ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.moving_tag }}"
echo "Immutable tag: ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.immutable_tag }}"
+17 -9
View File
@@ -17,24 +17,32 @@ env:
jobs:
build-and-package:
runs-on: ubuntu-latest
# Skip for draft PRs; remove this line if you want to run on drafts too
if: ${{ github.event.pull_request.draft == false }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: latest
uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: pnpm
cache-dependency-path: '**/pnpm-lock.yaml'
cache-dependency-path: pnpm-lock.yaml
- name: Debug dependency state
run: |
set -euo pipefail
echo "GITHUB_SHA=${GITHUB_SHA}"
git log --oneline -1
pnpm --version
node --version
grep -n "meshtastic__protobufs" pnpm-lock.yaml || true
grep -n "2.7.18" pnpm-lock.yaml || true
grep -n "2.7.20" pnpm-lock.yaml || true
- name: Install dependencies
run: pnpm install --frozen-lockfile
@@ -49,4 +57,4 @@ jobs:
run: pnpm run test
- name: Build web package
run: pnpm --filter "./packages/web" run build
run: pnpm --filter "./apps/web" run build
+85 -53
View File
@@ -4,47 +4,45 @@ on:
workflow_dispatch:
inputs:
packages:
description: 'Packages to release (comma-separated, or "all" for all packages)'
description: 'Packages to release (comma-separated, or "all")'
required: false
default: 'all'
default: "all"
bump:
description: "Semver bump (patch | minor | major)"
required: false
default: "patch"
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # <-- required for JSR OIDC
contents: write # we commit the bumped versions back
id-token: write # required for JSR OIDC
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@v4
# Node + pnpm (with cache)
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: '**/pnpm-lock.yaml'
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
version: latest
node-version: 24
cache: pnpm
cache-dependency-path: "**/pnpm-lock.yaml"
registry-url: "https://registry.npmjs.org"
- name: Configure npm auth
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
pnpm config set //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
pnpm config set registry https://registry.npmjs.org/
- name: Install deps (root)
run: pnpm install
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Resolve package list
id: pkgs
shell: bash
run: |
set -euo pipefail
if [ "${{ github.event.inputs.packages }}" = "all" ] || [ -z "${{ github.event.inputs.packages }}" ]; then
mapfile -t TARGETS < <(ls -d packages/* | grep -v 'packages/web')
else
@@ -53,61 +51,95 @@ jobs:
fi
printf '%s\n' "${TARGETS[@]}" | paste -sd, - > targets.txt
echo "list=$(cat targets.txt)" >> "$GITHUB_OUTPUT"
echo "Targets: $(cat targets.txt)"
- name: Build selected packages (tsdown)
- name: Bump package.json versions (no git tag)
shell: bash
run: |
set -euo pipefail
BUMP="${{ github.event.inputs.bump }}"
IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}"
for dir in "${TARGETS[@]}"; do
if [ -f "$dir/package.json" ]; then
echo "Bumping $dir -> $BUMP"
(cd "$dir" && npm version "$BUMP" --no-git-tag-version --allow-same-version)
fi
done
- name: Generate jsr.json from package.json (pkg-to-jsr)
shell: bash
run: |
set -euo pipefail
IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}"
for dir in "${TARGETS[@]}"; do
if [ -f "$dir/package.json" ]; then
echo "Generating jsr.json for $dir"
pnpm dlx pkg-to-jsr --root "$dir"
# # Optional: show result
# jq -C . "$dir/jsr.json" || cat "$dir/jsr.json"
fi
done
- name: Commit version bumps
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add packages/*/package.json packages/*/jsr.json 2>/dev/null || true
if ! git diff --cached --quiet; then
git checkout -b version_bump
git commit -m "chore(release): bump package versions (${{ github.event.inputs.bump }})"
git push -u origin version_bump
gh pr create --title "Bump package versions" --body "Bump versions of NPM and JSR packages" --base main --head version_bump
echo "Pushed to branch version_bump"
else
echo "No changes to commit."
fi
- name: Build selected packages
shell: bash
run: |
set -euo pipefail
IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}"
for dir in "${TARGETS[@]}"; do
echo "Building $dir"
pnpm --filter "./$dir" run build
done
- name: Sync jsr.json version from package.json
run: |
IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}"
for dir in "${TARGETS[@]}"; do
if [ -f "$dir/jsr.json" ] && [ -f "$dir/package.json" ]; then
PKG_VER=$(jq -r .version "$dir/package.json")
jq --arg v "$PKG_VER" '.version = $v' "$dir/jsr.json" > "$dir/jsr.json.tmp" && mv "$dir/jsr.json.tmp" "$dir/jsr.json"
echo "Updated $dir/jsr.json to version $PKG_VER"
fi
done
- name: Publish to JSR (OIDC)
shell: bash
run: |
set -euo pipefail
IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}"
for dir in "${TARGETS[@]}"; do
if [ -f "$dir/jsr.json" ]; then
echo "Publishing $dir to JSR via OIDC…"
cd "$dir"
[ -d dist ] || pnpm run build
if ! npx --yes jsr publish 2>&1 | tee jsr_publish.log; then
echo "JSR publish failed for $dir. Error output:"
cat jsr_publish.log
fi
cd - >/dev/null
( cd "$dir"
[ -d dist ] || pnpm run build
npx --yes jsr publish
)
fi
done
- name: Replace exports entry in package.json
- name: Configure npm auth
run: |
tmp=$(mktemp)
jq '.exports["."] = "./dist/mod.mjs"' package.json > "$tmp" \
&& mv "$tmp" package.json
pnpm config set //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
pnpm config set registry https://registry.npmjs.org/
- name: Publish to npm
shell: bash
run: |
set -euo pipefail
IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}"
for dir in "${TARGETS[@]}"; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir to npm…"
cd "$dir"
[ -d dist ] || pnpm run build
npm publish --access public || echo "npm publish failed for $dir"
cd - >/dev/null
( cd "$dir"
[ -d dist ] || pnpm run build
npm publish --access public
)
fi
done
+141
View File
@@ -0,0 +1,141 @@
name: Create Protobuf Release for JSR
on:
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g. v1.2.3). Used when manually dispatching."
required: true
type: string
dry_run:
description: "Don't actually publish to JSR (passes --dry-run)."
required: false
type: boolean
default: false
permissions: write-all
env:
PROTOBUF_DIR: ./packages/protobufs
jobs:
codegen:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Show files exist
run: |
set -euxo pipefail
ls -la $PROTOBUF_DIR/packages/ts || true
cat $PROTOBUF_DIR/packages/ts/deno.json
- name: Determine VERSION
run: |
set -euo pipefail
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
echo "No 'version' input. Provide inputs.version." >&2
exit 1
fi
STRIPPED="${VERSION#v}"
echo "VERSION=$STRIPPED" >> "$GITHUB_ENV"
echo "Resolved VERSION=$STRIPPED"
- name: Set Package Versions to current tag
working-directory: ${{ env.PROTOBUF_DIR }}/packages/ts
run: |
set -euxo pipefail
for f in deno.json; do
test -f "$f"
jq --arg version "${VERSION//\//-}" '
walk(
if type == "string" and test("__PACKAGE_VERSION__")
then sub("__PACKAGE_VERSION__"; $version)
else .
end
)
' "$f" > "$f.tmp"
mv "$f.tmp" "$f"
done
- name: Setup Buf
uses: bufbuild/buf-setup-action@main
with:
github_token: ${{ github.token }}
- name: Setup pnpm
uses: pnpm/action-setup@v6
- name: Install workspace dependencies
run: pnpm install --frozen-lockfile
- name: Generate code
run: pnpm --filter @meshtastic/protobufs-ws build
- name: Move generated .ts files and clean up
run: |
set -euxo pipefail
SRC_DIR="$PROTOBUF_DIR/packages/ts/dist/meshtastic"
DEST_DIR="$PROTOBUF_DIR/packages/ts/dist"
if [ -d "$SRC_DIR" ]; then
shopt -s nullglob
ts_files=("$SRC_DIR"/*.ts)
if [ ${#ts_files[@]} -gt 0 ]; then
mv "$SRC_DIR"/*.ts "$DEST_DIR"/
fi
rm -rf "$SRC_DIR"
else
echo "Source directory not found: $SRC_DIR" >&2
exit 1
fi
# Remove nanopb_pb.ts if present
if [ -f "$DEST_DIR/nanopb_pb.ts" ]; then
rm "$DEST_DIR/nanopb_pb.ts"
fi
- name: Copy license & README
run: |
cp LICENSE $PROTOBUF_DIR/packages/ts
cp README.md $PROTOBUF_DIR/packages/ts
- name: Upload TypeScript code
uses: actions/upload-artifact@v7
with:
name: ts_code
path: ${{ env.PROTOBUF_DIR }}/packages/ts
publish-jsr:
runs-on: ubuntu-24.04
needs: codegen
permissions:
contents: read
id-token: write
env:
DRY_RUN: ${{ inputs.dry_run }}
steps:
- name: Download TypeScript code
uses: actions/download-artifact@v8
with:
name: ts_code
- name: Set up Deno
uses: denoland/setup-deno@main
with:
deno-version: rc
- name: Publish to JSR
run: |
set -euxo pipefail
FLAGS="--unstable-sloppy-imports"
if [ "${DRY_RUN}" = "true" ]; then
FLAGS="$FLAGS --dry-run"
echo "Running publish in dry-run mode..."
fi
deno publish $FLAGS
+92 -91
View File
@@ -30,128 +30,129 @@ jobs:
release-web:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v6
with:
# For manual runs, allow building a chosen ref (branch/tag/SHA)
ref: ${{ inputs.ref != '' && inputs.ref || github.ref }}
- name: Determine tag & latest flag
id: meta
shell: bash
run: |
# Determine TAG
if [ "${{ github.event_name }}" = "release" ]; then
TAG="${{ github.event.release.tag_name }}"
# Push "latest" only for full releases (not prereleases)
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
PUSH_LATEST="false"
else
PUSH_LATEST="true"
fi
elif [ -n "${{ inputs.tag_name }}" ]; then
TAG="${{ inputs.tag_name }}"
PUSH_LATEST="false"
else
SHA="$(git rev-parse --short=12 HEAD)"
TAG="adhoc-${SHA}"
PUSH_LATEST="false"
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "push_latest=$PUSH_LATEST" >> "$GITHUB_OUTPUT"
echo "Resolved tag: $TAG (push_latest=$PUSH_LATEST)"
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: latest
uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: pnpm
cache-dependency-path: '**/pnpm-lock.yaml'
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build web package
working-directory: packages/web
working-directory: apps/web
run: pnpm run build
- name: Build web package
working-directory: packages/web
run: pnpm run build
- name: Create Web App Release Archive
working-directory: packages/web
- name: Create release archive
working-directory: apps/web
run: pnpm run package
- name: Upload Web App Archive (artifact)
uses: actions/upload-artifact@v4
- name: Upload archive (artifact)
uses: actions/upload-artifact@v7
with:
name: web-build-${{ steps.meta.outputs.tag }}
name: web-build
path: apps/web/dist/build.tar
if-no-files-found: error
path: packages/web/dist/build.tar
- name: Attach Web Archive to GitHub Release
- name: Attach archive to GitHub Release
if: ${{ github.event_name == 'release' || inputs.attach_to_release == true }}
uses: softprops/action-gh-release@v3
with:
files: apps/web/dist/build.tar
tag_name: ${{ github.event_name == 'release' && github.event.release.tag_name || inputs.tag_name }}
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Compute created timestamp & short SHA for labels/tags
- name: Compute meta
id: gen
shell: bash
run: |
if [ "${{ github.event_name }}" = "release" ]; then
TAG="${{ steps.meta.outputs.tag }}"
else
if [ -z "${{ inputs.tag_name }}" ]; then
echo "attach_to_release requested but no tag_name provided." >&2
exit 1
fi
TAG="${{ inputs.tag_name }}"
fi
gh release upload "$TAG" packages/web/dist/build.tar --clobber
echo "created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"
echo "shortsha=$(git rev-parse --short=12 HEAD)" >> "$GITHUB_OUTPUT"
# Build/tag matrix:
# - For release events: vX.Y.Z, semver helpers, and latest (only if NOT prerelease)
# - For prerelease events: vX.Y.Z and semver helpers (NO latest)
# - For manual runs:
# * if tag_name set: that raw tag
# * else: adhoc-<shortsha>
- name: Docker metadata (tags & labels)
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY_IMAGE }}
labels: |
org.opencontainers.image.source=${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ steps.gen.outputs.created }}
tags: |
# Full release (semantic tag)
type=raw,value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }}
# Semver helpers (major, major.minor) for releases/prereleases
type=semver,pattern={{version}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }}
type=semver,pattern={{major}}.{{minor}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' && github.event.release.prerelease == false }}
type=semver,pattern={{major}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' && github.event.release.prerelease == false }}
# Latest only for full releases (not prereleases)
type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.release.prerelease == false }}
# Manual: provided tag_name
type=raw,value=${{ inputs.tag_name }},enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name != '' }}
# Manual: fallback to adhoc-<shortsha>
type=raw,value=adhoc-${{ steps.gen.outputs.shortsha }},enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name == '' }}
# Always add immutable sha tag for traceability
type=raw,value=sha-${{ steps.gen.outputs.shortsha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Compute image tags
id: tags
shell: bash
run: |
if [ "${{ steps.meta.outputs.push_latest }}" = "true" ]; then
echo "list=latest, ${{ steps.meta.outputs.tag }}" >> "$GITHUB_OUTPUT"
else
echo "list=${{ steps.meta.outputs.tag }}" >> "$GITHUB_OUTPUT"
fi
TAGS="latest, ${{ steps.meta.outputs.tag }}"
else
TAGS="${{ steps.meta.outputs.tag }}"
fi
echo "list=$TAGS" >> "$GITHUB_OUTPUT"
echo "Using image tags: $TAGS"
- name: Set up Buildx
uses: docker/setup-buildx-action@v4
- name: Build Container Image
id: build-container
uses: redhat-actions/buildah-build@v2
- name: Login to GHCR
uses: docker/login-action@v4
with:
containerfiles: |
./packages/web/infra/Containerfile
image: ${{ env.REGISTRY_IMAGE }}
tags: ${{ steps.tags.outputs.list }}
oci: true
platforms: linux/amd64, linux/arm64
- name: Push Container to GHCR
id: push-to-registry
uses: redhat-actions/push-to-registry@v2
with:
image: ${{ steps.build-container.outputs.image }}
tags: ${{ steps.build-container.outputs.tags }}
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Output Image URL
run: echo "🖼️ Image pushed to ${{ steps.push-to-registry.outputs.registry-paths }}"
# Push images for:
# - release (released or prereleased)
# - manual with a tag_name (adhoc builds can still be pushed by name)
- name: Build and push image
uses: docker/build-push-action@v7
with:
context: .
file: ./apps/web/infra/Containerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.tag_name != '') }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
provenance: false
- name: Output image refs
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.tag_name != '') }}
run: |
echo "🖼️ Pushed tags:"
echo "${{ steps.meta.outputs.tags }}"
echo
echo "Pull examples:"
if [[ "${{ github.event_name }}" == "release" && "${{ github.event.release.prerelease }}" == "false" ]]; then
echo " docker pull ${{ env.REGISTRY_IMAGE }}:latest"
fi
# Always available:
echo " docker pull ${{ env.REGISTRY_IMAGE }}:${{ github.event.release.tag_name || inputs.tag_name || format('adhoc-{0}', steps.gen.outputs.shortsha) }}"
echo " docker pull ${{ env.REGISTRY_IMAGE }}:sha-${{ steps.gen.outputs.shortsha }}"
- name: Explain no image push
if: ${{ !(github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.tag_name != '')) }}
run: echo "ℹ️ No image pushed (manual run without tag_name)."
+53 -31
View File
@@ -15,59 +15,81 @@ jobs:
update-stable-branch:
name: Update stable from latest release source
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0 # need full history for reset/push
fetch-depth: 0
fetch-tags: true # IMPORTANT: we need tags to resolve the release commit
- name: Configure Git author
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Determine source ref & SHA
- name: Determine source SHA (prefer tag)
id: meta
shell: bash
run: |
set -euo pipefail
SRC="${{ github.event.release.target_commitish }}"
if [ -z "$SRC" ] || ! git ls-remote --exit-code origin "refs/heads/$SRC" >/dev/null 2>&1; then
# Fallback to main if target_commitish is empty or not a branch
SRC="main"
TAG="${{ github.event.release.tag_name }}"
TARGET="${{ github.event.release.target_commitish || '' }}"
# Always ensure we have latest remote heads/tags
git fetch --tags --prune origin
SHA=""
SRC_DESC=""
# 1) Prefer the release tag commit
if [ -n "${TAG}" ] && git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
SHA="$(git rev-list -n1 "${TAG}")"
SRC_DESC="tag:${TAG}"
fi
echo "Using source branch: $SRC"
git fetch origin "$SRC":"refs/remotes/origin/$SRC" --prune
SHA="$(git rev-parse "origin/$SRC")"
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
echo "src=$SRC" >> "$GITHUB_OUTPUT"
# 2) Fall back to target_commitish if it points to a branch on origin
if [ -z "${SHA}" ] && [ -n "${TARGET}" ] && git ls-remote --exit-code --heads origin "${TARGET}" >/dev/null 2>&1; then
git fetch origin "${TARGET}:${TARGET}" --prune
SHA="$(git rev-parse "${TARGET}^{commit}")"
SRC_DESC="branch:${TARGET}"
fi
- name: Prepare local stable branch
# 3) Fall back to main if present
if [ -z "${SHA}" ] && git ls-remote --exit-code --heads origin "main" >/dev/null 2>&1; then
git fetch origin "main:main" --prune
SHA="$(git rev-parse "main^{commit}")"
SRC_DESC="branch:main"
fi
if [ -z "${SHA}" ]; then
echo "::error::Unable to resolve source commit from tag (${TAG}), target_commitish (${TARGET}), or main."
exit 1
fi
echo "Using source: ${SRC_DESC}"
echo "sha=${SHA}" >> "$GITHUB_OUTPUT"
echo "source=${SRC_DESC}" >> "$GITHUB_OUTPUT"
- name: Create/reset local stable to SHA
shell: bash
run: |
set -euo pipefail
# Ensure we have the remote stable ref if it exists
# Make sure we know if remote stable exists (non-fatal if not)
git fetch origin stable:refs/remotes/origin/stable || true
if git show-ref --verify --quiet refs/heads/stable; then
echo "Local stable exists."
elif git show-ref --verify --quiet refs/remotes/origin/stable; then
echo "Creating local stable tracking branch from remote."
git checkout -b stable --track origin/stable
else
echo "Creating new local stable branch at source SHA."
git checkout -b stable "${{ steps.meta.outputs.sha }}"
fi
- name: Reset stable to source SHA
run: |
git checkout stable
git reset --hard "${{ steps.meta.outputs.sha }}"
# Create or reset local stable in one command
git checkout -B stable "${{ steps.meta.outputs.sha }}"
git status --short --branch
- name: Push stable (force-with-lease)
run: |
# Safer than --force; refuses if remote moved unexpectedly
git push origin stable --force-with-lease
# Safer than --force; refuses if remote moved unexpectedly (protects against races)
REMOTE_STABLE_SHA="$(git rev-parse refs/remotes/origin/stable || echo '')"
if [ -z "$REMOTE_STABLE_SHA" ]; then
# If remote stable doesn't exist, just use --force-with-lease=stable (no SHA)
git push origin stable:stable --force-with-lease=stable
else
# Use the specific SHA for maximum safety
git push origin stable:stable --force-with-lease=stable:$REMOTE_STABLE_SHA
fi
+9
View File
@@ -9,3 +9,12 @@ __screenshots__*
npm/
.idea
**/LICENSE
.DS_Store
packages/protobufs/packages/ts/dist
.pnpm-store/
# Local dev certs
*.pem
*.crt
*.key
View File
+1
View File
@@ -0,0 +1 @@
pnpm lint-staged
-1
View File
@@ -1 +0,0 @@
@jsr:registry=https://npm.jsr.io
+1 -1
View File
@@ -1,3 +1,3 @@
{
"recommendations": ["bradlc.vscode-tailwindcss", "biomejs.biome"]
"recommendations": ["bradlc.vscode-tailwindcss", "biomejs.biome"]
}
+1 -4
View File
@@ -1,9 +1,6 @@
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
},
"search.exclude": {
"**/i18n/locales/*-*/**": true,
"**/i18n/locales/*-*/**": true
},
}
+65
View File
@@ -0,0 +1,65 @@
# Protobuf catch-up to firmware-current
> Draft PR description + the one decision for maintainers. This file is **untracked** —
> use it as the PR body, then delete it (or leave it, it won't be committed).
## What this does
- Syncs the vendored `.proto` sources in `packages/protobufs/meshtastic/` from ~v2.7.20 to
**firmware-current (v2.7.25 + 48 commits)** — +2 new files (`deviceonly_legacy`, `serial_hal`)
and additions across `config` / `module_config` / `mesh` / `admin` / `portnums` / `telemetry`.
- Regenerates the v2 TS bindings (`buf generate`).
- Makes the app consume the **workspace** protobufs (`workspace:*`) instead of the stale JSR
`@meshtastic/protobufs@2.7.20`, finishing the monorepo migration that was half-done
(`@meshtastic/core` was already `workspace:*`; protobufs was still on JSR).
- One breaking-change fix: `admin.proto` `nodedb_reset` changed `int32 → bool`, so
`MeshDevice.resetNodes()` now sends `value: true` (the oneof-case presence triggers the
reset; `true` preserves favorites through it).
## Free wins (dynamic enum dropdowns — no UI code)
New LoRa regions (ITU/EU amateur bands), modem presets (LONG_TURBO, LITE/NARROW/TINY_*),
~25 hardware names, `OLED_SH1107_ROTATED`, serial `LOG`/`LOGTEXT` — they flow into the
existing enum-bound `<select>`s automatically once the bindings regenerate.
## Breaking proto changes that DON'T break us (verified)
- `deviceonly.proto` `NodeInfoLite` restructure — core never imports `NodeInfoLite`.
- `channel.proto` `is_client_muted → is_muted` + `mute` removed — neither web nor core
references those fields yet.
## The one decision for maintainers — how to consume the protobufs
This changeset takes **Option A (workspace consumption):** rename the workspace package
`@meshtastic/protobufs-ws → @meshtastic/protobufs` (still `private`), point its `exports` at the
TS source, and depend on it via `workspace:*` from root + core.
- ✅ Monorepo is self-consuming and always firmware-current; no publish round-trip; matches
the already-migrated `@meshtastic/core`.
- ⚠️ Diverges from the JSR publish flow; the published JSR `@meshtastic/protobufs`
(latest 2.7.23) is no longer what the app builds against.
**Option B (canonical publish flow):** keep the package JSR-published — sync the `.proto`
sources here, publish a new `@meshtastic/protobufs` to JSR, then bump the root range.
- ✅ Stays on the established pipeline; one source of truth on JSR.
- ⚠️ Needs a JSR publish, and can't reach firmware-current until that release lands
(JSR tops out at 2.7.23, still behind firmware).
If you prefer **B**, everything except the 3 dependency-wiring edits still applies — the
`.proto` sync, the regen, and the `nodedbReset` fix are identical; only the root dep, the core
dep, and the protobufs `package.json` name/exports get swapped for a JSR publish + range bump.
## Regenerating bindings
```
pnpm --filter @meshtastic/protobufs gen
```
Output lands in `packages/protobufs/packages/ts/dist/` (gitignored).
## Verified in isolation (this branch only — no feature/demo code)
- `packages/core` typecheck: clean except 2 **pre-existing** `queue.ts` strict-catch errors.
- `packages/web` `vite build`: green.
- 36 config/module validation tests: pass.
+21 -23
View File
@@ -12,6 +12,9 @@ This monorepo consolidates the official [Meshtastic](https://meshtastic.org) web
interface and its supporting JavaScript libraries. It aims to provide a unified
development experience for interacting with Meshtastic devices.
> [!NOTE]
> You can find the main Meshtastic documentation at https://meshtastic.org/docs/introduction/.
### Projects within this Monorepo (`packages/`)
All projects are located within the `packages/` directory:
@@ -21,17 +24,19 @@ All projects are located within the `packages/` directory:
- **[Hosted version](https://client.meshtastic.org)**
- **`packages/core`:** Core functionality for Meshtastic JS.
- **`packages/transport-node`:** TCP Transport for the NodeJS runtime.
- **`packages/transport-node-serial`:** NodeJS Serial Transport for the NodeJS runtime.
- **`packages/transport-deno`:** TCP Transport for the Deno runtime.
- **`packages/transport-http`:** HTTP Transport.
- **`packages/transport-web-bluetooth`:** Web Bluetooth Transport.
- **`packages/transport-web-serial`:** Web Serial Transport.
- **`packages/protobufs`:** Git submodule containing Meshtastic’s shared protobuf definitions, used to generate and publish the JSR protobuf package.
All `Meshtastic JS` packages (core and transports) are published both to
[JSR](https://jsr.io/@meshtastic). [NPM](https://www.npmjs.com/org/meshtastic)
---
## Stats
## Repository activity
| Project | Repobeats |
| :------------- | :-------------------------------------------------------------------------------------------------------------------- |
@@ -72,6 +77,9 @@ Follow the installation instructions on their home page.
```
This command installs all necessary dependencies for all packages within the
monorepo.
3. **Install the Buf CLI**
Required for building `packages/protobufs`
https://buf.build/docs/cli/installation/
### Running Projects
@@ -85,28 +93,18 @@ If you encounter any issues, please report them in our
[issues tracker](https://github.com/meshtastic/web/issues). Your feedback helps
improve the stability of future releases
### Contributing
## Star history
We welcome contributions! Here’s how the deployment flow works for pull
requests:
<a href="https://star-history.com/#meshtastic/web&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=meshtastic/web&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=meshtastic/web&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=meshtastic/web&type=Date" width="100%" />
</picture>
</a>
- **Preview Deployments:**\
Every pull request automatically generates a preview deployment on Vercel.
This allows you and reviewers to easily preview changes before merging.
## Contributors
- **Staging Environment (`client-test`):**\
Once your PR is merged, your changes will be available on our staging site:
[client-test.meshtastic.org](https://client-test.meshtastic.org/).\
This environment supports rapid feature iteration and testing without
impacting the production site.
- **Production Releases:**\
At regular intervals, stable and fully tested releases are promoted to our
production site: [client.meshtastic.org](https://client.meshtastic.org/).\
This is the primary interface used by the public to connect with their
Meshtastic nodes.
Please review our
[Contribution Guidelines](https://github.com/meshtastic/web/blob/main/CONTRIBUTING.md)
before submitting a pull request. We appreciate your help in making the project
better!
<a href="https://github.com/meshtastic/web/graphs/contributors">
<img src="https://contrib.rocks/image?repo=meshtastic/web" width="100%"/>
</a>
+13
View File
@@ -0,0 +1,13 @@
{
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxfmt/configuration_schema.json",
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"ignorePatterns": [
"node_modules",
"dist",
"protobufs",
"**/locales/*-*/*.json",
"**/packages/ui/"
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
"plugins": ["react", "react-perf", "jsx-a11y", "typescript", "import"],
"rules": {
"no-debugger": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": "error",
"import/no-unused-modules": "error"
},
"ignorePatterns": [
"node_modules",
"dist",
"protobufs",
"**/locales/*-*/*.json",
"**/packages/ui/"
],
"overrides": [
{
"files": ["**/*.test.ts", "**/*.test.tsx", "**/__tests__/**/*.{ts,tsx}"],
"rules": {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off"
}
}
]
}
+41 -41
View File
@@ -37,14 +37,14 @@ podman run -d -p 8080:8080 --restart always --name Meshtastic-Web ghcr.io/meshta
Our release process follows these guidelines:
- **Versioning:** We use Semantic Versioning (`Major.Minor.Patch`).
- **Stable Releases:** Published around the beginning of each month (e.g.,
`v2.6.1`).
- **Pre-releases:** A pre-release is typically issued mid-month for testing and
early adoption.
- **Nightly Builds:** An experimental Docker image containing the latest
cutting-edge features and fixes is automatically built nightly from the `main`
branch.
- **Versioning:** We use Semantic Versioning (`Major.Minor.Patch`).
- **Stable Releases:** Published around the beginning of each month (e.g.,
`v2.6.1`).
- **Pre-releases:** A pre-release is typically issued mid-month for testing and
early adoption.
- **Nightly Builds:** An experimental Docker image containing the latest
cutting-edge features and fixes is automatically built nightly from the `main`
branch.
### Nightly Builds
@@ -57,20 +57,20 @@ podman run -d -p 8080:8080 --restart always --name Meshtastic-Web ghcr.io/meshta
> [!WARNING]
>
> - Nightly builds represent the latest development state and may contain
> breaking changes
> - These builds undergo automated testing but may be less stable than tagged
> release versions
> - Not recommended for production environments unless you are actively testing
> new features
> - No guarantee of backward compatibility between nightly builds
> - Nightly builds represent the latest development state and may contain
> breaking changes
> - These builds undergo automated testing but may be less stable than tagged
> release versions
> - Not recommended for production environments unless you are actively testing
> new features
> - No guarantee of backward compatibility between nightly builds
#### Version Information
Each nightly build is tagged with:
- The nightly tag for the latest build
- A specific SHA for build reproducibility
- The nightly tag for the latest build
- A specific SHA for build reproducibility
### Feedback
@@ -118,39 +118,39 @@ pnpm run package
Meshtastic Web uses pnpm as its package manager for several compelling
reasons:
- **Efficient Storage**: pnpm uses content-addressable storage, avoiding duplication
of packages across projects and saving significant disk space.
- **Fast Performance**: Faster package installation compared to other package
managers through symlinks and efficient dependency resolution.
- **Strict Dependency Management**: Prevents access to unlisted dependencies,
ensuring better project reliability and security.
- **Workspace Support**: Excellent monorepo support with workspaces for managing
multiple packages efficiently.
- **Reproducible Builds**: Lockfile ensures consistent builds across all
environments.
- **Efficient Storage**: pnpm uses content-addressable storage, avoiding duplication
of packages across projects and saving significant disk space.
- **Fast Performance**: Faster package installation compared to other package
managers through symlinks and efficient dependency resolution.
- **Strict Dependency Management**: Prevents access to unlisted dependencies,
ensuring better project reliability and security.
- **Workspace Support**: Excellent monorepo support with workspaces for managing
multiple packages efficiently.
- **Reproducible Builds**: Lockfile ensures consistent builds across all
environments.
### Contributing
We welcome contributions! Here’s how the deployment flow works for pull
requests:
- **Preview Deployments:**\
Every pull request automatically generates a preview deployment on Vercel.
This allows you and reviewers to easily preview changes before merging.
- **Preview Deployments:**\
Every pull request automatically generates a preview deployment on Vercel.
This allows you and reviewers to easily preview changes before merging.
- **Staging Environment (`client-test`):**\
Once your PR is merged, your changes will be available on our staging site:
[client-test.meshtastic.org](https://client-test.meshtastic.org/).\
This environment supports rapid feature iteration and testing without
impacting the production site.
- **Staging Environment (`client-test`):**\
Once your PR is merged, your changes will be available on our staging site:
[client-test.meshtastic.org](https://client-test.meshtastic.org/).\
This environment supports rapid feature iteration and testing without
impacting the production site.
- **Production Releases:**\
At regular intervals, stable and fully tested releases are promoted to our
production site: [client.meshtastic.org](https://client.meshtastic.org/).\
This is the primary interface used by the public to connect with their
Meshtastic nodes.
- **Production Releases:**\
At regular intervals, stable and fully tested releases are promoted to our
production site: [client.meshtastic.org](https://client.meshtastic.org/).\
This is the primary interface used by the public to connect with their
Meshtastic nodes.
Please review our
[Contribution Guidelines](https://github.com/meshtastic/web/blob/main/CONTRIBUTING.md)
[Contribution Guidelines](https://github.com/meshtastic/web/blob/main/packages/web/CONTRIBUTING.md)
before submitting a pull request. We appreciate your help in making the project
better!
@@ -11,16 +11,6 @@
<link rel="manifest" href="site.webmanifest" />
<link rel="mask-icon" href="logo_black.svg" color="#67ea94" />
<link
rel="stylesheet"
href="https://rsms.me/inter/inter.css"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@xz/fonts@1/serve/cascadia-code.min.css"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="src/index.css"
@@ -1,4 +1,4 @@
FROM nginx:1.27-alpine
FROM nginx:1.29.1-alpine-slim
RUN rm -r /usr/share/nginx/html \
&& mkdir -p /usr/share/nginx/html \
@@ -6,9 +6,9 @@ RUN rm -r /usr/share/nginx/html \
WORKDIR /usr/share/nginx/html
ADD ./dist .
ADD ./apps/web/dist .
COPY ./infra/default.conf /etc/nginx/conf.d/default.conf
COPY ./apps/web/infra/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080
+123
View File
@@ -0,0 +1,123 @@
{
"name": "meshtastic-web",
"version": "2.6.6-0",
"type": "module",
"description": "Meshtastic web client",
"license": "GPL-3.0-only",
"repository": {
"type": "git",
"url": "git+https://github.com/meshtastic/web.git"
},
"bugs": {
"url": "https://github.com/meshtastic/web/issues"
},
"homepage": "https://meshtastic.org",
"scripts": {
"preinstall": "npx only-allow pnpm",
"setup:certs": "mkcert localhost 127.0.0.1 ::1",
"build": "vite build",
"build:analyze": "BUNDLE_ANALYZE=true pnpm run build",
"lint": "oxlint",
"lint:fix": "oxlint --fix",
"format": "oxfmt --check .",
"format:fix": "oxfmt .",
"check": "pnpm lint && pnpm format",
"check:fix": "pnpm lint:fix && pnpm format:fix",
"dev": "vite",
"dev:https": "USE_HTTPS=true vite",
"test": "vitest",
"typecheck": "pnpm run tsc --noEmit",
"preview": "vite preview",
"docker:build": "docker build -t meshtastic-web:latest -f ./infra/Containerfile .",
"package": "gzipper c -i html,js,css,png,ico,svg,json,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ ."
},
"dependencies": {
"@hookform/resolvers": "^5.2.2",
"@meshtastic/core": "workspace:*",
"@meshtastic/transport-http": "workspace:*",
"@meshtastic/transport-web-bluetooth": "workspace:*",
"@meshtastic/transport-web-serial": "workspace:*",
"@noble/curves": "^1.9.2",
"@preact/signals-core": "^1.8.0",
"better-result": "^1.0.0",
"@radix-ui/react-accordion": "^1.2.13",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-menubar": "^1.1.17",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slider": "^1.3.6",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toast": "^1.2.15",
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-visually-hidden": "^1.2.3",
"@tailwindcss/vite": "^4.1.14",
"@tanstack/react-router": "^1.170.15",
"@tanstack/react-router-devtools": "^1.167.0",
"@tanstack/router-cli": "^1.167.17",
"@tanstack/router-devtools": "^1.167.0",
"@turf/turf": "^7.2.0",
"@types/node": "^24.7.0",
"@types/web-bluetooth": "^0.0.21",
"base64-js": "^1.5.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"crypto-random-string": "^5.0.0",
"i18next": "^26.3.1",
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^4.0.0",
"idb-keyval": "^6.2.2",
"immer": "^11.1.8",
"js-cookie": "^3.0.7",
"lucide-react": "^1.17.0",
"maplibre-gl": "5.8.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-error-boundary": "^6.0.0",
"react-hook-form": "^7.78.0",
"react-i18next": "^17.0.8",
"react-map-gl": "8.1.0",
"react-qrcode-logo": "^4.0.0",
"rfc4648": "^1.5.4",
"vite": "^7.3.5",
"vite-plugin-html": "^3.2.2",
"vite-plugin-pwa": "^1.3.0",
"zod": "^4.1.12",
"zustand": "5.0.8"
},
"devDependencies": {
"@tanstack/router-plugin": "^1.168.18",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/chrome": "^0.1.22",
"@types/geojson": "^7946.0.16",
"@types/js-cookie": "^3.0.6",
"@types/react": "^19.2.1",
"@types/react-dom": "^19.2.0",
"@types/serviceworker": "^0.0.158",
"@types/w3c-web-serial": "^1.0.8",
"@vitejs/plugin-basic-ssl": "^2.1.0",
"@vitejs/plugin-react": "^5.0.4",
"autoprefixer": "^10.4.21",
"gzipper": "^8.2.1",
"happy-dom": "^20.8.9",
"oxfmt": "^0.16.0",
"oxlint": "^1.41.0",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.14",
"tailwindcss-animate": "^1.0.7",
"tar": "^7.5.16",
"testing-library": "^0.0.2",
"typescript": "^5.9.3",
"vitest": "^4.1.8"
}
}

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.
Binary file not shown.
@@ -0,0 +1,71 @@
{
"page": {
"sectionLabel": "Channels",
"channelName": "Channel: {{channelName}}",
"broadcastLabel": "Primary",
"channelIndex": "Ch {{index}}",
"import": "Import",
"export": "Export"
},
"validation": {
"pskInvalid": "Please enter a valid {{bits}} bit PSK."
},
"settings": {
"label": "Channel Settings",
"description": "Crypto, MQTT & misc settings"
},
"role": {
"label": "Role",
"description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed",
"options": {
"primary": "PRIMARY",
"disabled": "DISABLED",
"secondary": "SECONDARY"
}
},
"psk": {
"label": "Pre-Shared Key",
"description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)",
"generate": "Generate"
},
"name": {
"label": "Name",
"description": "A unique name for the channel <12 bytes, leave blank for default"
},
"uplinkEnabled": {
"label": "Uplink Enabled",
"description": "Send messages from the local mesh to MQTT"
},
"downlinkEnabled": {
"label": "Downlink Enabled",
"description": "Send messages from MQTT to the local mesh"
},
"positionPrecision": {
"label": "Location",
"description": "The precision of the location to share with the channel. Can be disabled.",
"options": {
"none": "Do not share location",
"precise": "Precise Location",
"metric_km23": "Within 23 kilometers",
"metric_km12": "Within 12 kilometers",
"metric_km5_8": "Within 5.8 kilometers",
"metric_km2_9": "Within 2.9 kilometers",
"metric_km1_5": "Within 1.5 kilometers",
"metric_m700": "Within 700 meters",
"metric_m350": "Within 350 meters",
"metric_m200": "Within 200 meters",
"metric_m90": "Within 90 meters",
"metric_m50": "Within 50 meters",
"imperial_mi15": "Within 15 miles",
"imperial_mi7_3": "Within 7.3 miles",
"imperial_mi3_6": "Within 3.6 miles",
"imperial_mi1_8": "Within 1.8 miles",
"imperial_mi0_9": "Within 0.9 miles",
"imperial_mi0_5": "Within 0.5 miles",
"imperial_mi0_2": "Within 0.2 miles",
"imperial_ft600": "Within 600 feet",
"imperial_ft300": "Within 300 feet",
"imperial_ft150": "Within 150 feet"
}
}
}
@@ -15,7 +15,6 @@
"messages": "Messages",
"map": "Map",
"config": "Config",
"channels": "Channels",
"nodes": "Nodes"
}
},
@@ -45,7 +44,8 @@
"label": "Debug",
"command": {
"reconfigure": "Reconfigure",
"clearAllStoredMessages": "Clear All Stored Message"
"clearAllStoredMessages": "Clear All Stored Message",
"clearAllStores": "Clear All Local Storage"
}
}
}
@@ -0,0 +1,165 @@
{
"button": {
"apply": "Apply",
"addConnection": "Add Connection",
"saveConnection": "Save connection",
"backupKey": "Backup Key",
"cancel": "Cancel",
"connect": "Connect",
"clearMessages": "Clear Messages",
"close": "Close",
"confirm": "Confirm",
"delete": "Delete",
"dismiss": "Dismiss",
"download": "Download",
"disconnect": "Disconnect",
"export": "Export",
"generate": "Generate",
"regenerate": "Regenerate",
"import": "Import",
"message": "Message",
"now": "Now",
"ok": "OK",
"print": "Print",
"remove": "Remove",
"requestNewKeys": "Request New Keys",
"requestPosition": "Request Position",
"reset": "Reset",
"retry": "Retry",
"save": "Save",
"setDefault": "Set as default",
"unsetDefault": "Unset default",
"scanQr": "Scan QR Code",
"traceRoute": "Trace Route",
"submit": "Submit"
},
"app": {
"title": "Meshtastic",
"fullTitle": "Meshtastic Web Client"
},
"loading": "Loading...",
"unit": {
"cps": "CPS",
"dbm": "dBm",
"hertz": "Hz",
"hop": {
"one": "Hop",
"plural": "Hops"
},
"hopsAway": {
"one": "{{count}} hop away",
"plural": "{{count}} hops away",
"unknown": "Unknown hops away"
},
"megahertz": "MHz",
"kilohertz": "kHz",
"raw": "raw",
"meter": {
"one": "Meter",
"plural": "Meters",
"suffix": "m"
},
"kilometer": {
"one": "Kilometer",
"plural": "Kilometers",
"suffix": "km"
},
"minute": {
"one": "Minute",
"plural": "Minutes"
},
"hour": {
"one": "Hour",
"plural": "Hours"
},
"millisecond": {
"one": "Millisecond",
"plural": "Milliseconds",
"suffix": "ms"
},
"second": {
"one": "Second",
"plural": "Seconds"
},
"day": {
"one": "Day",
"plural": "Days",
"today": "Today",
"yesterday": "Yesterday"
},
"month": {
"one": "Month",
"plural": "Months"
},
"year": {
"one": "Year",
"plural": "Years"
},
"snr": "SNR",
"volt": {
"one": "Volt",
"plural": "Volts",
"suffix": "V"
},
"record": {
"one": "Records",
"plural": "Records"
},
"degree": {
"one": "Degree",
"plural": "Degrees",
"suffix": "°"
}
},
"security": {
"0bit": "Empty",
"8bit": "8 bit",
"128bit": "128 bit",
"256bit": "256 bit"
},
"unknown": {
"longName": "Unknown",
"shortName": "UNK",
"notAvailable": "N/A",
"num": "??"
},
"nodeUnknownPrefix": "!",
"unset": "UNSET",
"fallbackName": "Meshtastic {{last4}}",
"node": "Node",
"formValidation": {
"unsavedChanges": "Unsaved changes",
"tooBig": {
"string": "Too long, expected less than or equal to {{maximum}} characters.",
"number": "Too big, expected a number smaller than or equal to {{maximum}}.",
"bytes": "Too big, expected less than or equal to {{params.maximum}} bytes."
},
"tooSmall": {
"string": "Too short, expected more than or equal to {{minimum}} characters.",
"number": "Too small, expected a number larger than or equal to {{minimum}}."
},
"invalidFormat": {
"ipv4": "Invalid format, expected an IPv4 address.",
"key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)."
},
"invalidType": {
"number": "Invalid type, expected a number."
},
"pskLength": {
"0bit": "Key is required to be empty.",
"8bit": "Key is required to be an 8 bit pre-shared key (PSK).",
"128bit": "Key is required to be a 128 bit pre-shared key (PSK).",
"256bit": "Key is required to be a 256 bit pre-shared key (PSK)."
},
"required": {
"generic": "This field is required.",
"managed": "At least one admin key is requred if the node is managed.",
"key": "Key is required."
},
"invalidOverrideFreq": {
"number": "Invalid format, expected a value in the range 410-930 MHz or 0 (use default)."
}
},
"yes": "Yes",
"no": "No"
}
@@ -0,0 +1,458 @@
{
"page": {
"title": "Settings",
"tabUser": "Карыстальнік",
"tabChannels": "Каналы",
"tabBluetooth": "Bluetooth",
"tabDevice": "Прылада",
"tabDisplay": "Экран",
"tabLora": "LoRa",
"tabNetwork": "Сетка",
"tabPosition": "Месцазнаходжанне",
"tabPower": "Power",
"tabSecurity": "Бяспека"
},
"sidebar": {
"label": "Configuration"
},
"device": {
"title": "Device Settings",
"description": "Settings for the device",
"buttonPin": {
"description": "Button pin override",
"label": "Button Pin"
},
"buzzerPin": {
"description": "Buzzer pin override",
"label": "Buzzer Pin"
},
"disableTripleClick": {
"description": "Disable triple click",
"label": "Disable Triple Click"
},
"doubleTapAsButtonPress": {
"description": "Treat double tap as button press",
"label": "Double Tap as Button Press"
},
"ledHeartbeatDisabled": {
"description": "Disable default blinking LED",
"label": "LED Heartbeat Disabled"
},
"nodeInfoBroadcastInterval": {
"description": "How often to broadcast node info",
"label": "Node Info Broadcast Interval"
},
"posixTimezone": {
"description": "The POSIX timezone string for the device",
"label": "POSIX Timezone"
},
"rebroadcastMode": {
"description": "How to handle rebroadcasting",
"label": "Rebroadcast Mode"
},
"role": {
"description": "What role the device performs on the mesh",
"label": "Role"
}
},
"bluetooth": {
"title": "Bluetooth Settings",
"description": "Settings for the Bluetooth module",
"note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.",
"enabled": {
"description": "Enable or disable Bluetooth",
"label": "Уключана"
},
"pairingMode": {
"description": "Pin selection behaviour.",
"label": "Pairing mode"
},
"pin": {
"description": "Pin to use when pairing",
"label": "Pin"
}
},
"display": {
"description": "Settings for the device display",
"title": "Display Settings",
"headingBold": {
"description": "Bolden the heading text",
"label": "Bold Heading"
},
"carouselDelay": {
"description": "How fast to cycle through windows",
"label": "Carousel Delay"
},
"compassNorthTop": {
"description": "Fix north to the top of compass",
"label": "Compass North Top"
},
"displayMode": {
"description": "Screen layout variant",
"label": "Display Mode"
},
"displayUnits": {
"description": "Display metric or imperial units",
"label": "Display Units"
},
"flipScreen": {
"description": "Flip display 180 degrees",
"label": "Flip Screen"
},
"gpsDisplayUnits": {
"description": "Coordinate display format",
"label": "GPS Display Units"
},
"oledType": {
"description": "Type of OLED screen attached to the device",
"label": "OLED Type"
},
"screenTimeout": {
"description": "Turn off the display after this long",
"label": "Screen Timeout"
},
"twelveHourClock": {
"description": "Use 12-hour clock format",
"label": "12-Hour Clock"
},
"wakeOnTapOrMotion": {
"description": "Wake the device on tap or motion",
"label": "Wake on Tap or Motion"
}
},
"lora": {
"title": "Mesh Settings",
"description": "Settings for the LoRa mesh",
"bandwidth": {
"description": "Channel bandwidth in kHz",
"label": "Bandwidth"
},
"boostedRxGain": {
"description": "Boosted RX gain",
"label": "Boosted RX Gain"
},
"codingRate": {
"description": "The denominator of the coding rate",
"label": "Coding Rate"
},
"frequencyOffset": {
"description": "Frequency offset to correct for crystal calibration errors",
"label": "Frequency Offset"
},
"frequencySlot": {
"description": "LoRa frequency channel number",
"label": "Frequency Slot"
},
"hopLimit": {
"description": "Maximum number of hops",
"label": "Hop Limit"
},
"ignoreMqtt": {
"description": "Don't forward MQTT messages over the mesh",
"label": "Ignore MQTT"
},
"modemPreset": {
"description": "Modem preset to use",
"label": "Modem Preset"
},
"okToMqtt": {
"description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT",
"label": "OK to MQTT"
},
"overrideDutyCycle": {
"description": "Override Duty Cycle",
"label": "Override Duty Cycle"
},
"overrideFrequency": {
"description": "Override frequency",
"label": "Override Frequency"
},
"region": {
"description": "Sets the region for your node",
"label": "Рэгіён"
},
"spreadingFactor": {
"description": "Indicates the number of chirps per symbol",
"label": "Spreading Factor"
},
"transmitEnabled": {
"description": "Enable/Disable transmit (TX) from the LoRa radio",
"label": "Transmit Enabled"
},
"transmitPower": {
"description": "Max transmit power",
"label": "Transmit Power"
},
"usePreset": {
"description": "Use one of the predefined modem presets",
"label": "Use Preset"
},
"meshSettings": {
"description": "Settings for the LoRa mesh",
"label": "Mesh Settings"
},
"waveformSettings": {
"description": "Settings for the LoRa waveform",
"label": "Waveform Settings"
},
"radioSettings": {
"label": "Radio Settings",
"description": "Settings for the LoRa radio"
}
},
"network": {
"title": "WiFi Config",
"description": "WiFi radio configuration",
"note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.",
"addressMode": {
"description": "Address assignment selection",
"label": "Address Mode"
},
"dns": {
"description": "DNS Server",
"label": "DNS"
},
"ethernetEnabled": {
"description": "Enable or disable the Ethernet port",
"label": "Уключана"
},
"gateway": {
"description": "Default Gateway",
"label": "Gateway"
},
"ip": {
"description": "IP Address",
"label": "IP"
},
"psk": {
"description": "Network password",
"label": "PSK"
},
"ssid": {
"description": "Network name",
"label": "SSID"
},
"subnet": {
"description": "Subnet Mask",
"label": "Subnet"
},
"wifiEnabled": {
"description": "Enable or disable the WiFi radio",
"label": "Уключана"
},
"meshViaUdp": {
"label": "Mesh via UDP"
},
"ntpServer": {
"label": "NTP Server"
},
"rsyslogServer": {
"label": "Rsyslog Server"
},
"ethernetConfigSettings": {
"description": "Ethernet port configuration",
"label": "Ethernet Config"
},
"ipConfigSettings": {
"description": "IP configuration",
"label": "IP Config"
},
"ntpConfigSettings": {
"description": "NTP configuration",
"label": "NTP Config"
},
"rsyslogConfigSettings": {
"description": "Rsyslog configuration",
"label": "Rsyslog Config"
},
"udpConfigSettings": {
"description": "UDP over Mesh configuration",
"label": "UDP Config"
}
},
"position": {
"title": "Position Settings",
"description": "Settings for the position module",
"broadcastInterval": {
"description": "How often your position is sent out over the mesh",
"label": "Broadcast Interval"
},
"enablePin": {
"description": "GPS module enable pin override",
"label": "Enable Pin"
},
"fixedPosition": {
"description": "Don't report GPS position, but a manually-specified one",
"label": "Fixed Position"
},
"gpsMode": {
"description": "Configure whether device GPS is Enabled, Disabled, or Not Present",
"label": "GPS Mode"
},
"gpsUpdateInterval": {
"description": "How often a GPS fix should be acquired",
"label": "GPS Update Interval"
},
"positionFlags": {
"description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.",
"label": "Position Flags"
},
"receivePin": {
"description": "GPS module RX pin override",
"label": "Receive Pin"
},
"smartPositionEnabled": {
"description": "Only send position when there has been a meaningful change in location",
"label": "Enable Smart Position"
},
"smartPositionMinDistance": {
"description": "Minimum distance (in meters) that must be traveled before a position update is sent",
"label": "Smart Position Minimum Distance"
},
"smartPositionMinInterval": {
"description": "Minimum interval (in seconds) that must pass before a position update is sent",
"label": "Smart Position Minimum Interval"
},
"transmitPin": {
"description": "GPS module TX pin override",
"label": "Transmit Pin"
},
"intervalsSettings": {
"description": "How often to send position updates",
"label": "Intervals"
},
"flags": {
"placeholder": "Select position flags...",
"altitude": "Altitude",
"altitudeGeoidalSeparation": "Altitude Geoidal Separation",
"altitudeMsl": "Altitude is Mean Sea Level",
"dop": "Dilution of precision (DOP) PDOP used by default",
"hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP",
"numSatellites": "Number of satellites",
"sequenceNumber": "Sequence number",
"timestamp": "Timestamp",
"unset": "Unset",
"vehicleHeading": "Vehicle heading",
"vehicleSpeed": "Vehicle speed"
}
},
"power": {
"adcMultiplierOverride": {
"description": "Used for tweaking battery voltage reading",
"label": "ADC Multiplier Override ratio"
},
"ina219Address": {
"description": "Address of the INA219 battery monitor",
"label": "INA219 Address"
},
"lightSleepDuration": {
"description": "How long the device will be in light sleep for",
"label": "Light Sleep Duration"
},
"minimumWakeTime": {
"description": "Minimum amount of time the device will stay awake for after receiving a packet",
"label": "Minimum Wake Time"
},
"noConnectionBluetoothDisabled": {
"description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long",
"label": "No Connection Bluetooth Disabled"
},
"powerSavingEnabled": {
"description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.",
"label": "Enable power saving mode"
},
"shutdownOnBatteryDelay": {
"description": "Automatically shutdown node after this long when on battery, 0 for indefinite",
"label": "Shutdown on battery delay"
},
"superDeepSleepDuration": {
"description": "How long the device will be in super deep sleep for",
"label": "Super Deep Sleep Duration"
},
"powerConfigSettings": {
"description": "Settings for the power module",
"label": "Power Config"
},
"sleepSettings": {
"description": "Sleep settings for the power module",
"label": "Sleep Settings"
}
},
"security": {
"description": "Settings for the Security configuration",
"title": "Security Settings",
"button_backupKey": "Backup Key",
"adminChannelEnabled": {
"description": "Allow incoming device control over the insecure legacy admin channel",
"label": "Allow Legacy Admin"
},
"enableDebugLogApi": {
"description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth",
"label": "Enable Debug Log API"
},
"managed": {
"description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.",
"label": "Managed"
},
"privateKey": {
"description": "Used to create a shared key with a remote device",
"label": "Private Key"
},
"publicKey": {
"description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key",
"label": "Public Key"
},
"primaryAdminKey": {
"description": "The primary public key authorized to send admin messages to this node",
"label": "Primary Admin Key"
},
"secondaryAdminKey": {
"description": "The secondary public key authorized to send admin messages to this node",
"label": "Secondary Admin Key"
},
"serialOutputEnabled": {
"description": "Serial Console over the Stream API",
"label": "Serial Output Enabled"
},
"tertiaryAdminKey": {
"description": "The tertiary public key authorized to send admin messages to this node",
"label": "Tertiary Admin Key"
},
"adminSettings": {
"description": "Settings for Admin",
"label": "Admin Settings"
},
"loggingSettings": {
"description": "Settings for Logging",
"label": "Logging Settings"
}
},
"user": {
"title": "User Settings",
"description": "Configure your device name and identity settings",
"longName": {
"label": "Long Name",
"description": "Your full display name (1-40 characters)",
"validation": {
"min": "Long name must be at least 1 character",
"max": "Long name must be at most 40 characters"
}
},
"shortName": {
"label": "Short Name",
"description": "Your abbreviated name (2-4 characters)",
"validation": {
"min": "Short name must be at least 2 characters",
"max": "Short name must be at most 4 characters"
}
},
"isUnmessageable": {
"label": "Unmessageable",
"description": "Used to identify unmonitored or infrastructure nodes so that messaging is not available to nodes that will never respond."
},
"isLicensed": {
"label": "Licensed amateur radio (HAM)",
"description": "Enable if you are a licensed amateur radio operator, enabling this option disables encryption and is not compatible with the default Meshtastic network."
}
}
}
@@ -0,0 +1,34 @@
{
"page": {
"title": "Connect to a Meshtastic device",
"description": "Add a device connection via HTTP, Bluetooth, or Serial. Your saved connections will be saved in your browser."
},
"connectionType_ble": "BLE",
"connectionType_serial": "Serial",
"connectionType_network": "Сетка",
"deleteConnection": "Delete connection",
"areYouSure": "This will remove {{name}}. You canot undo this action.",
"moreActions": "More actions",
"noConnections": {
"title": "No connections yet.",
"description": "Create your first connection. It will connect immediately and be saved for later."
},
"lastConnectedAt": "Last connected: {{date}}",
"neverConnected": "Never connected",
"toasts": {
"connected": "Злучаны",
"nowConnected": "{{name}} is now connected",
"nowDisconnected": "{{name}} are now disconnecte",
"disconnected": "Адлучана",
"failed": "Failed to connect",
"checkConnetion": "Check your device or settings and try again",
"defaultSet": "Default set",
"defaultConnection": "Default connection is now {{nameisconnected}}",
"deleted": "Deleted",
"deletedByName": "{{name}} was removed",
"pickConnectionAgain": "Could not connect. You may need to reselect the device/port.",
"added": "Connection added",
"savedByName": "{{name}} saved.",
"savedCantConnect": "The connection was saved but could not connect."
}
}
@@ -122,7 +122,7 @@
"title": "Mesh Settings",
"description": "Settings for the LoRa mesh",
"bandwidth": {
"description": "Channel bandwidth in MHz",
"description": "Channel bandwidth in kHz",
"label": "Bandwidth"
},
"boostedRxGain": {
@@ -0,0 +1,238 @@
{
"deleteMessages": {
"description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?",
"title": "Clear All Messages"
},
"import": {
"description": "The current LoRa configuration will be overridden.",
"error": {
"invalidUrl": "Invalid Meshtastic URL"
},
"channelPrefix": "Channel: ",
"primary": "Primary ",
"doNotImport": "No not import",
"channelName": "Назва",
"channelSlot": "Slot",
"channelSetUrl": "Channel Set/QR Code URL",
"useLoraConfig": "Import LoRa Config",
"presetDescription": "The current LoRa Config will be replaced.",
"title": "Import Channel Set"
},
"locationResponse": {
"title": "Location: {{identifier}}",
"altitude": "Altitude: ",
"coordinates": "Coordinates: ",
"noCoordinates": "No Coordinates"
},
"pkiRegenerateDialog": {
"title": "Regenerate Pre-Shared Key?",
"description": "Are you sure you want to regenerate the pre-shared key?",
"regenerate": "Regenerate"
},
"addConnection": {
"title": "Add connection",
"description": "Choose a connection type and fill in the details",
"validation": {
"requiresWebBluetooth": "This connection type requires <0>Web Bluetooth</0>. Please use a supported browser, like Chrome or Edge.",
"requiresWebSerial": "This connection type requires <0>Web Serial</0>. Please use a supported browser, like Chrome or Edge.",
"requiresSecureContext": "This application requires a <0>secure context</0>. Please connect using HTTPS or localhost.",
"additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context</0>. Please connect using HTTPS or localhost."
},
"bluetoothConnection": {
"namePlaceholder": "My Bluetooth Node",
"supported": {
"title": "Web Bluetooth supported"
},
"notSupported": {
"title": "Web Bluetooth not supported",
"description": "Your browser or device does not support Web Bluetooth"
},
"short": "BT: {{deviceName}}",
"long": "Bluetooth Device",
"device": "Прылада",
"selectDevice": "Select device",
"selected": "Bluetooth device selected",
"notSelected": "No device selected",
"helperText": "Uses the Meshtastic Bluetooth service for discovery."
},
"serialConnection": {
"namePlaceholder": "My Serial Node",
"helperText": "Selecting a port grants permission so the app can open it to connect.",
"supported": {
"title": "Web Serial supported"
},
"notSupported": {
"title": "Web Serial not supported",
"description": "Your browser or device does not support Web Serial"
},
"portSelected": {
"title": "Serial port selected",
"description": "Port permissions granted."
},
"port": "Port",
"selectPort": "Select port",
"deviceName": "USB {{vendorId}}:{{productId}}",
"notSelected": "No port selected"
},
"httpConnection": {
"namePlaceholder": "My HTTP Node",
"inputPlaceholder": "192.168.1.10 or meshtastic.local",
"heading": "URL or IP",
"useHttps": "Use HTTPS",
"invalidUrl": {
"title": "Invalid URL",
"description": "Please enter a valid HTTP or HTTPS URL."
},
"connectionTest": {
"description": "Test the connetion before saving to verify the device is reachable.",
"button": {
"loading": "Testing...",
"label": "Test connection"
},
"reachable": "Reachable",
"notReachable": "Not reachable",
"success": {
"title": "Connection test successful",
"description": "The device appears to be reachable."
},
"failure": {
"title": "Connection test failed",
"description": "Could not reach the device. Check the URL and try again."
}
}
}
},
"nodeDetails": {
"message": "Message",
"requestPosition": "Request Position",
"traceRoute": "Trace Route",
"airTxUtilization": "Air TX utilization",
"allRawMetrics": "All Raw Metrics:",
"batteryLevel": "Battery level",
"channelUtilization": "Channel utilization",
"details": "Details:",
"deviceMetrics": "Device Metrics:",
"hardware": "Hardware: ",
"lastHeard": "Last Heard: ",
"nodeHexPrefix": "Node Hex: ",
"nodeNumber": "Node Number: ",
"position": "Position:",
"role": "Role: ",
"uptime": "Uptime: ",
"voltage": "Voltage",
"title": "Node Details for {{identifier}}",
"ignoreNode": "Ignore node",
"removeNode": "Remove node",
"unignoreNode": "Unignore node",
"security": "Security:",
"publicKey": "Public Key: ",
"messageable": "Messageable: ",
"KeyManuallyVerifiedTrue": "Public Key has been manually verified",
"KeyManuallyVerifiedFalse": "Public Key is not manually verified"
},
"pkiBackup": {
"loseKeysWarning": "If you lose your keys, you will need to reset your device.",
"secureBackup": "Its important to backup your public and private keys and store your backup securely!",
"footer": "=== END OF KEYS ===",
"header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===",
"privateKey": "Private Key:",
"publicKey": "Public Key:",
"fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt",
"title": "Backup Keys"
},
"pkiBackupReminder": {
"description": "We recommend backing up your key data regularly. Would you like to back up now?",
"title": "Backup Reminder",
"remindLaterPrefix": "Remind me in",
"remindNever": "Never remind me",
"backupNow": "Back up now"
},
"pkiRegenerate": {
"description": "Are you sure you want to regenerate key pair?",
"title": "Regenerate Key Pair"
},
"qr": {
"addChannels": "Add Channels",
"replaceChannels": "Replace Channels",
"description": "The current LoRa configuration will also be shared.",
"sharableUrl": "Sharable URL",
"title": "Generate QR Code"
},
"reboot": {
"title": "Reboot device",
"description": "Reboot now or schedule a reboot of the connected node. Optionally, you can choose to reboot into OTA (Over-the-Air) mode.",
"ota": "Reboot into OTA mode",
"enterDelay": "Enter delay",
"scheduled": "Reboot has been scheduled",
"schedule": "Schedule reboot",
"now": "Reboot now",
"cancel": "Cancel scheduled reboot"
},
"refreshKeys": {
"description": {
"acceptNewKeys": "This will remove the node from device and request new keys.",
"keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.",
"unableToSendDmPrefix": "Your node is unable to send a direct message to node: "
},
"acceptNewKeys": "Accept New Keys",
"title": "Keys Mismatch - {{identifier}}"
},
"removeNode": {
"description": "Are you sure you want to remove this Node?",
"title": "Remove Node?"
},
"shutdown": {
"title": "Schedule Shutdown",
"description": "Turn off the connected node after x minutes."
},
"traceRoute": {
"routeToDestination": "Route to destination:",
"routeBack": "Route back:"
},
"tracerouteResponse": {
"title": "Traceroute: {{identifier}}"
},
"unsafeRoles": {
"confirmUnderstanding": "Yes, I know what I'm doing",
"conjunction": " and the blog post about ",
"postamble": " and understand the implications of changing the role.",
"preamble": "I have read the ",
"choosingRightDeviceRole": "Choosing The Right Device Role",
"deviceRoleDocumentation": "Device Role Documentation",
"title": "Are you sure?"
},
"managedMode": {
"confirmUnderstanding": "Yes, I know what I'm doing",
"title": "Are you sure?",
"description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration."
},
"clientNotification": {
"title": "Client Notification",
"TraceRoute can only be sent once every 30 seconds": "TraceRoute can only be sent once every 30 seconds",
"Compromised keys were detected and regenerated.": "Compromised keys were detected and regenerated."
},
"resetNodeDb": {
"title": "Reset Node Database",
"description": "This will clear all nodes from the connected device's node database and clear all message history in the client. This cannot be undone. Are you sure you want to continue?",
"confirm": "Reset Node Database",
"failedTitle": "There was an error resetting the Node DB. Please try again."
},
"clearAllStores": {
"title": "Clear All Local Storage",
"description": "This will clear all locally stored data, including message history and node databases for all previously connected devices. This will require you to reconnect to your node once complete and cannot be undone. Are you sure you want to continue?",
"confirm": "Clear all local storage",
"failedTitle": "There was an error clearing local storage. Please try again."
},
"factoryResetDevice": {
"title": "Factory Reset Device",
"description": "This will factory reset the connected device, erasing all configurations and data on the device as well as all nodes and messages saved in the client. This cannot be undone. Are you sure you want to continue?",
"confirm": "Factory Reset Device",
"failedTitle": "There was an error performing the factory reset. Please try again."
},
"factoryResetConfig": {
"title": "Factory Reset Config",
"description": "This will factory reset the configuration on the connected device, erasing all configurations on the device. This cannot be undone. Are you sure you want to continue?",
"confirm": "Factory Reset Config",
"failedTitle": "There was an error performing the factory reset. Please try again."
}
}
@@ -0,0 +1,38 @@
{
"maplibre": {
"GeolocateControl.FindMyLocation": "Find my location",
"NavigationControl.ZoomIn": "Zoom in",
"NavigationControl.ZoomOut": "Zoom out",
"CooperativeGesturesHandler.WindowsHelpText": "Use Ctrl + scroll to zoom the map",
"CooperativeGesturesHandler.MacHelpText": "Use ⌘ + scroll to zoom the map",
"CooperativeGesturesHandler.MobileHelpText": "Use two fingers to move the map"
},
"layerTool": {
"nodeMarkers": "Show nodes",
"directNeighbors": "Show direct connections",
"remoteNeighbors": "Show remote connections",
"positionPrecision": "Show position precision",
"traceroutes": "Show traceroutes",
"waypoints": "Show waypoints"
},
"mapMenu": {
"locateAria": "Locate my node",
"layersAria": "Change map style"
},
"waypointDetail": {
"edit": "Змяніць",
"description": "Description:",
"createdBy": "Edited by:",
"createdDate": "Created:",
"updated": "Updated:",
"expires": "Expires:",
"distance": "Distance:",
"bearing": "Absolute bearing:",
"lockedTo": "Locked by:",
"latitude": "Latitude:",
"longitude": "Longitude:"
},
"myNode": {
"tooltip": "This device"
}
}
@@ -0,0 +1,39 @@
{
"page": {
"title": "Messages: {{chatName}}",
"placeholder": "Enter Message"
},
"emptyState": {
"title": "Select a Chat",
"text": "No messages yet."
},
"selectChatPrompt": {
"text": "Select a channel or node to start messaging."
},
"sendMessage": {
"placeholder": "Enter your message here...",
"sendButton": "Send"
},
"actionsMenu": {
"addReactionLabel": "Add Reaction",
"replyLabel": "Reply"
},
"deliveryStatus": {
"delivered": {
"label": "Message delivered",
"displayText": "Message delivered"
},
"failed": {
"label": "Message delivery failed",
"displayText": "Delivery failed"
},
"unknown": {
"label": "Message status unknown",
"displayText": "Unknown state"
},
"waiting": {
"label": "Sending message",
"displayText": "Waiting for delivery"
}
}
}
@@ -0,0 +1,448 @@
{
"page": {
"tabAmbientLighting": "Ambient Lighting",
"tabAudio": "Audio",
"tabCannedMessage": "Canned",
"tabDetectionSensor": "Detection Sensor",
"tabExternalNotification": "Ext Notif",
"tabMqtt": "MQTT",
"tabNeighborInfo": "Neighbor Info",
"tabPaxcounter": "Paxcounter",
"tabRangeTest": "Range Test",
"tabSerial": "Serial",
"tabStoreAndForward": "S&F",
"tabTelemetry": "Telemetry"
},
"ambientLighting": {
"title": "Ambient Lighting Settings",
"description": "Settings for the Ambient Lighting module",
"ledState": {
"label": "LED State",
"description": "Sets LED to on or off"
},
"current": {
"label": "Current",
"description": "Sets the current for the LED output. Default is 10"
},
"red": {
"label": "Red",
"description": "Sets the red LED level. Values are 0-255"
},
"green": {
"label": "Green",
"description": "Sets the green LED level. Values are 0-255"
},
"blue": {
"label": "Blue",
"description": "Sets the blue LED level. Values are 0-255"
}
},
"audio": {
"title": "Audio Settings",
"description": "Settings for the Audio module",
"codec2Enabled": {
"label": "Codec 2 Enabled",
"description": "Enable Codec 2 audio encoding"
},
"pttPin": {
"label": "PTT Pin",
"description": "GPIO pin to use for PTT"
},
"bitrate": {
"label": "Bitrate",
"description": "Bitrate to use for audio encoding"
},
"i2sWs": {
"label": "i2S WS",
"description": "GPIO pin to use for i2S WS"
},
"i2sSd": {
"label": "i2S SD",
"description": "GPIO pin to use for i2S SD"
},
"i2sDin": {
"label": "i2S DIN",
"description": "GPIO pin to use for i2S DIN"
},
"i2sSck": {
"label": "i2S SCK",
"description": "GPIO pin to use for i2S SCK"
}
},
"cannedMessage": {
"title": "Canned Message Settings",
"description": "Settings for the Canned Message module",
"moduleEnabled": {
"label": "Module Enabled",
"description": "Enable Canned Message"
},
"rotary1Enabled": {
"label": "Rotary Encoder #1 Enabled",
"description": "Enable the rotary encoder"
},
"inputbrokerPinA": {
"label": "Encoder Pin A",
"description": "GPIO Pin Value (1-39) For encoder port A"
},
"inputbrokerPinB": {
"label": "Encoder Pin B",
"description": "GPIO Pin Value (1-39) For encoder port B"
},
"inputbrokerPinPress": {
"label": "Encoder Pin Press",
"description": "GPIO Pin Value (1-39) For encoder Press"
},
"inputbrokerEventCw": {
"label": "Clockwise event",
"description": "Select input event."
},
"inputbrokerEventCcw": {
"label": "Counter Clockwise event",
"description": "Select input event."
},
"inputbrokerEventPress": {
"label": "Press event",
"description": "Select input event"
},
"updown1Enabled": {
"label": "Up Down enabled",
"description": "Enable the up / down encoder"
},
"allowInputSource": {
"label": "Allow Input Source",
"description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'"
},
"sendBell": {
"label": "Send Bell",
"description": "Sends a bell character with each message"
}
},
"detectionSensor": {
"title": "Detection Sensor Settings",
"description": "Settings for the Detection Sensor module",
"enabled": {
"label": "Enabled",
"description": "Enable or disable Detection Sensor Module"
},
"minimumBroadcastSecs": {
"label": "Minimum Broadcast Seconds",
"description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected"
},
"stateBroadcastSecs": {
"label": "State Broadcast Seconds",
"description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes"
},
"sendBell": {
"label": "Send Bell",
"description": "Send ASCII bell with alert message"
},
"name": {
"label": "Friendly Name",
"description": "Used to format the message sent to mesh, max 20 Characters"
},
"monitorPin": {
"label": "Monitor Pin",
"description": "The GPIO pin to monitor for state changes"
},
"detectionTriggerType": {
"label": "Detection Triggered Type",
"description": "The type of trigger event to be used"
},
"usePullup": {
"label": "Use Pullup",
"description": "Whether or not use INPUT_PULLUP mode for GPIO pin"
}
},
"externalNotification": {
"title": "External Notification Settings",
"description": "Configure the external notification module",
"enabled": {
"label": "Module Enabled",
"description": "Enable External Notification"
},
"outputMs": {
"label": "Output MS",
"description": "Output MS"
},
"output": {
"label": "Output",
"description": "Output"
},
"outputVibra": {
"label": "Output Vibrate",
"description": "Output Vibrate"
},
"outputBuzzer": {
"label": "Output Buzzer",
"description": "Output Buzzer"
},
"active": {
"label": "Active",
"description": "Active"
},
"alertMessage": {
"label": "Alert Message",
"description": "Alert Message"
},
"alertMessageVibra": {
"label": "Alert Message Vibrate",
"description": "Alert Message Vibrate"
},
"alertMessageBuzzer": {
"label": "Alert Message Buzzer",
"description": "Alert Message Buzzer"
},
"alertBell": {
"label": "Alert Bell",
"description": "Should an alert be triggered when receiving an incoming bell?"
},
"alertBellVibra": {
"label": "Alert Bell Vibrate",
"description": "Alert Bell Vibrate"
},
"alertBellBuzzer": {
"label": "Alert Bell Buzzer",
"description": "Alert Bell Buzzer"
},
"usePwm": {
"label": "Use PWM",
"description": "Use PWM"
},
"nagTimeout": {
"label": "Nag Timeout",
"description": "Nag Timeout"
},
"useI2sAsBuzzer": {
"label": "Use I²S Pin as Buzzer",
"description": "Designate I²S Pin as Buzzer Output"
}
},
"mqtt": {
"title": "MQTT Settings",
"description": "Settings for the MQTT module",
"enabled": {
"label": "Enabled",
"description": "Enable or disable MQTT"
},
"address": {
"label": "MQTT Server Address",
"description": "MQTT server address to use for default/custom servers"
},
"username": {
"label": "MQTT Username",
"description": "MQTT username to use for default/custom servers"
},
"password": {
"label": "MQTT Password",
"description": "MQTT password to use for default/custom servers"
},
"encryptionEnabled": {
"label": "Encryption Enabled",
"description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data."
},
"jsonEnabled": {
"label": "JSON Enabled",
"description": "Whether to send/consume JSON packets on MQTT"
},
"tlsEnabled": {
"label": "TLS Enabled",
"description": "Enable or disable TLS"
},
"root": {
"label": "Root topic",
"description": "MQTT root topic to use for default/custom servers"
},
"proxyToClientEnabled": {
"label": "MQTT Client Proxy Enabled",
"description": "Utilizes the network connection to proxy MQTT messages to the client."
},
"mapReportingEnabled": {
"label": "Map Reporting Enabled",
"description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name."
},
"mapReportSettings": {
"publishIntervalSecs": {
"label": "Map Report Publish Interval (s)",
"description": "Interval in seconds to publish map reports"
},
"positionPrecision": {
"label": "Approximate Location",
"description": "Position shared will be accurate within this distance",
"options": {
"metric_km23": "Within 23 km",
"metric_km12": "Within 12 km",
"metric_km5_8": "Within 5.8 km",
"metric_km2_9": "Within 2.9 km",
"metric_km1_5": "Within 1.5 km",
"metric_m700": "Within 700 m",
"metric_m350": "Within 350 m",
"metric_m200": "Within 200 m",
"metric_m90": "Within 90 m",
"metric_m50": "Within 50 m",
"imperial_mi15": "Within 15 miles",
"imperial_mi7_3": "Within 7.3 miles",
"imperial_mi3_6": "Within 3.6 miles",
"imperial_mi1_8": "Within 1.8 miles",
"imperial_mi0_9": "Within 0.9 miles",
"imperial_mi0_5": "Within 0.5 miles",
"imperial_mi0_2": "Within 0.2 miles",
"imperial_ft600": "Within 600 feet",
"imperial_ft300": "Within 300 feet",
"imperial_ft150": "Within 150 feet"
}
}
}
},
"neighborInfo": {
"title": "Neighbor Info Settings",
"description": "Settings for the Neighbor Info module",
"enabled": {
"label": "Enabled",
"description": "Enable or disable Neighbor Info Module"
},
"updateInterval": {
"label": "Update Interval",
"description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh"
}
},
"paxcounter": {
"title": "Paxcounter Settings",
"description": "Settings for the Paxcounter module",
"enabled": {
"label": "Module Enabled",
"description": "Enable Paxcounter"
},
"paxcounterUpdateInterval": {
"label": "Update Interval (seconds)",
"description": "How long to wait between sending paxcounter packets"
},
"wifiThreshold": {
"label": "WiFi RSSI Threshold",
"description": "At what WiFi RSSI level should the counter increase. Defaults to -80."
},
"bleThreshold": {
"label": "BLE RSSI Threshold",
"description": "At what BLE RSSI level should the counter increase. Defaults to -80."
}
},
"rangeTest": {
"title": "Range Test Settings",
"description": "Settings for the Range Test module",
"enabled": {
"label": "Module Enabled",
"description": "Enable Range Test"
},
"sender": {
"label": "Message Interval",
"description": "How long to wait between sending test packets"
},
"save": {
"label": "Save CSV to storage",
"description": "ESP32 Only"
}
},
"serial": {
"title": "Serial Settings",
"description": "Settings for the Serial module",
"enabled": {
"label": "Module Enabled",
"description": "Enable Serial output"
},
"echo": {
"label": "Echo",
"description": "Any packets you send will be echoed back to your device"
},
"rxd": {
"label": "Receive Pin",
"description": "Set the GPIO pin to the RXD pin you have set up."
},
"txd": {
"label": "Transmit Pin",
"description": "Set the GPIO pin to the TXD pin you have set up."
},
"baud": {
"label": "Baud Rate",
"description": "The serial baud rate"
},
"timeout": {
"label": "Timeout",
"description": "Seconds to wait before we consider your packet as 'done'"
},
"mode": {
"label": "Mode",
"description": "Select Mode"
},
"overrideConsoleSerialPort": {
"label": "Override Console Serial Port",
"description": "If you have a serial port connected to the console, this will override it."
}
},
"storeForward": {
"title": "Store & Forward Settings",
"description": "Settings for the Store & Forward module",
"enabled": {
"label": "Module Enabled",
"description": "Enable Store & Forward"
},
"heartbeat": {
"label": "Heartbeat Enabled",
"description": "Enable Store & Forward heartbeat"
},
"records": {
"label": "Number of records",
"description": "Number of records to store"
},
"historyReturnMax": {
"label": "History return max",
"description": "Max number of records to return"
},
"historyReturnWindow": {
"label": "History return window",
"description": "Return records from this time window (minutes)"
}
},
"telemetry": {
"title": "Telemetry Settings",
"description": "Settings for the Telemetry module",
"deviceUpdateInterval": {
"label": "Device Metrics",
"description": "Device metrics update interval (seconds)"
},
"environmentUpdateInterval": {
"label": "Environment metrics update interval (seconds)",
"description": ""
},
"environmentMeasurementEnabled": {
"label": "Module Enabled",
"description": "Enable the Environment Telemetry"
},
"environmentScreenEnabled": {
"label": "Displayed on Screen",
"description": "Show the Telemetry Module on the OLED"
},
"environmentDisplayFahrenheit": {
"label": "Display Fahrenheit",
"description": "Display temp in Fahrenheit"
},
"airQualityEnabled": {
"label": "Air Quality Enabled",
"description": "Enable the Air Quality Telemetry"
},
"airQualityInterval": {
"label": "Air Quality Update Interval",
"description": "How often to send Air Quality data over the mesh"
},
"powerMeasurementEnabled": {
"label": "Power Measurement Enabled",
"description": "Enable the Power Measurement Telemetry"
},
"powerUpdateInterval": {
"label": "Power Update Interval",
"description": "How often to send Power data over the mesh"
},
"powerScreenEnabled": {
"label": "Power Screen Enabled",
"description": "Enable the Power Telemetry Screen"
}
}
}
@@ -0,0 +1,59 @@
{
"nodeDetail": {
"publicKeyEnabled": {
"label": "Public Key Enabled"
},
"noPublicKey": {
"label": "No Public Key"
},
"directMessage": {
"label": "Direct Message {{shortName}}"
},
"favorite": {
"label": "Favorite",
"tooltip": "Add or remove this node from your favorites"
},
"notFavorite": {
"label": "Not a Favorite"
},
"error": {
"label": "Error",
"text": "An error occurred while fetching node details. Please try again later."
},
"status": {
"heard": "Heard",
"mqtt": "MQTT"
},
"elevation": {
"label": "Elevation"
},
"channelUtil": {
"label": "Channel Util"
},
"airtimeUtil": {
"label": "Airtime Util"
}
},
"nodesTable": {
"headings": {
"longName": "Long Name",
"connection": "Connection",
"lastHeard": "Last Heard",
"encryption": "Encryption",
"model": "Model",
"macAddress": "MAC Address"
},
"connectionStatus": {
"direct": "Direct",
"away": "away",
"viaMqtt": ", via MQTT"
}
},
"actions": {
"added": "Added",
"removed": "Removed",
"ignoreNode": "Ignore Node",
"unignoreNode": "Unignore Node",
"requestPosition": "Request Position"
}
}
+230
View File
@@ -0,0 +1,230 @@
{
"navigation": {
"title": "Navigation",
"messages": "Messages",
"map": "Map",
"settings": "Settings",
"channels": "Channels",
"radioConfig": "Radio Config",
"deviceConfig": "Device Config",
"moduleConfig": "Module Config",
"manageConnections": "Manage Connections",
"nodes": "Nodes"
},
"app": {
"title": "Meshtastic",
"logo": "Meshtastic Logo"
},
"sidebar": {
"collapseToggle": {
"button": {
"open": "Open sidebar",
"close": "Close sidebar"
}
},
"deviceInfo": {
"volts": "{{voltage}} volts",
"firmware": {
"title": "Firmware",
"version": "v{{version}}",
"buildDate": "Build date: {{date}}"
}
}
},
"batteryStatus": {
"charging": "{{level}}% charging",
"pluggedIn": "Plugged in",
"title": "Battery"
},
"search": {
"nodes": "Search nodes...",
"channels": "Search channels...",
"commandPalette": "Search commands..."
},
"toast": {
"positionRequestSent": {
"title": "Position request sent."
},
"requestingPosition": {
"title": "Requesting position, please wait..."
},
"sendingTraceroute": {
"title": "Sending Traceroute, please wait..."
},
"tracerouteSent": {
"title": "Traceroute sent."
},
"savedChannel": {
"title": "Saved Channel: {{channelName}}"
},
"messages": {
"pkiEncryption": {
"title": "Chat is using PKI encryption."
},
"pskEncryption": {
"title": "Chat is using PSK encryption."
}
},
"configSaveError": {
"title": "Error Saving Config",
"description": "An error occurred while saving the configuration."
},
"validationError": {
"title": "Config Errors Exist",
"description": "Please fix the configuration errors before saving."
},
"saveSuccess": {
"title": "Saving Config",
"description": "The configuration change {{case}} has been saved."
},
"saveAllSuccess": {
"title": "Saved",
"description": "All configuration changes have been saved."
},
"favoriteNode": {
"title": "{{action}} {{nodeName}} {{direction}} favorites.",
"action": {
"added": "Added",
"removed": "Removed",
"to": "to",
"from": "from"
}
},
"ignoreNode": {
"title": "{{action}} {{nodeName}} {{direction}} ignore list",
"action": {
"added": "Added",
"removed": "Removed",
"to": "to",
"from": "from"
}
}
},
"notifications": {
"copied": {
"label": "Copied!"
},
"copyToClipboard": {
"label": "Copy to clipboard"
},
"hidePassword": {
"label": "Hide password"
},
"showPassword": {
"label": "Show password"
},
"deliveryStatus": {
"delivered": "Delivered",
"failed": "Delivery Failed",
"waiting": "Waiting",
"unknown": "Unknown"
}
},
"general": {
"label": "General"
},
"hardware": {
"label": "Hardware"
},
"metrics": {
"label": "Metrics"
},
"role": {
"label": "Role"
},
"filter": {
"label": "Filter"
},
"advanced": {
"label": "Advanced"
},
"clearInput": {
"label": "Clear input"
},
"resetFilters": {
"label": "Reset Filters"
},
"nodeName": {
"label": "Node name/number",
"placeholder": "Meshtastic 1234"
},
"airtimeUtilization": {
"label": "Airtime Utilization (%)",
"short": "Airtime Util. (%)"
},
"batteryLevel": {
"label": "Battery level (%)",
"labelText": "Battery level (%): {{value}}"
},
"batteryVoltage": {
"label": "Battery voltage (V)",
"title": "Voltage"
},
"channelUtilization": {
"label": "Channel Utilization (%)",
"short": "Channel Util. (%)"
},
"hops": {
"direct": "Direct",
"label": "Number of hops",
"text": "Number of hops: {{value}}"
},
"lastHeard": {
"label": "Last heard",
"labelText": "Last heard: {{value}}",
"nowLabel": "Now"
},
"snr": {
"label": "SNR (db)"
},
"favorites": {
"label": "Favorites"
},
"hide": {
"label": "Hide"
},
"showOnly": {
"label": "Show Only"
},
"viaMqtt": {
"label": "Connected via MQTT"
},
"hopsUnknown": {
"label": "Unknown number of hops"
},
"showUnheard": {
"label": "Never heard"
},
"language": {
"label": "Language",
"changeLanguage": "Change Language"
},
"theme": {
"dark": "Dark",
"light": "Light",
"system": "Automatic",
"changeTheme": "Change Color Scheme"
},
"errorPage": {
"title": "This is a little embarrassing...",
"description1": "We are really sorry but an error occurred in the web client that caused it to crash. <br /> This is not supposed to happen, and we are working hard to fix it.",
"description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.",
"reportInstructions": "Please include the following information in your report:",
"reportSteps": {
"step1": "What you were doing when the error occurred",
"step2": "What you expected to happen",
"step3": "What actually happened",
"step4": "Any other relevant information"
},
"reportLink": "You can report the issue to our <0>GitHub</0>",
"connectionsLink": "Return to the <0>connections</0>",
"detailsSummary": "Error Details",
"errorMessageLabel": "Error message:",
"stackTraceLabel": "Stack trace:",
"fallbackError": "{{error}}"
},
"footer": {
"text": "Powered by <0>▲ Vercel</0> | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information</1>",
"commitSha": "Commit SHA: {{sha}}"
}
}
@@ -0,0 +1,71 @@
{
"page": {
"sectionLabel": "Канали",
"channelName": "Канал: {{channelName}}",
"broadcastLabel": "Първичен",
"channelIndex": "К {{index}}",
"import": "Импортиране",
"export": "Експортиране"
},
"validation": {
"pskInvalid": "Моля, въведете валиден {{bits}} bit PSK."
},
"settings": {
"label": "Настройки на канала",
"description": "Крипто, MQTT и други настройки"
},
"role": {
"label": "Роля",
"description": "Телеметрията на устройството се изпраща през ПЪРВИЧЕН. Разрешен е само един ПЪРВИЧЕН.",
"options": {
"primary": "ПЪРВИЧЕН",
"disabled": "ДЕЗАКТИВИРАН",
"secondary": "ВТОРИЧЕН"
}
},
"psk": {
"label": "Предварително споделен ключ",
"description": "Поддържани дължини на PSK: 256-битова, 128-битова, 8-битова, празна (0-битова)",
"generate": "Генериране"
},
"name": {
"label": "Име",
"description": "Уникално име за канала <12 байта, оставете празно за подразбиране"
},
"uplinkEnabled": {
"label": "Uplink е активиран",
"description": "Изпращане на съобщения от локалната mesh към MQTT"
},
"downlinkEnabled": {
"label": "Downlink е активиран",
"description": "Изпращане на съобщения от MQTT към локалната mesh"
},
"positionPrecision": {
"label": "Местоположение",
"description": "Точността на местоположението, което да се споделя с канала. Може да бъде дезактивирано.",
"options": {
"none": "Да не се споделя местоположението",
"precise": "Точно местоположение",
"metric_km23": "В рамките на 23 километра",
"metric_km12": "В рамките на 12 километра",
"metric_km5_8": "В рамките на 5.8 километра",
"metric_km2_9": "В рамките на 2.9 километра",
"metric_km1_5": "В рамките на 1.5 километра",
"metric_m700": "В рамките на 700 метра",
"metric_m350": "В рамките на 350 метра",
"metric_m200": "В рамките на 200 метра",
"metric_m90": "В рамките на 90 метра",
"metric_m50": "В рамките на 50 метра",
"imperial_mi15": "В рамките на 15 мили",
"imperial_mi7_3": "В рамките на 7.3 мили",
"imperial_mi3_6": "В рамките на 3.6 мили",
"imperial_mi1_8": "В рамките на 1.8 мили",
"imperial_mi0_9": "В рамките на 0.9 мили",
"imperial_mi0_5": "В рамките на 0.5 мили",
"imperial_mi0_2": "В рамките на 0.2 мили",
"imperial_ft600": "В рамките на 600 фута",
"imperial_ft300": "В рамките на 300 фута",
"imperial_ft150": "В рамките на 150 фута"
}
}
}
@@ -15,7 +15,6 @@
"messages": "Съобщения",
"map": "Карта",
"config": "Конфигурация",
"channels": "Канали",
"nodes": "Възли"
}
},
@@ -33,9 +32,9 @@
"qrGenerator": "Генератор",
"qrImport": "Импортиране",
"scheduleShutdown": "Планирано изключване",
"scheduleReboot": "Планирано рестартиране",
"rebootToOtaMode": "Рестартиране в режим OTA",
"scheduleReboot": "Рестартиране на устройството",
"resetNodeDb": "Нулиране на базата данни с възли",
"dfuMode": "Влизане в DFU режим",
"factoryResetDevice": "Фабрично нулиране на устройството",
"factoryResetConfig": "Фабрично нулиране на конфигурацията",
"disconnect": "Прекъсване"
@@ -45,7 +44,8 @@
"label": "Отстраняване на грешки",
"command": {
"reconfigure": "Преконфигуриране",
"clearAllStoredMessages": "Изчистване на всички съхранени съобщения"
"clearAllStoredMessages": "Изчистване на всички съхранени съобщения",
"clearAllStores": "Clear All Local Storage"
}
}
}
@@ -0,0 +1,165 @@
{
"button": {
"apply": "Приложи",
"addConnection": "Добавяне на връзка",
"saveConnection": "Запазване на връзката",
"backupKey": "Резервно копие на ключа",
"cancel": "Отказ",
"connect": "Свързване",
"clearMessages": "Изчистване на съобщенията",
"close": "Затвори",
"confirm": "Потвърждаване",
"delete": "Изтриване",
"dismiss": "Отхвърляне",
"download": "Изтегляне",
"disconnect": "Прекъсване на връзката",
"export": "Експортиране",
"generate": "Генериране",
"regenerate": "Регенериране",
"import": "Импортиране",
"message": "Съобщение",
"now": "Сега",
"ok": "Добре",
"print": "Отпечатване",
"remove": "Изтрий",
"requestNewKeys": "Заявка за нови ключове",
"requestPosition": "Request Position",
"reset": "Нулиране",
"retry": "Retry",
"save": "Запис",
"setDefault": "Задаване по подразбиране",
"unsetDefault": "Unset default",
"scanQr": "Сканиране на QR кода",
"traceRoute": "Trace Route",
"submit": "Изпращане"
},
"app": {
"title": "Meshtastic",
"fullTitle": "Meshtastic Web клиент"
},
"loading": "Зареждане...",
"unit": {
"cps": "CPS",
"dbm": "dBm",
"hertz": "Hz",
"hop": {
"one": "Хоп",
"plural": "Хопа"
},
"hopsAway": {
"one": "{{count}} hop away",
"plural": "{{count}} hops away",
"unknown": "Unknown hops away"
},
"megahertz": "MHz",
"kilohertz": "kHz",
"raw": "raw",
"meter": {
"one": "Метър",
"plural": "Метри",
"suffix": "m"
},
"kilometer": {
"one": "Километър",
"plural": "Километри",
"suffix": "км"
},
"minute": {
"one": "Минута",
"plural": "Минути"
},
"hour": {
"one": "Час",
"plural": "Часа"
},
"millisecond": {
"one": "Милисекунда",
"plural": "Милисекунди",
"suffix": "ms"
},
"second": {
"one": "Секунда",
"plural": "Секунди"
},
"day": {
"one": "Ден",
"plural": "Дни",
"today": "Днес",
"yesterday": "Вчера"
},
"month": {
"one": "Месец",
"plural": "Месеца"
},
"year": {
"one": "Година",
"plural": "Години"
},
"snr": "SNR",
"volt": {
"one": "Волт",
"plural": "Волта",
"suffix": "V"
},
"record": {
"one": "Записи",
"plural": "Записи"
},
"degree": {
"one": "Градус",
"plural": "Градуса",
"suffix": "°"
}
},
"security": {
"0bit": "Празен",
"8bit": "8 bit",
"128bit": "128 bit",
"256bit": "256 bit"
},
"unknown": {
"longName": "Неизвестно",
"shortName": "НЕИЗВ.",
"notAvailable": "N/A",
"num": "??"
},
"nodeUnknownPrefix": "!",
"unset": "НЕЗАДАДЕН",
"fallbackName": "Meshtastic {{last4}}",
"node": "Възел",
"formValidation": {
"unsavedChanges": "Незапазени промени",
"tooBig": {
"string": "Твърде дълъг, очаква се по-малко или равно на {{maximum}} знака.",
"number": "Твърде голям, очаква се число по-малко или равно на {{maximum}}.",
"bytes": "Твърде голям, очаква се по-малък или равен на {{params.maximum}} байта."
},
"tooSmall": {
"string": "Твърде кратък, очаква се повече или равно на {{minimum}} знака.",
"number": "Твърде малък, очаква се число, по-голямо или равно на {{minimum}}."
},
"invalidFormat": {
"ipv4": "Невалиден формат, очаква се IPv4 адрес.",
"key": "Невалиден формат, очаква се предварително споделен ключ (PSK), кодиран с Base64."
},
"invalidType": {
"number": "Невалиден тип, очаква се число."
},
"pskLength": {
"0bit": "Ключът трябва да е празен.",
"8bit": "Ключът трябва да бъде 8-битов предварително споделен ключ (PSK).",
"128bit": "Ключът трябва да бъде 128-битов предварително споделен ключ (PSK).",
"256bit": "Ключът трябва да бъде 256-битов предварително споделен ключ (PSK)."
},
"required": {
"generic": "Това поле е задължително.",
"managed": "Изисква се поне един администраторски ключ, ако възелът е управляван.",
"key": "Ключът е задължителен."
},
"invalidOverrideFreq": {
"number": "Невалиден формат, очаквана е стойност в диапазона 410-930 MHz или 0 (използвайте стойността по подразбиране)."
}
},
"yes": "Да",
"no": "Не"
}
@@ -0,0 +1,458 @@
{
"page": {
"title": "Настройки",
"tabUser": "Потребител",
"tabChannels": "Канали",
"tabBluetooth": "Bluetooth",
"tabDevice": "Устройство",
"tabDisplay": "Дисплей",
"tabLora": "LoRa",
"tabNetwork": "Мрежа",
"tabPosition": "Позиция",
"tabPower": "Захранване",
"tabSecurity": "Сигурност"
},
"sidebar": {
"label": "Конфигурация"
},
"device": {
"title": "Настройки на устройството",
"description": "Настройки за устройството",
"buttonPin": {
"description": "Button pin override",
"label": "Пин за бутон"
},
"buzzerPin": {
"description": "Buzzer pin override",
"label": "Пин за зумер"
},
"disableTripleClick": {
"description": "Дезактивиране на трикратното щракване",
"label": "Дезактивиране на трикратното щракване"
},
"doubleTapAsButtonPress": {
"description": "Treat double tap as button press",
"label": "Double Tap as Button Press"
},
"ledHeartbeatDisabled": {
"description": "Дезактивиране на мигащия светодиод по подразбиране",
"label": "LED Heartbeat Disabled"
},
"nodeInfoBroadcastInterval": {
"description": "How often to broadcast node info",
"label": "Node Info Broadcast Interval"
},
"posixTimezone": {
"description": "The POSIX timezone string for the device",
"label": "POSIX часова зона"
},
"rebroadcastMode": {
"description": "How to handle rebroadcasting",
"label": "Режим на препредаване"
},
"role": {
"description": "Каква роля изпълнява устройството в mesh",
"label": "Роля"
}
},
"bluetooth": {
"title": "Настройки за Bluetooth",
"description": "Настройки за Bluetooth модула",
"note": "Забележка: Някои устройства (ESP32) не могат да използват едновременно Bluetooth и WiFi.",
"enabled": {
"description": "Активиране или дезактивиране на Bluetooth",
"label": "Активиран"
},
"pairingMode": {
"description": "Поведение при избор на ПИН.",
"label": "Режим на сдвояване"
},
"pin": {
"description": "Pin to use when pairing",
"label": "ПИН"
}
},
"display": {
"description": "Настройки за дисплея на устройството",
"title": "Настройки на дисплея",
"headingBold": {
"description": "Bolden the heading text",
"label": "Удебелен заглавен шрифт"
},
"carouselDelay": {
"description": "Колко бързо да се превключва между прозорците",
"label": "Carousel Delay"
},
"compassNorthTop": {
"description": "Фиксиране на север към горната част на компаса",
"label": "Север на компаса отгоре"
},
"displayMode": {
"description": "Screen layout variant",
"label": "Display Mode"
},
"displayUnits": {
"description": "Показване на метрични или имперски мерни единици",
"label": "Display Units"
},
"flipScreen": {
"description": "Обръщане на дисплея на 180 градуса",
"label": "Обръщане на дисплея"
},
"gpsDisplayUnits": {
"description": "Coordinate display format",
"label": "GPS Display Units"
},
"oledType": {
"description": "Тип на OLED екрана, прикрепен към устройството",
"label": "Тип OLED"
},
"screenTimeout": {
"description": "Turn off the display after this long",
"label": "Screen Timeout"
},
"twelveHourClock": {
"description": "Използване на 12-часов формат на часовника",
"label": "12-часов часовник"
},
"wakeOnTapOrMotion": {
"description": "Събуждане на устройството при докосване или движение",
"label": "Събуждане при докосване или движение"
}
},
"lora": {
"title": "Настройки на Mesh",
"description": "Настройки за LoRa mesh",
"bandwidth": {
"description": "Широчина на канала в kHz",
"label": "Широчина на честотната лента"
},
"boostedRxGain": {
"description": "Boosted RX gain",
"label": "Boosted RX Gain"
},
"codingRate": {
"description": "The denominator of the coding rate",
"label": "Coding Rate"
},
"frequencyOffset": {
"description": "Frequency offset to correct for crystal calibration errors",
"label": "Отместване на честотата"
},
"frequencySlot": {
"description": "Номер на LoRa честотен канал",
"label": "Честотен слот"
},
"hopLimit": {
"description": "Максимален брой хопове",
"label": "Лимит на хопове"
},
"ignoreMqtt": {
"description": "Да не се препращат MQTT съобщения през mesh",
"label": "Игнориране на MQTT"
},
"modemPreset": {
"description": "Използване на предварително настроен модем",
"label": "Предварително настроен модем"
},
"okToMqtt": {
"description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT",
"label": "OK to MQTT"
},
"overrideDutyCycle": {
"description": "Override Duty Cycle",
"label": "Override Duty Cycle"
},
"overrideFrequency": {
"description": "Override frequency",
"label": "Override Frequency"
},
"region": {
"description": "Задаване на региона за вашия възел",
"label": "Регион"
},
"spreadingFactor": {
"description": "Indicates the number of chirps per symbol",
"label": "Spreading Factor"
},
"transmitEnabled": {
"description": "Активиране/дезактивиране на предаването (TX) от LoRa радиото",
"label": "Предаването е активирано"
},
"transmitPower": {
"description": "Максимална мощност на предаване",
"label": "Мощност на предаване"
},
"usePreset": {
"description": "Използване на една от предварително зададените настройки на модема",
"label": "Използване на предварително зададени настройки"
},
"meshSettings": {
"description": "Настройки за LoRa mesh",
"label": "Настройки на Mesh"
},
"waveformSettings": {
"description": "Settings for the LoRa waveform",
"label": "Waveform Settings"
},
"radioSettings": {
"label": "Настройки на радиото",
"description": "Настройки за LoRa радиото"
}
},
"network": {
"title": "Конфигурация на WiFi",
"description": "Конфигурация на WiFi радиото",
"note": "Забележка: Някои устройства (ESP32) не могат да използват едновременно Bluetooth и WiFi.",
"addressMode": {
"description": "Address assignment selection",
"label": "Режим на адреса"
},
"dns": {
"description": "DNS сървър",
"label": "DNS"
},
"ethernetEnabled": {
"description": "Активиране или дезактивиране на Ethernet порта",
"label": "Активиран"
},
"gateway": {
"description": "Шлюз по подразбиране",
"label": "Шлюз"
},
"ip": {
"description": "IP адрес",
"label": "IP"
},
"psk": {
"description": "Парола за мрежата",
"label": "PSK"
},
"ssid": {
"description": "Име на мрежата",
"label": "SSID"
},
"subnet": {
"description": "Подмрежова маска",
"label": "Подмрежа"
},
"wifiEnabled": {
"description": "Активиране или дезактивиране на WiFi радиото",
"label": "Активиран"
},
"meshViaUdp": {
"label": "Mesh чрез UDP"
},
"ntpServer": {
"label": "NTP сървър"
},
"rsyslogServer": {
"label": "Сървър Rsyslog"
},
"ethernetConfigSettings": {
"description": "Конфигуриране на Ethernet порта",
"label": "Конфигурация на Ethernet "
},
"ipConfigSettings": {
"description": "Конфигуриране на IP",
"label": "Конфигурация на IP"
},
"ntpConfigSettings": {
"description": "Конфигуриране на NTP",
"label": "Конфигурация на NTP"
},
"rsyslogConfigSettings": {
"description": "Конфигуриране на Rsyslog",
"label": "Конфиг. на Rsyslog"
},
"udpConfigSettings": {
"description": "Конфигуриране на UDP през Mesh",
"label": "Конфигуриране на UDP"
}
},
"position": {
"title": "Настройки на позицията",
"description": "Настройки за модула за позиция",
"broadcastInterval": {
"description": "How often your position is sent out over the mesh",
"label": "Интервал на излъчване"
},
"enablePin": {
"description": "GPS module enable pin override",
"label": "Активиране на пин"
},
"fixedPosition": {
"description": "Да не се докладва GPS позиция, а ръчно зададена такава",
"label": "Фиксирана позиция"
},
"gpsMode": {
"description": "Конфигуриране дали GPS на устройството е активиран, деактивиран или липсва",
"label": "Режим на GPS"
},
"gpsUpdateInterval": {
"description": "Колко често трябва да се получава GPS сигнал",
"label": "Интервал на актуализиране на GPS"
},
"positionFlags": {
"description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.",
"label": "Position Flags"
},
"receivePin": {
"description": "GPS module RX pin override",
"label": "Receive Pin"
},
"smartPositionEnabled": {
"description": "Only send position when there has been a meaningful change in location",
"label": "Enable Smart Position"
},
"smartPositionMinDistance": {
"description": "Минималното разстояние (в метри), което трябва да се измине, преди да се изпрати актуализация на местоположението",
"label": "Минимално разстояние за интелигентна позиция"
},
"smartPositionMinInterval": {
"description": "Minimum interval (in seconds) that must pass before a position update is sent",
"label": "Smart Position Minimum Interval"
},
"transmitPin": {
"description": "GPS module TX pin override",
"label": "Transmit Pin"
},
"intervalsSettings": {
"description": "Колко често да се изпращат актуализации на позицията",
"label": "Интервали"
},
"flags": {
"placeholder": "Select position flags...",
"altitude": "Надморска височина",
"altitudeGeoidalSeparation": "Altitude Geoidal Separation",
"altitudeMsl": "Altitude is Mean Sea Level",
"dop": "Dilution of precision (DOP) PDOP used by default",
"hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP",
"numSatellites": "Брой сателити",
"sequenceNumber": "Пореден номер",
"timestamp": "Времево клеймо",
"unset": "Не е зададен",
"vehicleHeading": "Посока на движение на превозното средство",
"vehicleSpeed": "Скорост на превозното средство"
}
},
"power": {
"adcMultiplierOverride": {
"description": "Използва се за настройване на отчитането на напрежението на батерията",
"label": "ADC Multiplier Override ratio"
},
"ina219Address": {
"description": "Address of the INA219 battery monitor",
"label": "INA219 адрес"
},
"lightSleepDuration": {
"description": "Колко дълго устройството ще бъде в лек сън",
"label": "Продължителност на лекия сън"
},
"minimumWakeTime": {
"description": "Минималното време, през което устройството ще остане активно след получаване на пакет",
"label": "Минимално време за събуждане"
},
"noConnectionBluetoothDisabled": {
"description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long",
"label": "Няма връзка Bluetooth е дезактивиран"
},
"powerSavingEnabled": {
"description": "Изберете, ако се захранва от източник с малък ток (напр. слънчева енергия), за да се намали максимално консумацията на енергия.",
"label": "Активиране на енергоспестяващ режим"
},
"shutdownOnBatteryDelay": {
"description": "Automatically shutdown node after this long when on battery, 0 for indefinite",
"label": "Shutdown on battery delay"
},
"superDeepSleepDuration": {
"description": "Колко дълго устройството ще бъде в супер дълбок сън",
"label": "Продължителност на супер дълбокия сън"
},
"powerConfigSettings": {
"description": "Настройки за захранващия модул",
"label": "Конфигуриране на захранването"
},
"sleepSettings": {
"description": "Настройки за спящ режим за захранващия модул",
"label": "Настройки за сън"
}
},
"security": {
"description": "Настройки за конфигурацията за сигурност",
"title": "Насртойки на сигурността",
"button_backupKey": "Резервно копие на ключа",
"adminChannelEnabled": {
"description": "Allow incoming device control over the insecure legacy admin channel",
"label": "Allow Legacy Admin"
},
"enableDebugLogApi": {
"description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth",
"label": "Enable Debug Log API"
},
"managed": {
"description": "Ако е активирана, опциите за конфигурация на устройството могат да се променят дистанционно само от възел за отдалечено администриране чрез администраторски съобщения. Не активирайте тази опция, освен ако не е настроен поне един подходящ възел за отдалечено администриране и публичният ключ е съхранен в едно от полетата по-горе.",
"label": "Управлява се"
},
"privateKey": {
"description": "Използва се за създаване на споделен ключ с отдалечено устройство",
"label": "Частен ключ"
},
"publicKey": {
"description": "Изпраща се до други възли в mesh, за да им позволи да изчислят споделения секретен ключ",
"label": "Публичен ключ"
},
"primaryAdminKey": {
"description": "Основният публичен ключ, оторизиран за изпращане на администраторски съобщения до този възел",
"label": "Основен администраторски ключ"
},
"secondaryAdminKey": {
"description": "Вторичният публичен ключ, оторизиран за изпращане на администраторски съобщения до този възел.",
"label": "Вторичен администраторски ключ"
},
"serialOutputEnabled": {
"description": "Serial Console over the Stream API",
"label": "Serial Output Enabled"
},
"tertiaryAdminKey": {
"description": "Третичният публичен ключ, оторизиран за изпращане на администраторски съобщения до този възел",
"label": "Третичен администраторски ключ"
},
"adminSettings": {
"description": "Настройки за Admin",
"label": "Администраторски настройки"
},
"loggingSettings": {
"description": "Settings for Logging",
"label": "Logging Settings"
}
},
"user": {
"title": "User Settings",
"description": "Configure your device name and identity settings",
"longName": {
"label": "Дълго име",
"description": "Your full display name (1-40 characters)",
"validation": {
"min": "Long name must be at least 1 character",
"max": "Long name must be at most 40 characters"
}
},
"shortName": {
"label": "Кратко име",
"description": "Your abbreviated name (2-4 characters)",
"validation": {
"min": "Short name must be at least 2 characters",
"max": "Short name must be at most 4 characters"
}
},
"isUnmessageable": {
"label": "Без съобщения",
"description": "Used to identify unmonitored or infrastructure nodes so that messaging is not available to nodes that will never respond."
},
"isLicensed": {
"label": "Лицензиран радиолюбител (HAM)",
"description": "Enable if you are a licensed amateur radio operator, enabling this option disables encryption and is not compatible with the default Meshtastic network."
}
}
}
@@ -0,0 +1,34 @@
{
"page": {
"title": "Свързване с устройство Meshtastic",
"description": "Добавете връзка с устройството чрез HTTP, Bluetooth или сериен порт. Запазените ви връзки ще бъдат запазени във вашия браузър."
},
"connectionType_ble": "BLE",
"connectionType_serial": "Серийна",
"connectionType_network": "Мрежа",
"deleteConnection": "Изтриване на връзката",
"areYouSure": "Това ще премахне {{name}}. Не можете да отмените това действие.",
"moreActions": "Още действия",
"noConnections": {
"title": "Все още няма връзки.",
"description": "Създайте първата си връзка. Тя ще се свърже веднага и ще бъде запазена за по-късно."
},
"lastConnectedAt": "Последно свързване: {{date}}",
"neverConnected": "Никога не е бил свързан",
"toasts": {
"connected": "Свързано",
"nowConnected": "{{name}} е свързан сега",
"nowDisconnected": "{{name}} are now disconnecte",
"disconnected": "Прекъсната връзка",
"failed": "Свързването не е успешно",
"checkConnetion": "Проверете устройството или настройките си и опитайте отново",
"defaultSet": "Default set",
"defaultConnection": "Default connection is now {{nameisconnected}}",
"deleted": "Изтрит",
"deletedByName": "{{name}} беше премахнат",
"pickConnectionAgain": "Не можа да се свърже. Може да се наложи да изберете отново устройството/порта.",
"added": "Връзката е добавена",
"savedByName": "{{name}} е запазен.",
"savedCantConnect": "Връзката беше запазена, но не можа да се осъществи свързване."
}
}
@@ -114,15 +114,15 @@
"label": "12-часов часовник"
},
"wakeOnTapOrMotion": {
"description": "Wake the device on tap or motion",
"label": "Wake on Tap or Motion"
"description": "Събуждане на устройството при докосване или движение",
"label": "Събуждане при докосване или движение"
}
},
"lora": {
"title": "Настройки на Mesh",
"description": "Настройки за LoRa mesh",
"bandwidth": {
"description": "Широчина на канала в MHz",
"description": "Широчина на канала в kHz",
"label": "Широчина на честотната лента"
},
"boostedRxGain": {
@@ -204,7 +204,7 @@
"note": "Забележка: Някои устройства (ESP32) не могат да използват едновременно Bluetooth и WiFi.",
"addressMode": {
"description": "Address assignment selection",
"label": "Address Mode"
"label": "Режим на адреса"
},
"dns": {
"description": "DNS сървър",
@@ -231,8 +231,8 @@
"label": "SSID"
},
"subnet": {
"description": "Subnet Mask",
"label": "Subnet"
"description": "Подмрежова маска",
"label": "Подмрежа"
},
"wifiEnabled": {
"description": "Активиране или дезактивиране на WiFi радиото",
@@ -401,20 +401,20 @@
"label": "Публичен ключ"
},
"primaryAdminKey": {
"description": "The primary public key authorized to send admin messages to this node",
"label": "Primary Admin Key"
"description": "Основният публичен ключ, оторизиран за изпращане на администраторски съобщения до този възел",
"label": "Основен администраторски ключ"
},
"secondaryAdminKey": {
"description": "The secondary public key authorized to send admin messages to this node",
"label": "Secondary Admin Key"
"description": "Вторичният публичен ключ, оторизиран за изпращане на администраторски съобщения до този възел",
"label": "Вторичен администраторски ключ"
},
"serialOutputEnabled": {
"description": "Serial Console over the Stream API",
"label": "Serial Output Enabled"
},
"tertiaryAdminKey": {
"description": "The tertiary public key authorized to send admin messages to this node",
"label": "Tertiary Admin Key"
"description": "Третичният публичен ключ, оторизиран за изпращане на администраторски съобщения до този възел",
"label": "Третичен администраторски ключ"
},
"adminSettings": {
"description": "Настройки за Admin",
@@ -0,0 +1,238 @@
{
"deleteMessages": {
"description": "Това действие ще изчисти цялата история на съобщенията. Това не може да бъде отменено. Сигурни ли сте, че искате да продължите?",
"title": "Изчистване на всички съобщения"
},
"import": {
"description": "Текущата конфигурация на LoRa ще бъде презаписана.",
"error": {
"invalidUrl": "Невалиден Meshtastic URL"
},
"channelPrefix": "Канал: ",
"primary": "Първичен ",
"doNotImport": "No not import",
"channelName": "Име",
"channelSlot": "Слот",
"channelSetUrl": "Channel Set/QR Code URL",
"useLoraConfig": "Импортиране на конфигурация на LoRa",
"presetDescription": "Текущата конфигурация na LoRa ще бъде заменена.",
"title": "Import Channel Set"
},
"locationResponse": {
"title": "Местоположение: {{identifier}}",
"altitude": "Надморска височина: ",
"coordinates": "Координати:",
"noCoordinates": "Няма координати"
},
"pkiRegenerateDialog": {
"title": "Регенериране на предварително споделения ключ?",
"description": "Сигурни ли сте, че искате да регенерирате предварително споделения ключ?",
"regenerate": "Регенериране"
},
"addConnection": {
"title": "Добавяне на връзка",
"description": "Изберете тип връзка и попълнете данните",
"validation": {
"requiresWebBluetooth": "Този тип връзка изисква <0>Web Bluetooth</0>. Моля, използвайте поддържан браузър, като Chrome или Edge.",
"requiresWebSerial": "Този тип връзка изисква <0>Web Serial</0>. Моля, използвайте поддържан браузър, като Chrome или Edge.",
"requiresSecureContext": "Това приложение изисква <0>secure context</0>. Моля, свържете се чрез HTTPS или localhost.",
"additionallyRequiresSecureContext": "Освен това, изисква <0>secure context</0>. Моля, свържете се чрез HTTPS или localhost."
},
"bluetoothConnection": {
"namePlaceholder": "Моят Bluetooth възел",
"supported": {
"title": "Поддържа се Web Bluetooth"
},
"notSupported": {
"title": "Не се поддържа Web Bluetooth",
"description": "Вашият браузър или устройство не поддържа Web Bluetooth"
},
"short": "BT: {{deviceName}}",
"long": "Bluetooth устройство",
"device": "Устройство",
"selectDevice": "Изберете устройство",
"selected": "Избрано Bluetooth устройство",
"notSelected": "Няма избрано устройство",
"helperText": "Използва услугата Meshtastic Bluetooth за откриване."
},
"serialConnection": {
"namePlaceholder": "Моят сериен възел",
"helperText": "Selecting a port grants permission so the app can open it to connect.",
"supported": {
"title": "Web Serial supported"
},
"notSupported": {
"title": "Web Serial not supported",
"description": "Your browser or device does not support Web Serial"
},
"portSelected": {
"title": "Serial port selected",
"description": "Port permissions granted."
},
"port": "Порт",
"selectPort": "Изберете порт",
"deviceName": "USB {{vendorId}}:{{productId}}",
"notSelected": "Няма избран порт"
},
"httpConnection": {
"namePlaceholder": "Моят HTTP възел",
"inputPlaceholder": "192.168.1.10 или meshtastic.local",
"heading": "URL или IP",
"useHttps": "Използване на HTTPS",
"invalidUrl": {
"title": "Невалиден URL",
"description": "Моля, въведете валиден HTTP или HTTPS URL."
},
"connectionTest": {
"description": "Тествайте връзката, преди да я запазите, за да се уверите, че устройството е достъпно.",
"button": {
"loading": "Тестване...",
"label": "Тестване на връзката"
},
"reachable": "Достъпно",
"notReachable": "Не е достъпно",
"success": {
"title": "Тестът на връзката е успешен",
"description": "Устройството изглежда е достъпно."
},
"failure": {
"title": "Тестът на връзката не е успешен",
"description": "Не можа да се осъществи връзка с устройството. Проверете URL-а и опитайте отново."
}
}
}
},
"nodeDetails": {
"message": "Съобщение",
"requestPosition": "Request Position",
"traceRoute": "Trace Route",
"airTxUtilization": "Air TX utilization",
"allRawMetrics": "All Raw Metrics:",
"batteryLevel": "Ниво на батерията",
"channelUtilization": "Използване на канала",
"details": "Подробности:",
"deviceMetrics": "Device Metrics:",
"hardware": "Хардуер: ",
"lastHeard": "Последно чут: ",
"nodeHexPrefix": "Node Hex: ",
"nodeNumber": "Номер на възела: ",
"position": "Позиция:",
"role": "Роля: ",
"uptime": "Време на работа: ",
"voltage": "Напрежение",
"title": "Подробности за възел за {{identifier}}",
"ignoreNode": "Игнориране на възела",
"removeNode": "Премахване на възела",
"unignoreNode": "Премахване на игнорирането на възела",
"security": "Сигурност:",
"publicKey": "Публичен ключ:",
"messageable": "Messageable: ",
"KeyManuallyVerifiedTrue": "Публичният ключ е проверен ръчно",
"KeyManuallyVerifiedFalse": "Публичният ключ не е проверен ръчно"
},
"pkiBackup": {
"loseKeysWarning": "Ако загубите ключовете си, ще трябва да нулирате устройството си.",
"secureBackup": "Важно е да направите резервно копие на публичните и частните си ключове и да съхранявате резервното си копие сигурно!",
"footer": "=== КРАЙ НА КЛЮЧОВЕТЕ ===",
"header": "=== MESHTASTIC КЛЮЧОВЕ ЗА {{longName}} ({{shortName}}) ===",
"privateKey": "Частен ключ:",
"publicKey": "Публичен ключ:",
"fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt",
"title": "Backup Keys"
},
"pkiBackupReminder": {
"description": "Препоръчваме редовно да правите резервни копия на данните с вашите ключове. Искате ли да направите резервно копие сега?",
"title": "Напомняне за резервно копие",
"remindLaterPrefix": "Напомни ми в",
"remindNever": "Никога не ми напомняй",
"backupNow": "Създаване на резервно копие сега"
},
"pkiRegenerate": {
"description": "Сигурни ли сте, че искате да регенерирате двойката ключове?",
"title": "Регенериране на двойката ключове"
},
"qr": {
"addChannels": "Добавяне на канали",
"replaceChannels": "Замяна на канали",
"description": "Текущата конфигурация на LoRa също ще бъде споделена.",
"sharableUrl": "Sharable URL",
"title": "Генериране на QR код"
},
"reboot": {
"title": "Рестартиране на устройството",
"description": "Reboot now or schedule a reboot of the connected node. Optionally, you can choose to reboot into OTA (Over-the-Air) mode.",
"ota": "Reboot into OTA mode",
"enterDelay": "Въведете забавяне",
"scheduled": "Насрочено е рестартиране",
"schedule": "Планиране на рестартиране",
"now": "Рестартиране сега",
"cancel": "Cancel scheduled reboot"
},
"refreshKeys": {
"description": {
"acceptNewKeys": "This will remove the node from device and request new keys.",
"keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.",
"unableToSendDmPrefix": "Вашият възел не може да изпрати директно съобщение до възел:"
},
"acceptNewKeys": "риемане на нови ключове",
"title": "Keys Mismatch - {{identifier}}"
},
"removeNode": {
"description": "Сигурни ли сте, че искате да премахнете този възел?",
"title": "Премахване на възела?"
},
"shutdown": {
"title": "Планирано изключване",
"description": "Изключване на свързания възел след x минути."
},
"traceRoute": {
"routeToDestination": "Route to destination:",
"routeBack": "Route back:"
},
"tracerouteResponse": {
"title": "Traceroute: {{identifier}}"
},
"unsafeRoles": {
"confirmUnderstanding": "Да, знам какво правя",
"conjunction": "и публикацията в блога за ",
"postamble": " и разберам последиците от промяната на ролята.",
"preamble": "Аз прочетох ",
"choosingRightDeviceRole": "Избор на правилната роля на устройството",
"deviceRoleDocumentation": "Документация за ролите на устройството",
"title": "Сигурни ли сте?"
},
"managedMode": {
"confirmUnderstanding": "Да, знам какво правя",
"title": "Сигурни ли сте?",
"description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration."
},
"clientNotification": {
"title": "Client Notification",
"TraceRoute can only be sent once every 30 seconds": "TraceRoute can only be sent once every 30 seconds",
"Compromised keys were detected and regenerated.": "Бяха открити и регенерирани компрометирани ключове."
},
"resetNodeDb": {
"title": "Reset Node Database",
"description": "This will clear all nodes from the connected device's node database and clear all message history in the client. This cannot be undone. Are you sure you want to continue?",
"confirm": "Reset Node Database",
"failedTitle": "There was an error resetting the Node DB. Please try again."
},
"clearAllStores": {
"title": "Clear All Local Storage",
"description": "This will clear all locally stored data, including message history and node databases for all previously connected devices. This will require you to reconnect to your node once complete and cannot be undone. Are you sure you want to continue?",
"confirm": "Clear all local storage",
"failedTitle": "There was an error clearing local storage. Please try again."
},
"factoryResetDevice": {
"title": "Фабрично нулиране на устройството",
"description": "This will factory reset the connected device, erasing all configurations and data on the device as well as all nodes and messages saved in the client. This cannot be undone. Are you sure you want to continue?",
"confirm": "Фабрично нулиране на устройството",
"failedTitle": "There was an error performing the factory reset. Please try again."
},
"factoryResetConfig": {
"title": "Фабрично нулиране на конфигурацията",
"description": "This will factory reset the configuration on the connected device, erasing all configurations on the device. This cannot be undone. Are you sure you want to continue?",
"confirm": "Фабрично нулиране на конфигурацията",
"failedTitle": "There was an error performing the factory reset. Please try again."
}
}
@@ -0,0 +1,38 @@
{
"maplibre": {
"GeolocateControl.FindMyLocation": "Намиране на местоположението ми",
"NavigationControl.ZoomIn": "Увеличаване",
"NavigationControl.ZoomOut": "Намаляване",
"CooperativeGesturesHandler.WindowsHelpText": "Use Ctrl + scroll to zoom the map",
"CooperativeGesturesHandler.MacHelpText": "Use ⌘ + scroll to zoom the map",
"CooperativeGesturesHandler.MobileHelpText": "Използвайте два пръста, за да местите картата"
},
"layerTool": {
"nodeMarkers": "Показване на възли",
"directNeighbors": "Показване на директни връзки",
"remoteNeighbors": "Показване на отдалечени връзки",
"positionPrecision": "Show position precision",
"traceroutes": "Show traceroutes",
"waypoints": "Show waypoints"
},
"mapMenu": {
"locateAria": "Locate my node",
"layersAria": "Промяна на стила на картата"
},
"waypointDetail": {
"edit": "Редактирай",
"description": "Описание:",
"createdBy": "Редактирано от:",
"createdDate": "Създадено:",
"updated": "Актуализирано:",
"expires": "Изтича:",
"distance": "Разстояние:",
"bearing": "Absolute bearing:",
"lockedTo": "Заключено от:",
"latitude": "Географска ширина:",
"longitude": "Географска дължина:"
},
"myNode": {
"tooltip": "Това устройство"
}
}

Some files were not shown because too many files have changed in this diff Show More