From 6014fe5344cd22ff783af18db2b567e2cd7ef819 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 11 Oct 2019 19:08:54 -0400 Subject: Add support for persistent storage --- ext/bg/settings.html | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'ext/bg/settings.html') diff --git a/ext/bg/settings.html b/ext/bg/settings.html index e4710283..19dee8b3 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -395,12 +395,20 @@ -
+

Storage

+
+

+ Web browsers may sometimes clear stored data if the device is running low on storage space. + This can result in the stored dictionary data being deleted unexpectedly, causing Yomichan to stop working for no apparent reason. + In order to prevent this, persistent storage must be enable by clicking the "Persistent Storage" button below. +

+
+

Yomichan is using approximately of . @@ -425,7 +433,8 @@

- + +
-- cgit v1.2.3 From 70bceb5b567ade151d0299917187f4c075ea55ac Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 11 Oct 2019 19:22:46 -0400 Subject: Improve display of storage stats --- ext/bg/js/settings.js | 24 +++++++++++++++++++----- ext/bg/settings.html | 5 ++++- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'ext/bg/settings.html') diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 7ad628ba..bd15f5d0 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -705,13 +705,13 @@ async function getBrowser() { function storageBytesToLabeledString(size) { const base = 1000; - const labels = ['bytes', 'KB', 'MB', 'GB']; + const labels = [' bytes', 'KB', 'MB', 'GB']; let labelIndex = 0; while (size >= base) { size /= base; ++labelIndex; } - const label = size.toFixed(1); + const label = labelIndex === 0 ? `${size}` : size.toFixed(1); return `${label}${labels[labelIndex]}`; } @@ -723,6 +723,13 @@ async function storageEstimate() { } storageEstimate.mostRecent = null; +async function isStoragePeristent() { + try { + return await navigator.storage.persisted(); + } catch (e) { } + return false; +} + async function storageInfoInitialize() { storagePersistInitialize(); const browser = await getBrowser(); @@ -741,8 +748,14 @@ async function storageUpdateStats() { const valid = (estimate !== null); if (valid) { - document.querySelector('#storage-usage').textContent = storageBytesToLabeledString(estimate.usage); - document.querySelector('#storage-quota').textContent = storageBytesToLabeledString(estimate.quota); + // Firefox reports usage as 0 when persistent storage is enabled. + const finite = (estimate.usage > 0 || !(await isStoragePeristent())); + if (finite) { + document.querySelector('#storage-usage').textContent = storageBytesToLabeledString(estimate.usage); + document.querySelector('#storage-quota').textContent = storageBytesToLabeledString(estimate.quota); + } + document.querySelector('#storage-use-finite').classList.toggle('storage-hidden', !finite); + document.querySelector('#storage-use-infinite').classList.toggle('storage-hidden', finite); } storageUpdateStats.isUpdating = false; @@ -782,7 +795,7 @@ async function storagePersistInitialize() { info.classList.remove('storage-hidden'); button.classList.remove('storage-hidden'); - let persisted = await navigator.storage.persisted(); + let persisted = await isStoragePeristent(); if (persisted) { checkbox.checked = true; } @@ -794,6 +807,7 @@ async function storagePersistInitialize() { if (await navigator.storage.persist()) { persisted = true; checkbox.checked = true; + storageShowInfo(); } }, false); } diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 19dee8b3..76955b2c 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -410,9 +410,12 @@
-

+

Yomichan is using approximately of .

+

+ Yomichan is permitted unlimited storage. +

-- cgit v1.2.3 From be7fa57d5ced7f6969c5d66f0a35fafb9de3bcee Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 12 Oct 2019 12:59:51 -0400 Subject: Add support for a popup preview --- ext/bg/css/settings.css | 9 +++ ext/bg/js/settings-popup-preview.js | 147 ++++++++++++++++++++++++++++++++++++ ext/bg/js/settings.js | 38 ++++++++++ ext/bg/settings-popup-preview.html | 125 ++++++++++++++++++++++++++++++ ext/bg/settings.html | 13 ++++ ext/fg/js/frontend.js | 8 +- 6 files changed, 337 insertions(+), 3 deletions(-) create mode 100644 ext/bg/js/settings-popup-preview.js create mode 100644 ext/bg/settings-popup-preview.html (limited to 'ext/bg/settings.html') diff --git a/ext/bg/css/settings.css b/ext/bg/css/settings.css index 100478aa..09d60b26 100644 --- a/ext/bg/css/settings.css +++ b/ext/bg/css/settings.css @@ -148,6 +148,15 @@ input[type=checkbox]#storage-persist-button-checkbox { padding: 0; } +#settings-popup-preview-frame { + background-color: transparent; + border: none; + margin: 0; + padding: 0; + width: 100%; + height: 320px; +} + [data-show-for-browser] { display: none; } diff --git a/ext/bg/js/settings-popup-preview.js b/ext/bg/js/settings-popup-preview.js new file mode 100644 index 00000000..ec21e7e1 --- /dev/null +++ b/ext/bg/js/settings-popup-preview.js @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2019 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class SettingsPopupPreview { + constructor() { + this.frontend = null; + this.apiOptionsGetOld = apiOptionsGet; + this.popupShown = false; + } + + static create() { + const instance = new SettingsPopupPreview(); + instance.prepare(); + return instance; + } + + async prepare() { + // Setup events + window.addEventListener('resize', (e) => this.onWindowResize(e), false); + window.addEventListener('message', (e) => this.onMessage(e), false); + + const themeDarkCheckbox = document.querySelector('#theme-dark-checkbox'); + if (themeDarkCheckbox !== null) { + themeDarkCheckbox.addEventListener('change', () => this.onThemeDarkCheckboxChanged(themeDarkCheckbox), false); + } + + // Overwrite API functions + window.apiOptionsGet = (...args) => this.apiOptionsGet(...args); + + // Overwrite frontend + this.frontend = Frontend.create(); + window.yomichan_frontend = this.frontend; + + this.frontend.setEnabled = function () {}; + this.frontend.searchClear = function () {}; + + this.frontend.popup.childrenSupported = false; + this.frontend.popup.interactive = false; + + await this.frontend.isPrepared(); + + // Update search + this.updateSearch(); + } + + async apiOptionsGet(...args) { + const options = await this.apiOptionsGetOld(...args); + options.general.enable = true; + options.general.debugInfo = false; + options.general.popupWidth = 400; + options.general.popupHeight = 250; + options.general.popupHorizontalOffset = 0; + options.general.popupVerticalOffset = 10; + options.general.popupHorizontalOffset2 = 10; + options.general.popupVerticalOffset2 = 0; + options.general.popupHorizontalTextPosition = 'below'; + options.general.popupVerticalTextPosition = 'before'; + options.scanning.selectText = false; + return options; + } + + onWindowResize() { + if (this.frontend === null) { return; } + const textSource = this.frontend.textSourceLast; + if (textSource === null) { return; } + + const elementRect = textSource.getRect(); + const writingMode = textSource.getWritingMode(); + const options = this.frontend.options; + this.frontend.popup.show(elementRect, writingMode, options); + } + + onMessage(e) { + const {action, params} = e.data; + const handlers = SettingsPopupPreview.messageHandlers; + if (handlers.hasOwnProperty(action)) { + const handler = handlers[action]; + handler(this, params); + } + } + + onThemeDarkCheckboxChanged(node) { + document.documentElement.classList.toggle('dark', node.checked); + } + + setText(text) { + const exampleText = document.querySelector('#example-text'); + if (exampleText === null) { return; } + + exampleText.textContent = text; + this.updateSearch(); + } + + async updateSearch() { + const exampleText = document.querySelector('#example-text'); + if (exampleText === null) { return; } + + const textNode = exampleText.firstChild; + if (textNode === null) { return; } + + const range = document.createRange(); + range.selectNode(textNode); + const source = new TextSourceRange(range, range.toString(), null); + + this.frontend.textSourceLast = null; + await this.frontend.searchSource(source, 'script'); + await this.frontend.lastShowPromise; + + if (this.frontend.popup.isVisible()) { + this.popupShown = true; + } + + this.setInfoVisible(!this.popupShown); + } + + setInfoVisible(visible) { + const node = document.querySelector('.placeholder-info'); + if (node === null) { return; } + + node.classList.toggle('placeholder-info-visible', visible); + } +} + +SettingsPopupPreview.messageHandlers = { + setText: (self, {text}) => self.setText(text) +}; + +SettingsPopupPreview.instance = SettingsPopupPreview.create(); + + + diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index bd15f5d0..5732b8ae 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -248,6 +248,7 @@ async function onReady() { showExtensionInformation(); formSetupEventListeners(); + appearanceInitialize(); await audioSettingsInitialize(); await profileOptionsSetup(); @@ -259,6 +260,43 @@ async function onReady() { $(document).ready(utilAsync(onReady)); +/* + * Appearance + */ + +function appearanceInitialize() { + let previewVisible = false; + $('#settings-popup-preview-button').on('click', () => { + if (previewVisible) { return; } + showAppearancePreview(); + previewVisible = true; + }); +} + +function showAppearancePreview() { + const container = $('#settings-popup-preview-container'); + const buttonContainer = $('#settings-popup-preview-button-container'); + const settings = $('#settings-popup-preview-settings'); + const text = $('#settings-popup-preview-text'); + + const frame = document.createElement('iframe'); + frame.src = '/bg/settings-popup-preview.html'; + frame.id = 'settings-popup-preview-frame'; + + window.wanakana.bind(text[0]); + + text.on('input', () => { + const action = 'setText'; + const params = {text: text.val()}; + frame.contentWindow.postMessage({action, params}, '*'); + }); + + container.append(frame); + buttonContainer.remove(); + settings.css('display', ''); +} + + /* * Audio */ diff --git a/ext/bg/settings-popup-preview.html b/ext/bg/settings-popup-preview.html new file mode 100644 index 00000000..3d426f7a --- /dev/null +++ b/ext/bg/settings-popup-preview.html @@ -0,0 +1,125 @@ + + + + + + Yomichan Popup Preview + + + + +
+
+
+ 読め +
+ +
+ + + + + + + + + + + + + diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 76955b2c..9dd71490 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -235,6 +235,18 @@
+ + + +
+
+ +
+
+
@@ -603,6 +615,7 @@ + diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 52a23889..3ddeae78 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -44,6 +44,8 @@ class Frontend { this.isPreparedPromiseResolve = null; this.isPreparedPromise = new Promise((resolve) => { this.isPreparedPromiseResolve = resolve; }); + + this.lastShowPromise = Promise.resolve(); } static create() { @@ -331,7 +333,7 @@ class Frontend { } catch (e) { if (window.yomichan_orphaned) { if (textSource && this.options.scanning.modifier !== 'none') { - this.popup.showOrphaned( + this.lastShowPromise = this.popup.showOrphaned( textSource.getRect(), textSource.getWritingMode() ); @@ -369,7 +371,7 @@ class Frontend { const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); const url = window.location.href; - this.popup.termsShow( + this.lastShowPromise = this.popup.termsShow( textSource.getRect(), textSource.getWritingMode(), definitions, @@ -399,7 +401,7 @@ class Frontend { const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); const url = window.location.href; - this.popup.kanjiShow( + this.lastShowPromise = this.popup.kanjiShow( textSource.getRect(), textSource.getWritingMode(), definitions, -- cgit v1.2.3 From 696ea80e0681c9dab71e7b253acf4c87155004ba Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 12 Oct 2019 13:48:23 -0400 Subject: Add option for popup theme --- ext/bg/js/options.js | 1 + ext/bg/js/settings.js | 2 ++ ext/bg/settings.html | 8 ++++++++ 3 files changed, 11 insertions(+) (limited to 'ext/bg/settings.html') diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 1021e18d..088945c0 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -276,6 +276,7 @@ function profileOptionsCreateDefaults() { compactTags: false, compactGlossaries: false, mainDictionary: '', + popupTheme: 'default', customPopupCss: '' }, diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 5732b8ae..f09b35d9 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -39,6 +39,7 @@ async function formRead(options) { options.general.popupVerticalOffset = parseInt($('#popup-vertical-offset').val(), 10); 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.customPopupCss = $('#custom-popup-css').val(); options.audio.enabled = $('#audio-playback-enabled').prop('checked'); @@ -107,6 +108,7 @@ async function formWrite(options) { $('#popup-vertical-offset').val(options.general.popupVerticalOffset); $('#popup-horizontal-offset2').val(options.general.popupHorizontalOffset2); $('#popup-vertical-offset2').val(options.general.popupVerticalOffset2); + $('#popup-theme').val(options.general.popupTheme); $('#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 9dd71490..531c0e86 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -231,6 +231,14 @@
+
+ + +
+
-- cgit v1.2.3 From b086fca69fdbc74a44d31a06203b302493656151 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 12 Oct 2019 17:59:56 -0400 Subject: Add separate theme option for outer popup style --- ext/bg/js/options.js | 1 + ext/bg/js/settings-popup-preview.js | 8 +++++++ ext/bg/js/settings.js | 2 ++ ext/bg/settings.html | 22 ++++++++++++++----- ext/fg/js/popup.js | 43 ++++++++++++++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 6 deletions(-) (limited to 'ext/bg/settings.html') 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 @@
- - +
+
+ + +
+
+ + +
+
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(); -- cgit v1.2.3 From 32729482844d7af9e9f307a69c96ea34f1e66011 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 13 Oct 2019 11:05:21 -0400 Subject: Adds setting for controlling the outer style of the popup --- ext/bg/css/settings.css | 3 ++- ext/bg/js/options.js | 3 ++- ext/bg/js/settings.js | 2 ++ ext/bg/settings.html | 12 ++++++++++-- 4 files changed, 16 insertions(+), 4 deletions(-) (limited to 'ext/bg/settings.html') diff --git a/ext/bg/css/settings.css b/ext/bg/css/settings.css index 09d60b26..21cbe256 100644 --- a/ext/bg/css/settings.css +++ b/ext/bg/css/settings.css @@ -128,7 +128,8 @@ content: counter(audio-source-id); } -#custom-popup-css { +#custom-popup-css, +#custom-popup-outer-css { width: 100%; min-height: 34px; height: 96px; diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index cadc4443..fac17d68 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -278,7 +278,8 @@ function profileOptionsCreateDefaults() { mainDictionary: '', popupTheme: 'default', popupOuterTheme: 'default', - customPopupCss: '' + customPopupCss: '', + customPopupOuterCss: '' }, audio: { diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 900b89bb..7eee7bce 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -42,6 +42,7 @@ async function formRead(options) { options.general.popupTheme = $('#popup-theme').val(); options.general.popupOuterTheme = $('#popup-outer-theme').val(); options.general.customPopupCss = $('#custom-popup-css').val(); + options.general.customPopupOuterCss = $('#custom-popup-outer-css').val(); options.audio.enabled = $('#audio-playback-enabled').prop('checked'); options.audio.autoPlay = $('#auto-play-audio').prop('checked'); @@ -112,6 +113,7 @@ async function formWrite(options) { $('#popup-theme').val(options.general.popupTheme); $('#popup-outer-theme').val(options.general.popupOuterTheme); $('#custom-popup-css').val(options.general.customPopupCss); + $('#custom-popup-outer-css').val(options.general.customPopupOuterCss); $('#audio-playback-enabled').prop('checked', options.audio.enabled); $('#auto-play-audio').prop('checked', options.audio.autoPlay); diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 08e56a09..cb223e72 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -252,8 +252,16 @@
- -
+
+
+ +
+
+
+ +
+
+