DM support

This commit is contained in:
Sacha Weatherstone
2023-02-19 16:55:59 +10:00
parent 2265a304fe
commit b2c3c89965
17 changed files with 532 additions and 531 deletions
@@ -1,33 +1,46 @@
import { Subtle } from "@app/components/UI/Typography/Subtle.js";
import { MessageWithState, useDevice } from "@app/core/stores/deviceStore.js";
import { Message } from "@components/PageComponents/Messages/Message.js";
import { MessageInput } from "@components/PageComponents/Messages/MessageInput.js";
import { useDevice } from "@core/stores/deviceStore.js";
import type { Channel } from "@core/stores/deviceStore.js";
import type { Types } from "@meshtastic/meshtasticjs";
import { InboxIcon } from "lucide-react";
export interface ChannelChatProps {
channel: Channel;
messages?: MessageWithState[];
channel: Types.ChannelNumber;
to: Types.Destination;
}
export const ChannelChat = ({ channel }: ChannelChatProps): JSX.Element => {
export const ChannelChat = ({
messages,
channel,
to
}: ChannelChatProps): JSX.Element => {
const { nodes } = useDevice();
return (
<div className="flex flex-grow flex-col">
<div className="flex flex-grow flex-col">
{channel.messages.map((message, index) => (
<Message
key={index}
message={message}
lastMsgSameUser={
index === 0
? false
: channel.messages[index - 1].from === message.from
}
sender={nodes.find((node) => node.data.num === message.from)?.data}
/>
))}
{messages ? (
messages.map((message, index) => (
<Message
key={index}
message={message}
lastMsgSameUser={
index === 0 ? false : messages[index - 1].from === message.from
}
sender={nodes.get(message.from)}
/>
))
) : (
<div className="m-auto">
<InboxIcon className="m-auto" />
<Subtle>No Messages</Subtle>
</div>
)}
</div>
<div className="p-3">
<MessageInput channel={channel} />
<MessageInput to={to} channel={channel} />
</div>
</div>
);
@@ -1,6 +1,3 @@
import { WaypointMessage } from "@components/PageComponents/Messages/WaypointMessage.js";
import { useDevice } from "@core/stores/deviceStore.js";
import type { AllMessageTypes } from "@core/stores/deviceStore.js";
import { Hashicon } from "@emeraldpay/hashicon-react";
import {
CircleEllipsisIcon,
@@ -8,10 +5,11 @@ import {
CheckCircle2Icon
} from "lucide-react";
import type { Protobuf } from "@meshtastic/meshtasticjs";
import type { MessageWithState } from "@app/core/stores/deviceStore.js";
export interface MessageProps {
lastMsgSameUser: boolean;
message: AllMessageTypes;
message: MessageWithState;
sender?: Protobuf.NodeInfo;
}
@@ -20,13 +18,6 @@ export const Message = ({
message,
sender
}: MessageProps): JSX.Element => {
const { setPeerInfoOpen, setActivePeer, connection } = useDevice();
const openPeer = (): void => {
setActivePeer(message.from);
setPeerInfoOpen(true);
};
return lastMsgSameUser ? (
<div className="ml-5 flex">
{message.state === "ack" ? (
@@ -36,28 +27,21 @@ export const Message = ({
) : (
<AlertCircleIcon size={16} className="my-auto text-textSecondary" />
)}
{"waypointID" in message ? (
<WaypointMessage waypointID={message.waypointID} />
) : (
<span
className={`ml-4 border-l-2 border-l-backgroundPrimary pl-2 ${
message.state === "ack" ? "text-textPrimary" : "text-textSecondary"
}`}
>
{message.data}
</span>
)}
<span
className={`ml-4 border-l-2 border-l-backgroundPrimary pl-2 ${
message.state === "ack" ? "text-textPrimary" : "text-textSecondary"
}`}
>
{message.data}
</span>
</div>
) : (
<div className="mx-4 mt-2 gap-2">
<div className="flex gap-2">
<div className="w-6 cursor-pointer" onClick={openPeer}>
<div className="w-6 cursor-pointer">
<Hashicon value={(sender?.num ?? 0).toString()} size={32} />
</div>
<span
className="cursor-pointer font-medium text-textPrimary"
onClick={openPeer}
>
<span className="cursor-pointer font-medium text-textPrimary">
{sender?.user?.longName ?? "UNK"}
</span>
<span className="mt-1 font-mono text-xs text-textSecondary">
@@ -78,19 +62,13 @@ export const Message = ({
) : (
<AlertCircleIcon size={16} className="my-auto text-textSecondary" />
)}
{"waypointID" in message ? (
<WaypointMessage waypointID={message.waypointID} />
) : (
<span
className={`ml-4 border-l-2 border-l-backgroundPrimary pl-2 ${
message.state === "ack"
? "text-textPrimary"
: "text-textSecondary"
}`}
>
{message.data}
</span>
)}
<span
className={`ml-4 border-l-2 border-l-backgroundPrimary pl-2 ${
message.state === "ack" ? "text-textPrimary" : "text-textSecondary"
}`}
>
{message.data}
</span>
</div>
</div>
);
@@ -1,29 +1,50 @@
import { Input } from "@components/UI/Input.js";
import { useDevice } from "@core/stores/deviceStore.js";
import type { Channel } from "@core/stores/deviceStore.js";
import { SendIcon } from "lucide-react";
import type { Types } from "@meshtastic/meshtasticjs";
import { Button } from "@components/UI/Button.js";
export interface MessageInputProps {
channel: Channel;
to: Types.Destination;
channel: Types.ChannelNumber;
}
export const MessageInput = ({ channel }: MessageInputProps): JSX.Element => {
const { connection, setMessageState, messageDraft, setMessageDraft } =
useDevice();
export const MessageInput = ({
to,
channel
}: MessageInputProps): JSX.Element => {
const {
connection,
setMessageState,
messageDraft,
setMessageDraft,
hardware
} = useDevice();
const myNodeNum = hardware.myNodeNum;
const sendText = async (message: string) => {
await connection
?.sendText(
message,
"broadcast",
true,
channel.config.index as Types.ChannelNumber
?.sendText(message, to, true, channel)
.then((id) =>
setMessageState(
to === "broadcast" ? "broadcast" : "direct",
channel,
to as number,
myNodeNum,
id,
"ack"
)
)
.then((id) => setMessageState(channel.config.index, id, "ack"))
.catch((e: Types.PacketError) =>
setMessageState(channel.config.index, e.id, e.error)
setMessageState(
to === "broadcast" ? "broadcast" : "direct",
channel,
to as number,
myNodeNum,
e.id,
e.error
)
);
};
@@ -1,31 +0,0 @@
import { useDevice } from "@core/stores/deviceStore.js";
import { toMGRS } from "@core/utils/toMGRS.js";
import { MapPinIcon } from "lucide-react";
export interface WaypointMessageProps {
waypointID: number;
}
export const WaypointMessage = ({
waypointID
}: WaypointMessageProps): JSX.Element => {
const { waypoints } = useDevice();
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">
<MapPinIcon size={16} className="m-auto text-slate-600" />
<div>
<div className="flex gap-2">
<div className="font-bold">{waypoint?.name}</div>
<span className="font-mono text-sm text-slate-500">
{toMGRS(waypoint?.latitudeI, waypoint?.longitudeI)}
</span>
</div>
<span className="text-sm">{waypoint?.description}</span>
</div>
</div>
</div>
);
};