master #6
| @ -65,8 +65,9 @@ x | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|     <script src="/assets/js/common.js"></script> | ||||
|     <script src="/assets/js/common-popup.js"></script> | ||||
|     <script src="/assets/js/list-rooms.js"></script> | ||||
| </body> | ||||
| </html> | ||||
| {% ENDELDEF %} | ||||
| {% ENDELDEF %} | ||||
|  | ||||
| @ -3,7 +3,8 @@ | ||||
| } | ||||
| 
 | ||||
| #CL-bacbe { | ||||
|     margin: 6px; | ||||
|     margin-top: 6px; | ||||
|     margin-bottom: 4px; | ||||
| } | ||||
| 
 | ||||
| .CL-my-chat-box { | ||||
|  | ||||
| @ -28,9 +28,6 @@ let members = new Map(); | ||||
| for (let memberSt of initial_chatUpdResp.members){ | ||||
|     members.set(memberSt.id, memberSt); | ||||
| } | ||||
| // members.set(1, {id: 1, name: 'grisha', nickname: 'gri', role: 'admin'});
 | ||||
| // members.set(2, {id: 2, name: 'Pavlov Vladimir', nickname: 'pv', role: 'regular'});
 | ||||
| // members.set(3, {id: 3, name: 'Ivan', nickname: 'ivan', role: 'read-only'});
 | ||||
| 
 | ||||
| function updateOffsetOfVisibleMsg(msgId, offset){ | ||||
|     visibleMessages.get(msgId).style.bottom = String(offset) + "px"; | ||||
| @ -180,13 +177,10 @@ function test(id, uid){ | ||||
| } | ||||
| 
 | ||||
| let mainloopTimeout = null; | ||||
| 
 | ||||
| let mainloopPoller = null; | ||||
| 
 | ||||
| function setMainloopTimeout(){ | ||||
|     mainloopTimeout = setTimeout(mainloopPoller, 1000); | ||||
| } | ||||
| 
 | ||||
| mainloopPoller = function(){ | ||||
|     try { | ||||
|         console.log("Hello, World!"); | ||||
|  | ||||
							
								
								
									
										52
									
								
								assets/js/common.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								assets/js/common.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| async function apiRequest(type, req){ | ||||
|     let A = await fetch("/api/" + type, | ||||
|         {method: 'POST', body: JSON.stringify(req)}); | ||||
|     let B = await A.json(); | ||||
|     if (B.status !== 0) | ||||
|         throw Error("Server returned non-zero status"); | ||||
|     return B; | ||||
| } | ||||
| 
 | ||||
| /* Framework for pages with mainloop (it can be npt only polling, but also literally anything else */ | ||||
| let __mainloopDelayMs = 3000; | ||||
| let mainloopTimeout = null; | ||||
| let mainloopPoller = null; | ||||
| let __guestMainloopPollerAction = null; | ||||
| function setMainloopTimeout(){ | ||||
|     mainloopTimeout = setTimeout(mainloopPoller, __mainloopDelayMs); | ||||
| } | ||||
| function cancelMainloopTimeout(){ | ||||
|     clearTimeout(mainloopTimeout); | ||||
| } | ||||
| mainloopPoller = function(){ | ||||
|     try { | ||||
|         console.log("Hello, World!"); | ||||
|         __guestMainloopPollerAction(); | ||||
|     } catch (error){ | ||||
|         console.log(error) | ||||
|     } | ||||
|     setMainloopTimeout(); | ||||
| } | ||||
| 
 | ||||
| // 1
 | ||||
| const userChatRoleAdmin = "admin"; | ||||
| // 2
 | ||||
| const userChatRoleRegular = "regular"; | ||||
| // 3
 | ||||
| const userChatRoleReadOnly = "read-only"; | ||||
| // 4
 | ||||
| const userChatRoleDeleted = "not-a-member"; | ||||
| 
 | ||||
| function roleToColor(role) { | ||||
|     if (role === userChatRoleAdmin) { | ||||
|         return "#aafff3"; | ||||
|     } else if (role === userChatRoleRegular){ | ||||
|         return "#ffffff"; | ||||
| 
 | ||||
|     } else if (role === userChatRoleReadOnly){ | ||||
|         return "#bfb2b2"; | ||||
|     } else if (role === userChatRoleDeleted) { | ||||
|         return "#fb4a4a"; | ||||
|     } | ||||
|     return "#286500"  // Bug
 | ||||
| } | ||||
| @ -1,12 +1,35 @@ | ||||
| let LocalHistoryId = 0; | ||||
| 
 | ||||
| function genSentBase(){ | ||||
|     return { | ||||
|         'chatListUpdReq': { | ||||
|             'LocalHistoryId': LocalHistoryId | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| let myChats = new Map(); | ||||
| let chatBoxes = new Map(); | ||||
| 
 | ||||
| const roleDeleted = "not-a-member"; | ||||
| /* Generate text that is displayed on the right side of chat intro box */ | ||||
| function youAreXHere(myRoleHere){ | ||||
|     return "You are " + myRoleHere + " here"; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| let chatRenunciationWinStoredId = -1; | ||||
| 
 | ||||
| /* Updating chat html box after myMembershipSt in it was updated */ | ||||
| function updateBoxWithNewSt(box, myMembershipSt){ | ||||
|     let ID = myMembershipSt.chatId; | ||||
|     let roleP = box.querySelector(".CL-my-chat-box-my-role"); | ||||
|     roleP.innerText = youAreXHere(myMembershipSt.myRoleHere); | ||||
|     box.style.backgroundColor = roleToColor(myMembershipSt.myRoleHere); | ||||
| } | ||||
| 
 | ||||
| function convertStToBox(myMembershipSt){ | ||||
|     let chatURI = "/user/" + myMembershipSt.chatNickname; | ||||
|     let ID = myMembershipSt.chatId; | ||||
| 
 | ||||
|     let box = document.createElement("div"); | ||||
|     chatBoxes.set(myMembershipSt.chatId, box); | ||||
| @ -15,10 +38,9 @@ function convertStToBox(myMembershipSt){ | ||||
|     let inBoxNickname = document.createElement("a"); | ||||
|     box.appendChild(inBoxNickname); | ||||
|     inBoxNickname.className = "entity-nickname-txt CL-my-chat-box-nickname"; | ||||
|     console.log(myMembershipSt); | ||||
|     console.log(myMembershipSt.chatNickname); | ||||
|     inBoxNickname.innerText = myMembershipSt.chatNickname; | ||||
|     inBoxNickname.href = chatURI; | ||||
|     box.style.backgroundColor = roleToColor(myMembershipSt.myRoleHere); | ||||
| 
 | ||||
|     let inBoxName = document.createElement("a"); | ||||
|     box.appendChild(inBoxName); | ||||
| @ -29,9 +51,7 @@ function convertStToBox(myMembershipSt){ | ||||
|     let inBoxMyRoleHere = document.createElement("p"); | ||||
|     box.appendChild(inBoxMyRoleHere); | ||||
|     inBoxMyRoleHere.className = "entity-reg-field-txt CL-my-chat-box-my-role"; | ||||
|     inBoxMyRoleHere.innerText = "You are " + myMembershipSt.myRoleHere + " here"; | ||||
| 
 | ||||
|     let ID = myMembershipSt.chatId; | ||||
|     inBoxMyRoleHere.innerText = youAreXHere(myMembershipSt.myRoleHere); | ||||
| 
 | ||||
|     let inBoxLeaveBtn = document.createElement("img"); | ||||
|     box.appendChild(inBoxLeaveBtn); | ||||
| @ -40,19 +60,62 @@ function convertStToBox(myMembershipSt){ | ||||
|     inBoxLeaveBtn.onclick = function (ev) { | ||||
|         if (ev.button !== 0) | ||||
|             return; | ||||
|         console.log("Tried to leave chat" + ID); | ||||
|         chatRenunciationWinStoredId = ID; | ||||
|         activatePopupWindowById("chat-renunciation-win"); | ||||
|         document.getElementById("chat-renunciation-win-title").innerText = | ||||
|             "Do you really want to leave chat " + myMembershipSt.chatNickname + "?"; | ||||
|     }; | ||||
| 
 | ||||
|     return box; | ||||
| } | ||||
| 
 | ||||
| function updateLocalStateFromChatListUpdResp(chatListUpdResp){ | ||||
|     LocalHistoryId = chatListUpdResp.HistoryId; | ||||
| 
 | ||||
|     let literalChatList = document.getElementById("CL-dblec"); | ||||
| 
 | ||||
|     for (let myMembershipSt of chatListUpdResp.myChats){ | ||||
|         let chatId = myMembershipSt.chatId; | ||||
|         console.log(myMembershipSt); | ||||
|         if (myChats.has(chatId)){ | ||||
|             myChats.set(chatId, myMembershipSt); | ||||
|             updateBoxWithNewSt(chatBoxes.get(chatId), myMembershipSt); | ||||
|         } else { | ||||
|             if (myMembershipSt.myRoleHere === userChatRoleDeleted) | ||||
|                 continue; | ||||
|             myChats.set(chatId, myMembershipSt); | ||||
|             let box = convertStToBox(myMembershipSt) | ||||
|             chatBoxes.set(chatId, box); | ||||
|             literalChatList.appendChild(box); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Use it ONLY if `Recv` reported success */ | ||||
| function updateLocalStateFromRecv(Recv){ | ||||
|     updateLocalStateFromChatListUpdResp(Recv.chatListUpdResp); | ||||
| } | ||||
| 
 | ||||
| function configureChatCreationInterface(){ | ||||
|     document.getElementById("chat-creation-win-yes").onclick = function (ev) { | ||||
|         if (ev.button !== 0) | ||||
|             return; | ||||
|         let chatNicknameInput = document.getElementById("chat-nickname-input"); | ||||
|         let chatNameInput = document.getElementById("chat-name-input"); | ||||
|         let nickname = chatNicknameInput.value; | ||||
|         let name = chatNameInput.value; | ||||
|         deactivateActivePopup(); | ||||
|         // todo: create chat, send request
 | ||||
|         let Sent = genSentBase(); | ||||
|         Sent.content = {}; | ||||
|         Sent.content.nickname = nickname; | ||||
|         Sent.content.name = name; | ||||
|         apiRequest("createChat", Sent | ||||
|         ).then((Recv) => { | ||||
|             updateLocalStateFromRecv(Recv); | ||||
|         }).catch((e) => { | ||||
|             alert("Failed to create chat"); | ||||
|             console.log(e); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     document.getElementById("chat-creation-win-no").onclick = function (ev) { | ||||
| @ -64,6 +127,10 @@ function configureChatCreationInterface(){ | ||||
|     document.getElementById("CL-bacbe").onclick = function (ev){ | ||||
|         if (ev.button !== 0) | ||||
|             return; | ||||
|         let chatNicknameInput = document.getElementById("chat-nickname-input"); | ||||
|         let chatNameInput = document.getElementById("chat-name-input"); | ||||
|         chatNicknameInput.value = ""; | ||||
|         chatNameInput.value = ""; | ||||
|         activatePopupWindowById("chat-creation-win"); | ||||
|         console.log("Tried to show chat creation window"); | ||||
|     }; | ||||
| @ -74,7 +141,18 @@ function configureChatRenunciationInterfaceWinPart(){ | ||||
|         if (ev.button !== 0) | ||||
|             return; | ||||
|         deactivateActivePopup(); | ||||
|         // todo: actually leave chat
 | ||||
|         if (chatRenunciationWinStoredId < 0) | ||||
|             throw new Error("chatRenunciationWinStoredId < 0"); | ||||
|         let chatId = chatRenunciationWinStoredId; | ||||
|         let Sent = genSentBase(); | ||||
|         Sent.chatId = chatId; | ||||
|         apiRequest("leaveChat", Sent | ||||
|         ).then((Recv) => { | ||||
|             updateLocalStateFromRecv(Recv); | ||||
|         }).catch((e) => { | ||||
|             alert("Failed to leave chat"); | ||||
|             console.log(e); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     document.getElementById("chat-renunciation-win-no").onclick = function(ev) { | ||||
| @ -84,24 +162,21 @@ function configureChatRenunciationInterfaceWinPart(){ | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| __mainloopDelayMs = 3000; | ||||
| __guestMainloopPollerAction = function(){ | ||||
|     let Sent = genSentBase(); | ||||
|     apiRequest("chatListPollEvents", Sent | ||||
|     ).then((Recv) => { | ||||
|         console.log("Got a response"); | ||||
|         console.log(Recv); | ||||
|         updateLocalStateFromRecv(Recv); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| window.onload = function () { | ||||
|     console.log("Loading complete"); | ||||
|     LocalHistoryId = initial_chatListUpdResp.HistoryId; | ||||
| 
 | ||||
|     console.log(initial_chatListUpdResp); | ||||
| 
 | ||||
|     let literalChatList = document.getElementById("CL-dblec"); | ||||
| 
 | ||||
|     for (let myMembershipSt of initial_chatListUpdResp.myChats){ | ||||
|         console.log(myMembershipSt); | ||||
|         if (myMembershipSt.myRoleHere !== roleDeleted){ | ||||
|             myChats.set(myMembershipSt.chatId, myMembershipSt); | ||||
|             let box = convertStToBox(myMembershipSt) | ||||
|             chatBoxes.set(myMembershipSt.chatId, box); | ||||
|             literalChatList.appendChild(box); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     updateLocalStateFromChatListUpdResp(initial_chatListUpdResp); | ||||
|     configureChatCreationInterface(); | ||||
|     configureChatRenunciationInterfaceWinPart(); | ||||
|     mainloopPoller(); | ||||
| }; | ||||
|  | ||||
| @ -10,10 +10,13 @@ namespace iu9cawebchat { | ||||
|             return json::JSON(json::jdict{{"status", json::JSON(-1l)}}); | ||||
|         if (is_nickname_taken(conn, new_chat_nickname)) | ||||
|             return json::JSON(json::jdict{{"status", json::JSON(-2l)}}); | ||||
|         if (is_nickname_taken(conn, new_chat_nickname)) | ||||
|             return json::JSON(json::jdict{{"status", json::JSON(-3l)}}); | ||||
|         reserve_nickname(conn, new_chat_nickname); | ||||
| 
 | ||||
|         sqlite_nooutput(conn, | ||||
|             "INSERT INTO `chat` (`nickname`, `name`, `it_HistoryId`, `lastMsgId`) VALUES (?1, ?2, 0, -1)"); | ||||
|             "INSERT INTO `chat` (`nickname`, `name`, `it_HistoryId`, `lastMsgId`) VALUES (?1, ?2, 0, -1)", | ||||
|             {}, {{1, new_chat_nickname}, {2, new_chat_name}}); | ||||
| 
 | ||||
|         int64_t CHAT_ID = sqlite_trsess_last_insert_rowid(conn); | ||||
| 
 | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
| 
 | ||||
| namespace iu9cawebchat { | ||||
|     json::JSON poll_update_chat_list_resp(SqliteConnection& conn, int64_t userId, int64_t LocalHistoryId) { | ||||
|         printf("Userid: %ld\n", userId); | ||||
|         json::JSON chatListUpdResp; | ||||
|         SqliteStatement my_membership_changes(conn, | ||||
|            "SELECT `chatId`, `role` FROM `user_chat_membership` WHERE `userId` = ?1 " | ||||
| @ -32,7 +33,8 @@ namespace iu9cawebchat { | ||||
|     void poll_update_chat_list(SqliteConnection& conn, int64_t userId, const json::JSON& Sent, json::JSON& Recv) { | ||||
|         Recv["status"].asInteger() = json::Integer(0l); | ||||
|         // todo: in libjsonincpp: get rid of Integer
 | ||||
|         poll_update_chat_list_resp(conn, userId, Sent["chatListUpdReq"]["LocalHistoryId"].asInteger().get_int()); | ||||
|         printf("%s\n", json::generate_str(Sent, json::print_pretty).c_str()); | ||||
|         Recv["chatListUpdResp"] = poll_update_chat_list_resp(conn, userId, Sent["chatListUpdReq"]["LocalHistoryId"].asInteger().get_int()); | ||||
|     } | ||||
| 
 | ||||
|     json::JSON make_messageSt_obj(int64_t id, int64_t senderUserId, bool exists, bool isSystem, const std::string& text) { | ||||
| @ -158,6 +160,7 @@ namespace iu9cawebchat { | ||||
|     json::JSON internalapi_chatListPollEvents(SqliteConnection& conn, int64_t uid, const json::JSON& Sent) { | ||||
|         json::JSON Recv; | ||||
|         poll_update_chat_list(conn, uid, Sent, Recv); | ||||
|         printf("%s\n", json::generate_str(Recv, json::print_pretty).c_str()); | ||||
|         return Recv; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -144,7 +144,6 @@ namespace iu9cawebchat { | ||||
|     /* All the api calls processing is done in dedicated files.
 | ||||
|      * All functions related to polling are defined in api_pollevents.cpp */ | ||||
| 
 | ||||
|     // todo: move everything to dedicated files
 | ||||
|     int64_t get_current_history_id_of_chat(SqliteConnection& conn, int64_t chatId) { | ||||
|         SqliteStatement req(conn, "SELECT `it_HistoryId` FROM `chat` WHERE `id` = ?1", {{1, chatId}}, {}); | ||||
|         fsql_integer_or_null HistoryId; | ||||
|  | ||||
| @ -36,8 +36,7 @@ int main(int argc, char** argv){ | ||||
|             iu9cawebchat::run_website(config); | ||||
|         } else | ||||
|             een9_THROW("unknown action (known are 'run', 'initialize')"); | ||||
|         // todo: put back execption after debug
 | ||||
|     } catch (std::bad_weak_ptr& e) { | ||||
|     } catch (std::exception& e) { | ||||
|         printf("System failure\n%s\n", e.what()); | ||||
|     } | ||||
|     return 0; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user