add: outline buttons

This commit is contained in:
xiangyu 2022-05-03 00:55:10 +08:00
parent 71404137ec
commit 6bc782e3ce
5 changed files with 207 additions and 33 deletions

View File

@ -37,7 +37,7 @@
<div class="drive-header dx-treeview-item">
<div class="dx-treeview-item-content">
<i class="dx-icon dx-icon-hierarchy"></i>
<span>Note Outline</span>
<span>Knowledge Outline</span>
</div>
</div>
<div id="treeview"></div>
@ -45,6 +45,11 @@
</div>
</div>
</html:div>
<html:div id="outline-tools" flex="1" height="50" maxheight="50" minheight="50" style="display: flex; flex-flex-direction: row; justify-content: space-between; margin: 0px 50px 0px 50px;">
<div id="outline-addafter"></div>
<div id="outline-tab"></div>
<div id="outline-untab"></div>
</html:div>
</vbox>
<splitter id="outline-splitter" collapse="before">
<grippy></grippy>

View File

@ -18,7 +18,7 @@
}
.drive-panel {
padding: 20px 15px;
padding: 20px 0px 20px 30px;
font-size: 115%;
font-weight: bold;
border-right: 1px solid rgba(165, 165, 165, 0.4);

View File

@ -163,7 +163,7 @@ class AddonEvents extends AddonBase {
const title = _window.document.getElementById("knowledge-addlink");
this._Addon.views.changeEditorButtonView(
title,
"mainTitle",
"mainHeading",
"This is a Main Knowledge",
"empty"
);
@ -187,6 +187,7 @@ class AddonEvents extends AddonBase {
Zotero.debug("Knowledge4Zotero: addToKnowledge");
this._Addon.knowledge.addLinkToNote(
undefined,
// -1 for automatically insert to current selected line or end of note
-1,
message.content.editorInstance._item.id
);
@ -238,7 +239,24 @@ class AddonEvents extends AddonBase {
}
}
}
} else if (message.type === "moveOutlineTitle") {
} else if (message.type === "clickOutlineHeading") {
/*
message.content = {
event: {itemData}
}
*/
let editorInstance =
await this._Addon.knowledge.getWorkspaceEditorInstance();
// Set node id
this._Addon.knowledge.currentNodeID = parseInt(
(message.content.event as any).itemData.id
);
this._Addon.views.scrollToLine(
editorInstance,
// Scroll to 6 lines before the inserted line
(message.content.event as any).itemData.lineIndex - 5
);
} else if (message.type === "moveOutlineHeading") {
/*
message.content = {
params: {

View File

@ -4,11 +4,12 @@ const TreeModel = require("./treemodel");
class Knowledge extends AddonBase {
currentLine: number;
currentVersion: number;
currentNodeID: number;
workspaceWindow: Window;
constructor(parent: Knowledge4Zotero) {
super(parent);
this.currentLine = 0;
this.currentLine = -1;
this.currentNodeID = -1;
}
getWorkspaceNote() {
@ -35,7 +36,13 @@ class Knowledge extends AddonBase {
);
this.workspaceWindow = win;
await this.waitWorkspaceReady();
// @ts-ignore
win.addEventListener("resize", (e) => {
// @ts-ignore
this._Addon.views.setTreeViewHeight();
});
this.setWorkspaceNote("main");
this.currentLine = -1;
this._Addon.views.buildOutline();
}
}
@ -87,6 +94,9 @@ class Knowledge extends AddonBase {
_window.document
.getElementById("preview-splitter")
.setAttribute("state", "open");
} else {
// Set line to default
this.currentLine = -1;
}
await this.waitWorkspaceReady();
let noteEditor: any = await this.getWorkspaceEditor(type);
@ -175,30 +185,50 @@ class Knowledge extends AddonBase {
this.setLinesToNote(note, noteLines);
}
addSubLineToNote(note: ZoteroItem, text: string, lineIndex: number = -1) {
async addSubLineToNote(
note: ZoteroItem,
text: string,
lineIndex: number = -1
) {
if (lineIndex < 0) {
lineIndex = this.currentLine;
lineIndex =
this.currentLine >= 0
? this.currentLine + 1
: this.getLinesInNote(note).length + 1;
}
let parentNode = this.getLineParentInNote(note, lineIndex);
if (!parentNode) {
this.addLineToNote(note, text, lineIndex);
return;
}
let nodes = this.getNoteTreeAsList(note);
let i = 0;
for (let node of nodes) {
if (node.model.lineIndex === parentNode.model.lineIndex) {
break;
}
i++;
}
// Get next header line index
i++;
if (i >= nodes.length) {
i = nodes.length - 1;
}
// Add line before next header, which is also the end of current parent header
this.addLineToNote(note, text, nodes[i].model.lineIndex);
// let parentNode = this.getLineParentInNote(note, lineIndex);
// if (!parentNode) {
// this.addLineToNote(note, text, lineIndex);
// return;
// }
// let nodes = this.getNoteTreeAsList(note);
// let i = 0;
// for (let node of nodes) {
// if (node.model.lineIndex === parentNode.model.lineIndex) {
// break;
// }
// i++;
// }
// // Get next header line index
// i++;
// if (i >= nodes.length) {
// i = nodes.length - 1;
// }
// Add to next line
this.addLineToNote(note, text, lineIndex);
await Zotero.Promise.delay(500);
let editorInstance = await this.getWorkspaceEditorInstance();
this._Addon.views.scrollToLine(
editorInstance,
// Scroll to 6 lines before the inserted line
lineIndex - 5
);
this._Addon.events.onEditorEvent(
new EditorMessage("enterWorkspace", {
editorInstance: editorInstance,
params: "main",
})
);
}
addLinkToNote(
@ -234,6 +264,50 @@ class Knowledge extends AddonBase {
);
}
modifyLineInNote(note: ZoteroItem, text: string, lineIndex: number) {
note = note || this.getWorkspaceNote();
if (!note) {
return;
}
let noteLines = this.getLinesInNote(note);
if (lineIndex < 0 || lineIndex >= noteLines.length) {
return;
}
noteLines[lineIndex] = text;
this.setLinesToNote(note, noteLines);
}
changeHeadingLineInNote(
note: ZoteroItem,
rankChange: number,
lineIndex: number
) {
note = note || this.getWorkspaceNote();
if (!note) {
return;
}
const noteLines = this.getLinesInNote(note);
if (lineIndex < 0 || lineIndex >= noteLines.length) {
return;
}
const headerStartReg = new RegExp("<h[1-6]>");
const headerStopReg = new RegExp("</h[1-6]>");
let headerStart = noteLines[lineIndex].search(headerStartReg);
if (headerStart === -1) {
return;
}
let lineRank = parseInt(noteLines[lineIndex][headerStart + 2]) + rankChange;
if (lineRank > 6) {
lineRank = 6;
} else if (lineRank < 1) {
lineRank = 1;
}
noteLines[lineIndex] = noteLines[lineIndex]
.replace(headerStartReg, `<h${lineRank}>`)
.replace(headerStopReg, `</h${lineRank}>`);
this.setLinesToNote(note, noteLines);
}
moveHeaderLineInNote(
note: ZoteroItem,
currentNode: TreeModel.Node<object>,

View File

@ -13,7 +13,7 @@ class AddonViews extends AddonBase {
default: "chrome://Knowledge4Zotero/skin/favicon.png",
};
this.editorIcon = {
mainTitle: "Main Knowledge",
mainHeading: "Main Knowledge",
addToKnowledge: `<svg t="1651124422933" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3269" width="24" height="24"><path d="M896.00324 352c70.7 0 128-57.3 128-128 0-70.6-57.4-128-128-128-70.7 0-128 57.3-128 128 0 18.8 4.1 36.7 11.3 52.8 2.7 6 1.4 13.1-3.3 17.8l-24.2 24.2c-5.7 5.7-14.9 6.3-21.2 1.2-38.1-30.1-86.3-48-138.6-48-18.8 0-37.1 2.3-54.6 6.7-6.9 1.7-14.1-1.4-17.7-7.5l-6.6-11.4c-3.4-5.8-2.7-13.1 1.6-18.3 18.6-22.6 29.7-51.6 29.3-83.2C543.10324 89 486.30324 32.6 417.00324 32c-70.6-0.6-128.1 56.1-129 126.3-0.9 69.5 56.5 128.6 126 129.6 9.4 0.1 18.5-0.7 27.4-2.5 6.8-1.4 13.6 1.7 17.1 7.7l2.2 3.8c4 7 2.2 15.9-4.2 20.7-42.4 32.3-73 79.4-84 133.6-1.5 7.4-8.1 12.7-15.7 12.7h-94.1c-6.6 0-12.6-4-14.9-10.2-18.1-48-64.3-82.2-118.5-82.8C58.70324 370.3 0.50324 427.6 0.00324 498.1-0.49676 569.2 57.00324 627 128.00324 627c56.7 0 104.8-36.9 121.6-87.9 2.2-6.6 8.3-11.1 15.2-11.1h92c7.6 0 14.2 5.4 15.7 12.9 9.5 46.7 33.5 88 67 119.2 5.4 5 6.6 13.2 2.9 19.6l-21.7 37.6c-3.7 6.3-11.1 9.4-18.2 7.4-11.1-3.1-22.7-4.7-34.8-4.7-69.7 0.1-127 56.8-127.8 126.6-0.8 71.7 57.4 130 129.1 129.4 69.5-0.6 126.3-57.3 126.9-126.8 0.3-28-8.5-53.9-23.5-75.1-3.6-5.1-3.9-11.8-0.8-17.2l24.9-43.1c3.9-6.7 12-9.7 19.3-7 23.7 8.6 49.3 13.2 76 13.2 34.9 0 67.9-8 97.3-22.2 7.6-3.7 16.7-0.9 20.9 6.4l37 64c-26.3 23.5-43 57.7-43 95.8 0 70.9 58 128.5 128.9 128 69.7-0.5 126.2-56.7 127.1-126.3 0.9-70.1-57-129.3-127.1-129.7-6.2 0-12.3 0.4-18.3 1.2-6.5 0.9-12.8-2.2-16.1-7.8l-39.2-67.9c-3.4-5.9-2.7-13.3 1.7-18.4 34.2-39.3 54.9-90.7 54.9-147 0-38.9-9.9-75.5-27.4-107.4-3.4-6.2-2.2-13.9 2.8-18.9l28.4-28.4c4.9-4.9 12.4-6 18.7-2.9 17.4 8.6 36.9 13.5 57.6 13.5z m0-192c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zM128.00324 563c-35.3 0-64-28.7-64-64s28.7-64 64-64 64 28.7 64 64-28.7 64-64 64z m240 349c-35.3 0-64-28.7-64-64s28.7-64 64-64 64 28.7 64 64-28.7 64-64 64z m464-112c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zM416.00324 224c-35.3 0-64-28.7-64-64s28.7-64 64-64 64 28.7 64 64-28.7 64-64 64z m289.1 385.1C674.90324 639.4 634.70324 656 592.00324 656s-82.9-16.6-113.1-46.9C448.60324 578.9 432.00324 538.7 432.00324 496s16.6-82.9 46.9-113.1C509.10324 352.6 549.30324 336 592.00324 336s82.9 16.6 113.1 46.9C735.40324 413.1 752.00324 453.3 752.00324 496s-16.6 82.9-46.9 113.1z" p-id="3270"></path></svg>`,
notMainKnowledge: `<svg t="1651124314636" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1689" width="24" height="24"><path d="M877.44 383.786667L624.426667 117.333333C594.986667 86.186667 554.88 69.12 512 69.12s-82.986667 17.066667-112.426667 48.213333L146.56 383.786667a148.266667 148.266667 0 0 0-40.746667 102.4v302.08c0 85.76 69.76 155.52 155.52 155.52h501.546667c85.76 0 155.52-69.76 155.52-155.52V485.973333c0-38.186667-14.506667-74.453333-40.96-102.186666z m-44.373333 404.266666c0 38.826667-31.573333 70.186667-70.186667 70.186667H261.333333c-38.826667 0-70.186667-31.573333-70.186666-70.186667V485.973333c0-16.213333 6.186667-31.786667 17.28-43.52L461.44 176c13.226667-13.866667 31.146667-21.546667 50.56-21.546667s37.333333 7.68 50.56 21.76l253.013333 266.453334c11.306667 11.733333 17.28 27.306667 17.28 43.52v301.866666z" p-id="1690"></path><path d="M608 687.786667h-192c-23.466667 0-42.666667 19.2-42.666667 42.666666s19.2 42.666667 42.666667 42.666667h192c23.466667 0 42.666667-19.2 42.666667-42.666667s-19.2-42.666667-42.666667-42.666666z" p-id="1691"></path></svg>`,
isMainKnowledge: `<svg t="1651124352868" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1850" width="24" height="24"><path d="M877.44 388.053333L624.426667 121.813333C594.986667 90.666667 554.88 73.386667 512 73.386667s-82.986667 17.066667-112.426667 48.213333L146.56 388.053333a148.266667 148.266667 0 0 0-40.746667 102.4v302.08c0 85.76 69.76 155.52 155.52 155.52h501.546667c85.76 0 155.52-69.76 155.52-155.52V490.453333c0-38.4-14.506667-74.666667-40.96-102.4zM608 777.386667h-192c-23.466667 0-42.666667-19.2-42.666667-42.666667s19.2-42.666667 42.666667-42.666667h192c23.466667 0 42.666667 19.2 42.666667 42.666667s-19.2 42.666667-42.666667 42.666667z" p-id="1851"></path></svg>`,
@ -114,6 +114,8 @@ class AddonViews extends AddonBase {
let editor = this.getEditor(instance._iframeWindow.document);
if (lineIndex > editor.children.length) {
lineIndex = editor.children.length - 1;
} else if (lineIndex < 0) {
lineIndex = 0;
}
// @ts-ignore
editor.parentNode.scrollTo(0, editor.children[lineIndex].offsetTop);
@ -165,21 +167,22 @@ class AddonViews extends AddonBase {
}
async buildOutline(note: ZoteroItem) {
this._Addon.knowledge.currentNodeID = -1;
let treeList = this._Addon.knowledge.getNoteTreeAsList(note);
const treeData = [];
treeList.map((node: TreeModel.Node<object>) => {
treeData.push({
id: String(node.model.id),
name: node.model.name,
rank: node.model.rank,
lineIndex: node.model.lineIndex,
endIndex: node.model.endIndex,
isDirectory: node.hasChildren(),
expanded: true,
parentId:
node.model.rank > 1 ? String(node.parent.model.id) : undefined,
});
});
Zotero.debug(treeList);
Zotero.debug(treeData);
this.$(() => {
this.createTreeView("#treeview", treeData);
this.createSortable("#treeview", "treeData");
@ -193,8 +196,82 @@ class AddonViews extends AddonBase {
expandNodesRecursive: false,
dataStructure: "plain",
width: 220,
height: this.$("window").height() - 130,
displayExpr: "name",
noDataText: "No Heading 1 found",
onItemClick: (e) => {
this._Addon.events.onEditorEvent(
new EditorMessage("clickOutlineHeading", {
event: e,
})
);
},
onItemSelectionChanged: (e) => {
console.log(e);
},
});
this.$("#outline-addafter").dxButton({
icon: "plus",
hint: "Add Heading after the selected Heading's section",
onClick: (e) => {
if (this._Addon.knowledge.currentNodeID < 0) {
return;
}
const text = prompt("Enter new Heading:");
this._Addon.knowledge.openWorkspaceWindow();
if (text.trim()) {
let node = this._Addon.knowledge.getNoteTreeNodeById(
undefined,
this._Addon.knowledge.currentNodeID
);
this._Addon.knowledge.addSubLineToNote(
undefined,
`<h${node.model.rank}>${text}</h${node.model.rank}>`,
node.model.endIndex
);
}
},
});
this.$("#outline-tab").dxButton({
icon: "increaseindent",
hint: "Raise the selected Heading level",
onClick: (e) => {
if (this._Addon.knowledge.currentNodeID < 0) {
return;
}
let node = this._Addon.knowledge.getNoteTreeNodeById(
undefined,
this._Addon.knowledge.currentNodeID
);
this._Addon.knowledge.changeHeadingLineInNote(
undefined,
1,
node.model.lineIndex
);
},
});
this.$("#outline-untab").dxButton({
icon: "decreaseindent",
hint: "Decrease the selected Heading level",
onClick: (e) => {
if (this._Addon.knowledge.currentNodeID < 0) {
return;
}
let node = this._Addon.knowledge.getNoteTreeNodeById(
undefined,
this._Addon.knowledge.currentNodeID
);
this._Addon.knowledge.changeHeadingLineInNote(
undefined,
-1,
node.model.lineIndex
);
},
});
}
setTreeViewHeight() {
this.$("#treeview").css("height", `${this.$("window").height() - 130}px`);
}
createSortable(selector, driveName) {
@ -298,7 +375,7 @@ class AddonViews extends AddonBase {
: this.findIndex(toItems, toNode.itemData.id);
this._Addon.events.onEditorEvent(
new EditorMessage("moveOutlineTitle", {
new EditorMessage("moveOutlineHeading", {
params: {
fromID: parseInt(fromNode.itemData.id),
toID: toNode