From af4b7b75116614cc409e760918b1f13b2a851d84 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 23 Dec 2024 02:12:55 +0000 Subject: [PATCH 01/20] Add a toggle to show or hide boards results --- ui/analyse/src/study/multiBoard.ts | 52 +++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index b388e9108658b..ec89b2b33f4a8 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -17,6 +17,7 @@ import { Chessground as makeChessground } from 'chessground'; export class MultiBoardCtrl { playing: Toggle; + showResults: Toggle; teamSelect: Prop = prop(''); page: number = 1; maxPerPageStorage = storage.make('study.multiBoard.maxPerPage'); @@ -28,6 +29,7 @@ export class MultiBoardCtrl { readonly redraw: () => void, ) { this.playing = toggle(false, this.redraw); + this.showResults = toggle(true, this.redraw); if (this.initialTeamSelect) this.onChapterChange(this.initialTeamSelect); } @@ -102,6 +104,7 @@ export function view(ctrl: MultiBoardCtrl, study: StudyCtrl): MaybeVNode { ctrl.multiCloudEval && h('label.eval', [renderEvalToggle(ctrl.multiCloudEval), i18n.study.showEvalBar]), renderPlayingToggle(ctrl), + renderShowResultsToggle(ctrl), ]), ]), h( @@ -111,7 +114,7 @@ export function view(ctrl: MultiBoardCtrl, study: StudyCtrl): MaybeVNode { insert: gameLinksListener(study.chapterSelect), }, }, - pager.currentPageResults.map(makePreview(baseUrl, study.vm.chapterId, cloudEval)), + pager.currentPageResults.map(makePreview(baseUrl, study.vm.chapterId, cloudEval, ctrl.showResults())), ), ]); } @@ -176,6 +179,15 @@ const renderPlayingToggle = (ctrl: MultiBoardCtrl): MaybeVNode => i18n.study.playing, ]); +const renderShowResultsToggle = (ctrl: MultiBoardCtrl): MaybeVNode => + h('label.results', [ + h('input', { + attrs: { type: 'checkbox', checked: ctrl.showResults() }, + hook: bind('change', e => ctrl.showResults((e.target as HTMLInputElement).checked)), + }), + i18n.study.playing, // CHANGE TO A NEW I18N + ]); + const previewToCgConfig = (cp: ChapterPreview): CgConfig => ({ fen: cp.fen, lastMove: uciToMove(cp.lastMove), @@ -184,8 +196,17 @@ const previewToCgConfig = (cp: ChapterPreview): CgConfig => ({ }); const makePreview = - (roundPath: string, current: ChapterId, cloudEval?: MultiCloudEval) => (preview: ChapterPreview) => { + (roundPath: string, current: ChapterId, cloudEval?: MultiCloudEval, showResults?: boolean) => (preview: ChapterPreview) => { const orientation = preview.orientation || 'white'; + const baseConfig = { + coordinates: false, + viewOnly: true, + orientation, + drawable: { + enabled: false, + visible: false, + }, + } return h( `a.mini-game.is2d.chap-${preview.id}`, { @@ -193,7 +214,7 @@ const makePreview = attrs: gameLinkAttrs(roundPath, preview), }, [ - boardPlayer(preview, CgOpposite(orientation)), + boardPlayer(preview, CgOpposite(orientation), showResults), h('span.cg-gauge', [ cloudEval && verticalEvalGauge(preview, cloudEval), h( @@ -202,30 +223,29 @@ const makePreview = hook: { insert(vnode) { const el = vnode.elm as HTMLElement; - vnode.data!.cg = makeChessground(el, { + vnode.data!.cg = showResults ? makeChessground(el, { ...previewToCgConfig(preview), - coordinates: false, - viewOnly: true, - orientation, - drawable: { - enabled: false, - visible: false, - }, - }); + ...baseConfig, + }) : makeChessground(el, baseConfig); vnode.data!.fen = preview.fen; }, postpatch(old, vnode) { if (old.data!.fen !== preview.fen) { old.data!.cg?.set(previewToCgConfig(preview)); } + // In this case, showResults was set to true but the cg fen is still on the initial pos + if (showResults && old.data!.cg.fen != old.data!.cg.getFen()) { + old.data!.cg.set(previewToCgConfig(preview)) + } vnode.data!.fen = preview.fen; - vnode.data!.cg = old.data!.cg; + const el = vnode.elm as HTMLElement; + vnode.data!.cg = showResults ? old.data!.cg : makeChessground(el, baseConfig); }, }, }), ), ]), - boardPlayer(preview, orientation), + boardPlayer(preview, orientation, showResults), ], ); }; @@ -300,8 +320,8 @@ const computeTimeLeft = (preview: ChapterPreview, color: Color): number | undefi } else return; }; -const boardPlayer = (preview: ChapterPreview, color: Color) => { - const outcome = preview.status && preview.status !== '*' ? preview.status : undefined; +const boardPlayer = (preview: ChapterPreview, color: Color, showResults?: boolean) => { + const outcome = showResults && preview.status && preview.status !== '*' ? preview.status : undefined; const player = preview.players?.[color], score = outcome?.split('-')[color === 'white' ? 0 : 1]; return h('span.mini-game__player', [ From 375400455274834bec167d52149782fd91244036 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 23 Dec 2024 02:13:26 +0000 Subject: [PATCH 02/20] Show or hide results on the relayGames --- ui/analyse/src/study/relay/relayGames.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/analyse/src/study/relay/relayGames.ts b/ui/analyse/src/study/relay/relayGames.ts index 5d7869b6ff828..4ff908b33d99f 100644 --- a/ui/analyse/src/study/relay/relayGames.ts +++ b/ui/analyse/src/study/relay/relayGames.ts @@ -58,7 +58,7 @@ export const gamesList = (study: StudyCtrl, relay: RelayCtrl) => { playerFed(p.fed), h('span.name', [userTitle(p), p.name]), ]), - h(s === '1' ? 'good' : s === '0' ? 'bad' : 'status', [s]), + study.multiBoard.showResults() ? h(s === '1' ? 'good' : s === '0' ? 'bad' : 'status', [s]) : null, ] : [h('span.mini-game__user', h('span.name', 'Unknown player'))], ); From c2b74c8429def38810f749b5ef56027912a99e63 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 23 Dec 2024 02:23:29 +0000 Subject: [PATCH 03/20] Add i18n for the showResults toggle and a basic translation --- modules/coreI18n/src/main/key.scala | 1 + translation/source/study.xml | 1 + ui/@types/lichess/i18n.d.ts | 2 ++ 3 files changed, 4 insertions(+) diff --git a/modules/coreI18n/src/main/key.scala b/modules/coreI18n/src/main/key.scala index a2fff7e4c57d6..d09a8900298df 100644 --- a/modules/coreI18n/src/main/key.scala +++ b/modules/coreI18n/src/main/key.scala @@ -2391,6 +2391,7 @@ object I18nKey: val `allSyncMembersRemainOnTheSamePosition`: I18nKey = "study:allSyncMembersRemainOnTheSamePosition" val `shareChanges`: I18nKey = "study:shareChanges" val `playing`: I18nKey = "study:playing" + val `showResults`: I18nKey = "study:showResults" val `showEvalBar`: I18nKey = "study:showEvalBar" val `first`: I18nKey = "study:first" val `previous`: I18nKey = "study:previous" diff --git a/translation/source/study.xml b/translation/source/study.xml index 1c121d8022f2a..26f595f0d8119 100644 --- a/translation/source/study.xml +++ b/translation/source/study.xml @@ -53,6 +53,7 @@ All SYNC members remain on the same position Share changes with spectators and save them on the server Playing + Results Evaluation bars First Previous diff --git a/ui/@types/lichess/i18n.d.ts b/ui/@types/lichess/i18n.d.ts index 5c27b24b9eebc..f3a9f712271d4 100644 --- a/ui/@types/lichess/i18n.d.ts +++ b/ui/@types/lichess/i18n.d.ts @@ -4857,6 +4857,8 @@ interface I18n { shareChanges: string; /** Evaluation bars */ showEvalBar: string; + /** Results */ + showResults: string; /** Spectator */ spectator: string; /** Start */ From afc39229ab93353746770d3623fbd7814386b3ce Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 23 Dec 2024 02:24:02 +0000 Subject: [PATCH 04/20] Use the correct i18n --- ui/analyse/src/study/multiBoard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index ec89b2b33f4a8..4f11178a18ac0 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -185,7 +185,7 @@ const renderShowResultsToggle = (ctrl: MultiBoardCtrl): MaybeVNode => attrs: { type: 'checkbox', checked: ctrl.showResults() }, hook: bind('change', e => ctrl.showResults((e.target as HTMLInputElement).checked)), }), - i18n.study.playing, // CHANGE TO A NEW I18N + i18n.study.showResults, ]); const previewToCgConfig = (cp: ChapterPreview): CgConfig => ({ From 3ccd7633941d8a8186c1fa97158efa38989597f1 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 23 Dec 2024 02:28:28 +0000 Subject: [PATCH 05/20] Handle css for the new toggle like the others --- ui/analyse/css/study/panel/_multiboard.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/analyse/css/study/panel/_multiboard.scss b/ui/analyse/css/study/panel/_multiboard.scss index d27605c2e77c7..c4e7ecf9dcd80 100644 --- a/ui/analyse/css/study/panel/_multiboard.scss +++ b/ui/analyse/css/study/panel/_multiboard.scss @@ -47,12 +47,14 @@ } .playing, - .eval { + .eval, + .results { cursor: pointer; } .playing input, - .eval input { + .eval input, + .results input { vertical-align: middle; margin-inline-end: 3px; } From e95b2562b61655c54ed1ebfe18e3d66228637895 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Mon, 23 Dec 2024 02:35:46 +0000 Subject: [PATCH 06/20] Fix formatting --- ui/analyse/src/study/multiBoard.ts | 17 ++++++++++------- ui/analyse/src/study/relay/relayGames.ts | 4 +++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index 4f11178a18ac0..196a2a79d1e46 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -196,7 +196,8 @@ const previewToCgConfig = (cp: ChapterPreview): CgConfig => ({ }); const makePreview = - (roundPath: string, current: ChapterId, cloudEval?: MultiCloudEval, showResults?: boolean) => (preview: ChapterPreview) => { + (roundPath: string, current: ChapterId, cloudEval?: MultiCloudEval, showResults?: boolean) => + (preview: ChapterPreview) => { const orientation = preview.orientation || 'white'; const baseConfig = { coordinates: false, @@ -206,7 +207,7 @@ const makePreview = enabled: false, visible: false, }, - } + }; return h( `a.mini-game.is2d.chap-${preview.id}`, { @@ -223,10 +224,12 @@ const makePreview = hook: { insert(vnode) { const el = vnode.elm as HTMLElement; - vnode.data!.cg = showResults ? makeChessground(el, { - ...previewToCgConfig(preview), - ...baseConfig, - }) : makeChessground(el, baseConfig); + vnode.data!.cg = showResults + ? makeChessground(el, { + ...previewToCgConfig(preview), + ...baseConfig, + }) + : makeChessground(el, baseConfig); vnode.data!.fen = preview.fen; }, postpatch(old, vnode) { @@ -235,7 +238,7 @@ const makePreview = } // In this case, showResults was set to true but the cg fen is still on the initial pos if (showResults && old.data!.cg.fen != old.data!.cg.getFen()) { - old.data!.cg.set(previewToCgConfig(preview)) + old.data!.cg.set(previewToCgConfig(preview)); } vnode.data!.fen = preview.fen; const el = vnode.elm as HTMLElement; diff --git a/ui/analyse/src/study/relay/relayGames.ts b/ui/analyse/src/study/relay/relayGames.ts index 4ff908b33d99f..0e04cffb36d7c 100644 --- a/ui/analyse/src/study/relay/relayGames.ts +++ b/ui/analyse/src/study/relay/relayGames.ts @@ -58,7 +58,9 @@ export const gamesList = (study: StudyCtrl, relay: RelayCtrl) => { playerFed(p.fed), h('span.name', [userTitle(p), p.name]), ]), - study.multiBoard.showResults() ? h(s === '1' ? 'good' : s === '0' ? 'bad' : 'status', [s]) : null, + study.multiBoard.showResults() + ? h(s === '1' ? 'good' : s === '0' ? 'bad' : 'status', [s]) + : null, ] : [h('span.mini-game__user', h('span.name', 'Unknown player'))], ); From 2f764deea7f78d35640df13ee4795b5a55cc8d22 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sat, 28 Dec 2024 19:15:12 +0000 Subject: [PATCH 07/20] Remove clocks from boards grid when selecting no results --- ui/analyse/src/study/multiBoard.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index d7d5d97358dbb..deb2085ffd37f 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -324,11 +324,11 @@ const computeTimeLeft = (preview: ChapterPreview, color: Color): number | undefi }; const boardPlayer = (preview: ChapterPreview, color: Color, showResults?: boolean) => { - const outcome = showResults && preview.status && preview.status !== '*' ? preview.status : undefined; + const outcome = preview.status && preview.status !== '*' ? preview.status : undefined; const player = preview.players?.[color], score = outcome?.split('-')[color === 'white' ? 0 : 1]; return h('span.mini-game__player', [ player && renderUser(player), - score ? h('span.mini-game__result', score) : renderClock(preview, color), + showResults ? score ? h('span.mini-game__result', score) : renderClock(preview, color) : undefined, ]); }; From f2e3bb15a63a31d9cdf86d7934293833f32e67e0 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sat, 28 Dec 2024 19:37:39 +0000 Subject: [PATCH 08/20] Hide eval gauges when hiding results --- ui/analyse/src/study/multiBoard.ts | 2 +- ui/analyse/src/study/relay/relayGames.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index deb2085ffd37f..30fed499334d1 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -217,7 +217,7 @@ const makePreview = [ boardPlayer(preview, CgOpposite(orientation), showResults), h('span.cg-gauge', [ - cloudEval && verticalEvalGauge(preview, cloudEval), + showResults ? cloudEval && verticalEvalGauge(preview, cloudEval) : undefined, h( 'span.mini-game__board', h('span.cg-wrap', { diff --git a/ui/analyse/src/study/relay/relayGames.ts b/ui/analyse/src/study/relay/relayGames.ts index 0e04cffb36d7c..5405259772e78 100644 --- a/ui/analyse/src/study/relay/relayGames.ts +++ b/ui/analyse/src/study/relay/relayGames.ts @@ -12,6 +12,7 @@ export const gamesList = (study: StudyCtrl, relay: RelayCtrl) => { const chapters = study.chapters.list.all(); const cloudEval = study.multiCloudEval?.thisIfShowEval(); const roundPath = relay.roundPath(); + const showResults = study.multiBoard.showResults(); return h( 'div.relay-games', { @@ -45,7 +46,7 @@ export const gamesList = (study: StudyCtrl, relay: RelayCtrl) => { class: { 'relay-game--current': c.id === study.data.chapter.id }, }, [ - cloudEval && verticalEvalGauge(c, cloudEval), + showResults ? cloudEval && verticalEvalGauge(c, cloudEval) : undefined, h( 'span.relay-game__players', players.map((p, i) => { @@ -58,7 +59,7 @@ export const gamesList = (study: StudyCtrl, relay: RelayCtrl) => { playerFed(p.fed), h('span.name', [userTitle(p), p.name]), ]), - study.multiBoard.showResults() + showResults ? h(s === '1' ? 'good' : s === '0' ? 'bad' : 'status', [s]) : null, ] From 6ca3a4813001e3b146a51159bb6cac687a8b7357 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sat, 28 Dec 2024 21:11:54 +0000 Subject: [PATCH 09/20] Make the show results toggle a stored prop --- ui/analyse/src/study/multiBoard.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index 30fed499334d1..8a6225c5f0326 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -12,12 +12,12 @@ import { type StudyChapters, gameLinkAttrs, gameLinksListener } from './studyCha import { playerFed } from './playerBars'; import { userTitle } from 'common/userLink'; import { h } from 'snabbdom'; -import { storage } from 'common/storage'; +import { storage, storedBooleanProp, StoredProp } from 'common/storage'; import { Chessground as makeChessground } from 'chessground'; export class MultiBoardCtrl { playing: Toggle; - showResults: Toggle; + showResults: StoredProp; teamSelect: Prop = prop(''); page: number = 1; maxPerPageStorage = storage.make('study.multiBoard.maxPerPage'); @@ -29,7 +29,7 @@ export class MultiBoardCtrl { readonly redraw: () => void, ) { this.playing = toggle(false, this.redraw); - this.showResults = toggle(true, this.redraw); + this.showResults = storedBooleanProp("study.showResults", true); if (this.initialTeamSelect) this.onChapterChange(this.initialTeamSelect); } From 426fca505f9c387c72934622ebf952c21a34f321 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Sat, 28 Dec 2024 21:23:12 +0000 Subject: [PATCH 10/20] Fix formatting --- ui/analyse/src/study/multiBoard.ts | 4 ++-- ui/analyse/src/study/relay/relayGames.ts | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index 8a6225c5f0326..daf0971d217e6 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -29,7 +29,7 @@ export class MultiBoardCtrl { readonly redraw: () => void, ) { this.playing = toggle(false, this.redraw); - this.showResults = storedBooleanProp("study.showResults", true); + this.showResults = storedBooleanProp('study.showResults', true); if (this.initialTeamSelect) this.onChapterChange(this.initialTeamSelect); } @@ -329,6 +329,6 @@ const boardPlayer = (preview: ChapterPreview, color: Color, showResults?: boolea score = outcome?.split('-')[color === 'white' ? 0 : 1]; return h('span.mini-game__player', [ player && renderUser(player), - showResults ? score ? h('span.mini-game__result', score) : renderClock(preview, color) : undefined, + showResults ? (score ? h('span.mini-game__result', score) : renderClock(preview, color)) : undefined, ]); }; diff --git a/ui/analyse/src/study/relay/relayGames.ts b/ui/analyse/src/study/relay/relayGames.ts index 5405259772e78..ed50e447e6aba 100644 --- a/ui/analyse/src/study/relay/relayGames.ts +++ b/ui/analyse/src/study/relay/relayGames.ts @@ -59,9 +59,7 @@ export const gamesList = (study: StudyCtrl, relay: RelayCtrl) => { playerFed(p.fed), h('span.name', [userTitle(p), p.name]), ]), - showResults - ? h(s === '1' ? 'good' : s === '0' ? 'bad' : 'status', [s]) - : null, + showResults ? h(s === '1' ? 'good' : s === '0' ? 'bad' : 'status', [s]) : null, ] : [h('span.mini-game__user', h('span.name', 'Unknown player'))], ); From 72e9f3ff71fe72ed21e867f54f1ee0bd6b773a40 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 31 Dec 2024 22:42:53 +0000 Subject: [PATCH 11/20] Send to initial position when clicking on a broadcast game with results toggle to false --- ui/analyse/src/study/studyCtrl.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/analyse/src/study/studyCtrl.ts b/ui/analyse/src/study/studyCtrl.ts index e93fd1fdd800a..7da699dd570a5 100644 --- a/ui/analyse/src/study/studyCtrl.ts +++ b/ui/analyse/src/study/studyCtrl.ts @@ -463,6 +463,10 @@ export default class StudyCtrl { return false; } const componentCallbacks = () => { + if (!this.multiBoard.showResults()) + { + this.ctrl.userJump(this.ctrl.initialPath) + } this.relay?.onChapterChange(); this.multiBoard.onChapterChange(this.data.chapter.id); }; From 5d6027f2b810fecf5c0a86644e4d057f02bda7ff Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Tue, 31 Dec 2024 22:46:04 +0000 Subject: [PATCH 12/20] Fix formatting --- ui/analyse/src/study/studyCtrl.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/analyse/src/study/studyCtrl.ts b/ui/analyse/src/study/studyCtrl.ts index 7da699dd570a5..e101d53621415 100644 --- a/ui/analyse/src/study/studyCtrl.ts +++ b/ui/analyse/src/study/studyCtrl.ts @@ -463,9 +463,8 @@ export default class StudyCtrl { return false; } const componentCallbacks = () => { - if (!this.multiBoard.showResults()) - { - this.ctrl.userJump(this.ctrl.initialPath) + if (!this.multiBoard.showResults()) { + this.ctrl.userJump(this.ctrl.initialPath); } this.relay?.onChapterChange(); this.multiBoard.onChapterChange(this.data.chapter.id); From a9cb00bf63f24919bb0e93509cfe6d4801309366 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Wed, 1 Jan 2025 00:51:31 +0000 Subject: [PATCH 13/20] Render empty previews with a note when setting results to off --- ui/analyse/css/study/panel/_multiboard.scss | 5 +++++ ui/analyse/src/study/multiBoard.ts | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ui/analyse/css/study/panel/_multiboard.scss b/ui/analyse/css/study/panel/_multiboard.scss index c4e7ecf9dcd80..d2b6080e557ac 100644 --- a/ui/analyse/css/study/panel/_multiboard.scss +++ b/ui/analyse/css/study/panel/_multiboard.scss @@ -166,3 +166,8 @@ border-radius: 4px 0 0 4px; } } + +.empty-boards-note { + margin-bottom: .5em; + color: var(--c-font-dim) +} \ No newline at end of file diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index daf0971d217e6..bf582eee46e81 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -107,6 +107,7 @@ export function view(ctrl: MultiBoardCtrl, study: StudyCtrl): MaybeVNode { renderShowResultsToggle(ctrl), ]), ]), + !ctrl.showResults() ? h('div.empty-boards-note', { attrs: { 'data-icon': licon.InfoCircle } } , ' Since you chose to hide the results, all the preview boards are empty to avoid spoilers.') : undefined, h( 'div.now-playing', { @@ -229,7 +230,9 @@ const makePreview = ...previewToCgConfig(preview), ...baseConfig, }) - : makeChessground(el, baseConfig); + : makeChessground(el, { + fen: "8/8/8/8/8/8/8/8", + ...baseConfig,}); vnode.data!.fen = preview.fen; }, postpatch(old, vnode) { @@ -242,7 +245,7 @@ const makePreview = } vnode.data!.fen = preview.fen; const el = vnode.elm as HTMLElement; - vnode.data!.cg = showResults ? old.data!.cg : makeChessground(el, baseConfig); + vnode.data!.cg = showResults ? old.data!.cg : makeChessground(el, {fen: "8/8/8/8/8/8/8/8", ...baseConfig,}); }, }, }), From e6faf8b834ee2b91e2a5988bf6f2666f5dd11229 Mon Sep 17 00:00:00 2001 From: yahya lafhal Date: Wed, 1 Jan 2025 00:55:50 +0000 Subject: [PATCH 14/20] Fix ts formatting --- ui/analyse/css/study/panel/_multiboard.scss | 6 +++--- ui/analyse/src/study/multiBoard.ts | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ui/analyse/css/study/panel/_multiboard.scss b/ui/analyse/css/study/panel/_multiboard.scss index d2b6080e557ac..6f293821c512d 100644 --- a/ui/analyse/css/study/panel/_multiboard.scss +++ b/ui/analyse/css/study/panel/_multiboard.scss @@ -168,6 +168,6 @@ } .empty-boards-note { - margin-bottom: .5em; - color: var(--c-font-dim) -} \ No newline at end of file + margin-bottom: 0.5em; + color: var(--c-font-dim); +} diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index bf582eee46e81..393e98625b809 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -107,7 +107,13 @@ export function view(ctrl: MultiBoardCtrl, study: StudyCtrl): MaybeVNode { renderShowResultsToggle(ctrl), ]), ]), - !ctrl.showResults() ? h('div.empty-boards-note', { attrs: { 'data-icon': licon.InfoCircle } } , ' Since you chose to hide the results, all the preview boards are empty to avoid spoilers.') : undefined, + !ctrl.showResults() + ? h( + 'div.empty-boards-note', + { attrs: { 'data-icon': licon.InfoCircle } }, + ' Since you chose to hide the results, all the preview boards are empty to avoid spoilers.', + ) + : undefined, h( 'div.now-playing', { @@ -231,8 +237,9 @@ const makePreview = ...baseConfig, }) : makeChessground(el, { - fen: "8/8/8/8/8/8/8/8", - ...baseConfig,}); + fen: '8/8/8/8/8/8/8/8', + ...baseConfig, + }); vnode.data!.fen = preview.fen; }, postpatch(old, vnode) { @@ -245,7 +252,9 @@ const makePreview = } vnode.data!.fen = preview.fen; const el = vnode.elm as HTMLElement; - vnode.data!.cg = showResults ? old.data!.cg : makeChessground(el, {fen: "8/8/8/8/8/8/8/8", ...baseConfig,}); + vnode.data!.cg = showResults + ? old.data!.cg + : makeChessground(el, { fen: '8/8/8/8/8/8/8/8', ...baseConfig }); }, }, }), From 6fcb718f894e55a325b04e13bd72894998ddb15d Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 7 Jan 2025 10:38:09 +0100 Subject: [PATCH 15/20] redraw immediately when switching the broadcast results toggle --- ui/analyse/src/study/multiBoard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index 393e98625b809..27d9d9f858ade 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -190,7 +190,7 @@ const renderShowResultsToggle = (ctrl: MultiBoardCtrl): MaybeVNode => h('label.results', [ h('input', { attrs: { type: 'checkbox', checked: ctrl.showResults() }, - hook: bind('change', e => ctrl.showResults((e.target as HTMLInputElement).checked)), + hook: bind('change', e => ctrl.showResults((e.target as HTMLInputElement).checked), ctrl.redraw), }), i18n.study.showResults, ]); From ea6002aa56acdf27d16247962c69bdcf5bf0b076 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 7 Jan 2025 11:07:23 +0100 Subject: [PATCH 16/20] avoid flashing the current position when hiding the current broadcast results --- ui/analyse/src/study/studyCtrl.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ui/analyse/src/study/studyCtrl.ts b/ui/analyse/src/study/studyCtrl.ts index e101d53621415..87368f07abd51 100644 --- a/ui/analyse/src/study/studyCtrl.ts +++ b/ui/analyse/src/study/studyCtrl.ts @@ -361,7 +361,9 @@ export default class StudyCtrl { } else { nextPath = sameChapter ? prevPath - : this.data.chapter.relayPath || this.chapters.localPaths[this.vm.chapterId] || treePath.root; + : this.relay && !this.multiBoard.showResults() + ? treePath.root + : this.data.chapter.relayPath || this.chapters.localPaths[this.vm.chapterId] || treePath.root; } // path could be gone (because of subtree deletion), go as far as possible @@ -463,9 +465,6 @@ export default class StudyCtrl { return false; } const componentCallbacks = () => { - if (!this.multiBoard.showResults()) { - this.ctrl.userJump(this.ctrl.initialPath); - } this.relay?.onChapterChange(); this.multiBoard.onChapterChange(this.data.chapter.id); }; From 101c13dc0ddee00ff204a9c1d9a4911d74306127 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 12 Jan 2025 11:29:38 +0100 Subject: [PATCH 17/20] tweak broadcast spoiler warning --- ui/analyse/css/study/panel/_multiboard.scss | 4 ++-- ui/analyse/src/study/multiBoard.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/analyse/css/study/panel/_multiboard.scss b/ui/analyse/css/study/panel/_multiboard.scss index 6f293821c512d..88ac1d06f5fb5 100644 --- a/ui/analyse/css/study/panel/_multiboard.scss +++ b/ui/analyse/css/study/panel/_multiboard.scss @@ -168,6 +168,6 @@ } .empty-boards-note { - margin-bottom: 0.5em; - color: var(--c-font-dim); + padding: 1em; + color: $c-font-dim; } diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index 27d9d9f858ade..a515dfbd0419b 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -1,7 +1,7 @@ import * as licon from 'common/licon'; import { otbClockIsRunning, formatMs } from 'common/clock'; import { fenColor } from 'common/miniBoard'; -import { type MaybeVNode, type VNode, bind, onInsert } from 'common/snabbdom'; +import { type MaybeVNode, type VNode, bind, dataIcon, onInsert } from 'common/snabbdom'; import { opposite as CgOpposite, uciToMove } from 'chessground/util'; import type { ChapterId, ChapterPreview, StudyPlayer } from './interfaces'; import type StudyCtrl from './studyCtrl'; @@ -109,9 +109,9 @@ export function view(ctrl: MultiBoardCtrl, study: StudyCtrl): MaybeVNode { ]), !ctrl.showResults() ? h( - 'div.empty-boards-note', - { attrs: { 'data-icon': licon.InfoCircle } }, - ' Since you chose to hide the results, all the preview boards are empty to avoid spoilers.', + 'div.empty-boards-note.text', + { attrs: dataIcon(licon.InfoCircle) }, + 'Since you chose to hide the results, all the preview boards are empty to avoid spoilers.', ) : undefined, h( From 6a59c87ba165a128e82893fbfc2da7f3fe07f6b2 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 12 Jan 2025 11:33:51 +0100 Subject: [PATCH 18/20] avoid flashing the first board position --- ui/analyse/src/study/studyCtrl.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/analyse/src/study/studyCtrl.ts b/ui/analyse/src/study/studyCtrl.ts index 87368f07abd51..b3c65bc32b02d 100644 --- a/ui/analyse/src/study/studyCtrl.ts +++ b/ui/analyse/src/study/studyCtrl.ts @@ -243,7 +243,11 @@ export default class StudyCtrl { this.practice = practiceData && new StudyPracticeCtrl(ctrl, data, practiceData); if (this.vm.mode.sticky && !this.isGamebookPlay()) this.ctrl.userJump(this.data.position.path); - else if (this.data.chapter.relayPath && !defined(this.ctrl.requestInitialPly)) + else if ( + this.data.chapter.relayPath && + !defined(this.ctrl.requestInitialPly) && + !(this.relay && !this.multiBoard.showResults()) + ) this.ctrl.userJump(this.data.chapter.relayPath); this.configureAnalysis(); From 6b282972dc56b5c5454269fb9296030a15bfa3eb Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 12 Jan 2025 11:37:23 +0100 Subject: [PATCH 19/20] remove hardcoded empty board FEN --- ui/analyse/src/study/multiBoard.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index a515dfbd0419b..8aa045ef614c0 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -14,6 +14,7 @@ import { userTitle } from 'common/userLink'; import { h } from 'snabbdom'; import { storage, storedBooleanProp, StoredProp } from 'common/storage'; import { Chessground as makeChessground } from 'chessground'; +import { EMPTY_BOARD_FEN } from 'chessops/fen'; export class MultiBoardCtrl { playing: Toggle; @@ -237,7 +238,7 @@ const makePreview = ...baseConfig, }) : makeChessground(el, { - fen: '8/8/8/8/8/8/8/8', + fen: EMPTY_BOARD_FEN, ...baseConfig, }); vnode.data!.fen = preview.fen; @@ -254,7 +255,7 @@ const makePreview = const el = vnode.elm as HTMLElement; vnode.data!.cg = showResults ? old.data!.cg - : makeChessground(el, { fen: '8/8/8/8/8/8/8/8', ...baseConfig }); + : makeChessground(el, { fen: EMPTY_BOARD_FEN, ...baseConfig }); }, }, }), From 4e7ba0732c39a6f536b5f1623c347e1ed4abcc22 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 12 Jan 2025 11:47:53 +0100 Subject: [PATCH 20/20] simplify broadcast multiboard wrt results and spoilers --- ui/analyse/src/study/multiBoard.ts | 41 +++++++++--------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index 8aa045ef614c0..a00a4685063aa 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -2,7 +2,7 @@ import * as licon from 'common/licon'; import { otbClockIsRunning, formatMs } from 'common/clock'; import { fenColor } from 'common/miniBoard'; import { type MaybeVNode, type VNode, bind, dataIcon, onInsert } from 'common/snabbdom'; -import { opposite as CgOpposite, uciToMove } from 'chessground/util'; +import { opposite as cgOpposite, uciToMove } from 'chessground/util'; import type { ChapterId, ChapterPreview, StudyPlayer } from './interfaces'; import type StudyCtrl from './studyCtrl'; import { type CloudEval, type MultiCloudEval, renderEvalToggle, renderScore } from './multiCloudEval'; @@ -207,23 +207,14 @@ const makePreview = (roundPath: string, current: ChapterId, cloudEval?: MultiCloudEval, showResults?: boolean) => (preview: ChapterPreview) => { const orientation = preview.orientation || 'white'; - const baseConfig = { - coordinates: false, - viewOnly: true, - orientation, - drawable: { - enabled: false, - visible: false, - }, - }; return h( - `a.mini-game.is2d.chap-${preview.id}`, + `a.mini-game.is2d.chap-${preview.id}${showResults ? '' : '.no-spoilers'}`, { class: { active: preview.id === current }, attrs: gameLinkAttrs(roundPath, preview), }, [ - boardPlayer(preview, CgOpposite(orientation), showResults), + boardPlayer(preview, cgOpposite(orientation), showResults), h('span.cg-gauge', [ showResults ? cloudEval && verticalEvalGauge(preview, cloudEval) : undefined, h( @@ -232,30 +223,22 @@ const makePreview = hook: { insert(vnode) { const el = vnode.elm as HTMLElement; - vnode.data!.cg = showResults - ? makeChessground(el, { - ...previewToCgConfig(preview), - ...baseConfig, - }) - : makeChessground(el, { - fen: EMPTY_BOARD_FEN, - ...baseConfig, - }); + vnode.data!.cg = makeChessground(el, { + coordinates: false, + viewOnly: true, + orientation, + drawable: { enabled: false, visible: false }, + ...(showResults ? previewToCgConfig(preview) : { fen: EMPTY_BOARD_FEN }), + }); vnode.data!.fen = preview.fen; }, postpatch(old, vnode) { + if (!showResults) return; if (old.data!.fen !== preview.fen) { old.data!.cg?.set(previewToCgConfig(preview)); } - // In this case, showResults was set to true but the cg fen is still on the initial pos - if (showResults && old.data!.cg.fen != old.data!.cg.getFen()) { - old.data!.cg.set(previewToCgConfig(preview)); - } vnode.data!.fen = preview.fen; - const el = vnode.elm as HTMLElement; - vnode.data!.cg = showResults - ? old.data!.cg - : makeChessground(el, { fen: EMPTY_BOARD_FEN, ...baseConfig }); + vnode.data!.cg = old.data!.cg; }, }, }),