format and use more aggressive tabstop widths
This commit is contained in:
parent
7d4953fea6
commit
56feab2ea1
7 changed files with 366 additions and 344 deletions
|
@ -90,15 +90,6 @@ const App = ({
|
|||
}
|
||||
});
|
||||
};
|
||||
// if (!username) {
|
||||
// var newName = prompt(home.userNamePrompt) as string;
|
||||
// while (!validateName(newName)) {
|
||||
// console.log(newName);
|
||||
|
||||
// prompt("Username invalid! Please enter again.") as string;
|
||||
// }
|
||||
// setUsername(newName);
|
||||
// }
|
||||
if (!login) {
|
||||
return <></>;
|
||||
} else
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, {
|
||||
ReactElement,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
ReactElement,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { MessageDisplay } from "../MessageDisplay/MessageDisplay";
|
||||
import { Client } from "@stomp/stompjs";
|
||||
|
@ -13,117 +13,128 @@ import strings from "../Intl/strings.json";
|
|||
import { LangContext } from "../context";
|
||||
import { connectionAddress, endpoints } from "../consts";
|
||||
const Chat = ({ user }: { user: string }): React.ReactElement => {
|
||||
const lang = useContext(LangContext);
|
||||
const chatPage = strings[lang].chat;
|
||||
const [messages, setMessages] = useState<ReactElement[]>([]);
|
||||
let stompClientRef = useRef(
|
||||
new Client({
|
||||
brokerURL: connectionAddress,
|
||||
})
|
||||
);
|
||||
// TODO solve issue with non-static markup
|
||||
stompClientRef.current.onConnect = (frame) => {
|
||||
stompClientRef.current.subscribe(endpoints.subscription, (message) => {
|
||||
console.log(`Collected new message: ${message.body}`);
|
||||
const messageBody = JSON.parse(message.body) as Message;
|
||||
console.log(messageBody);
|
||||
setMessages((message) => {
|
||||
return message.concat([
|
||||
<MessageDisplay
|
||||
key={`${messageBody.type}@${messageBody.timeMillis}`}
|
||||
{...messageBody}
|
||||
/>,
|
||||
]);
|
||||
});
|
||||
});
|
||||
stompClientRef.current.publish({
|
||||
body: JSON.stringify({
|
||||
type: MessageType.HELLO,
|
||||
fromUserId: user,
|
||||
toUserId: "everyone",
|
||||
content: `${user} has joined the server!`,
|
||||
timeMillis: Date.now(),
|
||||
}),
|
||||
destination: endpoints.destination,
|
||||
});
|
||||
};
|
||||
const lang = useContext(LangContext);
|
||||
const chatPage = strings[lang].chat;
|
||||
const [messages, setMessages] = useState<ReactElement[]>([]);
|
||||
let stompClientRef = useRef(
|
||||
new Client({
|
||||
brokerURL: connectionAddress,
|
||||
})
|
||||
);
|
||||
// TODO solve issue with non-static markup
|
||||
stompClientRef.current.onConnect = (frame) => {
|
||||
stompClientRef.current.subscribe(
|
||||
endpoints.subscription,
|
||||
(message) => {
|
||||
console.log(
|
||||
`Collected new message: ${message.body}`
|
||||
);
|
||||
const messageBody = JSON.parse(
|
||||
message.body
|
||||
) as Message;
|
||||
console.log(messageBody);
|
||||
setMessages((message) => {
|
||||
return message.concat([
|
||||
<MessageDisplay
|
||||
key={`${messageBody.type}@${messageBody.timeMillis}`}
|
||||
{...messageBody}
|
||||
/>,
|
||||
]);
|
||||
});
|
||||
}
|
||||
);
|
||||
stompClientRef.current.publish({
|
||||
body: JSON.stringify({
|
||||
type: MessageType.HELLO,
|
||||
fromUserId: user,
|
||||
toUserId: "everyone",
|
||||
content: `${user} has joined the server!`,
|
||||
timeMillis: Date.now(),
|
||||
}),
|
||||
destination: endpoints.destination,
|
||||
});
|
||||
};
|
||||
// Generic error handlers
|
||||
stompClientRef.current.onWebSocketError = (error) => {
|
||||
console.error("Error with websocket", error);
|
||||
};
|
||||
|
||||
// Generic error handlers
|
||||
stompClientRef.current.onWebSocketError = (error) => {
|
||||
console.error("Error with websocket", error);
|
||||
};
|
||||
stompClientRef.current.onStompError = (frame) => {
|
||||
console.error(
|
||||
"Broker reported error: " + frame.headers["message"]
|
||||
);
|
||||
console.error("Additional details: " + frame.body);
|
||||
};
|
||||
|
||||
stompClientRef.current.onStompError = (frame) => {
|
||||
console.error("Broker reported error: " + frame.headers["message"]);
|
||||
console.error("Additional details: " + frame.body);
|
||||
};
|
||||
|
||||
// Button press event handler.
|
||||
const sendData = () => {
|
||||
const entryElement: HTMLInputElement = document.getElementById(
|
||||
"data-entry"
|
||||
) as HTMLInputElement;
|
||||
if (entryElement.value === "") {
|
||||
return;
|
||||
}
|
||||
const messageData: Message = {
|
||||
type: MessageType.MESSAGE,
|
||||
fromUserId: user,
|
||||
toUserId: "everyone",
|
||||
content: entryElement.value,
|
||||
timeMillis: Date.now(),
|
||||
};
|
||||
console.log(
|
||||
`STOMP connection status: ${stompClientRef.current.connected}`
|
||||
);
|
||||
stompClientRef.current.publish({
|
||||
body: JSON.stringify(messageData),
|
||||
destination: endpoints.destination,
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
entryElement.value = "";
|
||||
};
|
||||
useEffect(() => {
|
||||
// Stomp client is disconnected after each re-render
|
||||
// This should be actively avoided
|
||||
stompClientRef.current.activate();
|
||||
return () => {
|
||||
stompClientRef.current.deactivate();
|
||||
};
|
||||
}, []);
|
||||
// https://www.w3schools.com/jsref/obj_keyboardevent.asp
|
||||
document.addEventListener("keydown", (ev: KeyboardEvent) => {
|
||||
if (ev.key === "Enter") {
|
||||
sendData();
|
||||
}
|
||||
});
|
||||
useEffect(() => {
|
||||
try {
|
||||
const elem = document.querySelector(".chat-inner-wrapper");
|
||||
if (elem) {
|
||||
elem.scrollTop = elem.scrollHeight;
|
||||
} else {
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("error encountered");
|
||||
}
|
||||
return () => {};
|
||||
}, [messages]);
|
||||
return (
|
||||
<fieldset className="chat">
|
||||
<legend>
|
||||
Logged in as <b>{user}</b>
|
||||
</legend>
|
||||
<div className="chat-inner-wrapper">{messages}</div>
|
||||
<span className="entry-box">
|
||||
<input id="data-entry"></input>
|
||||
<button onClick={() => sendData()}>
|
||||
{chatPage.sendButtonPrompt}
|
||||
</button>
|
||||
</span>
|
||||
</fieldset>
|
||||
);
|
||||
// Button press event handler.
|
||||
const sendData = () => {
|
||||
const entryElement: HTMLInputElement = document.getElementById(
|
||||
"data-entry"
|
||||
) as HTMLInputElement;
|
||||
if (entryElement.value === "") {
|
||||
return;
|
||||
}
|
||||
const messageData: Message = {
|
||||
type: MessageType.MESSAGE,
|
||||
fromUserId: user,
|
||||
toUserId: "everyone",
|
||||
content: entryElement.value,
|
||||
timeMillis: Date.now(),
|
||||
};
|
||||
console.log(
|
||||
`STOMP connection status: ${stompClientRef.current.connected}`
|
||||
);
|
||||
stompClientRef.current.publish({
|
||||
body: JSON.stringify(messageData),
|
||||
destination: endpoints.destination,
|
||||
headers: {
|
||||
"Content-Type":
|
||||
"application/json; charset=utf-8",
|
||||
},
|
||||
});
|
||||
entryElement.value = "";
|
||||
};
|
||||
useEffect(() => {
|
||||
// Stomp client is disconnected after each re-render
|
||||
// This should be actively avoided
|
||||
stompClientRef.current.activate();
|
||||
return () => {
|
||||
stompClientRef.current.deactivate();
|
||||
};
|
||||
}, []);
|
||||
// https://www.w3schools.com/jsref/obj_keyboardevent.asp
|
||||
document.addEventListener("keydown", (ev: KeyboardEvent) => {
|
||||
if (ev.key === "Enter") {
|
||||
sendData();
|
||||
}
|
||||
});
|
||||
useEffect(() => {
|
||||
try {
|
||||
const elem = document.querySelector(
|
||||
".chat-inner-wrapper"
|
||||
);
|
||||
if (elem) {
|
||||
elem.scrollTop = elem.scrollHeight;
|
||||
} else {
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("error encountered");
|
||||
}
|
||||
return () => {};
|
||||
}, [messages]);
|
||||
return (
|
||||
<fieldset className="chat">
|
||||
<legend>
|
||||
Logged in as <b>{user}</b>
|
||||
</legend>
|
||||
<div className="chat-inner-wrapper">{messages}</div>
|
||||
<span className="entry-box">
|
||||
<input id="data-entry"></input>
|
||||
<button onClick={() => sendData()}>
|
||||
{chatPage.sendButtonPrompt}
|
||||
</button>
|
||||
</span>
|
||||
</fieldset>
|
||||
);
|
||||
};
|
||||
export default Chat;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.uname-error-text {
|
||||
color: red;
|
||||
}
|
||||
color: red;
|
||||
}
|
||||
|
|
|
@ -4,138 +4,156 @@ import { LoginType } from "../context";
|
|||
import { User } from "../type/userTypes";
|
||||
import "./Login.css";
|
||||
const encrypt = (rawPasswordString: string) => {
|
||||
// TODO Encryption method stub
|
||||
return rawPasswordString;
|
||||
// TODO Encryption method stub
|
||||
return rawPasswordString;
|
||||
};
|
||||
export const Login = ({
|
||||
setLogin,
|
||||
setLogin,
|
||||
}: {
|
||||
setLogin: (newLogin: LoginType | undefined) => void;
|
||||
setLogin: (newLogin: LoginType | undefined) => void;
|
||||
}): React.ReactElement => {
|
||||
const [valid, setValid] = useState<boolean | undefined>(true);
|
||||
const [validText, setValidText] = useState<string | undefined>();
|
||||
const registrationHandler = () => {
|
||||
const uname = (document.getElementById("username") as HTMLInputElement)
|
||||
.value;
|
||||
const passwd = encrypt(
|
||||
(document.getElementById("passwd") as HTMLInputElement).value
|
||||
);
|
||||
fetch(`http://${domain}:${port}${endpoints.user}`, {
|
||||
method: "POST",
|
||||
mode: "cors",
|
||||
headers: contentTypes.json,
|
||||
body: JSON.stringify({
|
||||
userName: uname,
|
||||
dateJoined: Date.now(),
|
||||
passwordHash: passwd,
|
||||
}),
|
||||
}).then((response) => {
|
||||
if (response.status === 400) {
|
||||
// 400 Bad request
|
||||
console.log("Username is taken or invalid!");
|
||||
setValid(false);
|
||||
setValidText("Username is taken or invalid!");
|
||||
} else if (response.status === 200) {
|
||||
// 200 OK
|
||||
const futureDate = new Date();
|
||||
futureDate.setHours(futureDate.getHours() + 2);
|
||||
setLogin({
|
||||
username: uname,
|
||||
lastSeen: Date.now(),
|
||||
validUntil: futureDate.getUTCMilliseconds(),
|
||||
});
|
||||
document.title = `IRC User ${uname}`;
|
||||
}
|
||||
});
|
||||
};
|
||||
// login button press handler
|
||||
const loginHandler = () => {
|
||||
const uname = (document.getElementById("username") as HTMLInputElement)
|
||||
.value;
|
||||
const passwd = encrypt(
|
||||
(document.getElementById("passwd") as HTMLInputElement).value
|
||||
);
|
||||
// async invocation of Fetch API
|
||||
fetch(`http://${domain}:${port}${endpoints.user}?name=${uname}`, {
|
||||
method: "GET",
|
||||
mode: "cors",
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.status === 404) {
|
||||
console.log("404 not found encountered");
|
||||
throw new Error("Username does not exist");
|
||||
} else if (res.status === 200) {
|
||||
console.log("200 OK");
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then((userObject) => {
|
||||
if (!userObject) {
|
||||
return;
|
||||
}
|
||||
const user = userObject as User;
|
||||
const validLogin = passwd === user.passwordHash;
|
||||
if (!validLogin) {
|
||||
// login invalid
|
||||
throw new Error("Password incorrect!");
|
||||
} else {
|
||||
// login valid
|
||||
const validUntilDate: Date = new Date();
|
||||
validUntilDate.setHours(validUntilDate.getHours() + 2);
|
||||
setLogin({
|
||||
username: user.userName,
|
||||
lastSeen: user.lastSeen,
|
||||
validUntil: validUntilDate.getUTCMilliseconds(),
|
||||
});
|
||||
document.title = `IRC User ${uname}`;
|
||||
}
|
||||
})
|
||||
.catch((reason: Error) => {
|
||||
setValid(false);
|
||||
setValidText(reason.message);
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div className="login">
|
||||
<fieldset>
|
||||
<legend>Login window</legend>
|
||||
<p className="uname-error-text">
|
||||
{valid && valid !== undefined ? "" : validText}
|
||||
</p>
|
||||
<label htmlFor="username">Username: </label>
|
||||
<br />
|
||||
<input id="username" type="text"></input>
|
||||
<br />
|
||||
<label htmlFor="passwd">Password: </label>
|
||||
<br />
|
||||
<input id="passwd" type="password"></input>
|
||||
<br />
|
||||
<button
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
loginHandler();
|
||||
}}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
registrationHandler();
|
||||
}}
|
||||
>
|
||||
Register
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
setLogin(undefined);
|
||||
setValid(false);
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</fieldset>
|
||||
</div>
|
||||
);
|
||||
const [valid, setValid] = useState<boolean | undefined>(true);
|
||||
const [validText, setValidText] = useState<string | undefined>();
|
||||
const registrationHandler = () => {
|
||||
const uname = (
|
||||
document.getElementById("username") as HTMLInputElement
|
||||
).value;
|
||||
const passwd = encrypt(
|
||||
(document.getElementById("passwd") as HTMLInputElement)
|
||||
.value
|
||||
);
|
||||
fetch(`http://${domain}:${port}${endpoints.user}`, {
|
||||
method: "POST",
|
||||
mode: "cors",
|
||||
headers: contentTypes.json,
|
||||
body: JSON.stringify({
|
||||
userName: uname,
|
||||
dateJoined: Date.now(),
|
||||
passwordHash: passwd,
|
||||
}),
|
||||
}).then((response) => {
|
||||
if (response.status === 400) {
|
||||
// 400 Bad request
|
||||
console.log("Username is taken or invalid!");
|
||||
setValid(false);
|
||||
setValidText("Username is taken or invalid!");
|
||||
} else if (response.status === 200) {
|
||||
// 200 OK
|
||||
const futureDate = new Date();
|
||||
futureDate.setHours(futureDate.getHours() + 2);
|
||||
setLogin({
|
||||
username: uname,
|
||||
lastSeen: Date.now(),
|
||||
validUntil: futureDate.getUTCMilliseconds(),
|
||||
});
|
||||
document.title = `IRC User ${uname}`;
|
||||
}
|
||||
});
|
||||
};
|
||||
// login button press handler
|
||||
const loginHandler = () => {
|
||||
const uname = (
|
||||
document.getElementById("username") as HTMLInputElement
|
||||
).value;
|
||||
const passwd = encrypt(
|
||||
(document.getElementById("passwd") as HTMLInputElement)
|
||||
.value
|
||||
);
|
||||
// async invocation of Fetch API
|
||||
fetch(
|
||||
`http://${domain}:${port}${endpoints.user}?name=${uname}`,
|
||||
{
|
||||
method: "GET",
|
||||
mode: "cors",
|
||||
}
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.status === 404) {
|
||||
console.log(
|
||||
"404 not found encountered"
|
||||
);
|
||||
throw new Error(
|
||||
"Username does not exist"
|
||||
);
|
||||
} else if (res.status === 200) {
|
||||
console.log("200 OK");
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then((userObject) => {
|
||||
if (!userObject) {
|
||||
return;
|
||||
}
|
||||
const user = userObject as User;
|
||||
const validLogin = passwd === user.passwordHash;
|
||||
if (!validLogin) {
|
||||
// login invalid
|
||||
throw new Error("Password incorrect!");
|
||||
} else {
|
||||
// login valid
|
||||
const validUntilDate: Date = new Date();
|
||||
validUntilDate.setHours(
|
||||
validUntilDate.getHours() + 2
|
||||
);
|
||||
setLogin({
|
||||
username: user.userName,
|
||||
lastSeen: user.lastSeen,
|
||||
validUntil: validUntilDate.getUTCMilliseconds(),
|
||||
});
|
||||
document.title = `IRC User ${uname}`;
|
||||
}
|
||||
})
|
||||
.catch((reason: Error) => {
|
||||
setValid(false);
|
||||
setValidText(reason.message);
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div className="login">
|
||||
<fieldset>
|
||||
<legend>Login window</legend>
|
||||
<p className="uname-error-text">
|
||||
{valid && valid !== undefined
|
||||
? ""
|
||||
: validText}
|
||||
</p>
|
||||
<label htmlFor="username">Username: </label>
|
||||
<br />
|
||||
<input id="username" type="text"></input>
|
||||
<br />
|
||||
<label htmlFor="passwd">Password: </label>
|
||||
<br />
|
||||
<input id="passwd" type="password"></input>
|
||||
<br />
|
||||
<button
|
||||
disabled={!valid}
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
loginHandler();
|
||||
}}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
<button
|
||||
disabled={!valid}
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
registrationHandler();
|
||||
}}
|
||||
>
|
||||
Register
|
||||
</button>
|
||||
<button
|
||||
disabled={valid}
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
setLogin(undefined);
|
||||
setValid(false);
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</fieldset>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,57 +4,64 @@ import { LangContext } from "../context";
|
|||
import strings from "../Intl/strings.json";
|
||||
import "./MessageDisplay.css";
|
||||
export const MessageDisplay = ({
|
||||
type,
|
||||
fromUserId,
|
||||
toUserId,
|
||||
content,
|
||||
timeMillis,
|
||||
type,
|
||||
fromUserId,
|
||||
toUserId,
|
||||
content,
|
||||
timeMillis,
|
||||
}: Message): React.ReactElement<Message> => {
|
||||
const dateTime: Date = new Date(timeMillis);
|
||||
const lang = useContext(LangContext);
|
||||
const msgPage = strings[lang].chat;
|
||||
/* FIXED funny error
|
||||
* DESCRIPTION
|
||||
* The line below was
|
||||
* return (<p>[{dateTime.toLocaleString(Intl.DateTimeFormat().resolvedOptions().timeZone)}]...</p>)
|
||||
* The line incorrectly generated a value of "UTC" as the parameter to toLocaleString()
|
||||
* While "UTC" is an accepted string value, in EEST, aka. "Europe/Athens" timezone string is not an acceptable parameter.
|
||||
* This caused the return statement to fail, and the message fails to render, despite it being correctly committed to the db.
|
||||
* Funny clown moment 🤡
|
||||
*/
|
||||
const timeString = `${
|
||||
dateTime.getHours() > 12
|
||||
? dateTime.getHours() - 12
|
||||
: dateTime.getHours()
|
||||
}:${dateTime.getMinutes()} ${dateTime.getHours() > 12 ? "PM" : "AM"}`;
|
||||
switch (type) {
|
||||
case MessageType.HELLO as MessageType:
|
||||
return (
|
||||
<p className="msg">
|
||||
[{timeString}]{" "}
|
||||
{msgPage.joinMessage.replace("$userName", fromUserId)}
|
||||
</p>
|
||||
);
|
||||
case MessageType.MESSAGE as MessageType:
|
||||
return (
|
||||
<p className="msg">
|
||||
[{timeString}]{" "}
|
||||
{msgPage.serverMessage
|
||||
.replace("$userName", fromUserId)
|
||||
.replace("$content", content)}
|
||||
</p>
|
||||
);
|
||||
case MessageType.DATA as MessageType:
|
||||
return <></>;
|
||||
case MessageType.CHNAME as MessageType:
|
||||
return <></>;
|
||||
default:
|
||||
console.error("Illegal MessageType reported!");
|
||||
return (
|
||||
<p className="msg-err">
|
||||
[{timeString}] **THIS MESSAGE CANNOT BE CORRECTLY SHOWN
|
||||
BECAUSE THE CLIENT ENCOUNTERED AN ERROR**
|
||||
</p>
|
||||
);
|
||||
}
|
||||
const dateTime: Date = new Date(timeMillis);
|
||||
const lang = useContext(LangContext);
|
||||
const msgPage = strings[lang].chat;
|
||||
/* FIXED funny error
|
||||
* DESCRIPTION
|
||||
* The line below was
|
||||
* return (<p>[{dateTime.toLocaleString(Intl.DateTimeFormat().resolvedOptions().timeZone)}]...</p>)
|
||||
* The line incorrectly generated a value of "UTC" as the parameter to toLocaleString()
|
||||
* While "UTC" is an accepted string value, in EEST, aka. "Europe/Athens" timezone string is not an acceptable parameter.
|
||||
* This caused the return statement to fail, and the message fails to render, despite it being correctly committed to the db.
|
||||
* Funny clown moment 🤡
|
||||
*/
|
||||
const timeString = `${
|
||||
dateTime.getHours() > 12
|
||||
? dateTime.getHours() - 12
|
||||
: dateTime.getHours()
|
||||
}:${dateTime.getMinutes()} ${dateTime.getHours() > 12 ? "PM" : "AM"}`;
|
||||
switch (type) {
|
||||
case MessageType.HELLO as MessageType:
|
||||
return (
|
||||
<p className="msg">
|
||||
[{timeString}]{" "}
|
||||
{msgPage.joinMessage.replace(
|
||||
"$userName",
|
||||
fromUserId
|
||||
)}
|
||||
</p>
|
||||
);
|
||||
case MessageType.MESSAGE as MessageType:
|
||||
return (
|
||||
<p className="msg">
|
||||
[{timeString}]{" "}
|
||||
{msgPage.serverMessage
|
||||
.replace(
|
||||
"$userName",
|
||||
fromUserId
|
||||
)
|
||||
.replace("$content", content)}
|
||||
</p>
|
||||
);
|
||||
case MessageType.DATA as MessageType:
|
||||
return <></>;
|
||||
case MessageType.CHNAME as MessageType:
|
||||
return <></>;
|
||||
default:
|
||||
console.error("Illegal MessageType reported!");
|
||||
return (
|
||||
<p className="msg-err">
|
||||
[{timeString}] **THIS MESSAGE CANNOT BE
|
||||
CORRECTLY SHOWN BECAUSE THE CLIENT
|
||||
ENCOUNTERED AN ERROR**
|
||||
</p>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,51 +1,46 @@
|
|||
export const enum MessageType {
|
||||
MESSAGE = "MESSAGE",
|
||||
CHNAME = "CHNAME",
|
||||
HELLO = "HELLO",
|
||||
DATA = "DATA",
|
||||
MESSAGE = "MESSAGE",
|
||||
CHNAME = "CHNAME",
|
||||
HELLO = "HELLO",
|
||||
DATA = "DATA",
|
||||
}
|
||||
export enum SystemMessageCode {
|
||||
REQ,
|
||||
RES,
|
||||
ERR,
|
||||
REQ,
|
||||
RES,
|
||||
ERR,
|
||||
}
|
||||
export type HistoryFetchResult = {
|
||||
count: number;
|
||||
items: Array<ChatMessage>;
|
||||
count: number;
|
||||
items: Array<ChatMessage>;
|
||||
};
|
||||
export type ErrorResult = {
|
||||
text: string;
|
||||
text: string;
|
||||
};
|
||||
export type TimestampSendRequest = {
|
||||
ts: number;
|
||||
ts: number;
|
||||
};
|
||||
export type SystemMessage = {
|
||||
code: SystemMessageCode;
|
||||
data: HistoryFetchResult | ErrorResult | TimestampSendRequest;
|
||||
code: SystemMessageCode;
|
||||
data: HistoryFetchResult | ErrorResult | TimestampSendRequest;
|
||||
};
|
||||
export type ChatMessage = {
|
||||
fromUserId: string;
|
||||
toUserId: string;
|
||||
content: string;
|
||||
timeMillis: number;
|
||||
fromUserId: string;
|
||||
toUserId: string;
|
||||
content: string;
|
||||
timeMillis: number;
|
||||
};
|
||||
export type HelloMessage = {
|
||||
fromUserId: string;
|
||||
timeMillis: number;
|
||||
fromUserId: string;
|
||||
timeMillis: number;
|
||||
};
|
||||
export type DataMessage = {};
|
||||
export type Message = {
|
||||
type: MessageType;
|
||||
// data: SystemMessage | ChatMessage | HelloMessage
|
||||
fromUserId: string;
|
||||
toUserId: string;
|
||||
content: string;
|
||||
timeMillis: number;
|
||||
type: MessageType;
|
||||
// data: SystemMessage | ChatMessage | HelloMessage
|
||||
fromUserId: string;
|
||||
toUserId: string;
|
||||
content: string;
|
||||
timeMillis: number;
|
||||
};
|
||||
export const acceptedLangs = [
|
||||
"en_US",
|
||||
"zh_TW",
|
||||
"el_GR",
|
||||
"ar_SA"
|
||||
] as const;
|
||||
export const acceptedLangs = ["en_US", "zh_TW", "el_GR", "ar_SA"] as const;
|
||||
export type LangType = (typeof acceptedLangs)[number];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export type User = {
|
||||
id: number;
|
||||
userName: string;
|
||||
dateJoined: number;
|
||||
lastSeen: number;
|
||||
passwordHash: string;
|
||||
id: number;
|
||||
userName: string;
|
||||
dateJoined: number;
|
||||
lastSeen: number;
|
||||
passwordHash: string;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue