This commit is contained in:
parent
0dd00d2138
commit
ad6fe1cd6e
8 changed files with 136 additions and 21 deletions
|
@ -115,6 +115,15 @@
|
|||
min-height: 30px;
|
||||
z-index: 1;
|
||||
|
||||
.block__icon {
|
||||
opacity: 1;
|
||||
margin-left: 8px;
|
||||
|
||||
&:disabled {
|
||||
opacity: .38;
|
||||
}
|
||||
}
|
||||
|
||||
&__space {
|
||||
min-width: 8px;
|
||||
transition: var(--b3-transition);
|
||||
|
@ -153,7 +162,6 @@
|
|||
}
|
||||
|
||||
&__icon {
|
||||
margin-right: 8px;
|
||||
opacity: 1;
|
||||
border: 0;
|
||||
line-height: 24px;
|
||||
|
|
|
@ -503,7 +503,7 @@
|
|||
|
||||
[data-node-id][fold="1"]:not(.li):not([data-type="NodeHeading"]) {
|
||||
@include text-clamp(1);
|
||||
opacity: 0.54;
|
||||
opacity: 0.38;
|
||||
font-size: 16px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
|
|
|
@ -28,8 +28,9 @@ import {Menu} from "../../plugin/Menu";
|
|||
import {getNoContainerElement} from "../wysiwyg/getBlock";
|
||||
import {openTitleMenu} from "../header/openTitleMenu";
|
||||
import {emitOpenMenu} from "../../plugin/EventBus";
|
||||
import {isInAndroid, isMac, updateHotkeyTip} from "../util/compatibility";
|
||||
import {isInAndroid, isIPad, isMac, updateHotkeyTip} from "../util/compatibility";
|
||||
import {resize} from "../util/resize";
|
||||
import {listIndent, listOutdent} from "../wysiwyg/list";
|
||||
|
||||
export class Breadcrumb {
|
||||
public element: HTMLElement;
|
||||
|
@ -40,18 +41,25 @@ export class Breadcrumb {
|
|||
constructor(protyle: IProtyle) {
|
||||
const element = document.createElement("div");
|
||||
element.className = "protyle-breadcrumb";
|
||||
let padHTML = ""
|
||||
/// #if BROWSER
|
||||
if (isIPad() || isInAndroid()) {
|
||||
padHTML = `<button class="block__icon fn__flex-center ariaLabel" disabled aria-label="${window.siyuan.languages.undo}" data-type="undo"><svg><use xlink:href="#iconUndo"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel" disabled aria-label="${window.siyuan.languages.redo}" data-type="redo"><svg><use xlink:href="#iconRedo"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel" disabled aria-label="${window.siyuan.languages.outdent}" data-type="outdent"><svg><use xlink:href="#iconOutdent"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel" disabled aria-label="${window.siyuan.languages.indent}" data-type="indent"><svg><use xlink:href="#iconIndent"></use></svg></button>`;
|
||||
}
|
||||
/// #endif
|
||||
element.innerHTML = `${isMobile() ?
|
||||
`<button class="protyle-breadcrumb__icon" data-type="mobile-menu">${window.siyuan.languages.breadcrumb}</button>` :
|
||||
'<div class="protyle-breadcrumb__bar"></div>'}
|
||||
<span class="protyle-breadcrumb__space"></span>
|
||||
<button class="protyle-breadcrumb__icon fn__none ariaLabel" aria-label="${updateHotkeyTip(window.siyuan.config.keymap.editor.general.exitFocus.custom)}" data-type="exit-focus">${window.siyuan.languages.exitFocus}</button>
|
||||
<button class="block__icon block__icon--show fn__flex-center ariaLabel${window.siyuan.config.readonly ? " fn__none" : ""}" aria-label="${window.siyuan.languages.lockEdit}" data-type="readonly"><svg><use xlink:href="#iconUnlock"></use></svg></button>
|
||||
<span class="fn__space${window.siyuan.config.readonly ? " fn__none" : ""}"></span>
|
||||
<button class="block__icon block__icon--show fn__flex-center ariaLabel" data-type="doc" aria-label="${isMac() ? window.siyuan.languages.gutterTip2 : window.siyuan.languages.gutterTip2.replace("⇧", "Shift+")}"><svg><use xlink:href="#iconFile"></use></svg></button>
|
||||
<span class="fn__space"></span>
|
||||
<button class="block__icon block__icon--show fn__flex-center ariaLabel" data-type="more" aria-label="${window.siyuan.languages.more}"><svg><use xlink:href="#iconMore"></use></svg></button>
|
||||
<button class="block__icon block__icon--show fn__flex-center fn__none ariaLabel" style="margin-left: 8px" data-type="context" aria-label="${window.siyuan.languages.context}"><svg><use xlink:href="#iconAlignCenter"></use></svg></button>`;
|
||||
|
||||
${padHTML}
|
||||
<button class="block__icon fn__flex-center ariaLabel${window.siyuan.config.readonly ? " fn__none" : ""}" aria-label="${window.siyuan.languages.lockEdit}" data-type="readonly"><svg><use xlink:href="#iconUnlock"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel" data-type="doc" aria-label="${isMac() ? window.siyuan.languages.gutterTip2 : window.siyuan.languages.gutterTip2.replace("⇧", "Shift+")}"><svg><use xlink:href="#iconFile"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel" data-type="more" aria-label="${window.siyuan.languages.more}"><svg><use xlink:href="#iconMore"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center fn__none ariaLabel" data-type="context" aria-label="${window.siyuan.languages.context}"><svg><use xlink:href="#iconAlignCenter"></use></svg></button>`;
|
||||
this.element = element.firstElementChild as HTMLElement;
|
||||
element.addEventListener("click", (event) => {
|
||||
/// #if !MOBILE
|
||||
|
@ -133,6 +141,36 @@ export class Breadcrumb {
|
|||
target.classList.add("block__icon--active");
|
||||
}
|
||||
break;
|
||||
} else if (type === "undo") {
|
||||
protyle.undo.undo(protyle);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (type === "redo") {
|
||||
protyle.undo.redo(protyle);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (type === "outdent") {
|
||||
if (protyle.toolbar.range) {
|
||||
const blockElement = hasClosestBlock(protyle.toolbar.range.startContainer);
|
||||
if (blockElement) {
|
||||
listOutdent(protyle, [blockElement.parentElement], protyle.toolbar.range);
|
||||
}
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (type === "indent") {
|
||||
if (protyle.toolbar.range) {
|
||||
const blockElement = hasClosestBlock(protyle.toolbar.range.startContainer);
|
||||
if (blockElement) {
|
||||
listIndent(protyle, [blockElement.parentElement], protyle.toolbar.range);
|
||||
}
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
}
|
||||
target = target.parentElement;
|
||||
}
|
||||
|
@ -528,9 +566,7 @@ export class Breadcrumb {
|
|||
}
|
||||
|
||||
public render(protyle: IProtyle, update = false) {
|
||||
if (isMobile()) {
|
||||
return;
|
||||
}
|
||||
/// #if !MOBILE
|
||||
let range: Range;
|
||||
let blockElement: Element;
|
||||
if (getSelection().rangeCount > 0) {
|
||||
|
@ -614,6 +650,7 @@ export class Breadcrumb {
|
|||
this.element.scrollLeft = (this.element.lastElementChild as HTMLElement).offsetLeft - this.element.clientWidth + 14;
|
||||
}
|
||||
});
|
||||
/// #endif
|
||||
}
|
||||
|
||||
public hide() {
|
||||
|
|
|
@ -442,7 +442,7 @@ export class Gutter {
|
|||
}], [{
|
||||
action: "foldHeading",
|
||||
id: itemId
|
||||
}]);
|
||||
}], options.protyle);
|
||||
item.insertAdjacentHTML("afterend", response.data[0].doOperations[0].retData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import {Constants} from "../../constants";
|
|||
import {hideElements} from "../ui/hideElements";
|
||||
import {scrollCenter} from "../../util/highlightById";
|
||||
import {matchHotKey} from "../util/hotKey";
|
||||
import { ipcRenderer } from "electron";
|
||||
import {ipcRenderer} from "electron";
|
||||
|
||||
interface IOperations {
|
||||
doOperations: IOperation[],
|
||||
|
@ -32,9 +32,17 @@ export class Undo {
|
|||
this.render(protyle, state, false);
|
||||
this.hasUndo = true;
|
||||
this.redoStack.push(state);
|
||||
if (protyle.breadcrumb) {
|
||||
const undoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="undo"]')
|
||||
if (undoElement) {
|
||||
if (this.undoStack.length === 0) {
|
||||
undoElement.setAttribute("disabled", "true");
|
||||
}
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="redo"]').removeAttribute("disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public redo(protyle: IProtyle) {
|
||||
if (protyle.disabled) {
|
||||
return;
|
||||
|
@ -45,6 +53,15 @@ export class Undo {
|
|||
const state = this.redoStack.pop();
|
||||
this.render(protyle, state, true);
|
||||
this.undoStack.push(state);
|
||||
if (protyle.breadcrumb) {
|
||||
const redoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="redo"]')
|
||||
if (redoElement) {
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="undo"]').removeAttribute("disabled");
|
||||
if (this.redoStack.length === 0) {
|
||||
redoElement.setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private render(protyle: IProtyle, state: IOperations, redo: boolean) {
|
||||
|
@ -52,7 +69,7 @@ export class Undo {
|
|||
protyle.wysiwyg.lastHTMLs = {};
|
||||
if (!redo) {
|
||||
state.undoOperations.forEach(item => {
|
||||
onTransaction(protyle, item, true);
|
||||
onTransaction(protyle, item, true);
|
||||
});
|
||||
transaction(protyle, state.undoOperations);
|
||||
} else {
|
||||
|
@ -65,19 +82,25 @@ export class Undo {
|
|||
scrollCenter(protyle);
|
||||
}
|
||||
|
||||
public replace(doOperations: IOperation[]) {
|
||||
public replace(doOperations: IOperation[], protyle: IProtyle) {
|
||||
// undo 引发 replace 导致 stack 错误 https://github.com/siyuan-note/siyuan/issues/9178
|
||||
if (this.hasUndo && this.redoStack.length > 0) {
|
||||
this.undoStack.push(this.redoStack.pop());
|
||||
this.redoStack = [];
|
||||
this.hasUndo = false;
|
||||
if (protyle.breadcrumb) {
|
||||
const redoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="redo"]')
|
||||
if (redoElement) {
|
||||
redoElement.setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.undoStack.length > 0) {
|
||||
this.undoStack[this.undoStack.length - 1].doOperations = doOperations;
|
||||
}
|
||||
}
|
||||
|
||||
public add( doOperations: IOperation[], undoOperations: IOperation[]) {
|
||||
public add(doOperations: IOperation[], undoOperations: IOperation[], protyle: IProtyle) {
|
||||
this.undoStack.push({undoOperations, doOperations});
|
||||
if (this.undoStack.length > Constants.SIZE_UNDO) {
|
||||
this.undoStack.shift();
|
||||
|
@ -86,6 +109,12 @@ export class Undo {
|
|||
this.redoStack = [];
|
||||
this.hasUndo = false;
|
||||
}
|
||||
if (protyle.breadcrumb) {
|
||||
const undoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="undo"]')
|
||||
if (undoElement) {
|
||||
undoElement.removeAttribute("disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public clear() {
|
||||
|
|
|
@ -314,6 +314,13 @@ export const disabledProtyle = (protyle: IProtyle) => {
|
|||
if (protyle.breadcrumb) {
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"] use').setAttribute("xlink:href", "#iconLock");
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"]').setAttribute("aria-label", window.siyuan.config.editor.readOnly ? window.siyuan.languages.tempUnlock : window.siyuan.languages.unlockEdit);
|
||||
const undoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="undo"]')
|
||||
if (undoElement && !undoElement.classList.contains("fn__none")) {
|
||||
undoElement.classList.add("fn__none")
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="redo"]').classList.add("fn__none")
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="indent"]').classList.add("fn__none")
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="outdent"]').classList.add("fn__none")
|
||||
}
|
||||
}
|
||||
hideTooltip();
|
||||
};
|
||||
|
@ -357,6 +364,13 @@ export const enableProtyle = (protyle: IProtyle) => {
|
|||
if (protyle.breadcrumb) {
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"] use').setAttribute("xlink:href", "#iconUnlock");
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"]').setAttribute("aria-label", window.siyuan.config.editor.readOnly ? window.siyuan.languages.cancelTempUnlock : window.siyuan.languages.lockEdit);
|
||||
const undoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="undo"]')
|
||||
if (undoElement && undoElement.classList.contains("fn__none")) {
|
||||
undoElement.classList.remove("fn__none")
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="redo"]').classList.remove("fn__none")
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="indent"]').classList.remove("fn__none")
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="outdent"]').classList.remove("fn__none")
|
||||
}
|
||||
}
|
||||
hideTooltip();
|
||||
};
|
||||
|
|
|
@ -1823,6 +1823,19 @@ export class WYSIWYG {
|
|||
if (range.toString() === "") {
|
||||
countSelectWord(range, protyle.block.rootID);
|
||||
}
|
||||
if (protyle.breadcrumb) {
|
||||
const indentElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="indent"]')
|
||||
if (indentElement) {
|
||||
const outdentElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="outdent"]');
|
||||
if (nodeElement.parentElement.classList.contains("li")) {
|
||||
indentElement.removeAttribute("disabled");
|
||||
outdentElement.removeAttribute("disabled");
|
||||
} else {
|
||||
indentElement.setAttribute("disabled", "true");
|
||||
outdentElement.setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
@ -2351,6 +2364,20 @@ export class WYSIWYG {
|
|||
/// #if !MOBILE
|
||||
pushBack(protyle, newRange);
|
||||
/// #endif
|
||||
if (protyle.breadcrumb) {
|
||||
const indentElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="indent"]')
|
||||
const blockElement = hasClosestBlock(newRange.startContainer);
|
||||
if (indentElement && blockElement) {
|
||||
const outdentElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="outdent"]');
|
||||
if (blockElement.parentElement.classList.contains("li")) {
|
||||
indentElement.removeAttribute("disabled");
|
||||
outdentElement.removeAttribute("disabled");
|
||||
} else {
|
||||
indentElement.setAttribute("disabled", "true");
|
||||
outdentElement.setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (isMobile() || isInIOS()) ? 520 : 0); // Android/iPad 双击慢了出不来
|
||||
protyle.hint.enableExtend = false;
|
||||
if (event.shiftKey) {
|
||||
|
|
|
@ -1027,9 +1027,9 @@ export const transaction = (protyle: IProtyle, doOperations: IOperation[], undoO
|
|||
protyle.updated = true;
|
||||
|
||||
if (needDebounce) {
|
||||
protyle.undo.replace(doOperations);
|
||||
protyle.undo.replace(doOperations, protyle);
|
||||
} else {
|
||||
protyle.undo.add(doOperations, undoOperations);
|
||||
protyle.undo.add(doOperations, undoOperations, protyle);
|
||||
}
|
||||
}
|
||||
if (needDebounce) {
|
||||
|
|
Loading…
Add table
Reference in a new issue