Skip to content

Commit 35a34b0

Browse files
committed
Merge branch 'miscs'
2 parents 4347e92 + a5c6407 commit 35a34b0

File tree

16 files changed

+579
-79
lines changed

16 files changed

+579
-79
lines changed

Diff for: .pre-commit-config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ repos:
4141
- id: insert-license
4242
name: Insert license header on JS files
4343
files: ^legadilo/.*\.js$
44+
exclude: theme_chooser\.js$
4445
args:
4546
- --license-filepath
4647
- "./devops/license-header-template.txt"

Diff for: CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## 24.12.4
4+
5+
- Use the theme (light or dark) that matches the system theme.
6+
- Add a theme selector.
7+
- Use a switch to enable/disable read on scroll. This is more visible and is clearer than what we had before.
8+
- Don’t disable feeds when saving modifications with enter.
9+
- Prevent a display issue when linking new email addresses.
10+
11+
## 24.12.3
12+
13+
- Small adjustments for extensions.
14+
- Add a privacy policy page.
15+
316
## 24.12.2
417

518
- Add a privacy policy to release the extension on Chrome webstore.

Diff for: legadilo/static/css/base.css

+15-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ html {
4242

4343
.btn-primary img.bi,
4444
.btn-danger img.bi {
45-
filter: invert(1);
45+
filter: invert(1) !important;
4646
}
4747

4848
.htmx-indicator,
@@ -114,3 +114,17 @@ html {
114114
height: var(--content-footer-height);
115115
}
116116
}
117+
118+
/* For the theme switcher */
119+
svg.bi {
120+
width: 1rem;
121+
height: 1rem;
122+
}
123+
124+
.bd-navbar .dropdown-menu .active .bi {
125+
display: block !important;
126+
}
127+
128+
[data-bs-theme="dark"] img.bi {
129+
filter: invert(0.715);
130+
}

Diff for: legadilo/static/js/list_of_articles.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
};
7676

7777
const readOnScroll = () => {
78-
const isReadOnScrollCheckboxTicked = document.getElementById("read-on-scroll-enabled").checked;
78+
const isReadOnScrollCheckboxTicked = document.getElementById("read-on-scroll-status").checked;
7979

8080
if (!isReadOnScrollCheckboxTicked) {
8181
return;

Diff for: legadilo/static/js/theme_chooser.js

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*!
2+
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
3+
* Copyright 2011-2024 The Bootstrap Authors
4+
* Licensed under the Creative Commons Attribution 3.0 Unported License.
5+
*/
6+
7+
// https://getbootstrap.com/docs/5.3/customize/color-modes/#javascript
8+
9+
(() => {
10+
"use strict";
11+
12+
const getStoredTheme = () => localStorage.getItem("theme");
13+
const setStoredTheme = (theme) => localStorage.setItem("theme", theme);
14+
15+
const getPreferredTheme = () => {
16+
const storedTheme = getStoredTheme();
17+
if (storedTheme) {
18+
return storedTheme;
19+
}
20+
21+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
22+
};
23+
24+
const setTheme = (theme) => {
25+
if (theme === "auto") {
26+
document.documentElement.setAttribute(
27+
"data-bs-theme",
28+
window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light",
29+
);
30+
} else {
31+
document.documentElement.setAttribute("data-bs-theme", theme);
32+
}
33+
};
34+
35+
setTheme(getPreferredTheme());
36+
37+
const showActiveTheme = (theme, focus = false) => {
38+
const themeSwitcher = document.querySelector("#bd-theme");
39+
40+
if (!themeSwitcher) {
41+
return;
42+
}
43+
44+
const themeSwitcherText = document.querySelector("#bd-theme-text");
45+
const activeThemeIcon = document.querySelector(".theme-icon-active use");
46+
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`);
47+
const svgOfActiveBtn = btnToActive.querySelector("svg use").getAttribute("href");
48+
49+
document.querySelectorAll("[data-bs-theme-value]").forEach((element) => {
50+
element.classList.remove("active");
51+
element.setAttribute("aria-pressed", "false");
52+
});
53+
54+
btnToActive.classList.add("active");
55+
btnToActive.setAttribute("aria-pressed", "true");
56+
activeThemeIcon.setAttribute("href", svgOfActiveBtn);
57+
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`;
58+
themeSwitcher.setAttribute("aria-label", themeSwitcherLabel);
59+
60+
if (focus) {
61+
themeSwitcher.focus();
62+
}
63+
};
64+
65+
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
66+
const storedTheme = getStoredTheme();
67+
if (storedTheme !== "light" && storedTheme !== "dark") {
68+
setTheme(getPreferredTheme());
69+
}
70+
});
71+
72+
window.addEventListener("DOMContentLoaded", () => {
73+
showActiveTheme(getPreferredTheme());
74+
75+
document.querySelectorAll("[data-bs-theme-value]").forEach((toggle) => {
76+
toggle.addEventListener("click", () => {
77+
const theme = toggle.getAttribute("data-bs-theme-value");
78+
setStoredTheme(theme);
79+
setTheme(theme);
80+
showActiveTheme(theme, true);
81+
});
82+
});
83+
});
84+
})();

Diff for: legadilo/templates/account/email.html

+1-6
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,7 @@ <h1>{% translate "E-mail Addresses" %}</h1>
7070
</p>
7171
{% endif %}
7272
<h2>{% translate "Add E-mail Address" %}</h2>
73-
<form method="post"
74-
action="{% url 'account_email' %}"
75-
class="add_email"
76-
hx-boost="true"
77-
hx-push-url="false"
78-
hx-indicator=".icon-indicator">
73+
<form method="post" action="{% url 'account_email' %}" class="add_email">
7974
{% csrf_token %}
8075
{{ form|crispy }}
8176
<button class="btn btn-primary" name="action_add" type="submit">

Diff for: legadilo/templates/base.html

+28-4
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,31 @@
5959
<script src="{% static 'htmx.min.js' %}" nonce="{{request.csp_nonce}}" defer></script>
6060
{% endif %}
6161
<script src="{% static 'js/base.js' %}" nonce="{{request.csp_nonce}}" defer></script>
62+
<!-- This cannot be deferred: we want the proper theme to apply immediately, not after the page has loaded -->
63+
<script src="{% static 'js/theme_chooser.js' %}"
64+
nonce="{{ request.csp_nonce }}"></script>
6265
{% block page_js %}
6366
{% endblock page_js %}
6467
{% endblock javascript %}
6568
</head>
6669
<body class="content-body">
70+
<!-- Icons for theme selector -->
71+
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
72+
<symbol id="check2" viewBox="0 0 16 16">
73+
<path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z" />
74+
</symbol>
75+
<symbol id="circle-half" viewBox="0 0 16 16">
76+
<path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z" />
77+
</symbol>
78+
<symbol id="sun-fill" viewBox="0 0 16 16">
79+
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z" />
80+
</symbol>
81+
<symbol id="moon-stars-fill" viewBox="0 0 16 16">
82+
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z" />
83+
<path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z" />
84+
</symbol>
85+
</svg>
86+
<!-- Ends icons for theme selector -->
6787
<div class="content-main-container">
6888
<div id="danger-modal"
6989
class="modal fade"
@@ -89,7 +109,7 @@ <h1 class="modal-title fs-5"></h1>
89109
</div>
90110
{% if not base.hide_header %}
91111
<div class="header-container mb-1 sticky-top">
92-
<nav class="navbar navbar-expand-md navbar-light bg-light">
112+
<nav class="navbar navbar-expand-md bd-navbar bg-body-tertiary">
93113
<div class="container-fluid">
94114
<button class="navbar-toggler navbar-toggler-right"
95115
type="button"
@@ -105,9 +125,11 @@ <h1 class="modal-title fs-5"></h1>
105125
<a class="navbar-brand" href="{% url 'reading:default_reading_list' %}">Legadilo</a>
106126
<div class="collapse navbar-collapse" id="navbarSupportedContent">
107127
<ul class="navbar-nav me-auto">
108-
<li class="nav-item active">
109-
<a class="nav-link" href="{% url 'reading:default_reading_list' %}">{% translate "Default reading list" %}</a>
110-
</li>
128+
{% if request.user.is_authenticated %}
129+
<li class="nav-item active">
130+
<a class="nav-link" href="{% url 'reading:default_reading_list' %}">{% translate "Default reading list" %}</a>
131+
</li>
132+
{% endif %}
111133
</ul>
112134
<ul class="navbar-nav">
113135
{% if request.user.is_authenticated %}
@@ -148,6 +170,7 @@ <h1 class="modal-title fs-5"></h1>
148170
</span>
149171
</a>
150172
</li>
173+
{% include "core/partials/theme_chooser.html" %}
151174
<li class="nav-item dropdown">
152175
<a class="nav-link dropdown-toggle"
153176
href="#"
@@ -169,6 +192,7 @@ <h1 class="modal-title fs-5"></h1>
169192
</div>
170193
</li>
171194
{% else %}
195+
{% include "core/partials/theme_chooser.html" %}
172196
{% if ACCOUNT_ALLOW_REGISTRATION %}
173197
<li class="nav-item">
174198
{# URL provided by django-allauth/account/urls.py #}

Diff for: legadilo/templates/core/partials/theme_chooser.html

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{% load i18n %}
2+
3+
<!-- Taken and slightly adapted from the boostrap website -->
4+
<li class="nav-item">
5+
<button id="bd-theme"
6+
class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center"
7+
type="button"
8+
aria-expanded="false"
9+
data-bs-toggle="dropdown"
10+
data-bs-display="static"
11+
aria-label="Toggle theme (auto)">
12+
<svg class="bi my-1 theme-icon-active">
13+
<use href="#circle-half"></use>
14+
</svg>
15+
<span id="bd-theme-text" class="d-lg-none ms-2">Toggle theme</span>
16+
</button>
17+
<ul class="dropdown-menu dropdown-menu-end"
18+
aria-labelledby="bd-theme-text">
19+
<li>
20+
<button class="dropdown-item d-flex align-items-center"
21+
type="button"
22+
data-bs-theme-value="light"
23+
aria-pressed="false">
24+
<svg class="bi me-2 opacity-50">
25+
<use href="#sun-fill"></use>
26+
</svg>
27+
{% translate "Light" %}
28+
<svg class="bi ms-auto d-none">
29+
<use href="#check2"></use>
30+
</svg>
31+
</button>
32+
<button class="dropdown-item d-flex align-items-center"
33+
type="button"
34+
data-bs-theme-value="dark"
35+
aria-pressed="false">
36+
<svg class="bi me-2 opacity-50">
37+
<use href="#moon-stars-fill"></use>
38+
</svg>
39+
{% translate "Dark" %}
40+
<svg class="bi ms-auto d-none">
41+
<use href="#check2"></use>
42+
</svg>
43+
</button>
44+
<button class="dropdown-item d-flex align-items-center"
45+
type="button"
46+
data-bs-theme-value="auto"
47+
aria-pressed="false">
48+
<svg class="bi me-2 opacity-50" viewBox="0 0 16 16">
49+
<use href="#circle-half"></use>
50+
</svg>
51+
{% translate "Auto" %}
52+
<svg class="bi ms-auto d-none">
53+
<use href="#check2"></use>
54+
</svg>
55+
</button>
56+
</li>
57+
</ul>
58+
</li>

Diff for: legadilo/templates/feeds/edit_feed.html

+14-10
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,20 @@ <h1>Editing feed '{{ feed.title }}'</h1>
3030
<form method="post">
3131
{% csrf_token %}
3232
{{ form|crispy }}
33-
<button form="delete-feed-form"
34-
class="btn btn-danger"
35-
type="submit"
36-
name="delete">{% translate "Delete" %}</button>
37-
{% if feed.enabled %}
38-
<button class="btn btn-outline-secondary" type="submit" name="disable">{% translate "Disable feed" %}</button>
39-
{% else %}
40-
<button class="btn btn-outline-secondary" type="submit" name="enable">{% translate "Reenable feed" %}</button>
41-
{% endif %}
42-
<button class="btn btn-primary" type="submit" name="save">{% translate "Save" %}</button>
33+
<div class="d-flex justify-content-between">
34+
<div>
35+
<button form="delete-feed-form"
36+
class="btn btn-danger"
37+
type="submit"
38+
name="delete">{% translate "Delete" %}</button>
39+
<button class="btn btn-primary" type="submit" name="save">{% translate "Save" %}</button>
40+
</div>
41+
{% if feed.enabled %}
42+
<button class="btn btn-outline-secondary" type="submit" name="disable">{% translate "Disable feed" %}</button>
43+
{% else %}
44+
<button class="btn btn-outline-secondary" type="submit" name="enable">{% translate "Reenable feed" %}</button>
45+
{% endif %}
46+
</div>
4347
</form>
4448
<div id="feed-debug-container" class="accordion mt-5">
4549
<div class="accordion-item">

Diff for: legadilo/templates/reading/edit_reading_list.html

+16-12
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,22 @@ <h1>
4242
<form method="post">
4343
{% csrf_token %}
4444
{{ form|crispy }}
45-
{% if reading_list %}
46-
<button form="delete-reading-list-form"
47-
class="btn btn-danger"
48-
type="submit"
49-
name="delete">{% translate "Delete" %}</button>
50-
<button class="btn btn-primary" type="submit">{% translate "Update" %}</button>
51-
{% else %}
52-
<button class="btn btn-primary" type="submit">{% translate "Create" %}</button>
53-
{% endif %}
54-
{% if not reading_list.is_default %}
55-
<button class="btn btn-outline-secondary" type="submit" name="make-default">{% translate "Make default" %}</button>
56-
{% endif %}
45+
<div class="d-flex justify-content-between">
46+
<div>
47+
{% if reading_list %}
48+
<button form="delete-reading-list-form"
49+
class="btn btn-danger"
50+
type="submit"
51+
name="delete">{% translate "Delete" %}</button>
52+
<button class="btn btn-primary" type="submit">{% translate "Update" %}</button>
53+
{% else %}
54+
<button class="btn btn-primary" type="submit">{% translate "Create" %}</button>
55+
{% endif %}
56+
</div>
57+
{% if not reading_list.is_default %}
58+
<button class="btn btn-outline-secondary" type="submit" name="make-default">{% translate "Make default" %}</button>
59+
{% endif %}
60+
</div>
5761
</form>
5862
<div class="mb-4"></div>
5963
{% endblock content %}

0 commit comments

Comments
 (0)