2.4.1 View
The below View has no well-defined Control to support the script system. Through the Message implementation, directly send the custom string command to the specific View to implement the control function.
-
TemporaryView
-
Create and enter the ChatRoom
UserInfo.java:
private void joinRoom(long roomid, long sessionid) { Procedure.execute(ProcedureHelper.nameProcedure("joinRoom", () -> { ChatRoom view = table.Roominfocache.update(roomid); if (null == view) { ......................................... view = ChatRoom.createInstance(); view.setInfo(new ViewChatRoomInfo(info.getName(), roomid)); view.setRoomId(roomid); table.Roominfocache.insert(roomid, view); } view.getMembership().add(sessionid); return true; })); }
The ChatRoom is saved in a Cache with the roomid as the index. If it is not existed in the Cache, it will be created and added into the Cache. Then the current user joins the ChatRoom as the member.
The user joins the ChatRoom:
ChatRoom.java:
protected void onAttached(long sessionid) { RoomInfo.increment_memberCount_mapkey(roomid, 1); }
Here the server makes a simple count. After the message of the member joining is noticed to all the members, the server generates this message to inform the server application that the join action has been finished.
chatroom.js:
v100.chatviews.ChatRoom.onopen = function(instanceid, memberids) { currentChatView = this[instanceid]; showChatFrame(currentChatView); ctx.register(currentChatView, "info", function(e) { showChatRoomName(e.value); }); ctx.register(currentChatView, "names", function(e) { updateName(e.sessionid, e.value.nickname); }); ctx.register(currentChatView, "lastmessage", function(e) { if (e.type == 1 || e.type == 2) showMessageToAll(e.value.user, e.value.msg); }); }
The new member itself, the current chatView is created in the client, the showChatFrame displays the chat webpage, and the listener of three fields of the ChatRoom are registered to listen the information change of the ChatRoom.
v100.chatviews.ChatRoom.onattach = function(instanceid, memberid) { onMemberAttach(memberid); }
The previous members receive the notification that there is new member joined. Then, the new member's described message is sent to the previous members.
function onMemberAttach(sessionid) { var done = false; if (typeof (currentChatView[sessionid]) != "undefined" && typeof (currentChatView[sessionid].names) != "undefined") { showTextToMessages("[user \"" + currentChatView[sessionid].names.nickname + "\" enter room]"); done = true; } if (!done) setTimeout("onMemberAttach( " + sessionid + ")", 1); }
A 1ms timer is used here to detect the received described information (username) of the new member. After receiving the message, the join message is reported in the chatroom. Actually, the message that new member enters and the data of the subscribed information are packaged and sent to the client, but because that the subscribed information is notified before the entering message is unreasonable, here is this kind of implementation. There is the solution without the timer -- onMemberAttach, which uses the container to record the new member's sessionid. When processing the subscribed message, it checks whether the sessionid is recorded. If yes, the sessionid is processed as the new member and is deleted from the container. If not, it is processed as the normal logic.
-
Leave the ChatRoom
-
Initiative leave
The user sends the leave Message to the ChatRoom.
chatroom.js:
function doLeave() { context.send(currentChatView, "leave="); }
ChatRoom.java:
protected void onMessage(String message, long sessionid) { int index = message.indexOf('='); if (-1 == index) return; final String cmd = message.substring(0, index).trim(); final String params = message.substring(index + 1); switch (cmd) { ............................... case "leave": { getMembership().remove(sessionid, (byte) 1); return; } } }
The server deletes the current user from the member list and sets the user definition closeReason as 1.
ChatRoom.java:
protected void onDetached(long sessionid, byte reason) { RoomInfo.increment_memberCount_mapkey(roomid, -1L); ........................ }
The server here makes a simple count. After the information that the member leaves is notified to the other members, the server generates this message to notify the server that the leave action has finished.
The left user itself.
chatroom.js:
v100.chatviews.ChatRoom.onclose = function(instanceid) { showMainFrame(); currentChatView = null; }
ShowMainFrame, enters the room selection.
The other users.
chatroom.js:
v100.chatviews.ChatRoom.ondetach = function(instanceid, memberid, reason) { onMemberDetach(memberid, reason >= 0); }
The user leave message is reported via onMemberDetach. The (reason==1)>=0 reports that the memberid leaves the Chatroom.
-
Disconnect leave
ChatRoom.java:
protected void onDetached(long sessionid, byte reason) { RoomInfo.increment_memberCount_mapkey(roomid, -1L); ........................ }
The server here makes a simple count. After the message that the member leaves is notified to the other members, the server generates this message to notify the server that the leave action has finished. reason == -1.
The other users
chatroom.js:
v100.chatviews.ChatRoom.ondetach = function(instanceid, memberid, reason) { onMemberDetach(memberid, reason >= 0); }
Here the reason < 0, onMemberDetach reports that the user memberid disconnects.
-
-
Destroy the Chatroom
Main.java:
private static void updateViewHallsFromCache(long sessionid, String message, List
destroylist) { ............................................ ProcedureHelper.executeWhileCommit(() -> Engine .getApplicationExecutor().execute(() -> { SessionManager.setViewHallsFromCache(); destroylist.forEach(room -> room.destroyInstance()); })); } cmdmap.put("deleteroom", (sessionid, params) -> { if (params.length < 3 || !UserInfo.getInstance(sessionid).isCommandMode()) return; Procedure.execute(() -> { ............................................ ChatRoom view = table.Roominfocache.update(removeroomid); List<ChatRoom> roomlist = new ArrayList<>(); if (null != view) { roomlist.add(view); table.Roominfocache.delete(removeroomid); } updateViewHallsFromCache(sessionid, "delete room succeed",roomlist); return true; }); }); The Roominfocache saves the ChatRoom list which needs to be destroyed via roomlist after deleting the room. After executing updateViewHallsFromCache, a task which is executed after the transaction is submitted is called to schedule an execution order. First update all the chatroom information via SessionManager.setViewHallsFromCache(), then delete the saved ChatRoom one by one. The reason is that:
ChatRoom.java:
protected void onDetached(long sessionid, byte reason) { RoomInfo.increment_memberCount_mapkey(roomid, -1L); UserInfo info = UserInfo.getInstance(sessionid); if (info != null) info.checkUpdateHallInfos(); }
The info.checkUpdateHallInfos() sends all the previous updated Chatroom information to the client appointed by the sessionid. So the appearance of the client is that first exit the chat page and enter the chatroom selection page, then the chatroom select page is refreshed.
It is noted that after obtaining the info, it needs to check whether the info is null. When the user disconnects, the ViewContext related to the user changes to the close status, and the info returns null. Usually, after executing the View's query operation, it should check whether the null is returned to avoid to process the unnecessary exception.
You could make an example. After entering the test chatroom, input the command:
1. .cm on 123456 2. .cm createhall hall0 3. .cm createroom hall0 room0
After inputting the above three commands, exit the chatroom, then reenter the room0 chatroom.
Input the commands:
1. .cm on 123456 2. .cm deleteroom hall0 room0
After the command 2 is input, the current user is kicked out from the chatroom page, and a page like the previous chatroom selection could be seen. Then the room0 is refreshed right now.
Other,
cmdmap.put("deletehall", (sessionid, params) -< { ............................................ }
The whole chat hall could be deleted and all the ChatRoom of the hall could be destroyed.
-