|
@@ -0,0 +1,213 @@
|
|
|
+const URL = "http://localhost:4000/message"
|
|
|
+const delay = ms => new Promise((resolve) => setTimeout(() => resolve(ms), ms));
|
|
|
+
|
|
|
+
|
|
|
+function createStore(reducer) {
|
|
|
+ let state = reducer(undefined, {})
|
|
|
+ let subscribers = []
|
|
|
+
|
|
|
+ function dispatch(action) {
|
|
|
+ if (typeof action === 'function') {
|
|
|
+ return action(dispatch)
|
|
|
+ }
|
|
|
+ const newState = reducer(state, action)
|
|
|
+ if (state !== newState) {
|
|
|
+ state = newState
|
|
|
+ subscribers.forEach(cb => cb())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ getState() {
|
|
|
+ return state;
|
|
|
+ },
|
|
|
+ subscribe(cb) {
|
|
|
+ subscribers.push(cb)
|
|
|
+ return () => subscribers = subscribers.filter(c => c !== cb)
|
|
|
+ },
|
|
|
+ dispatch
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+let btnSend = document.querySelector('#send');
|
|
|
+let inputNick = document.querySelector('#nick');
|
|
|
+let inputMessage = document.querySelector('#msg');
|
|
|
+let lastMessageId =0;
|
|
|
+
|
|
|
+async function getHistory() {
|
|
|
+ let msg = await jsonPost(
|
|
|
+ URL,
|
|
|
+ {func: 'getMessages',
|
|
|
+ messageId: lastMessageId})
|
|
|
+ lastMessageId = msg.nextMessageId
|
|
|
+ msg.data.forEach(i => showMessage(i.nick, i.message))
|
|
|
+}
|
|
|
+
|
|
|
+getHistory().then();
|
|
|
+
|
|
|
+function showMessage(inputNick, inputMessage) {
|
|
|
+ let divChat = document.querySelector('#chat');
|
|
|
+ let msgDiv = document.createElement('div');
|
|
|
+ msgDiv.style.display = 'inline-block';
|
|
|
+ let nickSpan = document.createElement('span');
|
|
|
+ nickSpan.innerHTML= '<b/>' + inputNick + ' : '
|
|
|
+ let messSpan = document.createElement('span');
|
|
|
+ messSpan.innerHTML= inputMessage
|
|
|
+
|
|
|
+ msgDiv.style.cssText = 'border-bottom: 1px solid gray; padding: 5px;'
|
|
|
+ divChat.prepend(msgDiv);
|
|
|
+ msgDiv.prepend(messSpan);
|
|
|
+ msgDiv.prepend(nickSpan);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function chatReducer(
|
|
|
+ state = {
|
|
|
+ messages: [],
|
|
|
+ sendStatus: "",
|
|
|
+ getStatus: "",
|
|
|
+ nextMessageId: 0
|
|
|
+ },
|
|
|
+ {type, messages=[]}) {
|
|
|
+
|
|
|
+ if (type === 'SEND_PENDING') {
|
|
|
+ return {...state, sendStatus: 'PENDING'}
|
|
|
+ }
|
|
|
+ if (type === 'SEND_RESOLVED') {
|
|
|
+ return {...state, sendStatus: 'RESOLVED'}
|
|
|
+ }
|
|
|
+ if (type === 'SEND_REJECTED') {
|
|
|
+ return {...state, sendStatus: 'REJECTED'}
|
|
|
+ }
|
|
|
+ if (type === 'SEND_CLEAR') {
|
|
|
+ return {...state, sendStatus: 'CLEAR'}
|
|
|
+ }
|
|
|
+ if (type === 'GET_PENDING') {
|
|
|
+ return {...state, getStatus: 'PENDING'}
|
|
|
+ }
|
|
|
+ if (type === 'GET_RESOLVED') {
|
|
|
+ return {...state, getStatus: 'PENDING', messages: [...state.messages, ...messages]}
|
|
|
+ }
|
|
|
+ if (type === 'GET_REJECTED') {
|
|
|
+ return {...state, getStatus: 'REJECTED'}
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return state;
|
|
|
+}
|
|
|
+
|
|
|
+const actionSendPending = () => ({type: "SEND_PENDING"})
|
|
|
+const actionSendResolved = () => ({type: "SEND_RESOLVED"})
|
|
|
+const actionSendRejected = () => ({type: "SEND_REJECTED"})
|
|
|
+
|
|
|
+const actionGetPending = () => ({type: "GET_PENDING"})
|
|
|
+const actionGetResolved = (messages, nextMessageId) => ({type: "GET_RESOLVED", messages,nextMessageId})
|
|
|
+const actionGetRejected = () => ({type: "GET_REJECTED"})
|
|
|
+const actionSendClear = () => ({type: "SEND_CLEAR"})
|
|
|
+
|
|
|
+const store = createStore(chatReducer)
|
|
|
+
|
|
|
+store.subscribe(() => console.log(store.getState()));
|
|
|
+
|
|
|
+store.subscribe(() => {}
|
|
|
+ // btnSend.disabled = store.getState().sendStatus === "PENDING";
|
|
|
+ // store.getState().sendStatus === "RESOLVED" && store.dispatch(actionSendClear())}
|
|
|
+ // store.dispatch(actionSendClear())
|
|
|
+ )
|
|
|
+
|
|
|
+const actionSend = (nick, message) =>
|
|
|
+ async dispatch => {
|
|
|
+ try {
|
|
|
+ dispatch(actionSendPending())
|
|
|
+ await jsonPost(
|
|
|
+ URL,
|
|
|
+ {
|
|
|
+ func: 'addMessage',
|
|
|
+ nick: nick,
|
|
|
+ message: message
|
|
|
+ }
|
|
|
+ )
|
|
|
+ dispatch(actionSendResolved())
|
|
|
+ } catch (e) {
|
|
|
+ dispatch(actionSendRejected(e))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+const actionGet = () =>
|
|
|
+
|
|
|
+ async dispatch => {
|
|
|
+ try {
|
|
|
+
|
|
|
+ dispatch(actionGetPending())
|
|
|
+ let data= await jsonPost(
|
|
|
+ URL,
|
|
|
+ {
|
|
|
+ func: 'getMessages',
|
|
|
+ messageId: lastMessageId
|
|
|
+ }
|
|
|
+ )
|
|
|
+ dispatch(actionGetResolved(data.data,data.nextMessageId))
|
|
|
+ lastMessageId = data.nextMessageId;
|
|
|
+ data.data.forEach(i => showMessage(i.nick, i.message))
|
|
|
+ } catch (e) {
|
|
|
+ dispatch(actionGetRejected(e))
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ // checkLoop().then()
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+store.getState()
|
|
|
+const sendAndCheck=async()=>{
|
|
|
+ if(inputNick.value.trim() && inputMessage.value.trim()){
|
|
|
+ await store.dispatch(actionSend(inputNick.value, inputMessage.value))
|
|
|
+ await store.dispatch(actionGet())}
|
|
|
+}
|
|
|
+async function checkLoop() {
|
|
|
+ while (true) {
|
|
|
+ store.dispatch(actionGet())
|
|
|
+ await delay(3000);
|
|
|
+ // await getMessages();
|
|
|
+ }
|
|
|
+}
|
|
|
+checkLoop().then()
|
|
|
+
|
|
|
+
|
|
|
+store.subscribe(() => {
|
|
|
+ let currentState = store.getState()
|
|
|
+ if ("PENDING") {
|
|
|
+ msg.placeholder = 'enter your message'
|
|
|
+ spinner.style.display = "inline-block";
|
|
|
+
|
|
|
+ } else if (currentState === "REJECTED") {
|
|
|
+
|
|
|
+ msg.placeholder = 'error'
|
|
|
+ msg.style.background='red'
|
|
|
+ spinner.style.display = "none";
|
|
|
+ } else if (currentState === "RESOLVED") {
|
|
|
+ msg.placeholder = 'enter your message'
|
|
|
+ spinner.style.display = "none";
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+btnSend.onclick = () => {store.dispatch(sendAndCheck())
|
|
|
+ inputMessage.value=''
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+async function jsonPost(url, data) {
|
|
|
+ let response = await fetch(url, {
|
|
|
+ method: 'POST',
|
|
|
+ body: JSON.stringify(data),
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.status == 200) {
|
|
|
+ let data2 = await response.json();
|
|
|
+ return data2;
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new Error('failed');
|
|
|
+}
|