Dark/Light Theme feature added (#133)

This commit is contained in:
Chris Caron 2023-09-02 19:14:08 -04:00 committed by GitHub
parent e6700d1269
commit 42893d7855
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 163 additions and 16 deletions

View File

@ -285,6 +285,7 @@ The use of environment variables allow you to provide over-rides to default sett
| Variable | Description |
|--------------------- | ----------- |
| `APPRISE_DEFAULT_THEME` | Can be set to `light` or `dark`; it defaults to `light` if not otherwise provided. The theme can be toggled from within the website as well.
| `APPRISE_CONFIG_DIR` | Defines an (optional) persistent store location of all configuration files saved. By default:<br/> - Configuration is written to the `apprise_api/var/config` directory when just using the _Django_ `manage runserver` script. However for the path for the container is `/config`.
| `APPRISE_ATTACH_DIR` | The directory the uploaded attachments are placed in. By default:<br/> - Attachments are written to the `apprise_api/var/attach` directory when just using the _Django_ `manage runserver` script. However for the path for the container is `/attach`.
| `APPRISE_ATTACH_SIZE` | Over-ride the attachment size (defined in MB). By default it is set to `200` (Megabytes). You can set this up to a maximum value of `500` which is the restriction in place for NginX (internal hosting ervice) at this time. If you set this to zero (`0`) then attachments will not be passed along even if provided.

View File

@ -7,14 +7,14 @@
<meta charset="utf-8">
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!--highlightjs-->
<link rel="stylesheet" href="{% static 'css/highlight.min.css' %}">
<!--materialize-->
<link rel="stylesheet" href="{% static 'css/materialize.min.css' %}" />
<link rel="stylesheet" href="{% get_static_prefix %}css/{{request.theme|safe}}/materialize.min.css" />
<!--material-design-icons-->
<link rel="stylesheet" href="{% static 'iconfont/material-icons.css' %}">
<!--common-->
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
<!--highlightjs-->
<link rel="stylesheet" href="{% get_static_prefix %}css/{{request.theme|safe}}/highlight.min.css">
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}" />
<!--materialize-->
<script src="{% static 'js/materialize.min.js' %}"></script>
@ -28,13 +28,16 @@
<body>
<div class="content">
<!-- Title -->
<div class="nav row teal lighten-5 z-depth-2">
<div class="nav row nav-color z-depth-2">
<div class="col s12">
<a href="{% url 'welcome' %}">
<img class="left" src="{% static "logo.png" %}" alt="{% trans "Apprise Logo" %}" />
</a>
<h1>{% trans "Apprise API" %}</h1>
<i>APPRISE v{{APPRISE_VERSION}}</i>
<ul>
<li>APPRISE v{{APPRISE_VERSION}}</li>
<li class="theme"><a href="{{ request.path }}?theme={{request.next_theme}}"><span class="tiny material-icons">invert_colors</span></a></li>
</ul>
</div>
</div>
<!-- Page Layout here -->
@ -43,29 +46,29 @@
<div class="col s3" style="width:20em">
{% if STATEFUL_MODE != 'disabled' %}
<ul class="collection z-depth-1">
<a class="collection-item" href="{% url 'config' 'apprise' %}"><i class="tiny material-icons">settings</i>
<a class="collection-item" href="{% url 'config' 'apprise' %}"><i class="material-icons">settings</i>
{% trans "Configuration Manager" %}</a>
</ul>
{% endif %}
<ul class="collection z-depth-1">
<a class="collection-item" href="{% url 'details' %}"><i class="tiny material-icons">settings</i>
<a class="collection-item" href="{% url 'details' %}"><i class="material-icons">settings</i>
{% trans "Apprise Details" %}</a>
<a class="collection-item" target="_blank"
href="https://github.com/caronc/apprise/wiki#notification-services">📣
{% trans "Notification Services" %}</a>
<a class="collection-item" target="_blank" href="https://github.com/caronc/apprise/wiki/config"><i
class="tiny material-icons">local_library</i> {% trans "Configuration Help" %}</a>
class="material-icons">local_library</i> {% trans "Configuration Help" %}</a>
<a class="collection-item" target="_blank" href="https://github.com/caronc/apprise/wiki/Troubleshooting"><i
class="tiny material-icons">build</i> {% trans "Troubleshooting" %}</a>
class="material-icons">build</i> {% trans "Troubleshooting" %}</a>
<a class="collection-item" target="_blank" href="https://github.com/caronc/apprise/wiki/CLI_Usage"><i
class="tiny material-icons">lightbulb_outline</i> {% trans "Using the CLI" %}</a>
class="material-icons">lightbulb_outline</i> {% trans "Using the CLI" %}</a>
</ul>
<ul class="collection z-depth-1">
<a class="collection-item" target="_blank"
href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MHANV39UZNQ5E"><i
class="tiny material-icons" style="color: maroon;">free_breakfast</i> <strong>{% trans "Buy Developer A Coffee" %}</strong></a>
class="material-icons" style="color: maroon;">free_breakfast</i> <strong>{% trans "Buy Developer A Coffee" %}</strong></a>
<a class="collection-item" target="_blank" href="https://github.com/sponsors/caronc"><i
class="tiny material-icons" style="color: red;">favorite</i> <strong>{% trans "Sponsor Apprise Development" %}</strong></a>
class="material-icons" style="color: red;">favorite</i> <strong>{% trans "Sponsor Apprise Development" %}</strong></a>
</ul>
{% block menu %}{% endblock %}
</div>

View File

View File

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2023 Chris Caron <lead2gold@gmail.com>
# All rights reserved.
#
# This code is licensed under the MIT License.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files(the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
from django.conf import settings
from core.themes import SiteTheme, SITE_THEMES
import datetime
class AutoThemeMiddleware:
"""
Using the `theme=` variable, allow one to fix the language to either
'dark' or 'light'
"""
def __init__(self, get_response):
"""
Prepare our initialization
"""
self.get_response = get_response
def __call__(self, request):
"""
Define our middleware hook
"""
# Our current theme
current_theme = \
request.COOKIES.get('t', request.COOKIES.get(
'theme', settings.APPRISE_DEFAULT_THEME))
# Extract our theme (fall back to our default if not set)
theme = request.GET.get("theme", current_theme).strip().lower()
theme = next((entry for entry in SITE_THEMES
if entry.startswith(theme)), None) \
if theme else None
if theme not in SITE_THEMES:
# Fallback to default theme
theme = SiteTheme.LIGHT
# Set our theme to a cookie
request.theme = theme
# Set our next theme
request.next_theme = SiteTheme.LIGHT \
if theme == SiteTheme.DARK \
else SiteTheme.DARK
# Get our response object
response = self.get_response(request)
# Set our cookie
max_age = 365 * 24 * 60 * 60 # 1 year
expires = datetime.datetime.utcnow() + \
datetime.timedelta(seconds=max_age)
# Set our cookie
response.set_cookie('theme', theme, expires=expires.utctimetuple())
# return our response
return response

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com>
# Copyright (C) 2023 Chris Caron <lead2gold@gmail.com>
# All rights reserved.
#
# This code is licensed under the MIT License.
@ -23,6 +23,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import os
from core.themes import SiteTheme
# Disable Timezones
USE_TZ = False
@ -64,6 +65,7 @@ INSTALLED_APPS = [
MIDDLEWARE = [
'django.middleware.common.CommonMiddleware',
'core.middleware.theme.AutoThemeMiddleware',
]
ROOT_URLCONF = 'core.urls'
@ -111,6 +113,7 @@ LOGGING = {
}
}
WSGI_APPLICATION = 'core.wsgi.application'
# Define our base URL
@ -120,6 +123,10 @@ BASE_URL = os.environ.get('BASE_URL', '')
# Static files relative path (CSS, JavaScript, Images)
STATIC_URL = BASE_URL + '/s/'
# Default theme can be either 'light' or 'dark'
APPRISE_DEFAULT_THEME = \
os.environ.get('APPRISE_DEFAULT_THEME', SiteTheme.LIGHT)
# The location to store Apprise configuration files
APPRISE_CONFIG_DIR = os.environ.get(
'APPRISE_CONFIG_DIR', os.path.join(BASE_DIR, 'var', 'config'))

View File

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com>
# All rights reserved.
#
# This code is licensed under the MIT License.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files(the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
class SiteTheme:
"""
Defines our site themes
"""
LIGHT = 'light'
DARK = 'dark'
SITE_THEMES = (
SiteTheme.LIGHT,
SiteTheme.DARK,
)

View File

@ -7,11 +7,16 @@
}
/* Apprise Version */
.nav i {
.nav ul {
float: right;
font-style: normal;
font-size: 0.7rem;
}
.theme {
text-align: right;
display: block;
float:right;
}
input {
display: block;

View File

@ -0,0 +1 @@
.nav.nav-color{background:#4c566a!important}.hljs{display:block;overflow-x:auto;padding:.5em;color:#d8dee9;background:#4c566a;transition:box-shadow .25s,-webkit-box-shadow .25s!important;border-radius:2px!important}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#bf616a}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#a3be8c}.hljs-bullet,.hljs-symbol{color:#b48ead}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.no-config .info{color: #4c566a}.tabs .tab a:hover, .tabs .tab a.active {color: #4c566a}.theme a {color: #d8dee9}.url-enabled{color: #02c7a6}.url-disabled{color:#e00202}.btn, .btn-large,.btn-small {background-color:#333}.btn-large:hover, .btn-small:hover, .btn:hover {background-color:#222}i.material-icons{color:#6e7d9c}i.material-icons:hover{color:#57637a}.nav h1{color:#d8dee9!important}

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
/* GitHub highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org> */
.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}

View File

@ -0,0 +1,2 @@
/* GitHub highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org> */
.nav.nav-color{background:#8fbcbb!important}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}a {color: #333}