108 lines
4.5 KiB
TypeScript
108 lines
4.5 KiB
TypeScript
import { DeviceDriver } from '../../drivers/types';
|
||
import { sleep, waitForSource } from './element.helper';
|
||
import { goToProfile } from './auth.helper';
|
||
|
||
async function tapText(driver: DeviceDriver, t: string): Promise<boolean> {
|
||
const el = driver.platform === 'android'
|
||
? await driver.findElementRaw('-android uiautomator', `new UiSelector().text("${t}")`)
|
||
: await driver.findElementRaw('name', t);
|
||
if (el) { await driver.tapElement(el); return true; }
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 进入 Manage Rooms(房间管理)列表页:Profile → Manage Homes → 第一个 home → Rooms。
|
||
* 坐标按 1080×2280(进第一个 home 行);换机型需调。
|
||
*/
|
||
export async function goToManageRooms(driver: DeviceDriver): Promise<boolean> {
|
||
await goToProfile(driver);
|
||
if (!(await tapText(driver, 'Manage Homes'))) return false;
|
||
await sleep(2500);
|
||
await tapText(driver, 'Got it'); // 可能的"邀请加入"提示弹框
|
||
await sleep(500);
|
||
await driver.tap(540, 486); // 进第一个 home(行中心)
|
||
await sleep(2500);
|
||
if (!(await tapText(driver, 'Rooms'))) return false;
|
||
await sleep(2500);
|
||
return waitForSource(driver, 'Manage Rooms', 6000).catch(() => false) as Promise<boolean>;
|
||
}
|
||
|
||
/** 在 Manage Rooms 页创建房间:Create Room → 输入名 → OK。返回房间是否出现在列表。 */
|
||
export async function createRoom(driver: DeviceDriver, roomName: string): Promise<boolean> {
|
||
// 进 Manage Rooms 首次会弹「新手引导文档」,会遮挡 Create Room → 先点 Got it 关掉(无则 tapText 返回 false,无副作用)。
|
||
await tapText(driver, 'Got it');
|
||
await sleep(800);
|
||
if (!(await tapText(driver, 'Create Room'))) return false;
|
||
await sleep(1500);
|
||
const ed = await driver.findElementRaw('-android uiautomator', 'new UiSelector().className("android.widget.EditText")');
|
||
if (!ed) return false;
|
||
await driver.typeText(ed, roomName);
|
||
await sleep(500);
|
||
await tapText(driver, 'OK');
|
||
await sleep(2500);
|
||
await tapText(driver, 'Got it'); // 创建后可能再弹引导,兜底关掉
|
||
await sleep(1000);
|
||
const ok = (await driver.getSource()).includes(roomName);
|
||
console.log(`创建房间 ${roomName}: ${ok}`);
|
||
return ok;
|
||
}
|
||
|
||
/** 删除房间(清理/恢复数据):点房间 → 详情页右上角删除图标(top_bar_right_icon)→ Attention 弹框 Confirm。返回房间是否已消失。 */
|
||
export async function deleteRoom(driver: DeviceDriver, roomName: string): Promise<boolean> {
|
||
if (!(await tapText(driver, roomName))) return false; // 进房间详情
|
||
await sleep(2000);
|
||
const icon = await driver.findElementRaw('id', 'com.theswitchbot.switchbot:id/top_bar_right_icon');
|
||
if (icon) await driver.tapElement(icon); else await driver.tap(1018, 185); // 右上角删除
|
||
await sleep(1500);
|
||
await tapText(driver, 'Confirm'); // Attention 确认框
|
||
await sleep(2500);
|
||
const gone = !(await driver.getSource()).includes(roomName);
|
||
console.log(`删除房间 ${roomName}: ${gone ? '已删除' : '仍存在'}`);
|
||
return gone;
|
||
}
|
||
|
||
export async function selectRoom(driver: DeviceDriver, roomName: string): Promise<boolean> {
|
||
if (driver.platform === 'android') {
|
||
const rooms = await driver.findElementsRaw('id', 'com.theswitchbot.switchbot:id/clSelectRoom');
|
||
for (const room of rooms) {
|
||
const text = await driver.getElementAttribute(room, 'text');
|
||
if (text.includes(roomName)) {
|
||
await driver.tapElement(room);
|
||
await sleep(500);
|
||
const saveEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Save")');
|
||
if (saveEl) await driver.tapElement(saveEl);
|
||
await sleep(2000);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// iOS
|
||
const cells = await driver.findElementsRaw('class name', 'XCUIElementTypeCell');
|
||
for (const cell of cells) {
|
||
const name = await driver.getElementAttribute(cell, 'name');
|
||
if (name.includes(roomName)) {
|
||
await driver.tapElement(cell);
|
||
await sleep(500);
|
||
const saveEl = await driver.findElementRaw('name', 'Save');
|
||
if (saveEl) await driver.tapElement(saveEl);
|
||
await sleep(2000);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
export async function getCurrentRoom(driver: DeviceDriver): Promise<string> {
|
||
const source = await driver.getSource();
|
||
if (source.includes('Not in any room')) return '';
|
||
if (driver.platform === 'android') {
|
||
const match = source.match(/sivDeviceRoom[\s\S]*?text="([^"]+)"/);
|
||
return match ? match[1] : '';
|
||
}
|
||
const roomLabel = await driver.findElementRaw('name', 'Room');
|
||
if (!roomLabel) return '';
|
||
return '';
|
||
}
|