first blood

This commit is contained in:
2026-01-26 14:23:13 +08:00
parent 1634953750
commit ee72a1fb3e
9 changed files with 575 additions and 0 deletions

123
src/index.ts Normal file
View File

@@ -0,0 +1,123 @@
import { NativeModules, Platform } from 'react-native';
const { RNBotModule } = NativeModules;
export interface NodeBounds {
left: number;
top: number;
right: number;
bottom: number;
centerX: number;
centerY: number;
}
export interface NodeInfo {
text?: string;
name?: string;
id?: string;
className?: string;
bounds: NodeBounds;
clickable: boolean;
editable: boolean;
}
class RNAuto {
private checkAndroid(): boolean {
if (Platform.OS !== 'android') {
console.warn('RNAuto 仅支持 Android');
return false;
}
return true;
}
/** 请求无障碍权限 */
async requestPermission(): Promise<boolean> {
if (!this.checkAndroid()) return false;
return await RNBotModule.requestPermission();
}
/** 检查服务是否运行 */
async isServiceEnabled(): Promise<boolean> {
if (!this.checkAndroid()) return false;
return await RNBotModule.isServiceEnabled();
}
/** 根据 ID 查找节点 */
async id(resId: string): Promise<NodeInfo[]> {
if (!this.checkAndroid()) return [];
return await RNBotModule.findNodes('id', resId);
}
/** 根据文本查找节点 */
async text(text: string): Promise<NodeInfo[]> {
if (!this.checkAndroid()) return [];
return await RNBotModule.findNodes('text', text);
}
/** 根据 ContentDescription 查找节点 */
async name(name: string): Promise<NodeInfo[]> {
if (!this.checkAndroid()) return [];
return await RNBotModule.findNodes('name', name);
}
/** 根据类名查找节点 */
async className(className: string): Promise<NodeInfo[]> {
if (!this.checkAndroid()) return [];
return await RNBotModule.findNodes('className', className);
}
/** 点击坐标 */
async click(x: number, y: number): Promise<boolean> {
if (!this.checkAndroid()) return false;
return await RNBotModule.click(x, y);
}
/** 点击节点 */
async clickNode(resId: string): Promise<boolean> {
const nodes = await this.id(resId);
if (nodes.length > 0) {
const { centerX, centerY } = nodes[0].bounds;
return await this.click(centerX, centerY);
}
return false;
}
/** 设置文本 */
async setText(resId: string, text: string): Promise<boolean> {
if (!this.checkAndroid()) return false;
return await RNBotModule.setText(resId, text);
}
/** 返回键 */
async back(): Promise<boolean> {
if (!this.checkAndroid()) return false;
return await RNBotModule.back();
}
/** Home 键 */
async home(): Promise<boolean> {
if (!this.checkAndroid()) return false;
return await RNBotModule.home();
}
/** 最近任务键 */
async recents(): Promise<boolean> {
if (!this.checkAndroid()) return false;
return await RNBotModule.recents();
}
/** 延迟 */
delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 别名兼容
fullId = this.id;
findById = this.id;
findByText = this.text;
findByName = this.name;
findByClassName = this.className;
}
export default new RNAuto();