Skip to content

Commit 4929e2b

Browse files
committed
add dark mode support
1 parent 50183c5 commit 4929e2b

File tree

4 files changed

+95
-5
lines changed

4 files changed

+95
-5
lines changed

src/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@
9393
</button>
9494
<div class="overflow-y-auto">
9595
<h3>Настройки</h3>
96+
Цветова схема:
97+
<div class="form-check form-switch ps-2 mb-3">
98+
<input type="radio" name="theme" value="auto" id="theme_auto"/>
99+
<label for="theme_auto" class="form-check-label">Автоматично</label>
100+
<br>
101+
<input type="radio" name="theme" value="light" id="theme_light"/>
102+
<label for="theme_light" class="form-check-label">Светла</label>
103+
<br>
104+
<input type="radio" name="theme" value="dark" id="theme_dark"/>
105+
<label for="theme_dark" class="form-check-label">Тъмна</label>
106+
</div>
107+
96108
Позиции на превозни средства:
97109
<div class="form-check form-switch ps-2 mb-1">
98110
<input type="radio" name="positions_data_source" id="sumc_gtfs" value="gtfs">

src/js/app.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ function populate_route_table(relevant_vehicles, tbody, table_cell) {
270270
const btns = [];
271271
for(const vehicle of relevant_vehicles) {
272272
const btn = document.createElement('button');
273-
btn.classList.add('vehicle-btn', 'btn', 'btn-outline-dark', 'btn-sm');
273+
const btn_main_class = is_dark_theme() ? 'btn-outline-light' : 'btn-outline-dark';
274+
btn.classList.add('vehicle-btn', 'btn', btn_main_class, 'btn-sm');
274275
btn.addEventListener('click', (e) => {
275276
zoom_to_vehicle(vehicle.cgm_id);
276277
});
@@ -282,7 +283,7 @@ function populate_route_table(relevant_vehicles, tbody, table_cell) {
282283
btn.setAttribute('data-cgm-id', vehicle.cgm_id);
283284
if(vehicle.is_unexpected) {
284285
btn.classList.add('btn-warning');
285-
btn.classList.remove('btn-outline-dark');
286+
btn.classList.remove(btn_main_class);
286287
btn.setAttribute('data-is-unexpected', 'true');
287288
tbody.setAttribute('data-unexpected', 'true');
288289
}
@@ -396,4 +397,46 @@ function init_settings() {
396397
const virtual_board_show_relative = get_setting('stop_time_style') === 'absolute';
397398
const check_el = document.querySelector('#virtual_board_show_relative');
398399
check_el.toggleAttribute('checked', virtual_board_show_relative);
400+
401+
const theme = get_setting('theme') || 'auto';
402+
apply_theme(theme);
403+
const theme_radios = document.querySelectorAll('input[name="theme"]');
404+
theme_radios.forEach(radio => {
405+
radio.toggleAttribute('checked', radio.value === theme);
406+
radio.addEventListener('change', (e) => {
407+
if(e.target.checked) {
408+
set_setting('theme', e.target.value);
409+
apply_theme(e.target.value);
410+
}
411+
});
412+
});
413+
}
414+
415+
function apply_theme(theme) {
416+
const html_el = document.querySelector('html');
417+
html_el.classList.remove('light-theme', 'dark-theme');
418+
const affected_btns = document.querySelectorAll('.btn-outline-dark, .btn-outline-light');
419+
let final_theme = theme;
420+
if(theme === 'auto') {
421+
const prefers_dark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
422+
final_theme = prefers_dark ? 'dark' : 'light';
423+
}
424+
html_el.setAttribute('data-bs-theme', final_theme);
425+
affected_btns.forEach(btn => {
426+
btn.classList.toggle('btn-outline-light', final_theme === 'dark');
427+
btn.classList.toggle('btn-outline-dark', final_theme === 'light');
428+
});
399429
}
430+
431+
export function is_dark_theme() {
432+
const theme = get_setting('theme');
433+
if(theme === 'dark') {
434+
return true;
435+
}
436+
else if(theme === 'light') {
437+
return false;
438+
}
439+
else {
440+
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
441+
}
442+
}

src/js/map_vehicles.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { get_vehicle_model_name } from '/data/models';
55
import { stops } from './map_stops';
66
import { cache, zoom_to_vehicle } from './app';
77
import { determine_time_ago } from './map';
8+
import { is_dark_theme } from './app';
89

910
function generate_vehicle_popup_text(vehicle, cache) {
1011
const {
@@ -50,10 +51,10 @@ function generate_vehicle_popup_text(vehicle, cache) {
5051
first_row.appendChild(route_num_span);
5152
if(car) {
5253
first_row.appendChild(document.createTextNode(` / ${car}`));
53-
54+
const btn_main_class = is_dark_theme() ? 'btn-outline-light' : 'btn-outline-dark';
5455
if(car !== 1 && allCarsOnLine[0].car !== car) {
5556
const prev_btn = document.createElement('button');
56-
prev_btn.className = 'btn btn-sm btn-outline-dark mx-1';
57+
prev_btn.className = `btn btn-sm ${btn_main_class} mx-1`;
5758
const i = document.createElement('i');
5859
i.className = 'bi bi-arrow-left';
5960
prev_btn.appendChild(i);
@@ -68,7 +69,7 @@ function generate_vehicle_popup_text(vehicle, cache) {
6869

6970
if(car !== totalCars) {
7071
const next_btn = document.createElement('button');
71-
next_btn.className = 'btn btn-sm btn-outline-dark mx-1';
72+
next_btn.className = `btn btn-sm ${btn_main_class} mx-1`;
7273
const i = document.createElement('i');
7374
i.className = 'bi bi-arrow-right';
7475
next_btn.appendChild(i);

src/styles.scss

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
html[data-bs-theme="dark"] .panel {
2+
background-color: var(--bs-dark);
3+
}
4+
5+
html[data-bs-theme="dark"] .leaflet-tile-container > img {
6+
filter: brightness(0.8);
7+
}
8+
9+
html[data-bs-theme="dark"] .leaflet-bar > a,
10+
html[data-bs-theme="dark"] .leaflet-popup-content-wrapper,
11+
html[data-bs-theme="dark"] .leaflet-popup-tip,
12+
html[data-bs-theme="dark"] .leaflet-tooltip
13+
{
14+
background-color: var(--bs-dark);
15+
color: #fff !important;
16+
}
17+
18+
html[data-bs-theme="dark"] .leaflet-tooltip-top::before {
19+
border-top-color: var(--bs-dark);
20+
}
21+
22+
html[data-bs-theme="dark"] .leaflet-tooltip {
23+
border: none;
24+
}
25+
26+
html[data-bs-theme="dark"] .leaflet-control-locate-location-arrow,
27+
html[data-bs-theme="dark"] .leaflet-control-locate-spinner {
28+
filter: invert(1);
29+
}
30+
31+
html[data-bs-theme="dark"] .leaflet-container {
32+
background: var(--bs-dark);
33+
}
34+
135
.panel {
236
z-index: 1100;
337
background-color: #fff;

0 commit comments

Comments
 (0)