Skip to content

Commit

Permalink
dynamic themes
Browse files Browse the repository at this point in the history
  • Loading branch information
schlawg committed Mar 30, 2024
1 parent b527746 commit ed26d39
Show file tree
Hide file tree
Showing 1,277 changed files with 2,967 additions and 4,537 deletions.
1 change: 0 additions & 1 deletion .ignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# search ignores
vendor
translation/dest
ui/*/css/build
public/font
public/sound
public/piece
Expand Down
19 changes: 1 addition & 18 deletions app/templating/AssetHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,7 @@ trait AssetHelper extends HasEnv:
def flairSrc(flair: Flair) = staticAssetUrl(s"$flairVersion/flair/img/$flair.webp")

def cssTag(name: String)(using ctx: Context): Frag =
cssTagWithDirAndTheme(name, isRTL(using ctx.lang), ctx.pref.currentBg)

def cssTagWithDirAndTheme(name: String, isRTL: Boolean, theme: String): Frag =
if theme == "system" then
frag(
cssTagWithDirAndSimpleTheme(name, isRTL, "light")(media := "(prefers-color-scheme: light)"),
cssTagWithDirAndSimpleTheme(name, isRTL, "dark")(media := "(prefers-color-scheme: dark)")
)
else cssTagWithDirAndSimpleTheme(name, isRTL, theme)

private def cssTagWithDirAndSimpleTheme(name: String, isRTL: Boolean, theme: String): Tag =
cssAt:
s"css/$name.${if isRTL then "rtl" else "ltr"}.$theme.${if minifiedAssets then "min" else "dev"}.css"
cssTagNoTheme(name)

def cssTagNoTheme(name: String): Frag =
cssAt(s"css/$name.${if minifiedAssets then "min" else "dev"}.css")
Expand All @@ -62,11 +50,6 @@ trait AssetHelper extends HasEnv:
case json: JsValue => safeJsonValue(json).value
case json => json.toString

val systemThemePolyfillJs = """
if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all')
document.querySelectorAll('[media="(prefers-color-scheme: dark)"]').forEach(e=>e.media='')
"""

// load iife scripts in <head> and defer
def iifeModule(path: String): Frag = script(deferAttr, src := assetUrl(path))

Expand Down
5 changes: 3 additions & 2 deletions app/views/base/embed.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ object embed:
layout.bits.viewport,
layout.bits.metaCsp(basicCsp.withNonce(ctx.nonce).withInlineIconFont),
st.headTitle(title),
layout.bits.systemThemeEmbedScript,
layout.bits.pieceSprite(ctx.pieceSet),
cssTagWithDirAndTheme(cssModule, isRTL = lila.i18n.LangList.isRTL(ctx.lang), ctx.bg),
(ctx.bg == "system").option(embedJsUnsafe(systemThemePolyfillJs, ctx.nonce))
cssTag("theme-light"), // includes both light & dark colors
cssTag(cssModule)
),
st.body(cls := s"${ctx.bg} highlight ${ctx.boardClass}")(
layout.dataSoundSet := SoundSet.silent.key,
Expand Down
37 changes: 24 additions & 13 deletions app/views/base/layout.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,32 @@ import lila.common.base.StringUtils.escapeHtmlRaw
object layout:

object bits:
val doctype = raw("<!DOCTYPE html>")
def htmlTag(using lang: Lang) = html(st.lang := lang.code, dir := isRTL.option("rtl"))
val topComment = raw("""<!-- Lichess is open source! See https://lichess.org/source -->""")
val charset = raw("""<meta charset="utf-8">""")
val doctype = raw("<!DOCTYPE html>")
def htmlTag(using lang: Lang, ctx: Context) =
html(st.lang := lang.code, dir := isRTL.option("rtl"), ctx.pref.themeColorClass.map(cls := _))
val topComment = raw("""<!-- Lichess is open source! See https://lichess.org/source -->""")
val charset = raw("""<meta charset="utf-8">""")
val viewport = raw:
"""<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">"""
def metaCsp(csp: ContentSecurityPolicy): Frag = raw:
s"""<meta http-equiv="Content-Security-Policy" content="$csp">"""
def metaCsp(csp: Option[ContentSecurityPolicy])(using ctx: PageContext): Frag =
metaCsp(csp.getOrElse(defaultCsp))
def metaThemeColor(using ctx: PageContext): Frag =
if ctx.pref.bg == lila.pref.Pref.Bg.SYSTEM then
raw:
s"""<meta name="theme-color" media="(prefers-color-scheme: light)" content="${ctx.pref.themeColorLight}">""" +
s"""<meta name="theme-color" media="(prefers-color-scheme: dark)" content="${ctx.pref.themeColorDark}">"""
else
raw:
raw:
s"""<meta name="theme-color" media="(prefers-color-scheme: light)" content="${ctx.pref.themeColorLight}">""" +
s"""<meta name="theme-color" media="(prefers-color-scheme: dark)" content="${ctx.pref.themeColorDark}">""" +
s"""<meta name="theme-color" content="${ctx.pref.themeColor}">"""
def systemThemeScript(using ctx: PageContext) =
(ctx.pref.bg === lila.pref.Pref.Bg.SYSTEM).option(
embedJsUnsafe(
"if (window.matchMedia('(prefers-color-scheme: light)').matches) " +
"document.documentElement.classList.add('light');"
)
)
def systemThemeEmbedScript(using ctx: EmbedContext) =
"<script>if (window.matchMedia('(prefers-color-scheme: light)').matches) " +
"document.documentElement.classList.add('light');</script>"
def pieceSprite(using ctx: PageContext): Frag = pieceSprite(ctx.pref.currentPieceSet)
def pieceSprite(ps: lila.pref.PieceSet): Frag =
link(
Expand Down Expand Up @@ -185,7 +193,6 @@ object layout:
frag(cashTag, jsModule("site")),
moreJs,
ctx.data.inquiry.isDefined.option(jsModule("mod.inquiry")),
(ctx.pref.bg == lila.pref.Pref.Bg.SYSTEM).option(embedJsUnsafe(systemThemePolyfillJs)),
(!netConfig.isProd).option(jsModule("devMode"))
)

Expand Down Expand Up @@ -258,17 +265,21 @@ object layout:
frag(
doctype,
htmlTag(
(ctx.data.inquiry.isEmpty && ctx.impersonatedBy.isEmpty && !ctx.blind)
.option(cls := ctx.pref.bg.themeColorClass),
topComment,
head(
charset,
viewport,
metaCsp(csp),
metaThemeColor,
systemThemeScript,
st.headTitle:
val prodTitle = fullTitle | s"$title$siteName"
if netConfig.isProd then prodTitle
else s"${ctx.me.so(_.username + " ")} $prodTitle"
,
cssTag("theme-all"),
cssTag("site"),
pref.is3d.option(cssTag("board-3d")),
ctx.data.inquiry.isDefined.option(cssTagNoTheme("mod.inquiry")),
Expand All @@ -288,7 +299,7 @@ object layout:
atomLinkTag | dailyNewsAtom,
(pref.bg == lila.pref.Pref.Bg.TRANSPARENT).option(pref.bgImgOrDefault).map { img =>
raw:
s"""<style id="bg-data">body.transp::before{background-image:url("${escapeHtmlRaw(img)
s"""<style id="bg-data">html.transp::before{background-image:url("${escapeHtmlRaw(img)
.replace("&amp;", "&")}");}</style>"""
},
fontPreload,
Expand Down Expand Up @@ -330,7 +341,7 @@ object layout:
dataBoardTheme := pref.currentTheme.name,
dataPieceSet := pref.currentPieceSet.name,
dataAnnounce := lila.api.AnnounceStore.get.map(a => safeJsonValue(a.json)),
style := zoomable.option(s"--zoom:$pageZoom")
style := zoomable.option(s"---zoom:$pageZoom")
)(
blindModeForm,
ctx.data.inquiry.map { views.html.mod.inquiry(_) },
Expand Down
2 changes: 1 addition & 1 deletion app/views/puzzle/dashboard.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ object dashboard:
),
div(
cls := s"$metricClass $metricClass--win",
style := s"--first:${results.firstWinPercent}%;--win:${results.winPercent}%"
style := s"---first:${results.firstWinPercent}%;---win:${results.winPercent}%"
)(
trans.puzzle.percentSolved(strong(s"${results.winPercent}%"))
),
Expand Down
5 changes: 5 additions & 0 deletions modules/pref/src/main/Pref.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ case class Pref(
val themeColorLight = "#dbd7d1"
val themeColorDark = "#2e2a24"
def themeColor = if bg == Bg.LIGHT then themeColorLight else themeColorDark
def themeColorClass =
if bg == Bg.LIGHT then "light".some
else if bg == Bg.TRANSPARENT then "transp".some
else if bg == Bg.SYSTEM then none
else "dark".some

def realSoundSet = SoundSet(soundSet)

Expand Down
41 changes: 10 additions & 31 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions ui/.build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
"license": "AGPL-3.0-or-later",
"type": "commonjs",
"dependencies": {
"@types/node": "^20.11.28",
"typescript": "^5.4.2",
"@types/node": "^20.11.30",
"@types/tinycolor2": "^1.4.6",
"build": "link:",
"esbuild": "^0.20.2",
"fast-glob": "^3.3.2"
"fast-glob": "^3.3.2",
"tinycolor2": "^1.6.0",
"typescript": "^5.4.3"
},
"scripts": {
"dev": "tsc && node dist/main.js"
Expand Down
6 changes: 6 additions & 0 deletions ui/.build/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const longArgs = [
'--prod',
'--split',
'--debug',
'--rgb',
'--clean',
'--clean-theme',
'--update',
Expand Down Expand Up @@ -52,6 +53,7 @@ export function main() {
env.clean = args.some(x => x.startsWith('--clean')) || oneDashArgs.includes('c');
env.cleanTheme = args.includes('--clean-theme');
env.install = !args.includes('--no-install') && !oneDashArgs.includes('n');
env.rgb = args.includes('--rgb');

if (env.rebuild && !env.install) {
env.warn(`--rebuild incompatible with --no-install`);
Expand Down Expand Up @@ -123,6 +125,7 @@ class Env {
prod = false;
split = false;
debug = false;
rgb = false;
install = true;
copies = true;
exitCode = new Map<'sass' | 'tsc' | 'esbuild', number | false>();
Expand Down Expand Up @@ -152,6 +155,9 @@ class Env {
get outDir(): string {
return path.join(this.rootDir, 'public');
}
get themeDir(): string {
return path.join(this.uiDir, 'common', 'css', 'theme');
}
get cssDir(): string {
return path.join(this.outDir, 'css');
}
Expand Down
Loading

0 comments on commit ed26d39

Please sign in to comment.