start user preferences implementation

pull/83/head
Thibault Duplessis 2013-10-19 17:22:32 +02:00
parent d692442eca
commit dbd405a796
16 changed files with 181 additions and 60 deletions

View File

@ -2,12 +2,11 @@ package controllers
import lila.app._
import views._
import lila.user.{ Context, BodyContext, Setting UserSetting }
import play.api.data.Form
import play.api.mvc._, Results._
object Setting extends LilaController {
object Pref extends LilaController {
def set(name: String) = OpenBody { implicit ctx
implicit val req = ctx.body

View File

@ -27,7 +27,7 @@ object Environment
with PaginatorHelper
with FormHelper
with SetupHelper
with SettingHelper
with PrefHelper
with MessageHelper
with lila.round.RoundHelper
with AiHelper

View File

@ -0,0 +1,15 @@
package lila.app
package templating
import lila.user.Context
import lila.pref.{ Theme, SessionAware }
import lila.pref.Env.{ current prevEnv }
import play.api.templates.Html
trait PrefHelper {
def pref(implicit ctx: Context) = new SessionAware(prevEnv.api)
def themeList = Theme.list
}

View File

@ -1,13 +0,0 @@
package lila.app
package templating
import lila.user.{ Theme, Setting, Context }
import play.api.templates.Html
trait SettingHelper {
def setting(implicit ctx: Context) = new Setting(ctx)
def themeList = Theme.list
}

View File

@ -102,8 +102,8 @@ GET /$gameId<[\w\-]{8}>/stats controllers.Analyse.stats(gameId: Strin
GET /$gameId<[\w\-]{8}>/pgn controllers.Analyse.pgn(gameId: String)
GET /$gameId<[\w\-]{8}>/fen controllers.Analyse.fen(gameId: String)
# Setting
POST /setting/:name controllers.Setting.set(name: String)
# Pref
POST /pref/:name controllers.Pref.set(name: String)
# Setup
GET /setup/ai controllers.Setup.aiForm

View File

@ -0,0 +1,15 @@
package lila.pref
import play.api.data._
import play.api.data.Forms._
object DataForm {
val theme = Form(single(
"theme" -> nonEmptyText.verifying(Theme contains _)
))
val bg = Form(single(
"bg" -> text.verifying(Set("light", "dark") contains _)
))
}

View File

@ -0,0 +1,21 @@
package lila.pref
import com.typesafe.config.Config
final class Env(
config: Config,
db: lila.db.Env) {
private val CollectionPref = config getString "collection.pref"
private[pref] lazy val prefColl = db(CollectionPref)
}
object Env {
private def app = play.api.Play.current
lazy val current = "[boot] pref" describes new Env(
config = lila.common.PlayApp loadConfig "pref",
db = lila.db.Env.current)
}

View File

@ -0,0 +1,58 @@
package lila.pref
import scala._
case class Pref(
id: String, // user id
dark: Boolean,
chat: Boolean,
sound: Boolean,
theme: String) {
def realTheme = Theme(theme)
def toggleDark = copy(dark = !dark)
def toggleChat = copy(chat = !chat)
def toggleSound = copy(sound = !sound)
def get(name: String): Option[String] = name match {
case "dark" dark.toString.some
case "chat" chat.toString.some
case "sound" sound.toString.some
case "theme" theme.some
case _ none
}
def set(name: String, value: String): Option[Pref] = name match {
case "dark" Pref.booleans get value map { b copy(dark = b) }
case "chat" Pref.booleans get value map { b copy(chat = b) }
case "sound" Pref.booleans get value map { b copy(sound = b) }
case "theme" Theme.allByName get value map { t copy(theme = t.name) }
case _ none
}
}
object Pref {
val default = Pref(
id = "",
dark = false,
chat = true,
sound = false,
theme = Theme.default.name)
private val booleans = Map("true" -> true, "false" -> false)
import lila.db.Tube
import Tube.Helpers._
import play.api.libs.json._
private[pref] lazy val tube = Tube[Pref](
(__.json update merge(defaults)) andThen Json.reads[Pref],
Json.writes[Pref]
)
private def defaults = Json.obj(
"dark" -> default.dark,
"chat" -> default.chat,
"sound" -> default.sound,
"theme" -> default.theme)
}

View File

@ -0,0 +1,24 @@
package lila.pref
import lila.user.User
import tube.prefTube
import lila.db.api._
final class PrefApi {
def getPref(id: String): Fu[Pref] = $find byId id map (_ | Pref.default)
def getPref(user: User): Fu[Pref] = getPref(user.id)
def getPref[A](user: User, pref: Pref A): Fu[A] = getPref(user) map pref
def getPrefString(user: User, name: String): Fu[Option[String]] =
getPref(user) map (_ get name)
def setPref(pref: Pref): Funit = $update(pref)
def setPref(user: User, change: Pref Pref): Funit =
getPref(user) map change flatMap setPref
def setPrefString(user: User, name: String, value: String): Funit =
getPref(user) map (_ get name)
}

View File

@ -0,0 +1,24 @@
package lila.pref
import play.api.mvc.Cookie
import lila.common.LilaCookie
import lila.user.Context
final class SessionAware(api: PrefApi)(implicit ctx: Context) {
def theme: Theme = Theme(get("theme").map(_ | Pref.default.theme).await)
def theme(value: String) = set("theme", Theme(value).toString)
def bg: String = ~get("dark").await.fold("light", "dark")
def bg(value: String) = set("dark", value)
private def get(name: String): Fu[Option[String]] =
fuccess(ctx.req.session get name) orElse {
ctx.me ?? { api.getPrefString(_, name) }
}
private def set(name: String, value: String): Fu[Cookie] =
ctx.me ?? { api.setPrefString(_, name, value) } inject
LilaCookie.session(name, value.toString)(ctx.req)
}

View File

@ -1,4 +1,4 @@
package lila.user
package lila.pref
import scalaz.NonEmptyList

View File

@ -0,0 +1,12 @@
package lila
import lila.db.Tube
package object pref extends PackageObject with WithPlay {
object tube {
private[pref] implicit lazy val prefTube =
Pref.tube inColl Env.current.prefColl
}
}

View File

@ -9,14 +9,6 @@ object DataForm {
"bio" -> text(maxLength = 400)
))
val theme = Form(single(
"theme" -> nonEmptyText.verifying(Theme contains _)
))
val bg = Form(single(
"bg" -> text.verifying(Set("light", "dark") contains _)
))
case class Passwd(
oldPasswd: String,
newPasswd1: String,
@ -32,6 +24,4 @@ object DataForm {
"the new passwords don't match",
_.samePasswords
))
private def jsBoolean = nonEmptyText.verifying(Set("true", "false") contains _)
}

View File

@ -1,29 +0,0 @@
package lila.user
import play.api.mvc.Cookie
import lila.common.LilaCookie
final class Setting(ctx: Context) {
def theme = Theme(get("theme"))
def theme(value: String) = set("theme", Theme(value).toString)
def bg = get("bg", "light")
def bg(value: String) = set("bg", value)
private def get(name: String, default: String = ""): String =
ctx.req.session get name orElse {
ctx.me flatMap (_ setting name) map (_.toString)
} getOrElse default
private def set(name: String, value: String): Fu[Cookie] =
ctx.me ?? { m
UserRepo.saveSetting(m.id, name, value.toString)
} inject LilaCookie.session(name, value.toString)(ctx.req)
}
object Setting {
def apply(ctx: Context) = new Setting(ctx)
}

View File

@ -29,7 +29,7 @@ object ApplicationBuild extends Build {
message, notification, i18n, game, bookmark, search,
gameSearch, timeline, forum, forumSearch, team, teamSearch,
ai, analyse, mod, monitor, site, round, lobby, setup,
importer, tournament, relation, report)
importer, tournament, relation, report, pref)
lazy val moduleRefs = modules map projectToRef
lazy val moduleCPDeps = moduleRefs map { new sbt.ClasspathDependency(_, None) }
@ -123,6 +123,10 @@ object ApplicationBuild extends Build {
libraryDependencies ++= provided(play.api, reactivemongo, playReactivemongo)
)
lazy val pref = project("pref", Seq(common, db, user)).settings(
libraryDependencies ++= provided(play.api, reactivemongo, playReactivemongo)
)
lazy val message = project("message", Seq(common, db, user, hub, relation, security)).settings(
libraryDependencies ++= provided(
play.api, reactivemongo, playReactivemongo, spray.caching)

3
todo
View File

@ -73,5 +73,6 @@ no challenge when playing http://en.lichess.org/forum/lichess-feedback/defis#2
user option for auto-promotion (requested by NM :P) (http://en.lichess.org/@/Matetricks)
check filter games icon on windows
people page = trends by day, week, month. user achievments?
user options: tenth of seconds, sounds
user options: tenth of seconds, sounds, sound choice
user stats: http://en.lichess.org/forum/lichess-feedback/feature-request-extended-stats
forum improvements http://en.lichess.org/forum/lichess-feedback/suggestions-for-the-forum#1