From 227de5cb9cc9af18686433fa2933c0e73ac8bb12 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 15 Jun 2016 10:49:05 +0200 Subject: [PATCH] more chat rewrite WIP --- app/controllers/Round.scala | 12 +- app/controllers/Simul.scala | 7 +- app/controllers/Tournament.scala | 9 +- app/views/analyse/replay.scala.html | 8 +- app/views/chat/dom.scala.html | 4 +- app/views/chat/js.scala.html | 11 +- app/views/round/player.scala.html | 7 +- app/views/round/watcher.scala.html | 8 +- app/views/simul/show.scala.html | 8 +- app/views/study/layout.scala.html | 4 +- app/views/study/show.scala.html | 3 +- app/views/tournament/show.scala.html | 8 +- modules/chat/src/main/Chat.scala | 6 + public/javascripts/main.js | 167 +-------------------------- public/stylesheets/chat.css | 3 + public/stylesheets/common.css | 64 ---------- ui/chat/src/ctrl.js | 21 +++- ui/chat/src/discussion.js | 21 +++- 18 files changed, 85 insertions(+), 286 deletions(-) diff --git a/app/controllers/Round.scala b/app/controllers/Round.scala index 923c282af4..b939a11fbf 100644 --- a/app/controllers/Round.scala +++ b/app/controllers/Round.scala @@ -57,9 +57,10 @@ object Round extends LilaController with TheftPrevention { PreventTheft(pov) { myTour(pov.game.tournamentId, true) zip (pov.game.simulId ?? Env.simul.repo.find) zip + getPlayerChat(pov.game) zip Env.game.crosstableApi(pov.game) zip (pov.game.isSwitchable ?? otherPovs(pov.game)) flatMap { - case (((tour, simul), crosstable), playing) => + case ((((tour, simul), chatOption), crosstable), playing) => simul foreach Env.simul.api.onPlayerConnection(pov.game, ctx.me) Env.api.roundApi.player(pov, lila.api.Mobile.Api.currentVersion) map { data => Ok(html.round.player(pov, data, @@ -67,7 +68,7 @@ object Round extends LilaController with TheftPrevention { simul = simul, cross = crosstable, playing = playing, - prefs = ctx.isAuth option (Env.pref.forms miniPrefOf ctx.pref))) + chatOption = chatOption)) } } }.mon(_.http.response.player.website), @@ -189,8 +190,11 @@ object Round extends LilaController with TheftPrevention { } private[controllers] def getWatcherChat(game: GameModel)(implicit ctx: Context) = - ctx.me ?? { me => - Env.chat.api.userChat.findMine(s"${game.id}/w", me) map (_.some) + Env.chat.api.userChat.findMine(s"${game.id}/w", ctx.me) + + private[controllers] def getPlayerChat(game: GameModel)(implicit ctx: Context) = + game.hasChat ?? { + Env.chat.api.playerChat.find(game.id) map (_.some) } def playerText(fullId: String) = Open { implicit ctx => diff --git a/app/controllers/Simul.scala b/app/controllers/Simul.scala index a1c5f59ad2..3b9ae2b9e8 100644 --- a/app/controllers/Simul.scala +++ b/app/controllers/Simul.scala @@ -40,7 +40,7 @@ object Simul extends LilaController { _.fold(simulNotFound.fuccess) { sim => env.version(sim.id) zip env.jsonView(sim) zip - chatOf(sim) map { + Env.chat.api.userChat.findMine(sim.id, ctx.me) map { case ((version, data), chat) => html.simul.show(sim, version, data, chat) } } @@ -120,11 +120,6 @@ object Simul extends LilaController { } } - private def chatOf(sim: Sim)(implicit ctx: Context): Fu[Option[lila.chat.UserChat.Mine]] = - ctx.me ?? { me => - Env.chat.api.userChat.findMine(sim.id, me) map (_.some) - } - private def AsHost(simulId: Sim.ID)(f: Sim => Result)(implicit ctx: Context): Fu[Result] = env.repo.find(simulId) flatMap { case None => notFound diff --git a/app/controllers/Tournament.scala b/app/controllers/Tournament.scala index 718f4117b9..3ed05b5e50 100644 --- a/app/controllers/Tournament.scala +++ b/app/controllers/Tournament.scala @@ -53,7 +53,9 @@ object Tournament extends LilaController { negotiate( html = repo byId id flatMap { _.fold(tournamentNotFound.fuccess) { tour => - env.version(tour.id).zip(chatOf(tour)).flatMap { + env.version(tour.id).zip { + Env.chat.api.userChat.findMine(tour.id, ctx.me) + }.flatMap { case (version, chat) => env.jsonView(tour, page, ctx.userId, none, version.some) map { html.tournament.show(tour, _, chat) } @@ -177,9 +179,4 @@ object Tournament extends LilaController { env.socketHandler.join(id, uid, ctx.me) } } - - private def chatOf(tour: lila.tournament.Tournament)(implicit ctx: Context) = - ctx.me ?? { me => - Env.chat.api.userChat.findMine(tour.id, me) map (_.some) - } } diff --git a/app/views/analyse/replay.scala.html b/app/views/analyse/replay.scala.html index 040cb1db78..dc67e35264 100644 --- a/app/views/analyse/replay.scala.html +++ b/app/views/analyse/replay.scala.html @@ -1,4 +1,4 @@ -@(pov: Pov, data: play.api.libs.json.JsObject, initialFen: Option[String], pgn: String, analysis: Option[lila.analyse.Analysis], analysisInProgress: Option[lila.fishnet.Work.InProgress], simul: Option[lila.simul.Simul], cross: Option[lila.game.Crosstable], userTv: Option[User], myChat: Option[lila.chat.UserChat.Mine])(implicit ctx: Context) +@(pov: Pov, data: play.api.libs.json.JsObject, initialFen: Option[String], pgn: String, analysis: Option[lila.analyse.Analysis], analysisInProgress: Option[lila.fishnet.Work.InProgress], simul: Option[lila.simul.Simul], cross: Option[lila.game.Crosstable], userTv: Option[User], myChat: lila.chat.UserChat.Mine)(implicit ctx: Context) @import pov._ @@ -22,9 +22,7 @@ tablebaseEndpoint: "@tablebaseEndpoint" } }; } -@myChat.map { c => -@chat.js(c, name = trans.spectatorRoom.str(), withNote = true) -} +@chat.js(myChat.chat, name = trans.spectatorRoom.str(), timeout = myChat.timeout, withNote = true) } @atom = { @@ -53,7 +51,7 @@ tablebaseEndpoint: "@tablebaseEndpoint" @analyse.layout( title = title, side = views.html.game.side(pov, initialFen, none, simul = simul, userTv = userTv).some, -chat = chat.dom(myChat).some, +chat = chat.dom().some, underchat = underchat.some, moreCss = moreCss, moreJs = moreJs, diff --git a/app/views/chat/dom.scala.html b/app/views/chat/dom.scala.html index 6c6339fa7f..452d665c54 100644 --- a/app/views/chat/dom.scala.html +++ b/app/views/chat/dom.scala.html @@ -1,5 +1,3 @@ -@(c: Option[lila.chat.UserChat.Mine])(implicit ctx: Context) +@() -@if(c.isDefined) { -} diff --git a/app/views/chat/js.scala.html b/app/views/chat/js.scala.html index 8bb343e604..eac5c2c5b6 100644 --- a/app/views/chat/js.scala.html +++ b/app/views/chat/js.scala.html @@ -1,16 +1,17 @@ -@(c: lila.chat.UserChat.Mine, name: String, withNote: Boolean = false, writeable: Boolean = true)(implicit ctx: Context) +@(chat: lila.chat.AnyChat, name: String, timeout: Boolean, withNote: Boolean = false, writeable: Boolean = true)(implicit ctx: Context) @embedJs { lichess.makeChat('chat', { -lines: @Html(J.stringify(lila.chat.JsonView(c.chat))), +lines: @Html(J.stringify(lila.chat.JsonView(chat))), i18n: @jsI18n(withNote = withNote), -id: "@c.chat.id", +id: "@chat.id", name: "@name", userId: @Html(ctx.userId.fold("null")(id => s""""$id"""")), +loginRequired: @chat.loginRequired, writeable: @writeable, -noteId: @if(withNote) {"@c.chat.id.take(8)"} else {null}, +noteId: @if(withNote) {"@chat.id.take(8)"} else {null}, kobold: @ctx.troll, mod: @isGranted(_.MarkTroll), -timeout: @c.timeout, +timeout: @timeout, timeoutReasons: @if(isGranted(_.MarkTroll)) { @Html(J.stringify(lila.chat.JsonView.timeoutReasons)) } else { null } }); } diff --git a/app/views/round/player.scala.html b/app/views/round/player.scala.html index 4c45c94411..54caf38ca0 100644 --- a/app/views/round/player.scala.html +++ b/app/views/round/player.scala.html @@ -1,4 +1,4 @@ -@(pov: Pov, data: play.api.libs.json.JsObject, tour: Option[lila.tournament.MiniStanding], simul: Option[lila.simul.Simul], cross: Option[lila.game.Crosstable], playing: List[Pov], prefs: Option[Form[_]])(implicit ctx: Context) +@(pov: Pov, data: play.api.libs.json.JsObject, tour: Option[lila.tournament.MiniStanding], simul: Option[lila.simul.Simul], cross: Option[lila.game.Crosstable], playing: List[Pov], chatOption: Option[lila.chat.MixedChat])(implicit ctx: Context) @import pov._ @@ -15,6 +15,9 @@ userId: @jsUserId }); }); } +@chatOption.map { c => +@chat.js(c, name = trans.chatRoom.str(), timeout = false, withNote = true) +} } @atom = { @@ -24,7 +27,7 @@ userId: @jsUserId @round.layout( title = title, side = views.html.game.side(pov, (data\"game"\"initialFen").asOpt[String], tour, simul), -chat = game.tournamentId.isEmpty.option(leftabs(pov, prefs)), +chat = chatOption.isDefined.option(chat.dom()), underchat = views.html.game.watchers().some, moreJs = moreJs, openGraph = povOpenGraph(pov).some, diff --git a/app/views/round/watcher.scala.html b/app/views/round/watcher.scala.html index cc6eab68b3..35157eb7a3 100644 --- a/app/views/round/watcher.scala.html +++ b/app/views/round/watcher.scala.html @@ -1,4 +1,4 @@ -@(pov: Pov, data: play.api.libs.json.JsObject, tour: Option[lila.tournament.MiniStanding], simul: Option[lila.simul.Simul], cross: Option[lila.game.Crosstable], userTv: Option[User] = None, myChat: Option[lila.chat.UserChat.Mine])(implicit ctx: Context) +@(pov: Pov, data: play.api.libs.json.JsObject, tour: Option[lila.tournament.MiniStanding], simul: Option[lila.simul.Simul], cross: Option[lila.game.Crosstable], userTv: Option[User] = None, myChat: lila.chat.UserChat.Mine)(implicit ctx: Context) @title = @{ s"${gameVsText(pov.game, withRatings = true)} in ${pov.gameId}" } @@ -12,9 +12,7 @@ i18n: @jsI18n() }); }); } -@myChat.map { c => -@chat.js(c, name = trans.spectatorRoom.str(), withNote = true) -} +@chat.js(myChat.chat, name = trans.spectatorRoom.str(), timeout = myChat.timeout, withNote = true) } @atom = { @@ -24,7 +22,7 @@ i18n: @jsI18n() @round.layout( title = title, side = views.html.game.side(pov, (data\"game"\"initialFen").asOpt[String], tour, simul = simul, userTv = userTv), -chat = chat.dom(myChat).some, +chat = chat.dom().some, underchat = views.html.game.watchers().some, moreJs = moreJs, openGraph = povOpenGraph(pov).some, diff --git a/app/views/simul/show.scala.html b/app/views/simul/show.scala.html index 0ded0990da..0728fb9d97 100644 --- a/app/views/simul/show.scala.html +++ b/app/views/simul/show.scala.html @@ -1,4 +1,4 @@ -@(sim: lila.simul.Simul, socketVersion: Int, data: play.api.libs.json.JsObject, myChat: Option[lila.chat.UserChat.Mine])(implicit ctx: Context) +@(sim: lila.simul.Simul, socketVersion: Int, data: play.api.libs.json.JsObject, myChat: lila.chat.UserChat.Mine)(implicit ctx: Context) @underchat = {
@@ -16,16 +16,14 @@ socketVersion: @socketVersion, userId: @jsUserId }; } -@myChat.map { c => -@chat.js(c, name = trans.chatRoom.str()) -} +@chat.js(myChat.chat, name = trans.chatRoom.str(), timeout = myChat.timeout) } @simul.layout( title = sim.fullName, side = simul.side(sim).some, underchat = underchat.some, -chat = chat.dom(myChat).some, +chat = chat.dom().some, moreJs = moreJs, chessground = false) {
diff --git a/app/views/study/layout.scala.html b/app/views/study/layout.scala.html index 63dec6be30..a65f00d251 100644 --- a/app/views/study/layout.scala.html +++ b/app/views/study/layout.scala.html @@ -1,4 +1,4 @@ -@(title: String, side: Html, chat: Html, underchat: Html, moreJs: Html)(body: Html)(implicit ctx: Context) +@(title: String, side: Html, underchat: Html, moreJs: Html)(body: Html)(implicit ctx: Context) @moreCss = { @cssTag("analyse.css") @@ -8,7 +8,7 @@ @base.layout( title = title, side = side.some, -chat = chat.some, +chat = chat.dom().some, underchat = underchat.some, moreCss = moreCss, moreJs = moreJs, diff --git a/app/views/study/show.scala.html b/app/views/study/show.scala.html index ea9464ae40..4d0d3df34e 100644 --- a/app/views/study/show.scala.html +++ b/app/views/study/show.scala.html @@ -17,7 +17,7 @@ socketUrl: "@routes.Study.websocket(s.id, apiVersion)", socketVersion: @socketVersion }; } -@chat.js(myChat, name = trans.chatRoom.str(), writeable = ctx.userId.??(s.canChat)) +@chat.js(myChat.chat, name = trans.chatRoom.str(), timeout = myChat.timeout, writeable = ctx.userId.??(s.canChat)) } @side = { @@ -33,7 +33,6 @@ socketVersion: @socketVersion @study.layout( title = s.name, side = side, -chat = chat.dom(myChat.some), underchat = underchat, moreJs = moreJs) {
@miniBoardContent
diff --git a/app/views/tournament/show.scala.html b/app/views/tournament/show.scala.html index aae562ecdc..1dfb2e4879 100644 --- a/app/views/tournament/show.scala.html +++ b/app/views/tournament/show.scala.html @@ -1,4 +1,4 @@ -@(tour: Tournament, data: play.api.libs.json.JsObject, myChat: Option[lila.chat.UserChat.Mine])(implicit ctx: Context) +@(tour: Tournament, data: play.api.libs.json.JsObject, myChat: lila.chat.UserChat.Mine)(implicit ctx: Context) @underchat = {
@@ -16,15 +16,13 @@ i18n: @jsI18n(), userId: @jsUserId }; } -@myChat.map { c => -@chat.js(c, name = trans.chatRoom.str()) -} +@chat.js(myChat.chat, name = trans.chatRoom.str(), timeout = myChat.timeout) } @tournament.layout( title = s"${tour.fullName} #${tour.id}", side = tournament.side(tour).some, -chat = chat.dom(myChat).some, +chat = chat.dom().some, underchat = underchat.some, moreJs = moreJs, chessground = false, diff --git a/modules/chat/src/main/Chat.scala b/modules/chat/src/main/Chat.scala index 521445c92b..faa938e674 100644 --- a/modules/chat/src/main/Chat.scala +++ b/modules/chat/src/main/Chat.scala @@ -6,6 +6,8 @@ sealed trait AnyChat { def id: ChatId def lines: List[Line] + val loginRequired: Boolean + def forUser(u: Option[User]): AnyChat def isEmpty = lines.isEmpty @@ -21,6 +23,8 @@ case class UserChat( id: ChatId, lines: List[UserLine]) extends Chat[UserLine] { + val loginRequired = true + def forUser(u: Option[User]) = u.??(_.troll).fold(this, copy(lines = lines filterNot (_.troll))) @@ -40,6 +44,8 @@ case class MixedChat( id: ChatId, lines: List[Line]) extends Chat[Line] { + val loginRequired = false + def forUser(u: Option[User]) = u.??(_.troll).fold(this, copy(lines = lines filter { case l: UserLine => !l.troll diff --git a/public/javascripts/main.js b/public/javascripts/main.js index 8fa5aa9cfd..af564bed8b 100644 --- a/public/javascripts/main.js +++ b/public/javascripts/main.js @@ -180,9 +180,6 @@ lichess.notifyApp = (function() { following_leaves: function(name) { $('#friend_box').friends('leaves', name); }, - message: function(msg) { - $('#chat').chat("append", msg); - }, new_notification: function(e) { var notification = e.notification; @@ -1055,7 +1052,6 @@ lichess.notifyApp = (function() { } } }); - var $chat; cfg.element = element.querySelector('.round'); cfg.socketSend = lichess.socket.send; cfg.onChange = data.player.spectator ? $.noop : function(data) { @@ -1066,15 +1062,10 @@ lichess.notifyApp = (function() { else if (data.game.status.id >= 30) presets = [ 'gg/Good game', 'wp/Well played', 'ty/Thank you', 'gtg/I\'ve got to go', 'bye/Bye!' ]; - $chat.chat('setPresets', presets); + lichess.pubsub.emit('chat.presets', presets); }; round = LichessRound(cfg); $('.crosstable', element).prependTo($('.underboard .center', element)).show(); - $chat = $('#chat').chat({ - messages: data.chat, - initialNote: data.note, - gameId: data.game.id - }); var $watchers = $('#site_header div.watchers').watchers(); var $nowPlaying = $('#now_playing'); startTournamentClock(); @@ -1162,157 +1153,6 @@ lichess.notifyApp = (function() { } }); - lichess.widget("chat", { - _create: function() { - this.options = $.extend({ - messages: [], - writeable: true, - initialNote: '', - gameId: null, - presets: [], - presetCount: 0 - }, this.options); - var self = this; - var $parent = self.element.parent(); - self.$msgs = self.element.find('.messages'); - self.withMsgs = !!self.$msgs.length; - if (self.withMsgs) { - self.$msgs.on('click', 'a', function() { - $(this).attr('target', '_blank'); - }); - var $form = self.element.find('form'); - var $input = self.element.find('input.lichess_say'); - self.options.placeholder = $input.attr('placeholder'); - self.writeable(self.options.writeable); - - // send a message - $form.submit(function() { - var text = $.trim($input.val()); - if (!text) return false; - if (text.length > 140) { - alert('Max length: 140 chars. ' + text.length + ' chars used.'); - return false; - } - $input.val(''); - lichess.socket.send('talk', text); - return false; - }); - - self.element.find('a.send').click(function() { - $input.trigger('click'); - $form.submit(); - }); - - // toggle the chat - var $toggle = $parent.find('input.toggle_chat'); - $toggle.change(function() { - var enabled = $toggle.is(':checked'); - self.element.toggleClass('hidden', !enabled); - if (!enabled) lichess.storage.set('nochat', 1); - else lichess.storage.remove('nochat'); - }); - $toggle[0].checked = lichess.storage.get('nochat') != 1; - if (!$toggle[0].checked) { - self.element.addClass('hidden'); - } - if (self.options.messages.length > 0) self._appendMany(self.options.messages); - self.element.on('click', '.presets button', function() { - $input.val($(this).data('hint')); - $form.submit(); - if (++self.options.presetCount >= 2) self.element.find('.presets').remove(); - $input.focus(); - }); - self._renderPresets(); - } - - $panels = self.element.find('div.chat_panels > div'); - $menu = $parent.find('.chat_menu'); - $menu.on('click', 'a', function() { - var panel = $(this).data('panel'); - $(this).siblings('.active').removeClass('active').end().addClass('active'); - $panels.removeClass('active').filter('.' + panel).addClass('active'); - }).find('a[data-panel=preferences]').one('click', function() { - self.element.find('.preferences form').each(function() { - var $form = $(this); - $form.find('group.radio').removeClass('radio'); - $form.find('input').change(function() { - $.ajax({ - url: $form.attr('action'), - method: $form.attr('method'), - data: $form.serialize() - }); - }); - }); - }); - $menu.find('a:first').click(); - - $notes = self.element.find('.notes textarea'); - if (self.options.gameId && $notes.length) { - $notes.on('change keyup paste', $.fp.debounce(function() { - $.post('/' + self.options.gameId + '/note', { - text: $notes.val() - }); - }, 1000)); - $notes.val(self.options.initialNote || ''); - } - }, - writeable: function(v) { - this.options.writeable = v; - this.element.find('input.lichess_say') - .prop('disabled', !v) - .prop('placeholder', v ? this.options.placeholder : 'Invited members only'); - }, - append: function(msg) { - this._appendHtml(this._render(msg)); - }, - setPresets: function(presets) { - if (presets.join('|') === this.options.presets.join('|')) return; - this.options.presetCount = 0; - this.options.presets = presets; - this._renderPresets(); - }, - _renderPresets: function() { - var $e = this.element.find('.messages_container'); - $e.find('.presets').remove(); - if (!this.options.presets.length) return; - $e.append($('
').addClass('presets').html( - this.options.presets.map(function(p) { - var s = p.split('/'); - return ''; - }).join('') - )); - }, - _appendMany: function(objs) { - var self = this, - html = ""; - $.each(objs, function() { - html += self._render(this); - }); - self._appendHtml(html); - }, - _render: function(msg) { - var user, sys = false; - if (msg.c) { - user = '[' + msg.c + ']'; - } else if (msg.u == 'lichess') { - sys = true; - user = ''; - } else { - user = $.userLinkLimit(msg.u, 14); - } - return '
  • ' + user + $.urlToLink(msg.t) + '
  • '; - }, - _appendHtml: function(html) { - if (!html) return; - this.$msgs.each(function(i, el) { - var autoScroll = (el.scrollTop == 0 || (el.scrollTop > (el.scrollHeight - el.clientHeight - 50))); - $(el).append(html); - if (autoScroll) el.scrollTop = 999999; - }); - $('body').trigger('lichess.content_loaded'); - } - }); - lichess.widget("clock", { _create: function() { var self = this; @@ -1916,11 +1756,6 @@ lichess.notifyApp = (function() { function startAnalyse(element, cfg) { var data = cfg.data; - if (data.chat) $('#chat').chat({ - messages: data.chat, - initialNote: data.note, - gameId: data.game.id - }); var $watchers = $('#site_header div.watchers').watchers(); var analyse, $panels; lichess.socket = lichess.StrongSocket( diff --git a/public/stylesheets/chat.css b/public/stylesheets/chat.css index c4997f3086..98676295b1 100644 --- a/public/stylesheets/chat.css +++ b/public/stylesheets/chat.css @@ -3,6 +3,9 @@ div.mchat { display: flex; flex-flow: column nowrap; } +body.kid div.mchat { + display: none; +} div.mchat .chat_tabs { display: flex; } diff --git a/public/stylesheets/common.css b/public/stylesheets/common.css index 55662b54b2..1f6a00a1e2 100644 --- a/public/stylesheets/common.css +++ b/public/stylesheets/common.css @@ -670,69 +670,6 @@ div.side_box .padded { width: 196px!important; } } -div.chat_menu { - margin-left: -30px; - margin-top: 12px; - margin-bottom: -12px; - text-align: center; - white-space: nowrap; -} -body.kid div.chat_menu, -body.kid #chat { - display: none; -} -div.chat_menu > a { - background: #f0f0f0; - border: 1px solid #c0c0c0; - height: 20px; - padding: 3px 8px 0 8px; - margin: -1px 0 -1px -5px; - display: inline-block; -} -div.chat_menu > a.active { - background-color: #eee; - border-bottom: 1px solid #eee; -} -div.chat_panels { - height: 325px; -} -.is3d div.chat_panels { - height: 290px; -} -div.chat_panels > * { - display: none; -} -div.chat_panels textarea { - resize: none; - height: calc(100% + 10px); - width: calc(100% - 12px); - padding: 0.5em; - border: none; - background-color: transparent; -} -div.chat_panels div.active { - display: block; - height: calc(100% - 22px); -} -div.chat_panels .preferences { - padding: 8px; - -webkit-user-select: none; - -moz-user-select: none; - overflow-y: auto; -} -div.chat_panels .preferences form > div { - margin-bottom: 15px; -} -div.chat_panels .preferences label { - cursor: pointer; -} -div.chat_panels .preferences input { - vertical-align: middle; -} -div.chat_panels .preferences a.prefs { - display: block; - text-align: center; -} .notification .message_infos, .notification .game_infos, div.side_box .game_infos { @@ -1593,7 +1530,6 @@ table.slist thead { text-shadow: 0 1px 0 #FFF; color: #848484; } -#chat div.top, .undertable_top, .button, a.button, diff --git a/ui/chat/src/ctrl.js b/ui/chat/src/ctrl.js index 6d4b430ed9..4828c3a6f7 100644 --- a/ui/chat/src/ctrl.js +++ b/ui/chat/src/ctrl.js @@ -7,7 +7,9 @@ module.exports = function(opts) { var data = { id: opts.id, name: opts.name, - lines: opts.lines + lines: opts.lines, + userId: opts.userId, + loginRequired: opts.loginRequired }; var vm = { @@ -19,7 +21,8 @@ module.exports = function(opts) { placeholderKey: 'talkInChat', moderating: m.prop(null), tab: m.prop('discussion'), - loading: m.prop(false) + loading: m.prop(false), + presets: m.prop([]) }; var trans = lichess.trans(opts.i18n); @@ -28,12 +31,12 @@ module.exports = function(opts) { data.lines.forEach(function(l) { if (l.u === username) l.d = true; }); - if (username.toLowerCase() === opts.userId) vm.isTimeout(true); + if (username.toLowerCase() === data.userId) vm.isTimeout(true); m.redraw(); }; var onReinstate = function(userId) { - if (userId === opts.userId) { + if (userId === data.userId) { vm.isTimeout(false); m.redraw(); } @@ -50,7 +53,7 @@ module.exports = function(opts) { send: lichess.pubsub.emit('socket.send') }) : null; - var note = opts.noteId ? makeNote({ + var note = data.userId && opts.noteId ? makeNote({ id: opts.noteId, trans: trans }) : null; @@ -60,10 +63,18 @@ module.exports = function(opts) { m.redraw(); }; + var setPresets = function(p) { + if (p.toString() !== vm.presets().toString()) { + vm.presets(p); + m.redraw(); + } + }; + lichess.pubsub.on('socket.in.message', onMessage); lichess.pubsub.on('socket.in.chat_timeout', onTimeout); lichess.pubsub.on('socket.in.chat_reinstate', onReinstate); lichess.pubsub.on('chat.writeable', setWriteable); + lichess.pubsub.on('chat.presets', setPresets); return { data: data, diff --git a/ui/chat/src/discussion.js b/ui/chat/src/discussion.js index 498a5b23e8..ad5b2ef3fc 100644 --- a/ui/chat/src/discussion.js +++ b/ui/chat/src/discussion.js @@ -29,6 +29,10 @@ function selectLines(lines) { } function input(ctrl) { + if (ctrl.data.loginRequired && !ctrl.data.userId) return m('input.lichess_say', { + placeholder: 'Login to chat', + disabled: true + }); var placeholder; if (ctrl.vm.isTimeout()) placeholder = 'You have been timed out.'; else if (!ctrl.vm.writeable()) placeholder = 'Invited members only.'; @@ -50,6 +54,20 @@ function input(ctrl) { }) } +function presets(ctrl) { + var ps = ctrl.vm.presets(); + if (ps.length) return m('div.presets', {}, ps.map(function(p) { + var s = p.split('/'); + return m('button', { + class: 'button hint--top thin', + 'data-hint': s[1], + onclick: function() { + ctrl.post(s[1]); + } + }, s[0]); + })); +} + module.exports = { view: function(ctrl) { if (!ctrl.vm.enabled()) return null; @@ -68,7 +86,8 @@ module.exports = { }, selectLines(ctrl.data.lines).map(renderLine(ctrl)) ), - input(ctrl) + input(ctrl), + presets(ctrl) ]; } };