From 1a7ce1ac1bc5e0a1cae24a6d6c105911a750851e Mon Sep 17 00:00:00 2001 From: agra Date: Fri, 15 May 2026 00:22:44 +0300 Subject: [PATCH] url: let plain-digit phones reach the native detector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `_hasSigil` short-circuits before any FFI hop and used to require a `.`, `:`, `@`, or `+` in the text. A phone number with no leading `+` and no separators (`0731098515`) or with parens-and-space-only separation (`(0731) 098 515`) never crossed into NSDataDetector / android.util.Patterns and silently rendered as plain body text. Track a digit counter while walking the sigil scan and trip after the fifth digit — enough to plausibly be a phone but cheap enough that `I'm 30 today` still skips FFI. The native min-7-digit filter (added in 5512acd) still handles ZIPs / scores / version strings, so the looser sigil doesn't cost us false positives on the rendered side. --- lib/src/url.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/src/url.dart b/lib/src/url.dart index 0cd4f74..1d0ca30 100644 --- a/lib/src/url.dart +++ b/lib/src/url.dart @@ -228,6 +228,7 @@ final _MatchUrl? _matchUrl = _lookupMatchUrl(); final _Free? _free = _lookupFree(); bool _hasSigil(String text) { + int digits = 0; for (int i = 0; i < text.length; i++) { final c = text.codeUnitAt(i); if (c == 0x2E /* . */ || @@ -236,6 +237,14 @@ bool _hasSigil(String text) { c == 0x2B /* + */) { return true; } + // A phone number with no `+` and no separators (e.g. `0731098515`) + // wouldn't otherwise reach the native detector. The native side + // applies its own min-digit-count filter, so even a five-digit ZIP + // here is harmless — the FFI hop is sub-ms. + if (c >= 0x30 && c <= 0x39) { + digits++; + if (digits >= 5) return true; + } } return false; }