wovvmap-webview-bridge 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +213 -180
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,180 +1,213 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
| { type: "event"; key: "
|
|
102
|
-
| { type: "event"; key: "
|
|
103
|
-
| { type: "event"; key: "
|
|
104
|
-
| { type: "event"; key: "
|
|
105
|
-
| { type: "event"; key: "
|
|
106
|
-
| {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
type
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
1
|
+
|
|
2
|
+
# React Native WebView Bridge
|
|
3
|
+
|
|
4
|
+
A tiny bridge layer to communicate between a React Native app (using `react-native-webview`) and a web page. It provides:
|
|
5
|
+
|
|
6
|
+
- A ready-to-use `<WebViewScreen />` wrapper
|
|
7
|
+
- A simple `sendToWeb(...)` API for posting messages to the webview
|
|
8
|
+
- Typed event handling for messages coming **from** the web page
|
|
9
|
+
- Lightweight in-app state storage (via `koshin`) to keep UI in sync with bridge events
|
|
10
|
+
|
|
11
|
+
> **Demo idea:** Your message referenced a Snack example. You can adapt this package to the same flow as in your Snack: https://snack.expo.dev/@krushnkant/react-native-webview
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# with npm
|
|
19
|
+
npm i react-native-webview
|
|
20
|
+
|
|
21
|
+
# or with yarn
|
|
22
|
+
yarn add react-native-webview
|
|
23
|
+
|
|
24
|
+
# or with pnpm
|
|
25
|
+
pnpm add react-native-webview
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
1) **Render the WebView and hook the bridge handler**
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import React from "react";
|
|
36
|
+
import { WebViewScreen } from "<your-package-name>";
|
|
37
|
+
// If you want to register custom event callbacks:
|
|
38
|
+
import { registerBridgeHandler } from "<your-package-name>";
|
|
39
|
+
|
|
40
|
+
export default function App() {
|
|
41
|
+
React.useEffect(() => {
|
|
42
|
+
// Optional handlers for clicks coming from the web scene
|
|
43
|
+
registerBridgeHandler("isSceneClick", (evt) => {
|
|
44
|
+
console.log("Scene clicked:", evt);
|
|
45
|
+
});
|
|
46
|
+
registerBridgeHandler("isShapClick", (evt) => {
|
|
47
|
+
console.log("Shape clicked:", evt.value);
|
|
48
|
+
});
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
return <WebViewScreen url={"https://your-web-app.example.com"} />;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Under the hood, `<WebViewScreen />` wires `onMessage` to the bridge message handler so any `postMessage(...)` coming from your web page is typed and routed correctly. fileciteturn1file6
|
|
56
|
+
|
|
57
|
+
2) **Send commands *to* the web app**
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import {
|
|
61
|
+
sendActiveFloorToBridge,
|
|
62
|
+
sendEndPointToBridge,
|
|
63
|
+
sendPathFinishBtnClick,
|
|
64
|
+
sendPathNextBtnClick,
|
|
65
|
+
sendPathPreBtnClick,
|
|
66
|
+
sendStartPointToBridge,
|
|
67
|
+
} from "<your-package-name>";
|
|
68
|
+
|
|
69
|
+
// examples:
|
|
70
|
+
sendStartPointToBridge("node_123");
|
|
71
|
+
sendEndPointToBridge("node_999");
|
|
72
|
+
sendActiveFloorToBridge(2);
|
|
73
|
+
sendPathNextBtnClick();
|
|
74
|
+
sendPathPreBtnClick();
|
|
75
|
+
sendPathFinishBtnClick();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
These helpers call the shared `sendToWeb(...)` which posts a JSON-serialized message to the underlying `WebView` instance. fileciteturn1file1 fileciteturn1file7
|
|
79
|
+
|
|
80
|
+
3) **Keep UI in sync with bridge state (optional)**
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { bridgeStorage } from "<your-package-name>";
|
|
84
|
+
|
|
85
|
+
bridgeStorage.subscribe((state) => {
|
|
86
|
+
// state includes: isBridgeLoaded, isMapLoaded, searchablePoints, activeFloor, etc.
|
|
87
|
+
console.log(state);
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Internally this uses a small `koshin` store with fields like `isBridgeLoaded`, `isMapLoaded`, `searchablePoints`, `activeFloor`, `floorImages`, `stapByStapList`, and `nextPreState`. fileciteturn1file0
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## What the Web Page Should Send
|
|
96
|
+
|
|
97
|
+
Your web page (inside the WebView) should `postMessage(JSON.stringify(...))` with the following **Incoming** event shapes:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
type IncomingMessage =
|
|
101
|
+
| { type: "event"; key: "isConnection"; value: boolean; file: string }
|
|
102
|
+
| { type: "event"; key: "mapLoaded"; value: boolean; file: string }
|
|
103
|
+
| { type: "event"; key: "_searchablePoints"; value: NodePoint[]; file: string }
|
|
104
|
+
| { type: "event"; key: "Category"; value: Category[]; file: string }
|
|
105
|
+
| { type: "event"; key: "_activeFloor"; value: number; file: string }
|
|
106
|
+
| { type: "event"; key: "FloorImg"; value: FloorImage[]; file: string }
|
|
107
|
+
| { type: "event"; key: "isSceneClick"; file: string }
|
|
108
|
+
| { type: "event"; key: "isShapClick"; value: NodePoint; file: string }
|
|
109
|
+
| { type: "event"; key: "stapByStapList"; value: StepInstruction[]; file: string }
|
|
110
|
+
| { type: "event"; key: "pathNextPreState"; value: NavState; file: string };
|
|
111
|
+
```
|
|
112
|
+
The built-in handler parses the message, updates store fields, and triggers any registered callbacks for `isSceneClick` / `isShapClick`. fileciteturn1file3 fileciteturn1file2
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## What the App Sends to the Web Page
|
|
117
|
+
|
|
118
|
+
Outgoing commands you can dispatch from React Native:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
type OutgoingMessage =
|
|
122
|
+
| { type: "applyCSS"; selector: string; style: Partial<Record<string, string | number>> }
|
|
123
|
+
| { type: "event"; key: "ping"; value: boolean; file: string }
|
|
124
|
+
| { type: "event"; key: "setEndPoint"; value: string; file: string }
|
|
125
|
+
| { type: "event"; key: "setStartPoint"; value: string; file: string }
|
|
126
|
+
| { type: "event"; key: "setActiveFloor"; value: number; file: string }
|
|
127
|
+
| { type: "event"; key: "pathNextBtnClick"; file: string }
|
|
128
|
+
| { type: "event"; key: "pathPreBtnClick"; file: string }
|
|
129
|
+
| { type: "event"; key: "pathFinishBtnClick"; file: string };
|
|
130
|
+
```
|
|
131
|
+
These go through `sendToWeb(...)` which uses a shared `webviewRef` to `postMessage(...)`. fileciteturn1file7
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## API Reference
|
|
136
|
+
|
|
137
|
+
### Components
|
|
138
|
+
|
|
139
|
+
#### `<WebViewScreen />`
|
|
140
|
+
A thin wrapper around `react-native-webview` that plugs in the bridge message handler.
|
|
141
|
+
|
|
142
|
+
**Props**
|
|
143
|
+
- `url: string` – the URL to load inside the WebView.
|
|
144
|
+
|
|
145
|
+
fileciteturn1file6
|
|
146
|
+
|
|
147
|
+
### Functions
|
|
148
|
+
|
|
149
|
+
- `registerBridgeHandler(type, handler)` — Register a callback for `"isSceneClick"` or `"isShapClick"` events. fileciteturn1file3
|
|
150
|
+
- `sendStartPointToBridge(pointId)` — Ask web map to set the start point. fileciteturn1file1
|
|
151
|
+
- `sendEndPointToBridge(pointId)` — Ask web map to set the end point. fileciteturn1file1
|
|
152
|
+
- `sendActiveFloorToBridge(floorIndex)` — Switch active floor on the web map. fileciteturn1file1
|
|
153
|
+
- `sendPathNextBtnClick()` / `sendPathPreBtnClick()` / `sendPathFinishBtnClick()` — Control path stepper on the web map. fileciteturn1file1
|
|
154
|
+
- `bridgeStorage` — Reactive store with connection and navigation-related state. fileciteturn1file0
|
|
155
|
+
|
|
156
|
+
### Types (partial)
|
|
157
|
+
- `NodePoint`, `Category`, `FloorImage`, `StepInstruction`, `NavState`, `IncomingMessage`, `OutgoingMessage` — TypeScript contracts shared across the bridge. fileciteturn1file5
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Minimal Web Side (Example)
|
|
162
|
+
|
|
163
|
+
Your web app should listen for messages and respond via `window.ReactNativeWebView.postMessage(...)`:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
// inside the web page
|
|
167
|
+
window.addEventListener("message", (e) => {
|
|
168
|
+
try {
|
|
169
|
+
const msg = JSON.parse(e.data);
|
|
170
|
+
if (msg.type === "event" && msg.key === "setActiveFloor") {
|
|
171
|
+
// do something in the web app
|
|
172
|
+
console.log("Active floor requested:", msg.value);
|
|
173
|
+
// notify RN app that web is connected
|
|
174
|
+
window.ReactNativeWebView?.postMessage(JSON.stringify({
|
|
175
|
+
type: "event",
|
|
176
|
+
key: "isConnection",
|
|
177
|
+
value: true,
|
|
178
|
+
file: "web-app",
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
} catch {}
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Project Structure (Library)
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
src/
|
|
191
|
+
├─ index.ts # package exports fileciteturn1file4
|
|
192
|
+
├─ handlers/WebBridgeHandlers # incoming event router & registration fileciteturn1file3
|
|
193
|
+
├─ webviewBridge/WebViewBridgeRef.ts # shared ref + sendToWeb fileciteturn1file7
|
|
194
|
+
├─ webviewBridge/BridgeService.ts # convenience sending helpers fileciteturn1file1
|
|
195
|
+
├─ webviewBridge/BridgeStorage.ts # tiny state store (koshin) fileciteturn1file0
|
|
196
|
+
├─ webviewBridge/WebViewScreen.tsx # ready-to-use WebView wrapper fileciteturn1file6
|
|
197
|
+
├─ types/types.ts # shared TS contracts fileciteturn1file5
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Requirements
|
|
203
|
+
|
|
204
|
+
- React Native
|
|
205
|
+
- [`react-native-webview`](https://github.com/react-native-webview/react-native-webview)
|
|
206
|
+
- [`koshin`](https://www.npmjs.com/package/koshin)
|
|
207
|
+
- TypeScript recommended
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
MIT © Your Name
|