Skip to content

Commit b888d8f

Browse files
authored
Merge branch 'master' into feat/add-error-boundary
2 parents d978978 + e224a4e commit b888d8f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+378
-320
lines changed

.npmrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
@buf:registry=https://buf.build/gen/npm/v1
1+
@jsr:registry=https://npm.jsr.io

bun.lock

+147-139
Large diffs are not rendered by default.

package.json

+23-20
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@
3737
},
3838
"homepage": "https://meshtastic.org",
3939
"dependencies": {
40-
"@bufbuild/protobuf": "^1.10.0",
41-
"@meshtastic/js": "2.3.7-5",
40+
"@bufbuild/protobuf": "^2.2.3",
41+
"@meshtastic/core": "npm:@jsr/[email protected]",
42+
"@meshtastic/js": "npm:@jsr/[email protected]",
43+
"@meshtastic/transport-http": "npm:@jsr/meshtastic__transport-http",
44+
"@meshtastic/transport-web-serial": "npm:@jsr/meshtastic__transport-web-serial",
4245
"@noble/curves": "^1.8.1",
4346
"@radix-ui/react-accordion": "^1.2.3",
4447
"@radix-ui/react-checkbox": "^1.1.4",
@@ -63,45 +66,45 @@
6366
"crypto-random-string": "^5.0.0",
6467
"immer": "^10.1.1",
6568
"js-cookie": "^3.0.5",
66-
"lucide-react": "^0.475.0",
67-
"mapbox-gl": "^3.9.4",
68-
"maplibre-gl": "4.1.2",
69+
"lucide-react": "^0.477.0",
70+
"mapbox-gl": "^3.10.0",
71+
"maplibre-gl": "5.1.1",
6972
"react": "^19.0.0",
7073
"react-dom": "^19.0.0",
7174
"react-error-boundary": "^5.0.0",
7275
"react-hook-form": "^7.54.2",
73-
"react-map-gl": "7.1.9",
76+
"react-map-gl": "8.0.1",
7477
"react-qrcode-logo": "^3.0.0",
75-
"react-scan": "^0.2.4",
78+
"react-scan": "^0.2.8",
7679
"rfc4648": "^1.5.4",
7780
"vite-plugin-node-polyfills": "^0.23.0",
7881
"zustand": "5.0.3"
7982
},
8083
"devDependencies": {
8184
"@biomejs/biome": "^1.9.4",
82-
"@tailwindcss/postcss": "^4.0.7",
85+
"@tailwindcss/postcss": "^4.0.9",
8386
"@testing-library/react": "^16.2.0",
84-
"@types/chrome": "^0.0.304",
87+
"@types/chrome": "^0.0.307",
8588
"@types/js-cookie": "^3.0.6",
86-
"@types/node": "^22.13.4",
89+
"@types/node": "^22.13.7",
8790
"@types/react": "^19.0.10",
8891
"@types/react-dom": "^19.0.4",
89-
"@types/serviceworker": "^0.0.122",
90-
"@types/w3c-web-serial": "^1.0.7",
91-
"@types/web-bluetooth": "^0.0.20",
92+
"@types/serviceworker": "^0.0.123",
93+
"@types/w3c-web-serial": "^1.0.8",
94+
"@types/web-bluetooth": "^0.0.21",
9295
"@vitejs/plugin-react": "^4.3.4",
9396
"autoprefixer": "^10.4.20",
9497
"gzipper": "^8.2.0",
95-
"happy-dom": "^17.1.4",
96-
"postcss": "^8.5.1",
98+
"happy-dom": "^17.1.8",
99+
"postcss": "^8.5.3",
97100
"simple-git-hooks": "^2.11.1",
98-
"tailwind-merge": "^3.0.1",
99-
"tailwindcss": "^4.0.7",
101+
"tailwind-merge": "^3.0.2",
102+
"tailwindcss": "^4.0.9",
100103
"tailwindcss-animate": "^1.0.7",
101104
"tar": "^7.4.3",
102-
"typescript": "^5.7.3",
103-
"vite": "^6.1.1",
105+
"typescript": "^5.8.2",
106+
"vite": "^6.2.0",
104107
"vite-plugin-pwa": "^0.21.1",
105-
"vitest": "^3.0.6"
108+
"vitest": "^3.0.7"
106109
}
107110
}

src/App.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ import { useDeviceStore } from "@core/stores/deviceStore.ts";
1313
import { Dashboard } from "@pages/Dashboard/index.tsx";
1414
import type { JSX } from "react";
1515
import { ErrorBoundary } from "react-error-boundary";
16-
import { MapProvider } from "react-map-gl";
1716
import { ErrorPage } from "./components/UI/ErrorPage";
17+
import { MapProvider } from "react-map-gl/maplibre";
18+
1819

1920
export const App = (): JSX.Element => {
2021
const { getDevice } = useDeviceStore();

src/components/Dialog/DeviceNameDialog.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useDevice } from "@app/core/stores/deviceStore.ts";
2+
import { create } from "@bufbuild/protobuf";
23
import { Button } from "@components/UI/Button.tsx";
34
import {
45
Dialog,
@@ -10,7 +11,7 @@ import {
1011
} from "@components/UI/Dialog.tsx";
1112
import { Input } from "@components/UI/Input.tsx";
1213
import { Label } from "@components/UI/Label.tsx";
13-
import { Protobuf } from "@meshtastic/js";
14+
import { Protobuf } from "@meshtastic/core";
1415
import { useForm } from "react-hook-form";
1516

1617
export interface User {
@@ -40,7 +41,7 @@ export const DeviceNameDialog = ({
4041

4142
const onSubmit = handleSubmit((data) => {
4243
connection?.setOwner(
43-
new Protobuf.Mesh.User({
44+
create(Protobuf.Mesh.UserSchema, {
4445
...myNode?.user,
4546
...data,
4647
}),

src/components/Dialog/ImportDialog.tsx

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { create, fromBinary } from "@bufbuild/protobuf";
12
import { Button } from "@components/UI/Button.tsx";
23
import { Checkbox } from "@components/UI/Checkbox.tsx";
34
import {
@@ -12,7 +13,7 @@ import { Input } from "@components/UI/Input.tsx";
1213
import { Label } from "@components/UI/Label.tsx";
1314
import { Switch } from "@components/UI/Switch.tsx";
1415
import { useDevice } from "@core/stores/deviceStore.ts";
15-
import { Protobuf } from "@meshtastic/js";
16+
import { Protobuf } from "@meshtastic/core";
1617
import { toByteArray } from "base64-js";
1718
import { type JSX, useEffect, useState } from "react";
1819

@@ -55,7 +56,10 @@ export const ImportDialog = ({
5556
.replace(/-/g, "+")
5657
.replace(/_/g, "/");
5758
setChannelSet(
58-
Protobuf.AppOnly.ChannelSet.fromBinary(toByteArray(paddedString)),
59+
fromBinary(
60+
Protobuf.AppOnly.ChannelSetSchema,
61+
toByteArray(paddedString),
62+
),
5963
);
6064
setValidUrl(true);
6165
} catch (error) {
@@ -67,7 +71,7 @@ export const ImportDialog = ({
6771
const apply = () => {
6872
channelSet?.settings.map((ch: unknown, index: number) => {
6973
connection?.setChannel(
70-
new Protobuf.Channel.Channel({
74+
create(Protobuf.Channel.ChannelSchema, {
7175
index,
7276
role:
7377
index === 0
@@ -80,7 +84,7 @@ export const ImportDialog = ({
8084

8185
if (channelSet?.loraConfig) {
8286
connection?.setConfig(
83-
new Protobuf.Config.Config({
87+
create(Protobuf.Config.ConfigSchema, {
8488
payloadVariant: {
8589
case: "lora",
8690
value: channelSet.loraConfig,

src/components/Dialog/LocationResponseDialog.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
DialogHeader,
77
DialogTitle,
88
} from "@components/UI/Dialog";
9-
import type { Protobuf, Types } from "@meshtastic/js";
9+
import type { Protobuf, Types } from "@meshtastic/core";
1010
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
1111
import type { JSX } from "react";
1212

@@ -44,7 +44,9 @@ export const LocationResponseDialog = ({
4444
Coordinates:{" "}
4545
<a
4646
className="text-blue-500 dark:text-blue-400"
47-
href={`https://www.openstreetmap.org/?mlat=${location?.data.latitudeI / 1e7}&mlon=${location?.data.longitudeI / 1e7}&layers=N`}
47+
href={`https://www.openstreetmap.org/?mlat=${
48+
location?.data.latitudeI / 1e7
49+
}&mlon=${location?.data.longitudeI / 1e7}&layers=N`}
4850
target="_blank"
4951
rel="noreferrer"
5052
>

src/components/Dialog/NodeDetailsDialog.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
DialogHeader,
1414
DialogTitle,
1515
} from "@components/UI/Dialog";
16-
import { Protobuf } from "@meshtastic/js";
16+
import { Protobuf } from "@meshtastic/core";
1717
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
1818
import { DeviceImage } from "../generic/DeviceImage";
1919
import { TimeAgo } from "../generic/TimeAgo";
@@ -87,7 +87,9 @@ export const NodeDetailsDialog = ({
8787
Coordinates:{" "}
8888
<a
8989
className="text-blue-500 dark:text-blue-400"
90-
href={`https://www.openstreetmap.org/?mlat=${device.position.latitudeI / 1e7}&mlon=${device.position.longitudeI / 1e7}&layers=N`}
90+
href={`https://www.openstreetmap.org/?mlat=${
91+
device.position.latitudeI / 1e7
92+
}&mlon=${device.position.longitudeI / 1e7}&layers=N`}
9193
target="_blank"
9294
rel="noreferrer"
9395
>

src/components/Dialog/NodeOptionsDialog.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
DialogHeader,
88
DialogTitle,
99
} from "@components/UI/Dialog";
10-
import type { Protobuf } from "@meshtastic/js";
10+
import type { Protobuf } from "@meshtastic/core";
1111
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
1212
import { TrashIcon } from "lucide-react";
1313
import type { JSX } from "react";

src/components/Dialog/QRDialog.tsx

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { create, toBinary } from "@bufbuild/protobuf";
12
import { Checkbox } from "@components/UI/Checkbox.tsx";
23
import {
34
Dialog,
@@ -9,7 +10,7 @@ import {
910
} from "@components/UI/Dialog.tsx";
1011
import { Input } from "@components/UI/Input.tsx";
1112
import { Label } from "@components/UI/Label.tsx";
12-
import { Protobuf, type Types } from "@meshtastic/js";
13+
import { Protobuf, type Types } from "@meshtastic/core";
1314
import { fromByteArray } from "base64-js";
1415
import { ClipboardIcon } from "lucide-react";
1516
import { useEffect, useMemo, useState } from "react";
@@ -39,13 +40,16 @@ export const QRDialog = ({
3940
.filter((ch) => selectedChannels.includes(ch.index))
4041
.map((channel) => channel.settings)
4142
.filter((ch): ch is Protobuf.Channel.ChannelSettings => !!ch);
42-
const encoded = new Protobuf.AppOnly.ChannelSet(
43-
new Protobuf.AppOnly.ChannelSet({
43+
const encoded = create(
44+
Protobuf.AppOnly.ChannelSetSchema,
45+
create(Protobuf.AppOnly.ChannelSetSchema, {
4446
loraConfig,
4547
settings: channelsToEncode,
4648
}),
4749
);
48-
const base64 = fromByteArray(encoded.toBinary())
50+
const base64 = fromByteArray(
51+
toBinary(Protobuf.AppOnly.ChannelSetSchema, encoded),
52+
)
4953
.replace(/=/g, "")
5054
.replace(/\+/g, "-")
5155
.replace(/\//g, "_");

src/components/Dialog/TracerouteResponseDialog.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
DialogHeader,
77
DialogTitle,
88
} from "@components/UI/Dialog";
9-
import type { Protobuf, Types } from "@meshtastic/js";
9+
import type { Protobuf, Types } from "@meshtastic/core";
1010
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
1111
import type { JSX } from "react";
1212
import { TraceRoute } from "../PageComponents/Messages/TraceRoute";

src/components/Form/DynamicForm.tsx

+21-18
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,27 @@ export function DynamicForm<T extends FieldValues>({
100100
<Subtle>{fieldGroup.description}</Subtle>
101101
</div>
102102

103-
{fieldGroup.fields.map((field) => (
104-
<FieldWrapper
105-
key={field.label}
106-
label={field.label}
107-
description={field.description}
108-
valid={
109-
field.validationText === undefined ||
110-
field.validationText === ""
111-
}
112-
validationText={field.validationText}
113-
>
114-
<DynamicFormField
115-
field={field}
116-
control={control}
117-
disabled={isDisabled(field.disabledBy, field.disabled)}
118-
/>
119-
</FieldWrapper>
120-
))}
103+
{fieldGroup.fields.map((field) => {
104+
return (
105+
<FieldWrapper
106+
key={field.label}
107+
label={field.label}
108+
fieldName={field.name}
109+
description={field.description}
110+
valid={
111+
field.validationText === undefined ||
112+
field.validationText === ""
113+
}
114+
validationText={field.validationText}
115+
>
116+
<DynamicFormField
117+
field={field}
118+
control={control}
119+
disabled={isDisabled(field.disabledBy, field.disabled)}
120+
/>
121+
</FieldWrapper>
122+
);
123+
})}
121124
</div>
122125
))}
123126
{hasSubmitButton && <Button type="submit">Submit</Button>}

src/components/Form/FormInput.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export function GenericInput<T extends FieldValues>({
5353
}
5454
step={field.properties?.step}
5555
value={field.type === "number" ? Number.parseFloat(value) : value}
56+
id={field.name}
5657
onChange={(e) => {
5758
if (field.inputChange) field.inputChange(e);
5859
onChange(

src/components/Form/FormPasswordGenerator.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Controller, type FieldValues } from "react-hook-form";
1111

1212
export interface PasswordGeneratorProps<T> extends BaseFormBuilderProps<T> {
1313
type: "passwordGenerator";
14+
id: string;
1415
hide?: boolean;
1516
bits?: { text: string; value: string; key: string }[];
1617
devicePSKBitCount: number;
@@ -41,6 +42,7 @@ export function PasswordGenerator<T extends FieldValues>({
4142
render={({ field: { value, ...rest } }) => (
4243
<Generator
4344
type={field.hide && !passwordShown ? "password" : "text"}
45+
id={field.id}
4446
action={
4547
field.hide
4648
? {

src/components/Form/FormSelect.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export function SelectInput<T extends FieldValues>({
5050
{...remainingProperties}
5151
{...rest}
5252
>
53-
<SelectTrigger>
53+
<SelectTrigger id={field.name}>
5454
<SelectValue />
5555
</SelectTrigger>
5656
<SelectContent>

src/components/Form/FormToggle.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export function ToggleInput<T extends FieldValues>({
3333
<Switch
3434
checked={value}
3535
onCheckedChange={onChangeHandler(onChange)}
36+
id={field.name}
3637
disabled={disabled}
3738
{...field.properties}
3839
{...rest}

src/components/Form/FormWrapper.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Label } from "@components/UI/Label.tsx";
22

33
export interface FieldWrapperProps {
44
label: string;
5+
fieldName: string;
56
description?: string;
67
disabled?: boolean;
78
children?: React.ReactNode;
@@ -11,6 +12,7 @@ export interface FieldWrapperProps {
1112

1213
export const FieldWrapper = ({
1314
label,
15+
fieldName,
1416
description,
1517
children,
1618
valid,
@@ -19,7 +21,7 @@ export const FieldWrapper = ({
1921
<div className="pt-6 sm:pt-5">
2022
<fieldset aria-labelledby="label-notifications">
2123
<div className="sm:grid sm:grid-cols-3 sm:items-baseline sm:gap-4">
22-
<Label>{label}</Label>
24+
<Label htmlFor={fieldName}>{label}</Label>
2325
<div className="sm:col-span-2">
2426
<div className="max-w-lg">
2527
<p className="text-sm text-slate-500">{description}</p>

src/components/PageComponents/Channel.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { ChannelValidation } from "@app/validation/channel.tsx";
2+
import { create } from "@bufbuild/protobuf";
23
import { DynamicForm } from "@components/Form/DynamicForm.tsx";
34
import { useToast } from "@core/hooks/useToast.ts";
45
import { useDevice } from "@core/stores/deviceStore.ts";
5-
import { Protobuf } from "@meshtastic/js";
6+
import { Protobuf } from "@meshtastic/core";
67
import { fromByteArray, toByteArray } from "base64-js";
78
import cryptoRandomString from "crypto-random-string";
89
import { useState } from "react";
@@ -27,7 +28,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => {
2728
useState<boolean>(false);
2829

2930
const onSubmit = (data: ChannelValidation) => {
30-
const channel = new Protobuf.Channel.Channel({
31+
const channel = create(Protobuf.Channel.ChannelSchema, {
3132
...data,
3233
settings: {
3334
...data.settings,

0 commit comments

Comments
 (0)