diff --git a/addon/chrome/content/dist/index.html b/addon/chrome/content/dist/index.html index e958be2..2f33519 100644 --- a/addon/chrome/content/dist/index.html +++ b/addon/chrome/content/dist/index.html @@ -1,5 +1,5 @@ - + diff --git a/package.json b/package.json index 9ca0cd5..c716830 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zotero-style", - "version": "2.4.8", + "version": "2.5.0", "description": "让你的Zotero看起来更有趣", "config": { "addonName": "Zotero Style", diff --git a/src/modules/graphView.ts b/src/modules/graphView.ts index 5508aa0..af75b6b 100644 --- a/src/modules/graphView.ts +++ b/src/modules/graphView.ts @@ -45,6 +45,7 @@ export default class GraphView { theme = "light" } } + Zotero.Prefs.set(`${config.addonRef}.graphView.theme`, theme) const fillTag = 7583672 const themeColor = { light: { @@ -150,6 +151,7 @@ export default class GraphView { } this.renderer.colors = themeColor[theme].colors this.renderer.testCSS(); + this.container.style.backgroundColor = themeColor[theme].backgroundColor; this.resizer.style.backgroundColor = themeColor[theme].resizerColor; this.renderer.containerEl.style.backgroundColor = themeColor[theme].backgroundColor; @@ -375,7 +377,8 @@ export default class GraphView { width: "100%", minHeight: `${minHeight}px`, height: Zotero.Prefs.get(`${config.addonRef}.graphView.height`) as string, - display: Zotero.Prefs.get(`${config.addonRef}.graphView.enable`) ? "" : "none" + display: Zotero.Prefs.get(`${config.addonRef}.graphView.enable`) ? "" : "none", + backgroundColor: "transparent" } }) // 选项 @@ -468,18 +471,17 @@ export default class GraphView { frame.style.width = "100%" frame.style.height = "100%" frame.style.overflow = "hidden" - frame.style.backgroundColor = "#ffffff" + frame.style.backgroundColor = "transparent" container.append(frame) mainNode.append(container) this.container = container - await this.initIFrame(frame) // 调节高度 const resizer = this.resizer = ztoolkit.UI.createElement(document, "div", { styles: { height: `1px`, width: "100%", - backgroundColor: "#cecece", + backgroundColor: "transparent", cursor: "ns-resize", }, }) @@ -516,6 +518,7 @@ export default class GraphView { document.removeEventListener('mouseup', mouseUpHandler); }; resizer.addEventListener('mousedown', mouseDownHandler); + await this.initIFrame(frame) this.setTheme() } diff --git a/src/modules/tags.ts b/src/modules/tags.ts index 745c91c..f22074b 100644 --- a/src/modules/tags.ts +++ b/src/modules/tags.ts @@ -29,6 +29,7 @@ export class Tags { "Frequency (9-0)", ] } + private searchText?: string; private plainTags: string[] = []; private nestedTags!: NestedTags["children"]; /** @@ -107,6 +108,15 @@ export class Tags { #zotero-tag-selector .tag-selector-list { height: auto !important; } + .nested-search-box .icon { + display: flex; + justify-content: center; + align-items: center; + opacity: 0.8; + } + .nested-search-box .icon:hover { + opacity: 1 + } ` }, }); @@ -156,6 +166,17 @@ export class Tags { } public async getPlainTags(): Promise { + let func: Function | undefined + if (this.searchText && this.searchText.trim().length) { + let regex: RegExp; + const res = this.searchText.match(/\/(.+)\/(\w*)/) + if (res) { + regex = new RegExp(res[1], res[2]) + func = (s: string) => regex.test(s) + } else { + func = (s: string) => s.indexOf(this.searchText!) != -1 + } + } let plainTags: string[] = []; ( Zotero.Prefs.get("tagSelector.displayAllTags") @@ -173,6 +194,11 @@ export class Tags { .filter((tag: string) => { return Tags.getTagMatch(tag) }) + if (func) { + plainTags = plainTags.filter((tag: string) => { + return func!(tag) + }) + } return plainTags } @@ -256,7 +282,9 @@ export class Tags { flex: "1 1 auto", display: "flex", width: `${ZoteroPane.tagSelector.getContainerDimensions().width}px`, - justifyContent: "space-between" + flexDirection: "column", + justifyContent: "space-between", + alignItems: "center" } }, this.container) as HTMLDivElement // 左侧边到条目面板中间的splitter @@ -266,17 +294,126 @@ export class Tags { styles: { width: "calc(100% - 10px)", padding: "5px", - height: "auto", + height: "100%", overflowX: "", overflowY: "auto" } }, this.nestedTagsContainer) as HTMLDivElement; + // 搜索框 + const searchBoxHeight = 15 + const searchBox = ztoolkit.UI.appendElement({ + tag: "div", + classList: ["nested-search-box"], + styles: { + width: "calc(100% - 35px)", + height: `${searchBoxHeight}px`, + padding: "5px", + borderRadius: "5px", + border: "1px solid #e0e0e0", + display: "flex", + flexDirection: "row", + alignItems: "center", + marginBottom: "3px", + marginTop: "3px", + opacity: "0.6" + }, + children: [ + { + tag: "div", + styles: { + width: `${searchBoxHeight}px`, + height: `${searchBoxHeight}px`, + display: "flex", + justifyContent: "center", + alignItems: "center", + }, + properties: { + innerHTML: `` + } + }, + { + tag: "input", + id: "nested-tags-search-input", + styles: { + outline: "none", + border: "none", + width: "100%", + margin: "0 5px" + }, + properties: { + value: this.searchText + }, + listeners: [ + { + type: "focus", + listener: () => { + searchBox.style.opacity = "1" + } + }, + { + type: "blur", + listener: () => { + searchBox.style.opacity = "0.6" + } + }, + { + type: "keyup", + listener: async () => { + const inputNode = searchBox.querySelector("input") as HTMLInputElement + const clearNode = searchBox.querySelector(".clear") as HTMLInputElement + const searchText = inputNode.value as string + if (searchText.length) { + clearNode.style.display = "" + } + // 搜索 + console.log("search...", searchText) + this.searchText = searchText + // 复制一份 + this.plainTags = await this.getPlainTags() + this.nestedTags = await this.getNestedTags() + box.innerHTML = "" + await this.render(box, this.nestedTags) + } + } + ] + }, + { + tag: "div", + classList: ["icon", "clear"], + styles: { + width: `${searchBoxHeight}px`, + height: `${searchBoxHeight}px`, + display: "none" + }, + properties: { + innerHTML: `` + }, + listeners: [ + { + type: "click", + listener: async () => { + const inputNode = searchBox.querySelector("input") as HTMLInputElement + const clearNode = searchBox.querySelector(".clear") as HTMLInputElement + inputNode.value = "" + clearNode.style.display = "none" + this.searchText = "" + // 复制一份 + this.plainTags = await this.getPlainTags() + this.nestedTags = await this.getNestedTags() + box.innerHTML = "" + await this.render(box, this.nestedTags) + } + } + ] + }, + ] + }, this.nestedTagsContainer) as HTMLDivElement; + // 这是Zotero原本标签视图的父节点,在Zotero中这么命名 const tagSelector = this.container.querySelector(".tag-selector")! as HTMLDivElement this.render(box, this.nestedTags) let icons = { sort: ``, - // sort: ``, nest: ``, collapse: { true: ``, diff --git a/src/modules/views.ts b/src/modules/views.ts index 9888b08..d6a373d 100644 --- a/src/modules/views.ts +++ b/src/modules/views.ts @@ -109,6 +109,7 @@ export default class Views { @keyframes rotate{from{transform: rotate(0deg)} to{transform: rotate(359deg)} } + ` }, }); diff --git a/update.json b/update.json index a14937e..e4d1f9b 100644 --- a/update.json +++ b/update.json @@ -3,7 +3,7 @@ "zoterostyle@polygon.org": { "updates": [ { - "version": "2.4.8", + "version": "2.5.0", "update_link": "https://github.com/muisedestiny/zotero-style/releases/latest/download/zotero-style.xpi", "applications": { "gecko": { @@ -12,7 +12,7 @@ } }, { - "version": "2.4.8", + "version": "2.5.0", "update_link": "https://github.com/muisedestiny/zotero-style/releases/latest/download/zotero-style.xpi", "applications": { "zotero": { diff --git a/update.rdf b/update.rdf index bc98edf..0685aa8 100644 --- a/update.rdf +++ b/update.rdf @@ -5,7 +5,7 @@ - 2.4.8 + 2.5.0 zotero@chnm.gmu.edu