|
|
|
@ -4,7 +4,13 @@ import { Input } from "@components/UI/Input.tsx"; |
|
|
|
import { useDevice } from "@core/stores/deviceStore.ts"; |
|
|
|
import type { Types } from "@meshtastic/js"; |
|
|
|
import { SendIcon } from "lucide-react"; |
|
|
|
import { type JSX, useCallback, useMemo, useState } from "react"; |
|
|
|
import { |
|
|
|
type JSX, |
|
|
|
startTransition, |
|
|
|
useCallback, |
|
|
|
useMemo, |
|
|
|
useState, |
|
|
|
} from "react"; |
|
|
|
|
|
|
|
export interface MessageInputProps { |
|
|
|
to: Types.Destination; |
|
|
|
@ -63,11 +69,11 @@ export const MessageInput = ({ |
|
|
|
|
|
|
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { |
|
|
|
const newValue = e.target.value; |
|
|
|
const byteLength = new Blob([newValue]).size; |
|
|
|
if (byteLength <= maxBytes) { |
|
|
|
const messageLength = newValue.length; |
|
|
|
if (messageLength <= maxBytes) { |
|
|
|
setLocalDraft(newValue); |
|
|
|
debouncedSetMessageDraft(newValue); |
|
|
|
setMessageBytes(maxBytes - byteLength); |
|
|
|
setMessageBytes(maxBytes - messageLength); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
@ -75,11 +81,15 @@ export const MessageInput = ({ |
|
|
|
<div className="flex gap-2"> |
|
|
|
<form |
|
|
|
className="w-full" |
|
|
|
onSubmit={(e) => { |
|
|
|
e.preventDefault(); |
|
|
|
sendText(localDraft); |
|
|
|
setLocalDraft(""); |
|
|
|
setMessageDraft(""); |
|
|
|
action={async (formData: FormData) => { |
|
|
|
// prevent user from sending blank/empty message
|
|
|
|
if (localDraft === "") return; |
|
|
|
const message = formData.get("messageInput") as string; |
|
|
|
startTransition(() => { |
|
|
|
sendText(message); |
|
|
|
setLocalDraft(""); |
|
|
|
setMessageDraft(""); |
|
|
|
}); |
|
|
|
}} |
|
|
|
> |
|
|
|
<div className="flex flex-grow gap-2"> |
|
|
|
@ -87,6 +97,7 @@ export const MessageInput = ({ |
|
|
|
<Input |
|
|
|
autoFocus={true} |
|
|
|
minLength={1} |
|
|
|
name="messageInput" |
|
|
|
placeholder="Enter Message" |
|
|
|
value={localDraft} |
|
|
|
onChange={handleInputChange} |
|
|
|
|