diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json
index 2775bb8a6..41c82d39b 100644
--- a/app/appearance/langs/zh_CN.json
+++ b/app/appearance/langs/zh_CN.json
@@ -730,7 +730,7 @@
"insertImgURL": "插入图片链接",
"insertIframeURL": "插入 IFrame 链接",
"context": "上下文",
- "dockTip": "\n单击 展开/最小化\n右键 调整位置",
+ "dockTip": "\n单击 展开/最小化\n右键/拖拽 调整位置",
"shadow": "投影",
"hollow": "镂空",
"attrValue1": "属性值留空则会自动删除该属性",
diff --git a/app/src/boot/globalEvent/click.ts b/app/src/boot/globalEvent/click.ts
index 46d2cd455..2c7cf0e3f 100644
--- a/app/src/boot/globalEvent/click.ts
+++ b/app/src/boot/globalEvent/click.ts
@@ -15,7 +15,6 @@ export const globalClick = (event: MouseEvent & { target: HTMLElement }) => {
if (ghostElement.dataset.ghostType === "dock") {
ghostElement.parentElement.querySelectorAll(".dock__item").forEach((item: HTMLElement) => {
item.style.opacity = "";
- item.classList.add("b3-tooltips");
});
document.querySelector("#dockMoveItem")?.remove();
} else {
diff --git a/app/src/layout/dock/index.ts b/app/src/layout/dock/index.ts
index 43a4db214..174f04e2f 100644
--- a/app/src/layout/dock/index.ts
+++ b/app/src/layout/dock/index.ts
@@ -87,7 +87,7 @@ export class Dock {
}
}
if (!showDock) {
- this.element.firstElementChild.innerHTML = `
+ this.element.firstElementChild.innerHTML = `
`;
this.element.classList.add("fn__none");
@@ -157,7 +157,6 @@ export class Dock {
moveEvent.stopPropagation();
if (!ghostElement) {
item.style.opacity = "0.38";
- item.classList.remove("b3-tooltips");
ghostElement = item.cloneNode(true) as HTMLElement;
ghostElement.setAttribute("data-ghost-type", "dock");
this.element.append(ghostElement);
@@ -281,11 +280,10 @@ export class Dock {
documentSelf.onselectstart = null;
documentSelf.onselect = null;
ghostElement?.remove();
- if (item.classList.contains("b3-tooltips")) {
+ if (item.style.opacity !== "0.38") {
return;
}
item.style.opacity = "";
- item.classList.add("b3-tooltips");
if (!moveItem.classList.contains("fn__none")) {
let dock;
if (moveItem.parentElement.parentElement.id === "dockBottom") {
@@ -773,8 +771,6 @@ export class Dock {
delete sourceDock.data[type];
// 目标处理
- sourceElement.classList.remove("b3-tooltips__n", "b3-tooltips__ne", "b3-tooltips__nw", "b3-tooltips__s", "b3-tooltips__se", "b3-tooltips__sw", "b3-tooltips__e", "b3-tooltips__w");
- sourceElement.classList.add(`b3-tooltips__${this.getClassDirect(index)}`);
sourceElement.setAttribute("data-index", index.toString());
if (previousType) {
this.element.querySelector(`[data-type="${previousType}"]`).after(sourceElement);
@@ -804,23 +800,6 @@ export class Dock {
delete this.data[key];
}
- private getClassDirect(index: number) {
- let direct = "e";
- switch (this.position) {
- case "Right":
- direct = "w";
- break;
- case "Bottom":
- if (index === 0) {
- direct = "ne";
- } else {
- direct = "nw";
- }
- break;
- }
- return direct;
- }
-
public setSize() {
const activesElement = this.element.querySelectorAll(".dock__item--active");
activesElement.forEach((item) => {
@@ -860,7 +839,7 @@ export class Dock {
if (typeof tabIndex === "undefined" && !TYPES.includes(item.type)) {
return;
}
- html += `
+ html += `">
`;
this.data[item.type] = true;
@@ -873,7 +852,7 @@ export class Dock {
this.element.firstElementChild.lastElementChild.insertAdjacentHTML("beforebegin", html);
}
} else {
- this.element.firstElementChild.innerHTML = `${html}
+ this.element.firstElementChild.innerHTML = `${html}
`;
}
diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts
index 7f96d17c6..cbcecda2a 100644
--- a/app/src/protyle/gutter/index.ts
+++ b/app/src/protyle/gutter/index.ts
@@ -14,20 +14,19 @@ import {copyPlainText, isMac, isOnlyMeta, openByMobile, updateHotkeyTip, writeTe
import {
transaction,
turnsIntoOneTransaction,
- turnsIntoTransaction,
+ turnsIntoTransaction, turnsOneInto,
updateBatchTransaction,
updateTransaction
} from "../wysiwyg/transaction";
import {removeBlock} from "../wysiwyg/remove";
-import {focusBlock, focusByRange, focusByWbr, getEditorRange} from "../util/selection";
+import {focusBlock, focusByRange, getEditorRange} from "../util/selection";
import {hideElements} from "../ui/hideElements";
-import {processRender} from "../util/processCode";
import {highlightRender} from "../render/highlightRender";
import {blockRender} from "../render/blockRender";
import {removeEmbed} from "../wysiwyg/removeEmbed";
import {getContenteditableElement, getTopAloneElement, isNotEditBlock} from "../wysiwyg/getBlock";
import * as dayjs from "dayjs";
-import {fetchPost, fetchSyncPost} from "../../util/fetch";
+import {fetchPost} from "../../util/fetch";
import {
cancelSB,
genEmptyElement,
@@ -449,91 +448,8 @@ export class Gutter {
icon: options.icon,
label: options.label,
accelerator: options.accelerator,
- async click() {
- if (!options.nodeElement.querySelector("wbr")) {
- getContenteditableElement(options.nodeElement)?.insertAdjacentHTML("afterbegin", "");
- }
- if (options.type === "CancelList" || options.type === "CancelBlockquote") {
- for await(const item of options.nodeElement.querySelectorAll('[data-type="NodeHeading"][fold="1"]')) {
- const itemId = item.getAttribute("data-node-id");
- item.removeAttribute("fold");
- const response = await fetchSyncPost("/api/transactions", {
- session: options.protyle.id,
- app: Constants.SIYUAN_APPID,
- transactions: [{
- doOperations: [{
- action: "unfoldHeading",
- id: itemId,
- }],
- undoOperations: [{
- action: "foldHeading",
- id: itemId
- }],
- }]
- });
- options.protyle.undo.add([{
- action: "unfoldHeading",
- id: itemId,
- }], [{
- action: "foldHeading",
- id: itemId
- }], options.protyle);
- item.insertAdjacentHTML("afterend", response.data[0].doOperations[0].retData);
- }
- }
- const oldHTML = options.nodeElement.outerHTML;
- const previousId = options.nodeElement.previousElementSibling?.getAttribute("data-node-id");
- const parentId = options.nodeElement.parentElement.getAttribute("data-node-id") || options.protyle.block.parentID;
- // @ts-ignore
- const newHTML = options.protyle.lute[options.type](options.nodeElement.outerHTML, options.level);
- options.nodeElement.outerHTML = newHTML;
- if (options.type === "CancelList" || options.type === "CancelBlockquote") {
- const tempElement = document.createElement("template");
- tempElement.innerHTML = newHTML;
- const doOperations: IOperation[] = [{
- action: "delete",
- id: options.id
- }];
- const undoOperations: IOperation[] = [];
- let tempPreviousId = previousId;
- Array.from(tempElement.content.children).forEach((item) => {
- const tempId = item.getAttribute("data-node-id");
- doOperations.push({
- action: "insert",
- data: item.outerHTML,
- id: tempId,
- previousID: tempPreviousId,
- parentID: parentId
- });
- undoOperations.push({
- action: "delete",
- id: tempId
- });
- tempPreviousId = tempId;
- });
- undoOperations.push({
- action: "insert",
- data: oldHTML,
- id: options.id,
- previousID: previousId,
- parentID: parentId
- });
- transaction(options.protyle, doOperations, undoOperations);
- } else {
- updateTransaction(options.protyle, options.id, newHTML, oldHTML);
- }
- focusByWbr(options.protyle.wysiwyg.element, getEditorRange(options.protyle.wysiwyg.element));
- options.protyle.wysiwyg.element.querySelectorAll('[data-type~="block-ref"]').forEach(item => {
- if (item.textContent === "") {
- fetchPost("/api/block/getRefText", {id: item.getAttribute("data-id")}, (response) => {
- item.innerHTML = response.data;
- });
- }
- });
- blockRender(options.protyle, options.protyle.wysiwyg.element);
- processRender(options.protyle.wysiwyg.element);
- highlightRender(options.protyle.wysiwyg.element);
- avRender(options.protyle.wysiwyg.element, options.protyle);
+ click() {
+ turnsOneInto(options);
}
};
}
diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts
index 33ac3fc9e..f200ff3ed 100644
--- a/app/src/protyle/wysiwyg/keydown.ts
+++ b/app/src/protyle/wysiwyg/keydown.ts
@@ -31,7 +31,13 @@ import {
import {matchHotKey} from "../util/hotKey";
import {enter, softEnter} from "./enter";
import {fixTable} from "../util/table";
-import {turnsIntoOneTransaction, turnsIntoTransaction, updateBatchTransaction, updateTransaction} from "./transaction";
+import {
+ turnsIntoOneTransaction,
+ turnsIntoTransaction,
+ turnsOneInto,
+ updateBatchTransaction,
+ updateTransaction
+} from "./transaction";
import {fontEvent} from "../toolbar/Font";
import {addSubList, listIndent, listOutdent} from "./list";
import {newFileContentBySelect, rename, replaceFileName} from "../../editor/rename";
@@ -1330,10 +1336,73 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
return true;
}
}
- if (matchHotKey(window.siyuan.config.keymap.editor.insert.check.custom, event)) {
- protyle.hint.splitChar = "/";
- protyle.hint.lastIndex = -1;
- protyle.hint.fill("* [ ] " + Lute.Caret, protyle);
+ const isMatchList = matchHotKey(window.siyuan.config.keymap.editor.insert.list.custom, event)
+ const isMatchCheck = matchHotKey(window.siyuan.config.keymap.editor.insert.check.custom, event)
+ const isMatchOList = matchHotKey(window.siyuan.config.keymap.editor.insert["ordered-list"].custom, event)
+ if (isMatchList || isMatchOList || isMatchCheck) {
+ const selectsElement: HTMLElement[] = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"));
+ if (selectsElement.length === 0) {
+ protyle.hint.splitChar = "/";
+ protyle.hint.lastIndex = -1;
+ protyle.hint.fill((isMatchCheck ? "* [ ] " : (isMatchList ? "* " : "1. ")) + Lute.Caret, protyle);
+ } else if (selectsElement.length === 1) {
+ const subType = selectsElement[0].dataset.subtype
+ const type = selectsElement[0].dataset.type
+ if (type === "NodeParagraph") {
+ turnsIntoOneTransaction({
+ protyle,
+ selectsElement,
+ type: isMatchCheck ? "Blocks2TLs" : (isMatchList ? "Blocks2ULs" : "Blocks2OLs")
+ });
+ } else if (type === "NodeList") {
+ const id = selectsElement[0].dataset.nodeId
+ if (subType === "o" && (isMatchList || isMatchCheck)) {
+ turnsOneInto({
+ protyle,
+ nodeElement: selectsElement[0],
+ id,
+ type: isMatchCheck ? "UL2TL" : "OL2UL",
+ });
+ } else if (subType === "t" && (isMatchList || isMatchOList)) {
+ turnsOneInto({
+ protyle,
+ nodeElement: selectsElement[0],
+ id,
+ type: isMatchList ? "TL2UL" : "TL2OL",
+ });
+ } else if (isMatchCheck || isMatchOList) {
+ turnsOneInto({
+ protyle,
+ nodeElement: selectsElement[0],
+ id,
+ type: isMatchCheck ? "OL2TL" : "UL2OL",
+ });
+ }
+ }
+ } else {
+ let isList = false;
+ let isContinue = false;
+ selectsElement.find((item, index) => {
+ if (item.classList.contains("li")) {
+ isList = true;
+ return true;
+ }
+ if (item.nextElementSibling && selectsElement[index + 1] &&
+ item.nextElementSibling.isSameNode(selectsElement[index + 1])) {
+ isContinue = true;
+ } else if (index !== selectsElement.length - 1) {
+ isContinue = false;
+ return true;
+ }
+ });
+ if (!isList && isContinue) {
+ turnsIntoOneTransaction({
+ protyle,
+ selectsElement,
+ type: isMatchCheck ? "Blocks2TLs" : (isMatchList ? "Blocks2ULs" : "Blocks2OLs")
+ });
+ }
+ }
event.preventDefault();
event.stopPropagation();
return;
diff --git a/app/src/protyle/wysiwyg/transaction.ts b/app/src/protyle/wysiwyg/transaction.ts
index e7012be5c..e42cff9fa 100644
--- a/app/src/protyle/wysiwyg/transaction.ts
+++ b/app/src/protyle/wysiwyg/transaction.ts
@@ -1,6 +1,6 @@
-import {fetchPost} from "../../util/fetch";
+import {fetchPost, fetchSyncPost} from "../../util/fetch";
import {focusBlock, focusByWbr, focusSideBlock, getEditorRange} from "../util/selection";
-import {getTopAloneElement} from "./getBlock";
+import {getContenteditableElement, getTopAloneElement} from "./getBlock";
import {Constants} from "../../constants";
import {blockRender} from "../render/blockRender";
import {processRender} from "../util/processCode";
@@ -1025,6 +1025,99 @@ export const turnsIntoTransaction = (options: {
hideElements(["gutter"], options.protyle);
};
+export const turnsOneInto = async (options: {
+ protyle: IProtyle,
+ nodeElement: Element,
+ id: string,
+ type: string,
+ level?: number
+}) => {
+ if (!options.nodeElement.querySelector("wbr")) {
+ getContenteditableElement(options.nodeElement)?.insertAdjacentHTML("afterbegin", "");
+ }
+ if (options.type === "CancelList" || options.type === "CancelBlockquote") {
+ for await(const item of options.nodeElement.querySelectorAll('[data-type="NodeHeading"][fold="1"]')) {
+ const itemId = item.getAttribute("data-node-id");
+ item.removeAttribute("fold");
+ const response = await fetchSyncPost("/api/transactions", {
+ session: options.protyle.id,
+ app: Constants.SIYUAN_APPID,
+ transactions: [{
+ doOperations: [{
+ action: "unfoldHeading",
+ id: itemId,
+ }],
+ undoOperations: [{
+ action: "foldHeading",
+ id: itemId
+ }],
+ }]
+ });
+ options.protyle.undo.add([{
+ action: "unfoldHeading",
+ id: itemId,
+ }], [{
+ action: "foldHeading",
+ id: itemId
+ }], options.protyle);
+ item.insertAdjacentHTML("afterend", response.data[0].doOperations[0].retData);
+ }
+ }
+ const oldHTML = options.nodeElement.outerHTML;
+ const previousId = options.nodeElement.previousElementSibling?.getAttribute("data-node-id");
+ const parentId = options.nodeElement.parentElement.getAttribute("data-node-id") || options.protyle.block.parentID;
+ // @ts-ignore
+ const newHTML = options.protyle.lute[options.type](options.nodeElement.outerHTML, options.level);
+ options.nodeElement.outerHTML = newHTML;
+ if (options.type === "CancelList" || options.type === "CancelBlockquote") {
+ const tempElement = document.createElement("template");
+ tempElement.innerHTML = newHTML;
+ const doOperations: IOperation[] = [{
+ action: "delete",
+ id: options.id
+ }];
+ const undoOperations: IOperation[] = [];
+ let tempPreviousId = previousId;
+ Array.from(tempElement.content.children).forEach((item) => {
+ const tempId = item.getAttribute("data-node-id");
+ doOperations.push({
+ action: "insert",
+ data: item.outerHTML,
+ id: tempId,
+ previousID: tempPreviousId,
+ parentID: parentId
+ });
+ undoOperations.push({
+ action: "delete",
+ id: tempId
+ });
+ tempPreviousId = tempId;
+ });
+ undoOperations.push({
+ action: "insert",
+ data: oldHTML,
+ id: options.id,
+ previousID: previousId,
+ parentID: parentId
+ });
+ transaction(options.protyle, doOperations, undoOperations);
+ } else {
+ updateTransaction(options.protyle, options.id, newHTML, oldHTML);
+ }
+ focusByWbr(options.protyle.wysiwyg.element, getEditorRange(options.protyle.wysiwyg.element));
+ options.protyle.wysiwyg.element.querySelectorAll('[data-type~="block-ref"]').forEach(item => {
+ if (item.textContent === "") {
+ fetchPost("/api/block/getRefText", {id: item.getAttribute("data-id")}, (response) => {
+ item.innerHTML = response.data;
+ });
+ }
+ });
+ blockRender(options.protyle, options.protyle.wysiwyg.element);
+ processRender(options.protyle.wysiwyg.element);
+ highlightRender(options.protyle.wysiwyg.element);
+ avRender(options.protyle.wysiwyg.element, options.protyle);
+}
+
const updateRef = (protyle: IProtyle, id: string, index = 0) => {
if (index > 6) {
return;