mirror of
https://github.com/hectorqin/reader.git
synced 2026-11-12 14:01:00 +08:00
81 lines
2.8 KiB
Markdown
81 lines
2.8 KiB
Markdown
# 外壳与 H5 的接口
|
||
|
||
这份文件是外壳实现时必须照抄的部分。它很短,因为两边只在一个对象上耦合。
|
||
|
||
## 1. 启动流程
|
||
|
||
```
|
||
外壳启动
|
||
→ 读加密存储里的 serverUrl + refreshToken
|
||
→ 通过 /auth/refresh 换一个 accessToken(失败则显示登录)
|
||
→ 把 web/dist 的 index.html 加载进 WebView
|
||
· 注入 window.readerBridge(见下)
|
||
· 注入 accessToken 到 localStorage 的 `reader.session`
|
||
→ H5 自己完成后续所有请求
|
||
```
|
||
|
||
H5 只从 `localStorage['reader.session']` 读会话(`web/src/net/api.ts` 的
|
||
`defaultStorage()`)。外壳必须在页面脚本执行前把它写好 —— 用
|
||
`WebViewClient.onPageStarted` 或 `evaluateJavascript` 在 `loadUrl` 之前
|
||
注入都可以,但**必须在 `index.html` 的 module script 之前**。
|
||
|
||
## 2. 路由
|
||
|
||
H5 会自己解析 manifest 并决定谁来渲染。外壳只要监听:
|
||
|
||
```kotlin
|
||
// 外壳侧:H5 请求原生接管分页内容
|
||
webView.addJavascriptInterface(object {
|
||
@JavascriptInterface fun openPaged(bookId: String) { /* 起原生 Pager */ }
|
||
}, "readerNative")
|
||
```
|
||
|
||
H5 侧分发的时机在 `ReaderView.open()` 里(`caps.paged === 'native'` 分支),
|
||
目前通过 `CustomEvent('reader:native-page')` 触发。外壳把它接成上面那个
|
||
接口即可。
|
||
|
||
## 3. 返回
|
||
|
||
原生 Pager 退出时回到 WebView,并通知 H5 重新拉一次进度:
|
||
|
||
```js
|
||
window.dispatchEvent(new CustomEvent('reader:native-return'))
|
||
```
|
||
|
||
H5 侧的监听尚未实现(`reader-view.ts` 里留了位置),因为尚无外壳可测。
|
||
第 1 条之所以只写「已实现的部分」,就是因为这类回调**没测过就不能算数**。
|
||
|
||
## 4. 硬件键
|
||
|
||
音量键翻页是阅读器的基本期待。外壳把它转成:
|
||
|
||
```js
|
||
window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
||
```
|
||
|
||
H5 的键盘处理已经被浏览器实测过(`bindGestures()`),所以这条路不用新增
|
||
代码。
|
||
|
||
## 5. 离线
|
||
|
||
```
|
||
GET /api/v1/books/:id/content
|
||
→ 200,带 ETag 与 Accept-Ranges: bytes
|
||
→ 中断后用 Range: bytes=<已收字节>- 续传
|
||
```
|
||
|
||
目录书(漫画目录)没有单一文件,`/content` 会返回 `400 DIRECTORY_BOOK`。
|
||
这类书要缓存的是 manifest 里 `files` 列出的**每一页**:
|
||
|
||
```
|
||
GET /api/v1/books/:id/file?path=<manifest 里列出的 rel_path>
|
||
→ 200,一张图;ETag 按文件算
|
||
```
|
||
|
||
`path` 只能取 `files` 里出现过的值。服务端只按这份契约匹配,不会用 query 拼路径,
|
||
所以乱填只会拿到 404,不会拿到别的书的东西。
|
||
|
||
`/data` 里的书架元数据由客户端自己缓存(`GET /api/v1/books` 的响应)。
|
||
服务端离线时,外壳读本地缓存渲染书架,并静默降级 —— 设计文档 §8.2
|
||
要求「客户端必须优雅处理服务端不可达」,这条不能靠报错弹窗实现。
|