956 Code changes to enable dark mode

pull/1185/head
tanc 2 years ago
parent 87726e0bb2
commit 427cf105a3

@ -202,7 +202,8 @@ def changedetection_app(config=None, datastore_o=None):
watch_api.add_resource(api_v1.SystemInfo, '/api/v1/systeminfo', watch_api.add_resource(api_v1.SystemInfo, '/api/v1/systeminfo',
resource_class_kwargs={'datastore': datastore, 'update_q': update_q}) resource_class_kwargs={'datastore': datastore, 'update_q': update_q})
def getDarkModeSetting():
return datastore.data['settings']['application']['css_dark_mode']
# Setup cors headers to allow all domains # Setup cors headers to allow all domains
# https://flask-cors.readthedocs.io/en/latest/ # https://flask-cors.readthedocs.io/en/latest/
@ -403,6 +404,7 @@ def changedetection_app(config=None, datastore_o=None):
form = forms.quickWatchForm(request.form) form = forms.quickWatchForm(request.form)
output = render_template("watch-overview.html", output = render_template("watch-overview.html",
dark_mode=getDarkModeSetting(),
form=form, form=form,
watches=sorted_watches, watches=sorted_watches,
tags=existing_tags, tags=existing_tags,
@ -661,6 +663,7 @@ def changedetection_app(config=None, datastore_o=None):
browser_steps_config=browser_step_ui_config, browser_steps_config=browser_step_ui_config,
current_base_url=datastore.data['settings']['application']['base_url'], current_base_url=datastore.data['settings']['application']['base_url'],
emailprefix=os.getenv('NOTIFICATION_MAIL_BUTTON_PREFIX', False), emailprefix=os.getenv('NOTIFICATION_MAIL_BUTTON_PREFIX', False),
dark_mode=getDarkModeSetting(),
form=form, form=form,
has_default_notification_urls=True if len(datastore.data['settings']['application']['notification_urls']) else False, has_default_notification_urls=True if len(datastore.data['settings']['application']['notification_urls']) else False,
has_empty_checktime=using_default_check_time, has_empty_checktime=using_default_check_time,
@ -748,6 +751,7 @@ def changedetection_app(config=None, datastore_o=None):
output = render_template("settings.html", output = render_template("settings.html",
form=form, form=form,
dark_mode=getDarkModeSetting(),
current_base_url = datastore.data['settings']['application']['base_url'], current_base_url = datastore.data['settings']['application']['base_url'],
hide_remove_pass=os.getenv("SALTED_PASS", False), hide_remove_pass=os.getenv("SALTED_PASS", False),
api_key=datastore.data['settings']['application'].get('api_access_token'), api_key=datastore.data['settings']['application'].get('api_access_token'),
@ -788,6 +792,7 @@ def changedetection_app(config=None, datastore_o=None):
# Could be some remaining, or we could be on GET # Could be some remaining, or we could be on GET
output = render_template("import.html", output = render_template("import.html",
dark_mode=getDarkModeSetting(),
import_url_list_remaining="\n".join(remaining_urls), import_url_list_remaining="\n".join(remaining_urls),
original_distill_json='' original_distill_json=''
) )
@ -865,6 +870,7 @@ def changedetection_app(config=None, datastore_o=None):
newest=newest_version_file_contents, newest=newest_version_file_contents,
previous=previous_version_file_contents, previous=previous_version_file_contents,
extra_stylesheets=extra_stylesheets, extra_stylesheets=extra_stylesheets,
dark_mode=getDarkModeSetting(),
versions=dates[:-1], # All except current/last versions=dates[:-1], # All except current/last
uuid=uuid, uuid=uuid,
newest_version_timestamp=dates[-1], newest_version_timestamp=dates[-1],
@ -912,6 +918,7 @@ def changedetection_app(config=None, datastore_o=None):
content=content, content=content,
history_n=watch.history_n, history_n=watch.history_n,
extra_stylesheets=extra_stylesheets, extra_stylesheets=extra_stylesheets,
dark_mode=getDarkModeSetting(),
# current_diff_url=watch['url'], # current_diff_url=watch['url'],
watch=watch, watch=watch,
uuid=uuid, uuid=uuid,
@ -958,6 +965,7 @@ def changedetection_app(config=None, datastore_o=None):
content=content, content=content,
history_n=watch.history_n, history_n=watch.history_n,
extra_stylesheets=extra_stylesheets, extra_stylesheets=extra_stylesheets,
dark_mode=getDarkModeSetting(),
ignored_line_numbers=ignored_line_numbers, ignored_line_numbers=ignored_line_numbers,
triggered_line_numbers=trigger_line_numbers, triggered_line_numbers=trigger_line_numbers,
current_diff_url=watch['url'], current_diff_url=watch['url'],
@ -976,6 +984,7 @@ def changedetection_app(config=None, datastore_o=None):
def notification_logs(): def notification_logs():
global notification_debug_log global notification_debug_log
output = render_template("notification-log.html", output = render_template("notification-log.html",
dark_mode=getDarkModeSetting(),
logs=notification_debug_log if len(notification_debug_log) else ["Notification logs are empty - no notifications sent yet."]) logs=notification_debug_log if len(notification_debug_log) else ["Notification logs are empty - no notifications sent yet."])
return output return output
@ -1204,6 +1213,14 @@ def changedetection_app(config=None, datastore_o=None):
flash("{} watches are queued for rechecking.".format(i)) flash("{} watches are queued for rechecking.".format(i))
return redirect(url_for('index', tag=tag)) return redirect(url_for('index', tag=tag))
@app.route("/toggle-theme", methods=['GET'])
@login_required
def toggle_theme():
current_mode = datastore.data['settings']['application']['css_dark_mode']
new_mode = not current_mode
datastore.data['settings']['application']['css_dark_mode'] = new_mode
return ''
@app.route("/form/checkbox-operations", methods=['POST']) @app.route("/form/checkbox-operations", methods=['POST'])
@login_required @login_required
def form_watch_list_checkbox_operations(): def form_watch_list_checkbox_operations():

@ -27,6 +27,7 @@ class model(dict):
'base_url' : None, 'base_url' : None,
'extract_title_as_title': False, 'extract_title_as_title': False,
'empty_pages_are_a_change': False, 'empty_pages_are_a_change': False,
'css_dark_mode': False,
'fetch_backend': getenv("DEFAULT_FETCH_BACKEND", "html_requests"), 'fetch_backend': getenv("DEFAULT_FETCH_BACKEND", "html_requests"),
'filter_failure_notification_threshold_attempts': _FILTER_FAILURE_THRESHOLD_ATTEMPTS_DEFAULT, 'filter_failure_notification_threshold_attempts': _FILTER_FAILURE_THRESHOLD_ATTEMPTS_DEFAULT,
'global_ignore_text': [], # List of text to ignore when calculating the comparison checksum 'global_ignore_text': [], # List of text to ignore when calculating the comparison checksum

@ -1,16 +1,17 @@
var a = document.getElementById('a'); var a = document.getElementById("a");
var b = document.getElementById('b'); var b = document.getElementById("b");
var result = document.getElementById('result'); var result = document.getElementById("result");
function changed() { function changed() {
// https://github.com/kpdecker/jsdiff/issues/389 // https://github.com/kpdecker/jsdiff/issues/389
// I would love to use `{ignoreWhitespace: true}` here but it breaks the formatting // I would love to use `{ignoreWhitespace: true}` here but it breaks the formatting
options = {ignoreWhitespace: document.getElementById('ignoreWhitespace').checked}; options = {
ignoreWhitespace: document.getElementById("ignoreWhitespace").checked,
};
var diff = Diff[window.diffType](a.textContent, b.textContent, options); var diff = Diff[window.diffType](a.textContent, b.textContent, options);
var fragment = document.createDocumentFragment(); var fragment = document.createDocumentFragment();
for (var i = 0; i < diff.length; i++) { for (var i = 0; i < diff.length; i++) {
if (diff[i].added && diff[i + 1] && diff[i + 1].removed) { if (diff[i].added && diff[i + 1] && diff[i + 1].removed) {
var swap = diff[i]; var swap = diff[i];
diff[i] = diff[i + 1]; diff[i] = diff[i + 1];
@ -19,21 +20,22 @@ function changed() {
var node; var node;
if (diff[i].removed) { if (diff[i].removed) {
node = document.createElement('del'); node = document.createElement("del");
node.classList.add("change"); node.classList.add("change");
node.appendChild(document.createTextNode(diff[i].value)); const wrapper = node.appendChild(document.createElement("span"));
wrapper.appendChild(document.createTextNode(diff[i].value));
} else if (diff[i].added) { } else if (diff[i].added) {
node = document.createElement('ins'); node = document.createElement("ins");
node.classList.add("change"); node.classList.add("change");
node.appendChild(document.createTextNode(diff[i].value)); const wrapper = node.appendChild(document.createElement("span"));
wrapper.appendChild(document.createTextNode(diff[i].value));
} else { } else {
node = document.createTextNode(diff[i].value); node = document.createTextNode(diff[i].value);
} }
fragment.appendChild(node); fragment.appendChild(node);
} }
result.textContent = ''; result.textContent = "";
result.appendChild(fragment); result.appendChild(fragment);
// Jump at start // Jump at start
@ -42,11 +44,9 @@ function changed() {
} }
window.onload = function () { window.onload = function () {
/* Convert what is options from UTC time.time() to local browser time */ /* Convert what is options from UTC time.time() to local browser time */
var diffList = document.getElementById("diff-version"); var diffList = document.getElementById("diff-version");
if (typeof (diffList) != 'undefined' && diffList != null) { if (typeof diffList != "undefined" && diffList != null) {
for (var option of diffList.options) { for (var option of diffList.options) {
var dateObject = new Date(option.value * 1000); var dateObject = new Date(option.value * 1000);
option.label = dateObject.toLocaleString(); option.label = dateObject.toLocaleString();
@ -55,16 +55,17 @@ window.onload = function () {
/* Set current version date as local time in the browser also */ /* Set current version date as local time in the browser also */
var current_v = document.getElementById("current-v-date"); var current_v = document.getElementById("current-v-date");
var dateObject = new Date(newest_version_timestamp*1000); var dateObject = new Date(newest_version_timestamp * 1000);
current_v.innerHTML = dateObject.toLocaleString(); current_v.innerHTML = dateObject.toLocaleString();
onDiffTypeChange(document.querySelector('#settings [name="diff_type"]:checked')); onDiffTypeChange(
document.querySelector('#settings [name="diff_type"]:checked'),
);
changed(); changed();
}; };
a.onpaste = a.onchange = a.onpaste = a.onchange = b.onpaste = b.onchange = changed;
b.onpaste = b.onchange = changed;
if ('oninput' in a) { if ("oninput" in a) {
a.oninput = b.oninput = changed; a.oninput = b.oninput = changed;
} else { } else {
a.onkeyup = b.onkeyup = changed; a.onkeyup = b.onkeyup = changed;
@ -72,29 +73,26 @@ if ('oninput' in a) {
function onDiffTypeChange(radio) { function onDiffTypeChange(radio) {
window.diffType = radio.value; window.diffType = radio.value;
// Not necessary // Not necessary
// document.title = "Diff " + radio.value.slice(4); // document.title = "Diff " + radio.value.slice(4);
} }
var radio = document.getElementsByName('diff_type'); var radio = document.getElementsByName("diff_type");
for (var i = 0; i < radio.length; i++) { for (var i = 0; i < radio.length; i++) {
radio[i].onchange = function (e) { radio[i].onchange = function (e) {
onDiffTypeChange(e.target); onDiffTypeChange(e.target);
changed(); changed();
} };
} }
document.getElementById('ignoreWhitespace').onchange = function (e) { document.getElementById("ignoreWhitespace").onchange = function (e) {
changed(); changed();
} };
var inputs = document.getElementsByClassName('change'); var inputs = document.getElementsByClassName("change");
inputs.current = 0; inputs.current = 0;
function next_diff() { function next_diff() {
var element = inputs[inputs.current]; var element = inputs[inputs.current];
var headerOffset = 80; var headerOffset = 80;
var elementPosition = element.getBoundingClientRect().top; var elementPosition = element.getBoundingClientRect().top;
@ -102,7 +100,7 @@ function next_diff() {
window.scrollTo({ window.scrollTo({
top: offsetPosition, top: offsetPosition,
behavior: "smooth" behavior: "smooth",
}); });
inputs.current++; inputs.current++;

@ -0,0 +1,26 @@
/**
* @file
* Toggles theme between light and dark mode.
*/
$(document).ready(function () {
const url = "/toggle-theme";
const button = document.getElementsByClassName("toggle-theme")[0];
button.onclick = () => {
fetch(url)
.then(function () {
const htmlElement = document.getElementsByTagName("html");
const isDarkMode = htmlElement[0].dataset.darkmode === "true";
htmlElement[0].dataset.darkmode = !isDarkMode;
if (isDarkMode) {
button.classList.remove("dark");
} else {
button.classList.add("dark");
}
})
.catch(function (e) {
console.log("Can't toggle the theme. Error was: ", e);
});
};
});
Loading…
Cancel
Save