Support 'System' theme setting (#91)

This commit is contained in:
Alex Ling 2020-07-19 10:43:55 +00:00
parent 6acfa02314
commit 87b72fbd30
7 changed files with 126 additions and 72 deletions

View File

@ -30,18 +30,18 @@
cursor: pointer;
}
.uk-list li {
.uk-list li:not(.nopointer) {
cursor: pointer;
}
.reader-bg {
background-color: black;
}
#scan-status {
cursor: auto;
}
.reader-bg {
background-color: black;
}
.break-word {
word-wrap: break-word;
}

View File

@ -1,13 +1,14 @@
var scanning = false;
function scan() {
let scanning = false;
const scan = () => {
scanning = true;
$('#scan-status > div').removeAttr('hidden');
$('#scan-status > span').attr('hidden', '');
var color = $('#scan').css('color');
const color = $('#scan').css('color');
$('#scan').css('color', 'gray');
$.post(base_url + 'api/admin/scan', function (data) {
var ms = data.milliseconds;
var titles = data.titles;
$.post(base_url + 'api/admin/scan', (data) => {
const ms = data.milliseconds;
const titles = data.titles;
$('#scan-status > span').text('Scanned ' + titles + ' titles in ' + ms + 'ms');
$('#scan-status > span').removeAttr('hidden');
$('#scan').css('color', color);
@ -15,11 +16,25 @@ function scan() {
scanning = false;
});
}
$(function() {
$('li').click(function() {
url = $(this).attr('data-url');
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
}
$(() => {
$('li').click((e) => {
const url = $(e.currentTarget).attr('data-url');
if (url) {
$(location).attr('href', url);
}
});
const setting = loadThemeSetting();
$('#theme-select').val(setting.capitalize());
$('#theme-select').change((e) => {
const newSetting = $(e.currentTarget).val().toLowerCase();
saveThemeSetting(newSetting);
setTheme();
});
});

View File

@ -32,32 +32,34 @@ const download = () => {
const chapters = globalChapters.filter(c => ids.indexOf(c.id) >= 0);
console.log(ids);
$.ajax({
type: 'POST',
url: base_url + 'api/admin/mangadex/download',
data: JSON.stringify({chapters: chapters}),
contentType: "application/json",
dataType: 'json'
})
.done(data => {
console.log(data);
if (data.error) {
alert('danger', `Failed to add chapters to the download queue. Error: ${data.error}`);
return;
}
const successCount = parseInt(data.success);
const failCount = parseInt(data.fail);
UIkit.modal.confirm(`${successCount} of ${successCount + failCount} chapters added to the download queue. Proceed to the download manager?`).then(() => {
window.location.href = base_url + 'admin/downloads';
type: 'POST',
url: base_url + 'api/admin/mangadex/download',
data: JSON.stringify({
chapters: chapters
}),
contentType: "application/json",
dataType: 'json'
})
.done(data => {
console.log(data);
if (data.error) {
alert('danger', `Failed to add chapters to the download queue. Error: ${data.error}`);
return;
}
const successCount = parseInt(data.success);
const failCount = parseInt(data.fail);
UIkit.modal.confirm(`${successCount} of ${successCount + failCount} chapters added to the download queue. Proceed to the download manager?`).then(() => {
window.location.href = base_url + 'admin/downloads';
});
styleModal();
})
.fail((jqXHR, status) => {
alert('danger', `Failed to add chapters to the download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
})
.always(() => {
$('#download-spinner').attr('hidden', '');
$('#download-btn').removeAttr('hidden');
});
styleModal();
})
.fail((jqXHR, status) => {
alert('danger', `Failed to add chapters to the download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
})
.always(() => {
$('#download-spinner').attr('hidden', '');
$('#download-btn').removeAttr('hidden');
});
});
styleModal();
};
@ -66,8 +68,7 @@ const toggleSpinner = () => {
if (attr) {
$('#spinner').removeAttr('hidden');
$('#search-btn').attr('hidden', '');
}
else {
} else {
$('#search-btn').removeAttr('hidden');
$('#spinner').attr('hidden', '');
}
@ -98,8 +99,7 @@ const search = () => {
const path = new URL(input).pathname;
const match = /\/title\/([0-9]+)/.exec(path);
int_id = parseInt(match[1]);
}
catch(e) {
} catch (e) {
int_id = parseInt(input);
}
@ -139,8 +139,12 @@ const search = () => {
const comp = (a, b) => {
var ai;
var bi;
try {ai = parseFloat(a);} catch(e) {}
try {bi = parseFloat(b);} catch(e) {}
try {
ai = parseFloat(a);
} catch (e) {}
try {
bi = parseFloat(b);
} catch (e) {}
if (typeof ai === 'undefined') return -1;
if (typeof bi === 'undefined') return 1;
if (ai < bi) return 1;
@ -176,8 +180,7 @@ const parseRange = str => {
if (!matches) {
alert('danger', `Failed to parse filter input ${str}`);
return [null, null];
}
else if (typeof matches[1] !== 'undefined' && typeof matches[2] !== 'undefined') {
} else if (typeof matches[1] !== 'undefined' && typeof matches[2] !== 'undefined') {
// e.g., <= 30
num = parseInt(matches[2]);
if (isNaN(num)) {
@ -194,8 +197,7 @@ const parseRange = str => {
case '>=':
return [num, null];
}
}
else if (typeof matches[3] !== 'undefined') {
} else if (typeof matches[3] !== 'undefined') {
// a single number
num = parseInt(matches[3]);
if (isNaN(num)) {
@ -203,8 +205,7 @@ const parseRange = str => {
return [null, null];
}
return [num, num];
}
else if (typeof matches[4] !== 'undefined' && typeof matches[5] !== 'undefined') {
} else if (typeof matches[4] !== 'undefined' && typeof matches[5] !== 'undefined') {
// e.g., 10 - 23
num = parseInt(matches[4]);
const n2 = parseInt(matches[5]);
@ -213,8 +214,7 @@ const parseRange = str => {
return [null, null];
}
return [num, n2];
}
else {
} else {
// empty or space only
return [null, null];
}
@ -280,7 +280,7 @@ const buildTable = () => {
const group_str = Object.entries(chp.groups).map(([k, v]) => {
return `<a href="${baseURL }/group/${v}">${k}</a>`;
}).join(' | ');
const dark = getTheme() === 'dark' ? 'dark' : '';
const dark = loadTheme() === 'dark' ? 'dark' : '';
return `<tr class="ui-widget-content ${dark}">
<td><a href="${baseURL}/chapter/${chp.id}">${chp.id}</a></td>
<td>${chp.title}</td>
@ -302,7 +302,7 @@ const buildTable = () => {
};
const unescapeHTML = (str) => {
var elt = document.createElement("span");
elt.innerHTML = str;
return elt.innerText;
var elt = document.createElement("span");
elt.innerHTML = str;
return elt.innerText;
};

View File

@ -1,22 +1,44 @@
const getTheme = () => {
var theme = localStorage.getItem('theme');
if (!theme) theme = 'light';
return theme;
// https://flaviocopes.com/javascript-detect-dark-mode/
const preferDarkMode = () => {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
};
const saveTheme = theme => {
localStorage.setItem('theme', theme);
const validThemeSetting = (theme) => {
return ['dark', 'light', 'system'].indexOf(theme) >= 0;
};
// dark / light / system
const loadThemeSetting = () => {
let str = localStorage.getItem('theme');
if (!str || !validThemeSetting(str)) str = 'light';
return str;
};
// dark / light
const loadTheme = () => {
let setting = loadThemeSetting();
if (setting === 'system') {
setting = preferDarkMode() ? 'dark' : 'light';
}
return setting;
};
const saveThemeSetting = setting => {
if (!validThemeSetting(setting)) setting = 'light';
localStorage.setItem('theme', setting);
};
// when toggled, Auto will be changed to light or dark
const toggleTheme = () => {
const theme = getTheme();
const theme = loadTheme();
const newTheme = theme === 'dark' ? 'light' : 'dark';
saveThemeSetting(newTheme);
setTheme(newTheme);
saveTheme(newTheme);
};
const setTheme = themeStr => {
if (themeStr === 'dark') {
const setTheme = (theme) => {
if (!theme) theme = loadTheme();
if (theme === 'dark') {
$('html').css('background', 'rgb(20, 20, 20)');
$('body').addClass('uk-light');
$('.uk-card').addClass('uk-card-secondary');
@ -32,7 +54,7 @@ const setTheme = themeStr => {
};
const styleModal = () => {
const color = getTheme() === 'dark' ? '#222' : '';
const color = loadTheme() === 'dark' ? '#222' : '';
$('.uk-modal-header').css('background', color);
$('.uk-modal-body').css('background', color);
$('.uk-modal-footer').css('background', color);
@ -40,9 +62,18 @@ const styleModal = () => {
// do it before document is ready to prevent the initial flash of white on
// most pages
setTheme(getTheme());
setTheme();
$(() => {
// hack for the reader page
setTheme(getTheme());
setTheme();
// on system dark mode setting change
if (window.matchMedia) {
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', event => {
if (loadThemeSetting() === 'system')
setTheme(event.matches ? 'dark' : 'light');
});
}
});

View File

@ -7,6 +7,14 @@
<span hidden></span>
</span>
</li>
<li class="nopointer">
<span>Theme</span>
<select id="theme-select" class="uk-select uk-align-right uk-width-1-3@m uk-width-1-2">
<option>Dark</option>
<option>Light</option>
<option>System</option>
</select>
</li>
<li data-url="<%= base_url %>admin/downloads">Download Manager</li>
</ul>

View File

@ -56,7 +56,7 @@
</div>
</div>
<script>
setTheme(getTheme());
setTheme();
const base_url = "<%= base_url %>";
</script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit.min.js"></script>

View File

@ -27,7 +27,7 @@
</div>
</div>
<script>
setTheme(getTheme());
setTheme();
</script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit-icons.min.js"></script>