Vanessa 2025-11-29 11:17:58 +08:00
parent 9f0eaa6a0b
commit cad7d48320
6 changed files with 87 additions and 66 deletions

View file

@ -3,21 +3,20 @@ import * as path from "path";
/// #endif /// #endif
import {matchHotKey} from "../../protyle/util/hotKey"; import {matchHotKey} from "../../protyle/util/hotKey";
import {fetchPost} from "../../util/fetch"; import {fetchPost} from "../../util/fetch";
import {openFileById} from "../../editor/util";
import {Constants} from "../../constants"; import {Constants} from "../../constants";
import {newFileByName} from "../../util/newFile"; import {newFileByName} from "../../util/newFile";
import {App} from "../../index"; import {App} from "../../index";
import {Dialog} from "../../dialog"; import {Dialog} from "../../dialog";
import {getAllModels} from "../../layout/getAll"; import {getAllModels} from "../../layout/getAll";
import {hasClosestByClassName} from "../../protyle/util/hasClosest"; import {hasClosestByClassName} from "../../protyle/util/hasClosest";
import {getArticle, inputEvent, replace} from "../../search/util"; import {getArticle, inputEvent, openSearchEditor, replace} from "../../search/util";
import {useShell} from "../../util/pathName"; import {useShell} from "../../util/pathName";
import {assetInputEvent, renderPreview} from "../../search/assets"; import {assetInputEvent, renderPreview} from "../../search/assets";
import {initSearchMenu} from "../../menus/search"; import {initSearchMenu} from "../../menus/search";
import {writeText} from "../../protyle/util/compatibility"; import {writeText} from "../../protyle/util/compatibility";
import {checkFold} from "../../util/noRelyPCFunction";
import {getUnRefList} from "../../search/unRef"; import {getUnRefList} from "../../search/unRef";
import {toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "../../search/toggleHistory"; import {toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "../../search/toggleHistory";
import {Protyle} from "../../protyle";
export const searchKeydown = (app: App, event: KeyboardEvent) => { export const searchKeydown = (app: App, event: KeyboardEvent) => {
if (getSelection().rangeCount === 0) { if (getSelection().rangeCount === 0) {
@ -29,7 +28,7 @@ export const searchKeydown = (app: App, event: KeyboardEvent) => {
} }
let element: HTMLElement; let element: HTMLElement;
let dialog: Dialog; let dialog: Dialog;
let edit; let edit: Protyle;
let unRefEdit; let unRefEdit;
let config: Config.IUILayoutTabSearchConfig; let config: Config.IUILayoutTabSearchConfig;
window.siyuan.dialogs.find((item) => { window.siyuan.dialogs.find((item) => {
@ -98,20 +97,15 @@ export const searchKeydown = (app: App, event: KeyboardEvent) => {
} }
if (searchType !== "asset") { if (searchType !== "asset") {
if (matchHotKey(window.siyuan.config.keymap.editor.general.insertRight.custom, event)) { if (matchHotKey(window.siyuan.config.keymap.editor.general.insertRight.custom, event)) {
const id = currentList.getAttribute("data-node-id"); openSearchEditor({
checkFold(id, (zoomIn) => { protyle: edit.protyle,
openFileById({ id: currentList.getAttribute("data-node-id"),
app, cb: () => {
id, if (dialog) {
position: "right", dialog.destroy({focus: "false"});
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] : }
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL], },
zoomIn, openPosition: "right",
scrollPosition: "center"
});
if (dialog) {
dialog.destroy({focus: "false"});
}
}); });
return true; return true;
} }
@ -222,19 +216,14 @@ export const searchKeydown = (app: App, event: KeyboardEvent) => {
if (targetId === "replaceInput") { if (targetId === "replaceInput") {
replace(element, config, edit, false); replace(element, config, edit, false);
} else { } else {
const id = currentList.getAttribute("data-node-id"); openSearchEditor({
checkFold(id, (zoomIn) => { protyle: edit.protyle,
openFileById({ id: currentList.getAttribute("data-node-id"),
app, cb: () => {
id, if (dialog) {
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] : dialog.destroy({focus: "false"});
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL], }
zoomIn, },
scrollPosition: "center"
});
if (dialog) {
dialog.destroy({focus: "false"});
}
}); });
} }
} else { } else {

View file

@ -130,6 +130,7 @@ export abstract class Constants {
public static readonly CB_GET_BACKLINK = "cb-get-backlink"; // 悬浮窗为传递型需展示上下文 public static readonly CB_GET_BACKLINK = "cb-get-backlink"; // 悬浮窗为传递型需展示上下文
public static readonly CB_GET_UNUNDO = "cb-get-unundo"; // 不需要记录历史 public static readonly CB_GET_UNUNDO = "cb-get-unundo"; // 不需要记录历史
public static readonly CB_GET_SCROLL = "cb-get-scroll"; // 滚动到指定位置,用于直接打开文档,必有 rootID public static readonly CB_GET_SCROLL = "cb-get-scroll"; // 滚动到指定位置,用于直接打开文档,必有 rootID
public static readonly CB_GET_SEARCH = "cb-get-search"; // 通过搜索打开
public static readonly CB_GET_CONTEXT = "cb-get-context"; // 包含上下文 public static readonly CB_GET_CONTEXT = "cb-get-context"; // 包含上下文
public static readonly CB_GET_ROOTSCROLL = "cb-get-rootscroll"; // 如果为 rootID 就滚动到指定位置,必有 rootID public static readonly CB_GET_ROOTSCROLL = "cb-get-rootscroll"; // 如果为 rootID 就滚动到指定位置,必有 rootID
public static readonly CB_GET_HTML = "cb-get-html"; // 直接渲染,不需要再 /api/block/getDocInfo否则搜索表格无法定位 public static readonly CB_GET_HTML = "cb-get-html"; // 直接渲染,不需要再 /api/block/getDocInfo否则搜索表格无法定位

View file

@ -10,7 +10,7 @@ import {Constants} from "../constants";
import {setEditMode} from "../protyle/util/setEditMode"; import {setEditMode} from "../protyle/util/setEditMode";
import {Files} from "../layout/dock/Files"; import {Files} from "../layout/dock/Files";
import {fetchPost, fetchSyncPost} from "../util/fetch"; import {fetchPost, fetchSyncPost} from "../util/fetch";
import {focusBlock, focusByRange} from "../protyle/util/selection"; import {focusBlock, focusByOffset, focusByRange} from "../protyle/util/selection";
import {onGet} from "../protyle/util/onGet"; import {onGet} from "../protyle/util/onGet";
/// #if !BROWSER /// #if !BROWSER
import {ipcRenderer} from "electron"; import {ipcRenderer} from "electron";
@ -398,9 +398,14 @@ const switchEditor = (editor: Editor, options: IOpenFileOptions, allModels: IMod
} }
if (options.action?.includes(Constants.CB_GET_FOCUS)) { if (options.action?.includes(Constants.CB_GET_FOCUS)) {
if (nodeElement) { if (nodeElement) {
const newRange = focusBlock(nodeElement, undefined, !options.action?.includes(Constants.CB_GET_OUTLINE)); if (options.action.includes(Constants.CB_GET_SEARCH)) {
if (newRange) { const scrollAttr = window.siyuan.storage[Constants.LOCAL_FILEPOSITION][editor.editor.protyle.block.rootID];
editor.editor.protyle.toolbar.range = newRange; focusByOffset(nodeElement, scrollAttr.focusStart, scrollAttr.focusEnd);
} else {
const newRange = focusBlock(nodeElement, undefined, !options.action?.includes(Constants.CB_GET_OUTLINE));
if (newRange) {
editor.editor.protyle.toolbar.range = newRange;
}
} }
scrollCenter(editor.editor.protyle, (editor.editor.protyle.disabled || options.scrollPosition) ? nodeElement : null, options.scrollPosition); scrollCenter(editor.editor.protyle, (editor.editor.protyle.disabled || options.scrollPosition) ? nodeElement : null, options.scrollPosition);
editor.editor.protyle.observerLoad = new ResizeObserver(() => { editor.editor.protyle.observerLoad = new ResizeObserver(() => {

View file

@ -85,6 +85,7 @@ export const getDocByScroll = (options: {
highlight: !isSupportCSSHL(), highlight: !isSupportCSSHL(),
}, response => { }, response => {
onGet({ onGet({
scrollPosition: options.mergedOptions.scrollPosition,
data: response, data: response,
protyle: options.protyle, protyle: options.protyle,
action: actions, action: actions,
@ -98,6 +99,7 @@ export const getDocByScroll = (options: {
} else { } else {
actions.push(Constants.CB_GET_ALL); actions.push(Constants.CB_GET_ALL);
onGet({ onGet({
scrollPosition: options.mergedOptions.scrollPosition,
data: response, data: response,
protyle: options.protyle, protyle: options.protyle,
action: actions, action: actions,
@ -121,6 +123,7 @@ export const getDocByScroll = (options: {
highlight: !isSupportCSSHL(), highlight: !isSupportCSSHL(),
}, response => { }, response => {
onGet({ onGet({
scrollPosition: options.mergedOptions.scrollPosition,
data: response, data: response,
protyle: options.protyle, protyle: options.protyle,
action: actions, action: actions,

View file

@ -15,7 +15,7 @@ import {onGet} from "../protyle/util/onGet";
import {addLoading} from "../protyle/ui/initUI"; import {addLoading} from "../protyle/ui/initUI";
import {getIconByType} from "../editor/getIcon"; import {getIconByType} from "../editor/getIcon";
import {unicode2Emoji} from "../emoji"; import {unicode2Emoji} from "../emoji";
import {hasClosestByClassName, hasClosestByTag} from "../protyle/util/hasClosest"; import {hasClosestBlock, hasClosestByClassName, hasClosestByTag} from "../protyle/util/hasClosest";
import {isIPad, isNotCtrl, setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility"; import {isIPad, isNotCtrl, setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility";
import {newFileByName} from "../util/newFile"; import {newFileByName} from "../util/newFile";
import { import {
@ -45,6 +45,7 @@ import {getDefaultType} from "./getDefault";
import {isSupportCSSHL, searchMarkRender} from "../protyle/render/searchMarkRender"; import {isSupportCSSHL, searchMarkRender} from "../protyle/render/searchMarkRender";
import {saveKeyList, toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "./toggleHistory"; import {saveKeyList, toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "./toggleHistory";
import {highlightById} from "../util/highlightById"; import {highlightById} from "../util/highlightById";
import {getSelectionOffset} from "../protyle/util/selection";
export const openGlobalSearch = (app: App, text: string, replace: boolean, searchData?: Config.IUILayoutTabSearchConfig) => { export const openGlobalSearch = (app: App, text: string, replace: boolean, searchData?: Config.IUILayoutTabSearchConfig) => {
text = text.trim(); text = text.trim();
@ -814,20 +815,11 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
} }
} else { } else {
if (event.altKey) { if (event.altKey) {
const id = target.getAttribute("data-node-id"); openSearchEditor({
checkFold(id, (zoomIn) => { protyle: edit.protyle,
openFileById({ id: target.getAttribute("data-node-id"),
app, cb: closeCB,
id, openPosition: "right",
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] :
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL],
zoomIn,
position: "right",
scrollPosition: "center"
});
if (closeCB) {
closeCB();
}
}); });
} else if (!target.classList.contains("b3-list-item--focus")) { } else if (!target.classList.contains("b3-list-item--focus")) {
(searchType === "doc" ? searchPanelElement : unRefPanelElement).querySelector(".b3-list-item--focus").classList.remove("b3-list-item--focus"); (searchType === "doc" ? searchPanelElement : unRefPanelElement).querySelector(".b3-list-item--focus").classList.remove("b3-list-item--focus");
@ -856,19 +848,10 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
useShell("showItemInFolder", path.join(window.siyuan.config.system.dataDir, target.lastElementChild.getAttribute("aria-label"))); useShell("showItemInFolder", path.join(window.siyuan.config.system.dataDir, target.lastElementChild.getAttribute("aria-label")));
/// #endif /// #endif
} else { } else {
const id = target.getAttribute("data-node-id"); openSearchEditor({
checkFold(id, (zoomIn) => { protyle: edit.protyle,
openFileById({ id: target.getAttribute("data-node-id"),
app, cb: closeCB
id,
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] :
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL],
zoomIn,
scrollPosition: "center"
});
if (closeCB) {
closeCB();
}
}); });
} }
} }
@ -925,6 +908,45 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
return {edit, unRefEdit}; return {edit, unRefEdit};
}; };
export const openSearchEditor = (options: {
protyle: IProtyle,
openPosition?: string,
id?: string,
cb?: () => void
}) => {
const currentRange = options.protyle.highlight.ranges[options.protyle.highlight.rangeIndex];
if (currentRange) {
const rangeBlockElement = hasClosestBlock(currentRange.startContainer);
if (rangeBlockElement) {
options.id = rangeBlockElement.getAttribute("data-node-id");
const offset = getSelectionOffset(rangeBlockElement, null, options.protyle.highlight.ranges[options.protyle.highlight.rangeIndex]);
const scrollAttr: IScrollAttr = {
rootId: options.protyle.block.rootID,
focusId: options.id,
focusStart: offset.start,
focusEnd: offset.end,
zoomInId: options.protyle.block.showAll ? options.protyle.block.id : undefined
};
window.siyuan.storage[Constants.LOCAL_FILEPOSITION][options.protyle.block.rootID] = scrollAttr;
}
}
checkFold(options.id, (zoomIn) => {
openFileById({
app: options.protyle.app,
id:options.id,
action: currentRange ?
(zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_SCROLL, Constants.CB_GET_SEARCH] : [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_SCROLL, Constants.CB_GET_SEARCH]) :
(zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] : [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL]),
zoomIn,
position: options.openPosition,
scrollPosition: "center"
});
if (options.cb) {
options.cb();
}
});
};
export const genQueryHTML = (method: number, id: string) => { export const genQueryHTML = (method: number, id: string) => {
let methodTip = ""; let methodTip = "";
let methodIcon = ""; let methodIcon = "";

View file

@ -34,6 +34,7 @@ type TProtyleAction = "cb-get-append" | // 向下滚动加载
"cb-get-backlink" | // 悬浮窗为传递型需展示上下文 "cb-get-backlink" | // 悬浮窗为传递型需展示上下文
"cb-get-unundo" | // 不需要记录历史 "cb-get-unundo" | // 不需要记录历史
"cb-get-scroll" | // 滚动到指定位置,用于直接打开文档,必有 rootID "cb-get-scroll" | // 滚动到指定位置,用于直接打开文档,必有 rootID
"cb-get-search" | // 使用搜索打开搜索
"cb-get-context" | // 包含上下文 "cb-get-context" | // 包含上下文
"cb-get-rootscroll" | // 如果为 rootID 就滚动到指定位置,必有 rootID "cb-get-rootscroll" | // 如果为 rootID 就滚动到指定位置,必有 rootID
"cb-get-html" | // 直接渲染,不需要再 /api/block/getDocInfo否则搜索表格无法定位 "cb-get-html" | // 直接渲染,不需要再 /api/block/getDocInfo否则搜索表格无法定位
@ -343,9 +344,9 @@ interface IUpload {
interface IScrollAttr { interface IScrollAttr {
rootId: string, rootId: string,
startId: string, startId?: string,
endId: string endId?: string
scrollTop: number, scrollTop?: number,
focusId?: string, focusId?: string,
focusStart?: number focusStart?: number
focusEnd?: number focusEnd?: number