Use Headless UI & get visual message ack's working

This commit is contained in:
Sacha Weatherstone
2021-05-09 19:23:13 +10:00
parent d6be17a789
commit 50c276b9bc
21 changed files with 831 additions and 9433 deletions
+73 -76
View File
@@ -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>
);