瀏覽代碼

Support multiple chatrooms

Thomas Dy 10 年之前
父節點
當前提交
789d56da85
共有 4 個文件被更改,包括 47 次插入12 次删除
  1. 2 2
      app/controllers/Application.scala
  2. 25 7
      app/models/ChatRoom.scala
  3. 1 1
      conf/routes
  4. 19 2
      public/javascripts/chatServices.js

+ 2 - 2
app/controllers/Application.scala

@@ -23,9 +23,9 @@ object Application extends Controller {
   /**
    * Handles the chat websocket.
    */
-  def chat(username: String) = WebSocket.async[JsValue] { request  =>
+  def chat(username: String, room: String = "default") = WebSocket.async[JsValue] { request  =>
 
-    ChatRoom.join(username)
+    ChatRoom.join(room, username)
 
   }
 

+ 25 - 7
app/models/ChatRoom.scala

@@ -19,19 +19,30 @@ object ChatRoom {
 
   implicit val timeout = Timeout(1 second)
 
-  lazy val default = Akka.system.actorOf(Props[ChatRoom])
+  lazy val roomMonitor = Akka.system.actorOf(Props[ChatRoom])
 
-  def join(username:String):scala.concurrent.Future[(Iteratee[JsValue,_],Enumerator[JsValue])] = {
+  var chatRooms = Map.empty[String, ActorRef]
 
-    (default ? Join(username)).map {
+  def closeRoom(room: String) = {
+    chatRooms -= room
+  }
+
+  def join(room: String, username:String):scala.concurrent.Future[(Iteratee[JsValue,_],Enumerator[JsValue])] = {
+
+    if(!chatRooms.keySet(room)) {
+      chatRooms += (room -> Akka.system.actorOf(Props(classOf[ChatRoom], room)))
+    }
+
+    val actor = chatRooms(room)
+    (actor ? Join(username)).map {
 
       case Connected(enumerator) =>
 
         // Create an Iteratee to consume the feed
         val iteratee = Iteratee.foreach[JsValue] { event =>
-          default ! Talk(username, (event \ "text").as[String])
+          actor ! Talk(username, (event \ "text").as[String])
         }.map { _ =>
-          default ! Quit(username)
+          actor ! Quit(username)
         }
 
         (iteratee,enumerator)
@@ -54,7 +65,7 @@ object ChatRoom {
 
 }
 
-class ChatRoom extends Actor {
+class ChatRoom(name: String) extends Actor {
 
   val tabooGame = Akka.system.actorOf(Props(classOf[TabooGame], self))
 
@@ -101,7 +112,14 @@ class ChatRoom extends Actor {
 
     case Quit(username) => {
       members = members - username
-      tabooGame ! Quit(username)
+      if(members.isEmpty) {
+        ChatRoom.closeRoom(name)
+        context.stop(tabooGame)
+        context.stop(self)
+      }
+      else {
+        tabooGame ! Quit(username)
+      }
     }
 
   }

+ 1 - 1
conf/routes

@@ -4,7 +4,7 @@
 
 # Home page
 GET     /                                controllers.Application.index
-GET     /room/chat                       controllers.Application.chat(username)
+GET     /room/chat                       controllers.Application.chat(username, room)
 GET     /jsRoutes                        controllers.Application.javascriptRoutes
 
 GET     /cards                           controllers.Cards.dump

+ 19 - 2
public/javascripts/chatServices.js

@@ -1,5 +1,5 @@
 angular.module('chatServices', [])
-.factory('Connection', function($rootScope, $timeout, $interval) {
+.factory('Connection', function($rootScope, $timeout, $interval, $location) {
   var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket;
   var chatSocket = null;
   var ping = null;
@@ -25,9 +25,26 @@ angular.module('chatServices', [])
     }
   };
 
+  function makeid() {
+    var text = "";
+    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+    for( var i=0; i < 5; i++ )
+      text += possible.charAt(Math.floor(Math.random() * possible.length));
+
+    return text;
+  }
+
+  function getRoom() {
+    if(!$location.path()) {
+      $location.path(makeid());
+    }
+    return $location.path();
+  }
+
   service.connect = function(username) {
     service.error = null;
-    chatSocket = new WS(jsRoutes.controllers.Application.chat(username).webSocketURL());
+    chatSocket = new WS(jsRoutes.controllers.Application.chat(username, getRoom()).webSocketURL());
     chatSocket.onmessage = wrap(function(event) {
       var message = JSON.parse(event.data);
       if(message.error) {