diff --git a/frontends/ycdl_flask/backend/common.py b/frontends/ycdl_flask/backend/common.py index 532e01a..39188b9 100644 --- a/frontends/ycdl_flask/backend/common.py +++ b/frontends/ycdl_flask/backend/common.py @@ -3,6 +3,7 @@ Do not execute this file directly. Use ycdl_flask_dev.py or ycdl_flask_prod.py. ''' import flask; from flask import request +import functools import threading import time @@ -65,6 +66,29 @@ def after_request(response): response = flasktools.gzip_response(request, response) return response +site.route = flasktools.decorate_and_route( + flask_app=site, + decorators=[ + flasktools.ensure_response_type, + functools.partial( + flasktools.give_theme_cookie, + cookie_name='ycdl_theme', + default_theme='slate', + ), + ], +) + +def render_template(request, template_name, **kwargs): + theme = request.cookies.get('ycdl_theme', None) + + response = flask.render_template( + template_name, + request=request, + theme=theme, + **kwargs, + ) + return response + #################################################################################################### # These functions will be called by the launcher, flask_dev, flask_prod. diff --git a/frontends/ycdl_flask/backend/endpoints/basic_endpoints.py b/frontends/ycdl_flask/backend/endpoints/basic_endpoints.py index c140321..48b04cc 100644 --- a/frontends/ycdl_flask/backend/endpoints/basic_endpoints.py +++ b/frontends/ycdl_flask/backend/endpoints/basic_endpoints.py @@ -6,7 +6,7 @@ site = common.site @site.route('/') def root(): - return flask.render_template('root.html') + return common.render_template(request, 'root.html') @site.route('/favicon.ico') @site.route('/favicon.png') diff --git a/frontends/ycdl_flask/backend/endpoints/channel_endpoints.py b/frontends/ycdl_flask/backend/endpoints/channel_endpoints.py index 8ed422b..a62be85 100644 --- a/frontends/ycdl_flask/backend/endpoints/channel_endpoints.py +++ b/frontends/ycdl_flask/backend/endpoints/channel_endpoints.py @@ -31,7 +31,7 @@ def get_all_channel_names(): @site.route('/channels') def get_channels(): channels = common.ycdldb.get_channels() - return flask.render_template('channels.html', channels=channels) + return common.render_template(request, 'channels.html', channels=channels) def _render_videos_listing(videos, channel, state, orderby): search_terms = request.args.get('q', '').lower().strip().replace('+', ' ').split() @@ -55,7 +55,8 @@ def _render_videos_listing(videos, channel, state, orderby): all_states = common.ycdldb.get_all_states() - return flask.render_template( + return common.render_template( + request, 'channel.html', all_states=all_states, channel=channel, diff --git a/frontends/ycdl_flask/static/css/theme_onyx.css b/frontends/ycdl_flask/static/css/theme_onyx.css new file mode 100644 index 0000000..8e11a08 --- /dev/null +++ b/frontends/ycdl_flask/static/css/theme_onyx.css @@ -0,0 +1,71 @@ +:root +{ + --color_primary: #000; + --color_secondary: #3b4d5d; + + --color_text_normal: #ccc; + --color_text_link: #1edeff; + --color_text_bubble: black; + + --color_textfields: var(--color_primary); + --color_text_placeholder: gray; + + --color_selection: rgba(0, 0, 255, 0.5); + --color_transparency: rgba(0, 0, 0, 0.0); + --color_dropshadow: rgba(0, 0, 0, 0.25); + --color_shadow: rgba(0, 0, 0, 0.5); + --color_highlight: rgba(255, 255, 255, 0.5); +} + +button, +button * +{ + color: black; +} + +.tab_buttons button +{ + color: var(--color_text_normal); +} + +input, +textarea, +.nice_link, +.panel +{ + border: 1px solid var(--color_text_normal); +} + +.channel_card +{ + padding: 10px; + border-radius: 4px; + border: 1px solid black; +} + +.video_card:hover +{ + box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); +} +.channel_card_pending, +.video_card_pending +{ + border: 2px solid #ffffaa; + background-color: rgba(255, 255, 170, 0.25); +} +.video_card_ignored +{ + border: 2px solid #ffc886; + background-color: rgba(255, 200, 134, 0.25); +} +.video_card_selected +{ + border: 2px solid #13f4ff !important; + background-color: rgba(19, 244, 255, 0.25) !important; +} +.channel_card_no_pending, +.video_card_downloaded +{ + border: 2px solid #aaffaa; + background-color: rgba(170, 255, 170, 0.25); +} diff --git a/frontends/ycdl_flask/static/css/theme_pearl.css b/frontends/ycdl_flask/static/css/theme_pearl.css new file mode 100644 index 0000000..fa947a0 --- /dev/null +++ b/frontends/ycdl_flask/static/css/theme_pearl.css @@ -0,0 +1,62 @@ +:root +{ + --color_primary: #f6ffff; + --color_secondary: #aad7ff; + + --color_text_normal: black; + --color_text_link: #00f; + --color_text_bubble: black; + + --color_textfields: white; + --color_text_placeholder: gray; + + --color_transparency: rgba(0, 0, 0, 0.1); + --color_dropshadow: rgba(0, 0, 0, 0.25); + --color_shadow: rgba(0, 0, 0, 0.5); + --color_highlight: rgba(255, 255, 255, 0.5); + + --color_tag_card_bg: #fff; + --color_tag_card_fg: black; +} + +.channel_card +{ + padding: 10px; + border-radius: 4px; + border: 1px solid black; +} + +.channel_card_pending +{ + background-color: #ffffaa; +} + +.channel_card_no_pending +{ + background-color: #aaffaa; +} + +.video_card +{ + border: 1px solid #000; +} +.video_card:hover +{ + box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); +} +.video_card_pending +{ + background-color: #ffffaa; +} +.video_card_ignored +{ + background-color: #ffc886; +} +.video_card_selected +{ + background-color: #13f4ff !important; +} +.video_card_downloaded +{ + background-color: #aaffaa; +} diff --git a/frontends/ycdl_flask/static/css/theme_slate.css b/frontends/ycdl_flask/static/css/theme_slate.css new file mode 100644 index 0000000..0ff9e80 --- /dev/null +++ b/frontends/ycdl_flask/static/css/theme_slate.css @@ -0,0 +1,65 @@ +:root +{ + --color_primary: #222; + --color_secondary: #3b4d5d; + + --color_text_normal: #efefef; + --color_text_link: #1edeff; + --color_text_bubble: black; + + --color_textfields: var(--color_secondary); + --color_text_placeholder: gray; + + --color_transparency: rgba(255, 255, 255, 0.05); + --color_dropshadow: rgba(0, 0, 0, 0.25); + --color_shadow: rgba(0, 0, 0, 0.5); + --color_highlight: rgba(255, 255, 255, 0.5); + + --color_tag_card_bg: #e6e6e6; + --color_tag_card_fg: black; +} + +button, +button * +{ + color: black; +} + +.tab_buttons button +{ + color: var(--color_text_normal); +} + +.channel_card +{ + padding: 10px; + border-radius: 4px; + border: 1px solid black; +} + +.video_card:hover +{ + box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); +} +.channel_card_pending, +.video_card_pending +{ + border: 2px solid #ffffaa; + background-color: rgba(255, 255, 170, 0.25); +} +.video_card_ignored +{ + border: 2px solid #ffc886; + background-color: rgba(255, 200, 134, 0.25); +} +.video_card_selected +{ + border: 2px solid #13f4ff !important; + background-color: rgba(19, 244, 255, 0.25) !important; +} +.channel_card_no_pending, +.video_card_downloaded +{ + border: 2px solid #aaffaa; + background-color: rgba(170, 255, 170, 0.25); +} diff --git a/frontends/ycdl_flask/static/css/ycdl.css b/frontends/ycdl_flask/static/css/ycdl.css index 87e3e26..09bfa4c 100644 --- a/frontends/ycdl_flask/static/css/ycdl.css +++ b/frontends/ycdl_flask/static/css/ycdl.css @@ -2,22 +2,9 @@ This file contains styles that apply to all pages within YCDL, but don't belong in common.css because they are specifically for this project. */ - -:root +html { - --color_primary: white; - - --color_text_normal: black; - --color_text_link: blue; - --color_text_bubble: var(--color_text_normal); - - --color_textfields: white; - --color_text_placeholder: gray; - - --color_transparency: rgba(0, 0, 0, 0.1); - --color_dropshadow: rgba(0, 0, 0, 0.25); - --color_shadow: rgba(0, 0, 0, 0.5); - --color_highlight: rgba(255, 255, 255, 0.5); + font-family: sans-serif; } .navigation_link:hover diff --git a/frontends/ycdl_flask/templates/channel.html b/frontends/ycdl_flask/templates/channel.html index 76b8d77..f192d4e 100644 --- a/frontends/ycdl_flask/templates/channel.html +++ b/frontends/ycdl_flask/templates/channel.html @@ -8,6 +8,7 @@ + {% if theme %}{% endif %} @@ -41,27 +42,6 @@ padding: 8px; border-radius: 4px; - border: 1px solid #000; -} -.video_card:hover -{ - box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); -} -.video_card_pending -{ - background-color: #ffffaa; -} -.video_card_ignored -{ - background-color: #ffc886; -} -.video_card_selected -{ - background-color: #13f4ff !important; -} -.video_card_downloaded -{ - background-color: #aaffaa; } .video_thumbnail @@ -409,10 +389,6 @@ function deselect_all() video_card_first_selected = null; for (const video_card of Array.from(video_card_selections)) { - if (video_card.classList.contains("hidden")) - { - continue; - } video_card.classList.remove("video_card_selected"); } } diff --git a/frontends/ycdl_flask/templates/channels.html b/frontends/ycdl_flask/templates/channels.html index 311ff8c..89d883e 100644 --- a/frontends/ycdl_flask/templates/channels.html +++ b/frontends/ycdl_flask/templates/channels.html @@ -8,6 +8,7 @@ + {% if theme %}{% endif %} @@ -31,17 +32,6 @@ { padding: 10px; border-radius: 4px; - border: 1px solid black; -} - -.channel_card_pending -{ - background-color: #ffffaa; -} - -.channel_card_no_pending -{ - background-color: #aaffaa; } diff --git a/frontends/ycdl_flask/templates/root.html b/frontends/ycdl_flask/templates/root.html index ae1d36f..80eb9f9 100644 --- a/frontends/ycdl_flask/templates/root.html +++ b/frontends/ycdl_flask/templates/root.html @@ -7,9 +7,10 @@ + {% if theme %}{% endif %}