|
| 1 | +import 'dart:math'; |
| 2 | + |
1 | 3 | import 'package:flutter/services.dart';
|
2 | 4 | import 'package:intl_phone_number_input/src/utils/phone_number/phone_number_util.dart';
|
3 | 5 |
|
@@ -38,61 +40,69 @@ class AsYouTypeFormatter extends TextInputFormatter {
|
38 | 40 | if (newValueLength > 0 && newValueLength > oldValueLength) {
|
39 | 41 | String newValueText = newValue.text;
|
40 | 42 | String rawText = newValueText.replaceAll(separatorChars, '');
|
41 |
| - String textToParse = dialCode + rawText; |
42 | 43 |
|
43 |
| - final _ = newValueText |
44 |
| - .substring( |
45 |
| - oldValue.selection.start == -1 ? 0 : oldValue.selection.start, |
46 |
| - newValue.selection.end == -1 ? 0 : newValue.selection.end) |
47 |
| - .replaceAll(separatorChars, ''); |
| 44 | + int rawCursorPosition = newValue.selection.end; |
| 45 | + |
| 46 | + int digitsBeforeCursor = 0, digitsAfterCursor = 0; |
| 47 | + |
| 48 | + if (rawCursorPosition > 0 && rawCursorPosition <= newValueText.length) { |
| 49 | + final rawTextBeforeCursor = newValueText |
| 50 | + .substring(0, rawCursorPosition) |
| 51 | + .replaceAll(separatorChars, ''); |
| 52 | + final rawTextAfterCursor = newValueText |
| 53 | + .substring(rawCursorPosition) |
| 54 | + .replaceAll(separatorChars, ''); |
| 55 | + |
| 56 | + digitsBeforeCursor = rawTextBeforeCursor.length; |
| 57 | + digitsAfterCursor = rawTextAfterCursor.length; |
| 58 | + } |
| 59 | + |
| 60 | + String textToParse = dialCode + rawText; |
48 | 61 |
|
49 | 62 | formatAsYouType(input: textToParse).then(
|
50 | 63 | (String? value) {
|
51 | 64 | String parsedText = parsePhoneNumber(value);
|
52 | 65 |
|
53 |
| - int offset = |
54 |
| - newValue.selection.end == -1 ? 0 : newValue.selection.end; |
55 |
| - |
56 |
| - if (separatorChars.hasMatch(parsedText)) { |
57 |
| - String valueInInputIndex = parsedText[offset - 1]; |
| 66 | + int newCursorPosition = 0; |
58 | 67 |
|
59 |
| - if (offset < parsedText.length) { |
60 |
| - int offsetDifference = parsedText.length - offset; |
| 68 | + if (digitsBeforeCursor > 0 || digitsAfterCursor > 0) { |
| 69 | + for (var i = 0; i < parsedText.length; i++) { |
| 70 | + final startCursor = i; |
61 | 71 |
|
62 |
| - if (offsetDifference < 2) { |
63 |
| - if (separatorChars.hasMatch(valueInInputIndex)) { |
64 |
| - offset += 1; |
| 72 | + if (allowedChars.hasMatch(parsedText[startCursor])) { |
| 73 | + if (digitsBeforeCursor > 0) { |
| 74 | + digitsBeforeCursor--; |
65 | 75 | } else {
|
66 |
| - bool isLastChar; |
67 |
| - try { |
68 |
| - var _ = newValueText[newValue.selection.end]; |
69 |
| - isLastChar = false; |
70 |
| - } on RangeError { |
71 |
| - isLastChar = true; |
72 |
| - } |
73 |
| - if (isLastChar) { |
74 |
| - offset += offsetDifference; |
75 |
| - } |
| 76 | + newCursorPosition = startCursor + 1; |
| 77 | + break; |
76 | 78 | }
|
77 |
| - } else { |
78 |
| - if (parsedText.length > offset - 1) { |
79 |
| - if (separatorChars.hasMatch(valueInInputIndex)) { |
80 |
| - offset += 1; |
81 |
| - } |
| 79 | + } |
| 80 | + |
| 81 | + final endCursor = parsedText.length - 1 - i; |
| 82 | + |
| 83 | + if (allowedChars.hasMatch(parsedText[endCursor])) { |
| 84 | + if (digitsAfterCursor > 0) { |
| 85 | + digitsAfterCursor--; |
| 86 | + } else { |
| 87 | + newCursorPosition = endCursor + 1; |
| 88 | + break; |
82 | 89 | }
|
83 | 90 | }
|
84 | 91 | }
|
85 |
| - |
86 |
| - this.onInputFormatted( |
87 |
| - TextEditingValue( |
88 |
| - text: parsedText, |
89 |
| - selection: TextSelection.collapsed(offset: offset), |
90 |
| - ), |
91 |
| - ); |
92 | 92 | }
|
| 93 | + |
| 94 | + newCursorPosition = min(max(newCursorPosition, 0), parsedText.length); |
| 95 | + |
| 96 | + this.onInputFormatted( |
| 97 | + TextEditingValue( |
| 98 | + text: parsedText, |
| 99 | + selection: TextSelection.collapsed(offset: newCursorPosition), |
| 100 | + ), |
| 101 | + ); |
93 | 102 | },
|
94 | 103 | );
|
95 | 104 | }
|
| 105 | + |
96 | 106 | return newValue;
|
97 | 107 | }
|
98 | 108 |
|
|
0 commit comments