Reactor Chat Tutorial, Part 2
Chat Example 2 adds the following new features to Chat Example 1:
- Customizable user names
- User join/leave messages
- A user list
Here's what the new chat looks like:
Note: this example focuses on the Reactor API, and therefore shows only the bare minimum code required to create a chat user interface.
The Code
Here's the code for the new chat:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | package { import flash.display.Sprite; import flash.events.KeyboardEvent; import flash.text.TextField; import flash.text.TextFieldType; import flash.ui.Keyboard; import net.user1.reactor.Attribute; import net.user1.reactor.IClient; import net.user1.reactor.Reactor; import net.user1.reactor.ReactorEvent; import net.user1.reactor.Room; import net.user1.reactor.RoomEvent; import net.user1.reactor.SynchronizationState; public class UnionChatPart2 extends Sprite { // Union objects protected var reactor:Reactor; protected var chatRoom:Room; // User interface objects protected var incomingMessages:TextField; protected var outgoingMessages:TextField; protected var userlist:TextField; protected var nameInput:TextField; // Constructor public function UnionChatPart2 () { // Create the user interface buildUI(); // Make the Reactor object reactor = new Reactor(); // Run readyListener() when the connection is ready reactor.addEventListener(ReactorEvent.READY, readyListener); // Connect to the server reactor.connect("tryunion.com", 80); } // Method invoked when the connection is ready protected function readyListener (e:ReactorEvent):void { incomingMessages.appendText("Connected to Union\n"); chatRoom = reactor.getRoomManager().createRoom( "chatRoom"); chatRoom.addMessageListener("CHAT_MESSAGE", chatMessageListener); chatRoom.addEventListener(RoomEvent.JOIN, joinRoomListener); chatRoom.addEventListener(RoomEvent.ADD_OCCUPANT, addClientListener); chatRoom.addEventListener(RoomEvent.REMOVE_OCCUPANT, removeClientListener); chatRoom.addEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE, updateClientAttributeListener); chatRoom.join(); } // Create the user interface protected function buildUI ():void { incomingMessages = new TextField; incomingMessages.border = true; incomingMessages.background = true; incomingMessages.width = 300; incomingMessages.height = 200; outgoingMessages = new TextField; outgoingMessages.type = TextFieldType.INPUT; outgoingMessages.border = true; outgoingMessages.background = true; outgoingMessages.width = 399; outgoingMessages.height = 20; outgoingMessages.y = 210; outgoingMessages.addEventListener(KeyboardEvent.KEY_UP, outgoingKeyUpListener); userlist = new TextField(); userlist.border = true; userlist.background = true; userlist.width = 89; userlist.height = 200; userlist.x = 310; nameInput = new TextField(); nameInput.type = TextFieldType.INPUT; nameInput.border = true; nameInput.background = true; nameInput.width = 399; nameInput.height = 20; nameInput.y = 240; nameInput.addEventListener(KeyboardEvent.KEY_UP, nameKeyUpListener); addChild(incomingMessages); addChild(outgoingMessages); addChild(userlist); addChild(nameInput); } // Keyboard listener for outgoingMessages protected function outgoingKeyUpListener (e:KeyboardEvent):void { if (e.keyCode == Keyboard.ENTER) { chatRoom.sendMessage("CHAT_MESSAGE", true, null, outgoingMessages.text); outgoingMessages.text = ""; } } // Keyboard listener for nameInput protected function nameKeyUpListener (e:KeyboardEvent):void { var self:IClient; if (e.keyCode == Keyboard.ENTER) { self = reactor.self(); self.setAttribute("username", nameInput.text); nameInput.text = ""; } } // Method invoked when a chat message is received protected function chatMessageListener (fromClient:IClient, messageText:String ):void { incomingMessages.appendText(getUserName(fromClient) + " says: " + messageText + "\n"); incomingMessages.scrollV = incomingMessages.maxScrollV; } // Method invoked when the current client joins the room protected function joinRoomListener (e:RoomEvent):void { updateUserList(); } // Method invoked when a client joins the room protected function addClientListener (e:RoomEvent):void { if (e.getClient().isSelf()) { incomingMessages.appendText("You joined the chat.\n"); } else { if (chatRoom.getSyncState() != SynchronizationState.SYNCHRONIZING) { // Show a "guest joined" message only when the room isn't performing // its initial occupant-list synchronization. incomingMessages.appendText(getUserName(e.getClient()) + " joined the chat.\n"); } } incomingMessages.scrollV = incomingMessages.maxScrollV; updateUserList(); } // Method invoked when a client leave the room protected function removeClientListener (e:RoomEvent):void { incomingMessages.appendText(getUserName(e.getClient()) + " left the chat.\n"); incomingMessages.scrollV = incomingMessages.maxScrollV; updateUserList(); } // Method invoked when any client in the room // changes the value of a shared attribute protected function updateClientAttributeListener (e:RoomEvent):void { var changedAttr:Attribute = e.getChangedAttr(); if (changedAttr.name == "username") { if (changedAttr.oldValue == null) { incomingMessages.appendText("Guest" + e.getClientID()); } else { incomingMessages.appendText(changedAttr.oldValue); } incomingMessages.appendText(" 's name changed to " + getUserName(e.getClient()) + ".\n"); incomingMessages.scrollV = incomingMessages.maxScrollV; updateUserList(); } } // Helper method to display the room's // clients in the user list protected function updateUserList ():void { userlist.text = ""; for each (var client:IClient in chatRoom.getOccupants()) { userlist.appendText(getUserName(client) + "\n"); } } // Helper method to retrieve a client's user name. // If no user name is set for the specified client, // returns "Guestn" (where 'n' is the client's id). protected function getUserName (client:IClient):String { var username:String = client.getAttribute("username"); if (username == null) { return "Guest" + client.getClientID(); } else { return username; } } } } |