-
Notifications
You must be signed in to change notification settings - Fork 250
feat(ui): responsive ui updates EVERYONE ELSE = DONT CREATE UI PRs #971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@danditomaso is attempting to deploy a commit to the Meshtastic Team on Vercel. A member of the Team first needs to authorize it. |
|
How is this going @danditomaso - would you like a hand with anything? |
|
It's coming (so is Christmas). I had posted screenshots in the linux-native meshtastic discord channel. Just doing an overhaul of the UI and sneaking in some updates along the way. Should be ready soon, if you have any translation updates to share feel free to make those types of changes
|
- Replace biome with oxlint for linting and oxfmt for formatting - Update lint-staged configuration for new tooling - Add husky pre-commit hook - Fix lint errors in staged files: - Replace biome-ignore comments with eslint-disable-next-line - Fix no-explicit-any errors by using `as never` for dynamic config values - Fix react-hooks/exhaustive-deps warnings with proper suppression comments - Add aria-selected to tab role elements for accessibility - Add variant/size to SidebarMenuButton type definition - Memoize tabs array in ModuleConfig to prevent re-renders - Remove unused imports and fix unused parameter warnings
Inline transport creation directly into ConnectionService, removing the unnecessary strategy abstraction layer: - Delete BluetoothStrategy.ts, SerialStrategy.ts, HttpStrategy.ts, types.ts - Add private methods: createTransport, createHttpTransport, createBluetoothTransport, createSerialTransport, disconnectTransport - Replace ConnectionState.strategy with ConnectionState.connectionType - Transport logic is now ~180 lines in ConnectionService vs 4 separate files This reduces indirection without changing behavior.
Split the monolithic BrowserHardware object into two focused modules: - browserSerial.ts: Web Serial API utilities (hasSerial, getSerialPorts, etc.) - browserBluetooth.ts: Web Bluetooth API utilities (hasBluetooth, etc.) Benefits: - Better tree-shaking: apps only using one transport don't bundle the other - Clearer responsibility separation - Functions exported directly instead of object methods The original BrowserHardware.ts is preserved as a re-export facade for backward compatibility, marked as deprecated. ConnectionService.ts updated to import from the new modules directly.
Split config synchronization logic into dedicated ConfigSyncService: - tryLoadCachedConfig: Load cached config for fast reconnection - saveConfigToCache: Save fresh config after successful connection - saveBaseHashes: Compute and save config hashes for change detection - saveFreshConfig: Combined save operation This reduces ConnectionService from 917 to 828 lines while creating a focused 175-line ConfigSyncService for cache and hash management. The new service uses a ConfigSyncContext interface to receive only the device properties it needs, improving testability.
Connection Recovery Fixes: - Add smart auto-reconnect with 30-minute threshold - Fast recovery mode: skip config sync when < 30 min with cached config - Full recovery mode: complete config sync when > 30 min or no cache - Add fallback from fast to full recovery on connection failure - Add toast notifications for recovery status feedback - Fix serial stream lock error with forceReleaseStreams() utility - Detect and cleanup locked streams before creating new transport Code Quality Migration: - Remove Biome and migrate to oxlint/oxfmt (already configured at repo root) - Remove all biome-ignore comments (8 locations) - Convert MigrationService class to regular functions - Update all imports from MigrationService to deleteDeviceData - Remove Biome scripts from package.json Files Changed: - ConnectionService.ts: Smart recovery logic with toast notifications - transportFactory.ts: Stream lock detection and cleanup - browserSerial.ts: forceReleaseStreams() utility - migrationService.ts: Convert class to functions - Multiple dialog components: Update imports - Remove biome-ignore comments from footer, checkbox test, MessageInput, ConnectPage, store test Fixes issues: - Settings page stuck in loading state - Serial stream lock errors on reconnection - Duplicate connection attempts wiping config data
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR performs a large UI and architecture reshuffle in packages/web, updates core transport/stream handling (serial + packet decode/queue), adds a new mock transport package, and revises i18n strings and tooling (lint/format + git hooks).
Changes:
- Migrates web app structure to a new
src/app/*layout with TanStack Router, sidebar layout, and updated shared UI imports/mocks. - Adds
@meshtastic/transport-mockpackage utilities and updates serial transport + core packet stream/queue behavior. - Removes vendored/proxy protobuf/UI package files and updates i18n strings + developer tooling (Oxlint/Oxfmt + Husky).
Reviewed changes
Copilot reviewed 177 out of 754 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/web/src/components/Dialog/TracerouteResponseDialog.tsx | Removes legacy dialog component (likely migrated/replaced elsewhere). |
| packages/web/src/components/Dialog/RefreshKeysDialog/useRefreshKeysDialog.ts | Removes hook for legacy refresh keys dialog. |
| packages/web/src/components/Dialog/RefreshKeysDialog/RefreshKeysDialog.tsx | Removes legacy refresh keys dialog UI. |
| packages/web/src/components/Dialog/PkiRegenerateDialog.tsx | Removes legacy PKI regenerate dialog. |
| packages/web/src/components/Dialog/PKIBackupDialog.tsx | Removes legacy PKI backup dialog UI/print/download logic. |
| packages/web/src/components/Dialog/NewDeviceDialog.tsx | Removes legacy new device dialog UI. |
| packages/web/src/components/Dialog/LocationResponseDialog.tsx | Removes legacy location response dialog UI. |
| packages/web/src/components/Dialog/ImportDialog.tsx | Removes legacy import dialog UI. |
| packages/web/src/components/Dialog/DialogManager.tsx | Removes legacy dialog manager mounting point. |
| packages/web/src/components/Dialog/ClearAllStoresDialog/ClearAllStoresDialog.tsx | Removes “Clear All Stores” dialog wrapper usage. |
| packages/web/src/components/Dialog/ClearAllStoresDialog/ClearAllStoresDialog.test.tsx | Removes tests for removed ClearAllStoresDialog. |
| packages/web/src/app/routerContext.ts | Adds typed router context surface (services/repos/stores). |
| packages/web/src/app/router.ts | Adds TanStack router instance. |
| packages/web/src/app/layouts/index.ts | Exports new app layout components. |
| packages/web/src/app/layouts/AppLayout.tsx | Adds new app layout using sidebar/tooltip/Separator and new DialogManager. |
| packages/web/src/app/index.ts | Adds new app entry exports. |
| packages/web/src/app/App.tsx | Adds new app root wiring ThemeProvider + SidebarProvider + Outlet. |
| packages/web/src/mocks/components/UI/Link.tsx | Updates mock to new shared UI link import path. |
| packages/web/src/mocks/components/UI/Label.tsx | Updates mock to new shared UI label import path. |
| packages/web/src/mocks/components/UI/Checkbox.tsx | Updates mock to new shared UI checkbox import path. |
| packages/web/src/mocks/components/UI/Button.tsx | Updates mock to new shared UI button import path. |
| packages/web/src/mocks/README.md | Updates mock documentation/examples to new import paths. |
| packages/web/src/DeviceWrapper.tsx | Removes legacy CurrentDeviceContext wrapper. |
| packages/web/src/App.tsx | Removes old app root/layout plumbing (dialogs, connections fallback, devtools, etc.). |
| packages/web/public/i18n/locales/zh-TW/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/zh-TW/dialog.json | Removes <br /> from import dialog description string. |
| packages/web/public/i18n/locales/zh-CN/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/uk-UA/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/tr-TR/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/sv-SE/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/ru-RU/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/ru-RU/dialog.json | Removes <br /> from import dialog description string. |
| packages/web/public/i18n/locales/pt-PT/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/pt-BR/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/pl-PL/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/nl-NL/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/ko-KR/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/ja-JP/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/it-IT/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/hu-HU/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/fr-FR/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/fi-FI/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/es-ES/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/en/ui.json | Restructures UI i18n keys and adds large Preferences section + new nav labels. |
| packages/web/public/i18n/locales/en/nodes.json | Expands nodes page/table strings and headings. |
| packages/web/public/i18n/locales/en/moduleConfig.json | Renames moduleConfig page tab keys. |
| packages/web/public/i18n/locales/en/messages.json | Restructures messages i18n keys (input/actions/delivery status). |
| packages/web/public/i18n/locales/en/map.json | Adds “positionTrails” label. |
| packages/web/public/i18n/locales/en/dialog.json | Adds deviceShare/removeDevice; removes clearAllStores section; tweaks import description. |
| packages/web/public/i18n/locales/en/connections.json | Adds status/button strings and adjusts empty-state description. |
| packages/web/public/i18n/locales/en/config.json | Adds extensive settings/config i18n structure and database strings. |
| packages/web/public/i18n/locales/en/common.json | Adds extra button labels and unit strings. |
| packages/web/public/i18n/locales/en/commandPalette.json | Removes commandPalette “clearAllStores” entry. |
| packages/web/public/i18n/locales/en/channels.json | Adds user name validation strings. |
| packages/web/public/i18n/locales/de-DE/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/cs-CZ/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/bg-BG/ui.json | Removes <br /> from error page description string. |
| packages/web/public/i18n/locales/be-BY/ui.json | Removes <br /> from error page description string. |
| packages/web/index.html | Switches favicon SVG from /icon.svg to /logo.svg. |
| packages/web/drizzle.config.ts | Adds drizzle-kit config for SQLite migrations/schema paths. |
| packages/web/components.json | Adds shadcn/ui components config for web package. |
| packages/ui/vite.config.ts | Removes UI package build config (package appears removed). |
| packages/ui/tsconfig.json | Removes UI package TS config. |
| packages/ui/src/lib/utils.ts | Removes UI package cn helper (package appears removed). |
| packages/ui/src/lib/theme/default.css | Removes UI package default theme CSS export. |
| packages/ui/src/lib/components/theme-toggle.tsx | Removes UI package ThemeToggle component. |
| packages/ui/src/lib/components/index.ts | Removes UI package components barrel export. |
| packages/ui/src/lib/components/Sidebar/AppSidebar.tsx | Removes UI package AppSidebar component implementation. |
| packages/ui/src/index.ts | Removes UI package public exports. |
| packages/ui/src/hooks/use-mobile.ts | Removes UI package mobile hook. |
| packages/ui/src/components/ui/tooltip.tsx | Removes UI package tooltip component. |
| packages/ui/src/components/ui/skeleton.tsx | Removes UI package skeleton component. |
| packages/ui/src/components/ui/sheet.tsx | Removes UI package sheet component. |
| packages/ui/src/components/ui/separator.tsx | Removes UI package separator component. |
| packages/ui/src/components/ui/input.tsx | Removes UI package input component. |
| packages/ui/src/components/ui/dropdown-menu.tsx | Removes UI package dropdown menu component. |
| packages/ui/src/components/ui/collapsible.tsx | Removes UI package collapsible component. |
| packages/ui/src/components/ui/button.tsx | Removes UI package button component. |
| packages/ui/src/components/ui/badge.tsx | Removes UI package badge component. |
| packages/ui/src/components/theme-provider.tsx | Removes UI package theme provider. |
| packages/ui/src/app.css | Removes UI package app color-scheme CSS. |
| packages/ui/package.json | Removes UI package manifest (package appears removed). |
| packages/ui/components.json | Removes UI package shadcn config. |
| packages/transport-web-serial/src/transport.ts | Adds extra serial debug logging and tweaks disconnect handling comments/errors. |
| packages/transport-web-serial/src/transport.test.ts | Adds regression test ensuring setSignals is not called during connect. |
| packages/transport-mock/tsconfig.json | Adds TS config for new mock transport package. |
| packages/transport-mock/src/scenarios.ts | Adds scenario definitions + helper for mock transport. |
| packages/transport-mock/src/generators/packets.ts | Adds packet generator helpers for mock data. |
| packages/transport-mock/src/generators/nodes.ts | Adds node generator helpers for mock meshes. |
| packages/transport-mock/src/generators/index.ts | Adds generator barrel exports. |
| packages/transport-mock/package.json | Adds new package manifest and build/publish scripts. |
| packages/transport-mock/mod.ts | Adds public entrypoint exports for mock transport package. |
| packages/transport-mock/README.md | Adds documentation for mock transport usage/scenarios. |
| packages/protobufs/packages/ts/mod.ts | Removes workspace protobuf TS entrypoint (vendored protobufs removed). |
| packages/protobufs/packages/ts/deno.json | Removes protobuf package Deno config. |
| packages/protobufs/packages/ts/README.md | Removes protobuf package readme. |
| packages/protobufs/package.json | Removes workspace protobuf package manifest. |
| packages/protobufs/nanopb.proto | Removes nanopb proto file from workspace. |
| packages/protobufs/meshtastic/xmodem.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/xmodem.options | Removes nanopb options. |
| packages/protobufs/meshtastic/telemetry.options | Removes nanopb options. |
| packages/protobufs/meshtastic/storeforward.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/storeforward.options | Removes nanopb options. |
| packages/protobufs/meshtastic/rtttl.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/rtttl.options | Removes nanopb options. |
| packages/protobufs/meshtastic/remote_hardware.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/powermon.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/portnums.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/paxcount.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/mqtt.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/mqtt.options | Removes nanopb options. |
| packages/protobufs/meshtastic/module_config.options | Removes nanopb options. |
| packages/protobufs/meshtastic/mesh.options | Removes nanopb options. |
| packages/protobufs/meshtastic/localonly.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/interdevice.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/interdevice.options | Removes nanopb options. |
| packages/protobufs/meshtastic/deviceonly.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/deviceonly.options | Removes nanopb options. |
| packages/protobufs/meshtastic/device_ui.options | Removes nanopb options. |
| packages/protobufs/meshtastic/connection_status.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/connection_status.options | Removes nanopb options. |
| packages/protobufs/meshtastic/config.options | Removes nanopb options. |
| packages/protobufs/meshtastic/clientonly.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/clientonly.options | Removes nanopb options. |
| packages/protobufs/meshtastic/channel.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/channel.options | Removes nanopb options. |
| packages/protobufs/meshtastic/cannedmessages.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/cannedmessages.options | Removes nanopb options. |
| packages/protobufs/meshtastic/atak.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/atak.options | Removes nanopb options. |
| packages/protobufs/meshtastic/apponly.proto | Removes vendored proto definition. |
| packages/protobufs/meshtastic/apponly.options | Removes nanopb options. |
| packages/protobufs/meshtastic/admin.options | Removes nanopb options. |
| packages/protobufs/deno.json | Removes protobuf package root Deno config. |
| packages/protobufs/buf.yaml | Removes buf workspace config. |
| packages/protobufs/buf.gen.yaml | Removes buf codegen config. |
| packages/protobufs/README.md | Removes protobuf package readme. |
| packages/protobufs/.vscode/settings.json | Removes editor settings for protobuf package. |
| packages/protobufs/.vscode/extensions.json | Removes extension recommendations for protobuf package. |
| packages/protobufs/.gitmodules | Removes protobuf submodule config. |
| packages/protobufs/.gitignore | Removes protobuf package ignore file. |
| packages/protobufs/.github/workflows/pull_request.yml | Removes protobuf package CI workflow. |
| packages/protobufs/.github/workflows/publish.yml | Removes protobuf package publish workflow. |
| packages/protobufs/.github/workflows/create_tag.yml | Removes protobuf package tag workflow. |
| packages/protobufs/.github/workflows/ci.yml | Removes protobuf package CI workflow. |
| packages/protobufs/.github/pull_request_template.md | Removes protobuf package PR template. |
| packages/protobufs/.gitattributes | Removes protobuf package attributes file. |
| packages/core/src/utils/transform/fromDevice.ts | Refactors framing parser to emit debug data and recover from malformed headers. |
| packages/core/src/utils/transform/fromDevice.test.ts | Adds test coverage for garbage/broken header recovery and valid packet parsing. |
| packages/core/src/utils/transform/decodePacket.ts | Adjusts log levels/messages when decoding packets/config/channel. |
| packages/core/src/utils/queue.ts | Changes timeout/ack behavior and adds debug logging for queued/sent packets. |
| packages/core/src/utils/mod.ts | Exports new decodePayload utilities from utils module. |
| packages/core/src/utils/decodePayload.ts | Adds portnum-based payload decoding + JSON conversion utilities. |
| packages/core/src/types.ts | Extends PacketMetadata with reply/emoji and hop fields. |
| packages/core/src/meshDevice.ts | Adds pipeline completion logging, two-stage configure flow, and ACK dispatch logic. |
| package.json | Switches tooling to oxlint/oxfmt and sets up husky + lint-staged; bumps protobufs version. |
| biome.json | Removes Biome config. |
| .oxlintrc.json | Adds oxlint configuration. |
| .oxfmtrc.json | Adds oxfmt configuration. |
| .husky/pre-commit | Adds husky pre-commit hook to run lint-staged. |
| .githooks/_/pre-commit | Removes simple-git-hooks pre-commit hook script. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| rxRssi: meshPacket.rxRssi, | ||
| rxSnr: meshPacket.rxSnr, | ||
| viaMqtt: meshPacket.viaMqtt, | ||
| replyId: dataPacket.replyId, | ||
| emoji: dataPacket.emoji, | ||
| }; |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PacketMetadata was updated to include required hop fields (hopsLimit, hopsStart), but the metadata object constructed here does not supply them. This will either fail TypeScript compilation or produce incomplete metadata at runtime. Populate these fields from the underlying mesh packet (e.g., meshPacket.hopLimit/meshPacket.hopStart`) or make the new fields optional if they are not always available.
| this.updateMessageACK(dataPacket.requestId, { | ||
| receivedACK: true, | ||
| ackError: routingPacket.variant.value, | ||
| ackTimestamp: meshPacket.rxTime || Date.now(), |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ackTimestampmixes units:meshPacket.rxTimeappears to be seconds-since-epoch, whileDate.now()is milliseconds. Downstream code multipliesackTimestamp * 1000when creating aDate, which will be incorrect if the fallback path is hit. Use consistent units (preferred: seconds everywhere, e.g. meshPacket.rxTime ?? Math.floor(Date.now() / 1000)) and avoid ||here sincerxTimecould be0` (unlikely but semantically wrong).
| ackTimestamp: meshPacket.rxTime || Date.now(), | |
| ackTimestamp: meshPacket.rxTime ?? Math.floor(Date.now() / 1000), |
| (async () => { | ||
| while (true) { | ||
| const { value, done } = await reader.read(); | ||
| if (done) break; | ||
| received.push(value); | ||
| } | ||
| })(); | ||
|
|
||
| // 1. Send garbage data (no 0x94) | ||
| await writer.write(new Uint8Array([0x01, 0x02, 0x03])); | ||
|
|
||
| // 2. Send broken header (0x94 but not 0xc3) | ||
| await writer.write(new Uint8Array([0x94, 0x00, 0x04])); | ||
|
|
||
| // 3. Send valid packet (0x94 0xc3 0x00 0x01 0xAA) (len 1) | ||
| // Header: 94 C3 00 01. Payload: AA. | ||
| await writer.write(new Uint8Array([0x94, 0xc3, 0x00, 0x01, 0xAA])); | ||
|
|
||
| // Give it a moment to process | ||
| await new Promise(resolve => setTimeout(resolve, 100)); |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is timing-dependent and may be flaky on slower CI runners: it relies on a fixed setTimeout(100) and does not await the background read loop completion before asserting. Prefer awaiting reads deterministically (e.g., read until you receive a packet output or until reader.read() returns done, with an explicit timeout) to make the test reliable and faster.`
| "system": "Automatic", | ||
| "changeTheme": "Change Color Scheme" | ||
| }, | ||
| "configProgres": "Loading conifg {{received}}/{{total}}", |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new key/value contains typos: configProgres and conifg. This is likely to leak into UI text and also makes the key easy to mis-reference. Consider renaming the key to configProgress and correcting the string to “Loading config {{received}}/{{total}}”.`
| "configProgres": "Loading conifg {{received}}/{{total}}", | |
| "configProgress": "Loading config {{received}}/{{total}}", |
| /** | ||
| * REGRESSION TEST: setSignals() must NOT be called during connection. | ||
| * | ||
| * Calling setSignals({ dataTerminalReady: false, requestToSend: false }) | ||
| * prevents the device from responding to config requests. This was | ||
| * discovered when the connection would hang during configureTwoStage(). | ||
| * | ||
| * See: https://github.com/meshtastic/meshtastic-web/issues/XXX | ||
| */ | ||
| it("does NOT call setSignals during connection (regression)", async () => { | ||
| const fake = new FakeSerialPort(); | ||
| const transport = await TransportWebSerial.createFromPort(fake as any); | ||
|
|
||
| // Wait for connection to be established | ||
| const reader = transport.fromDevice.getReader(); | ||
| for (let i = 0; i < 3; i++) { | ||
| const { value } = await reader.read(); | ||
| if (value?.type === "status" && value.data.status === Types.DeviceStatusEnum.DeviceConnected) { | ||
| break; | ||
| } | ||
| } |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two issues here: (1) the issue link placeholder issues/XXX should be replaced with a real issue or removed; and (2) the for (let i = 0; i < 3; i++) read loop may be flaky if more than 3 status messages are emitted before DeviceConnected (or if timing differs). Consider looping until connected with an explicit timeout (or a helper that waits for a specific status event) to make the test deterministic.`
- Fix i18n locale loading to use base language codes (e.g., 'en' instead of 'en-GB') - Prevents 404 errors when browser requests specific locale variants - Uses custom loadPath function to extract base language code - Remove missing logo_black.svg reference from index.html - Ensure all asset paths are absolute for consistency Fixes 404 errors: - /i18n/locales/en-GB/*.json -> now loads from /i18n/locales/en/*.json - /logo_black.svg (file did not exist) -> removed reference
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Description
This will touch most of the components in the UI, if you open a PR relating to any of the UI components this will cause a merge conflict. Hold off until this has been merged.
Related Issues
Changes Made
Testing Done
Screenshots (if applicable)
Checklist
CONTRIBUTING_I18N_DEVELOPER_GUIDE.md for more details)