diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 9367d48..9625e10 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 11.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 1e8c3c9..88359b2 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 86f9bde..158a39d 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -14,9 +14,9 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/path_provider/ios" SPEC CHECKSUMS: - Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c -PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.10.1 +COCOAPODS: 1.11.3 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index a1f9b1b..e3b475c 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ @@ -156,7 +156,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -340,7 +340,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -414,7 +414,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -463,7 +463,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..3db53b6 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + diff --git a/example/lib/main.dart b/example/lib/main.dart index 933f213..64408bf 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -46,14 +46,19 @@ class _AppState extends State { "text": "O4. This text contains a @user tag", "types": [LinkType.userTag] }, + { + "text": "O5. This text contains a phone number: (555) 444 2223", + "types": [LinkType.phone] + }, { "text": - "O5. My website url: https://hello.com/GOOGLE search using: www.google.com, social media is facebook.com, additional link http://example.com/method?param=fullstackoverflow.dev, hashtag #trending & mention @dev.user", + "O6. My website url: https://hello.com/GOOGLE search using: www.google.com, social media is facebook.com, additional link http://example.com/method?param=fullstackoverflow.dev, hashtag #trending & mention @dev.user +18009999999", "types": [ + LinkType.phone, LinkType.email, LinkType.url, LinkType.hashTag, - LinkType.userTag + LinkType.userTag, ] }, ]; @@ -96,13 +101,14 @@ class _AppState extends State { LinkType.hashTag: TextStyle(color: Colors.green), LinkType.userTag: TextStyle(color: Colors.deepPurple), LinkType.url: TextStyle(color: Colors.pink), + LinkType.phone: TextStyle(color: Colors.deepOrange), }, linkStyle: textStyle.copyWith( color: Colors.blue, fontWeight: FontWeight.bold, ), - onTap: (link) => - showSnackbar("link pressed: ${link.value!}"), + onTap: (link) => showSnackbar( + "link pressed: ${link.value!}. Type: ${link.type}"), )), ], ), diff --git a/example/pubspec.lock b/example/pubspec.lock index cb4ff1f..b050a7b 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -21,7 +21,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" charcode: dependency: transitive description: @@ -35,7 +35,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: @@ -63,7 +63,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" ffi: dependency: transitive description: @@ -122,28 +122,28 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" path_provider: dependency: transitive description: @@ -218,7 +218,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -239,21 +239,21 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.12" typed_data: dependency: transitive description: diff --git a/lib/src/enum.dart b/lib/src/enum.dart index 99f2eac..6f88abd 100644 --- a/lib/src/enum.dart +++ b/lib/src/enum.dart @@ -1 +1 @@ -enum LinkType { url, email, hashTag, userTag } +enum LinkType { url, email, hashTag, userTag, phone } diff --git a/lib/src/utils/regex.dart b/lib/src/utils/regex.dart index c0c0c60..8ff55e3 100644 --- a/lib/src/utils/regex.dart +++ b/lib/src/utils/regex.dart @@ -5,7 +5,8 @@ String urlRegExp = r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+'; String hashtagRegExp = r'(#+[a-zA-Z0-9(_)]{1,})'; String userTagRegExp = r'(? types) { ? buffer.write("($emailRegExp)") : buffer.write("($emailRegExp)|"); break; + case LinkType.phone: + isLast + ? buffer.write("($phoneRegExp)") + : buffer.write("($phoneRegExp)|"); + break; default: } } @@ -49,12 +55,14 @@ LinkType getMatchedType(String match) { late LinkType type; if (RegExp(emailRegExp).hasMatch(match)) { type = LinkType.email; + } else if (RegExp(phoneRegExp).hasMatch(match)) { + type = LinkType.phone; } else if (RegExp(userTagRegExp).hasMatch(match)) { type = LinkType.userTag; - }else if (RegExp(urlRegExp).hasMatch(match)) { + } else if (RegExp(urlRegExp).hasMatch(match)) { type = LinkType.url; } else if (RegExp(hashtagRegExp).hasMatch(match)) { type = LinkType.hashTag; - } + } return type; } diff --git a/pubspec.lock b/pubspec.lock index d1078e7..ce821e4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -28,7 +28,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" charcode: dependency: transitive description: @@ -56,7 +56,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: @@ -91,7 +91,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" file: dependency: transitive description: @@ -171,21 +171,21 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" mime: dependency: transitive description: @@ -213,7 +213,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" pedantic: dependency: transitive description: @@ -295,7 +295,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -316,35 +316,35 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test: dependency: "direct dev" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.21.1" + version: "1.21.4" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.12" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.4.13" + version: "0.4.16" typed_data: dependency: transitive description: diff --git a/test/utils/regex_test.dart b/test/utils/regex_test.dart index 55d8b89..f970631 100644 --- a/test/utils/regex_test.dart +++ b/test/utils/regex_test.dart @@ -10,7 +10,9 @@ void main() { const hashtagText = "#helloWorld and #dev are trending"; const emailText = "My email address is hey@stanleee.me and dev@gmail.com, yah!"; - const text = urlText + hashtagText + emailText; + + const phoneText = "My phone number is (222)322-3222 or +15552223333"; + const text = urlText + hashtagText + emailText + phoneText; const emails = ["hello@world.com", "foo.bar@js.com"]; @@ -46,6 +48,14 @@ void main() { '@hello_world_123' ]; + const phoneNums = [ + "1112223333", + "(111)222 3333", + "+5444333222", + "+91 (123) 456-7890", + "123-456-7890" + ]; + /// test("Should match all emails", () { for (final email in emails) { @@ -69,6 +79,11 @@ void main() { expect(RegExp(userTagRegExp).hasMatch(tag), isTrue); } }); + test("Should match all phones", () { + for (final tag in phoneNums) { + expect(RegExp(phoneRegExp).hasMatch(tag), isTrue); + } + }); test( "Should construct regex pattern from LinkTypes and match required output", @@ -76,13 +91,15 @@ void main() { final urlRegExp = constructRegExpFromLinkType([LinkType.url]); final hashtagRegExp = constructRegExpFromLinkType([LinkType.hashTag]); final emailRegExp = constructRegExpFromLinkType([LinkType.email]); + final phoneRegExp = constructRegExpFromLinkType([LinkType.phone]); final textRegExp = constructRegExpFromLinkType( - [LinkType.url, LinkType.hashTag, LinkType.email]); + [LinkType.url, LinkType.hashTag, LinkType.email, LinkType.phone]); expect(urlRegExp.allMatches(urlText).length, 4); expect(hashtagRegExp.allMatches(hashtagText).length, 2); expect(emailRegExp.allMatches(emailText).length, 2); - expect(textRegExp.allMatches(text).length, 8); + expect(phoneRegExp.allMatches(phoneText).length, 2); + expect(textRegExp.allMatches(text).length, 10); }); }); }