diff --git a/app/controllers/LilaController.scala b/app/controllers/LilaController.scala index e98e8912d5..3dbc077fc2 100644 --- a/app/controllers/LilaController.scala +++ b/app/controllers/LilaController.scala @@ -158,7 +158,7 @@ private[controllers] trait LilaController else Results.NotFound("resource not found").fuccess protected def notFoundReq(req: RequestHeader): Fu[SimpleResult] = - reqToCtx(req, lila.chat.LobbyChan.some) flatMap (x ⇒ notFound(x)) + reqToCtx(req) flatMap (x ⇒ notFound(x)) protected def isGranted(permission: Permission.type ⇒ Permission)(implicit ctx: Context): Boolean = isGranted(permission(Permission)) diff --git a/app/controllers/Lobby.scala b/app/controllers/Lobby.scala index 2bc77352b0..46caea9458 100644 --- a/app/controllers/Lobby.scala +++ b/app/controllers/Lobby.scala @@ -12,7 +12,7 @@ import views._ object Lobby extends LilaController { - def home = OpenWithChan(lila.chat.LobbyChan) { implicit ctx ⇒ + def home = Open { implicit ctx ⇒ ctx.me match { case Some(u) if u.artificial ⇒ fuccess { views.html.auth.artificialPassword(u, Env.security.forms.newPassword) diff --git a/app/controllers/Tournament.scala b/app/controllers/Tournament.scala index addd3041ca..3859e0f3b9 100644 --- a/app/controllers/Tournament.scala +++ b/app/controllers/Tournament.scala @@ -23,7 +23,7 @@ object Tournament extends LilaController { _.fold(tournamentNotFound(ctx).fuccess)(a ⇒ op(a) map { b ⇒ Redirect(b) }) } - val home = OpenWithChan(lila.chat.TournamentLobbyChan) { implicit ctx ⇒ + val home = Open { implicit ctx ⇒ tournaments zip UserRepo.allSortToints(10) map { case (((created, started), finished), leaderboard) ⇒ Ok(html.tournament.home(created, started, finished, leaderboard)) diff --git a/modules/chat/src/main/Api.scala b/modules/chat/src/main/Api.scala index 8e0739e41e..f8a11a0eec 100644 --- a/modules/chat/src/main/Api.scala +++ b/modules/chat/src/main/Api.scala @@ -20,7 +20,7 @@ private[chat] final class Api( def get(user: User): Fu[ChatHead] = prefApi getPref user map { pref ⇒ ChatHead( - chans = Chat.baseChans ::: pref.chat.chans.map(Chan.parse).flatten, + chans = LangChan(user.lang | "en") :: pref.chat.chans.map(Chan.parse).flatten, pageChanKey = none, activeChanKeys = pref.chat.activeChans, mainChanKey = pref.chat.mainChan) diff --git a/modules/chat/src/main/Chan.scala b/modules/chat/src/main/Chan.scala index eb2e824a24..23d657de0f 100644 --- a/modules/chat/src/main/Chan.scala +++ b/modules/chat/src/main/Chan.scala @@ -33,15 +33,16 @@ sealed abstract class AutoActiveChan(typ: String, i: String) extends IdChan(typ, val id = i } -object LichessChan extends StaticChan(Chan.typ.lichess, "Lichess") -object LobbyChan extends StaticChan(Chan.typ.lobby, "Lobby") object TvChan extends StaticChan(Chan.typ.tv, "TV") -object TournamentLobbyChan extends StaticChan(Chan.typ.tournamentLobby, "Tournament Lobby") case class GameWatcherChan(i: String) extends AutoActiveChan(Chan.typ.gameWatcher, i) case class GamePlayerChan(i: String) extends AutoActiveChan(Chan.typ.gamePlayer, i) case class TournamentChan(i: String) extends AutoActiveChan(Chan.typ.tournament, i) +case class LangChan(lang: String) extends IdChan(Chan.typ.lang, false) { + val id = lang +} + case class UserChan(u1: String, u2: String) extends IdChan("user", false) { val id = List(u1, u2).sorted mkString "-" def contains(userId: String) = u1 == userId || u2 == userId @@ -63,23 +64,19 @@ case class NamedChan(chan: Chan, name: String) { object Chan { object typ { - val lichess = "lichess" - val lobby = "lobby" + val lang = "lang" val tv = "tv" val gameWatcher = "gameWatcher" val gamePlayer = "gamePlayer" - val tournamentLobby = "tournamentLobby" val tournament = "tournament" val user = "user" } def apply(typ: String, idOption: Option[String]): Option[Chan] = typ match { - case Chan.typ.lichess ⇒ LichessChan.some - case Chan.typ.lobby ⇒ LobbyChan.some + case Chan.typ.lang ⇒ idOption map LangChan.apply case Chan.typ.tv ⇒ TvChan.some case Chan.typ.gameWatcher ⇒ idOption map GameWatcherChan case Chan.typ.gamePlayer ⇒ idOption map GamePlayerChan - case Chan.typ.tournamentLobby ⇒ TournamentLobbyChan.some case Chan.typ.tournament ⇒ idOption map TournamentChan case Chan.typ.user ⇒ idOption flatMap UserChan.apply case _ ⇒ none diff --git a/modules/chat/src/main/Chat.scala b/modules/chat/src/main/Chat.scala index b3852d5476..4ca3fbf767 100644 --- a/modules/chat/src/main/Chat.scala +++ b/modules/chat/src/main/Chat.scala @@ -35,7 +35,5 @@ case class Chat(head: ChatHead, namedChans: List[NamedChan], lines: List[Line]) object Chat { - val baseChans = List(LichessChan) - val systemUsername = "Lichess" } diff --git a/modules/chat/src/main/ChatActor.scala b/modules/chat/src/main/ChatActor.scala index 7ab009a8b8..d47e8b3c49 100644 --- a/modules/chat/src/main/ChatActor.scala +++ b/modules/chat/src/main/ChatActor.scala @@ -52,6 +52,25 @@ private[chat] final class ChatActor( case SetOpen(member, value) ⇒ prefApi.setPref(member.userId, (p: Pref) ⇒ p.updateChat(_.copy(on = value))) + case Join(member, chan) ⇒ { + (!chan.autoActive ?? prefApi.setPref(member.userId, (p: Pref) ⇒ + p.updateChat(_.withMainChan(chan.key.some).withActiveChan(chan.key, true)) + )) >>- { + member.setActiveChan(chan.key, true) + member.setMainChan(chan.key.some) + reloadChat(member) + } + } + + case Show(member, chan, value) ⇒ { + (!chan.autoActive ?? prefApi.setPref(member.userId, (p: Pref) ⇒ + p.updateChat(_.withActiveChan(chan.key, value)) + )) >>- { + member.setActiveChan(chan.key, value) + reloadChat(member) + } + } + case Query(member, toId) ⇒ UserRepo byId toId flatten s"Can't query non existing user $toId" foreach { to ⇒ relationApi.follows(to.id, member.userId) foreach { @@ -92,28 +111,9 @@ private[chat] final class ChatActor( member setBlocks blocks reloadChat(member) } - case "chat.set-active-chan" ⇒ withChan(data) { chan ⇒ - val value = data int "value" exists (1==) - val setMain = value && (data int "main" exists (1==)) - (!chan.autoActive) ?? prefApi.setPref(member.userId, (p: Pref) ⇒ p.updateChat(setMain.fold( - _.withActiveChan(chan.key, value).withMainChan(chan.key.some), - _.withActiveChan(chan.key, value) - ))) andThen { - case _ ⇒ { - member.setActiveChan(chan.key, value) - if (setMain) member.setMainChan(chan.key.some) - reloadChat(member) - } - } - } - case "chat.set-main" ⇒ withChanOption(data) { chan ⇒ - member.setMainChan(chan map (_.key)) - if (!chan.??(_.autoActive)) prefApi.setPref(member.userId, (p: Pref) ⇒ - p.updateChat(_.withMainChan(chan map (_.key))) - ) - } case "chat.tell" ⇒ data str "text" foreach { text ⇒ val chanOption = data str "chan" flatMap Chan.parse + println(text) if (text startsWith "/") commander ! Command(chanOption, member, text drop 1) else chanOption foreach { chan ⇒ api.write(chan.key, member.userId, text) foreach { _ foreach self.! } diff --git a/modules/chat/src/main/Commander.scala b/modules/chat/src/main/Commander.scala index e70c56cfac..f878b9ce6a 100644 --- a/modules/chat/src/main/Commander.scala +++ b/modules/chat/src/main/Commander.scala @@ -30,6 +30,16 @@ private[chat] final class Commander extends Actor { case "query" :: username :: _ ⇒ chat ! Query(member, username.toLowerCase) + case "join" :: chanName :: _ ⇒ Chan parse chanName foreach { chan ⇒ + chat ! Join(member, chan) + } + case "show" :: chanName :: _ ⇒ Chan parse chanName foreach { chan ⇒ + chat ! Show(member, chan, true) + } + case "hide" :: chanName :: _ ⇒ Chan parse chanName foreach { chan ⇒ + chat ! Show(member, chan, false) + } + case words ⇒ chanOption foreach { chan ⇒ replyTo(chan, member) { s"Command not found. Type /help for the list of available commands." @@ -48,6 +58,8 @@ For instance, try and send the message /help to see available commands. val helpLines = """ ___________________________ help ___________________________ /help display this message +/join enter a chat room. Ex: /join en +/query start a private chat with a friend /close close the chat """.lines.toList filter (_.nonEmpty) diff --git a/modules/chat/src/main/Namer.scala b/modules/chat/src/main/Namer.scala index 4bba091448..74a711f3a9 100644 --- a/modules/chat/src/main/Namer.scala +++ b/modules/chat/src/main/Namer.scala @@ -44,6 +44,10 @@ private[chat] final class Namer(getUsername: String ⇒ Fu[String]) { else if (user.id == u2) getUsername(u1) else fufail(s"${user.id} can't see $c") + case (LangChan(lang), _) ⇒ fuccess { + (lila.i18n.LangList name lang) | lang + } + case (c, _) ⇒ fuccess(c.toString) } diff --git a/modules/chat/src/main/actorApi.scala b/modules/chat/src/main/actorApi.scala index 72f05aec22..fbec174994 100644 --- a/modules/chat/src/main/actorApi.scala +++ b/modules/chat/src/main/actorApi.scala @@ -9,4 +9,7 @@ case class Tell(uid: String, line: Line) case class SetOpen(member: ChatMember, value: Boolean) case class Query(member: ChatMember, username: String) + +case class Join(member: ChatMember, chan: Chan) +case class Show(member: ChatMember, chan: Chan, value: Boolean) } diff --git a/project/Build.scala b/project/Build.scala index 028de5c88f..e9780cdc29 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -65,7 +65,7 @@ object ApplicationBuild extends Build { ) lazy val chat = project("chat", Seq( - common, db, hub, socket, user, security, pref, relation, game, tournament)).settings( + common, db, hub, socket, user, security, pref, relation, game, tournament, i18n)).settings( libraryDependencies ++= provided( play.api, RM, PRM) ) diff --git a/public/javascripts/big.js b/public/javascripts/big.js index 605a24ac6e..97293c995c 100644 --- a/public/javascripts/big.js +++ b/public/javascripts/big.js @@ -863,11 +863,11 @@ var storage = { self._tell(); return false; }); - self.$chans.on('click', '.name', function(e) { - self._setMain($(this).data('chan')); + self.$chans.on('click', '.name', function() { + self._join($(this).data('chan')); }); - self.$chans.on('click', 'input', function(e) { - self._setActive($(this).attr('name'), $(this).prop('checked')); + self.$chans.on('click', 'input', function() { + self._show($(this).attr('name'), $(this).prop('checked')); }); self.element.find('.help').click(function() { self._send('/help tutorial'); @@ -939,7 +939,7 @@ var storage = { }); }; if (!self.mainChan && text.indexOf('/help') === 0) { - self._setMain(_.keys(self.chans)[0]); + self._join(_.keys(self.chans)[0]); setTimeout(doSend, 777); } else doSend(); switch (text) { @@ -953,38 +953,13 @@ var storage = { break; } }, - _setActive: function(chan, value, setMain) { - var self = this; - if (!self._exists(chan)) return; - self._disablePlaceholder(); - setMain = setMain | false; - if (value) self.activeChans.push(chan); - else self.activeChans = _.without(self.activeChans, chan); - lichess.socket.send("chat.set-active-chan", { - chan: chan, - value: value ? 1 : 0, - main: setMain ? 1 : 0 - }); - if (setMain) self.mainChan = chan; - else if (self.mainChan == chan) self._setMain(null); - self._renderLines(); - self._renderChans(); + _show: function(chan, value) { + this._disablePlaceholder(); + this._send('/' + (value ? 'show' : 'hide') + ' ' + chan); }, - // chan can be null, then there is no main chan - _setMain: function(chan) { - var self = this; - self._disablePlaceholder(); - if (chan !== null && !self._isActive(chan)) { - self._setActive(chan, true, true); - } else { - self.mainChan = chan; - self._renderLines(); - self._renderChans(); - self._renderForm(); - lichess.socket.send("chat.set-main", { - chan: chan, - }); - } + _join: function(chan) { + this._disablePlaceholder(); + this._send('/join ' + chan); }, _chanIndex: function(key) { return _.keys(this.chans).indexOf(key);