From 370c5c4b8a6c26d9664ef0886eec36f97bb05257 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sat, 12 Oct 2024 21:38:19 +0000 Subject: [PATCH 01/54] Add game behavior preference to show or hide opponent rating --- modules/coreI18n/src/main/key.scala | 1 + modules/pref/src/main/ui/AccountPref.scala | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index a146ef5b1eb45..8d327912b7785 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -1092,6 +1092,7 @@ object I18nKey: val `sayGgWpAfterLosingOrDrawing`: I18nKey = "preferences:sayGgWpAfterLosingOrDrawing" val `yourPreferencesHaveBeenSaved`: I18nKey = "preferences:yourPreferencesHaveBeenSaved" val `scrollOnTheBoardToReplayMoves`: I18nKey = "preferences:scrollOnTheBoardToReplayMoves" + val `showOpponentRating`: I18nKey = "preferences:showOpponentRating" val `correspondenceEmailNotification`: I18nKey = "preferences:correspondenceEmailNotification" val `notifyStreamStart`: I18nKey = "preferences:notifyStreamStart" val `notifyInboxMsg`: I18nKey = "preferences:notifyInboxMsg" diff --git a/modules/pref/src/main/ui/AccountPref.scala b/modules/pref/src/main/ui/AccountPref.scala index f3519e4209df2..edcd3231f4e8c 100644 --- a/modules/pref/src/main/ui/AccountPref.scala +++ b/modules/pref/src/main/ui/AccountPref.scala @@ -186,6 +186,11 @@ final class AccountPref(helpers: Helpers, helper: PrefHelper, bits: AccountUi): trp.scrollOnTheBoardToReplayMoves(), radios(form("behavior.scrollMoves"), booleanChoices), "scrollOnTheBoardToReplayMoves" + ), + setting( + trp.showOpponentRating(), + radios(form("behavior.showRating"), booleanChoices), + "showOpponentRating" ) ), categFieldset(PrefCateg.Privacy, categ)( From 75e144aef0881ea7022f40c1cc512205fda6fcf3 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sat, 12 Oct 2024 21:38:51 +0000 Subject: [PATCH 02/54] Add basic translation for the show opponent rating pref --- translation/source/preferences.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/translation/source/preferences.xml b/translation/source/preferences.xml index 2ec3b7ddb337c..95ab1a4942268 100644 --- a/translation/source/preferences.xml +++ b/translation/source/preferences.xml @@ -53,6 +53,7 @@ Say "Good game, well played" upon defeat or draw Your preferences have been saved. Scroll on the board to replay moves + Show Opponent Rating Daily email listing your correspondence games Streamer goes live New inbox message From 0631267b77a8284dc72ffd5470681ada89c22493 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 13 Oct 2024 02:29:47 +0000 Subject: [PATCH 03/54] Handle hiding/showing opponent rating in round's userHtml view --- ui/bits/src/bits.account.ts | 1 + ui/round/src/view/user.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/bits/src/bits.account.ts b/ui/bits/src/bits.account.ts index fdfea85c721ee..d5cd0bd9b671a 100644 --- a/ui/bits/src/bits.account.ts +++ b/ui/bits/src/bits.account.ts @@ -15,6 +15,7 @@ site.load.then(() => { ['behavior', 'arrowSnap', 'arrow.snap', true], ['behavior', 'courtesy', 'courtesy', false], ['behavior', 'scrollMoves', 'scrollMoves', true], + ['behavior', 'showRating', 'showRating', true], ['notification', 'playBellSound', 'playBellSound', true], ]; diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 774ec751b5a3d..057413b5514d5 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -4,6 +4,7 @@ import { Player } from 'game'; import { Position } from '../interfaces'; import RoundController from '../ctrl'; import { ratingDiff, userLink } from 'common/userLink'; +import { storage } from 'common/storage'; export const aiName = (ctrl: RoundController, level: number): string => ctrl.trans('aiNameLevelAiLevel', 'Stockfish', level); @@ -17,6 +18,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi if (user) { const connecting = !player.onGame && ctrl.firstSeconds && user.online; + const showRating = user?.id !== d.opponent.user?.id || storage.boolean('showRating').getOrDefault(true) return h( `div.ruser-${position}.ruser.user-link`, { @@ -45,7 +47,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - !!rating && h('rating', rating + (player.provisional ? '?' : '')), + showRating && !!rating && h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && h('span', { From 64ce5d93e15d7e744adc0fb9158a46c0ff77b6dc Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 13 Oct 2024 19:51:37 +0000 Subject: [PATCH 04/54] Change the way I handled the new showRating pref to be more like keyboardMove or voiceMove pref --- modules/core/src/main/pref.scala | 2 ++ modules/pref/src/main/Pref.scala | 4 ++++ modules/pref/src/main/PrefForm.scala | 5 +++++ modules/pref/src/main/PrefHandlers.scala | 2 ++ modules/pref/src/main/PrefSingleChange.scala | 2 ++ modules/puzzle/src/main/JsonView.scala | 1 + modules/round/src/main/JsonView.scala | 1 + ui/bits/src/bits.account.ts | 1 - ui/round/src/interfaces.ts | 1 + ui/round/src/view/user.ts | 3 +-- 10 files changed, 19 insertions(+), 3 deletions(-) diff --git a/modules/core/src/main/pref.scala b/modules/core/src/main/pref.scala index c8ba49cdece9e..fa86e1f7b9307 100644 --- a/modules/core/src/main/pref.scala +++ b/modules/core/src/main/pref.scala @@ -8,6 +8,7 @@ trait Pref: val id: UserId val coords: Int val keyboardMove: Int + val showRating: Int val voice: Option[Int] val rookCastle: Int val animation: Int @@ -21,6 +22,7 @@ trait Pref: def hasKeyboardMove: Boolean def hasVoice: Boolean + def hasShowRating: Boolean def showRatings: Boolean def animationMillis: Int def animationMillisForSpeedPuzzles: Int diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index aa17bec4cc1c0..9fed0e42c1088 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -35,6 +35,7 @@ case class Pref( insightShare: Int, keyboardMove: Int, voice: Option[Int], + showRating: Int, zen: Int, ratings: Int, flairs: Boolean, @@ -100,6 +101,7 @@ case class Pref( def hasKeyboardMove = keyboardMove == KeyboardMove.YES def hasVoice = voice.has(Voice.YES) + def hasShowRating = showRating == ShowRating.YES def isUsingAltSocket = usingAltSocket.has(true) @@ -249,6 +251,7 @@ object Pref: object KeyboardMove extends BooleanPref object Voice extends BooleanPref + object ShowRating extends BooleanPref object RookCastle: val NO = 0 @@ -474,6 +477,7 @@ object Pref: insightShare = lila.core.pref.InsightShare.FRIENDS, keyboardMove = KeyboardMove.NO, voice = None, + showRating = ShowRating.YES, zen = Zen.NO, ratings = Ratings.YES, flairs = true, diff --git a/modules/pref/src/main/PrefForm.scala b/modules/pref/src/main/PrefForm.scala index 86614995e0bb8..35c1eec3304dd 100644 --- a/modules/pref/src/main/PrefForm.scala +++ b/modules/pref/src/main/PrefForm.scala @@ -40,6 +40,7 @@ object PrefForm: val zen = "zen" -> checkedNumber(Pref.Zen.choices) val voice = "voice" -> booleanNumber val keyboardMove = "keyboardMove" -> booleanNumber + val showRating = "showRating" -> booleanNumber val autoQueen = "autoQueen" -> checkedNumber(Pref.AutoQueen.choices) val premove = "premove" -> booleanNumber val takeback = "takeback" -> checkedNumber(Pref.Takeback.choices) @@ -84,6 +85,7 @@ object PrefForm: fields.confirmResign, fields.keyboardMove.map2(optional), fields.voice.map2(optional), + fields.showRating.map2(optional), "rookCastle" -> optional(booleanNumber) )(BehaviorData.apply)(unapply), "clock" -> mapping( @@ -124,6 +126,7 @@ object PrefForm: confirmResign: Int, keyboardMove: Option[Int], voice: Option[Int], + showRating: Option[Int], rookCastle: Option[Int] ) @@ -172,6 +175,7 @@ object PrefForm: captured = display.captured == 1, keyboardMove = behavior.keyboardMove | pref.keyboardMove, voice = if pref.voice.isEmpty && !behavior.voice.contains(1) then None else behavior.voice, + showRating = behavior.showRating | pref.showRating, zen = display.zen | pref.zen, ratings = ratings | pref.ratings, flairs = flairs | pref.flairs, @@ -205,6 +209,7 @@ object PrefForm: confirmResign = pref.confirmResign, keyboardMove = pref.keyboardMove.some, voice = pref.voice.getOrElse(0).some, + showRating = pref.showRating.some, rookCastle = pref.rookCastle.some ), clock = ClockData( diff --git a/modules/pref/src/main/PrefHandlers.scala b/modules/pref/src/main/PrefHandlers.scala index 41f70a7efdefa..f44f7e9a4d509 100644 --- a/modules/pref/src/main/PrefHandlers.scala +++ b/modules/pref/src/main/PrefHandlers.scala @@ -45,6 +45,7 @@ private object PrefHandlers: insightShare = r.getD("insightShare", Pref.default.insightShare), keyboardMove = r.getD("keyboardMove", Pref.default.keyboardMove), voice = r.getO("voice"), + showRating = r.getD("showRating", Pref.default.showRating), zen = r.getD("zen", Pref.default.zen), ratings = r.getD("ratings", Pref.default.ratings), flairs = r.getD("flairs", Pref.default.flairs), @@ -91,6 +92,7 @@ private object PrefHandlers: "confirmResign" -> o.confirmResign, "insightShare" -> o.insightShare, "keyboardMove" -> o.keyboardMove, + "showRating" -> o.showRating, "voice" -> o.voice, "zen" -> o.zen, "ratings" -> o.ratings, diff --git a/modules/pref/src/main/PrefSingleChange.scala b/modules/pref/src/main/PrefSingleChange.scala index d8870b8cb6125..f82a93ae830f3 100644 --- a/modules/pref/src/main/PrefSingleChange.scala +++ b/modules/pref/src/main/PrefSingleChange.scala @@ -37,6 +37,8 @@ object PrefSingleChange: _.copy(voice = v.some), changing(_.keyboardMove): v => _.copy(keyboardMove = v | Pref.KeyboardMove.NO), + changing(_.showRating): v => + _.copy(showRating = v | Pref.ShowRating.NO), changing(_.autoQueen): v => _.copy(autoQueen = v), changing(_.premove): v => diff --git a/modules/puzzle/src/main/JsonView.scala b/modules/puzzle/src/main/JsonView.scala index 4834973eecb8e..f7ae09d8b3456 100644 --- a/modules/puzzle/src/main/JsonView.scala +++ b/modules/puzzle/src/main/JsonView.scala @@ -82,6 +82,7 @@ final class JsonView( "coords" -> p.coords, "keyboardMove" -> p.keyboardMove, "voiceMove" -> p.voice, + "showRating" -> p.showRating, "rookCastle" -> p.rookCastle, "animation" -> Json.obj("duration" -> p.animationMillis), "destination" -> p.destination, diff --git a/modules/round/src/main/JsonView.scala b/modules/round/src/main/JsonView.scala index 52b17ca9d2dc7..04c28547a5877 100644 --- a/modules/round/src/main/JsonView.scala +++ b/modules/round/src/main/JsonView.scala @@ -116,6 +116,7 @@ final class JsonView( .add("confirmResign" -> (!flags.nvui && pref.confirmResign == Pref.ConfirmResign.YES)) .add("keyboardMove" -> (!flags.nvui && pref.hasKeyboardMove)) .add("voiceMove" -> (!flags.nvui && pref.hasVoice)) + .add("showRating" -> (!flags.nvui && pref.hasShowRating)) .add("rookCastle" -> (pref.rookCastle == Pref.RookCastle.YES)) .add("highlight" -> pref.highlight) .add("destination" -> pref.destination) diff --git a/ui/bits/src/bits.account.ts b/ui/bits/src/bits.account.ts index d5cd0bd9b671a..fdfea85c721ee 100644 --- a/ui/bits/src/bits.account.ts +++ b/ui/bits/src/bits.account.ts @@ -15,7 +15,6 @@ site.load.then(() => { ['behavior', 'arrowSnap', 'arrow.snap', true], ['behavior', 'courtesy', 'courtesy', false], ['behavior', 'scrollMoves', 'scrollMoves', true], - ['behavior', 'showRating', 'showRating', true], ['notification', 'playBellSound', 'playBellSound', true], ]; diff --git a/ui/round/src/interfaces.ts b/ui/round/src/interfaces.ts index 2ffee7304ff3e..ea195c1bfa3dc 100644 --- a/ui/round/src/interfaces.ts +++ b/ui/round/src/interfaces.ts @@ -188,6 +188,7 @@ export interface Pref { highlight: boolean; is3d: boolean; keyboardMove: boolean; + showRating: boolean; voiceMove: boolean; moveEvent: Prefs.MoveEvent; ratings: boolean; diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 057413b5514d5..3d85608a28cc1 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -4,7 +4,6 @@ import { Player } from 'game'; import { Position } from '../interfaces'; import RoundController from '../ctrl'; import { ratingDiff, userLink } from 'common/userLink'; -import { storage } from 'common/storage'; export const aiName = (ctrl: RoundController, level: number): string => ctrl.trans('aiNameLevelAiLevel', 'Stockfish', level); @@ -18,7 +17,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi if (user) { const connecting = !player.onGame && ctrl.firstSeconds && user.online; - const showRating = user?.id !== d.opponent.user?.id || storage.boolean('showRating').getOrDefault(true) + const showRating = user?.id !== d.opponent.user?.id || d.pref.showRating return h( `div.ruser-${position}.ruser.user-link`, { From 615a41f972882474527795df9a9c94ab13f28480 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 13 Oct 2024 20:06:52 +0000 Subject: [PATCH 05/54] Remove unnecessary occurence of showRating and enfore defaut value to true --- modules/pref/src/main/PrefSingleChange.scala | 2 +- modules/puzzle/src/main/JsonView.scala | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/pref/src/main/PrefSingleChange.scala b/modules/pref/src/main/PrefSingleChange.scala index f82a93ae830f3..09c39487ed1e3 100644 --- a/modules/pref/src/main/PrefSingleChange.scala +++ b/modules/pref/src/main/PrefSingleChange.scala @@ -38,7 +38,7 @@ object PrefSingleChange: changing(_.keyboardMove): v => _.copy(keyboardMove = v | Pref.KeyboardMove.NO), changing(_.showRating): v => - _.copy(showRating = v | Pref.ShowRating.NO), + _.copy(showRating = v | Pref.ShowRating.YES), changing(_.autoQueen): v => _.copy(autoQueen = v), changing(_.premove): v => diff --git a/modules/puzzle/src/main/JsonView.scala b/modules/puzzle/src/main/JsonView.scala index f7ae09d8b3456..4834973eecb8e 100644 --- a/modules/puzzle/src/main/JsonView.scala +++ b/modules/puzzle/src/main/JsonView.scala @@ -82,7 +82,6 @@ final class JsonView( "coords" -> p.coords, "keyboardMove" -> p.keyboardMove, "voiceMove" -> p.voice, - "showRating" -> p.showRating, "rookCastle" -> p.rookCastle, "animation" -> Json.obj("duration" -> p.animationMillis), "destination" -> p.destination, From 7a04f3ce38d1d92527cfe77e9f462f6d9e9b16c4 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 14 Oct 2024 00:53:48 +0000 Subject: [PATCH 06/54] Add the showRating pref to the JsonView --- modules/pref/src/main/JsonView.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/pref/src/main/JsonView.scala b/modules/pref/src/main/JsonView.scala index 0a7395bc8e800..abdf3ea6501b2 100644 --- a/modules/pref/src/main/JsonView.scala +++ b/modules/pref/src/main/JsonView.scala @@ -41,6 +41,7 @@ object JsonView: "insightShare" -> p.insightShare, "keyboardMove" -> p.keyboardMove, "voiceMove" -> p.hasVoice, + "showRating" -> p.showRating, "zen" -> p.zen, "ratings" -> p.ratings, "moveEvent" -> p.moveEvent, From 1c8e040b8603bc485852cad31785ff37b851dcc7 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 14 Oct 2024 22:24:12 +0000 Subject: [PATCH 07/54] Hide ratings in side and user mini while in game based on the new pref --- app/views/game/side.scala | 2 +- app/views/user/ui.scala | 6 +++++- modules/user/src/main/ui/UserShow.scala | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index bdba20efb64b0..5c75155d9c8b0 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -78,7 +78,7 @@ object side: game.players.mapList: p => frag( div(cls := s"player color-icon is ${p.color.name} text")( - playerLink(p, withOnline = false, withDiff = true, withBerserk = true) + playerLink(p, withOnline = false, withDiff = true, withBerserk = true, withRating = game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) || ctx.pref.hasShowRating) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { teamLink(_, withIcon = false)(cls := "team") diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 34a5c73a4b9dc..a435896b895c0 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -37,7 +37,11 @@ def mini( def userMarks = views.mod.user.userMarks(u.user, None) val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs - show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks) + val showRating= ctx.pref.hasShowRating || (playingGame match { + case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) + case None => true + }) + show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) def perfStatPage(data: PerfStatData, ratingChart: Option[SafeJsonStr])(using diff --git a/modules/user/src/main/ui/UserShow.scala b/modules/user/src/main/ui/UserShow.scala index 4c3d031fbcf98..43f3eef6e26d3 100644 --- a/modules/user/src/main/ui/UserShow.scala +++ b/modules/user/src/main/ui/UserShow.scala @@ -33,7 +33,8 @@ final class UserShow(helpers: Helpers, bits: UserBits): crosstable: UserId => Option[Frag], flag: Option[Flag], best8Perfs: List[PerfKey], - userMarks: => Frag + userMarks: => Frag, + showRating: Boolean = true )(using ctx: Context) = frag( div(cls := "upt__info")( @@ -55,7 +56,7 @@ final class UserShow(helpers: Helpers, bits: UserBits): if u.lame && ctx.isnt(u) && !Granter.opt(_.UserModView) then div(cls := "upt__info__warning")(trans.site.thisAccountViolatedTos()) else - ctx.pref.showRatings.option: + (ctx.pref.showRatings && showRating).option: div(cls := "upt__info__ratings")(best8Perfs.map(showPerfRating(u.perfs, _))) ), ctx.userId.map: myId => From fd3af47a1de50b9460db00db3b5ccb76d0f6a61d Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 15 Oct 2024 01:20:51 +0000 Subject: [PATCH 08/54] Hide the user's rating too when showRating pref is set to NO --- ui/round/src/view/user.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 3d85608a28cc1..49a0e5e28f535 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -17,7 +17,6 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi if (user) { const connecting = !player.onGame && ctrl.firstSeconds && user.online; - const showRating = user?.id !== d.opponent.user?.id || d.pref.showRating return h( `div.ruser-${position}.ruser.user-link`, { @@ -46,7 +45,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - showRating && !!rating && h('rating', rating + (player.provisional ? '?' : '')), + d.pref.showRating && !!rating && h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && h('span', { From e9387faa67e4acf8c9a51266b1cee3e655385ca7 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 15 Oct 2024 01:51:54 +0000 Subject: [PATCH 09/54] Handle showRating pref in the mini game ui --- modules/game/src/main/ui/GameUi.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 3662cb28c117a..2958fbab830bb 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -26,7 +26,7 @@ final class GameUi(helpers: Helpers): renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = ctx.pref.showRatings + showRatings = ctx.pref.showRatings && (!ctx.userId.exists(pov.game.userIds.has) || ctx.pref.hasShowRating || pov.game.finishedOrAborted) ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = From b94f204ebb44c72c80c07e9c4e1fba7b01fb1adb Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 15 Oct 2024 03:05:47 +0000 Subject: [PATCH 10/54] Reshow the hidden ratings after game ends --- ui/round/src/view/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 49a0e5e28f535..a00282d3af766 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -45,7 +45,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - d.pref.showRating && !!rating && h('rating', rating + (player.provisional ? '?' : '')), + (!ctrl.isPlaying() || d.pref.showRating) && !!rating && h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && h('span', { From 390d559961b37f52bbc076110dc0be5be6f59dd5 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 15 Oct 2024 19:44:43 +0000 Subject: [PATCH 11/54] Make ratings reapper in mini user popups after game ends --- app/controllers/User.scala | 3 ++- app/views/user/ui.scala | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index 1415ed4c01704..7c9ccf81faf60 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -178,9 +178,10 @@ final class User( ctx.isAuth.so(env.pref.api.followable(user.id)) ).flatMapN: (blocked, crosstable, followable) => val ping = env.socket.isOnline(user.id).so(env.socket.getLagRating(user.id)) + val isUserPlaying = ctx.userId.so(env.round.playing(_)) negotiate( html = (ctx.isnt(user)).so(currentlyPlaying(user.user)).flatMap { pov => - Ok.snip(views.user.mini(user, pov, blocked, followable, relation, ping, crosstable)) + Ok.snip(views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, isUserPlaying)) .map(_.withHeaders(CACHE_CONTROL -> "max-age=5")) }, json = diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index a435896b895c0..dfcc68a1a9ed4 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -18,7 +18,8 @@ def mini( followable: Boolean, relation: Option[lila.relation.Relation], ping: Option[Int], - ct: Option[lila.game.Crosstable] + ct: Option[lila.game.Crosstable], + isUserPlaying: Boolean )(using ctx: Context) = val rel = views.relation.mini(u.id, blocked, followable, relation) def crosstable(myId: UserId) = ct @@ -39,7 +40,7 @@ def mini( val perfs = u.perfs.best8Perfs val showRating= ctx.pref.hasShowRating || (playingGame match { case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) - case None => true + case None => !isUserPlaying }) show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) From 92da48189e125d9a42ab74f57529695cdcb93c99 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 15 Oct 2024 20:02:31 +0000 Subject: [PATCH 12/54] Rename pref and variables around it for clarity --- app/views/game/side.scala | 2 +- app/views/user/ui.scala | 2 +- modules/core/src/main/pref.scala | 4 ++-- modules/coreI18n/src/main/key.scala | 2 +- modules/game/src/main/ui/GameUi.scala | 2 +- modules/pref/src/main/JsonView.scala | 2 +- modules/pref/src/main/Pref.scala | 8 ++++---- modules/pref/src/main/PrefForm.scala | 10 +++++----- modules/pref/src/main/PrefHandlers.scala | 4 ++-- modules/pref/src/main/PrefSingleChange.scala | 4 ++-- modules/pref/src/main/ui/AccountPref.scala | 6 +++--- modules/round/src/main/JsonView.scala | 2 +- translation/source/preferences.xml | 2 +- ui/round/src/interfaces.ts | 2 +- ui/round/src/view/user.ts | 2 +- 15 files changed, 27 insertions(+), 27 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 5c75155d9c8b0..cd8d9eca2b23a 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -78,7 +78,7 @@ object side: game.players.mapList: p => frag( div(cls := s"player color-icon is ${p.color.name} text")( - playerLink(p, withOnline = false, withDiff = true, withBerserk = true, withRating = game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) || ctx.pref.hasShowRating) + playerLink(p, withOnline = false, withDiff = true, withBerserk = true, withRating = game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) || ctx.pref.hasShowRatingsInGame) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { teamLink(_, withIcon = false)(cls := "team") diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index dfcc68a1a9ed4..c42127a3b2ce2 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -38,7 +38,7 @@ def mini( def userMarks = views.mod.user.userMarks(u.user, None) val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs - val showRating= ctx.pref.hasShowRating || (playingGame match { + val showRating= ctx.pref.hasShowRatingsInGame || (playingGame match { case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) case None => !isUserPlaying }) diff --git a/modules/core/src/main/pref.scala b/modules/core/src/main/pref.scala index fa86e1f7b9307..185e7c36c4ae6 100644 --- a/modules/core/src/main/pref.scala +++ b/modules/core/src/main/pref.scala @@ -8,7 +8,7 @@ trait Pref: val id: UserId val coords: Int val keyboardMove: Int - val showRating: Int + val showRatingsInGame: Int val voice: Option[Int] val rookCastle: Int val animation: Int @@ -22,7 +22,7 @@ trait Pref: def hasKeyboardMove: Boolean def hasVoice: Boolean - def hasShowRating: Boolean + def hasShowRatingsInGame: Boolean def showRatings: Boolean def animationMillis: Int def animationMillisForSpeedPuzzles: Int diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index 8d327912b7785..04c81118e0e77 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -1092,7 +1092,7 @@ object I18nKey: val `sayGgWpAfterLosingOrDrawing`: I18nKey = "preferences:sayGgWpAfterLosingOrDrawing" val `yourPreferencesHaveBeenSaved`: I18nKey = "preferences:yourPreferencesHaveBeenSaved" val `scrollOnTheBoardToReplayMoves`: I18nKey = "preferences:scrollOnTheBoardToReplayMoves" - val `showOpponentRating`: I18nKey = "preferences:showOpponentRating" + val `showRatingsWhilePlaying`: I18nKey = "preferences:showRatingsWhilePlaying" val `correspondenceEmailNotification`: I18nKey = "preferences:correspondenceEmailNotification" val `notifyStreamStart`: I18nKey = "preferences:notifyStreamStart" val `notifyInboxMsg`: I18nKey = "preferences:notifyInboxMsg" diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 2958fbab830bb..698e736d12163 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -26,7 +26,7 @@ final class GameUi(helpers: Helpers): renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = ctx.pref.showRatings && (!ctx.userId.exists(pov.game.userIds.has) || ctx.pref.hasShowRating || pov.game.finishedOrAborted) + showRatings = ctx.pref.showRatings && (!ctx.userId.exists(pov.game.userIds.has) || ctx.pref.hasShowRatingsInGame || pov.game.finishedOrAborted) ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = diff --git a/modules/pref/src/main/JsonView.scala b/modules/pref/src/main/JsonView.scala index abdf3ea6501b2..443726e7ebdbb 100644 --- a/modules/pref/src/main/JsonView.scala +++ b/modules/pref/src/main/JsonView.scala @@ -41,7 +41,7 @@ object JsonView: "insightShare" -> p.insightShare, "keyboardMove" -> p.keyboardMove, "voiceMove" -> p.hasVoice, - "showRating" -> p.showRating, + "showRatingsInGame" -> p.showRatingsInGame, "zen" -> p.zen, "ratings" -> p.ratings, "moveEvent" -> p.moveEvent, diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 9fed0e42c1088..571406ae7b8d7 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -35,7 +35,7 @@ case class Pref( insightShare: Int, keyboardMove: Int, voice: Option[Int], - showRating: Int, + showRatingsInGame: Int, zen: Int, ratings: Int, flairs: Boolean, @@ -101,7 +101,7 @@ case class Pref( def hasKeyboardMove = keyboardMove == KeyboardMove.YES def hasVoice = voice.has(Voice.YES) - def hasShowRating = showRating == ShowRating.YES + def hasShowRatingsInGame = showRatingsInGame == ShowRatingsInGame.YES def isUsingAltSocket = usingAltSocket.has(true) @@ -251,7 +251,7 @@ object Pref: object KeyboardMove extends BooleanPref object Voice extends BooleanPref - object ShowRating extends BooleanPref + object ShowRatingsInGame extends BooleanPref object RookCastle: val NO = 0 @@ -477,7 +477,7 @@ object Pref: insightShare = lila.core.pref.InsightShare.FRIENDS, keyboardMove = KeyboardMove.NO, voice = None, - showRating = ShowRating.YES, + showRatingsInGame = ShowRatingsInGame.YES, zen = Zen.NO, ratings = Ratings.YES, flairs = true, diff --git a/modules/pref/src/main/PrefForm.scala b/modules/pref/src/main/PrefForm.scala index 35c1eec3304dd..14a2836ffd874 100644 --- a/modules/pref/src/main/PrefForm.scala +++ b/modules/pref/src/main/PrefForm.scala @@ -40,7 +40,7 @@ object PrefForm: val zen = "zen" -> checkedNumber(Pref.Zen.choices) val voice = "voice" -> booleanNumber val keyboardMove = "keyboardMove" -> booleanNumber - val showRating = "showRating" -> booleanNumber + val showRatingsInGame = "showRatingsInGame" -> booleanNumber val autoQueen = "autoQueen" -> checkedNumber(Pref.AutoQueen.choices) val premove = "premove" -> booleanNumber val takeback = "takeback" -> checkedNumber(Pref.Takeback.choices) @@ -85,7 +85,7 @@ object PrefForm: fields.confirmResign, fields.keyboardMove.map2(optional), fields.voice.map2(optional), - fields.showRating.map2(optional), + fields.showRatingsInGame.map2(optional), "rookCastle" -> optional(booleanNumber) )(BehaviorData.apply)(unapply), "clock" -> mapping( @@ -126,7 +126,7 @@ object PrefForm: confirmResign: Int, keyboardMove: Option[Int], voice: Option[Int], - showRating: Option[Int], + showRatingsInGame: Option[Int], rookCastle: Option[Int] ) @@ -175,7 +175,7 @@ object PrefForm: captured = display.captured == 1, keyboardMove = behavior.keyboardMove | pref.keyboardMove, voice = if pref.voice.isEmpty && !behavior.voice.contains(1) then None else behavior.voice, - showRating = behavior.showRating | pref.showRating, + showRatingsInGame = behavior.showRatingsInGame | pref.showRatingsInGame, zen = display.zen | pref.zen, ratings = ratings | pref.ratings, flairs = flairs | pref.flairs, @@ -209,7 +209,7 @@ object PrefForm: confirmResign = pref.confirmResign, keyboardMove = pref.keyboardMove.some, voice = pref.voice.getOrElse(0).some, - showRating = pref.showRating.some, + showRatingsInGame = pref.showRatingsInGame.some, rookCastle = pref.rookCastle.some ), clock = ClockData( diff --git a/modules/pref/src/main/PrefHandlers.scala b/modules/pref/src/main/PrefHandlers.scala index f44f7e9a4d509..41fb2a01aeef5 100644 --- a/modules/pref/src/main/PrefHandlers.scala +++ b/modules/pref/src/main/PrefHandlers.scala @@ -45,7 +45,7 @@ private object PrefHandlers: insightShare = r.getD("insightShare", Pref.default.insightShare), keyboardMove = r.getD("keyboardMove", Pref.default.keyboardMove), voice = r.getO("voice"), - showRating = r.getD("showRating", Pref.default.showRating), + showRatingsInGame = r.getD("showRatingsInGame", Pref.default.showRatingsInGame), zen = r.getD("zen", Pref.default.zen), ratings = r.getD("ratings", Pref.default.ratings), flairs = r.getD("flairs", Pref.default.flairs), @@ -92,7 +92,7 @@ private object PrefHandlers: "confirmResign" -> o.confirmResign, "insightShare" -> o.insightShare, "keyboardMove" -> o.keyboardMove, - "showRating" -> o.showRating, + "showRatingsInGame" -> o.showRatingsInGame, "voice" -> o.voice, "zen" -> o.zen, "ratings" -> o.ratings, diff --git a/modules/pref/src/main/PrefSingleChange.scala b/modules/pref/src/main/PrefSingleChange.scala index 09c39487ed1e3..b13a888900883 100644 --- a/modules/pref/src/main/PrefSingleChange.scala +++ b/modules/pref/src/main/PrefSingleChange.scala @@ -37,8 +37,8 @@ object PrefSingleChange: _.copy(voice = v.some), changing(_.keyboardMove): v => _.copy(keyboardMove = v | Pref.KeyboardMove.NO), - changing(_.showRating): v => - _.copy(showRating = v | Pref.ShowRating.YES), + changing(_.showRatingsInGame): v => + _.copy(showRatingsInGame = v | Pref.ShowRatingsInGame.YES), changing(_.autoQueen): v => _.copy(autoQueen = v), changing(_.premove): v => diff --git a/modules/pref/src/main/ui/AccountPref.scala b/modules/pref/src/main/ui/AccountPref.scala index edcd3231f4e8c..e657ed39a1950 100644 --- a/modules/pref/src/main/ui/AccountPref.scala +++ b/modules/pref/src/main/ui/AccountPref.scala @@ -188,9 +188,9 @@ final class AccountPref(helpers: Helpers, helper: PrefHelper, bits: AccountUi): "scrollOnTheBoardToReplayMoves" ), setting( - trp.showOpponentRating(), - radios(form("behavior.showRating"), booleanChoices), - "showOpponentRating" + trp.showRatingsWhilePlaying(), + radios(form("behavior.showRatingsInGame"), booleanChoices), + "showRatingsWhilePlaying" ) ), categFieldset(PrefCateg.Privacy, categ)( diff --git a/modules/round/src/main/JsonView.scala b/modules/round/src/main/JsonView.scala index 04c28547a5877..b172d5d50d4bc 100644 --- a/modules/round/src/main/JsonView.scala +++ b/modules/round/src/main/JsonView.scala @@ -116,7 +116,7 @@ final class JsonView( .add("confirmResign" -> (!flags.nvui && pref.confirmResign == Pref.ConfirmResign.YES)) .add("keyboardMove" -> (!flags.nvui && pref.hasKeyboardMove)) .add("voiceMove" -> (!flags.nvui && pref.hasVoice)) - .add("showRating" -> (!flags.nvui && pref.hasShowRating)) + .add("showRatingsInGame" -> (!flags.nvui && pref.hasShowRatingsInGame)) .add("rookCastle" -> (pref.rookCastle == Pref.RookCastle.YES)) .add("highlight" -> pref.highlight) .add("destination" -> pref.destination) diff --git a/translation/source/preferences.xml b/translation/source/preferences.xml index 95ab1a4942268..5aafd65f1d2d0 100644 --- a/translation/source/preferences.xml +++ b/translation/source/preferences.xml @@ -53,7 +53,7 @@ Say "Good game, well played" upon defeat or draw Your preferences have been saved. Scroll on the board to replay moves - Show Opponent Rating + Show ratings while playing your games Daily email listing your correspondence games Streamer goes live New inbox message diff --git a/ui/round/src/interfaces.ts b/ui/round/src/interfaces.ts index ea195c1bfa3dc..67970e826bdbb 100644 --- a/ui/round/src/interfaces.ts +++ b/ui/round/src/interfaces.ts @@ -188,7 +188,7 @@ export interface Pref { highlight: boolean; is3d: boolean; keyboardMove: boolean; - showRating: boolean; + showRatingsInGame: boolean; voiceMove: boolean; moveEvent: Prefs.MoveEvent; ratings: boolean; diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index a00282d3af766..094e18553e57a 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -45,7 +45,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - (!ctrl.isPlaying() || d.pref.showRating) && !!rating && h('rating', rating + (player.provisional ? '?' : '')), + (!ctrl.isPlaying() || d.pref.showRatingsInGame) && !!rating && h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && h('span', { From d8fdb7264da0190953a4a3f8d7a5a1ad063d72bc Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 15 Oct 2024 20:08:09 +0000 Subject: [PATCH 13/54] Format code --- app/controllers/User.scala | 7 +- app/views/game/side.scala | 10 ++- app/views/user/ui.scala | 6 +- modules/game/src/main/ui/GameUi.scala | 4 +- modules/pref/src/main/JsonView.scala | 18 ++--- modules/pref/src/main/Pref.scala | 12 ++-- modules/pref/src/main/PrefForm.scala | 34 +++++----- modules/pref/src/main/PrefHandlers.scala | 86 ++++++++++++------------ ui/round/src/view/user.ts | 4 +- 9 files changed, 97 insertions(+), 84 deletions(-) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index 7c9ccf81faf60..b57232ea961cd 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -177,12 +177,13 @@ final class User( ctx.userId.soFu(env.game.crosstableApi(user.id, _)), ctx.isAuth.so(env.pref.api.followable(user.id)) ).flatMapN: (blocked, crosstable, followable) => - val ping = env.socket.isOnline(user.id).so(env.socket.getLagRating(user.id)) + val ping = env.socket.isOnline(user.id).so(env.socket.getLagRating(user.id)) val isUserPlaying = ctx.userId.so(env.round.playing(_)) negotiate( html = (ctx.isnt(user)).so(currentlyPlaying(user.user)).flatMap { pov => - Ok.snip(views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, isUserPlaying)) - .map(_.withHeaders(CACHE_CONTROL -> "max-age=5")) + Ok.snip( + views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, isUserPlaying) + ).map(_.withHeaders(CACHE_CONTROL -> "max-age=5")) }, json = import lila.game.JsonView.given diff --git a/app/views/game/side.scala b/app/views/game/side.scala index cd8d9eca2b23a..7ddf2fdd95a29 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -78,7 +78,15 @@ object side: game.players.mapList: p => frag( div(cls := s"player color-icon is ${p.color.name} text")( - playerLink(p, withOnline = false, withDiff = true, withBerserk = true, withRating = game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) || ctx.pref.hasShowRatingsInGame) + playerLink( + p, + withOnline = false, + withDiff = true, + withBerserk = true, + withRating = game.finishedOrAborted || !ctx.userId.exists( + game.userIds.has + ) || ctx.pref.hasShowRatingsInGame + ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { teamLink(_, withIcon = false)(cls := "team") diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index c42127a3b2ce2..65575cac6199c 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -38,10 +38,10 @@ def mini( def userMarks = views.mod.user.userMarks(u.user, None) val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs - val showRating= ctx.pref.hasShowRatingsInGame || (playingGame match { + val showRating = ctx.pref.hasShowRatingsInGame || (playingGame match case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) - case None => !isUserPlaying - }) + case None => !isUserPlaying + ) show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 698e736d12163..1b2e4f35db2aa 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -26,7 +26,9 @@ final class GameUi(helpers: Helpers): renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = ctx.pref.showRatings && (!ctx.userId.exists(pov.game.userIds.has) || ctx.pref.hasShowRatingsInGame || pov.game.finishedOrAborted) + showRatings = ctx.pref.showRatings && (!ctx.userId.exists( + pov.game.userIds.has + ) || ctx.pref.hasShowRatingsInGame || pov.game.finishedOrAborted) ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = diff --git a/modules/pref/src/main/JsonView.scala b/modules/pref/src/main/JsonView.scala index 443726e7ebdbb..6a9b12233c433 100644 --- a/modules/pref/src/main/JsonView.scala +++ b/modules/pref/src/main/JsonView.scala @@ -37,13 +37,13 @@ object JsonView: if lichobileCompat then Pref.SubmitMove.lichobile.serverToApp(p.submitMove) else p.submitMove }, - "confirmResign" -> p.confirmResign, - "insightShare" -> p.insightShare, - "keyboardMove" -> p.keyboardMove, - "voiceMove" -> p.hasVoice, - "showRatingsInGame" -> p.showRatingsInGame, - "zen" -> p.zen, - "ratings" -> p.ratings, - "moveEvent" -> p.moveEvent, - "rookCastle" -> p.rookCastle + "confirmResign" -> p.confirmResign, + "insightShare" -> p.insightShare, + "keyboardMove" -> p.keyboardMove, + "voiceMove" -> p.hasVoice, + "showRatingsInGame" -> p.showRatingsInGame, + "zen" -> p.zen, + "ratings" -> p.ratings, + "moveEvent" -> p.moveEvent, + "rookCastle" -> p.rookCastle ) diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 571406ae7b8d7..e0177bc5a8a21 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -99,9 +99,9 @@ case class Pref( def agree = copy(agreement = Agreement.current) - def hasKeyboardMove = keyboardMove == KeyboardMove.YES - def hasVoice = voice.has(Voice.YES) - def hasShowRatingsInGame = showRatingsInGame == ShowRatingsInGame.YES + def hasKeyboardMove = keyboardMove == KeyboardMove.YES + def hasVoice = voice.has(Voice.YES) + def hasShowRatingsInGame = showRatingsInGame == ShowRatingsInGame.YES def isUsingAltSocket = usingAltSocket.has(true) @@ -249,9 +249,9 @@ object Pref: EVERYBODY -> "With everybody" ) - object KeyboardMove extends BooleanPref - object Voice extends BooleanPref - object ShowRatingsInGame extends BooleanPref + object KeyboardMove extends BooleanPref + object Voice extends BooleanPref + object ShowRatingsInGame extends BooleanPref object RookCastle: val NO = 0 diff --git a/modules/pref/src/main/PrefForm.scala b/modules/pref/src/main/PrefForm.scala index 14a2836ffd874..2a5fa64dc6c5a 100644 --- a/modules/pref/src/main/PrefForm.scala +++ b/modules/pref/src/main/PrefForm.scala @@ -36,23 +36,23 @@ object PrefForm: "URL must use https", url => url.isBlank || url.startsWith("https://") || url.startsWith("//") ) - val is3d = "is3d" -> tolerantBoolean - val zen = "zen" -> checkedNumber(Pref.Zen.choices) - val voice = "voice" -> booleanNumber - val keyboardMove = "keyboardMove" -> booleanNumber - val showRatingsInGame = "showRatingsInGame" -> booleanNumber - val autoQueen = "autoQueen" -> checkedNumber(Pref.AutoQueen.choices) - val premove = "premove" -> booleanNumber - val takeback = "takeback" -> checkedNumber(Pref.Takeback.choices) - val autoThreefold = "autoThreefold" -> checkedNumber(Pref.AutoThreefold.choices) - val submitMove = "submitMove" -> bitCheckedNumber(Pref.SubmitMove.choices) - val confirmResign = "confirmResign" -> checkedNumber(Pref.ConfirmResign.choices) - val moretime = "moretime" -> checkedNumber(Pref.Moretime.choices) - val clockSound = "clockSound" -> booleanNumber - val pieceNotation = "pieceNotation" -> booleanNumber - val ratings = "ratings" -> booleanNumber - val flairs = "flairs" -> boolean - val follow = "follow" -> booleanNumber + val is3d = "is3d" -> tolerantBoolean + val zen = "zen" -> checkedNumber(Pref.Zen.choices) + val voice = "voice" -> booleanNumber + val keyboardMove = "keyboardMove" -> booleanNumber + val showRatingsInGame = "showRatingsInGame" -> booleanNumber + val autoQueen = "autoQueen" -> checkedNumber(Pref.AutoQueen.choices) + val premove = "premove" -> booleanNumber + val takeback = "takeback" -> checkedNumber(Pref.Takeback.choices) + val autoThreefold = "autoThreefold" -> checkedNumber(Pref.AutoThreefold.choices) + val submitMove = "submitMove" -> bitCheckedNumber(Pref.SubmitMove.choices) + val confirmResign = "confirmResign" -> checkedNumber(Pref.ConfirmResign.choices) + val moretime = "moretime" -> checkedNumber(Pref.Moretime.choices) + val clockSound = "clockSound" -> booleanNumber + val pieceNotation = "pieceNotation" -> booleanNumber + val ratings = "ratings" -> booleanNumber + val flairs = "flairs" -> boolean + val follow = "follow" -> booleanNumber object board: val brightness = "boardBrightness" -> number(0, 150) val opacity = "boardOpacity" -> number(0, 100) diff --git a/modules/pref/src/main/PrefHandlers.scala b/modules/pref/src/main/PrefHandlers.scala index 41fb2a01aeef5..e8c98d9d2d9f0 100644 --- a/modules/pref/src/main/PrefHandlers.scala +++ b/modules/pref/src/main/PrefHandlers.scala @@ -61,48 +61,48 @@ private object PrefHandlers: def writes(w: BSON.Writer, o: Pref) = $doc( - "_id" -> o.id, - "bg" -> o.bg, - "bgImg" -> o.bgImg, - "is3d" -> o.is3d, - "theme" -> o.theme, - "pieceSet" -> o.pieceSet, - "theme3d" -> o.theme3d, - "pieceSet3d" -> o.pieceSet3d, - "soundSet" -> SoundSet.name2key(o.soundSet), - "autoQueen" -> o.autoQueen, - "autoThreefold" -> o.autoThreefold, - "takeback" -> o.takeback, - "moretime" -> o.moretime, - "clockTenths" -> o.clockTenths, - "clockBar" -> o.clockBar, - "clockSound" -> o.clockSound, - "premove" -> o.premove, - "animation" -> o.animation, - "captured" -> o.captured, - "follow" -> o.follow, - "highlight" -> o.highlight, - "destination" -> o.destination, - "coords" -> o.coords, - "replay" -> o.replay, - "challenge" -> o.challenge, - "message" -> o.message, - "studyInvite" -> o.studyInvite, - "submitMove" -> o.submitMove, - "confirmResign" -> o.confirmResign, - "insightShare" -> o.insightShare, - "keyboardMove" -> o.keyboardMove, + "_id" -> o.id, + "bg" -> o.bg, + "bgImg" -> o.bgImg, + "is3d" -> o.is3d, + "theme" -> o.theme, + "pieceSet" -> o.pieceSet, + "theme3d" -> o.theme3d, + "pieceSet3d" -> o.pieceSet3d, + "soundSet" -> SoundSet.name2key(o.soundSet), + "autoQueen" -> o.autoQueen, + "autoThreefold" -> o.autoThreefold, + "takeback" -> o.takeback, + "moretime" -> o.moretime, + "clockTenths" -> o.clockTenths, + "clockBar" -> o.clockBar, + "clockSound" -> o.clockSound, + "premove" -> o.premove, + "animation" -> o.animation, + "captured" -> o.captured, + "follow" -> o.follow, + "highlight" -> o.highlight, + "destination" -> o.destination, + "coords" -> o.coords, + "replay" -> o.replay, + "challenge" -> o.challenge, + "message" -> o.message, + "studyInvite" -> o.studyInvite, + "submitMove" -> o.submitMove, + "confirmResign" -> o.confirmResign, + "insightShare" -> o.insightShare, + "keyboardMove" -> o.keyboardMove, "showRatingsInGame" -> o.showRatingsInGame, - "voice" -> o.voice, - "zen" -> o.zen, - "ratings" -> o.ratings, - "flairs" -> o.flairs, - "rookCastle" -> o.rookCastle, - "moveEvent" -> o.moveEvent, - "pieceNotation" -> o.pieceNotation, - "resizeHandle" -> o.resizeHandle, - "agreement" -> o.agreement, - "usingAltSocket" -> o.usingAltSocket, - "board" -> o.board, - "tags" -> o.tags + "voice" -> o.voice, + "zen" -> o.zen, + "ratings" -> o.ratings, + "flairs" -> o.flairs, + "rookCastle" -> o.rookCastle, + "moveEvent" -> o.moveEvent, + "pieceNotation" -> o.pieceNotation, + "resizeHandle" -> o.resizeHandle, + "agreement" -> o.agreement, + "usingAltSocket" -> o.usingAltSocket, + "board" -> o.board, + "tags" -> o.tags ) diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 094e18553e57a..d971b56934d20 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -45,7 +45,9 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - (!ctrl.isPlaying() || d.pref.showRatingsInGame) && !!rating && h('rating', rating + (player.provisional ? '?' : '')), + (!ctrl.isPlaying() || d.pref.showRatingsInGame) && + !!rating && + h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && h('span', { From d1cc05b5df30ea5b76bbe6b4a520a0cfd2df54b5 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 20 Oct 2024 04:01:40 +0000 Subject: [PATCH 14/54] Add in-game only option in existing ratings pref instead of a new pref --- modules/game/src/main/ui/GameUi.scala | 4 ++-- modules/pref/src/main/JsonView.scala | 1 - modules/pref/src/main/Pref.scala | 18 ++++++++++++------ modules/pref/src/main/PrefForm.scala | 7 +------ modules/pref/src/main/PrefHandlers.scala | 2 -- modules/pref/src/main/PrefSingleChange.scala | 2 -- modules/pref/src/main/ui/AccountPref.scala | 7 +------ modules/pref/src/main/ui/PrefHelper.scala | 7 +++++++ 8 files changed, 23 insertions(+), 25 deletions(-) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 1b2e4f35db2aa..a42a770c0dca8 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -26,9 +26,9 @@ final class GameUi(helpers: Helpers): renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = ctx.pref.showRatings && (!ctx.userId.exists( + showRatings = ctx.pref.showRatings || (ctx.pref.hasShowRatingsInGame && (!ctx.userId.exists( pov.game.userIds.has - ) || ctx.pref.hasShowRatingsInGame || pov.game.finishedOrAborted) + ) || pov.game.finishedOrAborted)) ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = diff --git a/modules/pref/src/main/JsonView.scala b/modules/pref/src/main/JsonView.scala index 6a9b12233c433..74cb8f8026b2f 100644 --- a/modules/pref/src/main/JsonView.scala +++ b/modules/pref/src/main/JsonView.scala @@ -41,7 +41,6 @@ object JsonView: "insightShare" -> p.insightShare, "keyboardMove" -> p.keyboardMove, "voiceMove" -> p.hasVoice, - "showRatingsInGame" -> p.showRatingsInGame, "zen" -> p.zen, "ratings" -> p.ratings, "moveEvent" -> p.moveEvent, diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index e0177bc5a8a21..a8c1047867ed1 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -35,7 +35,6 @@ case class Pref( insightShare: Int, keyboardMove: Int, voice: Option[Int], - showRatingsInGame: Int, zen: Int, ratings: Int, flairs: Boolean, @@ -93,7 +92,8 @@ case class Pref( def isZen = zen == Zen.YES def isZenAuto = zen == Zen.GAME_AUTO - val showRatings = ratings == Ratings.YES + def showRatings = ratings == Ratings.YES // was val before + def hasShowRatingsInGame = ratings == Ratings.GAME_ONLY def is2d = !is3d @@ -101,7 +101,6 @@ case class Pref( def hasKeyboardMove = keyboardMove == KeyboardMove.YES def hasVoice = voice.has(Voice.YES) - def hasShowRatingsInGame = showRatingsInGame == ShowRatingsInGame.YES def isUsingAltSocket = usingAltSocket.has(true) @@ -251,7 +250,6 @@ object Pref: object KeyboardMove extends BooleanPref object Voice extends BooleanPref - object ShowRatingsInGame extends BooleanPref object RookCastle: val NO = 0 @@ -428,7 +426,16 @@ object Pref: GAME_AUTO -> "In-game only" ) - object Ratings extends BooleanPref + object Ratings: + val NO = 0 + val YES = 1 + val GAME_ONLY = 2 + + val choices = Seq( + NO -> "No", + YES -> "Yes", + GAME_ONLY -> "In-game only" + ) val darkByDefaultSince = instantOf(2021, 11, 7, 8, 0) val systemByDefaultSince = instantOf(2022, 12, 23, 8, 0) @@ -477,7 +484,6 @@ object Pref: insightShare = lila.core.pref.InsightShare.FRIENDS, keyboardMove = KeyboardMove.NO, voice = None, - showRatingsInGame = ShowRatingsInGame.YES, zen = Zen.NO, ratings = Ratings.YES, flairs = true, diff --git a/modules/pref/src/main/PrefForm.scala b/modules/pref/src/main/PrefForm.scala index 2a5fa64dc6c5a..727734efb5381 100644 --- a/modules/pref/src/main/PrefForm.scala +++ b/modules/pref/src/main/PrefForm.scala @@ -40,7 +40,6 @@ object PrefForm: val zen = "zen" -> checkedNumber(Pref.Zen.choices) val voice = "voice" -> booleanNumber val keyboardMove = "keyboardMove" -> booleanNumber - val showRatingsInGame = "showRatingsInGame" -> booleanNumber val autoQueen = "autoQueen" -> checkedNumber(Pref.AutoQueen.choices) val premove = "premove" -> booleanNumber val takeback = "takeback" -> checkedNumber(Pref.Takeback.choices) @@ -50,7 +49,7 @@ object PrefForm: val moretime = "moretime" -> checkedNumber(Pref.Moretime.choices) val clockSound = "clockSound" -> booleanNumber val pieceNotation = "pieceNotation" -> booleanNumber - val ratings = "ratings" -> booleanNumber + val ratings = "ratings" -> checkedNumber(Pref.Ratings.choices) val flairs = "flairs" -> boolean val follow = "follow" -> booleanNumber object board: @@ -85,7 +84,6 @@ object PrefForm: fields.confirmResign, fields.keyboardMove.map2(optional), fields.voice.map2(optional), - fields.showRatingsInGame.map2(optional), "rookCastle" -> optional(booleanNumber) )(BehaviorData.apply)(unapply), "clock" -> mapping( @@ -126,7 +124,6 @@ object PrefForm: confirmResign: Int, keyboardMove: Option[Int], voice: Option[Int], - showRatingsInGame: Option[Int], rookCastle: Option[Int] ) @@ -175,7 +172,6 @@ object PrefForm: captured = display.captured == 1, keyboardMove = behavior.keyboardMove | pref.keyboardMove, voice = if pref.voice.isEmpty && !behavior.voice.contains(1) then None else behavior.voice, - showRatingsInGame = behavior.showRatingsInGame | pref.showRatingsInGame, zen = display.zen | pref.zen, ratings = ratings | pref.ratings, flairs = flairs | pref.flairs, @@ -209,7 +205,6 @@ object PrefForm: confirmResign = pref.confirmResign, keyboardMove = pref.keyboardMove.some, voice = pref.voice.getOrElse(0).some, - showRatingsInGame = pref.showRatingsInGame.some, rookCastle = pref.rookCastle.some ), clock = ClockData( diff --git a/modules/pref/src/main/PrefHandlers.scala b/modules/pref/src/main/PrefHandlers.scala index e8c98d9d2d9f0..c8bf8f46a6629 100644 --- a/modules/pref/src/main/PrefHandlers.scala +++ b/modules/pref/src/main/PrefHandlers.scala @@ -45,7 +45,6 @@ private object PrefHandlers: insightShare = r.getD("insightShare", Pref.default.insightShare), keyboardMove = r.getD("keyboardMove", Pref.default.keyboardMove), voice = r.getO("voice"), - showRatingsInGame = r.getD("showRatingsInGame", Pref.default.showRatingsInGame), zen = r.getD("zen", Pref.default.zen), ratings = r.getD("ratings", Pref.default.ratings), flairs = r.getD("flairs", Pref.default.flairs), @@ -92,7 +91,6 @@ private object PrefHandlers: "confirmResign" -> o.confirmResign, "insightShare" -> o.insightShare, "keyboardMove" -> o.keyboardMove, - "showRatingsInGame" -> o.showRatingsInGame, "voice" -> o.voice, "zen" -> o.zen, "ratings" -> o.ratings, diff --git a/modules/pref/src/main/PrefSingleChange.scala b/modules/pref/src/main/PrefSingleChange.scala index b13a888900883..d8870b8cb6125 100644 --- a/modules/pref/src/main/PrefSingleChange.scala +++ b/modules/pref/src/main/PrefSingleChange.scala @@ -37,8 +37,6 @@ object PrefSingleChange: _.copy(voice = v.some), changing(_.keyboardMove): v => _.copy(keyboardMove = v | Pref.KeyboardMove.NO), - changing(_.showRatingsInGame): v => - _.copy(showRatingsInGame = v | Pref.ShowRatingsInGame.YES), changing(_.autoQueen): v => _.copy(autoQueen = v), changing(_.premove): v => diff --git a/modules/pref/src/main/ui/AccountPref.scala b/modules/pref/src/main/ui/AccountPref.scala index e657ed39a1950..f731633254f9a 100644 --- a/modules/pref/src/main/ui/AccountPref.scala +++ b/modules/pref/src/main/ui/AccountPref.scala @@ -77,7 +77,7 @@ final class AccountPref(helpers: Helpers, helper: PrefHelper, bits: AccountUi): setting( trp.showPlayerRatings(), frag( - radios(form("ratings"), booleanChoices), + radios(form("ratings"), translatedRatingsChoices), div(cls := "help text shy", dataIcon := Icon.InfoCircle)(trp.explainShowPlayerRatings()) ), "showRatings" @@ -186,11 +186,6 @@ final class AccountPref(helpers: Helpers, helper: PrefHelper, bits: AccountUi): trp.scrollOnTheBoardToReplayMoves(), radios(form("behavior.scrollMoves"), booleanChoices), "scrollOnTheBoardToReplayMoves" - ), - setting( - trp.showRatingsWhilePlaying(), - radios(form("behavior.showRatingsInGame"), booleanChoices), - "showRatingsWhilePlaying" ) ), categFieldset(PrefCateg.Privacy, categ)( diff --git a/modules/pref/src/main/ui/PrefHelper.scala b/modules/pref/src/main/ui/PrefHelper.scala index 062bdc168411a..ae7bc657ce44d 100644 --- a/modules/pref/src/main/ui/PrefHelper.scala +++ b/modules/pref/src/main/ui/PrefHelper.scala @@ -20,6 +20,13 @@ trait PrefHelper: (Pref.Zen.GAME_AUTO, trans.preferences.inGameOnly.txt()) ) + def translatedRatingsChoices(using Translate) = + List( + (Pref.Ratings.NO, trans.site.no.txt()), + (Pref.Ratings.YES, trans.site.yes.txt()), + (Pref.Ratings.GAME_ONLY, trans.preferences.inGameOnly.txt()) + ) + def translatedBoardCoordinateChoices(using Translate) = List( (Pref.Coords.NONE, trans.site.no.txt()), From ca3a63169c73ecbebd897977e3bcb2c95ea1fafc Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 20 Oct 2024 21:56:41 +0000 Subject: [PATCH 15/54] Fix logic to work with the changed rating pref --- app/views/game/side.scala | 4 +--- app/views/user/ui.scala | 4 ++-- modules/core/src/main/pref.scala | 1 - modules/game/src/main/ui/GameUi.scala | 4 +--- modules/pref/src/main/Pref.scala | 2 +- ui/round/src/view/user.ts | 4 ++-- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 7ddf2fdd95a29..29776d376c4fe 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -83,9 +83,7 @@ object side: withOnline = false, withDiff = true, withBerserk = true, - withRating = game.finishedOrAborted || !ctx.userId.exists( - game.userIds.has - ) || ctx.pref.hasShowRatingsInGame + withRating = if (ctx.pref.hasShowRatingsInGame) game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) else true ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 65575cac6199c..abe3d0ba59bd7 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -38,10 +38,10 @@ def mini( def userMarks = views.mod.user.userMarks(u.user, None) val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs - val showRating = ctx.pref.hasShowRatingsInGame || (playingGame match + val showRating = if (ctx.pref.hasShowRatingsInGame) (playingGame match case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) case None => !isUserPlaying - ) + ) else true show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) diff --git a/modules/core/src/main/pref.scala b/modules/core/src/main/pref.scala index 185e7c36c4ae6..04fac8e114d9d 100644 --- a/modules/core/src/main/pref.scala +++ b/modules/core/src/main/pref.scala @@ -8,7 +8,6 @@ trait Pref: val id: UserId val coords: Int val keyboardMove: Int - val showRatingsInGame: Int val voice: Option[Int] val rookCastle: Int val animation: Int diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index a42a770c0dca8..7e1bbfa9ffe05 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -26,9 +26,7 @@ final class GameUi(helpers: Helpers): renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = ctx.pref.showRatings || (ctx.pref.hasShowRatingsInGame && (!ctx.userId.exists( - pov.game.userIds.has - ) || pov.game.finishedOrAborted)) + showRatings = if (ctx.pref.hasShowRatingsInGame) pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) else ctx.pref.showRatings ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index a8c1047867ed1..4ba4b4d7567be 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -92,7 +92,7 @@ case class Pref( def isZen = zen == Zen.YES def isZenAuto = zen == Zen.GAME_AUTO - def showRatings = ratings == Ratings.YES // was val before + def showRatings = ratings != Ratings.NO // was val before def hasShowRatingsInGame = ratings == Ratings.GAME_ONLY def is2d = !is3d diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index d971b56934d20..10febb9366eb5 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -13,6 +13,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi user = player.user, perf = (user?.perfs || {})[d.game.perf], rating = player.rating || perf?.rating, + showRating = d.pref.showRatingsInGame ? !ctrl.isPlaying() : !!rating , signal = user?.id === d.opponent.user?.id ? d.opponentSignal : undefined; if (user) { @@ -45,8 +46,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - (!ctrl.isPlaying() || d.pref.showRatingsInGame) && - !!rating && + showRating && h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && From 77e79c8dc26767699e5195082dafde8932d76203 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 22 Oct 2024 17:39:27 +0000 Subject: [PATCH 16/54] Remove placeholder space from user popup without rating --- app/views/base/page.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/base/page.scala b/app/views/base/page.scala index 27c95a227b23c..813be2e0e64cc 100644 --- a/app/views/base/page.scala +++ b/app/views/base/page.scala @@ -103,7 +103,7 @@ object page: "kid" -> ctx.kid.yes, "mobile" -> lila.common.HTTPRequest.isMobileBrowser(ctx.req), "playing fixed-scroll" -> p.playing, - "no-rating" -> !pref.showRatings, + "no-rating" -> (!pref.showRatings || (p.playing && pref.hasShowRatingsInGame)), "no-flair" -> !pref.flairs, "zen" -> (pref.isZen || (p.playing && pref.isZenAuto)), "zenable" -> p.zenable, From bf0175ca83ae9beffa03359e833e01ba307fc1dc Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 22 Oct 2024 17:41:40 +0000 Subject: [PATCH 17/54] Remove comment --- modules/pref/src/main/Pref.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 4ba4b4d7567be..7de06789883cc 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -92,7 +92,7 @@ case class Pref( def isZen = zen == Zen.YES def isZenAuto = zen == Zen.GAME_AUTO - def showRatings = ratings != Ratings.NO // was val before + def showRatings = ratings != Ratings.NO def hasShowRatingsInGame = ratings == Ratings.GAME_ONLY def is2d = !is3d From 0763f1367e4efccb773f83dc3f4ac0bbe69c8439 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 22 Oct 2024 17:44:54 +0000 Subject: [PATCH 18/54] Fix formatting --- app/views/game/side.scala | 5 +- app/views/user/ui.scala | 11 +-- modules/game/src/main/ui/GameUi.scala | 5 +- modules/pref/src/main/JsonView.scala | 16 ++--- modules/pref/src/main/Pref.scala | 10 +-- modules/pref/src/main/PrefForm.scala | 32 ++++----- modules/pref/src/main/PrefHandlers.scala | 86 ++++++++++++------------ ui/round/src/view/user.ts | 5 +- 8 files changed, 89 insertions(+), 81 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 29776d376c4fe..1db4acf377de7 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -83,7 +83,10 @@ object side: withOnline = false, withDiff = true, withBerserk = true, - withRating = if (ctx.pref.hasShowRatingsInGame) game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) else true + withRating = + if ctx.pref.hasShowRatingsInGame then + game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) + else true ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index abe3d0ba59bd7..9aacb403592a2 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -38,10 +38,13 @@ def mini( def userMarks = views.mod.user.userMarks(u.user, None) val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs - val showRating = if (ctx.pref.hasShowRatingsInGame) (playingGame match - case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) - case None => !isUserPlaying - ) else true + val showRating = + if ctx.pref.hasShowRatingsInGame then + (playingGame match + case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) + case None => !isUserPlaying + ) + else true show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 7e1bbfa9ffe05..598f448b5e71e 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -26,7 +26,10 @@ final class GameUi(helpers: Helpers): renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = if (ctx.pref.hasShowRatingsInGame) pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) else ctx.pref.showRatings + showRatings = + if ctx.pref.hasShowRatingsInGame then + pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) + else ctx.pref.showRatings ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = diff --git a/modules/pref/src/main/JsonView.scala b/modules/pref/src/main/JsonView.scala index 74cb8f8026b2f..0a7395bc8e800 100644 --- a/modules/pref/src/main/JsonView.scala +++ b/modules/pref/src/main/JsonView.scala @@ -37,12 +37,12 @@ object JsonView: if lichobileCompat then Pref.SubmitMove.lichobile.serverToApp(p.submitMove) else p.submitMove }, - "confirmResign" -> p.confirmResign, - "insightShare" -> p.insightShare, - "keyboardMove" -> p.keyboardMove, - "voiceMove" -> p.hasVoice, - "zen" -> p.zen, - "ratings" -> p.ratings, - "moveEvent" -> p.moveEvent, - "rookCastle" -> p.rookCastle + "confirmResign" -> p.confirmResign, + "insightShare" -> p.insightShare, + "keyboardMove" -> p.keyboardMove, + "voiceMove" -> p.hasVoice, + "zen" -> p.zen, + "ratings" -> p.ratings, + "moveEvent" -> p.moveEvent, + "rookCastle" -> p.rookCastle ) diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 7de06789883cc..fd015d5f64acf 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -92,15 +92,15 @@ case class Pref( def isZen = zen == Zen.YES def isZenAuto = zen == Zen.GAME_AUTO - def showRatings = ratings != Ratings.NO + def showRatings = ratings != Ratings.NO def hasShowRatingsInGame = ratings == Ratings.GAME_ONLY def is2d = !is3d def agree = copy(agreement = Agreement.current) - def hasKeyboardMove = keyboardMove == KeyboardMove.YES - def hasVoice = voice.has(Voice.YES) + def hasKeyboardMove = keyboardMove == KeyboardMove.YES + def hasVoice = voice.has(Voice.YES) def isUsingAltSocket = usingAltSocket.has(true) @@ -248,8 +248,8 @@ object Pref: EVERYBODY -> "With everybody" ) - object KeyboardMove extends BooleanPref - object Voice extends BooleanPref + object KeyboardMove extends BooleanPref + object Voice extends BooleanPref object RookCastle: val NO = 0 diff --git a/modules/pref/src/main/PrefForm.scala b/modules/pref/src/main/PrefForm.scala index 727734efb5381..4a138ae3df0f8 100644 --- a/modules/pref/src/main/PrefForm.scala +++ b/modules/pref/src/main/PrefForm.scala @@ -36,22 +36,22 @@ object PrefForm: "URL must use https", url => url.isBlank || url.startsWith("https://") || url.startsWith("//") ) - val is3d = "is3d" -> tolerantBoolean - val zen = "zen" -> checkedNumber(Pref.Zen.choices) - val voice = "voice" -> booleanNumber - val keyboardMove = "keyboardMove" -> booleanNumber - val autoQueen = "autoQueen" -> checkedNumber(Pref.AutoQueen.choices) - val premove = "premove" -> booleanNumber - val takeback = "takeback" -> checkedNumber(Pref.Takeback.choices) - val autoThreefold = "autoThreefold" -> checkedNumber(Pref.AutoThreefold.choices) - val submitMove = "submitMove" -> bitCheckedNumber(Pref.SubmitMove.choices) - val confirmResign = "confirmResign" -> checkedNumber(Pref.ConfirmResign.choices) - val moretime = "moretime" -> checkedNumber(Pref.Moretime.choices) - val clockSound = "clockSound" -> booleanNumber - val pieceNotation = "pieceNotation" -> booleanNumber - val ratings = "ratings" -> checkedNumber(Pref.Ratings.choices) - val flairs = "flairs" -> boolean - val follow = "follow" -> booleanNumber + val is3d = "is3d" -> tolerantBoolean + val zen = "zen" -> checkedNumber(Pref.Zen.choices) + val voice = "voice" -> booleanNumber + val keyboardMove = "keyboardMove" -> booleanNumber + val autoQueen = "autoQueen" -> checkedNumber(Pref.AutoQueen.choices) + val premove = "premove" -> booleanNumber + val takeback = "takeback" -> checkedNumber(Pref.Takeback.choices) + val autoThreefold = "autoThreefold" -> checkedNumber(Pref.AutoThreefold.choices) + val submitMove = "submitMove" -> bitCheckedNumber(Pref.SubmitMove.choices) + val confirmResign = "confirmResign" -> checkedNumber(Pref.ConfirmResign.choices) + val moretime = "moretime" -> checkedNumber(Pref.Moretime.choices) + val clockSound = "clockSound" -> booleanNumber + val pieceNotation = "pieceNotation" -> booleanNumber + val ratings = "ratings" -> checkedNumber(Pref.Ratings.choices) + val flairs = "flairs" -> boolean + val follow = "follow" -> booleanNumber object board: val brightness = "boardBrightness" -> number(0, 150) val opacity = "boardOpacity" -> number(0, 100) diff --git a/modules/pref/src/main/PrefHandlers.scala b/modules/pref/src/main/PrefHandlers.scala index c8bf8f46a6629..41f70a7efdefa 100644 --- a/modules/pref/src/main/PrefHandlers.scala +++ b/modules/pref/src/main/PrefHandlers.scala @@ -60,47 +60,47 @@ private object PrefHandlers: def writes(w: BSON.Writer, o: Pref) = $doc( - "_id" -> o.id, - "bg" -> o.bg, - "bgImg" -> o.bgImg, - "is3d" -> o.is3d, - "theme" -> o.theme, - "pieceSet" -> o.pieceSet, - "theme3d" -> o.theme3d, - "pieceSet3d" -> o.pieceSet3d, - "soundSet" -> SoundSet.name2key(o.soundSet), - "autoQueen" -> o.autoQueen, - "autoThreefold" -> o.autoThreefold, - "takeback" -> o.takeback, - "moretime" -> o.moretime, - "clockTenths" -> o.clockTenths, - "clockBar" -> o.clockBar, - "clockSound" -> o.clockSound, - "premove" -> o.premove, - "animation" -> o.animation, - "captured" -> o.captured, - "follow" -> o.follow, - "highlight" -> o.highlight, - "destination" -> o.destination, - "coords" -> o.coords, - "replay" -> o.replay, - "challenge" -> o.challenge, - "message" -> o.message, - "studyInvite" -> o.studyInvite, - "submitMove" -> o.submitMove, - "confirmResign" -> o.confirmResign, - "insightShare" -> o.insightShare, - "keyboardMove" -> o.keyboardMove, - "voice" -> o.voice, - "zen" -> o.zen, - "ratings" -> o.ratings, - "flairs" -> o.flairs, - "rookCastle" -> o.rookCastle, - "moveEvent" -> o.moveEvent, - "pieceNotation" -> o.pieceNotation, - "resizeHandle" -> o.resizeHandle, - "agreement" -> o.agreement, - "usingAltSocket" -> o.usingAltSocket, - "board" -> o.board, - "tags" -> o.tags + "_id" -> o.id, + "bg" -> o.bg, + "bgImg" -> o.bgImg, + "is3d" -> o.is3d, + "theme" -> o.theme, + "pieceSet" -> o.pieceSet, + "theme3d" -> o.theme3d, + "pieceSet3d" -> o.pieceSet3d, + "soundSet" -> SoundSet.name2key(o.soundSet), + "autoQueen" -> o.autoQueen, + "autoThreefold" -> o.autoThreefold, + "takeback" -> o.takeback, + "moretime" -> o.moretime, + "clockTenths" -> o.clockTenths, + "clockBar" -> o.clockBar, + "clockSound" -> o.clockSound, + "premove" -> o.premove, + "animation" -> o.animation, + "captured" -> o.captured, + "follow" -> o.follow, + "highlight" -> o.highlight, + "destination" -> o.destination, + "coords" -> o.coords, + "replay" -> o.replay, + "challenge" -> o.challenge, + "message" -> o.message, + "studyInvite" -> o.studyInvite, + "submitMove" -> o.submitMove, + "confirmResign" -> o.confirmResign, + "insightShare" -> o.insightShare, + "keyboardMove" -> o.keyboardMove, + "voice" -> o.voice, + "zen" -> o.zen, + "ratings" -> o.ratings, + "flairs" -> o.flairs, + "rookCastle" -> o.rookCastle, + "moveEvent" -> o.moveEvent, + "pieceNotation" -> o.pieceNotation, + "resizeHandle" -> o.resizeHandle, + "agreement" -> o.agreement, + "usingAltSocket" -> o.usingAltSocket, + "board" -> o.board, + "tags" -> o.tags ) diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 10febb9366eb5..3012a608093fc 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -13,7 +13,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi user = player.user, perf = (user?.perfs || {})[d.game.perf], rating = player.rating || perf?.rating, - showRating = d.pref.showRatingsInGame ? !ctrl.isPlaying() : !!rating , + showRating = d.pref.showRatingsInGame ? !ctrl.isPlaying() : !!rating, signal = user?.id === d.opponent.user?.id ? d.opponentSignal : undefined; if (user) { @@ -46,8 +46,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - showRating && - h('rating', rating + (player.provisional ? '?' : '')), + showRating && h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && h('span', { From 511994e59a22c27fa44fd278d4c0f4c78d907eed Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 22 Oct 2024 17:58:33 +0000 Subject: [PATCH 19/54] Remove unnecessary translation --- modules/coreI18n/src/main/key.scala | 1 - translation/source/preferences.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index 04c81118e0e77..a146ef5b1eb45 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -1092,7 +1092,6 @@ object I18nKey: val `sayGgWpAfterLosingOrDrawing`: I18nKey = "preferences:sayGgWpAfterLosingOrDrawing" val `yourPreferencesHaveBeenSaved`: I18nKey = "preferences:yourPreferencesHaveBeenSaved" val `scrollOnTheBoardToReplayMoves`: I18nKey = "preferences:scrollOnTheBoardToReplayMoves" - val `showRatingsWhilePlaying`: I18nKey = "preferences:showRatingsWhilePlaying" val `correspondenceEmailNotification`: I18nKey = "preferences:correspondenceEmailNotification" val `notifyStreamStart`: I18nKey = "preferences:notifyStreamStart" val `notifyInboxMsg`: I18nKey = "preferences:notifyInboxMsg" diff --git a/translation/source/preferences.xml b/translation/source/preferences.xml index 5aafd65f1d2d0..2ec3b7ddb337c 100644 --- a/translation/source/preferences.xml +++ b/translation/source/preferences.xml @@ -53,7 +53,6 @@ Say "Good game, well played" upon defeat or draw Your preferences have been saved. Scroll on the board to replay moves - Show ratings while playing your games Daily email listing your correspondence games Streamer goes live New inbox message From 80239e83e31f10f8007b427fd4a4c357345d123b Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 22 Oct 2024 18:21:50 +0000 Subject: [PATCH 20/54] Fix server formatting --- app/controllers/User.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index e95f86b429304..d509fdf668f3b 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -177,7 +177,7 @@ final class User( ctx.userId.soFu(env.game.crosstableApi(user.id, _)), ctx.isAuth.so(env.pref.api.followable(user.id)) ).flatMapN: (blocked, crosstable, followable) => - val ping = env.socket.isOnline.exec(user.id).so(env.socket.getLagRating(user.id)) + val ping = env.socket.isOnline.exec(user.id).so(env.socket.getLagRating(user.id)) val isUserPlaying = ctx.userId.so(env.round.playing(_)) negotiate( html = (ctx.isnt(user)).so(currentlyPlaying(user.user)).flatMap { pov => From e5e3258a669316e0850875449fc67159a1c247e0 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 22 Oct 2024 19:20:38 +0000 Subject: [PATCH 21/54] retrigger checks From e1d86e189060baef99347f85e0234e034c0fecb1 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Wed, 23 Oct 2024 15:36:02 +0000 Subject: [PATCH 22/54] Change UI text for the new show ratings option --- modules/coreI18n/src/main/key.scala | 1 + modules/pref/src/main/Pref.scala | 2 +- modules/pref/src/main/ui/PrefHelper.scala | 2 +- translation/source/preferences.xml | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index 5bb1465cd4446..43443a988d37a 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -1076,6 +1076,7 @@ object I18nKey: val `displayBoardResizeHandle`: I18nKey = "preferences:displayBoardResizeHandle" val `onlyOnInitialPosition`: I18nKey = "preferences:onlyOnInitialPosition" val `inGameOnly`: I18nKey = "preferences:inGameOnly" + val `exceptInGame`: I18nKey = "preferences:exceptInGame" val `chessClock`: I18nKey = "preferences:chessClock" val `tenthsOfSeconds`: I18nKey = "preferences:tenthsOfSeconds" val `whenTimeRemainingLessThanTenSeconds`: I18nKey = "preferences:whenTimeRemainingLessThanTenSeconds" diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index fd015d5f64acf..4e40472d6c193 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -434,7 +434,7 @@ object Pref: val choices = Seq( NO -> "No", YES -> "Yes", - GAME_ONLY -> "In-game only" + GAME_ONLY -> "Except in-game" ) val darkByDefaultSince = instantOf(2021, 11, 7, 8, 0) diff --git a/modules/pref/src/main/ui/PrefHelper.scala b/modules/pref/src/main/ui/PrefHelper.scala index ae7bc657ce44d..442ba058799dc 100644 --- a/modules/pref/src/main/ui/PrefHelper.scala +++ b/modules/pref/src/main/ui/PrefHelper.scala @@ -24,7 +24,7 @@ trait PrefHelper: List( (Pref.Ratings.NO, trans.site.no.txt()), (Pref.Ratings.YES, trans.site.yes.txt()), - (Pref.Ratings.GAME_ONLY, trans.preferences.inGameOnly.txt()) + (Pref.Ratings.GAME_ONLY, trans.preferences.exceptInGame.txt()) ) def translatedBoardCoordinateChoices(using Translate) = diff --git a/translation/source/preferences.xml b/translation/source/preferences.xml index 2ec3b7ddb337c..4f8fafaa9ccf7 100644 --- a/translation/source/preferences.xml +++ b/translation/source/preferences.xml @@ -20,6 +20,7 @@ Show board resize handle Only on initial position In-game only + Except in-game Chess clock Tenths of seconds When time remaining < 10 seconds From 8de680b0cc8d401d8af40522ec4c25455294412f Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Wed, 23 Oct 2024 15:40:24 +0000 Subject: [PATCH 23/54] Renaming so it makes sense --- app/views/base/page.scala | 2 +- app/views/game/side.scala | 2 +- app/views/user/ui.scala | 2 +- modules/core/src/main/pref.scala | 2 +- modules/game/src/main/ui/GameUi.scala | 2 +- modules/pref/src/main/Pref.scala | 6 +++--- modules/pref/src/main/ui/PrefHelper.scala | 2 +- modules/round/src/main/JsonView.scala | 2 +- ui/round/src/interfaces.ts | 2 +- ui/round/src/view/user.ts | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/views/base/page.scala b/app/views/base/page.scala index 54838fc8c9fbf..5523552e61af7 100644 --- a/app/views/base/page.scala +++ b/app/views/base/page.scala @@ -102,7 +102,7 @@ object page: "kid" -> ctx.kid.yes, "mobile" -> lila.common.HTTPRequest.isMobileBrowser(ctx.req), "playing fixed-scroll" -> p.playing, - "no-rating" -> (!pref.showRatings || (p.playing && pref.hasShowRatingsInGame)), + "no-rating" -> (!pref.showRatings || (p.playing && pref.hideRatingsInGame)), "no-flair" -> !pref.flairs, "zen" -> (pref.isZen || (p.playing && pref.isZenAuto)), "zenable" -> p.zenable, diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 1db4acf377de7..13aa62d6afe12 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -84,7 +84,7 @@ object side: withDiff = true, withBerserk = true, withRating = - if ctx.pref.hasShowRatingsInGame then + if ctx.pref.hideRatingsInGame then game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) else true ) diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 9aacb403592a2..558c239836228 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -39,7 +39,7 @@ def mini( val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs val showRating = - if ctx.pref.hasShowRatingsInGame then + if ctx.pref.hideRatingsInGame then (playingGame match case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) case None => !isUserPlaying diff --git a/modules/core/src/main/pref.scala b/modules/core/src/main/pref.scala index 04fac8e114d9d..e9e2f716b1939 100644 --- a/modules/core/src/main/pref.scala +++ b/modules/core/src/main/pref.scala @@ -21,7 +21,7 @@ trait Pref: def hasKeyboardMove: Boolean def hasVoice: Boolean - def hasShowRatingsInGame: Boolean + def hideRatingsInGame: Boolean def showRatings: Boolean def animationMillis: Int def animationMillisForSpeedPuzzles: Int diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 598f448b5e71e..864f67f299ef0 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -27,7 +27,7 @@ final class GameUi(helpers: Helpers): pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), showRatings = - if ctx.pref.hasShowRatingsInGame then + if ctx.pref.hideRatingsInGame then pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) else ctx.pref.showRatings ) diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 4e40472d6c193..3ded81fb965d1 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -93,7 +93,7 @@ case class Pref( def isZenAuto = zen == Zen.GAME_AUTO def showRatings = ratings != Ratings.NO - def hasShowRatingsInGame = ratings == Ratings.GAME_ONLY + def hideRatingsInGame = ratings == Ratings.EXCEPT_GAME def is2d = !is3d @@ -429,12 +429,12 @@ object Pref: object Ratings: val NO = 0 val YES = 1 - val GAME_ONLY = 2 + val EXCEPT_GAME = 2 val choices = Seq( NO -> "No", YES -> "Yes", - GAME_ONLY -> "Except in-game" + EXCEPT_GAME -> "Except in-game" ) val darkByDefaultSince = instantOf(2021, 11, 7, 8, 0) diff --git a/modules/pref/src/main/ui/PrefHelper.scala b/modules/pref/src/main/ui/PrefHelper.scala index 442ba058799dc..b8d3c7b087b05 100644 --- a/modules/pref/src/main/ui/PrefHelper.scala +++ b/modules/pref/src/main/ui/PrefHelper.scala @@ -24,7 +24,7 @@ trait PrefHelper: List( (Pref.Ratings.NO, trans.site.no.txt()), (Pref.Ratings.YES, trans.site.yes.txt()), - (Pref.Ratings.GAME_ONLY, trans.preferences.exceptInGame.txt()) + (Pref.Ratings.EXCEPT_GAME, trans.preferences.exceptInGame.txt()) ) def translatedBoardCoordinateChoices(using Translate) = diff --git a/modules/round/src/main/JsonView.scala b/modules/round/src/main/JsonView.scala index 7a286662b338a..5413ead4560fd 100644 --- a/modules/round/src/main/JsonView.scala +++ b/modules/round/src/main/JsonView.scala @@ -116,7 +116,7 @@ final class JsonView( .add("confirmResign" -> (!flags.nvui && pref.confirmResign == Pref.ConfirmResign.YES)) .add("keyboardMove" -> (!flags.nvui && pref.hasKeyboardMove)) .add("voiceMove" -> (!flags.nvui && pref.hasVoice)) - .add("showRatingsInGame" -> (!flags.nvui && pref.hasShowRatingsInGame)) + .add("hideRatingsInGame" -> (pref.hideRatingsInGame)) .add("rookCastle" -> (pref.rookCastle == Pref.RookCastle.YES)) .add("highlight" -> pref.highlight) .add("destination" -> pref.destination) diff --git a/ui/round/src/interfaces.ts b/ui/round/src/interfaces.ts index 98614341ce9e1..c7f17db2b95c5 100644 --- a/ui/round/src/interfaces.ts +++ b/ui/round/src/interfaces.ts @@ -187,7 +187,7 @@ export interface Pref { highlight: boolean; is3d: boolean; keyboardMove: boolean; - showRatingsInGame: boolean; + hideRatingsInGame: boolean; voiceMove: boolean; moveEvent: Prefs.MoveEvent; ratings: boolean; diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index dc3d17a742798..48eeca8926a0a 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -10,7 +10,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi user = player.user, perf = (user?.perfs || {})[d.game.perf], rating = player.rating || perf?.rating, - showRating = d.pref.showRatingsInGame ? !ctrl.isPlaying() : !!rating, + showRating = d.pref.hideRatingsInGame ? !ctrl.isPlaying() : !!rating, signal = user?.id === d.opponent.user?.id ? d.opponentSignal : undefined; if (user) { From e67f1b6d26b1a2011627ca0f48c27ce74f8c0f0f Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Wed, 23 Oct 2024 15:53:15 +0000 Subject: [PATCH 24/54] Simplify if statements with boolean logic --- app/views/game/side.scala | 5 +---- app/views/user/ui.scala | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 13aa62d6afe12..1f93f494b4acb 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -83,10 +83,7 @@ object side: withOnline = false, withDiff = true, withBerserk = true, - withRating = - if ctx.pref.hideRatingsInGame then - game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) - else true + withRating = !ctx.pref.hideRatingsInGame || game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 558c239836228..774f59ff4dcd4 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -39,12 +39,11 @@ def mini( val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs val showRating = - if ctx.pref.hideRatingsInGame then + !ctx.pref.hideRatingsInGame || (playingGame match case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) case None => !isUserPlaying ) - else true show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) From bbe24f1a31a5f9fd63175522271214be880e4f06 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Wed, 23 Oct 2024 16:29:48 +0000 Subject: [PATCH 25/54] Use game.playable instead of game.finishedOrAborted --- app/views/game/side.scala | 2 +- app/views/user/ui.scala | 2 +- modules/game/src/main/ui/GameUi.scala | 2 +- ui/@types/lichess/i18n.d.ts | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 1f93f494b4acb..170e2a09963f3 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -83,7 +83,7 @@ object side: withOnline = false, withDiff = true, withBerserk = true, - withRating = !ctx.pref.hideRatingsInGame || game.finishedOrAborted || !ctx.userId.exists(game.userIds.has) + withRating = !ctx.pref.hideRatingsInGame || !game.playable || !ctx.userId.exists(game.userIds.has) ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 774f59ff4dcd4..88c57ccca0bc2 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -41,7 +41,7 @@ def mini( val showRating = !ctx.pref.hideRatingsInGame || (playingGame match - case Some(pov) => pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) + case Some(pov) => !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) case None => !isUserPlaying ) show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 864f67f299ef0..6ce87df0b1e31 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -28,7 +28,7 @@ final class GameUi(helpers: Helpers): withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), showRatings = if ctx.pref.hideRatingsInGame then - pov.game.finishedOrAborted || !ctx.userId.exists(pov.game.userIds.has) + !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) else ctx.pref.showRatings ) diff --git a/ui/@types/lichess/i18n.d.ts b/ui/@types/lichess/i18n.d.ts index 4352705306642..e48158ca325b2 100644 --- a/ui/@types/lichess/i18n.d.ts +++ b/ui/@types/lichess/i18n.d.ts @@ -2077,6 +2077,8 @@ interface I18n { displayBoardResizeHandle: string; /** Drag a piece */ dragPiece: string; + /** Except in-game */ + exceptInGame: string; /** Can be disabled during a game with the board menu */ explainCanThenBeTemporarilyDisabled: string; /** Hold the key while promoting to temporarily disable auto-promotion */ From 688c7b439b09e78d9322d1615772699cf94fd5b7 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Wed, 23 Oct 2024 16:32:20 +0000 Subject: [PATCH 26/54] Format code --- app/views/game/side.scala | 3 ++- app/views/user/ui.scala | 2 +- modules/game/src/main/ui/GameUi.scala | 3 +-- modules/pref/src/main/Pref.scala | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 170e2a09963f3..16c3583c009a7 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -83,7 +83,8 @@ object side: withOnline = false, withDiff = true, withBerserk = true, - withRating = !ctx.pref.hideRatingsInGame || !game.playable || !ctx.userId.exists(game.userIds.has) + withRating = + !ctx.pref.hideRatingsInGame || !game.playable || !ctx.userId.exists(game.userIds.has) ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 88c57ccca0bc2..00198917d44fc 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -43,7 +43,7 @@ def mini( (playingGame match case Some(pov) => !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) case None => !isUserPlaying - ) + ) show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 6ce87df0b1e31..8811922a7fe5c 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -27,8 +27,7 @@ final class GameUi(helpers: Helpers): pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), showRatings = - if ctx.pref.hideRatingsInGame then - !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) + if ctx.pref.hideRatingsInGame then !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) else ctx.pref.showRatings ) diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 3ded81fb965d1..057b0d751f7bc 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -92,7 +92,7 @@ case class Pref( def isZen = zen == Zen.YES def isZenAuto = zen == Zen.GAME_AUTO - def showRatings = ratings != Ratings.NO + def showRatings = ratings != Ratings.NO def hideRatingsInGame = ratings == Ratings.EXCEPT_GAME def is2d = !is3d @@ -427,13 +427,13 @@ object Pref: ) object Ratings: - val NO = 0 - val YES = 1 + val NO = 0 + val YES = 1 val EXCEPT_GAME = 2 val choices = Seq( - NO -> "No", - YES -> "Yes", + NO -> "No", + YES -> "Yes", EXCEPT_GAME -> "Except in-game" ) From 4030f2c8fbb530618f4096c147ed406d94d31a81 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Thu, 24 Oct 2024 10:25:59 +0200 Subject: [PATCH 27/54] codegolf --- app/controllers/User.scala | 3 +-- app/views/user/ui.scala | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index d509fdf668f3b..1c6b3f627d5c5 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -44,10 +44,9 @@ final class User( env.game.cached .lastPlayedPlayingId(username.id) .orElse(env.game.gameRepo.quickLastPlayedId(username.id)) - .flatMap { + .flatMap: case None => NotFound("No ongoing game") case Some(gameId) => gameC.exportGame(gameId) - } private def apiGames(u: UserModel, filter: String, page: Int)(using BodyContext[?]) = userGames(u, filter, page).flatMap(env.game.userGameApi.jsPaginator).map { res => diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 00198917d44fc..17a4f3e0124bb 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -40,10 +40,9 @@ def mini( val perfs = u.perfs.best8Perfs val showRating = !ctx.pref.hideRatingsInGame || - (playingGame match + playingGame.match case Some(pov) => !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) case None => !isUserPlaying - ) show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) From 8426a851e1d296d38dc4983e96f817c1f98dd266 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Thu, 24 Oct 2024 10:27:24 +0200 Subject: [PATCH 28/54] rename isUserPlaying that is not about the user being shown, but the one being logged, aka me --- app/controllers/User.scala | 6 +++--- app/views/user/ui.scala | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index 1c6b3f627d5c5..c219f6bf8ea4e 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -176,12 +176,12 @@ final class User( ctx.userId.soFu(env.game.crosstableApi(user.id, _)), ctx.isAuth.so(env.pref.api.followable(user.id)) ).flatMapN: (blocked, crosstable, followable) => - val ping = env.socket.isOnline.exec(user.id).so(env.socket.getLagRating(user.id)) - val isUserPlaying = ctx.userId.so(env.round.playing(_)) + val ping = env.socket.isOnline.exec(user.id).so(env.socket.getLagRating(user.id)) + val amPlaying = ctx.userId.so(env.round.playing(_)) negotiate( html = (ctx.isnt(user)).so(currentlyPlaying(user.user)).flatMap { pov => Ok.snip( - views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, isUserPlaying) + views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, amPlaying) ).map(_.withHeaders(CACHE_CONTROL -> "max-age=5")) }, json = diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 17a4f3e0124bb..7f53cf6776f00 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -19,7 +19,7 @@ def mini( relation: Option[lila.relation.Relation], ping: Option[Int], ct: Option[lila.game.Crosstable], - isUserPlaying: Boolean + amPlaying: Boolean )(using ctx: Context) = val rel = views.relation.mini(u.id, blocked, followable, relation) def crosstable(myId: UserId) = ct @@ -42,7 +42,7 @@ def mini( !ctx.pref.hideRatingsInGame || playingGame.match case Some(pov) => !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) - case None => !isUserPlaying + case None => !amPlaying show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) From f9bb60c15884dfb887e4dc31c6e3c71c1c83aeee Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Thu, 24 Oct 2024 11:37:33 +0200 Subject: [PATCH 29/54] fix code duplication with Pref.showRatingsIn --- app/views/game/side.scala | 3 +-- app/views/user/ui.scala | 14 +++++--------- modules/api/src/main/Context.scala | 1 - modules/core/src/main/pref.scala | 4 +++- modules/game/src/main/ui/GameUi.scala | 4 +--- modules/pref/src/main/Pref.scala | 9 +++++++++ modules/ui/src/main/Context.scala | 1 + 7 files changed, 20 insertions(+), 16 deletions(-) diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 16c3583c009a7..24b885bf72dec 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -83,8 +83,7 @@ object side: withOnline = false, withDiff = true, withBerserk = true, - withRating = - !ctx.pref.hideRatingsInGame || !game.playable || !ctx.userId.exists(game.userIds.has) + withRating = ctx.pref.showRatingsIn(game.some, false) ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 7f53cf6776f00..1322ae5e954fe 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -34,15 +34,11 @@ def mini( val opponent = ~cross.showOpponentScore(myId) s"""${cross.showScore(myId)} - $opponent""" ) - val playing = playingGame.map(views.game.mini(_)) - def userMarks = views.mod.user.userMarks(u.user, None) - val flag = u.profileOrDefault.flagInfo - val perfs = u.perfs.best8Perfs - val showRating = - !ctx.pref.hideRatingsInGame || - playingGame.match - case Some(pov) => !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) - case None => !amPlaying + val playing = playingGame.map(views.game.mini(_)) + def userMarks = views.mod.user.userMarks(u.user, None) + val flag = u.profileOrDefault.flagInfo + val perfs = u.perfs.best8Perfs + val showRating = ctx.pref.showRatingsIn(playingGame.map(_.game), amPlaying) show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) diff --git a/modules/api/src/main/Context.scala b/modules/api/src/main/Context.scala index 56f64371a0c91..e807513f67a7c 100644 --- a/modules/api/src/main/Context.scala +++ b/modules/api/src/main/Context.scala @@ -20,7 +20,6 @@ final class LoginContext( val oauth: Option[TokenScopes] ): export me.{ isDefined as isAuth, isEmpty as isAnon } - def myId: Option[MyId] = me.map(_.myId) def user: Option[User] = Me.raw(me) def userId: Option[UserId] = user.map(_.id) def username: Option[UserName] = user.map(_.username) diff --git a/modules/core/src/main/pref.scala b/modules/core/src/main/pref.scala index e9e2f716b1939..ea51685aa2271 100644 --- a/modules/core/src/main/pref.scala +++ b/modules/core/src/main/pref.scala @@ -2,7 +2,8 @@ package lila.core package pref import lila.core.user.User -import lila.core.userId.UserId +import lila.core.userId.{ MyId, UserId } +import lila.core.game.Game trait Pref: val id: UserId @@ -23,6 +24,7 @@ trait Pref: def hasVoice: Boolean def hideRatingsInGame: Boolean def showRatings: Boolean + def showRatingsIn(game: Option[Game], amPlaying: Boolean)(using Option[MyId]): Boolean def animationMillis: Int def animationMillisForSpeedPuzzles: Int def pieceNotationIsLetter: Boolean diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 8811922a7fe5c..b24ea0419f863 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -26,9 +26,7 @@ final class GameUi(helpers: Helpers): renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = - if ctx.pref.hideRatingsInGame then !pov.game.playable || !ctx.userId.exists(pov.game.userIds.has) - else ctx.pref.showRatings + showRatings = ctx.pref.showRatingsIn(pov.game.some, false)(using ctx.myId) ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 057b0d751f7bc..be7fe78016c69 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -95,6 +95,15 @@ case class Pref( def showRatings = ratings != Ratings.NO def hideRatingsInGame = ratings == Ratings.EXCEPT_GAME + def showRatingsIn(game: Option[lila.core.game.Game], amPlaying: Boolean)(using + myId: Option[MyId] + ): Boolean = + if ratings == Ratings.EXCEPT_GAME + then + game.fold(!amPlaying): g => + !g.playable || !myId.exists(me => g.userIds.has(me.id)) + else ratings == Ratings.YES + def is2d = !is3d def agree = copy(agreement = Agreement.current) diff --git a/modules/ui/src/main/Context.scala b/modules/ui/src/main/Context.scala index d26d1cb647530..b42d13faf2b3b 100644 --- a/modules/ui/src/main/Context.scala +++ b/modules/ui/src/main/Context.scala @@ -28,6 +28,7 @@ trait Context: def is[U: UserIdOf](u: U): Boolean = me.exists(_.is(u)) def isnt[U: UserIdOf](u: U): Boolean = !is(u) + def myId: Option[MyId] = me.map(_.myId) def noBlind = !blind def flash(name: String): Option[String] = req.flash.get(name) inline def noBot = !isBot From 182a2774140474f02870862e40eefaec3dff2fb7 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Thu, 24 Oct 2024 11:41:56 +0200 Subject: [PATCH 30/54] move logic out of view into controller --- app/controllers/User.scala | 9 +++++---- app/views/user/ui.scala | 11 +++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index c219f6bf8ea4e..f573ff5655b0c 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -176,12 +176,13 @@ final class User( ctx.userId.soFu(env.game.crosstableApi(user.id, _)), ctx.isAuth.so(env.pref.api.followable(user.id)) ).flatMapN: (blocked, crosstable, followable) => - val ping = env.socket.isOnline.exec(user.id).so(env.socket.getLagRating(user.id)) - val amPlaying = ctx.userId.so(env.round.playing(_)) negotiate( - html = (ctx.isnt(user)).so(currentlyPlaying(user.user)).flatMap { pov => + html = ctx.isnt(user).so(currentlyPlaying(user.user)).flatMap { pov => + val ping = env.socket.isOnline.exec(user.id).so(env.socket.getLagRating(user.id)) + val showRating = + ctx.pref.showRatingsIn(pov.map(_.game), ctx.userId.so(env.round.playing(_))) Ok.snip( - views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, amPlaying) + views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, showRating) ).map(_.withHeaders(CACHE_CONTROL -> "max-age=5")) }, json = diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index 1322ae5e954fe..c70dba8ec1fa6 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -19,7 +19,7 @@ def mini( relation: Option[lila.relation.Relation], ping: Option[Int], ct: Option[lila.game.Crosstable], - amPlaying: Boolean + showRating: Boolean )(using ctx: Context) = val rel = views.relation.mini(u.id, blocked, followable, relation) def crosstable(myId: UserId) = ct @@ -34,11 +34,10 @@ def mini( val opponent = ~cross.showOpponentScore(myId) s"""${cross.showScore(myId)} - $opponent""" ) - val playing = playingGame.map(views.game.mini(_)) - def userMarks = views.mod.user.userMarks(u.user, None) - val flag = u.profileOrDefault.flagInfo - val perfs = u.perfs.best8Perfs - val showRating = ctx.pref.showRatingsIn(playingGame.map(_.game), amPlaying) + val playing = playingGame.map(views.game.mini(_)) + def userMarks = views.mod.user.userMarks(u.user, None) + val flag = u.profileOrDefault.flagInfo + val perfs = u.perfs.best8Perfs show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) From 64a6f85d5f2af06fb30b58789b3fcd4d5f53c45b Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Thu, 24 Oct 2024 11:44:34 +0200 Subject: [PATCH 31/54] remove superfluous parens --- modules/round/src/main/JsonView.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/round/src/main/JsonView.scala b/modules/round/src/main/JsonView.scala index 5413ead4560fd..0ef2f54e5fcbe 100644 --- a/modules/round/src/main/JsonView.scala +++ b/modules/round/src/main/JsonView.scala @@ -116,7 +116,7 @@ final class JsonView( .add("confirmResign" -> (!flags.nvui && pref.confirmResign == Pref.ConfirmResign.YES)) .add("keyboardMove" -> (!flags.nvui && pref.hasKeyboardMove)) .add("voiceMove" -> (!flags.nvui && pref.hasVoice)) - .add("hideRatingsInGame" -> (pref.hideRatingsInGame)) + .add("hideRatingsInGame" -> pref.hideRatingsInGame) .add("rookCastle" -> (pref.rookCastle == Pref.RookCastle.YES)) .add("highlight" -> pref.highlight) .add("destination" -> pref.destination) From 55f143bfc676d6888f276fe40fdc98ff2d7578e1 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Thu, 24 Oct 2024 11:44:44 +0200 Subject: [PATCH 32/54] remove duplicated showRatings check --- modules/user/src/main/ui/UserShow.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/user/src/main/ui/UserShow.scala b/modules/user/src/main/ui/UserShow.scala index 752a07e30a9db..134f4838198a5 100644 --- a/modules/user/src/main/ui/UserShow.scala +++ b/modules/user/src/main/ui/UserShow.scala @@ -56,7 +56,7 @@ final class UserShow(helpers: Helpers, bits: UserBits): if u.lame && ctx.isnt(u) && !Granter.opt(_.UserModView) then div(cls := "upt__info__warning")(trans.site.thisAccountViolatedTos()) else - (ctx.pref.showRatings && showRating).option: + showRating.option: div(cls := "upt__info__ratings")(best8Perfs.map(showPerfRating(u.perfs, _))) ), ctx.userId.map: myId => From 872929606f7d6450186197b3f2f41ca06096cdd0 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 5 Nov 2024 21:24:24 +0000 Subject: [PATCH 33/54] Hide ratings in round crosstable minis --- app/controllers/Round.scala | 3 ++- app/views/user/ui.scala | 2 +- modules/game/src/main/ui/GameUi.scala | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/controllers/Round.scala b/app/controllers/Round.scala index b98c8f803b9e2..a68db03344c2e 100644 --- a/app/controllers/Round.scala +++ b/app/controllers/Round.scala @@ -290,11 +290,12 @@ final class Round( akka.pattern.after(500.millis, env.system.scheduler)(redirection) def mini(gameId: GameId, color: Color) = Open: + val showRating = ctx.pref.showRatingsIn(None, ctx.userId.so(env.round.playing(_)))(using ctx.myId) FoundSnip( env.round.proxyRepo .povIfPresent(gameId, color) .orElse(env.game.gameRepo.pov(gameId, color)) - )(pov => Snippet(views.game.mini(pov))) + )(pov => Snippet(views.game.mini(pov, showRating = showRating))) def miniFullId(fullId: GameFullId) = Open: FoundSnip(env.round.proxyRepo.povIfPresent(fullId).orElse(env.game.gameRepo.pov(fullId))): pov => diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index c70dba8ec1fa6..a96058d76a89d 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -34,7 +34,7 @@ def mini( val opponent = ~cross.showOpponentScore(myId) s"""${cross.showScore(myId)} - $opponent""" ) - val playing = playingGame.map(views.game.mini(_)) + val playing = playingGame.map(views.game.mini(_, showRating = showRating)) def userMarks = views.mod.user.userMarks(u.user, None) val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index b24ea0419f863..c8fcd62f8b601 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -20,13 +20,13 @@ final class GameUi(helpers: Helpers): private val dataTimeControl = attr("data-tc") val cgWrap = span(cls := "cg-wrap")(cgWrapContent) - def apply(pov: Pov, ownerLink: Boolean = false, tv: Boolean = false, withLink: Boolean = true)(using + def apply(pov: Pov, ownerLink: Boolean = false, tv: Boolean = false, withLink: Boolean = true, showRating: Boolean = true)(using ctx: Context ): Tag = renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = ctx.pref.showRatingsIn(pov.game.some, false)(using ctx.myId) + showRatings = showRating ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = From b1506dd58d306ca7c8177ed34a12a59d2b98464b Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 5 Nov 2024 22:14:33 +0000 Subject: [PATCH 34/54] Format code --- modules/game/src/main/ui/GameUi.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index c8fcd62f8b601..3dd0e6d27279c 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -20,7 +20,13 @@ final class GameUi(helpers: Helpers): private val dataTimeControl = attr("data-tc") val cgWrap = span(cls := "cg-wrap")(cgWrapContent) - def apply(pov: Pov, ownerLink: Boolean = false, tv: Boolean = false, withLink: Boolean = true, showRating: Boolean = true)(using + def apply( + pov: Pov, + ownerLink: Boolean = false, + tv: Boolean = false, + withLink: Boolean = true, + showRating: Boolean = true + )(using ctx: Context ): Tag = renderMini( From d7447289d255b7c4317e936858d5c81d8ceb1d9c Mon Sep 17 00:00:00 2001 From: YaFred Date: Sat, 14 Dec 2024 08:00:32 +0100 Subject: [PATCH 35/54] move student to another class --- app/controllers/Clas.scala | 14 ++++++++++++++ app/views/clas.scala | 2 +- conf/clas.routes | 2 ++ modules/clas/src/main/ui/StudentFormUi.scala | 20 ++++++++++++++++++++ modules/clas/src/main/ui/StudentUi.scala | 7 ++++++- 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index b27410747d61d..cf3336181ada1 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -472,6 +472,20 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): else redirectTo(clas) } + def studentMove(id: ClasId, username: UserStr) = Secure(_.Teacher) { ctx ?=> me ?=> + WithClassAndStudents(id): (clas, students) => + WithStudent(clas, username): s => + if s.student.managed + then Ok.page(views.clas.student.move(clas, students, s)) + else Redirect(routes.Clas.studentShow(clas.id, s.user.username)) + } + + def studentMovePost(id: ClasId, username: UserStr) = SecureBody(_.Teacher) { ctx ?=> me ?=> + WithClassAndStudents(id): (clas, students) => + WithStudent(clas, username): s => + Redirect(routes.Clas.show(clas.id)) + } + def becomeTeacher = AuthBody { ctx ?=> me ?=> couldBeTeacher.elseNotFound: val perm = lila.core.perm.Permission.Teacher.dbKey diff --git a/app/views/clas.scala b/app/views/clas.scala index 8811ff105f2df..3a8518dc90c0f 100644 --- a/app/views/clas.scala +++ b/app/views/clas.scala @@ -18,7 +18,7 @@ object student: lazy val formUi = lila.clas.ui.StudentFormUi(helpers, views.clas.ui, ui) export ui.{ invite } - export formUi.{ newStudent as form, many as manyForm, edit, release, close } + export formUi.{ newStudent as form, many as manyForm, edit, release, close, move } def show( clas: Clas, diff --git a/conf/clas.routes b/conf/clas.routes index 7d119b15396be..d0a03ee08cdcf 100644 --- a/conf/clas.routes +++ b/conf/clas.routes @@ -32,3 +32,5 @@ POST /class/$id<\w{8}>/student/:username/release controllers.clas.Clas.studentR GET /class/$id<\w{8}>/student/:username/close controllers.clas.Clas.studentClose(id: ClasId, username: UserStr) POST /class/$id<\w{8}>/student/:username/close controllers.clas.Clas.studentClosePost(id: ClasId, username: UserStr) POST /class/$id<\w{8}>/invitation/revoke controllers.clas.Clas.invitationRevoke(id: ClasInviteId) +GET /class/$id<\w{8}>/student/:username/move controllers.clas.Clas.studentMove(id: ClasId, username: UserStr) +POST /class/$id<\w{8}>/student/:username/move controllers.clas.Clas.studentMovePost(id: ClasId, username: UserStr) diff --git a/modules/clas/src/main/ui/StudentFormUi.scala b/modules/clas/src/main/ui/StudentFormUi.scala index 59803a9417101..840e28a31d39e 100644 --- a/modules/clas/src/main/ui/StudentFormUi.scala +++ b/modules/clas/src/main/ui/StudentFormUi.scala @@ -250,6 +250,26 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi ) ) + def move(clas: Clas, students: List[Student], s: Student.WithUser)(using Context) = + ClasPage(s.user.username.value, Left(clas.withStudents(students)), s.student.some)( + cls := "student-show student-edit" + ): + frag( + studentUi.top(clas, s), + div(cls := "box__pad")( + h2("Move to another class"), + p( + "Select a class" + ), + postForm(cls := "form3", action := routes.Clas.studentMovePost(clas.id, s.user.username))( + form3.actions( + a(href := routes.Clas.studentShow(clas.id, s.user.username))(trans.site.cancel()), + form3.submit(trans.site.apply()) + ) + ) + ) + ) + def close(clas: Clas, students: List[Student], s: Student.WithUser)(using Context) = ClasPage(s.user.username.value, Left(clas.withStudents(students)), s.student.some)( cls := "student-show student-edit" diff --git a/modules/clas/src/main/ui/StudentUi.scala b/modules/clas/src/main/ui/StudentUi.scala index e54f41201eb6c..85407d8da9df7 100644 --- a/modules/clas/src/main/ui/StudentUi.scala +++ b/modules/clas/src/main/ui/StudentUi.scala @@ -64,7 +64,12 @@ final class StudentUi(helpers: Helpers, clasUi: ClasUi)(using NetDomain): href := routes.Clas.studentRelease(clas.id, s.user.username), cls := "button button-empty", title := trans.clas.upgradeFromManaged.txt() - )(trans.clas.release()) + )(trans.clas.release()), + a( + href := routes.Clas.studentMove(clas.id, s.user.username), + cls := "button button-empty", + title := "Move" + )("Move") ) ) ) From 734b9f3cf49378e3ab54f05976d7267caa6de8be Mon Sep 17 00:00:00 2001 From: YaFred Date: Sat, 14 Dec 2024 19:05:54 +0100 Subject: [PATCH 36/54] move student to another class --- app/controllers/Clas.scala | 17 +++++++++--- conf/clas.routes | 2 +- modules/clas/src/main/ui/StudentFormUi.scala | 29 ++++++++++++++------ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index cf3336181ada1..a09b24b7ccbb0 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -475,12 +475,13 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): def studentMove(id: ClasId, username: UserStr) = Secure(_.Teacher) { ctx ?=> me ?=> WithClassAndStudents(id): (clas, students) => WithStudent(clas, username): s => - if s.student.managed - then Ok.page(views.clas.student.move(clas, students, s)) - else Redirect(routes.Clas.studentShow(clas.id, s.user.username)) + WithMyOtherClasses(clas): classes => + if s.student.managed + then Ok.page(views.clas.student.move(clas, students, s, classes)) + else Redirect(routes.Clas.studentShow(clas.id, s.user.username)) } - def studentMovePost(id: ClasId, username: UserStr) = SecureBody(_.Teacher) { ctx ?=> me ?=> + def studentMovePost(id: ClasId, username: UserStr, to: ClasId) = SecureBody(_.Teacher) { ctx ?=> me ?=> WithClassAndStudents(id): (clas, students) => WithStudent(clas, username): s => Redirect(routes.Clas.show(clas.id)) @@ -537,6 +538,14 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): WithClass(clasId): c => env.clas.api.student.activeOf(c).flatMap { f(c, _) } + private def WithMyOtherClasses(clas: lila.clas.Clas)( + f: (List[lila.clas.Clas]) => Fu[Result] + )(using teacher: Me): Fu[Result] = + val res = + for classes <- env.clas.api.clas.of(teacher) + yield classes.filter(_.id != clas.id) + res.flatMap(f) + private def WithStudent(clas: lila.clas.Clas, username: UserStr)( f: lila.clas.Student.WithUser => Fu[Result] )(using Context): Fu[Result] = diff --git a/conf/clas.routes b/conf/clas.routes index d0a03ee08cdcf..893c5a1bc7c8b 100644 --- a/conf/clas.routes +++ b/conf/clas.routes @@ -33,4 +33,4 @@ GET /class/$id<\w{8}>/student/:username/close controllers.clas.Clas.studentClo POST /class/$id<\w{8}>/student/:username/close controllers.clas.Clas.studentClosePost(id: ClasId, username: UserStr) POST /class/$id<\w{8}>/invitation/revoke controllers.clas.Clas.invitationRevoke(id: ClasInviteId) GET /class/$id<\w{8}>/student/:username/move controllers.clas.Clas.studentMove(id: ClasId, username: UserStr) -POST /class/$id<\w{8}>/student/:username/move controllers.clas.Clas.studentMovePost(id: ClasId, username: UserStr) +POST /class/$id<\w{8}>/student/:username/move/$to<\w{8}> controllers.clas.Clas.studentMovePost(id: ClasId, username: UserStr, to: ClasId) diff --git a/modules/clas/src/main/ui/StudentFormUi.scala b/modules/clas/src/main/ui/StudentFormUi.scala index 840e28a31d39e..a764181272e57 100644 --- a/modules/clas/src/main/ui/StudentFormUi.scala +++ b/modules/clas/src/main/ui/StudentFormUi.scala @@ -250,22 +250,33 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi ) ) - def move(clas: Clas, students: List[Student], s: Student.WithUser)(using Context) = + def move(clas: Clas, students: List[Student], s: Student.WithUser, otherClasses: List[Clas])(using + Context + ) = ClasPage(s.user.username.value, Left(clas.withStudents(students)), s.student.some)( cls := "student-show student-edit" ): + + val classForms: Frag = + for (aClass <- otherClasses) + yield ( + postForm( + action := routes.Clas.studentMovePost(clas.id, s.student.userId, aClass.id) + )( + form3.submit(aClass.name, icon = Icon.Target.some)( + cls := "yes-no-confirm button-blue button-empty", + title := "Move to " + aClass.name + ) + ) + ) + frag( studentUi.top(clas, s), div(cls := "box__pad")( h2("Move to another class"), - p( - "Select a class" - ), - postForm(cls := "form3", action := routes.Clas.studentMovePost(clas.id, s.user.username))( - form3.actions( - a(href := routes.Clas.studentShow(clas.id, s.user.username))(trans.site.cancel()), - form3.submit(trans.site.apply()) - ) + classForms, + form3.actions( + a(href := routes.Clas.studentShow(clas.id, s.user.username))(trans.site.cancel()) ) ) ) From b35a2c111bb8c914f8285935980eccdaf5658960 Mon Sep 17 00:00:00 2001 From: YaFred Date: Sat, 14 Dec 2024 22:07:56 +0100 Subject: [PATCH 37/54] move student to another class --- app/controllers/Clas.scala | 11 +++++++---- modules/clas/src/main/ClasApi.scala | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index a09b24b7ccbb0..430ac37752998 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -11,6 +11,7 @@ import lila.clas.ClasForm.ClasData import lila.clas.ClasInvite import lila.core.id.{ ClasId, ClasInviteId } import lila.core.security.ClearPassword +import lila.clas.ClasForm.CreateStudent final class Clas(env: Env, authC: Auth) extends LilaController(env): @@ -476,15 +477,17 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): WithClassAndStudents(id): (clas, students) => WithStudent(clas, username): s => WithMyOtherClasses(clas): classes => - if s.student.managed - then Ok.page(views.clas.student.move(clas, students, s, classes)) - else Redirect(routes.Clas.studentShow(clas.id, s.user.username)) + Ok.page(views.clas.student.move(clas, students, s, classes)) } def studentMovePost(id: ClasId, username: UserStr, to: ClasId) = SecureBody(_.Teacher) { ctx ?=> me ?=> WithClassAndStudents(id): (clas, students) => WithStudent(clas, username): s => - Redirect(routes.Clas.show(clas.id)) + WithClass(to): toClas => + (env.clas.api.student + .createCopy(toClas, s, me) >> + env.clas.api.student.closeAccount(s)) + .inject(Redirect(routes.Clas.show(clas.id))) } def becomeTeacher = AuthBody { ctx ?=> me ?=> diff --git a/modules/clas/src/main/ClasApi.scala b/modules/clas/src/main/ClasApi.scala index 94404a085ef2c..015fd51e44d3e 100644 --- a/modules/clas/src/main/ClasApi.scala +++ b/modules/clas/src/main/ClasApi.scala @@ -10,6 +10,8 @@ import lila.core.id.{ ClasId, ClasInviteId, StudentId } import lila.core.msg.MsgApi import lila.db.dsl.{ *, given } import lila.rating.{ Perf, PerfType, UserPerfs } +import lila.core.user.Me.userId +import lila.clas.Student.WithUser final class ClasApi( colls: ClasColls, @@ -258,6 +260,19 @@ final class ClasApi( sendWelcomeMessage(teacher.id, user, clas)).inject(Student.WithPassword(student, password)) } + def createCopy( + clas: Clas, + s: WithUser, + teacher: Me + ): Fu[Option[Student]] = + val stu = Student.make(s.user, clas, teacher.userId, s.student.realName, s.student.managed) + colls.student.insert + .one(stu) + .inject(stu.some) + .recoverWith(lila.db.recoverDuplicateKey { _ => + student.get(clas, s.user.id) + }) + def manyCreate( clas: Clas, data: ClasForm.ManyNewStudent, From c1ad04ae2abddbbd2ef6aacc3d6ff30357cd7960 Mon Sep 17 00:00:00 2001 From: YaFred Date: Sun, 15 Dec 2024 01:22:10 +0100 Subject: [PATCH 38/54] useless import --- app/controllers/Clas.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index 430ac37752998..6c71f8f438c50 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -11,7 +11,6 @@ import lila.clas.ClasForm.ClasData import lila.clas.ClasInvite import lila.core.id.{ ClasId, ClasInviteId } import lila.core.security.ClearPassword -import lila.clas.ClasForm.CreateStudent final class Clas(env: Env, authC: Auth) extends LilaController(env): From 460a0a10c33351e02b46410f0e9d3dc6bc15bbf2 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 15 Dec 2024 22:45:26 +0000 Subject: [PATCH 39/54] Use scss logic to handle rating hiding --- app/controllers/Round.scala | 3 +-- app/controllers/User.scala | 4 +--- app/views/game/side.scala | 3 +-- app/views/user/ui.scala | 7 +++---- modules/core/src/main/pref.scala | 1 - modules/pref/src/main/Pref.scala | 9 --------- modules/ui/src/main/helper/GameHelper.scala | 2 +- modules/user/src/main/ui/UserShow.scala | 5 ++--- ui/common/css/component/_mini-game.scss | 3 +++ ui/common/css/component/_power-tip.scss | 3 +++ ui/common/css/component/_user-link.scss | 5 +++++ 11 files changed, 20 insertions(+), 25 deletions(-) diff --git a/app/controllers/Round.scala b/app/controllers/Round.scala index a68db03344c2e..b98c8f803b9e2 100644 --- a/app/controllers/Round.scala +++ b/app/controllers/Round.scala @@ -290,12 +290,11 @@ final class Round( akka.pattern.after(500.millis, env.system.scheduler)(redirection) def mini(gameId: GameId, color: Color) = Open: - val showRating = ctx.pref.showRatingsIn(None, ctx.userId.so(env.round.playing(_)))(using ctx.myId) FoundSnip( env.round.proxyRepo .povIfPresent(gameId, color) .orElse(env.game.gameRepo.pov(gameId, color)) - )(pov => Snippet(views.game.mini(pov, showRating = showRating))) + )(pov => Snippet(views.game.mini(pov))) def miniFullId(fullId: GameFullId) = Open: FoundSnip(env.round.proxyRepo.povIfPresent(fullId).orElse(env.game.gameRepo.pov(fullId))): pov => diff --git a/app/controllers/User.scala b/app/controllers/User.scala index 7896ace2e9f1a..a2cdadbe12740 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -179,10 +179,8 @@ final class User( negotiate( html = ctx.isnt(user).so(currentlyPlaying(user.user)).flatMap { pov => val ping = env.socket.isOnline.exec(user.id).so(env.socket.getLagRating(user.id)) - val showRating = - ctx.pref.showRatingsIn(pov.map(_.game), ctx.userId.so(env.round.playing(_))) Ok.snip( - views.user.mini(user, pov, blocked, followable, relation, ping, crosstable, showRating) + views.user.mini(user, pov, blocked, followable, relation, ping, crosstable) ).map(_.withHeaders(CACHE_CONTROL -> "max-age=5")) }, json = diff --git a/app/views/game/side.scala b/app/views/game/side.scala index 29a970cfc72a9..d68b06d89fa31 100644 --- a/app/views/game/side.scala +++ b/app/views/game/side.scala @@ -82,8 +82,7 @@ object side: p, withOnline = false, withDiff = true, - withBerserk = true, - withRating = ctx.pref.showRatingsIn(game.some, false) + withBerserk = true ) ), tour.flatMap(_.teamVs).map(_.teams(p.color)).map { diff --git a/app/views/user/ui.scala b/app/views/user/ui.scala index a96058d76a89d..34a5c73a4b9dc 100644 --- a/app/views/user/ui.scala +++ b/app/views/user/ui.scala @@ -18,8 +18,7 @@ def mini( followable: Boolean, relation: Option[lila.relation.Relation], ping: Option[Int], - ct: Option[lila.game.Crosstable], - showRating: Boolean + ct: Option[lila.game.Crosstable] )(using ctx: Context) = val rel = views.relation.mini(u.id, blocked, followable, relation) def crosstable(myId: UserId) = ct @@ -34,11 +33,11 @@ def mini( val opponent = ~cross.showOpponentScore(myId) s"""${cross.showScore(myId)} - $opponent""" ) - val playing = playingGame.map(views.game.mini(_, showRating = showRating)) + val playing = playingGame.map(views.game.mini(_)) def userMarks = views.mod.user.userMarks(u.user, None) val flag = u.profileOrDefault.flagInfo val perfs = u.perfs.best8Perfs - show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks, showRating) + show.ui.mini(u, playing, blocked, followable, ping, rel, crosstable, flag, perfs, userMarks) val perfStat = lila.perfStat.PerfStatUi(helpers)(views.user.bits.communityMenu("ratings")) def perfStatPage(data: PerfStatData, ratingChart: Option[SafeJsonStr])(using diff --git a/modules/core/src/main/pref.scala b/modules/core/src/main/pref.scala index 312f4fea7ee24..bc2a2a26c0cc4 100644 --- a/modules/core/src/main/pref.scala +++ b/modules/core/src/main/pref.scala @@ -25,7 +25,6 @@ trait Pref: def hasVoice: Boolean def hideRatingsInGame: Boolean def showRatings: Boolean - def showRatingsIn(game: Option[Game], amPlaying: Boolean)(using Option[MyId]): Boolean def animationMillis: Int def animationMillisForSpeedPuzzles: Int def pieceNotationIsLetter: Boolean diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 54f6d02d81b2a..fc9aebf0d083e 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -95,15 +95,6 @@ case class Pref( def showRatings = ratings != Ratings.NO def hideRatingsInGame = ratings == Ratings.EXCEPT_GAME - def showRatingsIn(game: Option[lila.core.game.Game], amPlaying: Boolean)(using - myId: Option[MyId] - ): Boolean = - if ratings == Ratings.EXCEPT_GAME - then - game.fold(!amPlaying): g => - !g.playable || !myId.exists(me => g.userIds.has(me.id)) - else ratings == Ratings.YES - def is2d = !is3d def agree = copy(agreement = Agreement.current) diff --git a/modules/ui/src/main/helper/GameHelper.scala b/modules/ui/src/main/helper/GameHelper.scala index 090515fabfb06..a44a64ba800ad 100644 --- a/modules/ui/src/main/helper/GameHelper.scala +++ b/modules/ui/src/main/helper/GameHelper.scala @@ -48,7 +48,7 @@ trait GameHelper: user.name, user.flair.map(userFlair), withRating.option( - frag( + span(cls := "rating")( " (", player.rating.fold(frag("?")): rating => if player.provisional.yes then diff --git a/modules/user/src/main/ui/UserShow.scala b/modules/user/src/main/ui/UserShow.scala index 134f4838198a5..8237e971affda 100644 --- a/modules/user/src/main/ui/UserShow.scala +++ b/modules/user/src/main/ui/UserShow.scala @@ -33,8 +33,7 @@ final class UserShow(helpers: Helpers, bits: UserBits): crosstable: UserId => Option[Frag], flag: Option[Flag], best8Perfs: List[PerfKey], - userMarks: => Frag, - showRating: Boolean = true + userMarks: => Frag )(using ctx: Context) = frag( div(cls := "upt__info")( @@ -56,7 +55,7 @@ final class UserShow(helpers: Helpers, bits: UserBits): if u.lame && ctx.isnt(u) && !Granter.opt(_.UserModView) then div(cls := "upt__info__warning")(trans.site.thisAccountViolatedTos()) else - showRating.option: + ctx.pref.showRatings.option: div(cls := "upt__info__ratings")(best8Perfs.map(showPerfRating(u.perfs, _))) ), ctx.userId.map: myId => diff --git a/ui/common/css/component/_mini-game.scss b/ui/common/css/component/_mini-game.scss index 5a17cd71cf689..5f419bf712ce6 100644 --- a/ui/common/css/component/_mini-game.scss +++ b/ui/common/css/component/_mini-game.scss @@ -44,6 +44,9 @@ margin-inline-start: 1ch; font-size: 0.9em; + body.no-rating & { + display: none; + } } &__clock { diff --git a/ui/common/css/component/_power-tip.scss b/ui/common/css/component/_power-tip.scss index 29066ac33ddc1..b46e114d311b7 100644 --- a/ui/common/css/component/_power-tip.scss +++ b/ui/common/css/component/_power-tip.scss @@ -67,6 +67,9 @@ padding: 2px 3px; text-align: left; } + body.no-rating & { + display: none; + } } &__warning { diff --git a/ui/common/css/component/_user-link.scss b/ui/common/css/component/_user-link.scss index 0e46ff4907ae6..5b43bb0856970 100644 --- a/ui/common/css/component/_user-link.scss +++ b/ui/common/css/component/_user-link.scss @@ -47,6 +47,11 @@ content: $licon-Agent; } } + .rating { + body.no-rating & { + display: none; + } + } } a.user-link:hover { From 3387b14b329ad0931de8b64ff3a2eba0f996ed96 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 15 Dec 2024 22:55:52 +0000 Subject: [PATCH 40/54] Remove unnecessary showRating argument form GameUI mini --- modules/game/src/main/ui/GameUi.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index 3dd0e6d27279c..be1a3dd0097c9 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -25,14 +25,13 @@ final class GameUi(helpers: Helpers): ownerLink: Boolean = false, tv: Boolean = false, withLink: Boolean = true, - showRating: Boolean = true )(using ctx: Context ): Tag = renderMini( pov, withLink.option(gameLink(pov.game, pov.color, ownerLink, tv)), - showRatings = showRating + showRatings = ctx.pref.showRatings ) def noCtx(pov: Pov, tv: Boolean = false, channelKey: Option[String] = None): Tag = From 178eee1a6489e4fb2dd17d964d732543eefdfa62 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 15 Dec 2024 23:00:13 +0000 Subject: [PATCH 41/54] Fix formatting --- modules/game/src/main/ui/GameUi.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/game/src/main/ui/GameUi.scala b/modules/game/src/main/ui/GameUi.scala index be1a3dd0097c9..b523a95e87a74 100644 --- a/modules/game/src/main/ui/GameUi.scala +++ b/modules/game/src/main/ui/GameUi.scala @@ -24,7 +24,7 @@ final class GameUi(helpers: Helpers): pov: Pov, ownerLink: Boolean = false, tv: Boolean = false, - withLink: Boolean = true, + withLink: Boolean = true )(using ctx: Context ): Tag = From e41563bd7e402450b23223092c8f0150db9eff09 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sun, 15 Dec 2024 23:19:41 +0000 Subject: [PATCH 42/54] Use scss for hiding the side UI rating in game --- modules/round/src/main/JsonView.scala | 1 - ui/round/css/_user.scss | 3 +++ ui/round/src/interfaces.ts | 1 - ui/round/src/view/user.ts | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/round/src/main/JsonView.scala b/modules/round/src/main/JsonView.scala index 0ef2f54e5fcbe..bf7dc549e2de4 100644 --- a/modules/round/src/main/JsonView.scala +++ b/modules/round/src/main/JsonView.scala @@ -116,7 +116,6 @@ final class JsonView( .add("confirmResign" -> (!flags.nvui && pref.confirmResign == Pref.ConfirmResign.YES)) .add("keyboardMove" -> (!flags.nvui && pref.hasKeyboardMove)) .add("voiceMove" -> (!flags.nvui && pref.hasVoice)) - .add("hideRatingsInGame" -> pref.hideRatingsInGame) .add("rookCastle" -> (pref.rookCastle == Pref.RookCastle.YES)) .add("highlight" -> pref.highlight) .add("destination" -> pref.destination) diff --git a/ui/round/css/_user.scss b/ui/round/css/_user.scss index 9f557e045f141..d0b3512c6113a 100644 --- a/ui/round/css/_user.scss +++ b/ui/round/css/_user.scss @@ -26,6 +26,9 @@ margin: 0 0.25em 0 0.3em; color: $c-font-dim; letter-spacing: -0.5px; + body.no-rating & { + display: none; + } } .line { diff --git a/ui/round/src/interfaces.ts b/ui/round/src/interfaces.ts index 514ceb269ba86..16c4662476874 100644 --- a/ui/round/src/interfaces.ts +++ b/ui/round/src/interfaces.ts @@ -187,7 +187,6 @@ export interface Pref { highlight: boolean; is3d: boolean; keyboardMove: boolean; - hideRatingsInGame: boolean; voiceMove: boolean; moveEvent: Prefs.MoveEvent; ratings: boolean; diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 5a47e68edc51d..561670e1b1ea0 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -10,7 +10,6 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi user = player.user, perf = (user?.perfs || {})[d.game.perf], rating = player.rating || perf?.rating, - showRating = d.pref.hideRatingsInGame ? !ctrl.isPlaying() : !!rating, signal = user?.id === d.opponent.user?.id ? d.opponentSignal : undefined; if (user) { @@ -43,7 +42,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi line: false, }), !!signal && signalBars(signal), - showRating && h('rating', rating + (player.provisional ? '?' : '')), + !!rating && h('rating', rating + (player.provisional ? '?' : '')), !!rating && ratingDiff(player), player.engine && h('span', { From 7438d5f816ad55e909c89353f66a2d7d59406342 Mon Sep 17 00:00:00 2001 From: YaFred Date: Tue, 17 Dec 2024 02:59:00 +0100 Subject: [PATCH 43/54] even non managed student can be moved to another class --- modules/clas/src/main/ui/StudentFormUi.scala | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/clas/src/main/ui/StudentFormUi.scala b/modules/clas/src/main/ui/StudentFormUi.scala index a764181272e57..350ff656f89c2 100644 --- a/modules/clas/src/main/ui/StudentFormUi.scala +++ b/modules/clas/src/main/ui/StudentFormUi.scala @@ -217,6 +217,13 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi cls := "button button-empty button-red", title := trans.clas.closeDesc1.txt() )(trans.clas.closeStudent()) + ), + (!s.student.managed).option( + a( + href := routes.Clas.studentMove(clas.id, s.user.username), + cls := "button button-empty", + title := "Move" + )("Move") ) ) ) From 7213ee2583430b12d52e97ecbf75bae4ac8480e5 Mon Sep 17 00:00:00 2001 From: YaFred Date: Wed, 18 Dec 2024 01:50:43 +0100 Subject: [PATCH 44/54] new translations --- modules/clas/src/main/ui/StudentFormUi.scala | 8 ++++---- modules/clas/src/main/ui/StudentUi.scala | 4 ++-- modules/coreI18n/src/main/key.scala | 3 +++ translation/source/class.xml | 3 +++ ui/@types/lichess/i18n.d.ts | 6 ++++++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/clas/src/main/ui/StudentFormUi.scala b/modules/clas/src/main/ui/StudentFormUi.scala index 350ff656f89c2..ea0016375b734 100644 --- a/modules/clas/src/main/ui/StudentFormUi.scala +++ b/modules/clas/src/main/ui/StudentFormUi.scala @@ -222,8 +222,8 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi a( href := routes.Clas.studentMove(clas.id, s.user.username), cls := "button button-empty", - title := "Move" - )("Move") + title := trans.clas.move.txt() + )(trans.clas.move()) ) ) ) @@ -272,7 +272,7 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi )( form3.submit(aClass.name, icon = Icon.Target.some)( cls := "yes-no-confirm button-blue button-empty", - title := "Move to " + aClass.name + title := trans.clas.moveToClass.txt(aClass.name) ) ) ) @@ -280,7 +280,7 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi frag( studentUi.top(clas, s), div(cls := "box__pad")( - h2("Move to another class"), + h2(trans.clas.moveToAnotherClass()), classForms, form3.actions( a(href := routes.Clas.studentShow(clas.id, s.user.username))(trans.site.cancel()) diff --git a/modules/clas/src/main/ui/StudentUi.scala b/modules/clas/src/main/ui/StudentUi.scala index 85407d8da9df7..34637847d8ba2 100644 --- a/modules/clas/src/main/ui/StudentUi.scala +++ b/modules/clas/src/main/ui/StudentUi.scala @@ -68,8 +68,8 @@ final class StudentUi(helpers: Helpers, clasUi: ClasUi)(using NetDomain): a( href := routes.Clas.studentMove(clas.id, s.user.username), cls := "button button-empty", - title := "Move" - )("Move") + title := trans.clas.move.txt() + )(trans.clas.move()) ) ) ) diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index e4179c5b93215..5107ed9cfa439 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -330,6 +330,9 @@ object I18nKey: val `anInvitationHasBeenSentToX`: I18nKey = "class:anInvitationHasBeenSentToX" val `xAlreadyHasAPendingInvitation`: I18nKey = "class:xAlreadyHasAPendingInvitation" val `xIsAKidAccountWarning`: I18nKey = "class:xIsAKidAccountWarning" + val `move`: I18nKey = "class:move" + val `moveToClass`: I18nKey = "class:moveToClass" + val `moveToAnotherClass`: I18nKey = "class:moveToAnotherClass" val `nbPendingInvitations`: I18nKey = "class:nbPendingInvitations" val `nbTeachers`: I18nKey = "class:nbTeachers" val `nbStudents`: I18nKey = "class:nbStudents" diff --git a/translation/source/class.xml b/translation/source/class.xml index c037cb3407514..afc4bc8ac5460 100644 --- a/translation/source/class.xml +++ b/translation/source/class.xml @@ -114,4 +114,7 @@ It will display a horizontal line. An invitation has been sent to %s %s already has a pending invitation %1$s is a kid account and can't receive your message. You must give them the invitation URL manually: %2$s + Move + Move to %s + Move to another class diff --git a/ui/@types/lichess/i18n.d.ts b/ui/@types/lichess/i18n.d.ts index 8df1de4f1f739..2a524053f58db 100644 --- a/ui/@types/lichess/i18n.d.ts +++ b/ui/@types/lichess/i18n.d.ts @@ -515,6 +515,12 @@ interface I18n { maxStudentsNote: I18nFormat; /** Message all students about new class material */ messageAllStudents: string; + /** Move */ + move: string; + /** Move to another class */ + moveToAnotherClass: string; + /** Move to %s */ + moveToClass: I18nFormat; /** You can also %s to create multiple Lichess accounts from a list of student names. */ multipleAccsFormDescription: I18nFormat; /** N/A */ From ad9ce9c0d3b9f1bc96c9861c47f08981127c0ec3 Mon Sep 17 00:00:00 2001 From: YaFred Date: Wed, 18 Dec 2024 02:12:55 +0100 Subject: [PATCH 45/54] missing translations --- modules/clas/src/main/ui/DashboardUi.scala | 4 ++-- modules/coreI18n/src/main/key.scala | 3 +++ translation/source/class.xml | 3 +++ ui/@types/lichess/i18n.d.ts | 6 ++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/clas/src/main/ui/DashboardUi.scala b/modules/clas/src/main/ui/DashboardUi.scala index 7d36bbe73c43e..68beb2432d016 100644 --- a/modules/clas/src/main/ui/DashboardUi.scala +++ b/modules/clas/src/main/ui/DashboardUi.scala @@ -139,11 +139,11 @@ final class DashboardUi(helpers: Helpers, ui: ClasUi)(using NetDomain): tr( td(userIdLink(i.userId.some)), td(i.realName), - td(if i.accepted.has(false) then "Declined" else "Pending"), + td(if i.accepted.has(false) then trans.clas.declined.txt() else trans.clas.pending.txt()), td(momentFromNow(i.created.at)), td: postForm(action := routes.Clas.invitationRevoke(i.id)): - submitButton(cls := "button button-red button-empty")("Revoke") + submitButton(cls := "button button-red button-empty")(trans.clas.revoke()) ) ) val archivedBox = diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index 5107ed9cfa439..33b1e7894f0aa 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -282,6 +282,9 @@ object I18nKey: val `welcomeToClass`: I18nKey = "class:welcomeToClass" val `invitationToClass`: I18nKey = "class:invitationToClass" val `clickToViewInvitation`: I18nKey = "class:clickToViewInvitation" + val `pending`: I18nKey = "class:pending" + val `declined`: I18nKey = "class:declined" + val `revoke`: I18nKey = "class:revoke" val `onlyVisibleToTeachers`: I18nKey = "class:onlyVisibleToTeachers" val `lastActiveDate`: I18nKey = "class:lastActiveDate" val `managed`: I18nKey = "class:managed" diff --git a/translation/source/class.xml b/translation/source/class.xml index afc4bc8ac5460..4d4997e2ea964 100644 --- a/translation/source/class.xml +++ b/translation/source/class.xml @@ -57,6 +57,9 @@ Here is the link to access the class. One pending invitation %s pending invitations + Pending + Declined + Revoke Only visible to the class teachers Active Managed diff --git a/ui/@types/lichess/i18n.d.ts b/ui/@types/lichess/i18n.d.ts index 2a524053f58db..3a842f58f4f50 100644 --- a/ui/@types/lichess/i18n.d.ts +++ b/ui/@types/lichess/i18n.d.ts @@ -471,6 +471,8 @@ interface I18n { createMultipleAccounts: string; /** Only create accounts for real students. Do not use this to make multiple accounts for yourself. You would get banned. */ createStudentWarning: string; + /** Declined */ + declined: string; /** Edit news */ editNews: string; /** Features */ @@ -561,6 +563,8 @@ interface I18n { overview: string; /** Password: %s */ passwordX: I18nFormat; + /** Pending */ + pending: string; /** Private. Will never be shown outside the class. Helps you remember who the student is. */ privateWillNeverBeShown: string; /** Progress */ @@ -589,6 +593,8 @@ interface I18n { reopen: string; /** Reset password */ resetPassword: string; + /** Revoke */ + revoke: string; /** Send a message to all students. */ sendAMessage: string; /** Student: %1$s */ From 8ce33077bb0ce8765889261a3beacf63720d9cb6 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 09:11:03 +0100 Subject: [PATCH 46/54] sbt scalafmtAll --- modules/clas/src/main/ui/DashboardUi.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/clas/src/main/ui/DashboardUi.scala b/modules/clas/src/main/ui/DashboardUi.scala index 68beb2432d016..884a26b461c57 100644 --- a/modules/clas/src/main/ui/DashboardUi.scala +++ b/modules/clas/src/main/ui/DashboardUi.scala @@ -139,7 +139,9 @@ final class DashboardUi(helpers: Helpers, ui: ClasUi)(using NetDomain): tr( td(userIdLink(i.userId.some)), td(i.realName), - td(if i.accepted.has(false) then trans.clas.declined.txt() else trans.clas.pending.txt()), + td( + if i.accepted.has(false) then trans.clas.declined.txt() else trans.clas.pending.txt() + ), td(momentFromNow(i.created.at)), td: postForm(action := routes.Clas.invitationRevoke(i.id)): From f56652d25853cb2e3cdde7e3f90e2265e5f11336 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 09:32:19 +0100 Subject: [PATCH 47/54] tweak student move controller code, no functional change --- app/controllers/Clas.scala | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index 6c71f8f438c50..4957b98091831 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -475,18 +475,21 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): def studentMove(id: ClasId, username: UserStr) = Secure(_.Teacher) { ctx ?=> me ?=> WithClassAndStudents(id): (clas, students) => WithStudent(clas, username): s => - WithMyOtherClasses(clas): classes => - Ok.page(views.clas.student.move(clas, students, s, classes)) + for + classes <- env.clas.api.clas.of(me) + others = classes.filter(_.id != clas.id) + res <- Ok.page(views.clas.student.move(clas, students, s, others)) + yield res } def studentMovePost(id: ClasId, username: UserStr, to: ClasId) = SecureBody(_.Teacher) { ctx ?=> me ?=> WithClassAndStudents(id): (clas, students) => WithStudent(clas, username): s => WithClass(to): toClas => - (env.clas.api.student - .createCopy(toClas, s, me) >> - env.clas.api.student.closeAccount(s)) - .inject(Redirect(routes.Clas.show(clas.id))) + for + _ <- env.clas.api.student.createCopy(toClas, s, me) + _ <- env.clas.api.student.closeAccount(s) + yield Redirect(routes.Clas.show(clas.id)) } def becomeTeacher = AuthBody { ctx ?=> me ?=> @@ -540,14 +543,6 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): WithClass(clasId): c => env.clas.api.student.activeOf(c).flatMap { f(c, _) } - private def WithMyOtherClasses(clas: lila.clas.Clas)( - f: (List[lila.clas.Clas]) => Fu[Result] - )(using teacher: Me): Fu[Result] = - val res = - for classes <- env.clas.api.clas.of(teacher) - yield classes.filter(_.id != clas.id) - res.flatMap(f) - private def WithStudent(clas: lila.clas.Clas, username: UserStr)( f: lila.clas.Student.WithUser => Fu[Result] )(using Context): Fu[Result] = From c653943177bd0a429c7c600248ac763a73e55482 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 09:42:34 +0100 Subject: [PATCH 48/54] move implementation to ClasApi --- app/controllers/Clas.scala | 4 +--- modules/clas/src/main/ClasApi.scala | 14 ++++++-------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index 4957b98091831..5b58894696519 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -486,9 +486,7 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): WithClassAndStudents(id): (clas, students) => WithStudent(clas, username): s => WithClass(to): toClas => - for - _ <- env.clas.api.student.createCopy(toClas, s, me) - _ <- env.clas.api.student.closeAccount(s) + for _ <- env.clas.api.student.move(s, toClas) yield Redirect(routes.Clas.show(clas.id)) } diff --git a/modules/clas/src/main/ClasApi.scala b/modules/clas/src/main/ClasApi.scala index 015fd51e44d3e..3c4ec90b6b9bf 100644 --- a/modules/clas/src/main/ClasApi.scala +++ b/modules/clas/src/main/ClasApi.scala @@ -260,18 +260,16 @@ final class ClasApi( sendWelcomeMessage(teacher.id, user, clas)).inject(Student.WithPassword(student, password)) } - def createCopy( - clas: Clas, - s: WithUser, - teacher: Me - ): Fu[Option[Student]] = - val stu = Student.make(s.user, clas, teacher.userId, s.student.realName, s.student.managed) - colls.student.insert + def move(s: WithUser, toClas: Clas)(using teacher: Me): Fu[Option[Student]] = for + _ <- closeAccount(s) + stu = Student.make(s.user, toClas, teacher.userId, s.student.realName, s.student.managed) + moved <- colls.student.insert .one(stu) .inject(stu.some) .recoverWith(lila.db.recoverDuplicateKey { _ => - student.get(clas, s.user.id) + student.get(toClas, s.user.id) }) + yield moved def manyCreate( clas: Clas, From 6f96517ba8527d0515195c298d27eecc83b72dbd Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 09:44:18 +0100 Subject: [PATCH 49/54] visual success feedback after moving a student --- app/controllers/Clas.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index 5b58894696519..ce44029ffc7e1 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -487,7 +487,7 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): WithStudent(clas, username): s => WithClass(to): toClas => for _ <- env.clas.api.student.move(s, toClas) - yield Redirect(routes.Clas.show(clas.id)) + yield Redirect(routes.Clas.show(clas.id)).flashSuccess } def becomeTeacher = AuthBody { ctx ?=> me ?=> From 9ebe29d0735720eb68aaa3fba6748d5c1c29a522 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 09:51:28 +0100 Subject: [PATCH 50/54] don't override student notes and metadata when moving them --- modules/clas/src/main/ClasApi.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/clas/src/main/ClasApi.scala b/modules/clas/src/main/ClasApi.scala index 3c4ec90b6b9bf..b37969700376e 100644 --- a/modules/clas/src/main/ClasApi.scala +++ b/modules/clas/src/main/ClasApi.scala @@ -10,8 +10,6 @@ import lila.core.id.{ ClasId, ClasInviteId, StudentId } import lila.core.msg.MsgApi import lila.db.dsl.{ *, given } import lila.rating.{ Perf, PerfType, UserPerfs } -import lila.core.user.Me.userId -import lila.clas.Student.WithUser final class ClasApi( colls: ClasColls, @@ -260,9 +258,9 @@ final class ClasApi( sendWelcomeMessage(teacher.id, user, clas)).inject(Student.WithPassword(student, password)) } - def move(s: WithUser, toClas: Clas)(using teacher: Me): Fu[Option[Student]] = for + def move(s: Student.WithUser, toClas: Clas)(using teacher: Me): Fu[Option[Student]] = for _ <- closeAccount(s) - stu = Student.make(s.user, toClas, teacher.userId, s.student.realName, s.student.managed) + stu = s.student.copy(id = Student.makeId(s.user.id, toClas.id), clasId = toClas.id) moved <- colls.student.insert .one(stu) .inject(stu.some) From 0c12c471c54181f73c580dae1c74a6f8adfc6c57 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 10:00:17 +0100 Subject: [PATCH 51/54] scala code golf --- modules/clas/src/main/ui/StudentFormUi.scala | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/modules/clas/src/main/ui/StudentFormUi.scala b/modules/clas/src/main/ui/StudentFormUi.scala index ea0016375b734..94df46d617738 100644 --- a/modules/clas/src/main/ui/StudentFormUi.scala +++ b/modules/clas/src/main/ui/StudentFormUi.scala @@ -264,18 +264,13 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi cls := "student-show student-edit" ): - val classForms: Frag = - for (aClass <- otherClasses) - yield ( - postForm( - action := routes.Clas.studentMovePost(clas.id, s.student.userId, aClass.id) - )( - form3.submit(aClass.name, icon = Icon.Target.some)( - cls := "yes-no-confirm button-blue button-empty", - title := trans.clas.moveToClass.txt(aClass.name) - ) - ) + val classForms: Frag = otherClasses.map: toClass => + postForm(action := routes.Clas.studentMovePost(clas.id, s.student.userId, toClass.id))( + form3.submit(toClass.name, icon = Icon.InternalArrow.some)( + cls := "yes-no-confirm button-blue button-empty", + title := trans.clas.moveToClass.txt(toClass.name) ) + ) frag( studentUi.top(clas, s), From 3c2aed5f4f2a5b55e347019f488ffcab239488d9 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 10:07:38 +0100 Subject: [PATCH 52/54] avoid adding unnecessary translation --- modules/clas/src/main/ui/DashboardUi.scala | 2 +- modules/coreI18n/src/main/key.scala | 1 - translation/source/class.xml | 1 - ui/@types/lichess/i18n.d.ts | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/clas/src/main/ui/DashboardUi.scala b/modules/clas/src/main/ui/DashboardUi.scala index 884a26b461c57..532c19eac7f56 100644 --- a/modules/clas/src/main/ui/DashboardUi.scala +++ b/modules/clas/src/main/ui/DashboardUi.scala @@ -145,7 +145,7 @@ final class DashboardUi(helpers: Helpers, ui: ClasUi)(using NetDomain): td(momentFromNow(i.created.at)), td: postForm(action := routes.Clas.invitationRevoke(i.id)): - submitButton(cls := "button button-red button-empty")(trans.clas.revoke()) + submitButton(cls := "button button-red button-empty")(trans.site.delete()) ) ) val archivedBox = diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index 33b1e7894f0aa..28538e522c020 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -284,7 +284,6 @@ object I18nKey: val `clickToViewInvitation`: I18nKey = "class:clickToViewInvitation" val `pending`: I18nKey = "class:pending" val `declined`: I18nKey = "class:declined" - val `revoke`: I18nKey = "class:revoke" val `onlyVisibleToTeachers`: I18nKey = "class:onlyVisibleToTeachers" val `lastActiveDate`: I18nKey = "class:lastActiveDate" val `managed`: I18nKey = "class:managed" diff --git a/translation/source/class.xml b/translation/source/class.xml index 4d4997e2ea964..34a02207ea46b 100644 --- a/translation/source/class.xml +++ b/translation/source/class.xml @@ -59,7 +59,6 @@ Here is the link to access the class. Pending Declined - Revoke Only visible to the class teachers Active Managed diff --git a/ui/@types/lichess/i18n.d.ts b/ui/@types/lichess/i18n.d.ts index 3a842f58f4f50..7b93baaf32cf9 100644 --- a/ui/@types/lichess/i18n.d.ts +++ b/ui/@types/lichess/i18n.d.ts @@ -593,8 +593,6 @@ interface I18n { reopen: string; /** Reset password */ resetPassword: string; - /** Revoke */ - revoke: string; /** Send a message to all students. */ sendAMessage: string; /** Student: %1$s */ From b307b1d9ab061b8a454c1ecd595fda1d90f1fabe Mon Sep 17 00:00:00 2001 From: YaFred Date: Wed, 18 Dec 2024 16:56:40 +0100 Subject: [PATCH 53/54] remove superfluous translation --- modules/clas/src/main/ui/StudentFormUi.scala | 5 ++--- modules/clas/src/main/ui/StudentUi.scala | 5 ++--- modules/coreI18n/src/main/key.scala | 1 - translation/source/class.xml | 1 - ui/@types/lichess/i18n.d.ts | 2 -- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/modules/clas/src/main/ui/StudentFormUi.scala b/modules/clas/src/main/ui/StudentFormUi.scala index 94df46d617738..7bf632217891e 100644 --- a/modules/clas/src/main/ui/StudentFormUi.scala +++ b/modules/clas/src/main/ui/StudentFormUi.scala @@ -221,9 +221,8 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi (!s.student.managed).option( a( href := routes.Clas.studentMove(clas.id, s.user.username), - cls := "button button-empty", - title := trans.clas.move.txt() - )(trans.clas.move()) + cls := "button button-empty" + )(trans.clas.moveToAnotherClass()) ) ) ) diff --git a/modules/clas/src/main/ui/StudentUi.scala b/modules/clas/src/main/ui/StudentUi.scala index 34637847d8ba2..6a13b9e4d3404 100644 --- a/modules/clas/src/main/ui/StudentUi.scala +++ b/modules/clas/src/main/ui/StudentUi.scala @@ -67,9 +67,8 @@ final class StudentUi(helpers: Helpers, clasUi: ClasUi)(using NetDomain): )(trans.clas.release()), a( href := routes.Clas.studentMove(clas.id, s.user.username), - cls := "button button-empty", - title := trans.clas.move.txt() - )(trans.clas.move()) + cls := "button button-empty" + )(trans.clas.moveToAnotherClass()) ) ) ) diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index 28538e522c020..ef228129bf5f9 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -332,7 +332,6 @@ object I18nKey: val `anInvitationHasBeenSentToX`: I18nKey = "class:anInvitationHasBeenSentToX" val `xAlreadyHasAPendingInvitation`: I18nKey = "class:xAlreadyHasAPendingInvitation" val `xIsAKidAccountWarning`: I18nKey = "class:xIsAKidAccountWarning" - val `move`: I18nKey = "class:move" val `moveToClass`: I18nKey = "class:moveToClass" val `moveToAnotherClass`: I18nKey = "class:moveToAnotherClass" val `nbPendingInvitations`: I18nKey = "class:nbPendingInvitations" diff --git a/translation/source/class.xml b/translation/source/class.xml index 34a02207ea46b..5c2bccacb8046 100644 --- a/translation/source/class.xml +++ b/translation/source/class.xml @@ -116,7 +116,6 @@ It will display a horizontal line. An invitation has been sent to %s %s already has a pending invitation %1$s is a kid account and can't receive your message. You must give them the invitation URL manually: %2$s - Move Move to %s Move to another class diff --git a/ui/@types/lichess/i18n.d.ts b/ui/@types/lichess/i18n.d.ts index 7b93baaf32cf9..24829dbb28f57 100644 --- a/ui/@types/lichess/i18n.d.ts +++ b/ui/@types/lichess/i18n.d.ts @@ -517,8 +517,6 @@ interface I18n { maxStudentsNote: I18nFormat; /** Message all students about new class material */ messageAllStudents: string; - /** Move */ - move: string; /** Move to another class */ moveToAnotherClass: string; /** Move to %s */ From dda89a4999ce2fc687553b3f32e3ad91811b1f93 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 18 Dec 2024 17:30:30 +0100 Subject: [PATCH 54/54] student move button always in the same place --- modules/clas/src/main/ui/StudentFormUi.scala | 10 ++++------ modules/clas/src/main/ui/StudentUi.scala | 6 +----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/modules/clas/src/main/ui/StudentFormUi.scala b/modules/clas/src/main/ui/StudentFormUi.scala index 7bf632217891e..38095a7e77b63 100644 --- a/modules/clas/src/main/ui/StudentFormUi.scala +++ b/modules/clas/src/main/ui/StudentFormUi.scala @@ -218,12 +218,10 @@ final class StudentFormUi(helpers: Helpers, clasUi: ClasUi, studentUi: StudentUi title := trans.clas.closeDesc1.txt() )(trans.clas.closeStudent()) ), - (!s.student.managed).option( - a( - href := routes.Clas.studentMove(clas.id, s.user.username), - cls := "button button-empty" - )(trans.clas.moveToAnotherClass()) - ) + a( + href := routes.Clas.studentMove(clas.id, s.user.username), + cls := "button button-empty" + )(trans.clas.moveToAnotherClass()) ) ) ) diff --git a/modules/clas/src/main/ui/StudentUi.scala b/modules/clas/src/main/ui/StudentUi.scala index 6a13b9e4d3404..e54f41201eb6c 100644 --- a/modules/clas/src/main/ui/StudentUi.scala +++ b/modules/clas/src/main/ui/StudentUi.scala @@ -64,11 +64,7 @@ final class StudentUi(helpers: Helpers, clasUi: ClasUi)(using NetDomain): href := routes.Clas.studentRelease(clas.id, s.user.username), cls := "button button-empty", title := trans.clas.upgradeFromManaged.txt() - )(trans.clas.release()), - a( - href := routes.Clas.studentMove(clas.id, s.user.username), - cls := "button button-empty" - )(trans.clas.moveToAnotherClass()) + )(trans.clas.release()) ) ) )