优化HDC文本输入:支持多行文本和简化接口
- 在hdc/input.py中实现多行文本支持,使用HarmonyOS keyEvent 2054处理换行 - 移除type_text函数的x/y坐标参数,简化接口 - 将多行文本处理逻辑从handler.py移至hdc/input.py,统一处理 - 优化parse_action函数,支持Type动作的text参数提取 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -163,20 +163,8 @@ class ActionHandler:
|
|||||||
time.sleep(TIMING_CONFIG.action.text_clear_delay)
|
time.sleep(TIMING_CONFIG.action.text_clear_delay)
|
||||||
|
|
||||||
# Handle multiline text by splitting on newlines
|
# Handle multiline text by splitting on newlines
|
||||||
if '\n' in text:
|
device_factory.type_text(text, self.device_id)
|
||||||
lines = text.split('\n')
|
time.sleep(TIMING_CONFIG.action.text_input_delay)
|
||||||
for i, line in enumerate(lines):
|
|
||||||
if line: # Only type non-empty lines
|
|
||||||
device_factory.type_text(line, self.device_id)
|
|
||||||
time.sleep(0.01)
|
|
||||||
|
|
||||||
# Send ENTER key between lines (not after the last line)
|
|
||||||
if i < len(lines) - 1:
|
|
||||||
self._send_keyevent("KEYCODE_ENTER")
|
|
||||||
time.sleep(0.01)
|
|
||||||
else:
|
|
||||||
device_factory.type_text(text, self.device_id)
|
|
||||||
time.sleep(TIMING_CONFIG.action.text_input_delay)
|
|
||||||
|
|
||||||
# Restore original keyboard
|
# Restore original keyboard
|
||||||
device_factory.restore_keyboard(original_ime, self.device_id)
|
device_factory.restore_keyboard(original_ime, self.device_id)
|
||||||
@@ -357,7 +345,13 @@ def parse_action(response: str) -> dict[str, Any]:
|
|||||||
print(f"Parsing action: {response}")
|
print(f"Parsing action: {response}")
|
||||||
try:
|
try:
|
||||||
response = response.strip()
|
response = response.strip()
|
||||||
if response.startswith("do"):
|
if response.startswith('do(action="Type"') or response.startswith(
|
||||||
|
'do(action="Type_Name"'
|
||||||
|
):
|
||||||
|
text = response.split("text=", 1)[1][1:-2]
|
||||||
|
action = {"_metadata": "do", "action": "Type", "text": text}
|
||||||
|
return action
|
||||||
|
elif response.startswith("do"):
|
||||||
# Use AST parsing instead of eval for safety
|
# Use AST parsing instead of eval for safety
|
||||||
try:
|
try:
|
||||||
# Escape special characters (newlines, tabs, etc.) for valid Python syntax
|
# Escape special characters (newlines, tabs, etc.) for valid Python syntax
|
||||||
|
|||||||
@@ -7,28 +7,53 @@ from typing import Optional
|
|||||||
from phone_agent.hdc.connection import _run_hdc_command
|
from phone_agent.hdc.connection import _run_hdc_command
|
||||||
|
|
||||||
|
|
||||||
def type_text(text: str, device_id: str | None = None, x: int = None, y: int = None) -> None:
|
def type_text(text: str, device_id: str | None = None) -> None:
|
||||||
"""
|
"""
|
||||||
Type text into the currently focused input field.
|
Type text into the currently focused input field.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
text: The text to type.
|
text: The text to type. Supports multi-line text with newline characters.
|
||||||
device_id: Optional HDC device ID for multi-device setups.
|
device_id: Optional HDC device ID for multi-device setups.
|
||||||
x: Optional X coordinate for input field (deprecated, kept for compatibility).
|
|
||||||
y: Optional Y coordinate for input field (deprecated, kept for compatibility).
|
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
HarmonyOS uses: hdc shell uitest uiInput text "文本内容"
|
HarmonyOS uses: hdc shell uitest uiInput text "文本内容"
|
||||||
This command works without coordinates when input field is focused.
|
This command works without coordinates when input field is focused.
|
||||||
|
For multi-line text, the function splits by newlines and sends ENTER keyEvents.
|
||||||
|
ENTER key code in HarmonyOS: 2054
|
||||||
Recommendation: Click on the input field first to focus it, then use this function.
|
Recommendation: Click on the input field first to focus it, then use this function.
|
||||||
"""
|
"""
|
||||||
hdc_prefix = _get_hdc_prefix(device_id)
|
hdc_prefix = _get_hdc_prefix(device_id)
|
||||||
|
|
||||||
# Escape special characters for shell (keep quotes for proper text handling)
|
# Handle multi-line text by splitting on newlines
|
||||||
# The text will be wrapped in quotes in the command
|
if '\n' in text:
|
||||||
escaped_text = text.replace('"', '\\"').replace("$", "\\$")
|
lines = text.split('\n')
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if line: # Only process non-empty lines
|
||||||
|
# Escape special characters for shell
|
||||||
|
escaped_line = line.replace('"', '\\"').replace("$", "\\$")
|
||||||
|
|
||||||
|
_run_hdc_command(
|
||||||
|
hdc_prefix + ["shell", "uitest", "uiInput", "text", escaped_line],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send ENTER key event after each line except the last one
|
||||||
|
if i < len(lines) - 1:
|
||||||
|
try:
|
||||||
|
_run_hdc_command(
|
||||||
|
hdc_prefix + ["shell", "uitest", "uiInput", "keyEvent", "2054"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[HDC] ENTER keyEvent failed: {e}")
|
||||||
|
else:
|
||||||
|
# Single line text - original logic
|
||||||
|
# Escape special characters for shell (keep quotes for proper text handling)
|
||||||
|
# The text will be wrapped in quotes in the command
|
||||||
|
escaped_text = text.replace('"', '\\"').replace("$", "\\$")
|
||||||
|
|
||||||
try:
|
|
||||||
# HarmonyOS uitest uiInput text command
|
# HarmonyOS uitest uiInput text command
|
||||||
# Format: hdc shell uitest uiInput text "文本内容"
|
# Format: hdc shell uitest uiInput text "文本内容"
|
||||||
_run_hdc_command(
|
_run_hdc_command(
|
||||||
@@ -36,18 +61,6 @@ def type_text(text: str, device_id: str | None = None, x: int = None, y: int = N
|
|||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
|
||||||
print(f"[HDC] Text input failed: {e}")
|
|
||||||
# Fallback: try with coordinates if provided (for older HarmonyOS versions)
|
|
||||||
if x is not None and y is not None:
|
|
||||||
try:
|
|
||||||
_run_hdc_command(
|
|
||||||
hdc_prefix + ["shell", "uitest", "uiInput", "inputText", str(x), str(y), escaped_text],
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def clear_text(device_id: str | None = None) -> None:
|
def clear_text(device_id: str | None = None) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user