Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/src/boot/onGetConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {sendGlobalShortcut} from "./globalEvent/keydown";
import {closeWindow} from "../window/closeWin";
import {correctHotkey} from "./globalEvent/commonHotkey";
import {recordBeforeResizeTop} from "../protyle/util/resize";
import {processSYLink} from "../editor/openLink";
import {processSiYuanUri} from "../editor/openLink";
import {getAllEditor} from "../layout/getAll";

export const onGetConfig = (isStart: boolean, app: App) => {
Expand Down Expand Up @@ -172,7 +172,7 @@ export const initWindow = async (app: App) => {
});
if (!isWindow()) {
ipcRenderer.on(Constants.SIYUAN_OPEN_URL, (event, url) => {
processSYLink(app, url);
processSiYuanUri(app, url);
});
}
ipcRenderer.on(Constants.SIYUAN_OPEN_FILE, (event, data) => {
Expand Down
166 changes: 112 additions & 54 deletions app/src/editor/openLink.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getIdFromSYProtocol, isLocalPath, isSYProtocol, pathPosix} from "../util/pathName";
import {isLocalPath, isSiYuanUriProtocol, parseSiYuanUriBlockInfo, pathPosix} from "../util/pathName";
/// #if !BROWSER
import {shell, ipcRenderer} from "electron";
/// #endif
Expand All @@ -8,63 +8,19 @@ import {Constants} from "../constants";
import {openAsset, openBy, openFile, openFileById} from "./util";
/// #endif
import {showMessage} from "../dialog/message";
import {openByMobile} from "../protyle/util/compatibility";
import {App} from "../index";
import {isInIOS, isInAndroid, isInHarmony} from "../protyle/util/compatibility";
import {fetchPost} from "../util/fetch";
import {checkFold} from "../util/noRelyPCFunction";
import {openMobileFileById} from "../mobile/editor";

export const processSYLink = (app: App, url: string) => {
let urlObj: URL;
try {
urlObj = new URL(url);
if (urlObj.protocol !== "siyuan:") {
return false;
}
} catch (error) {
return false;
}
if (urlObj && urlObj.hostname === "plugins") {
const pluginNameType = urlObj.pathname.split("/")[1];
if (!pluginNameType) {
return false;
}
app.plugins.find(plugin => {
if (pluginNameType.startsWith(plugin.name)) {
// siyuan://plugins/plugin-name/foo?bar=baz
plugin.eventBus.emit("open-siyuan-url-plugin", {url});
import type {App} from "../index";

/// #if !MOBILE
// https://github.com/siyuan-note/siyuan/pull/9256
if (pluginNameType.split("/")[0] !== plugin.name) {
// siyuan://plugins/plugin-samplecustom_tab?title=自定义页签&icon=iconFace&data={"text": "This is the custom plugin tab I opened via protocol."}
let data = urlObj.searchParams.get("data");
try {
data = JSON.parse(data || "{}");
} catch (e) {
console.log("Error open plugin tab with protocol:", e);
}
openFile({
app,
custom: {
title: urlObj.searchParams.get("title"),
icon: urlObj.searchParams.get("icon"),
data,
id: pluginNameType
},
});
}
/// #endif
return true;
}
});
return true;
}
if (urlObj && isSYProtocol(url)) {
const id = getIdFromSYProtocol(url);
const focus = urlObj.searchParams.get("focus") === "1";
window.siyuan.editorIsFullscreen = urlObj.searchParams.get("fullscreen") === "1";
fetchPost("/api/block/checkBlockExist", {id}, existResponse => {
export const processSiYuanUriBlocks = (app: App, uriObj: URL): boolean => {
const blockInfo = parseSiYuanUriBlockInfo(uriObj);
if (blockInfo != null) {
const {id, focus} = blockInfo;
window.siyuan.editorIsFullscreen = blockInfo.fullscreen;
fetchPost("/api/block/checkBlockExist", { id }, existResponse => {
if (existResponse.data) {
checkFold(id, (zoomIn) => {
/// #if !MOBILE
Expand All @@ -84,7 +40,7 @@ export const processSYLink = (app: App, url: string) => {
}
app.plugins.forEach(plugin => {
plugin.eventBus.emit("open-siyuan-url-block", {
url,
url: uriObj.href,
id,
focus,
exist: existResponse.data,
Expand All @@ -96,6 +52,75 @@ export const processSYLink = (app: App, url: string) => {
return false;
};

export const processSiYuanUriPlugins = (app: App, uriObj: URL): boolean => {
const pluginNameOrTabType: string | null = (() => {
const name = uriObj.pathname.split("/")[1];
if (!name) {
return null;
}
try {
return decodeURIComponent(name);
} catch (error) {
return null;
}
})();

if (!pluginNameOrTabType) {
return false;
}

const plugin = app.plugins.find(plugin => pluginNameOrTabType === plugin.name);
if (plugin) {
// siyuan://plugins/plugin-name/foo?bar=baz
plugin.eventBus.emit("open-siyuan-url-plugin", { url: uriObj.href });
} else {
// siyuan://plugins/plugin-samplecustom_tab?title=自定义页签&icon=iconFace&data={"text": "This is the custom plugin tab I opened via protocol."}
/// #if !MOBILE
// https://github.com/siyuan-note/siyuan/pull/9256
const data = (() => {
try {
return JSON.parse(uriObj.searchParams.get("data") || "{}");
} catch (e) {
console.log("Error open plugin tab with protocol:", e);
return undefined;
}
})();
// id 不存在时无副作用
openFile({
app,
custom: {
title: uriObj.searchParams.get("title") ?? pluginNameOrTabType,
icon: uriObj.searchParams.get("icon") ?? "iconPlugin",
data,
id: pluginNameOrTabType
},
});
/// #endif
}
return true;
};

export const processSiYuanUri = (app: App, uri: string) => {
let uriObj: URL;
try {
uriObj = new URL(uri);
if (!isSiYuanUriProtocol(uriObj)) {
return false;
}
} catch (error) {
return false;
}
switch (uriObj.hostname) {
case "blocks":
return processSiYuanUriBlocks(app, uriObj);
case "plugins":
return processSiYuanUriPlugins(app, uriObj);
default:
break;
}
return false;
};

export const openLink = (protyle: IProtyle, aLink: string, event?: MouseEvent, ctrlIsPressed = false) => {
let linkAddress = Lute.UnEscapeHTMLStr(aLink);
let pdfParams;
Expand Down Expand Up @@ -164,3 +189,36 @@ export const openLink = (protyle: IProtyle, aLink: string, event?: MouseEvent, c
}
/// #endif
};

export const openByMobile = (uri: string) => {
if (!uri) {
return;
}
/// #if MOBILE
if (processSiYuanUri(window.siyuan.ws.app, uri)) {
return;
}
/// #endif
if (isInIOS()) {
if (uri.startsWith("assets/")) {
// iOS 16.7 之前的版本,uri 需要 encodeURIComponent
window.webkit.messageHandlers.openLink.postMessage(location.origin + "/assets/" + encodeURIComponent(uri.replace("assets/", "")));
} else if (uri.startsWith("/")) {
// 导出 zip 返回的是已经 encode 过的,因此不能再 encode
window.webkit.messageHandlers.openLink.postMessage(location.origin + uri);
} else {
try {
new URL(uri);
window.webkit.messageHandlers.openLink.postMessage(uri);
} catch (e) {
window.webkit.messageHandlers.openLink.postMessage("https://" + uri);
}
}
} else if (isInAndroid()) {
window.JSAndroid.openExternal(uri);
} else if (isInHarmony()) {
window.JSHarmony.openExternal(uri);
} else {
window.open(uri);
}
};
2 changes: 1 addition & 1 deletion app/src/menus/commonMenuItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import {
isInHarmony,
isInIOS,
isInMobileApp,
openByMobile,
saveExportFile,
writeText
} from "../protyle/util/compatibility";
import {openByMobile} from "../editor/openLink";
import {fetchPost, fetchSyncPost} from "../util/fetch";
import {hideMessage, showMessage} from "../dialog/message";
import {Dialog} from "../dialog";
Expand Down
2 changes: 1 addition & 1 deletion app/src/plugin/platformUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as compatibility from "../protyle/util/compatibility";
import {ipcRenderer} from "electron";
import {Constants} from "../constants";
/// #endif
export const openByMobile = compatibility.openByMobile;
export {openByMobile} from "../editor/openLink";
export const readText = compatibility.readText;
export const writeText = compatibility.writeText;
export const copyPlainText = compatibility.copyPlainText;
Expand Down
3 changes: 2 additions & 1 deletion app/src/protyle/preview/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {isOnlyMeta, openByMobile, writeText} from "../util/compatibility";
import {isOnlyMeta, writeText} from "../util/compatibility";
import {focusByRange} from "../util/selection";
import {openByMobile} from "../../editor/openLink";
import {showMessage} from "../../dialog/message";
import {isLocalPath, pathPosix} from "../../util/pathName";
import {previewDocImage} from "./image";
Expand Down
37 changes: 0 additions & 37 deletions app/src/protyle/util/compatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import {Constants} from "../../constants";
/// #if !BROWSER
import {ipcRenderer} from "electron";
/// #endif
/// #if MOBILE
import {processSYLink} from "../../editor/openLink";
/// #endif
import {getDefaultSubType, getDefaultType} from "../../search/getDefault";
import {hideMessage, showMessage} from "../../dialog/message";

Expand Down Expand Up @@ -66,39 +63,6 @@ export const getTextSiyuanFromTextHTML = (html: string) => {
};
};

export const openByMobile = (uri: string) => {
if (!uri) {
return;
}
/// #if MOBILE
if (processSYLink(window.siyuan.ws.app, uri)) {
return;
}
/// #endif
if (isInIOS()) {
if (uri.startsWith("assets/")) {
// iOS 16.7 之前的版本,uri 需要 encodeURIComponent
window.webkit.messageHandlers.openLink.postMessage(location.origin + "/assets/" + encodeURIComponent(uri.replace("assets/", "")));
} else if (uri.startsWith("/")) {
// 导出 zip 返回的是已经 encode 过的,因此不能再 encode
window.webkit.messageHandlers.openLink.postMessage(location.origin + uri);
} else {
try {
new URL(uri);
window.webkit.messageHandlers.openLink.postMessage(uri);
} catch (e) {
window.webkit.messageHandlers.openLink.postMessage("https://" + uri);
}
}
} else if (isInAndroid()) {
window.JSAndroid.openExternal(uri);
} else if (isInHarmony()) {
window.JSHarmony.openExternal(uri);
} else {
window.open(uri);
}
};

export const saveExportFile = async (uri: string, msgId?: string) => {
if (!uri) {
return;
Expand Down Expand Up @@ -696,4 +660,3 @@ export const initNativeDialogOverride = () => {
};
};
/// #endif

26 changes: 24 additions & 2 deletions app/src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1257,8 +1257,6 @@ interface IKernelPluginRpcError {
data?: any;
}



interface IKernelPluginRpc {
/**
* 通过 {@link Proxy} 实现的动态方法调用,插件开发者可以直接调用 `call.方法名(params)` 来调用内核插件暴露的方法,无需关心 JSON-RPC 的细节
Expand All @@ -1285,3 +1283,27 @@ interface IKernelPluginRpc {
*/
unbind: (method: TJsonRpcMethod, handler: TJsonRpcHandler<void>) => void;
}

/**
* SiYuan URI 块信息接口,用于描述通过 SiYuan URI 协议传递的块信息
*/
interface ISiYuanUriBlockInfo {
/**
* 块 ID
*/
id: string;

/**
* 是否聚焦该块
*
* @defaultValue false
*/
focus: boolean;

/**
* 是否全屏显示该块
*
* @defaultValue false
*/
fullscreen: boolean;
}
Loading