Vanessa 2022-12-07 18:27:24 +08:00
parent 560ff8c9d4
commit 9cc072f13d
10 changed files with 217 additions and 52 deletions

4
app/pnpm-lock.yaml generated
View file

@ -1928,10 +1928,10 @@ packages:
resolution: {integrity: sha512-m0+M53+HYMzqKxwNQZT143K7WwXEGUy9LY31l8dJphXx2P/FQod615mVbxHyqbDCG4J5bHdWm21qZ0e2DVY6CQ==}
engines: {node: '>=14.0.0'}
dependencies:
7zip-bin: 5.1.1
'@develar/schema-utils': 2.6.5
'@electron/universal': 1.2.1
'@malept/flatpak-bundler': 0.4.0
7zip-bin: 5.1.1
async-exit-hook: 2.0.1
bluebird-lst: 1.0.9
builder-util: 23.3.3
@ -2215,9 +2215,9 @@ packages:
/builder-util/23.3.3:
resolution: {integrity: sha512-MJZlUiq2PY5hjYv9+XNaoYdsITqvLgRDoHSFg/4nzpInbNxNjLQOolL04Zsyp+hgfcbFvMC4h0KkR1CMPHLWbA==}
dependencies:
7zip-bin: 5.1.1
'@types/debug': 4.1.7
'@types/fs-extra': 9.0.13
7zip-bin: 5.1.1
app-builder-bin: 4.0.0
bluebird-lst: 1.0.9
builder-util-runtime: 9.0.3

View file

@ -15,9 +15,9 @@ export class Backlink extends Model {
public type: "pin" | "local";
public blockId: string;
public rootId: string; // "local" 必传
private tree: Tree;
public tree: Tree;
private notebookId: string;
private mTree: Tree;
public mTree: Tree;
public editors: Protyle[] = [];
public status: {
[key: string]: {
@ -143,12 +143,15 @@ export class Backlink extends Model {
data: null,
click: (element) => {
this.toggleItem(element, false);
this.setFocus();
this.mTree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
ctrlClick(element) {
openFileById({
id: element.getAttribute("data-node-id"),
action: [Constants.CB_GET_CONTEXT]
});
this.mTree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
altClick(element) {
openFileById({
@ -156,6 +159,7 @@ export class Backlink extends Model {
position: "right",
action: [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT]
});
this.mTree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
shiftClick(element) {
openFileById({
@ -163,9 +167,12 @@ export class Backlink extends Model {
position: "bottom",
action: [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT]
});
this.mTree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
toggleClick: (liElement) => {
this.toggleItem(liElement, false);
this.setFocus();
this.mTree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
}
});
this.mTree = new Tree({
@ -173,12 +180,15 @@ export class Backlink extends Model {
data: null,
click: (element) => {
this.toggleItem(element, true);
this.setFocus();
this.tree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
ctrlClick(element) {
openFileById({
id: element.getAttribute("data-node-id"),
action: [Constants.CB_GET_CONTEXT]
});
this.tree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
altClick(element) {
openFileById({
@ -186,6 +196,7 @@ export class Backlink extends Model {
position: "right",
action: [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT]
});
this.tree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
shiftClick(element) {
openFileById({
@ -193,9 +204,12 @@ export class Backlink extends Model {
position: "bottom",
action: [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT]
});
this.tree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
toggleClick: (liElement) => {
this.toggleItem(liElement, true);
this.setFocus();
this.tree.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
},
blockExtHTML: `<span class="b3-list-item__action b3-tooltips b3-tooltips__nw" aria-label="${window.siyuan.languages.more}"><svg><use xlink:href="#iconMore"></use></svg></span>`
});
@ -227,11 +241,7 @@ export class Backlink extends Model {
});
});
this.element.addEventListener("click", (event) => {
if (this.type === "local") {
setPanelFocus(this.element.parentElement.parentElement);
} else {
setPanelFocus(this.element);
}
this.setFocus();
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(this.element)) {
if (target.classList.contains("block__icon") && target.parentElement.parentElement.isSameNode(this.element)) {
@ -299,6 +309,14 @@ export class Backlink extends Model {
}
}
private setFocus() {
if (this.type === "local") {
setPanelFocus(this.element.parentElement.parentElement);
} else {
setPanelFocus(this.element);
}
}
private showSortMenu(type: string, sort: string) {
const clickEvent = (currentSort: string) => {
(type === "sort" ? this.tree : this.mTree).element.previousElementSibling.querySelector(`[data-type="${type}"]`).setAttribute("data-sort", currentSort);

View file

@ -13,7 +13,7 @@ import {escapeHtml} from "../../util/escape";
export class Bookmark extends Model {
private openNodes: string[];
private tree: Tree;
public tree: Tree;
private element: Element;
constructor(tab: Tab) {

View file

@ -13,7 +13,7 @@ import {unicode2Emoji} from "../../emoji";
import {onGet} from "../../protyle/util/onGet";
export class Outline extends Model {
private tree: Tree;
public tree: Tree;
public element: HTMLElement;
public headerElement: HTMLElement;
public type: "pin" | "local";

View file

@ -12,7 +12,7 @@ import {escapeHtml} from "../../util/escape";
export class Tag extends Model {
private openNodes: string[];
private tree: Tree;
public tree: Tree;
private element: Element;
constructor(tab: Tab) {

View file

@ -541,7 +541,7 @@ export const copyTab = (tab: Tab) => {
});
};
export const getInstanceById = (id: string) => {
export const getInstanceById = (id: string, layout =window.siyuan.layout.centerLayout) => {
const _getInstanceById = (item: Layout | Wnd, id: string) => {
if (item.id === id) {
return item;
@ -557,7 +557,7 @@ export const getInstanceById = (id: string) => {
}
}
};
return _getInstanceById(window.siyuan.layout.centerLayout, id);
return _getInstanceById(layout, id);
};
export const addResize = (obj: Layout | Wnd) => {

View file

@ -1842,7 +1842,8 @@ export class Gutter {
this.element.style.left = `${left}px`;
if (left < this.element.parentElement.getBoundingClientRect().left) {
this.element.style.width = "24px";
this.element.style.left = `${rect.left - this.element.clientWidth - space / 2}px`;
// 需加 2否则和折叠标题无法对齐
this.element.style.left = `${rect.left - this.element.clientWidth - space / 2 + 3}px`;
html = "";
Array.from(this.element.children).reverse().forEach((item, index) => {
if (index !== 0) {

View file

@ -1,5 +1,5 @@
import {getAllModels} from "../layout/getAll";
import {getInstanceById, getWndByLayout, resizeTabs} from "../layout/util";
import {getInstanceById, getWndByLayout, resizeTabs, setPanelFocus} from "../layout/util";
import {Tab} from "../layout/Tab";
import {Search} from "./index";
import {Wnd} from "../layout/Wnd";
@ -78,6 +78,7 @@ export const openGlobalSearch = (text: string, replace: boolean) => {
}
});
wnd.split("lr").addTab(tab);
setPanelFocus(tab.panelElement);
};
export const genSearch = (config: ISearchOption, element: Element, closeCB?: () => void) => {

View file

@ -11,10 +11,9 @@ export class Tree {
private blockExtHTML: string;
private topExtHTML: string;
private click: (element: HTMLElement, event: MouseEvent) => void;
public click: (element: Element, event?: MouseEvent) => void;
private ctrlClick: (element: HTMLElement) => void;
private toggleClick: (element: HTMLElement) => void;
private toggleClick: (element: Element) => void;
private shiftClick: (element: HTMLElement) => void;
private altClick: (element: HTMLElement) => void;
private rightClick: (element: HTMLElement, event: MouseEvent) => void;
@ -83,8 +82,8 @@ data-treetype="${item.type}"
data-type="${item.nodeType}"
data-subtype="${item.subType}"
${item.label ? "data-label='" + item.label + "'" : ""}>
<span style="padding-left: ${(item.depth - 1) * 18 + 22}px;margin-right: 2px" class="b3-list-item__toggle${(item.type === "backlink" || hasChild) ? " b3-list-item__toggle--hl" : ""}">
<svg data-id="${encodeURIComponent(item.name + item.depth)}" class="b3-list-item__arrow ${hasChild ? "b3-list-item__arrow--open" : (item.type === "backlink" ? "" : "fn__hidden")}"><use xlink:href="#iconRight"></use></svg>
<span style="padding-left: ${(item.depth - 1) * 18 + 22}px;margin-right: 2px" class="b3-list-item__toggle${(item.type === "backlink" || hasChild) ? " b3-list-item__toggle--hl" : ""}${hasChild||item.type === "backlink" ? "" : " fn__hidden"}">
<svg data-id="${encodeURIComponent(item.name + item.depth)}" class="b3-list-item__arrow${hasChild ? " b3-list-item__arrow--open" : ""}"><use xlink:href="#iconRight"></use></svg>
</span>
${iconHTML}
<span class="b3-list-item__text"${titleTip}>${item.name}</span>
@ -129,8 +128,8 @@ data-type="${item.type}"
data-subtype="${item.subType}"
data-treetype="${type}"
data-def-path="${item.defPath}">
<span style="padding-left: ${(item.depth - 1) * 18 + 22}px;margin-right: 2px" class="b3-list-item__toggle${item.children ? " b3-list-item__toggle--hl" : ""}">
<svg data-id="${item.id}" class="b3-list-item__arrow${item.children ? "" : " fn__hidden"}"><use xlink:href="#iconRight"></use></svg>
<span style="padding-left: ${(item.depth - 1) * 18 + 22}px;margin-right: 2px" class="b3-list-item__toggle${item.children ? " b3-list-item__toggle--hl" : ""}${item.children ? "" : " fn__hidden"}">
<svg data-id="${item.id}" class="b3-list-item__arrow"><use xlink:href="#iconRight"></use></svg>
</span>
${iconHTML}
<span class="b3-list-item__text" ${type === "outline" ? ' title="' + Lute.EscapeHTMLStr(Lute.BlockDOM2Content(item.content)) + '"' : ""}>${item.content}</span>
@ -144,7 +143,7 @@ data-def-path="${item.defPath}">
return html;
}
private toggleBlocks(liElement: HTMLElement) {
public toggleBlocks(liElement: Element) {
if (this.toggleClick) {
this.toggleClick(liElement);
return;
@ -194,7 +193,7 @@ data-def-path="${item.defPath}">
this.element.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(this.element)) {
if (target.classList.contains("b3-list-item__toggle") && !target.firstElementChild.classList.contains("fn__hidden")) {
if (target.classList.contains("b3-list-item__toggle") && !target.classList.contains("fn__hidden")) {
this.toggleBlocks(target.parentElement);
this.setCurrent(target.parentElement);
event.preventDefault();

View file

@ -42,6 +42,8 @@ import {getStartEndElement} from "../protyle/wysiwyg/commonHotkey";
import {getNextFileLi, getPreviousFileLi} from "../protyle/wysiwyg/getBlock";
import {editor} from "../config/editor";
import {hintMoveBlock} from "../protyle/hint/extend";
import {Outline} from "../layout/dock/Outline";
import {Backlink} from "../layout/dock/Backlink";
const getRightBlock = (element: HTMLElement, x: number, y: number) => {
let index = 1;
@ -599,33 +601,6 @@ export const globalShortcut = () => {
return;
}
// 面板折叠展开操作
if (!event.repeat && (matchHotKey(window.siyuan.config.keymap.editor.general.collapse.custom, event) || matchHotKey(window.siyuan.config.keymap.editor.general.expand.custom, event))) {
let activePanelElement = document.querySelector(".layout__tab--active");
if (!activePanelElement) {
Array.from(document.querySelectorAll(".layout__wnd--active .layout-tab-container > div")).forEach(item => {
if (!item.classList.contains("fn__none")) {
activePanelElement = item;
return true;
}
});
}
if (activePanelElement) {
if (matchHotKey(window.siyuan.config.keymap.editor.general.collapse.custom, event)) {
if (activePanelElement.querySelector('.block__icon[data-type="collapse"]')) {
activePanelElement.querySelector('.block__icon[data-type="collapse"]').dispatchEvent(new CustomEvent("click"));
}
} else if (matchHotKey(window.siyuan.config.keymap.editor.general.expand.custom, event)) {
if (activePanelElement.querySelector('.block__icon[data-type="expand"]')) {
activePanelElement.querySelector('.block__icon[data-type="expand"]').dispatchEvent(new CustomEvent("click"));
}
}
}
event.stopPropagation();
event.preventDefault();
return;
}
// close tab
if (matchHotKey(window.siyuan.config.keymap.general.closeTab.custom, event) && !event.repeat) {
event.preventDefault();
@ -680,6 +655,11 @@ export const globalShortcut = () => {
return;
}
// 面板的操作
if (panelTreeKeydown(event)) {
return;
}
let searchKey = "";
if (matchHotKey(window.siyuan.config.keymap.general.replace.custom, event)) {
searchKey = window.siyuan.config.keymap.general.replace.custom;
@ -1147,3 +1127,169 @@ const fileTreeKeydown = (event: KeyboardEvent) => {
return true;
}
};
const panelTreeKeydown = (event: KeyboardEvent) => {
// 面板折叠展开操作
if (!matchHotKey(window.siyuan.config.keymap.editor.general.collapse.custom, event) &&
!matchHotKey(window.siyuan.config.keymap.editor.general.expand.custom, event) &&
!event.key.startsWith("Arrow") && event.key !== "Enter") {
return false;
}
let activePanelElement = document.querySelector(".layout__tab--active");
if (!activePanelElement) {
Array.from(document.querySelectorAll(".layout__wnd--active .layout-tab-container > div")).find(item => {
if (!item.classList.contains("fn__none") && item.className.indexOf("sy__") > -1) {
activePanelElement = item;
return true;
}
});
}
if (!activePanelElement) {
return false
}
if (activePanelElement.className.indexOf("sy__") === -1) {
return false;
}
if (!event.repeat && matchHotKey(window.siyuan.config.keymap.editor.general.collapse.custom, event)) {
const collapseElement = activePanelElement.querySelector('.block__icon[data-type="collapse"]');
if (collapseElement) {
collapseElement.dispatchEvent(new CustomEvent("click"));
event.preventDefault();
return true;
}
}
if (!event.repeat && matchHotKey(window.siyuan.config.keymap.editor.general.expand.custom, event)) {
const expandElement = activePanelElement.querySelector('.block__icon[data-type="expand"]');
if (expandElement) {
expandElement.dispatchEvent(new CustomEvent("click"));
event.preventDefault();
return true;
}
}
if (activePanelElement.classList.contains("sy__inbox") ||
activePanelElement.classList.contains("sy__globalGraph") ||
activePanelElement.classList.contains("sy__graph")) {
return false;
}
const model = (getInstanceById(activePanelElement.getAttribute("data-id"), window.siyuan.layout.layout) as Tab)?.model;
if (!model) {
return false;
}
let activeItemElement = activePanelElement.querySelector(".b3-list-item--focus")
if (!activeItemElement) {
activeItemElement = activePanelElement.querySelector(".b3-list .b3-list-item");
if (activeItemElement) {
activeItemElement.classList.add("b3-list-item--focus")
}
return false;
}
let tree = (model as Backlink).tree
if (activeItemElement.parentElement.parentElement.classList.contains("backlinkMList")) {
tree = (model as Backlink).mTree
}
if (event.key === "Enter") {
tree.click(activeItemElement);
event.preventDefault();
return true;
}
const arrowElement = activeItemElement.querySelector(".b3-list-item__arrow")
if ((event.key === "ArrowRight" && !arrowElement.classList.contains("b3-list-item__arrow--open") && !arrowElement.parentElement.classList.contains("fn__hidden")) ||
(event.key === "ArrowLeft" && arrowElement.classList.contains("b3-list-item__arrow--open") && !arrowElement.parentElement.classList.contains("fn__hidden"))) {
tree.toggleBlocks(activeItemElement);
event.preventDefault();
return true;
}
const ulElement = hasClosestByClassName(activeItemElement, "b3-list");
if (!ulElement) {
return false;
}
if (event.key === "ArrowLeft") {
let parentElement = activeItemElement.parentElement.previousElementSibling;
if (parentElement) {
if (parentElement.tagName !== "LI") {
parentElement = ulElement.querySelector(".b3-list-item");
}
activeItemElement.classList.remove("b3-list-item--focus");
parentElement.classList.add("b3-list-item--focus");
const parentRect = parentElement.getBoundingClientRect();
const scrollRect = ulElement.parentElement.getBoundingClientRect();
if (parentRect.top < scrollRect.top || parentRect.bottom > scrollRect.bottom) {
parentElement.scrollIntoView(parentRect.top < scrollRect.top);
}
}
event.preventDefault();
return true;
}
if (event.key === "ArrowDown" || event.key === "ArrowRight") {
let nextElement = activeItemElement;
while (nextElement) {
if (nextElement.nextElementSibling) {
if (nextElement.nextElementSibling.tagName === "UL") {
nextElement = nextElement.nextElementSibling.firstElementChild;
} else if (nextElement.nextElementSibling.classList.contains("protyle")) {
if (nextElement.nextElementSibling.nextElementSibling) {
nextElement = nextElement.nextElementSibling.nextElementSibling;
}
} else {
nextElement = nextElement.nextElementSibling;
}
break;
} else {
if (nextElement.parentElement.classList.contains("fn__flex-1")) {
break;
} else {
nextElement = nextElement.parentElement;
}
}
}
if (nextElement.classList.contains("b3-list-item") && !nextElement.classList.contains("b3-list-item--focus")) {
activeItemElement.classList.remove("b3-list-item--focus");
nextElement.classList.add("b3-list-item--focus");
const nextRect = nextElement.getBoundingClientRect();
const scrollRect = ulElement.parentElement.getBoundingClientRect();
if (nextRect.top < scrollRect.top || nextRect.bottom > scrollRect.bottom) {
nextElement.scrollIntoView(nextRect.top < scrollRect.top);
}
}
event.preventDefault();
return true;
}
if (event.key === "ArrowUp") {
let previousElement = activeItemElement;
while (previousElement) {
if (previousElement.previousElementSibling) {
if (previousElement.previousElementSibling.tagName === "LI") {
previousElement = previousElement.previousElementSibling;
} else if (previousElement.previousElementSibling.classList.contains("protyle")) {
if (previousElement.previousElementSibling.previousElementSibling) {
previousElement = previousElement.previousElementSibling.previousElementSibling;
}
} else {
const liElements = previousElement.previousElementSibling.querySelectorAll(".b3-list-item");
previousElement = liElements[liElements.length - 1];
}
break;
} else {
if (previousElement.parentElement.classList.contains("fn__flex-1")) {
break;
} else {
previousElement = previousElement.parentElement;
}
}
}
if (previousElement.classList.contains("b3-list-item") && !previousElement.classList.contains("b3-list-item--focus")) {
activeItemElement.classList.remove("b3-list-item--focus");
previousElement.classList.add("b3-list-item--focus");
const previousRect = previousElement.getBoundingClientRect();
const scrollRect = ulElement.parentElement.getBoundingClientRect();
if (previousRect.top < scrollRect.top || previousRect.bottom > scrollRect.bottom) {
previousElement.scrollIntoView(previousRect.top < scrollRect.top);
}
}
event.preventDefault();
return true;
}
return false
}