fix(companion): size the replace delete prefix to cover any focused field

This commit is contained in:
pj committed 2026-06-07 21:37:25 +05:30
1 parent fb6cfce37c
commit d65a816132
1 file changed
+13 -10
+13 -10
View File
@@ -14,9 +14,9 @@ enum TextInput {
var payload = text var payload = text
if replace { if replace {
let currentLength = focusedValueLength(bundleIdentifier: bundleIdentifier) let deleteCount = deletePrefixLength(bundleIdentifier: bundleIdentifier)
if currentLength > 0 { if deleteCount > 0 {
let deletes = String(repeating: XCUIKeyboardKey.delete.rawValue, count: currentLength) let deletes = String(repeating: XCUIKeyboardKey.delete.rawValue, count: deleteCount)
payload = deletes + text payload = deletes + text
} }
} }
@@ -45,20 +45,23 @@ enum TextInput {
} }
} }
// Reads the current value length of the focused editable field from a flat // Sizes the delete prefix for replace. The snapshot does not say which
// snapshot. Used to size the delete prefix for replace. // editable field holds keyboard focus (Compose fields never expose
private static func focusedValueLength(bundleIdentifier: String) -> Int { // hasKeyboardFocus), so the prefix covers the longest editable value on
// screen: deletes beyond the focused field's content are no-ops at the
// start of the field, while undersizing would leave residue and silently
// turn replace into append.
private static func deletePrefixLength(bundleIdentifier: String) -> Int {
let elements = Snapshot.elements(bundleIdentifier: bundleIdentifier) let elements = Snapshot.elements(bundleIdentifier: bundleIdentifier)
var longest = 0
for element in elements { for element in elements {
guard let type = element["type"] as? String, guard let type = element["type"] as? String,
type == "TextArea" || type == "TextField", type == "TextArea" || type == "TextField",
let value = element["AXValue"] as? String else { let value = element["AXValue"] as? String else {
continue continue
} }
if !value.isEmpty { longest = max(longest, value.count)
return value.count
}
} }
return 0 return longest
} }
} }