diff --git a/docs/guide/snapshot.md b/docs/guide/snapshot.md index f5b7469..aca1f53 100644 --- a/docs/guide/snapshot.md +++ b/docs/guide/snapshot.md @@ -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 存储 + +例如快照 中的 `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 重新导入快照即可 diff --git a/docs/selector/node.md b/docs/selector/node.md index 70d2c2b..a3ba771 100644 --- a/docs/selector/node.md +++ b/docs/selector/node.md @@ -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
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) | 右侧属性选择器的节点上下文
最右侧的 prev=null | +| 标识符 | 属性类型 | 描述 | +| ------- | --------------------- | -------------------------------------------------- | +| prev | [`context`](#context) | 右侧属性选择器的节点上下文
最右侧的 prev=null | +| current | [`node`](#node) | 当前节点
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
getPrev(0) -> prev
getPrev(1) -> prev.prev
getPrev(2) -> prev.prev.prev | + +## global + +global 具有 [context](#context) 的所有属性方法, 并且没有任何属性方法能获取 global 的引用, 下面只介绍额外属性方法 + +| 方法名 | 参数 | 返回类型 | 描述 | +| -------- | -------- | --------------------- | ------------------------------------- | +| equal | `T`, `T` | [`boolean`](#boolean) | a==b
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)