feat: add docs

This commit is contained in:
lisonge 2024-07-22 23:02:46 +08:00
parent 7404ba7f41
commit 67ef5da8d2
2 changed files with 108 additions and 31 deletions

View File

@ -15,34 +15,77 @@
有了快照之后, 用户只需要在指定页面抓取快照分享给开发者即可
另外对于某些出现频率极低的界面, 快照能直接保留这些界面的状态
另外对于某些出现频率极低的界面, 快照能直接保留这些界面的状态, 无需每次等待出现
## 抓取快照 {#capture}
## 抓取快照 {#capture-snapshot}
在 GKD 内可以通过多种方式抓取快照, 需要一些前置条件
抓取快照时必须**开启无障碍权限**, 否则无法获取 界面信息 和 无障碍节点信息
如果你的设备满足 Android>=11, 无障碍权限可以获取截图, 否则需要额外开启截屏服务
如果你的设备满足 Android>=11, GKD 可以通过 无障碍权限 获取截图, 否则需要额外开启截屏服务
`主页-设置-高级模式-截屏服务` 开启即可
不开启时 GKD 会使用 同尺寸透明图片 作为截图保存到快照里
当 Android<=10 且不开启截屏服务时 GKD 会使用 同尺寸透明图片 作为截图保存到快照里
以下是抓取快照的方式
### 通过悬浮窗按钮 {by-float-button}
### 通过悬浮窗按钮 {#by-button}
打开 `主页-设置-高级模式-悬浮窗服务` 后界面会出现一个可拖动的按钮, 在任意界面点击这个按钮即可抓取快照
### 通过快捷开关 {by-tile}
### 通过快捷开关 {#by-tile}
下拉打开状态栏, 左右滑动切换到有图标的界面, 点击添加或编辑, 在应用快捷开关找到 `捕获快照`, 图标和上面介绍的悬浮窗按钮一样
添加这个快捷开关到状态栏界面, 添加完毕后在任意界面下拉状态栏点击这个图标即可抓取快照
## 通过
### 通过音量快照 {#by-volume}
## 分享快照 {#share}
TODO
GKD 没有自己的文件存储服务器
### 通过截屏快照 {#by-screenshot}
TODO
### 通过审查工具 {#by-inspect}
TODO
### 通过调用服务 {#by-invoke-service}
TODO
## 分享快照 {#share-snapshot}
快照的一个好处在于可以分享并在线打开, 这可以更好地展示你的问题来获取别人的帮助
GKD 没有自己的文件存储服务器, 所有的快照都借助 Github 存储
例如快照 <https://i.gkd.li/i/16235400> 中的 `16235400` 实际指向了 Github 上的一个文件, 它的链接如下
```txt
https://github.com/user-attachments/files/16235400/file.zip
```
当你使用审查工具生成快照时, 审查工具会自动帮你上传文件到 Github 后得到链接, 相当于自动化以下行为
- 从审查工具下载快照为 file.zip 文件到电脑上
- 登录 Github 并转到任意能上传文件或者评论的公开页面
- 将刚刚的文件拖动进输入框, 文件链接会自动生成
其中使用到的工具库为
- [network-extension](https://github.com/gkd-kit/network-extension)
- [user-attachments](https://github.com/lisonge/user-attachments)
## 去除快照中的隐私信息 {#rm-privacy-info}
当抓取快照时, 图片中可能含有人的名字等敏感信息, 可能需要去除这些信息
在 GKD 的快照记录界面, 你可以先将快照图片保存到相册, 然后在相册做打马赛克之类的编辑, 之后回到记录界面替换截图即可
如果敏感信息是文字保留在快照里的节点信息上, 你需要将快照 zip 文件解压缩, 内部有一个 json 文件
节点信息就在 nodes 数组字段上, 可以直接使用文本替换为等价数量的 `*`, 修改文件后重新压缩为 zip 重新导入快照即可

View File

@ -5,7 +5,7 @@
## null
> [!NOTE] 提示
> `null` 无任何属性方法, 并且属性方法当调用者或者参数是 `null` 时, 均返回 `null`
> `null` 无任何属性方法, 并且在无特殊说明时, 属性方法当调用者或者参数是 `null` 时, 均返回 `null`
`name``null` 时, `name.length``null`
@ -15,21 +15,29 @@
## boolean
| 方法名 | 参数 | 返回类型 | 描述 |
| ------ | ---- | -------- | ----------- |
| toInt | | `int` | 转为 0 或 1 |
| 方法名 | 参数 | 返回类型 | 描述 |
| ------ | --------- | --------- | -------------------------------- |
| toInt | | `int` | 转为 0 或 1 |
| or | `boolean` | `boolean` | a \|\| b |
| and | `boolean` | `boolean` | a && b |
| not | `boolean` | `boolean` | !a |
| ifElse | `T`, `T` | `T` | if(a) T else T <br> T 是任意类型 |
## int
| 方法名 | 参数 | 返回类型 | 描述 |
| -------- | ----- | ------------------- | -------------------- |
| toString | | [`string`](#string) | 转为10进制字符串 |
| toString | `int` | `string` | 转为对应进制的字符串 |
| plus | `int` | `string` | 加上 |
| minus | `int` | `string` | 减去 |
| times | `int` | `string` | 乘以 |
| div | `int` | `string` | 除以 |
| rem | `int` | `string` | 取余 |
| 方法名 | 参数 | 返回类型 | 描述 |
| --------- | ----- | --------------------- | -------------------- |
| toString | | [`string`](#string) | 转为10进制字符串 |
| toString | `int` | `string` | 转为对应进制的字符串 |
| plus | `int` | `string` | 加上 |
| minus | `int` | `string` | 减去 |
| times | `int` | `string` | 乘以 |
| div | `int` | `string` | 除以 |
| rem | `int` | `string` | 取余 |
| more | `int` | [`boolean`](#boolean) | a > b |
| moreEqual | `int` | `boolean` | a >= b |
| less | `int` | `boolean` | a < b |
| lessEqual | `int` | `boolean` | a <= b |
## string
@ -80,20 +88,46 @@
| depth | `int` | |
| parent | [`node`](#node) | 获取父节点 |
| 方法名 | 参数 | 返回类型 | 描述 |
| -------- | ---- | --------------- | -------------------- |
| getChild | int | [`node`](#node) | 获取指定索引的子节点 |
| 方法名 | 参数 | 返回类型 | 描述 |
| -------- | ----- | --------------- | -------------------- |
| getChild | `int` | [`node`](#node) | 获取指定索引的子节点 |
## context
context 具有 [node](#node) 的所有属性方法, 下面只介绍额外属性方法
| 标识符 | 属性类型 | 描述 |
| ------ | --------------------- | ------------------------------------------------ |
| prev | [`context`](#context) | 右侧属性选择器的节点上下文 <br> 最右侧的 prev=null |
| 标识符 | 属性类型 | 描述 |
| ------- | --------------------- | -------------------------------------------------- |
| prev | [`context`](#context) | 右侧属性选择器的节点上下文 <br> 最右侧的 prev=null |
| current | [`node`](#node) | 当前节点 <br> current.id=id |
`FrameLayout[prev.name$='ImageView'] > ImageView` 中的 prev 就是 FrameLayout 右侧的 ImageView
| 方法名 | 参数 | 返回类型 | 描述 |
| ------- | ---- | --------------------- | ----------------------------------------------- |
```text
FrameLayout[prev.name$='ImageView'] > ImageView[current.name=name]
```
中的 prev 就是 FrameLayout 右侧的 ImageView, current 就是 ImageView
| 方法名 | 参数 | 返回类型 | 描述 |
| ------- | ---- | --------------------- | -------------------------------------------------------------------------------------------------------- |
| getPrev | int | [`context`](#context) | 快捷获取深层 prev <br> getPrev(0) -> prev <br> getPrev(1) -> prev.prev <br> getPrev(2) -> prev.prev.prev |
## global
global 具有 [context](#context) 的所有属性方法, 并且没有任何属性方法能获取 global 的引用, 下面只介绍额外属性方法
| 方法名 | 参数 | 返回类型 | 描述 |
| -------- | -------- | --------------------- | ------------------------------------- |
| equal | `T`, `T` | [`boolean`](#boolean) | a==b <br> T 是任意类型, a,b 允许 null |
| notEqual | `T`, `T` | `boolean` | a!=b |
示例
```text
[name=''][prev.name=''][current.name=''][parent.name='']
```
- 第一个 `name` 来自 [global](#global), 实际上任何 `xxx`/`xxx()` 都来自 global
- 第二个 `prev.name` 来自 [context](#context)
- 后续的 `current.name`/`parent.name` 都来自 [node](#node)