Skip to content

Commit c62fd12

Browse files
authored
fix(android): simplify scroll methods by removing startPoint parameter and enhancing scrolling logic (#1039)
* fix(android): simplify scroll methods by removing startPoint parameter and enhancing scrolling logic * fix(android): enhance scrolling methods to support startPoint parameter and improve swipe duration handling * docs(site): update acknowledgments to include Rslib as a build tool
1 parent 95b0c77 commit c62fd12

File tree

4 files changed

+70
-37
lines changed

4 files changed

+70
-37
lines changed

apps/site/docs/en/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ There are so many UI automation tools out there, and each one seems to be all-po
108108

109109
We would like to thank the following projects:
110110

111-
- [Rsbuild](https://github.com/web-infra-dev/rsbuild) for the build tool.
111+
- [Rsbuild](https://github.com/web-infra-dev/rsbuild) and [Rslib](https://github.com/web-infra-dev/rslib) for the build tool.
112112
- [UI-TARS](https://github.com/bytedance/ui-tars) for the open-source agent model UI-TARS.
113113
- [Qwen2.5-VL](https://github.com/QwenLM/Qwen2.5-VL) for the open-source VL model Qwen2.5-VL.
114114
- [scrcpy](https://github.com/Genymobile/scrcpy) and [yume-chan](https://github.com/yume-chan) allow us to control Android devices with browser.

apps/site/docs/zh/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ for (const record of recordList) {
105105

106106
我们要感谢以下项目:
107107

108-
- [Rsbuild](https://github.com/web-infra-dev/rsbuild) 提供构建工具。
108+
- [Rsbuild](https://github.com/web-infra-dev/rsbuild) [Rslib](https://github.com/web-infra-dev/rslib) 提供构建工具。
109109
- [UI-TARS](https://github.com/bytedance/ui-tars) 提供开源智能体模型 UI-TARS。
110110
- [Qwen2.5-VL](https://github.com/QwenLM/Qwen2.5-VL) 提供开源 VL 模型 Qwen2.5-VL。
111111
- [scrcpy](https://github.com/Genymobile/scrcpy)[yume-chan](https://github.com/yume-chan) 让我们能够用浏览器控制 Android 设备。

packages/android/src/page/index.ts

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -521,11 +521,14 @@ ${Object.keys(size)
521521
get mouse() {
522522
return {
523523
click: (x: number, y: number) => this.mouseClick(x, y),
524-
wheel: (deltaX: number, deltaY: number) =>
525-
this.mouseWheel(deltaX, deltaY),
524+
wheel: (deltaX: number, deltaY: number, duration?: number) =>
525+
this.mouseWheel(deltaX, deltaY, duration),
526526
move: (x: number, y: number) => this.mouseMove(x, y),
527-
drag: (from: { x: number; y: number }, to: { x: number; y: number }) =>
528-
this.mouseDrag(from, to),
527+
drag: (
528+
from: { x: number; y: number },
529+
to: { x: number; y: number },
530+
duration?: number,
531+
) => this.mouseDrag(from, to, duration),
529532
};
530533
}
531534

@@ -581,59 +584,74 @@ ${Object.keys(size)
581584

582585
async scrollUntilTop(startPoint?: Point): Promise<void> {
583586
if (startPoint) {
587+
const { height } = await this.size();
584588
const start = { x: startPoint.left, y: startPoint.top };
585-
const end = { x: start.x, y: 0 };
589+
const end = { x: start.x, y: height };
586590

587-
await this.mouseDrag(start, end);
591+
await repeat(defaultScrollUntilTimes, () =>
592+
this.mouseDrag(start, end, defaultFastScrollDuration),
593+
);
594+
await sleep(1000);
588595
return;
589596
}
590597

591598
await repeat(defaultScrollUntilTimes, () =>
592-
this.mouseWheel(0, 9999999, defaultFastScrollDuration),
599+
this.mouseWheel(0, -9999999, defaultFastScrollDuration),
593600
);
594601
await sleep(1000);
595602
}
596603

597604
async scrollUntilBottom(startPoint?: Point): Promise<void> {
598605
if (startPoint) {
599-
const { height } = await this.size();
600606
const start = { x: startPoint.left, y: startPoint.top };
601-
const end = { x: start.x, y: height };
602-
await this.mouseDrag(start, end);
607+
const end = { x: start.x, y: 0 };
608+
609+
await repeat(defaultScrollUntilTimes, () =>
610+
this.mouseDrag(start, end, defaultFastScrollDuration),
611+
);
612+
await sleep(1000);
603613
return;
604614
}
605615

606616
await repeat(defaultScrollUntilTimes, () =>
607-
this.mouseWheel(0, -9999999, defaultFastScrollDuration),
617+
this.mouseWheel(0, 9999999, defaultFastScrollDuration),
608618
);
609619
await sleep(1000);
610620
}
611621

612622
async scrollUntilLeft(startPoint?: Point): Promise<void> {
613623
if (startPoint) {
624+
const { width } = await this.size();
614625
const start = { x: startPoint.left, y: startPoint.top };
615-
const end = { x: 0, y: start.y };
616-
await this.mouseDrag(start, end);
626+
const end = { x: width, y: start.y };
627+
628+
await repeat(defaultScrollUntilTimes, () =>
629+
this.mouseDrag(start, end, defaultFastScrollDuration),
630+
);
631+
await sleep(1000);
617632
return;
618633
}
619634

620635
await repeat(defaultScrollUntilTimes, () =>
621-
this.mouseWheel(9999999, 0, defaultFastScrollDuration),
636+
this.mouseWheel(-9999999, 0, defaultFastScrollDuration),
622637
);
623638
await sleep(1000);
624639
}
625640

626641
async scrollUntilRight(startPoint?: Point): Promise<void> {
627642
if (startPoint) {
628-
const { width } = await this.size();
629643
const start = { x: startPoint.left, y: startPoint.top };
630-
const end = { x: width, y: start.y };
631-
await this.mouseDrag(start, end);
644+
const end = { x: 0, y: start.y };
645+
646+
await repeat(defaultScrollUntilTimes, () =>
647+
this.mouseDrag(start, end, defaultFastScrollDuration),
648+
);
649+
await sleep(1000);
632650
return;
633651
}
634652

635653
await repeat(defaultScrollUntilTimes, () =>
636-
this.mouseWheel(-9999999, 0, defaultFastScrollDuration),
654+
this.mouseWheel(9999999, 0, defaultFastScrollDuration),
637655
);
638656
await sleep(1000);
639657
}
@@ -644,13 +662,13 @@ ${Object.keys(size)
644662

645663
if (startPoint) {
646664
const start = { x: startPoint.left, y: startPoint.top };
647-
const endY = Math.max(0, start.y - scrollDistance);
665+
const endY = Math.min(height, start.y + scrollDistance);
648666
const end = { x: start.x, y: endY };
649667
await this.mouseDrag(start, end);
650668
return;
651669
}
652670

653-
await this.mouseWheel(0, scrollDistance);
671+
await this.mouseWheel(0, -scrollDistance);
654672
}
655673

656674
async scrollDown(distance?: number, startPoint?: Point): Promise<void> {
@@ -659,13 +677,13 @@ ${Object.keys(size)
659677

660678
if (startPoint) {
661679
const start = { x: startPoint.left, y: startPoint.top };
662-
const endY = Math.min(height, start.y + scrollDistance);
680+
const endY = Math.max(0, start.y - scrollDistance);
663681
const end = { x: start.x, y: endY };
664682
await this.mouseDrag(start, end);
665683
return;
666684
}
667685

668-
await this.mouseWheel(0, -scrollDistance);
686+
await this.mouseWheel(0, scrollDistance);
669687
}
670688

671689
async scrollLeft(distance?: number, startPoint?: Point): Promise<void> {
@@ -674,13 +692,13 @@ ${Object.keys(size)
674692

675693
if (startPoint) {
676694
const start = { x: startPoint.left, y: startPoint.top };
677-
const endX = Math.max(0, start.x - scrollDistance);
695+
const endX = Math.min(width, start.x + scrollDistance);
678696
const end = { x: endX, y: start.y };
679697
await this.mouseDrag(start, end);
680698
return;
681699
}
682700

683-
await this.mouseWheel(scrollDistance, 0);
701+
await this.mouseWheel(-scrollDistance, 0);
684702
}
685703

686704
async scrollRight(distance?: number, startPoint?: Point): Promise<void> {
@@ -689,13 +707,13 @@ ${Object.keys(size)
689707

690708
if (startPoint) {
691709
const start = { x: startPoint.left, y: startPoint.top };
692-
const endX = Math.min(width, start.x + scrollDistance);
710+
const endX = Math.max(0, start.x - scrollDistance);
693711
const end = { x: endX, y: start.y };
694712
await this.mouseDrag(start, end);
695713
return;
696714
}
697715

698-
await this.mouseWheel(-scrollDistance, 0);
716+
await this.mouseWheel(scrollDistance, 0);
699717
}
700718

701719
private async ensureYadb() {
@@ -804,20 +822,26 @@ ${Object.keys(size)
804822
private async mouseDrag(
805823
from: { x: number; y: number },
806824
to: { x: number; y: number },
825+
duration?: number,
807826
): Promise<void> {
808827
const adb = await this.getAdb();
809828

810829
// Use adjusted coordinates
811830
const { x: fromX, y: fromY } = this.adjustCoordinates(from.x, from.y);
812831
const { x: toX, y: toY } = this.adjustCoordinates(to.x, to.y);
813832

814-
await adb.shell(`input swipe ${fromX} ${fromY} ${toX} ${toY} 300`);
833+
// Ensure duration has a default value
834+
const swipeDuration = duration ?? 300;
835+
836+
await adb.shell(
837+
`input swipe ${fromX} ${fromY} ${toX} ${toY} ${swipeDuration}`,
838+
);
815839
}
816840

817841
private async mouseWheel(
818842
deltaX: number,
819843
deltaY: number,
820-
duration = defaultNormalScrollDuration,
844+
duration?: number,
821845
): Promise<void> {
822846
const { width, height } = await this.size();
823847

@@ -839,8 +863,11 @@ ${Object.keys(size)
839863
deltaY = Math.max(-maxNegativeDeltaY, Math.min(deltaY, maxPositiveDeltaY));
840864

841865
// Calculate the end coordinates
842-
const endX = startX + deltaX;
843-
const endY = startY + deltaY;
866+
// Note: For swipe, we need to reverse the delta direction
867+
// because positive deltaY should scroll up (show top content),
868+
// which requires swiping from bottom to top (decreasing Y)
869+
const endX = startX - deltaX;
870+
const endY = startY - deltaY;
844871

845872
// Adjust coordinates to fit device ratio
846873
const { x: adjustedStartX, y: adjustedStartY } = this.adjustCoordinates(
@@ -854,9 +881,12 @@ ${Object.keys(size)
854881

855882
const adb = await this.getAdb();
856883

884+
// Ensure duration has a default value
885+
const swipeDuration = duration ?? defaultNormalScrollDuration;
886+
857887
// Execute the swipe operation
858888
await adb.shell(
859-
`input swipe ${adjustedStartX} ${adjustedStartY} ${adjustedEndX} ${adjustedEndY} ${duration}`,
889+
`input swipe ${adjustedStartX} ${adjustedStartY} ${adjustedEndX} ${adjustedEndY} ${swipeDuration}`,
860890
);
861891
}
862892

packages/android/tests/ai/setting.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ describe(
1616
});
1717

1818
await agent.launch('com.android.settings/.Settings');
19-
2019
await agent.aiAction('scroll list to bottom');
2120
await agent.aiAction('open "More settings"');
22-
await agent.aiAction('scroll list to bottom');
21+
await agent.aiAction('scroll left until left edge');
22+
await agent.aiAction('scroll right until right edge');
2323
await agent.aiAction('scroll list to top');
24-
await agent.aiAction('swipe down one screen');
25-
await agent.aiAction('swipe up one screen');
24+
await agent.aiAction('scroll list to bottom');
25+
await agent.aiAction('scroll down one screen');
26+
await agent.aiAction('scroll up one screen');
27+
await agent.aiAction('scroll right one screen');
28+
await agent.aiAction('scroll left one screen');
2629
});
2730
},
2831
360 * 1000,

0 commit comments

Comments
 (0)