summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/bg/js/options.js1
-rw-r--r--ext/bg/js/settings-popup-preview.js8
-rw-r--r--ext/bg/js/settings.js2
-rw-r--r--ext/bg/settings.html22
-rw-r--r--ext/fg/js/popup.js43
5 files changed, 70 insertions, 6 deletions
diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js
index 088945c0..cadc4443 100644
--- a/ext/bg/js/options.js
+++ b/ext/bg/js/options.js
@@ -277,6 +277,7 @@ function profileOptionsCreateDefaults() {
compactGlossaries: false,
mainDictionary: '',
popupTheme: 'default',
+ popupOuterTheme: 'default',
customPopupCss: ''
},
diff --git a/ext/bg/js/settings-popup-preview.js b/ext/bg/js/settings-popup-preview.js
index 6f64c240..53a5f1d0 100644
--- a/ext/bg/js/settings-popup-preview.js
+++ b/ext/bg/js/settings-popup-preview.js
@@ -22,6 +22,7 @@ class SettingsPopupPreview {
this.frontend = null;
this.apiOptionsGetOld = apiOptionsGet;
this.popupShown = false;
+ this.themeChangeTimeout = null;
}
static create() {
@@ -97,6 +98,13 @@ class SettingsPopupPreview {
onThemeDarkCheckboxChanged(node) {
document.documentElement.classList.toggle('dark', node.checked);
+ if (this.themeChangeTimeout !== null) {
+ clearTimeout(this.themeChangeTimeout);
+ }
+ this.themeChangeTimeout = setTimeout(() => {
+ this.themeChangeTimeout = null;
+ this.frontend.popup.updateTheme();
+ }, 300);
}
setText(text) {
diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js
index b98754ab..900b89bb 100644
--- a/ext/bg/js/settings.js
+++ b/ext/bg/js/settings.js
@@ -40,6 +40,7 @@ async function formRead(options) {
options.general.popupHorizontalOffset2 = parseInt($('#popup-horizontal-offset2').val(), 0);
options.general.popupVerticalOffset2 = parseInt($('#popup-vertical-offset2').val(), 10);
options.general.popupTheme = $('#popup-theme').val();
+ options.general.popupOuterTheme = $('#popup-outer-theme').val();
options.general.customPopupCss = $('#custom-popup-css').val();
options.audio.enabled = $('#audio-playback-enabled').prop('checked');
@@ -109,6 +110,7 @@ async function formWrite(options) {
$('#popup-horizontal-offset2').val(options.general.popupHorizontalOffset2);
$('#popup-vertical-offset2').val(options.general.popupVerticalOffset2);
$('#popup-theme').val(options.general.popupTheme);
+ $('#popup-outer-theme').val(options.general.popupOuterTheme);
$('#custom-popup-css').val(options.general.customPopupCss);
$('#audio-playback-enabled').prop('checked', options.audio.enabled);
diff --git a/ext/bg/settings.html b/ext/bg/settings.html
index 531c0e86..08e56a09 100644
--- a/ext/bg/settings.html
+++ b/ext/bg/settings.html
@@ -232,11 +232,23 @@
</div>
<div class="form-group">
- <label for="popup-theme">Theme</label>
- <select class="form-control" id="popup-theme">
- <option value="default">Light</option>
- <option value="dark">Dark</option>
- </select>
+ <div class="row">
+ <div class="col-xs-6">
+ <label for="popup-theme">Popup theme</label>
+ <select class="form-control" id="popup-theme">
+ <option value="default">Light</option>
+ <option value="dark">Dark</option>
+ </select>
+ </div>
+ <div class="col-xs-6">
+ <label for="popup-outer-theme">Popup shadow theme</label>
+ <select class="form-control" id="popup-outer-theme">
+ <option value="auto">Auto-detect</option>
+ <option value="default">Light</option>
+ <option value="dark">Dark</option>
+ </select>
+ </div>
+ </div>
</div>
<div class="form-group options-advanced">
diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js
index 5ca8643f..ef4cdb67 100644
--- a/ext/fg/js/popup.js
+++ b/ext/fg/js/popup.js
@@ -85,7 +85,7 @@ class Popup {
async setOptions(options) {
this.options = options;
- this.container.dataset.yomichanTheme = options.general.popupTheme;
+ this.updateTheme();
}
async show(elementRect, writingMode) {
@@ -270,6 +270,47 @@ class Popup {
}
}
+ updateTheme() {
+ this.container.dataset.yomichanTheme = this.getTheme(this.options.general.popupOuterTheme);
+ }
+
+ getTheme(themeName) {
+ if (themeName === 'auto') {
+ const color = [255, 255, 255];
+ Popup.addColor(color, Popup.getColorInfo(window.getComputedStyle(document.documentElement).backgroundColor));
+ Popup.addColor(color, Popup.getColorInfo(window.getComputedStyle(document.body).backgroundColor));
+ const dark = (color[0] < 128 && color[1] < 128 && color[2] < 128);
+ themeName = dark ? 'dark' : 'default';
+ }
+
+ return themeName;
+ }
+
+ static addColor(target, color) {
+ if (color === null) { return; }
+
+ const a = color[3];
+ if (a <= 0.0) { return; }
+
+ const aInv = 1.0 - a;
+ for (let i = 0; i < 3; ++i) {
+ target[i] = target[i] * aInv + color[i] * a;
+ }
+ }
+
+ static getColorInfo(cssColor) {
+ const m = /^\s*rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d\.]+)\s*)?\)\s*$/.exec(cssColor);
+ if (m === null) { return null; }
+
+ const m4 = m[4];
+ return [
+ Number.parseInt(m[1], 10),
+ Number.parseInt(m[2], 10),
+ Number.parseInt(m[3], 10),
+ m4 ? Math.max(0.0, Math.min(1.0, Number.parseFloat(m4))) : 1.0
+ ];
+ }
+
async containsPoint(x, y) {
for (let popup = this; popup !== null && popup.isVisible(); popup = popup.child) {
const rect = popup.container.getBoundingClientRect();