Skip to content

Commit

Permalink
add: collection menu
Browse files Browse the repository at this point in the history
  • Loading branch information
windingwind committed Nov 29, 2023
1 parent addf94c commit 3b11a12
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 60 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ if (items?.length > 0) {
</details>
- `collection`: The target collection object, only available when triggered by collection menu.
- `require`: The `require` function to import global variables. Use `const window = require('window')` to import the `window` variable.
<details style="text-indent: 4em">
Expand Down
1 change: 1 addition & 0 deletions addon/locale/en-US/addon.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ prefs-action-shortcut = Shortcut
prefs-action-enabled = Enabled
prefs-action-menu = Menu Label
prefs-action-showInMenuItem = In Item Menu
prefs-action-showInMenuCollection = In Collection Menu
prefs-action-showInMenuReader = In Reader Menu
prefs-action-showInMenuReaderAnnotation = In Annotation Menu
Expand Down
1 change: 1 addition & 0 deletions addon/locale/it-IT/addon.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ prefs-action-shortcut = Scorciatoia
prefs-action-enabled = Attivo
prefs-action-menu = Etichetta menu
prefs-action-showInMenuItem = In Item Menu
prefs-action-showInMenuCollection = In Collection Menu
prefs-action-showInMenuReader = In Reader Menu
prefs-action-showInMenuReaderAnnotation = In Annotation Menu
Expand Down
1 change: 1 addition & 0 deletions addon/locale/zh-CN/addon.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ prefs-action-shortcut = 快捷键
prefs-action-enabled = 启用
prefs-action-menu = 菜单项
prefs-action-showInMenuItem = 条目菜单中
prefs-action-showInMenuCollection = 分类菜单中
prefs-action-showInMenuReader = 阅读器菜单中
prefs-action-showInMenuReaderAnnotation = 注释菜单中
Expand Down
24 changes: 24 additions & 0 deletions src/modules/edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ async function editAction(currentKey?: string) {
new KeyModifier(action.shortcut || "").getLocalized() ||
`[${getString("prefs-action-edit-shortcut-empty")}]`;
dialogData.showInMenuItem = !(action.showInMenu?.item === false);
dialogData.showInMenuCollection = !(action.showInMenu?.collection === false);
dialogData.showInMenuReader = !(action.showInMenu?.reader === false);
dialogData.showInMenuReaderAnnotation = !(
action.showInMenu?.readerAnnotation === false
Expand Down Expand Up @@ -259,6 +260,26 @@ async function editAction(currentKey?: string) {
width: "fit-content",
},
},
{
tag: "label",
namespace: "html",
properties: {
textContent: getString("prefs-action-showInMenuCollection"),
},
},
{
tag: "input",
properties: {
type: "checkbox",
},
attributes: {
"data-bind": "showInMenuCollection",
"data-prop": "checked",
},
styles: {
width: "fit-content",
},
},
{
tag: "label",
namespace: "html",
Expand Down Expand Up @@ -358,6 +379,7 @@ async function editAction(currentKey?: string) {
name: dialogData.name,
showInMenu: {
item: dialogData.showInMenuItem,
collection: dialogData.showInMenuCollection,
reader: dialogData.showInMenuReader,
readerAnnotation: dialogData.showInMenuReaderAnnotation,
},
Expand All @@ -376,6 +398,7 @@ async function editAction(currentKey?: string) {
break;
}
closeWindow(addon.data.prefs.editorWindow!);
addon.data.prefs.window?.focus();
return edited;
}

Expand Down Expand Up @@ -410,6 +433,7 @@ async function openEditorWindow(content: string) {
});
editor.setValue(content);
await unloadLock.promise;
addon.data.prefs.dialogWindow?.focus();
return modifiedContent;
}

Expand Down
109 changes: 64 additions & 45 deletions src/modules/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { config } from "../../package.json";
import { getString } from "../utils/locale";
import { getPref } from "../utils/prefs";
import { ActionData, ActionShowInMenu } from "../utils/actions";
import { getCurrentItems } from "../utils/items";
import { getCurrentItems, getItemsByKey } from "../utils/items";

export {
initItemMenu,
Expand All @@ -28,6 +28,21 @@ function initItemMenu(win: Window) {
],
});

ztoolkit.Menu.register("collection", {
tag: "menu",
popupId: `${config.addonRef}-collection-popup`,
label: getString("menupopup-label"),
icon: `chrome://${config.addonRef}/content/icons/favicon.png`,
onpopupshowing: `Zotero.${config.addonInstance}.hooks.onMenuEvent("showing", { window, target: "collection" })`,
children: [
{
tag: "menuitem",
label: getString("menupopup-placeholder"),
disabled: true,
},
],
});

ztoolkit.UI.appendElement(
{
tag: "menupopup",
Expand All @@ -41,7 +56,7 @@ function initItemMenu(win: Window) {
},
],
},
win.document.querySelector("popupset")!,
win.document.querySelector("popupset")!
);
}

Expand Down Expand Up @@ -109,15 +124,15 @@ function initReaderMenu() {
classList: ["dropmarker"],
},
],
}),
})
);
append(
ztoolkit.UI.createElement(doc, "style", {
id: `${config.addonRef}-reader-button`,
properties: {
textContent: readerButtonCSS,
},
}),
})
);
});
}
Expand All @@ -132,25 +147,23 @@ function initReaderAnnotationMenu() {
append({
label: action.menu!,
onCommand: () => {
triggerMenuCommand(
action.key,
reader._item.libraryID,
...params.ids,
triggerMenuCommand(action.key, () =>
getItemsByKey(reader._item.libraryID, ...params.ids)
);
},
});
}
},
}
);
}

function buildItemMenu(win: Window, target: "item" | "reader") {
function buildItemMenu(win: Window, target: "item" | "collection" | "reader") {
const doc = win.document;
const popup = doc.querySelector(
`#${config.addonRef}-${target}-popup`,
`#${config.addonRef}-${target}-popup`
) as XUL.MenuPopup;
// Remove all children in popup
while (popup.firstChild) {
while (popup?.firstChild) {
popup.removeChild(popup.firstChild);
}
// Add new children
Expand All @@ -161,34 +174,38 @@ function buildItemMenu(win: Window, target: "item" | "reader") {
tag: "menuitem",
properties: {
label: getString("menupopup-placeholder"),
},
attributes: {
disabled: true,
},
};
} else {
ztoolkit.UI.appendElement(
{
tag: "fragment",
children: enabledActions.map((action) => {
return {
tag: "menuitem",
properties: {
label:
action.menu + (action.shortcut ? ` (${action.shortcut})` : ""),
},
listeners: [
{
type: "command",
listener: (event) => {
triggerMenuCommand(action.key);
},
elemProp = {
tag: "fragment",
children: enabledActions.map((action) => {
return {
tag: "menuitem",
properties: {
label:
action.menu + (action.shortcut ? ` (${action.shortcut})` : ""),
},
listeners: [
{
type: "command",
listener: (event) => {
triggerMenuCommand(
action.key,
() => getCurrentItems(target),
target === "collection"
);
},
],
};
}),
},
popup,
);
},
],
};
}),
};
}
ztoolkit.UI.appendElement(elemProp, popup);
}

function getActionsByMenu(target: ActionShowInMenu) {
Expand All @@ -200,7 +217,7 @@ function getActionsByMenu(target: ActionShowInMenu) {
action &&
action.menu &&
action.enabled &&
(!action.showInMenu || action.showInMenu[target] !== false),
(!action.showInMenu || action.showInMenu[target] !== false)
)
.sort((x, y) => {
if (!x && !y) {
Expand All @@ -214,32 +231,34 @@ function getActionsByMenu(target: ActionShowInMenu) {
}
return ((x[sortBy] as string) || "").localeCompare(
(y[sortBy] || "") as string,
Zotero.locale,
Zotero.locale
);
});
}

async function triggerMenuCommand(
key: string,
libraryID?: number,
...itemKeys: string[]
getItems: () =>
| Zotero.DataObject[]
| Promise<Zotero.DataObject[]> = getCurrentItems,
withCollection: boolean = false
) {
let items: Zotero.Item[];
if (libraryID && itemKeys) {
items = itemKeys
.map((key) => Zotero.Items.getByLibraryAndKey(libraryID, key))
.filter((item) => item) as Zotero.Item[];
} else {
items = getCurrentItems();
const items = await getItems();
let collection: Zotero.Collection | undefined = undefined;
if (withCollection) {
collection = Zotero.getActiveZoteroPane().getSelectedCollection();
}

// Trigger action for all items
await addon.api.actionManager.dispatchActionByKey(key, {
itemIDs: items.map((item) => item.id),
collectionID: collection?.id,
});
// Trigger action for each item
for (const item of items) {
await addon.api.actionManager.dispatchActionByKey(key, {
itemID: item.id,
collectionID: collection?.id,
});
}
}
28 changes: 18 additions & 10 deletions src/utils/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ enum ActionOperationTypes {
"triggerAction",
}

type ActionShowInMenu = "item" | "reader" | "readerAnnotation";
type ActionShowInMenu = "item" | "collection" | "reader" | "readerAnnotation";

interface ActionData<T extends ActionOperationTypes = ActionOperationTypes> {
event: ActionEventTypes;
Expand Down Expand Up @@ -94,6 +94,7 @@ const emptyAction: ActionData = {
name: "",
showInMenu: {
item: false,
collection: false,
reader: false,
readerAnnotation: false,
},
Expand All @@ -103,14 +104,16 @@ type ActionMap = Map<string, ActionData>;

type ActionArgs = {
itemID?: number;
itemIDs?: number[];
collectionID?: number;
[key: string]: any;
};

function initActions() {
addon.data.actions.map = new ztoolkit.LargePref(
`${config.prefsPrefix}.rules`,
`${config.prefsPrefix}.rules.`,
"parser",
"parser"
).asMapLike() as ActionMap;
if (!getPref("rulesInit")) {
for (const key of defaultActions.keys()) {
Expand Down Expand Up @@ -158,7 +161,7 @@ function initActions() {

function updateCachedActionKeys() {
addon.data.actions.cachedKeys = Array.from(
addon.data.actions.map.keys(),
addon.data.actions.map.keys()
).sort((a, b) => {
const actionA = addon.data.actions.map.get(a);
const actionB = addon.data.actions.map.get(b);
Expand All @@ -169,13 +172,13 @@ function updateCachedActionKeys() {
actionA[
addon.data.prefs.columns[addon.data.prefs.columnIndex]
.dataKey as keyof ActionData
] || "",
] || ""
);
const valueB = String(
actionB[
addon.data.prefs.columns[addon.data.prefs.columnIndex]
.dataKey as keyof ActionData
] || "",
] || ""
);

return addon.data.prefs.columnAscending
Expand Down Expand Up @@ -231,7 +234,7 @@ async function applyAction(action: ActionData, args: ActionArgs) {
}
}
message = `Toggle tag ${tags.join(",")} to item ${item?.getField(
"title",
"title"
)}`;
break;
}
Expand All @@ -240,8 +243,13 @@ async function applyAction(action: ActionData, args: ActionArgs) {
const _require = (module: string) => ztoolkit.getGlobal(module);
const items = Zotero.Items.get(args.itemIDs || []) || null;

let paramList: any[] = [item, items, _require];
let paramSign = "item, items, require";
let collection: Zotero.Collection | false = false;
if (args.collectionID) {
collection = Zotero.Collections.get(args.collectionID) as Zotero.Collection | false;
}

let paramList: any[] = [item, items, collection, _require];
let paramSign = "item, items, collection, require";
switch (action.event) {
case ActionEventTypes.mainWindowLoad:
case ActionEventTypes.mainWindowUnload:
Expand Down Expand Up @@ -278,7 +286,7 @@ async function applyAction(action: ActionData, args: ActionArgs) {
const actions = getActions();
// Find the action by name
const nextAction = Object.values(actions).find(
(_action) => _action.name === action.data,
(_action) => _action.name === action.data
);
if (nextAction) {
await applyAction(nextAction, args);
Expand All @@ -299,7 +307,7 @@ async function applyAction(action: ActionData, args: ActionArgs) {
function getActions(): Record<string, ActionData>;
function getActions(key: string): ActionData | undefined;
function getActions(
key?: string,
key?: string
): Record<string, ActionData> | ActionData | undefined {
if (!key) {
const map = addon.data.actions.map;
Expand Down
Loading

0 comments on commit 3b11a12

Please sign in to comment.