mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 05:51:56 +08:00
Add: jsbridge supported
This commit is contained in:
parent
6d90543192
commit
9d5268107e
@ -9,7 +9,7 @@ module.exports = merge(commonConfig, {
|
||||
'react-hot-loader/patch', // activate HMR for React
|
||||
'webpack-dev-server/client?http://localhost:8080',// bundle the client for webpack-dev-server and connect to the provided endpoint
|
||||
'webpack/hot/only-dev-server', // bundle the client for hot reloading, only- means to only hot reload for successful updates
|
||||
'./index.tsx' // the entry point of our app
|
||||
'./index.ts' // the entry point of our app
|
||||
],
|
||||
devServer: {
|
||||
hot: true, // enable HMR on the server
|
||||
|
@ -6,7 +6,7 @@ const commonConfig = require('./common')
|
||||
|
||||
module.exports = merge(commonConfig, {
|
||||
mode: 'production',
|
||||
entry: './index.tsx',
|
||||
entry: './index.ts',
|
||||
output: {
|
||||
filename: 'js/bundle.[hash].min.js',
|
||||
path: resolve(__dirname, '../../dist'),
|
||||
|
12
src/index.ts
Normal file
12
src/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import renderApp from './render'
|
||||
import { isClashX, setupJsBridge } from './lib/jsBridge'
|
||||
|
||||
/**
|
||||
* Global entry
|
||||
* Will check if need setup jsbridge
|
||||
*/
|
||||
if (isClashX()) {
|
||||
setupJsBridge(renderApp)
|
||||
} else {
|
||||
renderApp()
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import { AppContainer } from 'react-hot-loader'
|
||||
import App from './components/App'
|
||||
|
||||
const rootEl = document.getElementById('root')
|
||||
|
||||
render(
|
||||
<AppContainer>
|
||||
<App />
|
||||
</AppContainer>,
|
||||
rootEl
|
||||
)
|
||||
|
||||
// Hot Module Replacement API
|
||||
declare let module: { hot: any }
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept('./components/App', () => {
|
||||
const NewApp = require('./components/App').default
|
||||
render(
|
||||
<AppContainer>
|
||||
<NewApp />
|
||||
</AppContainer>,
|
||||
rootEl
|
||||
)
|
||||
})
|
||||
}
|
91
src/lib/jsBridge.ts
Normal file
91
src/lib/jsBridge.ts
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* For support ClashX runtime
|
||||
*
|
||||
* Clash Dashboard will use jsbridge to
|
||||
* communicate with ClashX
|
||||
*
|
||||
* Before React app rendered, jsbridge
|
||||
* should be checked if initialized,
|
||||
* and also should checked if it's
|
||||
* ClashX runtime
|
||||
*
|
||||
* @author jas0ncn
|
||||
*/
|
||||
|
||||
/**
|
||||
* declare javascript bridge API
|
||||
*/
|
||||
export interface JsBridge {
|
||||
|
||||
/**
|
||||
* Register a javascript bridge event handle
|
||||
*/
|
||||
registerHandler: (eventName: string, callback: (data: any, responseCallback: (param: any) => void) => void) => void
|
||||
|
||||
/**
|
||||
* Call a native handle
|
||||
*/
|
||||
callHandler: (handleName: string, data: any, responseCallback: (responseData: any) => void) => void
|
||||
|
||||
/**
|
||||
* Who knows
|
||||
*/
|
||||
disableJavscriptAlertBoxSafetyTimeout: () => void
|
||||
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
interface Window {
|
||||
|
||||
/**
|
||||
* Global jsbridge instance
|
||||
*/
|
||||
WebViewJavascriptBridge?: JsBridge | null
|
||||
|
||||
/**
|
||||
* Global jsbridge init callback
|
||||
*/
|
||||
WVJBCallbacks?: Function[]
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* setup a jsbridge before app render
|
||||
* @param {Function} cb callback when jsbridge initialized
|
||||
* @see https://github.com/marcuswestin/WebViewJavascriptBridge
|
||||
*/
|
||||
export function setupJsBridge (callback = jsBridge => {}) {
|
||||
/**
|
||||
* You need check if inClashX first
|
||||
*/
|
||||
if (!isClashX()) {
|
||||
return callback(null)
|
||||
}
|
||||
|
||||
if (window.WebViewJavascriptBridge) {
|
||||
return callback(window.WebViewJavascriptBridge)
|
||||
}
|
||||
|
||||
// setup callback
|
||||
if (window.WVJBCallbacks) {
|
||||
return window.WVJBCallbacks.push(callback)
|
||||
}
|
||||
|
||||
window.WVJBCallbacks = [callback]
|
||||
|
||||
const WVJBIframe = document.createElement('iframe')
|
||||
WVJBIframe.style.display = 'none'
|
||||
WVJBIframe.src = 'https://__bridge_loaded__'
|
||||
document.documentElement.appendChild(WVJBIframe)
|
||||
setTimeout(() => document.documentElement.removeChild(WVJBIframe), 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if perched in ClashX Runtime
|
||||
*/
|
||||
export function isClashX () {
|
||||
return navigator.userAgent === 'ClashX Runtime'
|
||||
}
|
30
src/render.tsx
Normal file
30
src/render.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import * as React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import { AppContainer } from 'react-hot-loader'
|
||||
import App from './components/App'
|
||||
|
||||
const rootEl = document.getElementById('root')
|
||||
|
||||
// Hot Module Replacement API
|
||||
declare let module: { hot: any }
|
||||
|
||||
export default function renderApp () {
|
||||
render(
|
||||
<AppContainer>
|
||||
<App />
|
||||
</AppContainer>,
|
||||
rootEl
|
||||
)
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept('./components/App', () => {
|
||||
const NewApp = require('./components/App').default
|
||||
render(
|
||||
<AppContainer>
|
||||
<NewApp />
|
||||
</AppContainer>,
|
||||
rootEl
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
"sourceMap": true,
|
||||
"noImplicitAny": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"jsx": "react",
|
||||
|
@ -2,6 +2,7 @@
|
||||
"extends": "tslint-config-standard",
|
||||
"rules": {
|
||||
"indent": [true, "spaces", 4],
|
||||
"ter-indent": [true, 4]
|
||||
"ter-indent": [true, 4],
|
||||
"no-empty": false
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user