diff --git a/app/src/layout/dock/Files.ts b/app/src/layout/dock/Files.ts
index 07087e611..c827f2722 100644
--- a/app/src/layout/dock/Files.ts
+++ b/app/src/layout/dock/Files.ts
@@ -866,7 +866,7 @@ data-type="navigation-root" data-path="/">
}
window.siyuan.storage[Constants.LOCAL_FILESPATHS].forEach((item: IFilesPath) => {
item.openPaths.forEach((openPath) => {
- this.selectItem(item.notebookId, openPath, undefined, false);
+ this.selectItem(item.notebookId, openPath, undefined, false, false);
});
});
if (!init) {
@@ -1081,7 +1081,11 @@ data-type="navigation-root" data-path="/">
}, 2);
}
- private onLsSelect(data: { files: IFile[], box: string, path: string }, filePath: string, setStorage: boolean) {
+ private async onLsSelect(data: {
+ files: IFile[],
+ box: string,
+ path: string
+ }, filePath: string, setStorage: boolean, isSetCurrent: boolean) {
let fileHTML = "";
data.files.forEach((item: IFile) => {
fileHTML += this.genFileHTML(item);
@@ -1102,28 +1106,30 @@ data-type="navigation-root" data-path="/">
emojiElement.textContent = unicode2Emoji(window.siyuan.storage[Constants.LOCAL_IMAGES].folder);
}
liElement.insertAdjacentHTML("afterend", `
`);
- data.files.forEach((item: IFile) => {
+ let newLiElement;
+ for (let i = 0; i < data.files.length; i++) {
+ const item = data.files[i];
if (filePath === item.path) {
- this.selectItem(data.box, filePath, undefined, setStorage);
+ newLiElement = await this.selectItem(data.box, filePath, undefined, setStorage, isSetCurrent);
} else if (filePath.startsWith(item.path.replace(".sy", ""))) {
- fetchPost("/api/filetree/listDocsByPath", {
+ const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
notebook: data.box,
path: item.path
- }, response => {
- this.selectItem(response.data.box, filePath, response.data, setStorage);
});
+ newLiElement = await this.selectItem(response.data.box, filePath, response.data, setStorage, isSetCurrent);
}
- });
- if (setStorage) {
- this.setCurrent(this.element.querySelector(`ul[data-url="${data.box}"] li[data-path="${filePath}"]`));
}
+ if (isSetCurrent) {
+ this.setCurrent(newLiElement);
+ }
+ return newLiElement;
}
- private setCurrent(target: HTMLElement, isScroll = true) {
+ public setCurrent(target: HTMLElement, isScroll = true) {
if (!target) {
return;
}
- this.element.querySelectorAll("li").forEach((liItem) => {
+ this.element.querySelectorAll("li.b3-list-item--focus").forEach((liItem) => {
liItem.classList.remove("b3-list-item--focus");
});
target.classList.add("b3-list-item--focus");
@@ -1155,11 +1161,11 @@ data-type="navigation-root" data-path="/">
});
}
- public selectItem(notebookId: string, filePath: string, data?: {
+ public async selectItem(notebookId: string, filePath: string, data?: {
files: IFile[],
box: string,
path: string
- }, setStorage = true) {
+ }, setStorage = true, isSetCurrent = true) {
const treeElement = this.element.querySelector(`[data-url="${notebookId}"]`);
if (!treeElement) {
// 有文件树和编辑器的布局初始化时,文件树还未挂载
@@ -1181,24 +1187,24 @@ data-type="navigation-root" data-path="/">
if (liElement.getAttribute("data-path") === filePath) {
if (setStorage) {
- this.setCurrent(liElement);
this.getOpenPaths();
- } else {
- this.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
}
- return;
+ if (isSetCurrent) {
+ this.setCurrent(liElement);
+ }
+ return liElement;
}
if (data && data.path === currentPath) {
- this.onLsSelect(data, filePath, setStorage);
+ liElement = await this.onLsSelect(data, filePath, setStorage, isSetCurrent);
} else {
- fetchPost("/api/filetree/listDocsByPath", {
+ const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
notebook: notebookId,
path: currentPath
- }, response => {
- this.onLsSelect(response.data, filePath, setStorage);
});
+ liElement = await this.onLsSelect(response.data, filePath, setStorage, isSetCurrent);
}
+ return liElement;
}
private getOpenPaths() {
diff --git a/app/src/mobile/dock/MobileFiles.ts b/app/src/mobile/dock/MobileFiles.ts
index 0dda14d00..ebc05ec5f 100644
--- a/app/src/mobile/dock/MobileFiles.ts
+++ b/app/src/mobile/dock/MobileFiles.ts
@@ -5,7 +5,7 @@ import {Constants} from "../../constants";
import {getDisplayName, pathPosix, setNoteBook} from "../../util/pathName";
import {initFileMenu, initNavigationMenu, sortMenu} from "../../menus/navigation";
import {showMessage} from "../../dialog/message";
-import {fetchPost} from "../../util/fetch";
+import {fetchPost, fetchSyncPost} from "../../util/fetch";
import {genUUID} from "../../util/genID";
import {openMobileFileById} from "../editor";
import {unicode2Emoji} from "../../emoji";
@@ -361,7 +361,7 @@ export class MobileFiles extends Model {
}
window.siyuan.storage[Constants.LOCAL_FILESPATHS].forEach((item: IFilesPath) => {
item.openPaths.forEach((openPath) => {
- this.selectItem(item.notebookId, openPath, undefined, false);
+ this.selectItem(item.notebookId, openPath, undefined, false, false);
});
});
if (!init) {
@@ -577,20 +577,14 @@ export class MobileFiles extends Model {
}, 2);
}
- private onLsSelect(data: { files: IFile[], box: string, path: string }, filePath: string, setStorage: boolean) {
+ private async onLsSelect(data: {
+ files: IFile[],
+ box: string,
+ path: string
+ }, filePath: string, setStorage: boolean, isSetCurrent: boolean) {
let fileHTML = "";
data.files.forEach((item: IFile) => {
fileHTML += this.genFileHTML(item);
- if (filePath === item.path) {
- this.selectItem(data.box, filePath, undefined, setStorage);
- } else if (filePath.startsWith(item.path.replace(".sy", ""))) {
- fetchPost("/api/filetree/listDocsByPath", {
- notebook: data.box,
- path: item.path
- }, response => {
- this.selectItem(response.data.box, filePath, response.data, setStorage);
- });
- }
});
if (fileHTML === "") {
return;
@@ -600,26 +594,45 @@ export class MobileFiles extends Model {
// 文件展开时,刷新
liElement.nextElementSibling.remove();
}
- liElement.querySelector(".b3-list-item__arrow").classList.add("b3-list-item__arrow--open");
- liElement.insertAdjacentHTML("afterend", ``);
- if (setStorage) {
- this.setCurrent(this.element.querySelector(`ul[data-url="${data.box}"] li[data-path="${filePath}"]`));
+ const arrowElement = liElement.querySelector(".b3-list-item__arrow");
+ arrowElement.classList.add("b3-list-item__arrow--open");
+ arrowElement.parentElement.classList.remove("fn__hidden");
+ const emojiElement = liElement.querySelector(".b3-list-item__icon");
+ if (emojiElement.textContent === unicode2Emoji(window.siyuan.storage[Constants.LOCAL_IMAGES].file)) {
+ emojiElement.textContent = unicode2Emoji(window.siyuan.storage[Constants.LOCAL_IMAGES].folder);
}
+ liElement.insertAdjacentHTML("afterend", ``);
+ let newLiElement;
+ for (let i = 0; i < data.files.length; i++) {
+ const item = data.files[i];
+ if (filePath === item.path) {
+ newLiElement = await this.selectItem(data.box, filePath, undefined, setStorage, isSetCurrent);
+ } else if (filePath.startsWith(item.path.replace(".sy", ""))) {
+ const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
+ notebook: data.box,
+ path: item.path
+ });
+ newLiElement = await this.selectItem(response.data.box, filePath, response.data, setStorage, isSetCurrent);
+ }
+ }
+ if (isSetCurrent) {
+ this.setCurrent(newLiElement);
+ }
+ return newLiElement;
}
- private setCurrent(target: HTMLElement) {
+ public setCurrent(target: HTMLElement, isScroll = true) {
if (!target) {
return;
}
- this.element.querySelectorAll("li").forEach((liItem) => {
+ this.element.querySelectorAll("li.b3-list-item--focus").forEach((liItem) => {
liItem.classList.remove("b3-list-item--focus");
});
target.classList.add("b3-list-item--focus");
- const titleHeight = this.actionsElement.clientHeight;
- if (target.offsetTop - titleHeight < this.element.scrollTop) {
- this.element.scrollTop = target.offsetTop - titleHeight;
- } else if (target.offsetTop - this.element.clientHeight - titleHeight + target.clientHeight > this.element.scrollTop) {
- this.element.scrollTop = target.offsetTop - this.element.clientHeight - titleHeight + target.clientHeight;
+
+ if (isScroll) {
+ const elementRect = this.element.getBoundingClientRect();
+ this.element.scrollTop = this.element.scrollTop + (target.getBoundingClientRect().top - (elementRect.top + elementRect.height / 2));
}
}
@@ -644,11 +657,11 @@ export class MobileFiles extends Model {
});
}
- public selectItem(notebookId: string, filePath: string, data?: {
+ public async selectItem(notebookId: string, filePath: string, data?: {
files: IFile[],
box: string,
path: string
- }, setStorage = true) {
+ }, setStorage = true, isSetCurrent = true) {
const treeElement = this.element.querySelector(`[data-url="${notebookId}"]`);
if (!treeElement) {
// 有文件树和编辑器的布局初始化时,文件树还未挂载
@@ -670,24 +683,24 @@ export class MobileFiles extends Model {
if (liElement.getAttribute("data-path") === filePath) {
if (setStorage) {
- this.setCurrent(liElement);
this.getOpenPaths();
- } else {
- this.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
}
- return;
+ if (isSetCurrent) {
+ this.setCurrent(liElement);
+ }
+ return liElement;
}
if (data && data.path === currentPath) {
- this.onLsSelect(data, filePath, setStorage);
+ liElement = await this.onLsSelect(data, filePath, setStorage, isSetCurrent);
} else {
- fetchPost("/api/filetree/listDocsByPath", {
+ const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
notebook: notebookId,
path: currentPath
- }, response => {
- this.onLsSelect(response.data, filePath, setStorage);
});
+ liElement = await this.onLsSelect(response.data, filePath, setStorage, isSetCurrent);
}
+ return liElement;
}
private getOpenPaths() {
diff --git a/app/src/plugin/API.ts b/app/src/plugin/API.ts
index afbd99870..c720c50f9 100644
--- a/app/src/plugin/API.ts
+++ b/app/src/plugin/API.ts
@@ -30,6 +30,7 @@ import {globalCommand} from "../boot/globalEvent/command/global";
import {exportLayout} from "../layout/util";
import {saveScroll} from "../protyle/scroll/saveScroll";
import {hasClosestByClassName} from "../protyle/util/hasClosest";
+import {Files} from "../layout/dock/Files";
let openTab;
let openWindow;
@@ -248,6 +249,43 @@ const getActiveEditor = (wndActive = true) => {
return editor;
};
+export const expandDocTree = async (options: {
+ id: string,
+ isSetCurrent?: boolean
+}) => {
+ let isNotebook = false;
+ window.siyuan.notebooks.find(item => {
+ if (options.id === item.id) {
+ isNotebook = true;
+ return true;
+ }
+ });
+ let liElement: HTMLElement;
+ let notebookId = options.id;
+ const file = getModelByDockType("file") as Files;
+ if (typeof options.isSetCurrent === "undefined") {
+ options.isSetCurrent = true;
+ }
+ if (isNotebook) {
+ liElement = file.element.querySelector(`.b3-list[data-url="${options.id}"]`).firstElementChild as HTMLElement;
+ } else {
+ const response = await fetchSyncPost("api/block/getBlockInfo", {id: options.id});
+ notebookId = response.data.box;
+ liElement = await file.selectItem(response.data.box, response.data.path, undefined, undefined, options.isSetCurrent);
+ }
+ if (!liElement) {
+ return;
+ }
+ if (options.isSetCurrent || typeof options.isSetCurrent === "undefined") {
+ file.setCurrent(liElement);
+ }
+ const toggleElement = liElement.querySelector(".b3-list-item__arrow");
+ if (toggleElement.classList.contains("b3-list-item__arrow--open")) {
+ return;
+ }
+ file.getLeaf(liElement, notebookId);
+};
+
export const API = {
adaptHotkey: updateHotkeyTip,
confirm: confirmDialog,
@@ -281,4 +319,5 @@ export const API = {
openAttributePanel,
saveLayout,
globalCommand,
+ expandDocTree
};