Use Headless UI & get visual message ack's working
This commit is contained in:
+73
-76
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { MenuIcon, PaperAirplaneIcon } from '@heroicons/react/outline';
|
||||
import type {
|
||||
IHTTPConnection,
|
||||
Protobuf,
|
||||
@@ -9,102 +8,100 @@ import type {
|
||||
|
||||
import type { LanguageEnum, languageTemplate } from './App';
|
||||
import ChatMessage from './components/ChatMessage';
|
||||
import MessageBox from './components/MessageBox';
|
||||
import Sidebar from './components/Sidebar';
|
||||
|
||||
interface MainProps {
|
||||
Messages: { message: Types.TextPacket; ack: boolean }[];
|
||||
Connection: IHTTPConnection;
|
||||
MyNodeInfo: Protobuf.MyNodeInfo;
|
||||
Nodes: Types.NodeInfoPacket[];
|
||||
Channels: Protobuf.Channel[];
|
||||
IsReady: boolean;
|
||||
Preferences: Protobuf.RadioConfig_UserPreferences;
|
||||
Language: LanguageEnum;
|
||||
SetLanguage: React.Dispatch<React.SetStateAction<LanguageEnum>>;
|
||||
Translations: languageTemplate;
|
||||
connection: IHTTPConnection;
|
||||
myNodeInfo: Protobuf.MyNodeInfo;
|
||||
nodes: Types.NodeInfoPacket[];
|
||||
channels: Protobuf.Channel[];
|
||||
isReady: boolean;
|
||||
preferences: Protobuf.RadioConfig_UserPreferences;
|
||||
language: LanguageEnum;
|
||||
setLanguage: React.Dispatch<React.SetStateAction<LanguageEnum>>;
|
||||
translations: languageTemplate;
|
||||
darkmode: boolean;
|
||||
setDarkmode: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const Main = (props: MainProps) => {
|
||||
const [currentMessage, setCurrentMessage] = React.useState('');
|
||||
const [mobileNavOpen, setMobileNavOpen] = React.useState(true);
|
||||
const [messages, setMessages] = React.useState<
|
||||
{ message: Types.TextPacket; ack: boolean }[]
|
||||
>([]);
|
||||
const [settingsModalOpen, setSettingsModalOpen] = useState<boolean>(false);
|
||||
|
||||
const sendMessage = () => {
|
||||
if (props.IsReady) {
|
||||
props.Connection.sendText(currentMessage, undefined, true);
|
||||
setCurrentMessage('');
|
||||
}
|
||||
};
|
||||
React.useEffect(() => {
|
||||
const textPacketEvent = props.connection.onTextPacketEvent.subscribe(
|
||||
(message) => {
|
||||
setMessages((messages) => [
|
||||
...messages,
|
||||
{ message: message, ack: false },
|
||||
]);
|
||||
},
|
||||
);
|
||||
return () => textPacketEvent.unsubscribe();
|
||||
}, [props.connection]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const routingPacketEvent = props.connection.onRoutingPacketEvent.subscribe(
|
||||
(routingPacket) => {
|
||||
setMessages(
|
||||
messages.map((message) => {
|
||||
return routingPacket.packet.payloadVariant.oneofKind ===
|
||||
'decoded' &&
|
||||
message.message.packet.id ===
|
||||
routingPacket.packet.payloadVariant.decoded.requestId
|
||||
? {
|
||||
ack: true,
|
||||
message: message.message,
|
||||
}
|
||||
: message;
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
return () => routingPacketEvent.unsubscribe();
|
||||
}, [props.connection, messages]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col md:flex-row flex-grow space-2">
|
||||
<div className="flex flex-col md:flex-row flex-grow m-3 space-y-2 md:space-y-0 space-x-0 md:space-x-2">
|
||||
<div className="flex flex-col flex-grow container mx-auto">
|
||||
<div className="flex flex-col flex-grow py-6 px-3 space-y-2">
|
||||
{props.Messages.length ? (
|
||||
props.Messages.map((message, Main) => (
|
||||
<div className="flex flex-col flex-grow py-6 space-y-2">
|
||||
{messages.length ? (
|
||||
messages.map((message, Main) => (
|
||||
<ChatMessage
|
||||
nodes={props.Nodes}
|
||||
nodes={props.nodes}
|
||||
key={Main}
|
||||
message={message}
|
||||
myId={props.MyNodeInfo.myNodeNum}
|
||||
myId={props.myNodeInfo.myNodeNum}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<div className="m-auto text-2xl text-gray-500">
|
||||
{props.Translations.no_messages_message}
|
||||
{props.translations.no_messages_message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex space-x-2 w-full p-3">
|
||||
<form
|
||||
className="flex flex-wrap relative w-full"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
sendMessage();
|
||||
}}
|
||||
>
|
||||
{props.IsReady}
|
||||
<input
|
||||
type="text"
|
||||
placeholder={`${props.Translations.no_message_placeholder}...`}
|
||||
disabled={!props.IsReady}
|
||||
value={currentMessage}
|
||||
onChange={(e) => {
|
||||
setCurrentMessage(e.target.value);
|
||||
}}
|
||||
className={`p-3 placeholder-gray-400 text-gray-700 relative rounded-md shadow-md focus:outline-none w-full pr-10 ${
|
||||
props.IsReady ? 'cursor-text' : 'cursor-not-allowed'
|
||||
}`}
|
||||
/>
|
||||
<span className="flex z-10 h-full text-gray-400 absolute w-8 right-0">
|
||||
<PaperAirplaneIcon
|
||||
onClick={sendMessage}
|
||||
className={`text-xl hover:text-gray-500 h-6 w-6 my-auto ${
|
||||
props.IsReady ? 'cursor-pointer' : 'cursor-not-allowed'
|
||||
}`}
|
||||
/>
|
||||
</span>
|
||||
</form>
|
||||
<div
|
||||
className="flex p-3 text-xl hover:text-gray-500 text-gray-400 rounded-md shadow-md focus:outline-none cursor-pointer md:hidden"
|
||||
onClick={() => {
|
||||
setMobileNavOpen(!mobileNavOpen);
|
||||
}}
|
||||
>
|
||||
<MenuIcon className="m-auto h-6 2-6" />
|
||||
</div>
|
||||
</div>
|
||||
<MessageBox
|
||||
connection={props.connection}
|
||||
isReady={props.isReady}
|
||||
setSettingsModalOpen={setSettingsModalOpen}
|
||||
translations={props.translations}
|
||||
/>
|
||||
</div>
|
||||
<Sidebar
|
||||
IsReady={props.IsReady}
|
||||
Nodes={props.Nodes}
|
||||
Channels={props.Channels}
|
||||
Preferences={props.Preferences}
|
||||
Connection={props.Connection}
|
||||
MobileNavOpen={mobileNavOpen}
|
||||
Language={props.Language}
|
||||
SetLanguage={props.SetLanguage}
|
||||
Translations={props.Translations}
|
||||
myId={props.MyNodeInfo.myNodeNum}
|
||||
isReady={props.isReady}
|
||||
nodes={props.nodes}
|
||||
channels={props.channels}
|
||||
preferences={props.preferences}
|
||||
connection={props.connection}
|
||||
language={props.language}
|
||||
setLanguage={props.setLanguage}
|
||||
translations={props.translations}
|
||||
myId={props.myNodeInfo.myNodeNum}
|
||||
darkmode={props.darkmode}
|
||||
setDarkmode={props.setDarkmode}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user