147 lines
No EOL
5.5 KiB
Python
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 |