diff options
-rw-r--r-- | ext/css/settings.css | 187 | ||||
-rw-r--r-- | ext/js/pages/settings/dictionary-controller.js | 293 | ||||
-rw-r--r-- | ext/settings.html | 142 | ||||
-rw-r--r-- | ext/welcome.html | 95 |
4 files changed, 460 insertions, 257 deletions
diff --git a/ext/css/settings.css b/ext/css/settings.css index 6bc377c2..f0070a1f 100644 --- a/ext/css/settings.css +++ b/ext/css/settings.css @@ -1313,65 +1313,6 @@ body.preview-sidebar-visible .fab-container-item.fab-container-item-popup-previe display: none; } -.dictionary-info { - display: flex; - flex-flow: row nowrap; - align-items: center; -} -.dictionary-info-label { - margin-left: 1em; -} - -.dictionary-title { - color: inherit; - transition: color var(--animation-duration) ease-in-out; -} -.dictionary-item[data-enabled=false] .dictionary-title { - color: var(--text-color-light2); -} - -.dictionary-list { - display: flex; - flex-flow: column nowrap; - width: 100%; -} -.dictionary-list>.settings-item, -.dictionary-list>.settings-item+.settings-item { - margin-left: calc(var(--modal-padding-horizontal) * -1); - margin-right: calc(var(--modal-padding-horizontal) * -1); - border-top: var(--thin-border-size) solid var(--separator-color2); -} -.dictionary-details-table { - display: table; - width: 100%; -} -.dictionary-details-entry { - display: table-row; -} -.dictionary-details-entry+.dictionary-details-entry>* { - padding-top: 0.25em; -} -.dictionary-details-entry-label { - display: table-cell; - font-weight: bold; - white-space: nowrap; - padding-right: 0.5em; -} -.dictionary-details-entry-info { - display: table-cell; - white-space: pre-line; -} -.dictionary-counts { - width: 100%; - box-sizing: border-box; - font-size: inherit; - max-height: 10em; - line-height: 1.25; - font-family: 'Courier New', Courier, monospace; - white-space: pre; - overflow: auto; -} - .profile-add-button-container { display: flex; flex-flow: row nowrap; @@ -2096,28 +2037,47 @@ button.hotkey-list-item-enabled-button[data-scope-count='0'] { top: calc(1em * (3 / var(--font-size-no-units))); } -.warning-badge { +.badge { position: relative; width: var(--badge-size); height: var(--badge-size); margin: 0; padding: 0; - background-color: var(--warning-color-light); border-radius: 50%; box-shadow: var(--shadow-vertical); } -.warning-badge:not([hidden]) { +.badge:not([hidden]) { display: block; } -.warning-badge>.icon { +.badge>.icon { display: block; position: absolute; left: 0; top: 0; right: 0; bottom: 0; +} +.badge.badge-small-icon>.icon { + margin: calc(1em / var(--font-size-no-units)); +} +.badge.info-badge { + background-color: var(--accent-color-lighter); +} +.badge.info-badge>.icon { + background-color: var(--accent-color); +} +.badge.warning-badge { + background-color: var(--warning-color-light); +} +.badge.warning-badge>.icon { background-color: var(--warning-color); } +.badge.danger-badge { + background-color: var(--danger-color-lighter); +} +.badge.danger-badge>.icon { + background-color: var(--danger-color); +} .collapsible-dictionary-list { width: 100%; @@ -2160,6 +2120,107 @@ button.hotkey-list-item-enabled-button[data-scope-count='0'] { } +/* Dictionary settings */ +.dictionary-list { + width: 100%; + display: grid; + grid-template-columns: auto 1fr auto auto; + grid-template-rows: auto; + place-items: center start; + margin-top: 0.5em; +} +.dictionary-list[data-count='0']>.dictionary-item-top { + display: none; +} +.dictionary-item-button-height { + height: var(--icon-button-size); +} +.dictionary-item { + display: flex; + flex-flow: row nowrap; + align-items: center; + border-top: var(--thin-border-size) solid var(--separator-color2); +} +.dictionary-item-enabled-toggle-container { + margin-right: 0.5em; +} +.dictionary-item-title-container { + flex: 1 1 auto; + display: flex; + flex-flow: row nowrap; + align-items: center; + margin-right: 0.5em; +} +.dictionary-title { + color: inherit; + transition: color var(--animation-duration) ease-in-out; +} +.dictionary-item[data-enabled=false] .dictionary-title { + color: var(--text-color-light2); +} +input[type=number].dictionary-priority { + margin-top: 0; + margin-right: 0.5em; +} +.dictionary-outdated-button, +.dictionary-integrity-button { + --button-content-color: transparent; + --button-border-color: transparent; + --button-background-color: transparent; + --button-shadow: none; + + --button-hover-content-color: transparent; + --button-hover-border-color: transparent; + --button-hover-background-color: transparent; + --button-hover-shadow: none; + + --button-active-content-color: transparent; + --button-active-border-color: transparent; + --button-active-background-color: transparent; + --button-active-shadow: none; + + --button-disabled-content-color: transparent; + --button-disabled-border-color: transparent; + --button-disabled-background-color: transparent; + --button-disabled-shadow: none; + + --button-padding-vertical: 0; + --button-padding-horizontal: 0; + + margin-left: 0.375em; +} +.dictionary-details-table { + display: table; + width: 100%; +} +.dictionary-details-entry { + display: table-row; +} +.dictionary-details-entry+.dictionary-details-entry>* { + padding-top: 0.25em; +} +.dictionary-details-entry-label { + display: table-cell; + font-weight: bold; + white-space: nowrap; + padding-right: 0.5em; +} +.dictionary-details-entry-info { + display: table-cell; + white-space: pre-line; +} +.dictionary-counts { + width: 100%; + box-sizing: border-box; + font-size: inherit; + max-height: 10em; + line-height: 1.25; + font-family: 'Courier New', Courier, monospace; + white-space: pre; + overflow: auto; +} + + /* Generic layouts */ .margin-above { margin-top: 0.85em; diff --git a/ext/js/pages/settings/dictionary-controller.js b/ext/js/pages/settings/dictionary-controller.js index f000aa62..6d358f25 100644 --- a/ext/js/pages/settings/dictionary-controller.js +++ b/ext/js/pages/settings/dictionary-controller.js @@ -20,19 +20,21 @@ */ class DictionaryEntry { - constructor(dictionaryController, node, index, dictionaryInfo) { + constructor(dictionaryController, fragment, index, dictionaryInfo) { this._dictionaryController = dictionaryController; - this._node = node; this._index = index; this._dictionaryInfo = dictionaryInfo; this._eventListeners = new EventListenerCollection(); - this._detailsContainer = null; - this._hasDetails = false; - this._hasCounts = false; - } - - get node() { - return this._node; + this._counts = null; + this._nodes = [...fragment.childNodes]; + this._enabledCheckbox = fragment.querySelector('.dictionary-enabled'); + this._priorityInput = fragment.querySelector('.dictionary-priority'); + this._menuButton = fragment.querySelector('.dictionary-menu-button'); + this._outdatedButton = fragment.querySelector('.dictionary-outdated-button'); + this._integrityButton = fragment.querySelector('.dictionary-integrity-button'); + this._titleNode = fragment.querySelector('.dictionary-title'); + this._versionNode = fragment.querySelector('.dictionary-version'); + this._titleContainer = fragment.querySelector('.dictionary-item-title-container'); } get dictionaryTitle() { @@ -40,98 +42,80 @@ class DictionaryEntry { } prepare() { - const node = this._node; const index = this._index; - const {title, revision, prefixWildcardsSupported, version} = this._dictionaryInfo; - - this._detailsContainer = node.querySelector('.dictionary-details'); - - const enabledCheckbox = node.querySelector('.dictionary-enabled'); - const priorityInput = node.querySelector('.dictionary-priority'); - const menuButton = node.querySelector('.dictionary-menu-button'); - const detailsTable = node.querySelector('.dictionary-details-table'); - const outdatedContainer = node.querySelector('.dictionary-outdated-notification'); - const titleNode = node.querySelector('.dictionary-title'); - const versionNode = node.querySelector('.dictionary-version'); - const wildcardSupportedCheckbox = node.querySelector('.dictionary-prefix-wildcard-searches-supported'); - - const hasDetails = (detailsTable !== null && this._setupDetails(detailsTable)); - this._hasDetails = hasDetails; - - titleNode.textContent = title; - versionNode.textContent = `rev.${revision}`; - if (wildcardSupportedCheckbox !== null) { - wildcardSupportedCheckbox.checked = !!prefixWildcardsSupported; - } - if (outdatedContainer !== null) { - outdatedContainer.hidden = (version >= 3); - } - if (enabledCheckbox !== null) { - enabledCheckbox.dataset.setting = `dictionaries[${index}].enabled`; - this._eventListeners.addEventListener(enabledCheckbox, 'settingChanged', this._onEnabledChanged.bind(this), false); - } - if (priorityInput !== null) { - priorityInput.dataset.setting = `dictionaries[${index}].priority`; - } - if (menuButton !== null) { - this._eventListeners.addEventListener(menuButton, 'menuOpen', this._onMenuOpen.bind(this), false); - this._eventListeners.addEventListener(menuButton, 'menuClose', this._onMenuClose.bind(this), false); - } + const {title, revision, version} = this._dictionaryInfo; + + this._titleNode.textContent = title; + this._versionNode.textContent = `rev.${revision}`; + this._outdatedButton.hidden = (version >= 3); + this._priorityInput.dataset.setting = `dictionaries[${index}].priority`; + this._enabledCheckbox.dataset.setting = `dictionaries[${index}].enabled`; + this._eventListeners.addEventListener(this._enabledCheckbox, 'settingChanged', this._onEnabledChanged.bind(this), false); + this._eventListeners.addEventListener(this._menuButton, 'menuClose', this._onMenuClose.bind(this), false); + this._eventListeners.addEventListener(this._outdatedButton, 'click', this._onOutdatedButtonClick.bind(this), false); + this._eventListeners.addEventListener(this._integrityButton, 'click', this._onIntegrityButtonClick.bind(this), false); } cleanup() { this._eventListeners.removeAllEventListeners(); - const node = this._node; - if (node.parentNode !== null) { - node.parentNode.removeChild(node); + for (const node of this._nodes) { + if (node.parentNode !== null) { + node.parentNode.removeChild(node); + } } + this._nodes = []; } setCounts(counts) { - const node = this._node.querySelector('.dictionary-counts'); - node.textContent = JSON.stringify({info: this._dictionaryInfo, counts}, null, 4); - node.hidden = false; - this._hasCounts = true; + this._counts = counts; + this._integrityButton.hidden = false; } - // Private - - _onMenuOpen(e) { - const bodyNode = e.detail.menu.bodyNode; - const showDetails = bodyNode.querySelector('.popup-menu-item[data-menu-action="showDetails"]'); - const hideDetails = bodyNode.querySelector('.popup-menu-item[data-menu-action="hideDetails"]'); - const hasDetails = (this._detailsContainer !== null); - const detailsVisible = (hasDetails && !this._detailsContainer.hidden); - if (showDetails !== null) { - showDetails.hidden = detailsVisible; - showDetails.disabled = !hasDetails; - } - if (hideDetails !== null) { - hideDetails.hidden = !detailsVisible; - hideDetails.disabled = !hasDetails; - } + setEnabled(value) { + this._enabledCheckbox.checked = value; } + // Private + _onMenuClose(e) { switch (e.detail.action) { case 'delete': this._delete(); break; case 'showDetails': - if (this._detailsContainer !== null) { this._detailsContainer.hidden = false; } - break; - case 'hideDetails': - if (this._detailsContainer !== null) { this._detailsContainer.hidden = true; } + this._showDetails(); break; } } _onEnabledChanged(e) { const {detail: {value}} = e; - this._node.dataset.enabled = `${value}`; + this._titleContainer.dataset.enabled = `${value}`; this._dictionaryController.updateDictionariesEnabled(); } + _onOutdatedButtonClick() { + this._showDetails(); + } + + _onIntegrityButtonClick() { + this._showDetails(); + } + + _showDetails() { + const {title, revision, version} = this._dictionaryInfo; + + const modal = this._dictionaryController.modalController.getModal('dictionary-details'); + + modal.node.querySelector('.dictionary-title').textContent = title; + modal.node.querySelector('.dictionary-version').textContent = `rev.${revision}`; + modal.node.querySelector('.dictionary-outdated-notification').hidden = (version >= 3); + modal.node.querySelector('.dictionary-counts').textContent = this._counts !== null ? JSON.stringify(this._counts, null, 4) : ''; + this._setupDetails(modal.node.querySelector('.dictionary-details-table')); + + modal.setVisible(true); + } + _setupDetails(detailsTable) { const targets = [ ['Author', 'author'], @@ -156,6 +140,7 @@ class DictionaryEntry { any = true; } + detailsTable.textContent = ''; detailsTable.appendChild(fragment); return any; } @@ -165,6 +150,57 @@ class DictionaryEntry { } } +class DictionaryExtraInfo { + constructor(parent, totalCounts, remainders, totalRemainder) { + this._parent = parent; + this._totalCounts = totalCounts; + this._remainders = remainders; + this._totalRemainder = totalRemainder; + this._eventListeners = new EventListenerCollection(); + this._nodes = null; + } + + prepare(container) { + const fragment = this._parent.instantiateTemplateFragment('dictionary-extra'); + this._nodes = [...fragment.childNodes]; + + this._setTitle(fragment.querySelector('.dictionary-total-count')); + this._eventListeners.addEventListener(fragment.querySelector('.dictionary-integrity-button'), 'click', this._onIntegrityButtonClick.bind(this), false); + + container.appendChild(fragment); + } + + cleanup() { + this._eventListeners.removeAllEventListeners(); + for (const node of this._nodes) { + if (node.parentNode !== null) { + node.parentNode.removeChild(node); + } + } + this._nodes = []; + } + + // Private + + _onIntegrityButtonClick() { + this._showDetails(); + } + + _showDetails() { + const modal = this._parent.modalController.getModal('dictionary-extra-data'); + + const info = {counts: this._totalCounts, remainders: this._remainders}; + modal.node.querySelector('.dictionary-counts').textContent = JSON.stringify(info, null, 4); + this._setTitle(modal.node.querySelector('.dictionary-total-count')); + + modal.setVisible(true); + } + + _setTitle(node) { + node.textContent = `${this._totalRemainder} item${this._totalRemainder !== 1 ? 's' : ''}`; + } +} + class DictionaryController { constructor(settingsController, modalController, statusFooter) { this._settingsController = settingsController; @@ -176,34 +212,40 @@ class DictionaryController { this._checkingIntegrity = false; this._checkIntegrityButton = null; this._dictionaryEntryContainer = null; - this._integrityExtraInfoContainer = null; this._dictionaryInstallCountNode = null; this._dictionaryEnabledCountNode = null; this._noDictionariesInstalledWarnings = null; this._noDictionariesEnabledWarnings = null; this._deleteDictionaryModal = null; - this._integrityExtraInfoNode = null; + this._allCheckbox = null; + this._extraInfo = null; this._isDeleting = false; } + get modalController() { + return this._modalController; + } + async prepare() { this._checkIntegrityButton = document.querySelector('#dictionary-check-integrity'); this._dictionaryEntryContainer = document.querySelector('#dictionary-list'); - this._integrityExtraInfoContainer = document.querySelector('#dictionary-list-extra'); this._dictionaryInstallCountNode = document.querySelector('#dictionary-install-count'); this._dictionaryEnabledCountNode = document.querySelector('#dictionary-enabled-count'); this._noDictionariesInstalledWarnings = document.querySelectorAll('.no-dictionaries-installed-warning'); this._noDictionariesEnabledWarnings = document.querySelectorAll('.no-dictionaries-enabled-warning'); this._deleteDictionaryModal = this._modalController.getModal('dictionary-confirm-delete'); + this._allCheckbox = document.querySelector('#all-dictionaries-enabled'); yomichan.on('databaseUpdated', this._onDatabaseUpdated.bind(this)); this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this)); - + this._allCheckbox.addEventListener('change', this._onAllCheckboxChange.bind(this), false); document.querySelector('#dictionary-confirm-delete-button').addEventListener('click', this._onDictionaryConfirmDelete.bind(this), false); if (this._checkIntegrityButton !== null) { this._checkIntegrityButton.addEventListener('click', this._onCheckIntegrityButtonClick.bind(this), false); } + this._updateDictionaryEntryCount(); + await this._onDatabaseUpdated(); } @@ -219,6 +261,10 @@ class DictionaryController { return this._settingsController.instantiateTemplate(name); } + instantiateTemplateFragment(name) { + return this._settingsController.instantiateTemplateFragment(name); + } + async updateDictionariesEnabled() { const options = await this._settingsController.getOptions(); this._updateDictionariesEnabledWarnings(options); @@ -303,6 +349,12 @@ class DictionaryController { await this._updateEntries(); } + _onAllCheckboxChange() { + const value = this._allCheckbox.checked; + this._allCheckbox.checked = !value; + this._setAllDictionariesEnabled(value); + } + async _updateEntries() { const dictionaries = this._dictionaries; this._updateMainDictionarySelectOptions(dictionaries); @@ -311,6 +363,7 @@ class DictionaryController { entry.cleanup(); } this._dictionaryEntries = []; + this._updateDictionaryEntryCount(); if (this._dictionaryInstallCountNode !== null) { this._dictionaryInstallCountNode.textContent = `${dictionaries.length}`; @@ -341,29 +394,40 @@ class DictionaryController { } _updateDictionariesEnabledWarnings(options) { - let enabledCount = 0; + const {dictionaries} = options; + let enabledDictionaryCountValid = 0; + let enabledDictionaryCount = 0; + const dictionaryCount = dictionaries.length; if (this._dictionaries !== null) { const enabledDictionaries = new Set(); - for (const {name, enabled} of options.dictionaries) { + for (const {name, enabled} of dictionaries) { if (enabled) { + ++enabledDictionaryCount; enabledDictionaries.add(name); } } for (const {title} of this._dictionaries) { if (enabledDictionaries.has(title)) { - ++enabledCount; + ++enabledDictionaryCountValid; } } } - const hasEnabledDictionary = (enabledCount > 0); + const hasEnabledDictionary = (enabledDictionaryCountValid > 0); for (const node of this._noDictionariesEnabledWarnings) { node.hidden = hasEnabledDictionary; } if (this._dictionaryEnabledCountNode !== null) { - this._dictionaryEnabledCountNode.textContent = `${enabledCount}`; + this._dictionaryEnabledCountNode.textContent = `${enabledDictionaryCountValid}`; + } + + this._allCheckbox.checked = (enabledDictionaryCount >= dictionaryCount); + + const entries = this._dictionaryEntries; + for (let i = 0, ii = Math.min(entries.length, dictionaryCount); i < ii; ++i) { + entries[i].setEnabled(dictionaries[i].enabled); } } @@ -447,43 +511,29 @@ class DictionaryController { totalRemainder += remainders[key]; } - this._cleanupExtra(); - if (totalRemainder > 0) { - this.extra = this._createExtra(totalCounts, remainders, totalRemainder); + if (this._extraInfo !== null) { + this._extraInfo.cleanup(); + this._extraInfo = null; } - } - - _createExtra(totalCounts, remainders, totalRemainder) { - const node = this.instantiateTemplate('dictionary-extra'); - this._integrityExtraInfoNode = node; - - node.querySelector('.dictionary-total-count').textContent = `${totalRemainder} item${totalRemainder !== 1 ? 's' : ''}`; - - const n = node.querySelector('.dictionary-counts'); - n.textContent = JSON.stringify({counts: totalCounts, remainders}, null, 4); - n.hidden = false; - - this._integrityExtraInfoContainer.appendChild(node); - } - _cleanupExtra() { - const node = this._integrityExtraInfoNode; - if (node === null) { return; } - this._integrityExtraInfoNode = null; - - const parent = node.parentNode; - if (parent === null) { return; } - - parent.removeChild(node); + if (totalRemainder > 0) { + this._extraInfo = new DictionaryExtraInfo(this, totalCounts, remainders, totalRemainder); + this._extraInfo.prepare(this._dictionaryEntryContainer); + } } _createDictionaryEntry(index, dictionaryInfo) { - const node = this.instantiateTemplate('dictionary'); - this._dictionaryEntryContainer.appendChild(node); + const fragment = this.instantiateTemplateFragment('dictionary'); - const entry = new DictionaryEntry(this, node, index, dictionaryInfo); + const entry = new DictionaryEntry(this, fragment, index, dictionaryInfo); this._dictionaryEntries.push(entry); entry.prepare(); + + const container = this._dictionaryEntryContainer; + const relative = container.querySelector('.dictionary-item-bottom'); + container.insertBefore(fragment, relative); + + this._updateDictionaryEntryCount(); } async _deleteDictionary(dictionaryTitle) { @@ -589,4 +639,25 @@ class DictionaryController { _triggerStorageChanged() { yomichan.trigger('storageChanged'); } + + _updateDictionaryEntryCount() { + this._dictionaryEntryContainer.dataset.count = `${this._dictionaryEntries.length}`; + } + + async _setAllDictionariesEnabled(value) { + const options = await this._settingsController.getOptions(); + const {dictionaries} = options; + + const targets = []; + for (let i = 0, ii = dictionaries.length; i < ii; ++i) { + targets.push({ + action: 'set', + path: `dictionaries[${i}].enabled`, + value + }); + } + await this._settingsController.modifyProfileSettings(targets); + + await this.updateDictionariesEnabled(); + } } diff --git a/ext/settings.html b/ext/settings.html index 872dac4d..eee06a60 100644 --- a/ext/settings.html +++ b/ext/settings.html @@ -22,7 +22,7 @@ <div class="sidebar"><div class="sidebar-inner"> <div class="sidebar-body"> <a href="#!profile" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="profile"></span></span><span class="outline-item-label">Profile</span></a> - <a href="#!dictionaries" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="book"></span><span class="outline-item-left-warning-badge no-dictionaries-enabled-warning" hidden><div class="warning-badge"><span class="icon" data-icon="exclamation-point-short"></span></div></span></span><span class="outline-item-label">Dictionaries</span></a> + <a href="#!dictionaries" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="book"></span><span class="outline-item-left-warning-badge no-dictionaries-enabled-warning" hidden><div class="badge warning-badge"><span class="icon" data-icon="exclamation-point-short"></span></div></span></span><span class="outline-item-label">Dictionaries</span></a> <a href="#!general" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="cog"></span></span><span class="outline-item-label">General</span></a> <a href="#!scanning" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="scanning"></span></span><span class="outline-item-label">Scanning</span></a> <a href="#!popup" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="popup"></span></span><span class="outline-item-label">Popup</span></a> @@ -121,7 +121,7 @@ <div class="settings-item-label"> <div class="flex-row-nowrap"> <div>Configure installed and enabled dictionaries…</div> - <div class="flex-margin-left warning-badge no-dictionaries-enabled-warning" hidden><span class="icon" data-icon="exclamation-point-short"></span></div> + <div class="flex-margin-left badge warning-badge no-dictionaries-enabled-warning" hidden><span class="icon" data-icon="exclamation-point-short"></span></div> </div> </div> </div> @@ -2080,8 +2080,12 @@ for a list free dictionaries or click the <em>Import</em> button below to select a dictionary file to import. </div> <div id="dictionary-error" class="danger-text margin-above" hidden></div> - <div id="dictionary-list" class="dictionary-list"></div> - <div id="dictionary-list-extra" class="dictionary-list"></div> + <div id="dictionary-list" class="dictionary-list" data-count="0"> + <label class="dictionary-item-top toggle dictionary-item-enabled-toggle-container"><input type="checkbox" id="all-dictionaries-enabled"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <div class="dictionary-item-top dictionary-item-title-container">All</div> + <div class="dictionary-item-top">Priority</div> + <div class="dictionary-item-top dictionary-item-button-height"></div> + </div> <div hidden><input type="file" id="dictionary-import-file-input" accept=".zip,application/zip" multiple></div> </div> @@ -2166,86 +2170,102 @@ </div> </div></div> - -<!-- Dictionary templates --> -<template id="dictionary-template"><div class="settings-item dictionary-item"> - <div class="settings-item-inner"> - <div class="settings-item-left"> - <div class="settings-item-label dictionary-info"> - <label class="toggle"><input type="checkbox" class="dictionary-enabled"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> - <span class="dictionary-info-label"><strong class="dictionary-title"></strong> <span class="light dictionary-version"></span></span> - </div> - </div> - <div class="settings-item-right"> - <button class="icon-button dictionary-menu-button" data-menu="dictionary-menu" data-menu-position="below left"><span class="icon-button-inner"><span class="icon" data-icon="kebab-menu"></span></span></button> - </div> +<div id="dictionary-details-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content"> + <div class="modal-header"> + <div class="modal-title"><strong class="dictionary-title"></strong> <span class="light dictionary-version"></span></div> </div> - <div class="settings-item-children"> - + <div class="modal-body"> <div class="settings-item dictionary-outdated-notification" hidden><div class="settings-item-children danger-text"> This dictionary is outdated and may not support new extension features. Re-import the dictionary to enable support for the latest features. </div></div> - <div class="settings-item"><div class="settings-item-inner settings-item-inner-wrappable"> - <div class="settings-item-left"> - <div class="settings-item-label">Priority</div> - </div> - <div class="settings-item-right"> - <input type="number" step="1" class="short-height dictionary-priority"> - </div> - </div></div> - <div class="dictionary-details" hidden> - <div class="settings-item"> - <div class="settings-item-inner"> - <div class="settings-item-left"> - <div class="settings-item-label"> - Prefix wildcard searches supported - <a class="more-toggle more-only" data-parent-distance="4">(?)</a> - </div> - </div> - <div class="settings-item-right"> - <label class="toggle"><input type="checkbox" class="dictionary-prefix-wildcard-searches-supported" disabled readonly><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <div class="settings-item"> + <div class="settings-item-inner"> + <div class="settings-item-left"> + <div class="settings-item-label"> + Prefix wildcard searches supported + <a class="more-toggle more-only" data-parent-distance="4">(?)</a> </div> </div> - <div class="settings-item-children more" hidden> - <p class="warning-text"> - Changing this value requires the dictionary to be re-imported. - </p> - <p><a class="more-toggle" data-parent-distance="3">Hide…</a></p> + <div class="settings-item-right"> + <label class="toggle"><input type="checkbox" class="dictionary-prefix-wildcard-searches-supported" disabled readonly><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> </div> </div> - <div class="settings-item"><div class="settings-item-children"> - <div class="dictionary-details-table"></div> - <div class="dictionary-counts"></div> - </div></div> + <div class="settings-item-children more" hidden> + <p class="warning-text"> + Changing this value requires the dictionary to be re-imported. + </p> + <p><a class="more-toggle" data-parent-distance="3">Hide…</a></p> + </div> </div> - + <div class="settings-item"><div class="settings-item-children"> + <div class="dictionary-details-table"></div> + <div class="dictionary-counts"></div> + </div></div> </div> -</div></template> - -<template id="dictionary-details-entry-template"><div class="dictionary-details-entry"> - <span class="dictionary-details-entry-label"></span> - <span class="dictionary-details-entry-info"></span> -</div></template> + <div class="modal-footer"> + <button data-modal-action="hide">Close</button> + </div> +</div></div> -<template id="dictionary-extra-template"><div class="settings-item"> - <div class="settings-item-inner"> - <div class="settings-item-left"> - <div class="settings-item-label"><strong class="dictionary-title">Unassociated Data</strong> <span class="light dictionary-total-count"></span></div> +<div id="dictionary-extra-data-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content"> + <div class="modal-header"> + <div class="modal-title"> + <strong class="dictionary-title">Unassociated Data</strong> <span class="light dictionary-total-count"></span> </div> </div> - <div class="settings-item-children"> + <div class="modal-body"> <p class="warning-text"> The database contains extra data which is not associated with any installed dictionary. Purging the database can fix this issue. </p> <div class="dictionary-counts"></div> </div> + <div class="modal-footer"> + <button data-modal-action="hide">Close</button> + </div> +</div></div> + + +<!-- Dictionary templates --> +<template id="dictionary-template"> + <label class="toggle dictionary-item-enabled-toggle-container"><input type="checkbox" class="dictionary-enabled"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <div class="dictionary-item-title-container"> + <span> + <strong class="dictionary-title"></strong> <span class="light dictionary-version"></span> + </span> + <button class="dictionary-outdated-button" hidden> + <div class="badge warning-badge"><span class="icon" data-icon="exclamation-point-short"></span></div> + </button> + <button class="dictionary-integrity-button" hidden> + <div class="badge info-badge badge-small-icon"><span class="icon" data-icon="checkmark"></span></div> + </button> + </div> + <input type="number" step="1" class="short-height dictionary-priority"> + <button class="icon-button dictionary-menu-button" data-menu="dictionary-menu" data-menu-position="below left"><span class="icon-button-inner"><span class="icon" data-icon="kebab-menu"></span></span></button> +</template> + +<template id="dictionary-details-entry-template"><div class="dictionary-details-entry"> + <span class="dictionary-details-entry-label"></span> + <span class="dictionary-details-entry-info"></span> </div></template> +<template id="dictionary-extra-template"> + <div class="dictionary-item-bottom"></div> + <div class="dictionary-item-bottom dictionary-item-title-container"> + <span> + <strong class="dictionary-title">Unassociated Data</strong> <span class="light dictionary-total-count"></span> + </span> + <button class="dictionary-integrity-button"> + <div class="badge warning-badge"><span class="icon" data-icon="exclamation-point-short"></span></div> + </button> + </div> + <div class="dictionary-item-bottom"></div> + <div class="dictionary-item-bottom dictionary-item-button-height"></div> +</template> + <template id="dictionary-menu-template"><div class="popup-menu-container" tabindex="-1" role="dialog"><div class="popup-menu"><div class="popup-menu-body"> - <button class="popup-menu-item" data-menu-action="showDetails">Show details</button> - <button class="popup-menu-item" data-menu-action="hideDetails" hidden>Hide details</button> + <button class="popup-menu-item" data-menu-action="showDetails">Details…</button> <button class="popup-menu-item" data-menu-action="delete">Delete</button> </div></div></div></template> diff --git a/ext/welcome.html b/ext/welcome.html index 5876ad4c..fc7c203f 100644 --- a/ext/welcome.html +++ b/ext/welcome.html @@ -201,7 +201,15 @@ <!-- Dictionary modals --> <div id="dictionaries-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content"> - <div class="modal-header"><div class="modal-title">Dictionaries</div></div> + <div class="modal-header"> + <div class="modal-title">Dictionaries</div> + <div class="modal-header-button-container"> + <div class="modal-header-button-group"> + <button class="icon-button modal-header-button" data-modal-action="expand"><span class="icon-button-inner"><span class="icon" data-icon="expand"></span></span></button> + <button class="icon-button modal-header-button" data-modal-action="collapse"><span class="icon-button-inner"><span class="icon" data-icon="collapse"></span></span></button> + </div> + </div> + </div> <div class="modal-body"> <div class="settings-item"> <div class="settings-item-inner"> @@ -231,22 +239,18 @@ </div> </div> - <div class="settings-item"><div class="settings-item-inner"> - <div class="settings-item-left"> - <div class="settings-item-label"> - More dictionary settings are available on the <a href="/settings.html" rel="noopener">Settings</a> page - </div> - </div> - </div></div> - <div class="warning-text margin-above no-dictionaries-installed-warning" hidden> No dictionaries have been installed yet. Visit the <a href="https://foosoft.net/projects/yomichan/#dictionaries" target="_blank" rel="noopener noreferrer">Yomichan homepage</a> for a list free dictionaries or click the <em>Import</em> button below to select a dictionary file to import. </div> <div id="dictionary-error" class="danger-text margin-above" hidden></div> - <div id="dictionary-list" class="dictionary-list"></div> - <div id="dictionary-list-extra" class="dictionary-list"></div> + <div id="dictionary-list" class="dictionary-list" data-count="0"> + <label class="dictionary-item-top toggle dictionary-item-enabled-toggle-container"><input type="checkbox" id="all-dictionaries-enabled"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <div class="dictionary-item-top dictionary-item-title-container">All</div> + <div class="dictionary-item-top">Priority</div> + <div class="dictionary-item-top dictionary-item-button-height"></div> + </div> <div hidden><input type="file" id="dictionary-import-file-input" accept=".zip,application/zip" multiple></div> </div> @@ -290,23 +294,70 @@ </div> </div></div> - -<!-- Dictionary templates --> -<template id="dictionary-template"><div class="settings-item dictionary-item"> - <div class="settings-item-inner"> - <div class="settings-item-left"> - <div class="settings-item-label dictionary-info"> - <label class="toggle"><input type="checkbox" class="dictionary-enabled"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> - <span class="dictionary-info-label"><strong class="dictionary-title"></strong> <span class="light dictionary-version"></span></span> +<div id="dictionary-details-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content"> + <div class="modal-header"> + <div class="modal-title"><strong class="dictionary-title"></strong> <span class="light dictionary-version"></span></div> + </div> + <div class="modal-body"> + <div class="settings-item dictionary-outdated-notification" hidden><div class="settings-item-children danger-text"> + This dictionary is outdated and may not support new extension features. + Re-import the dictionary to enable support for the latest features. + </div></div> + <div class="settings-item"> + <div class="settings-item-inner"> + <div class="settings-item-left"> + <div class="settings-item-label"> + Prefix wildcard searches supported + <a class="more-toggle more-only" data-parent-distance="4">(?)</a> + </div> + </div> + <div class="settings-item-right"> + <label class="toggle"><input type="checkbox" class="dictionary-prefix-wildcard-searches-supported" disabled readonly><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + </div> + </div> + <div class="settings-item-children more" hidden> + <p class="warning-text"> + Changing this value requires the dictionary to be re-imported. + </p> + <p><a class="more-toggle" data-parent-distance="3">Hide…</a></p> </div> </div> - <div class="settings-item-right"> - <button class="icon-button dictionary-menu-button" data-menu="dictionary-menu" data-menu-position="below left"><span class="icon-button-inner"><span class="icon" data-icon="kebab-menu"></span></span></button> - </div> + <div class="settings-item"><div class="settings-item-children"> + <div class="dictionary-details-table"></div> + <div class="dictionary-counts"></div> + </div></div> </div> + <div class="modal-footer"> + <button data-modal-action="hide">Close</button> + </div> +</div></div> + + +<!-- Dictionary templates --> +<template id="dictionary-template"> + <label class="toggle dictionary-item-enabled-toggle-container"><input type="checkbox" class="dictionary-enabled"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <div class="dictionary-item-title-container"> + <span> + <strong class="dictionary-title"></strong> <span class="light dictionary-version"></span> + </span> + <button class="dictionary-outdated-button" hidden> + <div class="badge warning-badge"><span class="icon" data-icon="exclamation-point-short"></span></div> + </button> + <button class="dictionary-integrity-button" hidden> + <div class="badge info-badge badge-small-icon"><span class="icon" data-icon="checkmark"></span></div> + </button> + </div> + <input type="number" step="1" class="short-height dictionary-priority"> + <button class="icon-button dictionary-menu-button" data-menu="dictionary-menu" data-menu-position="below left"><span class="icon-button-inner"><span class="icon" data-icon="kebab-menu"></span></span></button> +</template> + +<template id="dictionary-details-entry-template"><div class="dictionary-details-entry"> + <span class="dictionary-details-entry-label"></span> + <span class="dictionary-details-entry-info"></span> </div></template> <template id="dictionary-menu-template"><div class="popup-menu-container" tabindex="-1" role="dialog"><div class="popup-menu"><div class="popup-menu-body"> + <button class="popup-menu-item" data-menu-action="showDetails">Details…</button> <button class="popup-menu-item" data-menu-action="delete">Delete</button> </div></div></div></template> |