1- import { getIdFromSYProtocol , isLocalPath , isSYProtocol , pathPosix } from "../util/pathName" ;
1+ import { isLocalPath , isSiYuanUriProtocol , parseSiYuanUriBlockInfo , pathPosix } from "../util/pathName" ;
22/// #if !BROWSER
33import { shell , ipcRenderer } from "electron" ;
44/// #endif
@@ -8,63 +8,19 @@ import {Constants} from "../constants";
88import { openAsset , openBy , openFile , openFileById } from "./util" ;
99/// #endif
1010import { showMessage } from "../dialog/message" ;
11- import { openByMobile } from "../protyle/util/compatibility" ;
12- import { App } from "../index" ;
11+ import { isInIOS , isInAndroid , isInHarmony } from "../protyle/util/compatibility" ;
1312import { fetchPost } from "../util/fetch" ;
1413import { checkFold } from "../util/noRelyPCFunction" ;
1514import { openMobileFileById } from "../mobile/editor" ;
1615
17- export const processSYLink = ( app : App , url : string ) => {
18- let urlObj : URL ;
19- try {
20- urlObj = new URL ( url ) ;
21- if ( urlObj . protocol !== "siyuan:" ) {
22- return false ;
23- }
24- } catch ( error ) {
25- return false ;
26- }
27- if ( urlObj && urlObj . hostname === "plugins" ) {
28- const pluginNameType = urlObj . pathname . split ( "/" ) [ 1 ] ;
29- if ( ! pluginNameType ) {
30- return false ;
31- }
32- app . plugins . find ( plugin => {
33- if ( pluginNameType . startsWith ( plugin . name ) ) {
34- // siyuan://plugins/plugin-name/foo?bar=baz
35- plugin . eventBus . emit ( "open-siyuan-url-plugin" , { url} ) ;
16+ import type { App } from "../index" ;
3617
37- /// #if !MOBILE
38- // https://github.com/siyuan-note/siyuan/pull/9256
39- if ( pluginNameType . split ( "/" ) [ 0 ] !== plugin . name ) {
40- // siyuan://plugins/plugin-samplecustom_tab?title=自定义页签&icon=iconFace&data={"text": "This is the custom plugin tab I opened via protocol."}
41- let data = urlObj . searchParams . get ( "data" ) ;
42- try {
43- data = JSON . parse ( data || "{}" ) ;
44- } catch ( e ) {
45- console . log ( "Error open plugin tab with protocol:" , e ) ;
46- }
47- openFile ( {
48- app,
49- custom : {
50- title : urlObj . searchParams . get ( "title" ) ,
51- icon : urlObj . searchParams . get ( "icon" ) ,
52- data,
53- id : pluginNameType
54- } ,
55- } ) ;
56- }
57- /// #endif
58- return true ;
59- }
60- } ) ;
61- return true ;
62- }
63- if ( urlObj && isSYProtocol ( url ) ) {
64- const id = getIdFromSYProtocol ( url ) ;
65- const focus = urlObj . searchParams . get ( "focus" ) === "1" ;
66- window . siyuan . editorIsFullscreen = urlObj . searchParams . get ( "fullscreen" ) === "1" ;
67- fetchPost ( "/api/block/checkBlockExist" , { id} , existResponse => {
18+ export const processSiYuanUriBlocks = ( app : App , uriObj : URL ) : boolean => {
19+ const blockInfo = parseSiYuanUriBlockInfo ( uriObj ) ;
20+ if ( blockInfo != null ) {
21+ const { id, focus} = blockInfo ;
22+ window . siyuan . editorIsFullscreen = blockInfo . fullscreen ;
23+ fetchPost ( "/api/block/checkBlockExist" , { id } , existResponse => {
6824 if ( existResponse . data ) {
6925 checkFold ( id , ( zoomIn ) => {
7026 /// #if !MOBILE
@@ -84,7 +40,7 @@ export const processSYLink = (app: App, url: string) => {
8440 }
8541 app . plugins . forEach ( plugin => {
8642 plugin . eventBus . emit ( "open-siyuan-url-block" , {
87- url,
43+ url : uriObj . href ,
8844 id,
8945 focus,
9046 exist : existResponse . data ,
@@ -96,6 +52,75 @@ export const processSYLink = (app: App, url: string) => {
9652 return false ;
9753} ;
9854
55+ export const processSiYuanUriPlugins = ( app : App , uriObj : URL ) : boolean => {
56+ const pluginNameOrTabType : string | null = ( ( ) => {
57+ const name = uriObj . pathname . split ( "/" ) [ 1 ] ;
58+ if ( ! name ) {
59+ return null ;
60+ }
61+ try {
62+ return decodeURIComponent ( name ) ;
63+ } catch ( error ) {
64+ return null ;
65+ }
66+ } ) ( ) ;
67+
68+ if ( ! pluginNameOrTabType ) {
69+ return false ;
70+ }
71+
72+ const plugin = app . plugins . find ( plugin => pluginNameOrTabType === plugin . name ) ;
73+ if ( plugin ) {
74+ // siyuan://plugins/plugin-name/foo?bar=baz
75+ plugin . eventBus . emit ( "open-siyuan-url-plugin" , { url : uriObj . href } ) ;
76+ } else {
77+ // siyuan://plugins/plugin-samplecustom_tab?title=自定义页签&icon=iconFace&data={"text": "This is the custom plugin tab I opened via protocol."}
78+ /// #if !MOBILE
79+ // https://github.com/siyuan-note/siyuan/pull/9256
80+ const data = ( ( ) => {
81+ try {
82+ return JSON . parse ( uriObj . searchParams . get ( "data" ) || "{}" ) ;
83+ } catch ( e ) {
84+ console . log ( "Error open plugin tab with protocol:" , e ) ;
85+ return undefined ;
86+ }
87+ } ) ( ) ;
88+ // id 不存在时无副作用
89+ openFile ( {
90+ app,
91+ custom : {
92+ title : uriObj . searchParams . get ( "title" ) ?? pluginNameOrTabType ,
93+ icon : uriObj . searchParams . get ( "icon" ) ?? "iconPlugin" ,
94+ data,
95+ id : pluginNameOrTabType
96+ } ,
97+ } ) ;
98+ /// #endif
99+ }
100+ return true ;
101+ } ;
102+
103+ export const processSiYuanUri = ( app : App , uri : string ) => {
104+ let uriObj : URL ;
105+ try {
106+ uriObj = new URL ( uri ) ;
107+ if ( ! isSiYuanUriProtocol ( uriObj ) ) {
108+ return false ;
109+ }
110+ } catch ( error ) {
111+ return false ;
112+ }
113+ switch ( uriObj . hostname ) {
114+ case "blocks" :
115+ return processSiYuanUriBlocks ( app , uriObj ) ;
116+ case "plugins" :
117+ return processSiYuanUriPlugins ( app , uriObj ) ;
118+ default :
119+ break ;
120+ }
121+ return false ;
122+ } ;
123+
99124export const openLink = ( protyle : IProtyle , aLink : string , event ?: MouseEvent , ctrlIsPressed = false ) => {
100125 let linkAddress = Lute . UnEscapeHTMLStr ( aLink ) ;
101126 let pdfParams ;
@@ -164,3 +189,36 @@ export const openLink = (protyle: IProtyle, aLink: string, event?: MouseEvent, c
164189 }
165190 /// #endif
166191} ;
192+
193+ export const openByMobile = ( uri : string ) => {
194+ if ( ! uri ) {
195+ return ;
196+ }
197+ /// #if MOBILE
198+ if ( processSiYuanUri ( window . siyuan . ws . app , uri ) ) {
199+ return ;
200+ }
201+ /// #endif
202+ if ( isInIOS ( ) ) {
203+ if ( uri . startsWith ( "assets/" ) ) {
204+ // iOS 16.7 之前的版本,uri 需要 encodeURIComponent
205+ window . webkit . messageHandlers . openLink . postMessage ( location . origin + "/assets/" + encodeURIComponent ( uri . replace ( "assets/" , "" ) ) ) ;
206+ } else if ( uri . startsWith ( "/" ) ) {
207+ // 导出 zip 返回的是已经 encode 过的,因此不能再 encode
208+ window . webkit . messageHandlers . openLink . postMessage ( location . origin + uri ) ;
209+ } else {
210+ try {
211+ new URL ( uri ) ;
212+ window . webkit . messageHandlers . openLink . postMessage ( uri ) ;
213+ } catch ( e ) {
214+ window . webkit . messageHandlers . openLink . postMessage ( "https://" + uri ) ;
215+ }
216+ }
217+ } else if ( isInAndroid ( ) ) {
218+ window . JSAndroid . openExternal ( uri ) ;
219+ } else if ( isInHarmony ( ) ) {
220+ window . JSHarmony . openExternal ( uri ) ;
221+ } else {
222+ window . open ( uri ) ;
223+ }
224+ } ;
0 commit comments