diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2019-10-12 12:59:51 -0400 | 
|---|---|---|
| committer | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2019-10-12 15:44:32 -0400 | 
| commit | be7fa57d5ced7f6969c5d66f0a35fafb9de3bcee (patch) | |
| tree | 35d7e02c9d49adb2bb42ccba0dc7f241d7da2eb3 /ext | |
| parent | 537d2ef532aa7b7498de13ab039bd23f28d32714 (diff) | |
Add support for a popup preview
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/bg/css/settings.css | 9 | ||||
| -rw-r--r-- | ext/bg/js/settings-popup-preview.js | 147 | ||||
| -rw-r--r-- | ext/bg/js/settings.js | 38 | ||||
| -rw-r--r-- | ext/bg/settings-popup-preview.html | 125 | ||||
| -rw-r--r-- | ext/bg/settings.html | 13 | ||||
| -rw-r--r-- | ext/fg/js/frontend.js | 8 | 
6 files changed, 337 insertions, 3 deletions
| 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 <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +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(); @@ -260,6 +261,43 @@ $(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 @@ +<!DOCTYPE html> +<html lang="en"> +    <head> +        <meta charset="UTF-8"> +        <meta name="viewport" content="width=device-width,initial-scale=1" /> +        <title>Yomichan Popup Preview</title> +        <link rel="stylesheet" type="text/css" href="/fg/css/client.css"> +        <style> +            html { +                transition: background-color 0.25s linear 0s, color 0.25s linear 0s; +                color: #333333; +            } +            html.dark { +                background-color: #1e1e1e; +                color: #d4d4d4; +            } +            html, body { +                margin: 0; +                padding: 0; +                border: 0; +                overflow: hidden; +                width: 100%; +                height: 100%; +                font-family: "Helvetica Neue", Helvetica, Arial ,sans-serif; +                font-size: 14px; +            } +            iframe#yomichan-float { +                resize: none; +            } +            .vertical-align-outer { +                width: 100%; +                height: 100%; +                white-space: nowrap; +            } +            .vertical-align-outer::before { +                content: ""; +                display: inline-block; +                vertical-align: middle; +                width: 0; +                height: 100%; +            } +            .vertical-align-inner { +                display: inline-block; +                vertical-align: middle; +                white-space: normal; +                width: 100%; +            } +            .horizontal-size { +                max-width: 400px; +                padding: 15px; +                margin: 0 auto; +            } +            .example-text-container { +                font-size: 24px; +                line-height: 1.25em; +                height: 1.25em; +            } +            .popup-placeholder { +                height: 250px; +                padding-top: 10px; +                border: 1px solid rgba(0, 0, 0, 0); +            } +            .placeholder-info { +                visibility: hidden; +                opacity: 0; +                transition: opacity 0.5s linear 0s, visibility 0s linear 0.5s; +            } +            .placeholder-info.placeholder-info-visible { +                visibility: visible; +                opacity: 1; +                transition: opacity 0.5s linear 0s, visibility 0s linear 0s; +            } + +            .options { +                float: right; +                font-size: 14px; +                line-height: 30px; +            } +            .theme-button { +                display: inline-block; +                margin-left: 0.5em; +                text-decoration: none; +                cursor: pointer; +                white-space: nowrap; +                line-height: 0; +            } +            .theme-button>input { +                vertical-align: middle; +                margin: 0 0.25em 0 0; +                padding: 0; +            } +            .theme-button>span { +                vertical-align: middle; +            } +            .theme-button:hover>span { +                text-decoration: underline; +            } +        </style> +    </head> +    <body> +        <div class="vertical-align-outer"><div class="vertical-align-inner"><div class="horizontal-size"> +            <div class="example-text-container"> +                <div class="options"><label class="theme-button"><input type="checkbox" id="theme-dark-checkbox" /><span>dark</span></label></div> +                <span id="example-text">読め</span> +            </div> +            <div class="popup-placeholder"> +                <div class="vertical-align-outer"><div class="vertical-align-inner placeholder-info"> +                    This page uses the dictionaries you have installed in order to show a preview. +                    If you see this message, make sure you have a dictionary installed. +                </div></div> +            </div> +        </div></div></div> + +        <script src="/mixed/js/extension.js"></script> +        <script src="/fg/js/api.js"></script> +        <script src="/fg/js/document.js"></script> +        <script src="/fg/js/frontend-api-receiver.js"></script> +        <script src="/fg/js/popup.js"></script> +        <script src="/fg/js/source.js"></script> +        <script src="/fg/js/util.js"></script> +        <script src="/fg/js/popup-proxy-host.js"></script> +        <script src="/fg/js/frontend.js"></script> +        <script src="/bg/js/settings-popup-preview.js"></script> +    </body> +</html> 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 @@                      <label for="custom-popup-css">Custom popup CSS</label>                      <div><textarea autocomplete="off" spellcheck="false" wrap="soft" id="custom-popup-css" class="form-control"></textarea></div>                  </div> + +                <div class="form-group ignore-form-changes" style="display: none;" id="settings-popup-preview-settings"> +                    <label for="settings-popup-preview-text">Popup preview text</label> +                    <input type="text" id="settings-popup-preview-text" class="form-control" value="読め"> +                </div> + +                <div class="form-group ignore-form-changes"> +                    <div id="settings-popup-preview-button-container"> +                        <button class="btn btn-default" id="settings-popup-preview-button">Show popup preview</button> +                    </div> +                    <div id="settings-popup-preview-container"></div> +                </div>              </div>              <div> @@ -603,6 +615,7 @@          <script src="/mixed/lib/jquery.min.js"></script>          <script src="/mixed/lib/bootstrap/js/bootstrap.min.js"></script>          <script src="/mixed/lib/handlebars.min.js"></script> +        <script src="/mixed/lib/wanakana.min.js"></script>          <script src="/mixed/js/extension.js"></script> 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, |