Multiple theme support & fixes
This commit is contained in:
@@ -111,7 +111,6 @@ export const Map = (): JSX.Element => {
|
||||
</div>
|
||||
))}
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
append({
|
||||
enabled: true,
|
||||
|
||||
@@ -84,46 +84,47 @@ export const LoRa = (): JSX.Element => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Select
|
||||
label="Preset"
|
||||
description="Modem preset to use"
|
||||
disabled={!usePreset}
|
||||
{...register("modemPreset", { valueAsNumber: true })}
|
||||
>
|
||||
{renderOptions(Protobuf.Config_LoRaConfig_ModemPreset)}
|
||||
</Select>
|
||||
<Input
|
||||
label="Bandwidth"
|
||||
description="Channel bandwidth in MHz"
|
||||
type="number"
|
||||
suffix="MHz"
|
||||
error={errors.bandwidth?.message}
|
||||
{...register("bandwidth", {
|
||||
valueAsNumber: true
|
||||
})}
|
||||
disabled={usePreset}
|
||||
/>
|
||||
<Input
|
||||
label="Spread Factor"
|
||||
description="Indicates the number of chirps per symbol"
|
||||
type="number"
|
||||
suffix="CPS"
|
||||
error={errors.spreadFactor?.message}
|
||||
{...register("spreadFactor", {
|
||||
valueAsNumber: true
|
||||
})}
|
||||
disabled={usePreset}
|
||||
/>
|
||||
<Input
|
||||
label="Coding Rate"
|
||||
description="The denominator of the coding rate"
|
||||
type="number"
|
||||
error={errors.codingRate?.message}
|
||||
{...register("codingRate", {
|
||||
valueAsNumber: true
|
||||
})}
|
||||
disabled={usePreset}
|
||||
/>
|
||||
{usePreset ? (
|
||||
<Select
|
||||
label="Preset"
|
||||
description="Modem preset to use"
|
||||
{...register("modemPreset", { valueAsNumber: true })}
|
||||
>
|
||||
{renderOptions(Protobuf.Config_LoRaConfig_ModemPreset)}
|
||||
</Select>
|
||||
) : (
|
||||
<>
|
||||
<Input
|
||||
label="Bandwidth"
|
||||
description="Channel bandwidth in MHz"
|
||||
type="number"
|
||||
suffix="MHz"
|
||||
error={errors.bandwidth?.message}
|
||||
{...register("bandwidth", {
|
||||
valueAsNumber: true
|
||||
})}
|
||||
/>
|
||||
<Input
|
||||
label="Spread Factor"
|
||||
description="Indicates the number of chirps per symbol"
|
||||
type="number"
|
||||
suffix="CPS"
|
||||
error={errors.spreadFactor?.message}
|
||||
{...register("spreadFactor", {
|
||||
valueAsNumber: true
|
||||
})}
|
||||
/>
|
||||
<Input
|
||||
label="Coding Rate"
|
||||
description="The denominator of the coding rate"
|
||||
type="number"
|
||||
error={errors.codingRate?.message}
|
||||
{...register("codingRate", {
|
||||
valueAsNumber: true
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</FormSection>
|
||||
<FormSection title="Radio Settings">
|
||||
<Controller
|
||||
|
||||
@@ -73,7 +73,7 @@ export const Position = (): JSX.Element => {
|
||||
}),
|
||||
{
|
||||
loading: "Saving...",
|
||||
success: "Saved Channel",
|
||||
success: "Saved Position Config, Restarting Node",
|
||||
error: "No response received"
|
||||
}
|
||||
);
|
||||
@@ -109,13 +109,17 @@ export const Position = (): JSX.Element => {
|
||||
dirty={isDirty}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<Input
|
||||
suffix="Seconds"
|
||||
label="Broadcast Interval"
|
||||
description="How often your position is sent out over the mesh"
|
||||
type="number"
|
||||
error={errors.positionBroadcastSecs?.message}
|
||||
{...register("positionBroadcastSecs", { valueAsNumber: true })}
|
||||
<Controller
|
||||
name="gpsEnabled"
|
||||
control={control}
|
||||
render={({ field: { value, ...rest } }) => (
|
||||
<Toggle
|
||||
label="GPS Enabled"
|
||||
description="Enable the internal GPS module"
|
||||
checked={value}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="positionBroadcastSmartEnabled"
|
||||
@@ -129,104 +133,13 @@ export const Position = (): JSX.Element => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="fixedPosition"
|
||||
control={control}
|
||||
render={({ field: { value, ...rest } }) => (
|
||||
<Toggle
|
||||
label="Use Fixed Position"
|
||||
description="Don't report GPS position, but a manually-specified one"
|
||||
checked={value}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<FormSection title="Fixed Position">
|
||||
<Input
|
||||
suffix="m"
|
||||
label="Altitude"
|
||||
type="number"
|
||||
error={errors.fixedAlt?.message}
|
||||
disabled={!fixedPositionEnabled}
|
||||
{...register("fixedAlt", { valueAsNumber: true })}
|
||||
/>
|
||||
<Input
|
||||
suffix="°"
|
||||
label="Latitude"
|
||||
type="number"
|
||||
error={errors.fixedLat?.message}
|
||||
disabled={!fixedPositionEnabled}
|
||||
{...register("fixedLat", { valueAsNumber: true })}
|
||||
/>
|
||||
<Input
|
||||
suffix="°"
|
||||
label="Longitude"
|
||||
type="number"
|
||||
error={errors.fixedLng?.message}
|
||||
disabled={!fixedPositionEnabled}
|
||||
{...register("fixedLng", { valueAsNumber: true })}
|
||||
/>
|
||||
</FormSection>
|
||||
<Controller
|
||||
name="gpsEnabled"
|
||||
control={control}
|
||||
render={({ field: { value, ...rest } }) => (
|
||||
<Toggle
|
||||
label="GPS Enabled"
|
||||
description="Enable the internal GPS module"
|
||||
checked={value}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Input
|
||||
suffix="Seconds"
|
||||
label="GPS Update Interval"
|
||||
description="How often a GPS fix should be acquired"
|
||||
type="number"
|
||||
error={errors.gpsUpdateInterval?.message}
|
||||
{...register("gpsUpdateInterval", { valueAsNumber: true })}
|
||||
/>
|
||||
<Input
|
||||
label="Fix Attempt Duration"
|
||||
description="How long the device will try to get a fix for"
|
||||
type="number"
|
||||
error={errors.gpsAttemptTime?.message}
|
||||
{...register("gpsAttemptTime", { valueAsNumber: true })}
|
||||
/>
|
||||
<Controller
|
||||
name="positionFlags"
|
||||
control={control}
|
||||
render={({ field, fieldState }): JSX.Element => {
|
||||
const { value, onChange, ...rest } = field;
|
||||
const { value, onChange } = field;
|
||||
const { error } = fieldState;
|
||||
// const options = Object.entries(
|
||||
// Protobuf.Config_PositionConfig_PositionFlags
|
||||
// )
|
||||
// .filter((value) => typeof value[1] !== "number")
|
||||
// .filter(
|
||||
// (value) =>
|
||||
// parseInt(value[0]) !==
|
||||
// Protobuf.Config_PositionConfig_PositionFlags.UNSET
|
||||
// )
|
||||
// .map((value) => {
|
||||
// return {
|
||||
// value: parseInt(value[0]),
|
||||
// label: value[1].toString().replace("POS_", "").toLowerCase(),
|
||||
// };
|
||||
// });
|
||||
|
||||
// const selected = bitwiseDecode(
|
||||
// value,
|
||||
// Protobuf.Config_PositionConfig_PositionFlags
|
||||
// ).map((flag) =>
|
||||
// Protobuf.Config_PositionConfig_PositionFlags[flag]
|
||||
// .replace("POS_", "")
|
||||
// .toLowerCase()
|
||||
// );
|
||||
// onChange={(e: { value: number; label: string }[]): void =>
|
||||
// onChange(bitwiseEncode(e.map((v) => v.value)))
|
||||
// }
|
||||
return (
|
||||
<BitwiseSelect
|
||||
label="Position Flags"
|
||||
@@ -239,6 +152,74 @@ export const Position = (): JSX.Element => {
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<FormSection title="Fixed Position">
|
||||
<Controller
|
||||
name="fixedPosition"
|
||||
control={control}
|
||||
render={({ field: { value, ...rest } }) => (
|
||||
<Toggle
|
||||
label="Enabled"
|
||||
description="Don't report GPS position, but a manually-specified one"
|
||||
checked={value}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{fixedPositionEnabled && (
|
||||
<>
|
||||
<Input
|
||||
suffix="m"
|
||||
label="Altitude"
|
||||
type="number"
|
||||
error={errors.fixedAlt?.message}
|
||||
disabled={!fixedPositionEnabled}
|
||||
{...register("fixedAlt", { valueAsNumber: true })}
|
||||
/>
|
||||
<Input
|
||||
suffix="°"
|
||||
label="Latitude"
|
||||
type="number"
|
||||
error={errors.fixedLat?.message}
|
||||
disabled={!fixedPositionEnabled}
|
||||
{...register("fixedLat", { valueAsNumber: true })}
|
||||
/>
|
||||
<Input
|
||||
suffix="°"
|
||||
label="Longitude"
|
||||
type="number"
|
||||
error={errors.fixedLng?.message}
|
||||
disabled={!fixedPositionEnabled}
|
||||
{...register("fixedLng", { valueAsNumber: true })}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</FormSection>
|
||||
<FormSection title="Intervals">
|
||||
<Input
|
||||
suffix="Seconds"
|
||||
label="Broadcast Interval"
|
||||
description="How often your position is sent out over the mesh"
|
||||
type="number"
|
||||
error={errors.positionBroadcastSecs?.message}
|
||||
{...register("positionBroadcastSecs", { valueAsNumber: true })}
|
||||
/>
|
||||
<Input
|
||||
suffix="Seconds"
|
||||
label="GPS Update Interval"
|
||||
description="How often a GPS fix should be acquired"
|
||||
type="number"
|
||||
error={errors.gpsUpdateInterval?.message}
|
||||
{...register("gpsUpdateInterval", { valueAsNumber: true })}
|
||||
/>
|
||||
<Input
|
||||
suffix="Seconds"
|
||||
label="Fix Attempt Duration"
|
||||
description="How long the device will try to get a fix for"
|
||||
type="number"
|
||||
error={errors.gpsAttemptTime?.message}
|
||||
{...register("gpsAttemptTime", { valueAsNumber: true })}
|
||||
/>
|
||||
</FormSection>
|
||||
<Input
|
||||
label="RX Pin"
|
||||
description="GPS Module RX pin override"
|
||||
|
||||
@@ -74,10 +74,10 @@ export const User = (): JSX.Element => {
|
||||
>
|
||||
<Input
|
||||
label="Device ID"
|
||||
disabled
|
||||
description="Preset unique identifier for this device."
|
||||
error={errors.id?.message}
|
||||
{...register("id")}
|
||||
readOnly
|
||||
/>
|
||||
<Input
|
||||
label="Device Name"
|
||||
|
||||
@@ -41,7 +41,6 @@ export const BLE = (): JSX.Element => {
|
||||
{bleDevices.map((device, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
void onConnect(device);
|
||||
}}
|
||||
|
||||
@@ -51,7 +51,6 @@ export const Serial = (): JSX.Element => {
|
||||
{serialPorts.map((port, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
void onConnect(port);
|
||||
}}
|
||||
|
||||
@@ -62,9 +62,9 @@ export const MapControlls = (): JSX.Element => {
|
||||
|
||||
return (
|
||||
<div className="absolute right-0 top-0 z-10 m-2 ">
|
||||
<div className="divide-y divide-orange-300 overflow-hidden rounded-md bg-white shadow-md">
|
||||
<div className="divide-y-2 divide-backgroundSecondary overflow-hidden rounded-md bg-backgroundPrimary text-textSecondary">
|
||||
<div
|
||||
className="cursor-pointer p-3 hover:bg-orange-200 hover:text-orange-700"
|
||||
className="hover:bg-orange-200 cursor-pointer p-3 hover:text-accent"
|
||||
onClick={() => {
|
||||
map?.zoomIn();
|
||||
}}
|
||||
@@ -72,7 +72,7 @@ export const MapControlls = (): JSX.Element => {
|
||||
<MagnifyingGlassPlusIcon className="h-4 w-4" />
|
||||
</div>
|
||||
<div
|
||||
className="cursor-pointer p-3 hover:bg-orange-200 hover:text-orange-700"
|
||||
className="hover:bg-orange-200 cursor-pointer p-3 hover:text-accent"
|
||||
onClick={() => {
|
||||
map?.zoomOut();
|
||||
}}
|
||||
@@ -80,13 +80,13 @@ export const MapControlls = (): JSX.Element => {
|
||||
<MagnifyingGlassMinusIcon className="h-4 w-4" />
|
||||
</div>
|
||||
<div
|
||||
className="cursor-pointer p-3 hover:bg-orange-200 hover:text-orange-700"
|
||||
className="hover:bg-orange-200 cursor-pointer p-3 hover:text-accent"
|
||||
onClick={() => {}}
|
||||
>
|
||||
<FiCrosshair className="h-4 w-4" />
|
||||
</div>
|
||||
<div
|
||||
className="cursor-pointer p-3 hover:bg-orange-200 hover:text-orange-700"
|
||||
className="hover:bg-orange-200 cursor-pointer p-3 hover:text-accent"
|
||||
onClick={() => getBBox()}
|
||||
>
|
||||
<ShareIcon className="h-4 w-4" />
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface ChannelChatProps {
|
||||
}
|
||||
|
||||
export const ChannelChat = ({ channel }: ChannelChatProps): JSX.Element => {
|
||||
const { nodes, connection, ackMessage } = useDevice();
|
||||
const { nodes } = useDevice();
|
||||
|
||||
return (
|
||||
<div className="flex flex-grow flex-col">
|
||||
@@ -31,7 +31,9 @@ export const ChannelChat = ({ channel }: ChannelChatProps): JSX.Element => {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<MessageInput channel={channel} />
|
||||
<div className="p-3">
|
||||
<MessageInput channel={channel} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,8 @@ import type { AllMessageTypes } from "@core/stores/deviceStore.js";
|
||||
import { Hashicon } from "@emeraldpay/hashicon-react";
|
||||
import {
|
||||
CheckCircleIcon,
|
||||
EllipsisHorizontalCircleIcon
|
||||
EllipsisHorizontalCircleIcon,
|
||||
ExclamationCircleIcon
|
||||
} from "@heroicons/react/24/outline";
|
||||
import type { Protobuf } from "@meshtastic/meshtasticjs";
|
||||
|
||||
@@ -31,16 +32,16 @@ export const Message = ({
|
||||
return lastMsgSameUser ? (
|
||||
<div className="ml-4 flex">
|
||||
{message.ack ? (
|
||||
<CheckCircleIcon className="my-auto h-4 text-slate-400" />
|
||||
<CheckCircleIcon className="my-auto h-4 text-textSecondary" />
|
||||
) : (
|
||||
<EllipsisHorizontalCircleIcon className="my-auto h-4 text-slate-200" />
|
||||
<EllipsisHorizontalCircleIcon className="my-auto h-4 text-textSecondary" />
|
||||
)}
|
||||
{"waypointID" in message ? (
|
||||
<WaypointMessage waypointID={message.waypointID} />
|
||||
) : (
|
||||
<span
|
||||
className={`ml-4 border-l-2 border-l-slate-200 pl-2 ${
|
||||
message.ack ? "text-black" : "text-slate-500"
|
||||
className={`ml-4 border-l-2 border-l-backgroundPrimary pl-2 ${
|
||||
message.ack ? "text-textPrimary" : "text-textSecondary"
|
||||
}`}
|
||||
>
|
||||
{message.text}
|
||||
@@ -54,12 +55,12 @@ export const Message = ({
|
||||
<Hashicon value={(sender?.num ?? 0).toString()} size={32} />
|
||||
</div>
|
||||
<span
|
||||
className="cursor-pointer font-medium text-slate-700"
|
||||
className="cursor-pointer font-medium text-textPrimary"
|
||||
onClick={openPeer}
|
||||
>
|
||||
{sender?.user?.longName ?? "UNK"}
|
||||
</span>
|
||||
<span className="text-sm">
|
||||
<span className="mt-1 font-mono text-xs text-textSecondary">
|
||||
{new Date(message.packet.rxTime).toLocaleTimeString(undefined, {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit"
|
||||
@@ -67,17 +68,18 @@ export const Message = ({
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex">
|
||||
{/* <ExclamationCircleIcon /> */}
|
||||
{message.ack ? (
|
||||
<CheckCircleIcon className="my-auto h-4 text-slate-400" />
|
||||
<CheckCircleIcon className="my-auto h-4 text-textSecondary" />
|
||||
) : (
|
||||
<EllipsisHorizontalCircleIcon className="my-auto h-4 text-slate-200" />
|
||||
<EllipsisHorizontalCircleIcon className="my-auto h-4 text-textSecondary" />
|
||||
)}
|
||||
{"waypointID" in message ? (
|
||||
<WaypointMessage waypointID={message.waypointID} />
|
||||
) : (
|
||||
<span
|
||||
className={`ml-4 border-l-2 border-l-slate-200 pl-2 ${
|
||||
message.ack ? "text-black" : "text-slate-500"
|
||||
className={`ml-4 border-l-2 border-l-backgroundPrimary pl-2 ${
|
||||
message.ack ? "text-textPrimary" : "text-textSecondary"
|
||||
}`}
|
||||
>
|
||||
{message.text}
|
||||
|
||||
@@ -50,15 +50,11 @@ export const MessageInput = ({ channel }: MessageInputProps): JSX.Element => {
|
||||
/>
|
||||
</span>
|
||||
<IconButton
|
||||
variant="secondary"
|
||||
icon={<PaperAirplaneIcon className="h-4 text-slate-500" />}
|
||||
icon={<PaperAirplaneIcon className="text-slate-500 h-4" />}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<IconButton
|
||||
variant="secondary"
|
||||
icon={<MapPinIcon className="h-4 text-slate-500" />}
|
||||
/>
|
||||
<IconButton icon={<MapPinIcon className="text-slate-500 h-4" />} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,13 +15,13 @@ export const WaypointMessage = ({
|
||||
const waypoint = waypoints.find((wp) => wp.id === waypointID);
|
||||
|
||||
return (
|
||||
<div className="ml-4 border-l-2 border-l-slate-200 pl-2">
|
||||
<div className="flex gap-2 rounded-md p-2 shadow-md shadow-orange-300">
|
||||
<MapPinIcon className="m-auto w-6 text-slate-600" />
|
||||
<div className="border-l-slate-200 ml-4 border-l-2 pl-2">
|
||||
<div className="flex gap-2 rounded-md p-2">
|
||||
<MapPinIcon className="text-slate-600 m-auto w-6" />
|
||||
<div>
|
||||
<div className="flex gap-2">
|
||||
<div className="font-bold">{waypoint?.name}</div>
|
||||
<span className="font-mono text-sm text-slate-500">
|
||||
<span className="text-slate-500 font-mono text-sm">
|
||||
{toMGRS(waypoint?.latitudeI, waypoint?.longitudeI)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user