aboutsummaryrefslogtreecommitdiff
path: root/ext/js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js')
-rw-r--r--ext/js/background/backend.js13
-rw-r--r--ext/js/comm/anki-connect.js8
-rw-r--r--ext/js/comm/api.js12
-rw-r--r--ext/js/data/options-util.js17
-rw-r--r--ext/js/display/display-anki.js46
-rw-r--r--ext/js/pages/settings/anki-controller.js2
-rw-r--r--ext/js/pages/settings/keyboard-shortcuts-controller.js2
7 files changed, 62 insertions, 38 deletions
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index 8b5e8383..090ba7b3 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -154,7 +154,7 @@ export class Backend {
['addAnkiNote', this._onApiAddAnkiNote.bind(this)],
['getAnkiNoteInfo', this._onApiGetAnkiNoteInfo.bind(this)],
['injectAnkiNoteMedia', this._onApiInjectAnkiNoteMedia.bind(this)],
- ['noteView', this._onApiNoteView.bind(this)],
+ ['viewNotes', this._onApiViewNotes.bind(this)],
['suspendAnkiCardsForNote', this._onApiSuspendAnkiCardsForNote.bind(this)],
['commandExec', this._onApiCommandExec.bind(this)],
['getTermAudioInfoList', this._onApiGetTermAudioInfoList.bind(this)],
@@ -580,11 +580,11 @@ export class Backend {
);
}
- /** @type {import('api').ApiHandler<'noteView'>} */
- async _onApiNoteView({noteId, mode, allowFallback}) {
- if (mode === 'edit') {
+ /** @type {import('api').ApiHandler<'viewNotes'>} */
+ async _onApiViewNotes({noteIds, mode, allowFallback}) {
+ if (noteIds.length === 1 && mode === 'edit') {
try {
- await this._anki.guiEditNote(noteId);
+ await this._anki.guiEditNote(noteIds[0]);
return 'edit';
} catch (e) {
if (!(e instanceof Error && this._anki.isErrorUnsupportedAction(e))) {
@@ -594,8 +594,7 @@ export class Backend {
}
}
}
- // Fallback
- await this._anki.guiBrowseNote(noteId);
+ await this._anki.guiBrowseNotes(noteIds);
return 'browse';
}
diff --git a/ext/js/comm/anki-connect.js b/ext/js/comm/anki-connect.js
index 7cb2d071..0bf38bda 100644
--- a/ext/js/comm/anki-connect.js
+++ b/ext/js/comm/anki-connect.js
@@ -201,6 +201,14 @@ export class AnkiConnect {
}
/**
+ * @param {import('anki').NoteId[]} noteIds
+ * @returns {Promise<import('anki').CardId[]>}
+ */
+ async guiBrowseNotes(noteIds) {
+ return await this.guiBrowse(`nid:${noteIds.join(',')}`);
+ }
+
+ /**
* Opens the note editor GUI.
* @param {import('anki').NoteId} noteId The ID of the note.
* @returns {Promise<void>} Nothing is returned.
diff --git a/ext/js/comm/api.js b/ext/js/comm/api.js
index 2e1e8826..b4fdbeb5 100644
--- a/ext/js/comm/api.js
+++ b/ext/js/comm/api.js
@@ -118,13 +118,13 @@ export class API {
}
/**
- * @param {import('api').ApiParam<'noteView', 'noteId'>} noteId
- * @param {import('api').ApiParam<'noteView', 'mode'>} mode
- * @param {import('api').ApiParam<'noteView', 'allowFallback'>} allowFallback
- * @returns {Promise<import('api').ApiReturn<'noteView'>>}
+ * @param {import('api').ApiParam<'viewNotes', 'noteIds'>} noteIds
+ * @param {import('api').ApiParam<'viewNotes', 'mode'>} mode
+ * @param {import('api').ApiParam<'viewNotes', 'allowFallback'>} allowFallback
+ * @returns {Promise<import('api').ApiReturn<'viewNotes'>>}
*/
- noteView(noteId, mode, allowFallback) {
- return this._invoke('noteView', {noteId, mode, allowFallback});
+ viewNotes(noteIds, mode, allowFallback) {
+ return this._invoke('viewNotes', {noteIds, mode, allowFallback});
}
/**
diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js
index 312c6efc..1644df2f 100644
--- a/ext/js/data/options-util.js
+++ b/ext/js/data/options-util.js
@@ -521,7 +521,8 @@ export class OptionsUtil {
this._updateVersion21,
this._updateVersion22,
this._updateVersion23,
- this._updateVersion24
+ this._updateVersion24,
+ this._updateVersion25
];
/* eslint-enable @typescript-eslint/unbound-method */
if (typeof targetVersion === 'number' && targetVersion < result.length) {
@@ -1140,6 +1141,20 @@ export class OptionsUtil {
}
/**
+ * - Change 'viewNote' action to 'viewNotes'.
+ * @type {import('options-util').UpdateFunction}
+ */
+ async _updateVersion25(options) {
+ for (const profile of options.profiles) {
+ for (const hotkey of profile.options.inputs.hotkeys) {
+ if (hotkey.action === 'viewNote') {
+ hotkey.action = 'viewNotes';
+ }
+ }
+ }
+ }
+
+ /**
* @param {string} url
* @returns {Promise<chrome.tabs.Tab>}
*/
diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js
index 665521dd..4766f1ae 100644
--- a/ext/js/display/display-anki.js
+++ b/ext/js/display/display-anki.js
@@ -99,11 +99,11 @@ export class DisplayAnki {
/** @type {(event: MouseEvent) => void} */
this._onNoteAddBind = this._onNoteAdd.bind(this);
/** @type {(event: MouseEvent) => void} */
- this._onViewNoteButtonClickBind = this._onViewNoteButtonClick.bind(this);
+ this._onViewNotesButtonClickBind = this._onViewNotesButtonClick.bind(this);
/** @type {(event: MouseEvent) => void} */
- this._onViewNoteButtonContextMenuBind = this._onViewNoteButtonContextMenu.bind(this);
+ this._onViewNotesButtonContextMenuBind = this._onViewNotesButtonContextMenu.bind(this);
/** @type {(event: import('popup-menu').MenuCloseEvent) => void} */
- this._onViewNoteButtonMenuCloseBind = this._onViewNoteButtonMenuClose.bind(this);
+ this._onViewNotesButtonMenuCloseBind = this._onViewNotesButtonMenuClose.bind(this);
}
/** */
@@ -114,7 +114,7 @@ export class DisplayAnki {
['addNoteKanji', () => { this._tryAddAnkiNoteForSelectedEntry('kanji'); }],
['addNoteTermKanji', () => { this._tryAddAnkiNoteForSelectedEntry('term-kanji'); }],
['addNoteTermKana', () => { this._tryAddAnkiNoteForSelectedEntry('term-kana'); }],
- ['viewNote', this._viewNoteForSelectedEntry.bind(this)]
+ ['viewNotes', this._viewNotesForSelectedEntry.bind(this)]
]);
/* eslint-enable @stylistic/no-multi-spaces */
this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this));
@@ -249,9 +249,9 @@ export class DisplayAnki {
eventListeners.addEventListener(node, 'click', this._onNoteAddBind);
}
for (const node of element.querySelectorAll('.action-button[data-action=view-note]')) {
- eventListeners.addEventListener(node, 'click', this._onViewNoteButtonClickBind);
- eventListeners.addEventListener(node, 'contextmenu', this._onViewNoteButtonContextMenuBind);
- eventListeners.addEventListener(node, 'menuClose', this._onViewNoteButtonMenuCloseBind);
+ eventListeners.addEventListener(node, 'click', this._onViewNotesButtonClickBind);
+ eventListeners.addEventListener(node, 'contextmenu', this._onViewNotesButtonContextMenuBind);
+ eventListeners.addEventListener(node, 'menuClose', this._onViewNotesButtonMenuCloseBind);
}
}
@@ -777,34 +777,34 @@ export class DisplayAnki {
/**
* @param {MouseEvent} e
*/
- _onViewNoteButtonClick(e) {
+ _onViewNotesButtonClick(e) {
const element = /** @type {HTMLElement} */ (e.currentTarget);
e.preventDefault();
if (e.shiftKey) {
- this._showViewNoteMenu(element);
+ this._showViewNotesMenu(element);
} else {
- this._viewNote(element);
+ this._viewNotes(element);
}
}
/**
* @param {MouseEvent} e
*/
- _onViewNoteButtonContextMenu(e) {
+ _onViewNotesButtonContextMenu(e) {
const element = /** @type {HTMLElement} */ (e.currentTarget);
e.preventDefault();
- this._showViewNoteMenu(element);
+ this._showViewNotesMenu(element);
}
/**
* @param {import('popup-menu').MenuCloseEvent} e
*/
- _onViewNoteButtonMenuClose(e) {
+ _onViewNotesButtonMenuClose(e) {
const {detail: {action, item}} = e;
switch (action) {
- case 'viewNote':
+ case 'viewNotes':
if (item !== null) {
- this._viewNote(item);
+ this._viewNotes(item);
}
break;
}
@@ -848,11 +848,11 @@ export class DisplayAnki {
/**
* @param {HTMLElement} node
*/
- async _viewNote(node) {
+ async _viewNotes(node) {
const noteIds = this._getNodeNoteIds(node);
if (noteIds.length === 0) { return; }
try {
- await this._display.application.api.noteView(noteIds[0], this._noteGuiMode, false);
+ await this._display.application.api.viewNotes(noteIds, this._noteGuiMode, false);
} catch (e) {
const displayErrors = (
toError(e).message === 'Mode not supported' ?
@@ -867,7 +867,7 @@ export class DisplayAnki {
/**
* @param {HTMLElement} node
*/
- _showViewNoteMenu(node) {
+ _showViewNotesMenu(node) {
const noteIds = this._getNodeNoteIds(node);
if (noteIds.length === 0) { return; }
@@ -883,7 +883,7 @@ export class DisplayAnki {
/** @type {Element} */
const label = querySelectorNotNull(item, '.popup-menu-item-label');
label.textContent = `Note ${i + 1}: ${noteId}`;
- item.dataset.menuAction = 'viewNote';
+ item.dataset.menuAction = 'viewNotes';
item.dataset.noteIds = `${noteId}`;
menuBodyNode.appendChild(item);
}
@@ -920,12 +920,14 @@ export class DisplayAnki {
return entry !== null ? entry.querySelector('.action-button[data-action=view-note]') : null;
}
- /** */
- _viewNoteForSelectedEntry() {
+ /**
+ * Shows notes for selected pop-up entry when "View Notes" hotkey is used.
+ */
+ _viewNotesForSelectedEntry() {
const index = this._display.selectedIndex;
const button = this._getViewNoteButton(index);
if (button !== null) {
- this._viewNote(button);
+ this._viewNotes(button);
}
}
diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js
index a2948eda..3a6345ed 100644
--- a/ext/js/pages/settings/anki-controller.js
+++ b/ext/js/pages/settings/anki-controller.js
@@ -455,7 +455,7 @@ export class AnkiController {
throw new Error('Could not find a note to test with');
}
- await this._settingsController.application.api.noteView(noteId, mode, false);
+ await this._settingsController.application.api.viewNotes([noteId], mode, false);
}
/**
diff --git a/ext/js/pages/settings/keyboard-shortcuts-controller.js b/ext/js/pages/settings/keyboard-shortcuts-controller.js
index 24d34d5b..7b28a322 100644
--- a/ext/js/pages/settings/keyboard-shortcuts-controller.js
+++ b/ext/js/pages/settings/keyboard-shortcuts-controller.js
@@ -62,7 +62,7 @@ export class KeyboardShortcutController {
['addNoteKanji', {scopes: new Set(['popup', 'search'])}],
['addNoteTermKanji', {scopes: new Set(['popup', 'search'])}],
['addNoteTermKana', {scopes: new Set(['popup', 'search'])}],
- ['viewNote', {scopes: new Set(['popup', 'search'])}],
+ ['viewNotes', {scopes: new Set(['popup', 'search'])}],
['playAudio', {scopes: new Set(['popup', 'search'])}],
['playAudioFromSource', {scopes: new Set(['popup', 'search']), argument: {template: 'hotkey-argument-audio-source', default: 'jpod101'}}],
['copyHostSelection', {scopes: new Set(['popup'])}],