Skip to content

Instantly share code, notes, and snippets.

@milesegan
Created August 16, 2010 03:15
Show Gist options
  • Save milesegan/526333 to your computer and use it in GitHub Desktop.
Save milesegan/526333 to your computer and use it in GitHub Desktop.
package code.comet
import net.liftweb._
import http._
import actor._
import js._
import JsCmds._
import js.jquery.JqJsCmds.{AppendHtml, FadeOut, Hide, FadeIn}
import java.util.Date
import scala.xml._
import util.Helpers._
import util.Log
object ChatServer extends LiftActor with ListenerManager {
private var messages: List[ChatCmd] = List("Welcome")
def createUpdate = messages
override def lowPriority = {
case s: String => messages ::= s ; updateListeners()
case d: RemoveMessage => messages ::= d ; updateListeners()
}
}
sealed trait ChatCmd
object ChatCmd {
implicit def strToMsg(msg: String): ChatCmd =
new AddMessage(nextFuncName, msg, new Date)
}
final case class AddMessage(guid: String, msg: String, date: Date) extends ChatCmd
final case class RemoveMessage(guid: String) extends ChatCmd
class Chat extends CometActor with CometListener {
private var msgs: List[ChatCmd] = Nil
private var bindLine: NodeSeq = Nil
def registerWith = ChatServer
override def lowPriority = {
case m: List[ChatCmd] => {
val delta = m diff msgs
msgs = m
updateDeltas(delta)
}
}
def updateDeltas(what: List[ChatCmd]) {
partialUpdate(what.foldRight(Noop) {
case (m: AddMessage , x) =>
x & AppendHtml("ul_dude", doLine(m)) &
Hide(m.guid) & FadeIn(m.guid, TimeSpan(0),TimeSpan(500))
case (RemoveMessage(guid), x) =>
x & FadeOut(guid,TimeSpan(0),TimeSpan(500)) &
After(TimeSpan(500),Replace(guid, NodeSeq.Empty))
})
}
def render =
bind("chat", // the namespace for binding
"line" -> lines _, // bind the function lines
"input" -> SHtml.text("", s => ChatServer ! s)) // the input
private def lines(xml: NodeSeq): NodeSeq = {
bindLine = xml
val deleted = Set((for {
RemoveMessage(guid) <- msgs
} yield guid) :_*)
for {
m @ AddMessage(guid, msg, date) <- msgs.reverse if !deleted.contains(guid)
node <- doLine(m)
} yield node
}
private def doLine(m: AddMessage): NodeSeq =
bind("chat", addId(bindLine, m.guid),
"msg" -> m.msg,
"btn" -> SHtml.ajaxButton("delete",
() => {
ChatServer !
RemoveMessage(m.guid)
Noop}))
private def addId(in: NodeSeq, id: String): NodeSeq = in map {
case e: Elem => e % ("id" -> id)
case x => x
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment