Improve dictionary options (#1640)

* Update dictionary options layout

* Update extras

* Improve display when no dictionaries are installed

* Implement "All" toggle

* Move modal

* Update welcome page

* Remove resizer button

* Fix ordering

* Fix extra closing tag
This commit is contained in:
toasted-nutbread 2021-04-30 18:01:16 -04:00 committed by GitHub
parent d77d8e44e0
commit 076e201225
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 461 additions and 258 deletions

View File

@ -1313,65 +1313,6 @@ body.preview-sidebar-visible .fab-container-item.fab-container-item-popup-previe
display: none; 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 { .profile-add-button-container {
display: flex; display: flex;
flex-flow: row nowrap; 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))); top: calc(1em * (3 / var(--font-size-no-units)));
} }
.warning-badge { .badge {
position: relative; position: relative;
width: var(--badge-size); width: var(--badge-size);
height: var(--badge-size); height: var(--badge-size);
margin: 0; margin: 0;
padding: 0; padding: 0;
background-color: var(--warning-color-light);
border-radius: 50%; border-radius: 50%;
box-shadow: var(--shadow-vertical); box-shadow: var(--shadow-vertical);
} }
.warning-badge:not([hidden]) { .badge:not([hidden]) {
display: block; display: block;
} }
.warning-badge>.icon { .badge>.icon {
display: block; display: block;
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
right: 0; right: 0;
bottom: 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); 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 { .collapsible-dictionary-list {
width: 100%; 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 */ /* Generic layouts */
.margin-above { .margin-above {
margin-top: 0.85em; margin-top: 0.85em;

View File

@ -20,19 +20,21 @@
*/ */
class DictionaryEntry { class DictionaryEntry {
constructor(dictionaryController, node, index, dictionaryInfo) { constructor(dictionaryController, fragment, index, dictionaryInfo) {
this._dictionaryController = dictionaryController; this._dictionaryController = dictionaryController;
this._node = node;
this._index = index; this._index = index;
this._dictionaryInfo = dictionaryInfo; this._dictionaryInfo = dictionaryInfo;
this._eventListeners = new EventListenerCollection(); this._eventListeners = new EventListenerCollection();
this._detailsContainer = null; this._counts = null;
this._hasDetails = false; this._nodes = [...fragment.childNodes];
this._hasCounts = false; this._enabledCheckbox = fragment.querySelector('.dictionary-enabled');
} this._priorityInput = fragment.querySelector('.dictionary-priority');
this._menuButton = fragment.querySelector('.dictionary-menu-button');
get node() { this._outdatedButton = fragment.querySelector('.dictionary-outdated-button');
return this._node; 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() { get dictionaryTitle() {
@ -40,98 +42,80 @@ class DictionaryEntry {
} }
prepare() { prepare() {
const node = this._node;
const index = this._index; const index = this._index;
const {title, revision, prefixWildcardsSupported, version} = this._dictionaryInfo; const {title, revision, version} = this._dictionaryInfo;
this._detailsContainer = node.querySelector('.dictionary-details'); this._titleNode.textContent = title;
this._versionNode.textContent = `rev.${revision}`;
const enabledCheckbox = node.querySelector('.dictionary-enabled'); this._outdatedButton.hidden = (version >= 3);
const priorityInput = node.querySelector('.dictionary-priority'); this._priorityInput.dataset.setting = `dictionaries[${index}].priority`;
const menuButton = node.querySelector('.dictionary-menu-button'); this._enabledCheckbox.dataset.setting = `dictionaries[${index}].enabled`;
const detailsTable = node.querySelector('.dictionary-details-table'); this._eventListeners.addEventListener(this._enabledCheckbox, 'settingChanged', this._onEnabledChanged.bind(this), false);
const outdatedContainer = node.querySelector('.dictionary-outdated-notification'); this._eventListeners.addEventListener(this._menuButton, 'menuClose', this._onMenuClose.bind(this), false);
const titleNode = node.querySelector('.dictionary-title'); this._eventListeners.addEventListener(this._outdatedButton, 'click', this._onOutdatedButtonClick.bind(this), false);
const versionNode = node.querySelector('.dictionary-version'); this._eventListeners.addEventListener(this._integrityButton, 'click', this._onIntegrityButtonClick.bind(this), false);
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);
}
} }
cleanup() { cleanup() {
this._eventListeners.removeAllEventListeners(); this._eventListeners.removeAllEventListeners();
const node = this._node; for (const node of this._nodes) {
if (node.parentNode !== null) { if (node.parentNode !== null) {
node.parentNode.removeChild(node); node.parentNode.removeChild(node);
}
} }
this._nodes = [];
} }
setCounts(counts) { setCounts(counts) {
const node = this._node.querySelector('.dictionary-counts'); this._counts = counts;
node.textContent = JSON.stringify({info: this._dictionaryInfo, counts}, null, 4); this._integrityButton.hidden = false;
node.hidden = false; }
this._hasCounts = true;
setEnabled(value) {
this._enabledCheckbox.checked = value;
} }
// Private // 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;
}
}
_onMenuClose(e) { _onMenuClose(e) {
switch (e.detail.action) { switch (e.detail.action) {
case 'delete': case 'delete':
this._delete(); this._delete();
break; break;
case 'showDetails': case 'showDetails':
if (this._detailsContainer !== null) { this._detailsContainer.hidden = false; } this._showDetails();
break;
case 'hideDetails':
if (this._detailsContainer !== null) { this._detailsContainer.hidden = true; }
break; break;
} }
} }
_onEnabledChanged(e) { _onEnabledChanged(e) {
const {detail: {value}} = e; const {detail: {value}} = e;
this._node.dataset.enabled = `${value}`; this._titleContainer.dataset.enabled = `${value}`;
this._dictionaryController.updateDictionariesEnabled(); 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) { _setupDetails(detailsTable) {
const targets = [ const targets = [
['Author', 'author'], ['Author', 'author'],
@ -156,6 +140,7 @@ class DictionaryEntry {
any = true; any = true;
} }
detailsTable.textContent = '';
detailsTable.appendChild(fragment); detailsTable.appendChild(fragment);
return any; 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 { class DictionaryController {
constructor(settingsController, modalController, statusFooter) { constructor(settingsController, modalController, statusFooter) {
this._settingsController = settingsController; this._settingsController = settingsController;
@ -176,34 +212,40 @@ class DictionaryController {
this._checkingIntegrity = false; this._checkingIntegrity = false;
this._checkIntegrityButton = null; this._checkIntegrityButton = null;
this._dictionaryEntryContainer = null; this._dictionaryEntryContainer = null;
this._integrityExtraInfoContainer = null;
this._dictionaryInstallCountNode = null; this._dictionaryInstallCountNode = null;
this._dictionaryEnabledCountNode = null; this._dictionaryEnabledCountNode = null;
this._noDictionariesInstalledWarnings = null; this._noDictionariesInstalledWarnings = null;
this._noDictionariesEnabledWarnings = null; this._noDictionariesEnabledWarnings = null;
this._deleteDictionaryModal = null; this._deleteDictionaryModal = null;
this._integrityExtraInfoNode = null; this._allCheckbox = null;
this._extraInfo = null;
this._isDeleting = false; this._isDeleting = false;
} }
get modalController() {
return this._modalController;
}
async prepare() { async prepare() {
this._checkIntegrityButton = document.querySelector('#dictionary-check-integrity'); this._checkIntegrityButton = document.querySelector('#dictionary-check-integrity');
this._dictionaryEntryContainer = document.querySelector('#dictionary-list'); this._dictionaryEntryContainer = document.querySelector('#dictionary-list');
this._integrityExtraInfoContainer = document.querySelector('#dictionary-list-extra');
this._dictionaryInstallCountNode = document.querySelector('#dictionary-install-count'); this._dictionaryInstallCountNode = document.querySelector('#dictionary-install-count');
this._dictionaryEnabledCountNode = document.querySelector('#dictionary-enabled-count'); this._dictionaryEnabledCountNode = document.querySelector('#dictionary-enabled-count');
this._noDictionariesInstalledWarnings = document.querySelectorAll('.no-dictionaries-installed-warning'); this._noDictionariesInstalledWarnings = document.querySelectorAll('.no-dictionaries-installed-warning');
this._noDictionariesEnabledWarnings = document.querySelectorAll('.no-dictionaries-enabled-warning'); this._noDictionariesEnabledWarnings = document.querySelectorAll('.no-dictionaries-enabled-warning');
this._deleteDictionaryModal = this._modalController.getModal('dictionary-confirm-delete'); this._deleteDictionaryModal = this._modalController.getModal('dictionary-confirm-delete');
this._allCheckbox = document.querySelector('#all-dictionaries-enabled');
yomichan.on('databaseUpdated', this._onDatabaseUpdated.bind(this)); yomichan.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
this._settingsController.on('optionsChanged', this._onOptionsChanged.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); document.querySelector('#dictionary-confirm-delete-button').addEventListener('click', this._onDictionaryConfirmDelete.bind(this), false);
if (this._checkIntegrityButton !== null) { if (this._checkIntegrityButton !== null) {
this._checkIntegrityButton.addEventListener('click', this._onCheckIntegrityButtonClick.bind(this), false); this._checkIntegrityButton.addEventListener('click', this._onCheckIntegrityButtonClick.bind(this), false);
} }
this._updateDictionaryEntryCount();
await this._onDatabaseUpdated(); await this._onDatabaseUpdated();
} }
@ -219,6 +261,10 @@ class DictionaryController {
return this._settingsController.instantiateTemplate(name); return this._settingsController.instantiateTemplate(name);
} }
instantiateTemplateFragment(name) {
return this._settingsController.instantiateTemplateFragment(name);
}
async updateDictionariesEnabled() { async updateDictionariesEnabled() {
const options = await this._settingsController.getOptions(); const options = await this._settingsController.getOptions();
this._updateDictionariesEnabledWarnings(options); this._updateDictionariesEnabledWarnings(options);
@ -303,6 +349,12 @@ class DictionaryController {
await this._updateEntries(); await this._updateEntries();
} }
_onAllCheckboxChange() {
const value = this._allCheckbox.checked;
this._allCheckbox.checked = !value;
this._setAllDictionariesEnabled(value);
}
async _updateEntries() { async _updateEntries() {
const dictionaries = this._dictionaries; const dictionaries = this._dictionaries;
this._updateMainDictionarySelectOptions(dictionaries); this._updateMainDictionarySelectOptions(dictionaries);
@ -311,6 +363,7 @@ class DictionaryController {
entry.cleanup(); entry.cleanup();
} }
this._dictionaryEntries = []; this._dictionaryEntries = [];
this._updateDictionaryEntryCount();
if (this._dictionaryInstallCountNode !== null) { if (this._dictionaryInstallCountNode !== null) {
this._dictionaryInstallCountNode.textContent = `${dictionaries.length}`; this._dictionaryInstallCountNode.textContent = `${dictionaries.length}`;
@ -341,29 +394,40 @@ class DictionaryController {
} }
_updateDictionariesEnabledWarnings(options) { _updateDictionariesEnabledWarnings(options) {
let enabledCount = 0; const {dictionaries} = options;
let enabledDictionaryCountValid = 0;
let enabledDictionaryCount = 0;
const dictionaryCount = dictionaries.length;
if (this._dictionaries !== null) { if (this._dictionaries !== null) {
const enabledDictionaries = new Set(); const enabledDictionaries = new Set();
for (const {name, enabled} of options.dictionaries) { for (const {name, enabled} of dictionaries) {
if (enabled) { if (enabled) {
++enabledDictionaryCount;
enabledDictionaries.add(name); enabledDictionaries.add(name);
} }
} }
for (const {title} of this._dictionaries) { for (const {title} of this._dictionaries) {
if (enabledDictionaries.has(title)) { if (enabledDictionaries.has(title)) {
++enabledCount; ++enabledDictionaryCountValid;
} }
} }
} }
const hasEnabledDictionary = (enabledCount > 0); const hasEnabledDictionary = (enabledDictionaryCountValid > 0);
for (const node of this._noDictionariesEnabledWarnings) { for (const node of this._noDictionariesEnabledWarnings) {
node.hidden = hasEnabledDictionary; node.hidden = hasEnabledDictionary;
} }
if (this._dictionaryEnabledCountNode !== null) { 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]; totalRemainder += remainders[key];
} }
this._cleanupExtra(); if (this._extraInfo !== null) {
this._extraInfo.cleanup();
this._extraInfo = null;
}
if (totalRemainder > 0) { if (totalRemainder > 0) {
this.extra = this._createExtra(totalCounts, remainders, totalRemainder); this._extraInfo = new DictionaryExtraInfo(this, totalCounts, remainders, totalRemainder);
this._extraInfo.prepare(this._dictionaryEntryContainer);
} }
} }
_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);
}
_createDictionaryEntry(index, dictionaryInfo) { _createDictionaryEntry(index, dictionaryInfo) {
const node = this.instantiateTemplate('dictionary'); const fragment = this.instantiateTemplateFragment('dictionary');
this._dictionaryEntryContainer.appendChild(node);
const entry = new DictionaryEntry(this, node, index, dictionaryInfo); const entry = new DictionaryEntry(this, fragment, index, dictionaryInfo);
this._dictionaryEntries.push(entry); this._dictionaryEntries.push(entry);
entry.prepare(); entry.prepare();
const container = this._dictionaryEntryContainer;
const relative = container.querySelector('.dictionary-item-bottom');
container.insertBefore(fragment, relative);
this._updateDictionaryEntryCount();
} }
async _deleteDictionary(dictionaryTitle) { async _deleteDictionary(dictionaryTitle) {
@ -589,4 +639,25 @@ class DictionaryController {
_triggerStorageChanged() { _triggerStorageChanged() {
yomichan.trigger('storageChanged'); 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();
}
} }

View File

@ -22,7 +22,7 @@
<div class="sidebar"><div class="sidebar-inner"> <div class="sidebar"><div class="sidebar-inner">
<div class="sidebar-body"> <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="#!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="#!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="#!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> <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="settings-item-label">
<div class="flex-row-nowrap"> <div class="flex-row-nowrap">
<div>Configure installed and enabled dictionaries&hellip;</div> <div>Configure installed and enabled dictionaries&hellip;</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> </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. for a list free dictionaries or click the <em>Import</em> button below to select a dictionary file to import.
</div> </div>
<div id="dictionary-error" class="danger-text margin-above" hidden></div> <div id="dictionary-error" class="danger-text margin-above" hidden></div>
<div id="dictionary-list" class="dictionary-list"></div> <div id="dictionary-list" class="dictionary-list" data-count="0">
<div id="dictionary-list-extra" class="dictionary-list"></div> <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 hidden><input type="file" id="dictionary-import-file-input" accept=".zip,application/zip" multiple></div>
</div> </div>
@ -2166,86 +2170,102 @@
</div> </div>
</div></div> </div></div>
<div id="dictionary-details-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content">
<!-- Dictionary templates --> <div class="modal-header">
<template id="dictionary-template"><div class="settings-item dictionary-item"> <div class="modal-title"><strong class="dictionary-title"></strong> <span class="light dictionary-version"></span></div>
<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> </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"> <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. This dictionary is outdated and may not support new extension features.
Re-import the dictionary to enable support for the latest features. Re-import the dictionary to enable support for the latest features.
</div></div> </div></div>
<div class="settings-item"><div class="settings-item-inner settings-item-inner-wrappable"> <div class="settings-item">
<div class="settings-item-left"> <div class="settings-item-inner">
<div class="settings-item-label">Priority</div> <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>
<div class="settings-item-right"> <div class="settings-item-children more" hidden>
<input type="number" step="1" class="short-height dictionary-priority"> <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&hellip;</a></p>
</div> </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>
<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>
</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&hellip;</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> </div>
</div></template> <div class="modal-footer">
<button data-modal-action="hide">Close</button>
</div>
</div></div>
<template id="dictionary-details-entry-template"><div class="dictionary-details-entry"> <div id="dictionary-extra-data-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content">
<span class="dictionary-details-entry-label"></span> <div class="modal-header">
<span class="dictionary-details-entry-info"></span> <div class="modal-title">
</div></template> <strong class="dictionary-title">Unassociated Data</strong> <span class="light dictionary-total-count"></span>
<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> </div>
</div> </div>
<div class="settings-item-children"> <div class="modal-body">
<p class="warning-text"> <p class="warning-text">
The database contains extra data which is not associated with any installed dictionary. The database contains extra data which is not associated with any installed dictionary.
Purging the database can fix this issue. Purging the database can fix this issue.
</p> </p>
<div class="dictionary-counts"></div> <div class="dictionary-counts"></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> </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"> <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="showDetails">Details&hellip;</button>
<button class="popup-menu-item" data-menu-action="hideDetails" hidden>Hide details</button>
<button class="popup-menu-item" data-menu-action="delete">Delete</button> <button class="popup-menu-item" data-menu-action="delete">Delete</button>
</div></div></div></template> </div></div></div></template>

View File

@ -201,7 +201,15 @@
<!-- Dictionary modals --> <!-- Dictionary modals -->
<div id="dictionaries-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content"> <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="modal-body">
<div class="settings-item"> <div class="settings-item">
<div class="settings-item-inner"> <div class="settings-item-inner">
@ -231,22 +239,18 @@
</div> </div>
</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> <div class="warning-text margin-above no-dictionaries-installed-warning" hidden>
No dictionaries have been installed yet. No dictionaries have been installed yet.
Visit the <a href="https://foosoft.net/projects/yomichan/#dictionaries" target="_blank" rel="noopener noreferrer">Yomichan homepage</a> 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. for a list free dictionaries or click the <em>Import</em> button below to select a dictionary file to import.
</div> </div>
<div id="dictionary-error" class="danger-text margin-above" hidden></div> <div id="dictionary-error" class="danger-text margin-above" hidden></div>
<div id="dictionary-list" class="dictionary-list"></div> <div id="dictionary-list" class="dictionary-list" data-count="0">
<div id="dictionary-list-extra" class="dictionary-list"></div> <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 hidden><input type="file" id="dictionary-import-file-input" accept=".zip,application/zip" multiple></div>
</div> </div>
@ -290,23 +294,70 @@
</div> </div>
</div></div> </div></div>
<div id="dictionary-details-modal" class="modal" tabindex="-1" role="dialog" hidden><div class="modal-content">
<!-- Dictionary templates --> <div class="modal-header">
<template id="dictionary-template"><div class="settings-item dictionary-item"> <div class="modal-title"><strong class="dictionary-title"></strong> <span class="light dictionary-version"></span></div>
<div class="settings-item-inner"> </div>
<div class="settings-item-left"> <div class="modal-body">
<div class="settings-item-label dictionary-info"> <div class="settings-item dictionary-outdated-notification" hidden><div class="settings-item-children danger-text">
<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> This dictionary is outdated and may not support new extension features.
<span class="dictionary-info-label"><strong class="dictionary-title"></strong> <span class="light dictionary-version"></span></span> 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&hellip;</a></p>
</div> </div>
</div> </div>
<div class="settings-item-right"> <div class="settings-item"><div class="settings-item-children">
<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 class="dictionary-details-table"></div>
</div> <div class="dictionary-counts"></div>
</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> </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"> <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&hellip;</button>
<button class="popup-menu-item" data-menu-action="delete">Delete</button> <button class="popup-menu-item" data-menu-action="delete">Delete</button>
</div></div></div></template> </div></div></div></template>