team-3/src/c3nav/site/themes.py
2024-03-28 17:38:09 +01:00

147 lines
No EOL
5.5 KiB
Python

from c3nav import settings
from c3nav.mapdata.utils.cache.cache_decorator import mapdata_cache
def css_vars_as_str(vars):
css_str = ''
for name, value in vars.items():
css_str += f'--color-{name}: {value};'
return css_str
remove = ['grid']
modify = {
'grid-text': ('grid', lambda rgb: f'rgba({rgb[0]},{rgb[1]},{rgb[2]},0.6)'),
'grid-lines': ('grid', lambda rgb: f'rgba({rgb[0]},{rgb[1]},{rgb[2]},0.2)'),
'modal-backdrop': ('modal-backdrop', lambda rgb: f'rgba({rgb[0]},{rgb[1]},{rgb[2]},0.2)'),
'shadow': ('shadow', lambda rgb: f'rgba({rgb[0]},{rgb[1]},{rgb[2]},0.2)'),
'control-shadow': ('shadow', lambda rgb: f'rgba({rgb[0]},{rgb[1]},{rgb[2]},0.6)'),
'overlay-background': ('overlay-background', lambda rgb: f'rgba({rgb[0]},{rgb[1]},{rgb[2]},0.6)'),
}
def modify_vars(css_vars):
from c3nav.mapdata.utils.color import color_to_rgb
for key, (source, fn) in modify.items():
try:
rgb = [x * 255 for x in color_to_rgb(css_vars[source])]
except ValueError: # ignore invalid colors
continue
css_vars[key] = fn(rgb)
for key in remove:
del css_vars[key]
def make_themes(theme_models):
from c3nav import settings
from django.utils.translation import gettext_lazy as _
themes = {}
base_css_vars = settings.BASE_THEME['css'].copy()
modify_vars(base_css_vars)
primary_color = base_css_vars['primary']
if settings.BASE_THEME['randomize_primary_color']:
del base_css_vars['primary']
base_theme_vars_str = css_vars_as_str(base_css_vars)
base_theme = {
'css_code': ':root{%s}' % base_theme_vars_str,
'theme_color': base_css_vars['header-background'],
'randomize_primary_color': settings.BASE_THEME['randomize_primary_color'],
'primary_color': primary_color,
}
if settings.BASE_THEME['is_dark']:
default_dark = base_theme
default_light = None
else:
default_light = base_theme
default_dark = None
for theme in theme_models:
css_vars = theme.css_vars()
modify_vars(css_vars)
primary_color = css_vars['primary']
if theme.randomize_primary_color:
del css_vars['primary']
css_vars_str = css_vars_as_str(css_vars)
css_code = (':root{%s}' % css_vars_str) + theme.extra_css
themes[theme.pk] = {
'name': theme.title,
'css': css_code,
'funky': theme.funky,
'theme_color_dark': theme.color_css_header_background,
'theme_color_light': theme.color_css_header_background,
'randomize_primary_color': theme.randomize_primary_color,
'primary_color': primary_color,
}
if theme.default:
if theme.dark:
default_dark = {
'css_code': css_code,
'theme_color': css_vars['header-background'],
'primary_color': primary_color,
}
else:
default_light = {
'css_code': css_code,
'theme_color': css_vars['header-background'],
'primary_color': primary_color,
}
if default_dark is not None and default_light is not None:
name = _('Automatic')
css_code = ('@media(prefers-color-scheme:light){%s@media(prefers-color-scheme:dark){%s}'
% (default_light['css_code'], default_dark['css_code']))
randomize_primary_color = default_dark['randomize_primary_color'] or default_light['randomize_primary_color']
else:
name = _('Default')
default_theme = default_light or default_dark
css_code = default_theme['css_code']
randomize_primary_color = default_theme['randomize_primary_color']
themes[0] = {
'name': name,
'css': css_code,
'funky': False,
'theme_color_dark': default_dark['theme_color'] if default_dark is not None else default_light['theme_color'],
'theme_color_light': default_light['theme_color'] if default_light is not None else default_dark['theme_color'],
'randomize_primary_color': randomize_primary_color,
'primary_color': default_light['primary_color'] if default_light is not None else default_dark['primary_color'],
}
return themes
@mapdata_cache
def css_themes_all():
from c3nav.mapdata.models.theme import Theme
return make_themes(Theme.objects.all())
@mapdata_cache
def css_themes_public():
from c3nav.mapdata.models.theme import Theme
return make_themes(Theme.objects.filter(public=True))
def random_color():
import random
return settings.RANDOM_PRIMARY_COLOR_LIST[random.randrange(0, 360)]
def get_random_primary_color(request):
if settings.PRIMARY_COLOR_RANDOMISATION['mode'] == 'off':
return settings.BASE_THEME['css']['primary']
elif settings.PRIMARY_COLOR_RANDOMISATION['mode'] == 'request':
return random_color()
elif settings.PRIMARY_COLOR_RANDOMISATION['mode'] == 'session':
if 'randomized_primary_color' not in request.session:
request.session['randomized_primary_color'] = random_color()
return request.session['randomized_primary_color']
elif settings.PRIMARY_COLOR_RANDOMISATION['mode'] == 'time':
from django.core.cache import cache
color = cache.get('randomized_primary_color', None)
if color is None:
color = random_color()
cache.set('randomized_primary_color', color, settings.PRIMARY_COLOR_RANDOMISATION['duration'].total_seconds())
return color