├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── kotlin │ └── co │ └── quis │ └── flutter_contacts │ ├── Contact.kt │ ├── ContactChangeObserver.kt │ ├── FlutterContacts.kt │ ├── FlutterContactsPlugin.kt │ └── properties │ ├── Account.kt │ ├── Address.kt │ ├── Email.kt │ ├── Event.kt │ ├── Group.kt │ ├── Name.kt │ ├── Note.kt │ ├── Organization.kt │ ├── Phone.kt │ ├── SocialMedia.kt │ └── Website.kt ├── doc └── api │ ├── __404error.html │ ├── categories.json │ ├── config │ ├── FlutterContactsConfig-class-sidebar.html │ ├── FlutterContactsConfig-class.html │ ├── FlutterContactsConfig │ │ ├── FlutterContactsConfig.html │ │ ├── includeNonVisibleOnAndroid.html │ │ ├── includeNotesOnIos13AndAbove.html │ │ ├── returnUnifiedContacts.html │ │ └── vCardVersion.html │ ├── VCardVersion-enum-sidebar.html │ ├── VCardVersion.html │ ├── VCardVersion │ │ ├── VCardVersion.html │ │ └── values-constant.html │ ├── config-library-sidebar.html │ └── config-library.html │ ├── contact │ ├── Contact-class-sidebar.html │ ├── Contact-class.html │ ├── Contact │ │ ├── Contact.fromJson.html │ │ ├── Contact.fromVCard.html │ │ ├── Contact.html │ │ ├── accounts.html │ │ ├── addresses.html │ │ ├── deduplicateProperties.html │ │ ├── delete.html │ │ ├── displayName.html │ │ ├── emails.html │ │ ├── events.html │ │ ├── groups.html │ │ ├── hashCode.html │ │ ├── id.html │ │ ├── insert.html │ │ ├── isStarred.html │ │ ├── isUnified.html │ │ ├── name.html │ │ ├── notes.html │ │ ├── operator_equals.html │ │ ├── organizations.html │ │ ├── phones.html │ │ ├── photo.html │ │ ├── photoFetched.html │ │ ├── photoOrThumbnail.html │ │ ├── propertiesFetched.html │ │ ├── socialMedias.html │ │ ├── thumbnail.html │ │ ├── thumbnailFetched.html │ │ ├── toJson.html │ │ ├── toString.html │ │ ├── toVCard.html │ │ ├── update.html │ │ └── websites.html │ ├── contact-library-sidebar.html │ └── contact-library.html │ ├── diacritics │ ├── diacritics-library-sidebar.html │ ├── diacritics-library.html │ └── removeDiacritics.html │ ├── flutter_contacts │ ├── FlutterContacts-class-sidebar.html │ ├── FlutterContacts-class.html │ ├── FlutterContacts │ │ ├── FlutterContacts.html │ │ ├── addListener.html │ │ ├── config.html │ │ ├── deleteContact.html │ │ ├── deleteContacts.html │ │ ├── deleteGroup.html │ │ ├── getContact.html │ │ ├── getContacts.html │ │ ├── getGroups.html │ │ ├── insertContact.html │ │ ├── insertGroup.html │ │ ├── openExternalEdit.html │ │ ├── openExternalInsert.html │ │ ├── openExternalPick.html │ │ ├── openExternalView.html │ │ ├── removeListener.html │ │ ├── requestPermission.html │ │ ├── updateContact.html │ │ └── updateGroup.html │ ├── flutter_contacts-library-sidebar.html │ └── flutter_contacts-library.html │ ├── index.html │ ├── index.json │ ├── properties_account │ ├── Account-class-sidebar.html │ ├── Account-class.html │ ├── Account │ │ ├── Account.fromJson.html │ │ ├── Account.html │ │ ├── mimetypes.html │ │ ├── name.html │ │ ├── rawId.html │ │ ├── toJson.html │ │ ├── toString.html │ │ └── type.html │ ├── properties_account-library-sidebar.html │ └── properties_account-library.html │ ├── properties_address │ ├── Address-class-sidebar.html │ ├── Address-class.html │ ├── Address │ │ ├── Address.fromJson.html │ │ ├── Address.html │ │ ├── city.html │ │ ├── country.html │ │ ├── customLabel.html │ │ ├── hashCode.html │ │ ├── isoCountry.html │ │ ├── label.html │ │ ├── neighborhood.html │ │ ├── operator_equals.html │ │ ├── pobox.html │ │ ├── postalCode.html │ │ ├── state.html │ │ ├── street.html │ │ ├── subAdminArea.html │ │ ├── subLocality.html │ │ ├── toJson.html │ │ ├── toString.html │ │ └── toVCard.html │ ├── AddressLabel-enum-sidebar.html │ ├── AddressLabel.html │ ├── AddressLabel │ │ ├── AddressLabel.html │ │ └── values-constant.html │ ├── properties_address-library-sidebar.html │ └── properties_address-library.html │ ├── properties_email │ ├── Email-class-sidebar.html │ ├── Email-class.html │ ├── Email │ │ ├── Email.fromJson.html │ │ ├── Email.html │ │ ├── address.html │ │ ├── customLabel.html │ │ ├── hashCode.html │ │ ├── isPrimary.html │ │ ├── label.html │ │ ├── operator_equals.html │ │ ├── toJson.html │ │ ├── toString.html │ │ └── toVCard.html │ ├── EmailLabel-enum-sidebar.html │ ├── EmailLabel.html │ ├── EmailLabel │ │ ├── EmailLabel.html │ │ └── values-constant.html │ ├── properties_email-library-sidebar.html │ └── properties_email-library.html │ ├── properties_event │ ├── Event-class-sidebar.html │ ├── Event-class.html │ ├── Event │ │ ├── Event.fromJson.html │ │ ├── Event.html │ │ ├── customLabel.html │ │ ├── day.html │ │ ├── hashCode.html │ │ ├── label.html │ │ ├── month.html │ │ ├── operator_equals.html │ │ ├── toJson.html │ │ ├── toString.html │ │ ├── toVCard.html │ │ └── year.html │ ├── EventLabel-enum-sidebar.html │ ├── EventLabel.html │ ├── EventLabel │ │ ├── EventLabel.html │ │ └── values-constant.html │ ├── properties_event-library-sidebar.html │ └── properties_event-library.html │ ├── properties_group │ ├── Group-class-sidebar.html │ ├── Group-class.html │ ├── Group │ │ ├── Group.fromJson.html │ │ ├── Group.html │ │ ├── id.html │ │ ├── name.html │ │ ├── toJson.html │ │ └── toString.html │ ├── properties_group-library-sidebar.html │ └── properties_group-library.html │ ├── properties_name │ ├── Name-class-sidebar.html │ ├── Name-class.html │ ├── Name │ │ ├── Name.fromJson.html │ │ ├── Name.html │ │ ├── first.html │ │ ├── firstPhonetic.html │ │ ├── hashCode.html │ │ ├── last.html │ │ ├── lastPhonetic.html │ │ ├── middle.html │ │ ├── middlePhonetic.html │ │ ├── nickname.html │ │ ├── operator_equals.html │ │ ├── prefix.html │ │ ├── suffix.html │ │ ├── toJson.html │ │ ├── toString.html │ │ └── toVCard.html │ ├── properties_name-library-sidebar.html │ └── properties_name-library.html │ ├── properties_note │ ├── Note-class-sidebar.html │ ├── Note-class.html │ ├── Note │ │ ├── Note.fromJson.html │ │ ├── Note.html │ │ ├── hashCode.html │ │ ├── operator_equals.html │ │ ├── toJson.html │ │ ├── toString.html │ │ └── toVCard.html │ ├── properties_note-library-sidebar.html │ └── properties_note-library.html │ ├── properties_organization │ ├── Organization-class-sidebar.html │ ├── Organization-class.html │ ├── Organization │ │ ├── Organization.fromJson.html │ │ ├── Organization.html │ │ ├── company.html │ │ ├── department.html │ │ ├── hashCode.html │ │ ├── jobDescription.html │ │ ├── officeLocation.html │ │ ├── operator_equals.html │ │ ├── phoneticName.html │ │ ├── symbol.html │ │ ├── title.html │ │ ├── toJson.html │ │ ├── toString.html │ │ └── toVCard.html │ ├── properties_organization-library-sidebar.html │ └── properties_organization-library.html │ ├── properties_phone │ ├── Phone-class-sidebar.html │ ├── Phone-class.html │ ├── Phone │ │ ├── Phone.fromJson.html │ │ ├── Phone.html │ │ ├── customLabel.html │ │ ├── hashCode.html │ │ ├── isPrimary.html │ │ ├── label.html │ │ ├── normalizedNumber.html │ │ ├── number.html │ │ ├── operator_equals.html │ │ ├── toJson.html │ │ ├── toString.html │ │ └── toVCard.html │ ├── PhoneLabel-enum-sidebar.html │ ├── PhoneLabel.html │ ├── PhoneLabel │ │ ├── PhoneLabel.html │ │ └── values-constant.html │ ├── properties_phone-library-sidebar.html │ └── properties_phone-library.html │ ├── properties_social_media │ ├── SocialMedia-class-sidebar.html │ ├── SocialMedia-class.html │ ├── SocialMedia │ │ ├── SocialMedia.fromJson.html │ │ ├── SocialMedia.html │ │ ├── customLabel.html │ │ ├── hashCode.html │ │ ├── label.html │ │ ├── operator_equals.html │ │ ├── toJson.html │ │ ├── toString.html │ │ ├── toVCard.html │ │ └── userName.html │ ├── SocialMediaLabel-enum-sidebar.html │ ├── SocialMediaLabel.html │ ├── SocialMediaLabel │ │ ├── SocialMediaLabel.html │ │ └── values-constant.html │ ├── lowerCaseStringToSocialMediaLabel.html │ ├── properties_social_media-library-sidebar.html │ └── properties_social_media-library.html │ ├── properties_website │ ├── Website-class-sidebar.html │ ├── Website-class.html │ ├── Website │ │ ├── Website.fromJson.html │ │ ├── Website.html │ │ ├── customLabel.html │ │ ├── hashCode.html │ │ ├── label.html │ │ ├── operator_equals.html │ │ ├── toJson.html │ │ ├── toString.html │ │ ├── toVCard.html │ │ └── url.html │ ├── WebsiteLabel-enum-sidebar.html │ ├── WebsiteLabel.html │ ├── WebsiteLabel │ │ ├── WebsiteLabel.html │ │ └── values-constant.html │ ├── properties_website-library-sidebar.html │ └── properties_website-library.html │ ├── search.html │ ├── static-assets │ ├── docs.dart.js │ ├── docs.dart.js.map │ ├── favicon.png │ ├── github.css │ ├── highlight.pack.js │ ├── play_button.svg │ ├── readme.md │ ├── search.svg │ └── styles.css │ └── vcard │ ├── Param-class-sidebar.html │ ├── Param-class.html │ ├── Param │ ├── Param.html │ ├── key.html │ ├── toString.html │ └── value.html │ ├── VCardParser-class-sidebar.html │ ├── VCardParser-class.html │ ├── VCardParser │ ├── VCardParser.html │ ├── decode.html │ ├── encode.html │ ├── parse.html │ └── unfold.html │ ├── vCardEncode.html │ ├── vcard-library-sidebar.html │ └── vcard-library.html ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── co │ │ │ │ │ └── quis │ │ │ │ │ └── flutter_contacts_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ └── main.dart └── pubspec.yaml ├── example_full ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── co │ │ │ │ │ └── quis │ │ │ │ │ └── flutter_contacts_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── .last_build_id │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── main.dart │ ├── pages │ │ ├── contact_list_page.dart │ │ ├── contact_page.dart │ │ ├── edit_contact_page.dart │ │ ├── form_components │ │ │ ├── address_form.dart │ │ │ ├── email_form.dart │ │ │ ├── event_form.dart │ │ │ ├── name_form.dart │ │ │ ├── note_form.dart │ │ │ ├── organization_form.dart │ │ │ ├── phone_form.dart │ │ │ ├── social_media_form.dart │ │ │ └── website_form.dart │ │ └── groups_page.dart │ └── util │ │ └── avatar.dart └── pubspec.yaml ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── Contact.swift │ ├── FlutterContactsPlugin.h │ ├── FlutterContactsPlugin.m │ ├── SwiftFlutterContactsPlugin.swift │ └── properties │ │ ├── Account.swift │ │ ├── Address.swift │ │ ├── Email.swift │ │ ├── Event.swift │ │ ├── Group.swift │ │ ├── Name.swift │ │ ├── Note.swift │ │ ├── Organization.swift │ │ ├── Phone.swift │ │ ├── SocialMedia.swift │ │ └── Website.swift └── flutter_contacts.podspec ├── lib ├── config.dart ├── contact.dart ├── diacritics.dart ├── flutter_contacts.dart ├── properties │ ├── account.dart │ ├── address.dart │ ├── email.dart │ ├── event.dart │ ├── group.dart │ ├── name.dart │ ├── note.dart │ ├── organization.dart │ ├── phone.dart │ ├── social_media.dart │ └── website.dart └── vcard.dart ├── pubspec.yaml ├── scripts └── format.sh └── test ├── contact_test.dart ├── diacritics_test.dart ├── flutter_contacts_test.dart ├── testdata └── vcards │ ├── android-default-contact-app.json │ ├── android-default-contact-app.vcf │ ├── bvcard.com.json │ ├── bvcard.com.vcf │ ├── ios.json │ ├── ios.vcf │ ├── macos.json │ ├── macos.vcf │ ├── qr-code-generator.com.json │ ├── qr-code-generator.com.vcf │ ├── vcardmaker.com.json │ ├── vcardmaker.com.vcf │ ├── whatsapp.json │ └── whatsapp.vcf ├── vcard_parser_test.dart ├── vcard_v3_test.dart └── vcard_v4_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | 9 | pubspec.lock 10 | 11 | # IntelliJ related 12 | *.iml 13 | *.ipr 14 | *.iws 15 | .idea/ -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: f139b11009aeb8ed2a3a3aa8b0066e482709dde3 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Joachim Valente 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:pedantic/analysis_options.yaml 2 | 3 | linter: 4 | rules: 5 | # set literals are not supported before dart 2.2 6 | prefer_collection_literals: false 7 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'co.quis.flutter_contacts' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.7.22' 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:8.3.1' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | rootProject.allprojects { 18 | repositories { 19 | google() 20 | mavenCentral() 21 | } 22 | } 23 | 24 | apply plugin: 'com.android.library' 25 | apply plugin: 'kotlin-android' 26 | 27 | android { 28 | compileSdk 34 29 | 30 | namespace 'co.quis.flutter_contacts' 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_17 34 | targetCompatibility JavaVersion.VERSION_17 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = 17 39 | } 40 | 41 | defaultConfig { 42 | minSdk 19 43 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 44 | } 45 | lintOptions { 46 | disable 'InvalidPackage' 47 | } 48 | 49 | dependencies { 50 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutter_contacts' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/Contact.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts 2 | 3 | import co.quis.flutter_contacts.properties.Account 4 | import co.quis.flutter_contacts.properties.Address 5 | import co.quis.flutter_contacts.properties.Email 6 | import co.quis.flutter_contacts.properties.Event 7 | import co.quis.flutter_contacts.properties.Group 8 | import co.quis.flutter_contacts.properties.Name 9 | import co.quis.flutter_contacts.properties.Note 10 | import co.quis.flutter_contacts.properties.Organization 11 | import co.quis.flutter_contacts.properties.Phone 12 | import co.quis.flutter_contacts.properties.SocialMedia 13 | import co.quis.flutter_contacts.properties.Website 14 | 15 | data class Contact( 16 | var id: String, 17 | var displayName: String, 18 | var thumbnail: ByteArray? = null, 19 | var photo: ByteArray? = null, 20 | val isStarred: Boolean = false, 21 | var name: Name = Name(), 22 | var phones: List = listOf(), 23 | var emails: List = listOf(), 24 | var addresses: List
= listOf(), 25 | var organizations: List = listOf(), 26 | var websites: List = listOf(), 27 | var socialMedias: List = listOf(), 28 | var events: List = listOf(), 29 | var notes: List = listOf(), 30 | var accounts: List = listOf(), 31 | var groups: List = listOf() 32 | ) { 33 | companion object { 34 | fun fromMap(m: Map): Contact { 35 | return Contact( 36 | m["id"] as String, 37 | m["displayName"] as String, 38 | m["thumbnail"] as? ByteArray, 39 | m["photo"] as? ByteArray, 40 | m["isStarred"] as Boolean, 41 | Name.fromMap(m["name"] as Map), 42 | (m["phones"] as List>).map { Phone.fromMap(it) }, 43 | (m["emails"] as List>).map { Email.fromMap(it) }, 44 | (m["addresses"] as List>).map { Address.fromMap(it) }, 45 | (m["organizations"] as List>).map { Organization.fromMap(it) }, 46 | (m["websites"] as List>).map { Website.fromMap(it) }, 47 | (m["socialMedias"] as List>).map { SocialMedia.fromMap(it) }, 48 | (m["events"] as List>).map { Event.fromMap(it) }, 49 | (m["notes"] as List>).map { Note.fromMap(it) }, 50 | (m["accounts"] as List>).map { Account.fromMap(it) }, 51 | (m["groups"] as List>).map { Group.fromMap(it) } 52 | ) 53 | } 54 | } 55 | 56 | fun toMap(): Map = mapOf( 57 | "id" to id, 58 | "displayName" to displayName, 59 | "thumbnail" to thumbnail, 60 | "photo" to photo, 61 | "isStarred" to isStarred, 62 | "name" to name.toMap(), 63 | "phones" to phones.map { it.toMap() }, 64 | "emails" to emails.map { it.toMap() }, 65 | "addresses" to addresses.map { it.toMap() }, 66 | "organizations" to organizations.map { it.toMap() }, 67 | "websites" to websites.map { it.toMap() }, 68 | "socialMedias" to socialMedias.map { it.toMap() }, 69 | "events" to events.map { it.toMap() }, 70 | "notes" to notes.map { it.toMap() }, 71 | "accounts" to accounts.map { it.toMap() }, 72 | "groups" to groups.map { it.toMap() } 73 | ) 74 | } 75 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/ContactChangeObserver.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts 2 | 3 | import android.database.ContentObserver 4 | import android.os.Handler 5 | import io.flutter.plugin.common.EventChannel 6 | 7 | class ContactChangeObserver : ContentObserver { 8 | val _sink: EventChannel.EventSink 9 | 10 | constructor(handler: Handler, sink: EventChannel.EventSink) : super(handler) { 11 | this._sink = sink 12 | } 13 | 14 | override fun onChange(selfChange: Boolean) { 15 | _sink?.success(selfChange) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Account.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Account( 4 | var rawId: String, 5 | var type: String, 6 | var name: String, 7 | var mimetypes: List = listOf() 8 | ) { 9 | 10 | companion object { 11 | fun fromMap(m: Map): Account = Account( 12 | m["rawId"] as String, 13 | m["type"] as String, 14 | m["name"] as String, 15 | m["mimetypes"] as List 16 | ) 17 | } 18 | 19 | fun toMap(): Map = mapOf( 20 | "rawId" to rawId, 21 | "type" to type, 22 | "name" to name, 23 | "mimetypes" to mimetypes 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Address.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Address( 4 | var address: String, 5 | // one of: home, school, work, other, custom 6 | var label: String = "home", 7 | var customLabel: String = "", 8 | var street: String = "", 9 | var pobox: String = "", 10 | var neighborhood: String = "", 11 | var city: String = "", 12 | var state: String = "", 13 | var postalCode: String = "", 14 | var country: String = "", 15 | var isoCountry: String = "", 16 | var subAdminArea: String = "", 17 | var subLocality: String = "" 18 | ) { 19 | 20 | companion object { 21 | fun fromMap(m: Map): Address = Address( 22 | m["address"] as String, 23 | m["label"] as String, 24 | m["customLabel"] as String, 25 | m["street"] as String, 26 | m["pobox"] as String, 27 | m["neighborhood"] as String, 28 | m["city"] as String, 29 | m["state"] as String, 30 | m["postalCode"] as String, 31 | m["country"] as String, 32 | m["isoCountry"] as String, 33 | m["subAdminArea"] as String, 34 | m["subLocality"] as String 35 | ) 36 | } 37 | 38 | fun toMap(): Map = mapOf( 39 | "address" to address, 40 | "label" to label, 41 | "customLabel" to customLabel, 42 | "street" to street, 43 | "pobox" to pobox, 44 | "neighborhood" to neighborhood, 45 | "city" to city, 46 | "state" to state, 47 | "postalCode" to postalCode, 48 | "country" to country, 49 | "isoCountry" to isoCountry, 50 | "subAdminArea" to subAdminArea, 51 | "subLocality" to subLocality 52 | ) 53 | } 54 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Email.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Email( 4 | var address: String, 5 | // one of: home, iCloud, mobile, school, work, other, custom 6 | var label: String = "home", 7 | var customLabel: String = "", 8 | var isPrimary: Boolean = false 9 | ) { 10 | companion object { 11 | fun fromMap(m: Map): Email = Email( 12 | m["address"] as String, 13 | m["label"] as String, 14 | m["customLabel"] as String, 15 | m["isPrimary"] as Boolean 16 | ) 17 | } 18 | 19 | fun toMap(): Map = mapOf( 20 | "address" to address, 21 | "label" to label, 22 | "customLabel" to customLabel, 23 | "isPrimary" to isPrimary 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Event.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Event( 4 | var year: Int?, 5 | var month: Int, 6 | var day: Int, 7 | // one of: anniversary, birthday, other, custom 8 | var label: String = "birthday", 9 | var customLabel: String = "" 10 | ) { 11 | companion object { 12 | fun fromMap(m: Map): Event = Event( 13 | m["year"] as Int?, 14 | m["month"] as Int, 15 | m["day"] as Int, 16 | m["label"] as String, 17 | m["customLabel"] as String 18 | ) 19 | } 20 | 21 | fun toMap(): Map = mapOf( 22 | "year" to year, 23 | "month" to month, 24 | "day" to day, 25 | "label" to label, 26 | "customLabel" to customLabel 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Group.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Group( 4 | var id: String, 5 | var name: String 6 | ) { 7 | 8 | companion object { 9 | fun fromMap(m: Map): Group = Group( 10 | m["id"] as String, 11 | m["name"] as String 12 | ) 13 | } 14 | 15 | fun toMap(): Map = mapOf( 16 | "id" to id, 17 | "name" to name 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Name.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Name( 4 | var first: String = "", 5 | var last: String = "", 6 | var middle: String = "", 7 | var prefix: String = "", 8 | var suffix: String = "", 9 | var nickname: String = "", 10 | var firstPhonetic: String = "", 11 | var lastPhonetic: String = "", 12 | var middlePhonetic: String = "" 13 | ) { 14 | companion object { 15 | fun fromMap(m: Map): Name = Name( 16 | m["first"] as String, 17 | m["last"] as String, 18 | m["middle"] as String, 19 | m["prefix"] as String, 20 | m["suffix"] as String, 21 | m["nickname"] as String, 22 | m["firstPhonetic"] as String, 23 | m["lastPhonetic"] as String, 24 | m["middlePhonetic"] as String 25 | ) 26 | } 27 | 28 | fun toMap(): Map = mapOf( 29 | "first" to first, 30 | "last" to last, 31 | "middle" to middle, 32 | "prefix" to prefix, 33 | "suffix" to suffix, 34 | "nickname" to nickname, 35 | "firstPhonetic" to firstPhonetic, 36 | "lastPhonetic" to lastPhonetic, 37 | "middlePhonetic" to middlePhonetic 38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Note.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Note( 4 | var note: String 5 | ) { 6 | companion object { 7 | fun fromMap(m: Map): Note = Note(m["note"] as String) 8 | } 9 | 10 | fun toMap(): Map = mapOf("note" to note) 11 | } 12 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Organization.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Organization( 4 | var company: String = "", 5 | var title: String = "", 6 | var department: String = "", 7 | var jobDescription: String = "", 8 | var symbol: String = "", 9 | var phoneticName: String = "", 10 | var officeLocation: String = "" 11 | ) { 12 | companion object { 13 | fun fromMap(m: Map): Organization = Organization( 14 | m["company"] as String, 15 | m["title"] as String, 16 | m["department"] as String, 17 | m["jobDescription"] as String, 18 | m["symbol"] as String, 19 | m["phoneticName"] as String, 20 | m["officeLocation"] as String 21 | ) 22 | } 23 | 24 | fun toMap(): Map = mapOf( 25 | "company" to company, 26 | "title" to title, 27 | "department" to department, 28 | "jobDescription" to jobDescription, 29 | "symbol" to symbol, 30 | "phoneticName" to phoneticName, 31 | "officeLocation" to officeLocation 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Phone.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Phone( 4 | var number: String, 5 | var normalizedNumber: String, 6 | // one of: assistant, callback, car, companyMain, faxHome, faxOther, faxWork, home, 7 | // iPhone, isdn, main, mms, mobile, pager, radio, school, telex, ttyTtd, work, 8 | // workMobile, workPager, other, custom 9 | var label: String = "mobile", 10 | var customLabel: String, 11 | var isPrimary: Boolean = false 12 | ) { 13 | companion object { 14 | fun fromMap(m: Map): Phone = Phone( 15 | m["number"] as String, 16 | m["normalizedNumber"] as String, 17 | m["label"] as String, 18 | m["customLabel"] as String, 19 | m["isPrimary"] as Boolean 20 | ) 21 | } 22 | 23 | fun toMap(): Map = mapOf( 24 | "number" to number, 25 | "normalizedNumber" to normalizedNumber, 26 | "label" to label, 27 | "customLabel" to customLabel, 28 | "isPrimary" to isPrimary 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/SocialMedia.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class SocialMedia( 4 | var userName: String, 5 | // one of: aim, baiduTieba, discord, facebook, flickr, gaduGadu, gameCenter, 6 | // googleTalk, icq, instagram, jabber, line, linkedIn, medium, messenger, msn, 7 | // mySpace, netmeeting, pinterest, qqchat, qzone, reddit, sinaWeibo, skype, 8 | // snapchat, telegram, tencentWeibo, tikTok, tumblr, twitter, viber, wechat, 9 | // whatsapp, yahoo, yelp, youtube, zoom, other, custom 10 | var label: String = "other", 11 | var customLabel: String = "" 12 | ) { 13 | companion object { 14 | fun fromMap(m: Map): SocialMedia = SocialMedia( 15 | m["userName"] as String, 16 | m["label"] as String, 17 | m["customLabel"] as String 18 | ) 19 | } 20 | 21 | fun toMap(): Map = mapOf( 22 | "userName" to userName, 23 | "label" to label, 24 | "customLabel" to customLabel 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /android/src/main/kotlin/co/quis/flutter_contacts/properties/Website.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts.properties 2 | 3 | data class Website( 4 | var url: String, 5 | // one of: blog, ftp, home, homepage, profile, school, work, other, custom 6 | var label: String = "homepage", 7 | var customLabel: String = "" 8 | ) { 9 | companion object { 10 | fun fromMap(m: Map): Website = Website( 11 | m["url"] as String, 12 | m["label"] as String, 13 | m["customLabel"] as String 14 | ) 15 | } 16 | 17 | fun toMap(): Map = mapOf( 18 | "url" to url, 19 | "label" to label, 20 | "customLabel" to customLabel 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /doc/api/categories.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /doc/api/config/FlutterContactsConfig-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. FlutterContactsConfig
  4. 5 | 6 | 7 | 8 |
  5. 9 | Properties 10 |
  6. 11 |
  7. hashCode
  8. 12 |
  9. includeNonVisibleOnAndroid
  10. 13 |
  11. includeNotesOnIos13AndAbove
  12. 14 |
  13. returnUnifiedContacts
  14. 15 |
  15. runtimeType
  16. 16 |
  17. vCardVersion
  18. 17 | 18 |
  19. Methods
  20. 19 |
  21. noSuchMethod
  22. 20 |
  23. toString
  24. 21 | 22 |
  25. Operators
  26. 23 |
  27. operator ==
  28. 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | -------------------------------------------------------------------------------- /doc/api/config/VCardVersion-enum-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. VCardVersion
  4. 5 | 6 |
  5. Values
  6. 7 |
  7. v3
  8. 8 |
  9. v4
  10. 9 | 10 | 11 |
  11. 12 | Properties 13 |
  12. 14 |
  13. hashCode
  14. 15 |
  15. index
  16. 16 |
  17. runtimeType
  18. 17 | 18 |
  19. Methods
  20. 19 |
  21. noSuchMethod
  22. 20 |
  23. toString
  24. 21 | 22 |
  25. Operators
  26. 23 |
  27. operator ==
  28. 24 | 25 | 26 | 27 | 28 | 29 | 30 |
  29. Constants
  30. 31 |
  31. values
  32. 32 |
33 | -------------------------------------------------------------------------------- /doc/api/config/config-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. FlutterContactsConfig
  4. 4 | 5 |
  5. Enums
  6. 6 |
  7. VCardVersion
  8. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /doc/api/contact/Contact-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Contact
  4. 5 |
  5. fromJson
  6. 6 |
  7. fromVCard
  8. 7 | 8 | 9 | 10 |
  9. 11 | Properties 12 |
  10. 13 |
  11. accounts
  12. 14 |
  13. addresses
  14. 15 |
  15. displayName
  16. 16 |
  17. emails
  18. 17 |
  19. events
  20. 18 |
  21. groups
  22. 19 |
  23. hashCode
  24. 20 |
  25. id
  26. 21 |
  27. isStarred
  28. 22 |
  29. isUnified
  30. 23 |
  31. name
  32. 24 |
  33. notes
  34. 25 |
  35. organizations
  36. 26 |
  37. phones
  38. 27 |
  39. photo
  40. 28 |
  41. photoFetched
  42. 29 |
  43. photoOrThumbnail
  44. 30 |
  45. propertiesFetched
  46. 31 |
  47. runtimeType
  48. 32 |
  49. socialMedias
  50. 33 |
  51. thumbnail
  52. 34 |
  53. thumbnailFetched
  54. 35 |
  55. websites
  56. 36 | 37 |
  57. Methods
  58. 38 |
  59. deduplicateProperties
  60. 39 |
  61. delete
  62. 40 |
  63. insert
  64. 41 |
  65. noSuchMethod
  66. 42 |
  67. toJson
  68. 43 |
  69. toString
  70. 44 |
  71. toVCard
  72. 45 |
  73. update
  74. 46 | 47 |
  75. Operators
  76. 48 |
  77. operator ==
  78. 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 | -------------------------------------------------------------------------------- /doc/api/contact/contact-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Contact
  4. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /doc/api/diacritics/diacritics-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 5 | 6 | 7 | 8 |
  1. Functions
  2. 9 |
  3. removeDiacritics
  4. 10 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /doc/api/flutter_contacts/FlutterContacts-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. FlutterContacts
  4. 5 | 6 | 7 | 8 |
  5. 9 | Properties 10 |
  6. 11 |
  7. hashCode
  8. 12 |
  9. runtimeType
  10. 13 | 14 |
  11. Methods
  12. 15 |
  13. noSuchMethod
  14. 16 |
  15. toString
  16. 17 | 18 |
  17. Operators
  18. 19 |
  19. operator ==
  20. 20 | 21 | 22 | 23 | 24 |
  21. Static properties
  22. 25 |
  23. config
  24. 26 | 27 |
  25. Static methods
  26. 28 |
  27. addListener
  28. 29 |
  29. deleteContact
  30. 30 |
  31. deleteContacts
  32. 31 |
  33. deleteGroup
  34. 32 |
  35. getContact
  36. 33 |
  37. getContacts
  38. 34 |
  39. getGroups
  40. 35 |
  41. insertContact
  42. 36 |
  43. insertGroup
  44. 37 |
  45. openExternalEdit
  46. 38 |
  47. openExternalInsert
  48. 39 |
  49. openExternalPick
  50. 40 |
  51. openExternalView
  52. 41 |
  53. removeListener
  54. 42 |
  55. requestPermission
  56. 43 |
  57. updateContact
  58. 44 |
  59. updateGroup
  60. 45 | 46 |
47 | -------------------------------------------------------------------------------- /doc/api/flutter_contacts/flutter_contacts-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Account
  4. 4 |
  5. Address
  6. 5 |
  7. Contact
  8. 6 |
  9. Email
  10. 7 |
  11. Event
  12. 8 |
  13. FlutterContacts
  14. 9 |
  15. Group
  16. 10 |
  17. Name
  18. 11 |
  19. Note
  20. 12 |
  21. Organization
  22. 13 |
  23. Phone
  24. 14 |
  25. SocialMedia
  26. 15 |
  27. Website
  28. 16 | 17 |
  29. Enums
  30. 18 |
  31. AddressLabel
  32. 19 |
  33. EmailLabel
  34. 20 |
  35. EventLabel
  36. 21 |
  37. PhoneLabel
  38. 22 |
  39. SocialMediaLabel
  40. 23 |
  41. WebsiteLabel
  42. 24 | 25 | 26 | 27 | 28 |
  43. Properties
  44. 29 |
  45. lowerCaseStringToSocialMediaLabel
  46. 30 | 31 | 32 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /doc/api/properties_account/Account-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Account
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. hashCode
  10. 13 |
  11. mimetypes
  12. 14 |
  13. name
  14. 15 |
  15. rawId
  16. 16 |
  17. runtimeType
  18. 17 |
  19. type
  20. 18 | 19 |
  21. Methods
  22. 20 |
  23. noSuchMethod
  24. 21 |
  25. toJson
  26. 22 |
  27. toString
  28. 23 | 24 |
  29. Operators
  30. 25 |
  31. operator ==
  32. 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | -------------------------------------------------------------------------------- /doc/api/properties_account/properties_account-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Account
  4. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /doc/api/properties_address/Address-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Address
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. address
  10. 13 |
  11. city
  12. 14 |
  13. country
  14. 15 |
  15. customLabel
  16. 16 |
  17. hashCode
  18. 17 |
  19. isoCountry
  20. 18 |
  21. label
  22. 19 |
  23. neighborhood
  24. 20 |
  25. pobox
  26. 21 |
  27. postalCode
  28. 22 |
  29. runtimeType
  30. 23 |
  31. state
  32. 24 |
  33. street
  34. 25 |
  35. subAdminArea
  36. 26 |
  37. subLocality
  38. 27 | 28 |
  39. Methods
  40. 29 |
  41. noSuchMethod
  42. 30 |
  43. toJson
  44. 31 |
  45. toString
  46. 32 |
  47. toVCard
  48. 33 | 34 |
  49. Operators
  50. 35 |
  51. operator ==
  52. 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | -------------------------------------------------------------------------------- /doc/api/properties_address/AddressLabel-enum-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. AddressLabel
  4. 5 | 6 |
  5. Values
  6. 7 |
  7. home
  8. 8 |
  9. school
  10. 9 |
  11. work
  12. 10 |
  13. other
  14. 11 |
  15. custom
  16. 12 | 13 | 14 |
  17. 15 | Properties 16 |
  18. 17 |
  19. hashCode
  20. 18 |
  21. index
  22. 19 |
  23. runtimeType
  24. 20 | 21 |
  25. Methods
  26. 22 |
  27. noSuchMethod
  28. 23 |
  29. toString
  30. 24 | 25 |
  31. Operators
  32. 26 |
  33. operator ==
  34. 27 | 28 | 29 | 30 | 31 | 32 | 33 |
  35. Constants
  36. 34 |
  37. values
  38. 35 |
36 | -------------------------------------------------------------------------------- /doc/api/properties_address/properties_address-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Address
  4. 4 | 5 |
  5. Enums
  6. 6 |
  7. AddressLabel
  8. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /doc/api/properties_email/Email-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Email
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. address
  10. 13 |
  11. customLabel
  12. 14 |
  13. hashCode
  14. 15 |
  15. isPrimary
  16. 16 |
  17. label
  18. 17 |
  19. runtimeType
  20. 18 | 19 |
  21. Methods
  22. 20 |
  23. noSuchMethod
  24. 21 |
  25. toJson
  26. 22 |
  27. toString
  28. 23 |
  29. toVCard
  30. 24 | 25 |
  31. Operators
  32. 26 |
  33. operator ==
  34. 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | -------------------------------------------------------------------------------- /doc/api/properties_email/EmailLabel-enum-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. EmailLabel
  4. 5 | 6 |
  5. Values
  6. 7 |
  7. home
  8. 8 |
  9. iCloud
  10. 9 |
  11. mobile
  12. 10 |
  13. school
  14. 11 |
  15. work
  16. 12 |
  17. other
  18. 13 |
  19. custom
  20. 14 | 15 | 16 |
  21. 17 | Properties 18 |
  22. 19 |
  23. hashCode
  24. 20 |
  25. index
  26. 21 |
  27. runtimeType
  28. 22 | 23 |
  29. Methods
  30. 24 |
  31. noSuchMethod
  32. 25 |
  33. toString
  34. 26 | 27 |
  35. Operators
  36. 28 |
  37. operator ==
  38. 29 | 30 | 31 | 32 | 33 | 34 | 35 |
  39. Constants
  40. 36 |
  41. values
  42. 37 |
38 | -------------------------------------------------------------------------------- /doc/api/properties_email/properties_email-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Email
  4. 4 | 5 |
  5. Enums
  6. 6 |
  7. EmailLabel
  8. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /doc/api/properties_event/Event-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Event
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. customLabel
  10. 13 |
  11. day
  12. 14 |
  13. hashCode
  14. 15 |
  15. label
  16. 16 |
  17. month
  18. 17 |
  19. runtimeType
  20. 18 |
  21. year
  22. 19 | 20 |
  23. Methods
  24. 21 |
  25. noSuchMethod
  26. 22 |
  27. toJson
  28. 23 |
  29. toString
  30. 24 |
  31. toVCard
  32. 25 | 26 |
  33. Operators
  34. 27 |
  35. operator ==
  36. 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /doc/api/properties_event/EventLabel-enum-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. EventLabel
  4. 5 | 6 |
  5. Values
  6. 7 |
  7. anniversary
  8. 8 |
  9. birthday
  10. 9 |
  11. other
  12. 10 |
  13. custom
  14. 11 | 12 | 13 |
  15. 14 | Properties 15 |
  16. 16 |
  17. hashCode
  18. 17 |
  19. index
  20. 18 |
  21. runtimeType
  22. 19 | 20 |
  23. Methods
  24. 21 |
  25. noSuchMethod
  26. 22 |
  27. toString
  28. 23 | 24 |
  29. Operators
  30. 25 |
  31. operator ==
  32. 26 | 27 | 28 | 29 | 30 | 31 | 32 |
  33. Constants
  34. 33 |
  35. values
  36. 34 |
35 | -------------------------------------------------------------------------------- /doc/api/properties_event/properties_event-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Event
  4. 4 | 5 |
  5. Enums
  6. 6 |
  7. EventLabel
  8. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /doc/api/properties_group/Group-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Group
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. hashCode
  10. 13 |
  11. id
  12. 14 |
  13. name
  14. 15 |
  15. runtimeType
  16. 16 | 17 |
  17. Methods
  18. 18 |
  19. noSuchMethod
  20. 19 |
  21. toJson
  22. 20 |
  23. toString
  24. 21 | 22 |
  25. Operators
  26. 23 |
  27. operator ==
  28. 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | -------------------------------------------------------------------------------- /doc/api/properties_group/properties_group-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Group
  4. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /doc/api/properties_name/Name-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Name
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. first
  10. 13 |
  11. firstPhonetic
  12. 14 |
  13. hashCode
  14. 15 |
  15. last
  16. 16 |
  17. lastPhonetic
  18. 17 |
  19. middle
  20. 18 |
  21. middlePhonetic
  22. 19 |
  23. nickname
  24. 20 |
  25. prefix
  26. 21 |
  27. runtimeType
  28. 22 |
  29. suffix
  30. 23 | 24 |
  31. Methods
  32. 25 |
  33. noSuchMethod
  34. 26 |
  35. toJson
  36. 27 |
  37. toString
  38. 28 |
  39. toVCard
  40. 29 | 30 |
  41. Operators
  42. 31 |
  43. operator ==
  44. 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | -------------------------------------------------------------------------------- /doc/api/properties_name/properties_name-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Name
  4. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /doc/api/properties_note/Note-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Note
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. hashCode
  10. 13 |
  11. note
  12. 14 |
  13. runtimeType
  14. 15 | 16 |
  15. Methods
  16. 17 |
  17. noSuchMethod
  18. 18 |
  19. toJson
  20. 19 |
  21. toString
  22. 20 |
  23. toVCard
  24. 21 | 22 |
  25. Operators
  26. 23 |
  27. operator ==
  28. 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | -------------------------------------------------------------------------------- /doc/api/properties_note/properties_note-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Note
  4. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /doc/api/properties_organization/Organization-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Organization
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. company
  10. 13 |
  11. department
  12. 14 |
  13. hashCode
  14. 15 |
  15. jobDescription
  16. 16 |
  17. officeLocation
  18. 17 |
  19. phoneticName
  20. 18 |
  21. runtimeType
  22. 19 |
  23. symbol
  24. 20 |
  25. title
  26. 21 | 22 |
  27. Methods
  28. 23 |
  29. noSuchMethod
  30. 24 |
  31. toJson
  32. 25 |
  33. toString
  34. 26 |
  35. toVCard
  36. 27 | 28 |
  37. Operators
  38. 29 |
  39. operator ==
  40. 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | -------------------------------------------------------------------------------- /doc/api/properties_organization/properties_organization-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Organization
  4. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /doc/api/properties_phone/Phone-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Phone
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. customLabel
  10. 13 |
  11. hashCode
  12. 14 |
  13. isPrimary
  14. 15 |
  15. label
  16. 16 |
  17. normalizedNumber
  18. 17 |
  19. number
  20. 18 |
  21. runtimeType
  22. 19 | 20 |
  23. Methods
  24. 21 |
  25. noSuchMethod
  26. 22 |
  27. toJson
  28. 23 |
  29. toString
  30. 24 |
  31. toVCard
  32. 25 | 26 |
  33. Operators
  34. 27 |
  35. operator ==
  36. 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /doc/api/properties_phone/properties_phone-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Phone
  4. 4 | 5 |
  5. Enums
  6. 6 |
  7. PhoneLabel
  8. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /doc/api/properties_social_media/SocialMedia-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. SocialMedia
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. customLabel
  10. 13 |
  11. hashCode
  12. 14 |
  13. label
  14. 15 |
  15. runtimeType
  16. 16 |
  17. userName
  18. 17 | 18 |
  19. Methods
  20. 19 |
  21. noSuchMethod
  22. 20 |
  23. toJson
  24. 21 |
  25. toString
  26. 22 |
  27. toVCard
  28. 23 | 24 |
  29. Operators
  30. 25 |
  31. operator ==
  32. 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | -------------------------------------------------------------------------------- /doc/api/properties_social_media/properties_social_media-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. SocialMedia
  4. 4 | 5 |
  5. Enums
  6. 6 |
  7. SocialMediaLabel
  8. 7 | 8 | 9 | 10 | 11 |
  9. Properties
  10. 12 |
  11. lowerCaseStringToSocialMediaLabel
  12. 13 | 14 | 15 | 16 | 17 |
18 | -------------------------------------------------------------------------------- /doc/api/properties_website/Website-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Website
  4. 5 |
  5. fromJson
  6. 6 | 7 | 8 | 9 |
  7. 10 | Properties 11 |
  8. 12 |
  9. customLabel
  10. 13 |
  11. hashCode
  12. 14 |
  13. label
  14. 15 |
  15. runtimeType
  16. 16 |
  17. url
  18. 17 | 18 |
  19. Methods
  20. 19 |
  21. noSuchMethod
  22. 20 |
  23. toJson
  24. 21 |
  25. toString
  26. 22 |
  27. toVCard
  28. 23 | 24 |
  29. Operators
  30. 25 |
  31. operator ==
  32. 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | -------------------------------------------------------------------------------- /doc/api/properties_website/WebsiteLabel-enum-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. WebsiteLabel
  4. 5 | 6 |
  5. Values
  6. 7 |
  7. blog
  8. 8 |
  9. ftp
  10. 9 |
  11. home
  12. 10 |
  13. homepage
  14. 11 |
  15. profile
  16. 12 |
  17. school
  18. 13 |
  19. work
  20. 14 |
  21. other
  22. 15 |
  23. custom
  24. 16 | 17 | 18 |
  25. 19 | Properties 20 |
  26. 21 |
  27. hashCode
  28. 22 |
  29. index
  30. 23 |
  31. runtimeType
  32. 24 | 25 |
  33. Methods
  34. 26 |
  35. noSuchMethod
  36. 27 |
  37. toString
  38. 28 | 29 |
  39. Operators
  40. 30 |
  41. operator ==
  42. 31 | 32 | 33 | 34 | 35 | 36 | 37 |
  43. Constants
  44. 38 |
  45. values
  46. 39 |
40 | -------------------------------------------------------------------------------- /doc/api/properties_website/properties_website-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Website
  4. 4 | 5 |
  5. Enums
  6. 6 |
  7. WebsiteLabel
  8. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /doc/api/static-assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/doc/api/static-assets/favicon.png -------------------------------------------------------------------------------- /doc/api/static-assets/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | } 14 | 15 | .hljs-comment, 16 | .hljs-quote { 17 | color: #998; 18 | font-style: italic; 19 | } 20 | 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-subst { 24 | color: #333; 25 | font-weight: bold; 26 | } 27 | 28 | .hljs-number, 29 | .hljs-literal, 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-tag .hljs-attr { 33 | color: #008080; 34 | } 35 | 36 | .hljs-string, 37 | .hljs-doctag { 38 | color: #d14; 39 | } 40 | 41 | .hljs-title, 42 | .hljs-section, 43 | .hljs-selector-id { 44 | color: #900; 45 | font-weight: bold; 46 | } 47 | 48 | .hljs-subst { 49 | font-weight: normal; 50 | } 51 | 52 | .hljs-type, 53 | .hljs-class .hljs-title { 54 | color: #458; 55 | font-weight: bold; 56 | } 57 | 58 | .hljs-tag, 59 | .hljs-name, 60 | .hljs-attribute { 61 | color: #000080; 62 | font-weight: normal; 63 | } 64 | 65 | .hljs-regexp, 66 | .hljs-link { 67 | color: #009926; 68 | } 69 | 70 | .hljs-symbol, 71 | .hljs-bullet { 72 | color: #990073; 73 | } 74 | 75 | .hljs-built_in, 76 | .hljs-builtin-name { 77 | color: #0086b3; 78 | } 79 | 80 | .hljs-meta { 81 | color: #999; 82 | font-weight: bold; 83 | } 84 | 85 | .hljs-deletion { 86 | background: #fdd; 87 | } 88 | 89 | .hljs-addition { 90 | background: #dfd; 91 | } 92 | 93 | .hljs-emphasis { 94 | font-style: italic; 95 | } 96 | 97 | .hljs-strong { 98 | font-weight: bold; 99 | } 100 | -------------------------------------------------------------------------------- /doc/api/static-assets/play_button.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/api/static-assets/readme.md: -------------------------------------------------------------------------------- 1 | # Dart documentation generator 2 | 3 | This directory includes static sources used by the Dart documentation generator 4 | through the `dart doc` command. 5 | 6 | To learn more about generating and viewing the generated documentation, 7 | check out the [`dart doc` documentation][]. 8 | 9 | [`dart doc` documentation]: https://dart.dev/tools/dart-doc 10 | 11 | ## Third-party resources 12 | 13 | ## highlight.js 14 | 15 | Generated from https://highlightjs.org/download/ on 2021-07-13. 16 | 17 | **License:** https://github.com/highlightjs/highlight.js/blob/main/LICENSE 18 | 19 | **Included languages:** 20 | 21 | * bash 22 | * c 23 | * css 24 | * dart 25 | * diff 26 | * html, xml 27 | * java 28 | * javascript 29 | * json 30 | * kotlin 31 | * markdown 32 | * objective-c 33 | * plaintext 34 | * shell 35 | * swift 36 | * yaml 37 | -------------------------------------------------------------------------------- /doc/api/static-assets/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/api/vcard/Param-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. Param
  4. 5 | 6 | 7 | 8 |
  5. 9 | Properties 10 |
  6. 11 |
  7. hashCode
  8. 12 |
  9. key
  10. 13 |
  11. runtimeType
  12. 14 |
  13. value
  14. 15 | 16 |
  15. Methods
  16. 17 |
  17. noSuchMethod
  18. 18 |
  19. toString
  20. 19 | 20 |
  21. Operators
  22. 21 |
  23. operator ==
  24. 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | -------------------------------------------------------------------------------- /doc/api/vcard/VCardParser-class-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  1. Constructors
  2. 4 |
  3. VCardParser
  4. 5 | 6 | 7 | 8 |
  5. 9 | Properties 10 |
  6. 11 |
  7. hashCode
  8. 12 |
  9. runtimeType
  10. 13 | 14 |
  11. Methods
  12. 15 |
  13. decode
  14. 16 |
  15. encode
  16. 17 |
  17. noSuchMethod
  18. 18 |
  19. parse
  20. 19 |
  21. toString
  22. 20 |
  23. unfold
  24. 21 | 22 |
  25. Operators
  26. 23 |
  27. operator ==
  28. 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | -------------------------------------------------------------------------------- /doc/api/vcard/vcard-library-sidebar.html: -------------------------------------------------------------------------------- 1 |
    2 |
  1. Classes
  2. 3 |
  3. Param
  4. 4 |
  5. VCardParser
  6. 5 | 6 | 7 | 8 | 9 | 10 | 11 |
  7. Functions
  8. 12 |
  9. vCardEncode
  10. 13 | 14 | 15 | 16 |
17 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c1042314a94e693b4ea92404dab84852e9428442 8 | channel: master 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_contacts_example 2 | 3 | Demonstrates how to use the flutter_contacts plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "dev.flutter.flutter-gradle-plugin" 4 | } 5 | 6 | def localProperties = new Properties() 7 | def localPropertiesFile = rootProject.file('local.properties') 8 | if (localPropertiesFile.exists()) { 9 | localPropertiesFile.withReader('UTF-8') { reader -> 10 | localProperties.load(reader) 11 | } 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | android { 25 | compileSdk 34 26 | 27 | namespace 'co.quis.flutter_contacts_example' 28 | 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_17 31 | targetCompatibility JavaVersion.VERSION_17 32 | } 33 | 34 | sourceSets { 35 | main.java.srcDirs += 'src/main/kotlin' 36 | } 37 | 38 | lintOptions { 39 | disable 'InvalidPackage' 40 | } 41 | 42 | defaultConfig { 43 | applicationId "co.quis.flutter_contacts_example" 44 | minSdk 21 45 | targetSdk 34 46 | versionCode flutterVersionCode.toInteger() 47 | versionName flutterVersionName 48 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 49 | } 50 | 51 | buildTypes { 52 | release { 53 | // TODO: Add your own signing config for the release build. 54 | // Signing with the debug keys for now, so `flutter run --release` works. 55 | signingConfig signingConfigs.debug 56 | } 57 | } 58 | } 59 | 60 | flutter { 61 | source '../..' 62 | } 63 | 64 | dependencies { 65 | testImplementation 'junit:junit:4.13.2' 66 | androidTestImplementation 'androidx.test:runner:1.6.1' 67 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' 68 | } -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/co/quis/flutter_contacts_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity : FlutterActivity() 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.3.1" apply false 22 | } 23 | 24 | include ":app" 25 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_contacts (0.0.1): 4 | - Flutter 5 | 6 | DEPENDENCIES: 7 | - Flutter (from `Flutter`) 8 | - flutter_contacts (from `.symlinks/plugins/flutter_contacts/ios`) 9 | 10 | EXTERNAL SOURCES: 11 | Flutter: 12 | :path: Flutter 13 | flutter_contacts: 14 | :path: ".symlinks/plugins/flutter_contacts/ios" 15 | 16 | SPEC CHECKSUMS: 17 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 18 | flutter_contacts: edb1c5ce76aa433e20e6cb14c615f4c0b66e0983 19 | 20 | PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 21 | 22 | COCOAPODS: 1.15.2 23 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_contacts_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | NSContactsUsageDescription 45 | Access contact list 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIApplicationSupportsIndirectInputEvents 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_contacts/flutter_contacts.dart'; 3 | 4 | void main() => runApp(FlutterContactsExample()); 5 | 6 | class FlutterContactsExample extends StatefulWidget { 7 | @override 8 | _FlutterContactsExampleState createState() => _FlutterContactsExampleState(); 9 | } 10 | 11 | class _FlutterContactsExampleState extends State { 12 | List? _contacts; 13 | bool _permissionDenied = false; 14 | 15 | @override 16 | void initState() { 17 | super.initState(); 18 | _fetchContacts(); 19 | } 20 | 21 | Future _fetchContacts() async { 22 | if (!await FlutterContacts.requestPermission(readonly: true)) { 23 | setState(() => _permissionDenied = true); 24 | } else { 25 | final contacts = await FlutterContacts.getContacts(); 26 | setState(() => _contacts = contacts); 27 | } 28 | } 29 | 30 | @override 31 | Widget build(BuildContext context) => MaterialApp( 32 | home: Scaffold( 33 | appBar: AppBar(title: Text('flutter_contacts_example')), 34 | body: _body())); 35 | 36 | Widget _body() { 37 | if (_permissionDenied) return Center(child: Text('Permission denied')); 38 | if (_contacts == null) return Center(child: CircularProgressIndicator()); 39 | return ListView.builder( 40 | itemCount: _contacts!.length, 41 | itemBuilder: (context, i) => ListTile( 42 | title: Text(_contacts![i].displayName), 43 | onTap: () async { 44 | final fullContact = 45 | await FlutterContacts.getContact(_contacts![i].id); 46 | await Navigator.of(context).push( 47 | MaterialPageRoute(builder: (_) => ContactPage(fullContact!))); 48 | })); 49 | } 50 | } 51 | 52 | class ContactPage extends StatelessWidget { 53 | final Contact contact; 54 | ContactPage(this.contact); 55 | 56 | @override 57 | Widget build(BuildContext context) => Scaffold( 58 | appBar: AppBar(title: Text(contact.displayName)), 59 | body: Column(children: [ 60 | Text('First name: ${contact.name.first}'), 61 | Text('Last name: ${contact.name.last}'), 62 | Text( 63 | 'Phone number: ${contact.phones.isNotEmpty ? contact.phones.first.number : '(none)'}'), 64 | Text( 65 | 'Email address: ${contact.emails.isNotEmpty ? contact.emails.first.address : '(none)'}'), 66 | ])); 67 | } 68 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_contacts_example 2 | description: Demonstrates how to use the flutter_contacts plugin. 3 | publish_to: "none" 4 | 5 | environment: 6 | sdk: ">=2.12.0-0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | flutter_contacts: 12 | path: ../ 13 | 14 | flutter: 15 | uses-material-design: true 16 | -------------------------------------------------------------------------------- /example_full/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | 39 | pubspec.lock -------------------------------------------------------------------------------- /example_full/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: f139b11009aeb8ed2a3a3aa8b0066e482709dde3 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example_full/README.md: -------------------------------------------------------------------------------- 1 | # flutter_contacts_example 2 | 3 | Demonstrates how to use the flutter_contacts plugin. -------------------------------------------------------------------------------- /example_full/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /example_full/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "dev.flutter.flutter-gradle-plugin" 4 | } 5 | 6 | def localProperties = new Properties() 7 | def localPropertiesFile = rootProject.file('local.properties') 8 | if (localPropertiesFile.exists()) { 9 | localPropertiesFile.withReader('UTF-8') { reader -> 10 | localProperties.load(reader) 11 | } 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | android { 25 | compileSdk 34 26 | 27 | namespace 'co.quis.flutter_contacts_example' 28 | 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_17 31 | targetCompatibility JavaVersion.VERSION_17 32 | } 33 | 34 | sourceSets { 35 | main.java.srcDirs += 'src/main/kotlin' 36 | } 37 | 38 | lintOptions { 39 | disable 'InvalidPackage' 40 | } 41 | 42 | defaultConfig { 43 | applicationId "co.quis.flutter_contacts_example" 44 | minSdk 21 45 | targetSdk 34 46 | versionCode flutterVersionCode.toInteger() 47 | versionName flutterVersionName 48 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 49 | } 50 | 51 | buildTypes { 52 | release { 53 | // TODO: Add your own signing config for the release build. 54 | // Signing with the debug keys for now, so `flutter run --release` works. 55 | signingConfig signingConfigs.debug 56 | } 57 | } 58 | } 59 | 60 | flutter { 61 | source '../..' 62 | } 63 | 64 | dependencies { 65 | testImplementation 'junit:junit:4.13.2' 66 | androidTestImplementation 'androidx.test:runner:1.6.1' 67 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' 68 | } -------------------------------------------------------------------------------- /example_full/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example_full/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example_full/android/app/src/main/kotlin/co/quis/flutter_contacts_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package co.quis.flutter_contacts_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity : FlutterActivity() 6 | -------------------------------------------------------------------------------- /example_full/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example_full/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example_full/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example_full/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example_full/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example_full/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example_full/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example_full/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example_full/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example_full/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /example_full/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip 7 | -------------------------------------------------------------------------------- /example_full/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.3.1" apply false 22 | } 23 | 24 | include ":app" 25 | -------------------------------------------------------------------------------- /example_full/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example_full/ios/Flutter/.last_build_id: -------------------------------------------------------------------------------- 1 | 822131e42e6e229d1550608792c18706 -------------------------------------------------------------------------------- /example_full/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example_full/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example_full/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example_full/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /example_full/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_contacts (0.0.1): 4 | - Flutter 5 | - image_picker_ios (0.0.1): 6 | - Flutter 7 | 8 | DEPENDENCIES: 9 | - Flutter (from `Flutter`) 10 | - flutter_contacts (from `.symlinks/plugins/flutter_contacts/ios`) 11 | - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) 12 | 13 | EXTERNAL SOURCES: 14 | Flutter: 15 | :path: Flutter 16 | flutter_contacts: 17 | :path: ".symlinks/plugins/flutter_contacts/ios" 18 | image_picker_ios: 19 | :path: ".symlinks/plugins/image_picker_ios/ios" 20 | 21 | SPEC CHECKSUMS: 22 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 23 | flutter_contacts: edb1c5ce76aa433e20e6cb14c615f4c0b66e0983 24 | image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 25 | 26 | PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 27 | 28 | COCOAPODS: 1.15.2 29 | -------------------------------------------------------------------------------- /example_full/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example_full/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example_full/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example_full/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example_full/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example_full/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example_full/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example_full/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example_full/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_contacts_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | NSContactsUsageDescription 47 | Access contact list 48 | 49 | 50 | NSCameraUsageDescription 51 | Access camera to add contact pictures 52 | CADisableMinimumFrameDurationOnPhone 53 | 54 | UIApplicationSupportsIndirectInputEvents 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /example_full/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /example_full/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'pages/contact_list_page.dart'; 4 | import 'pages/contact_page.dart'; 5 | import 'pages/edit_contact_page.dart'; 6 | import 'pages/groups_page.dart'; 7 | 8 | void main() => runApp(FlutterContactsExample()); 9 | 10 | class FlutterContactsExample extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | title: 'flutter_contacts_example', 15 | theme: ThemeData( 16 | primarySwatch: Colors.blue, 17 | ), 18 | initialRoute: '/contactList', 19 | routes: { 20 | '/contactList': (context) => ContactListPage(), 21 | '/contact': (context) => ContactPage(), 22 | '/editContact': (context) => EditContactPage(), 23 | '/groups': (context) => GroupsPage(), 24 | }, 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /example_full/lib/pages/form_components/email_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_contacts/properties/email.dart'; 3 | 4 | class EmailForm extends StatefulWidget { 5 | final Email email; 6 | final void Function(Email) onUpdate; 7 | final void Function() onDelete; 8 | 9 | EmailForm( 10 | this.email, { 11 | required this.onUpdate, 12 | required this.onDelete, 13 | Key? key, 14 | }) : super(key: key); 15 | 16 | @override 17 | _EmailFormState createState() => _EmailFormState(); 18 | } 19 | 20 | class _EmailFormState extends State { 21 | final _formKey = GlobalKey(); 22 | static final _validLabels = EmailLabel.values; 23 | 24 | late TextEditingController _addressController; 25 | late EmailLabel _label; 26 | late TextEditingController _customLabelController; 27 | 28 | @override 29 | void initState() { 30 | super.initState(); 31 | _addressController = TextEditingController(text: widget.email.address); 32 | _label = widget.email.label; 33 | _customLabelController = 34 | TextEditingController(text: widget.email.customLabel); 35 | } 36 | 37 | void _onChanged() { 38 | final email = Email( 39 | _addressController.text, 40 | label: _label, 41 | customLabel: 42 | _label == EmailLabel.custom ? _customLabelController.text : '', 43 | ); 44 | widget.onUpdate(email); 45 | } 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | return ListTile( 50 | trailing: PopupMenuButton( 51 | itemBuilder: (context) => 52 | [PopupMenuItem(value: 'Delete', child: Text('Delete'))], 53 | onSelected: (_) => widget.onDelete(), 54 | ), 55 | subtitle: Padding( 56 | padding: const EdgeInsets.all(8.0), 57 | child: Form( 58 | key: _formKey, 59 | onChanged: _onChanged, 60 | child: Column( 61 | children: [ 62 | TextFormField( 63 | controller: _addressController, 64 | keyboardType: TextInputType.emailAddress, 65 | decoration: InputDecoration(hintText: 'Address'), 66 | ), 67 | DropdownButtonFormField( 68 | isExpanded: true, // to avoid overflow 69 | items: _validLabels 70 | .map((e) => DropdownMenuItem( 71 | value: e, child: Text(e.toString()))) 72 | .toList(), 73 | value: _label, 74 | onChanged: (EmailLabel? label) { 75 | setState(() { 76 | if (label != null) _label = label; 77 | }); 78 | // Unfortunately, the form's `onChanged` gets triggered before 79 | // the dropdown's `onChanged`, so it doesn't update the 80 | // contact when updating the dropdown, and we need to do it 81 | // explicitly here. 82 | _onChanged(); 83 | }, 84 | ), 85 | _label == EmailLabel.custom 86 | ? TextFormField( 87 | controller: _customLabelController, 88 | textCapitalization: TextCapitalization.sentences, 89 | decoration: InputDecoration(hintText: 'Custom label'), 90 | ) 91 | : Container(), 92 | ], 93 | ), 94 | ), 95 | ), 96 | ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /example_full/lib/pages/form_components/note_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_contacts/properties/note.dart'; 3 | 4 | class NoteForm extends StatefulWidget { 5 | final Note note; 6 | final void Function(Note)? onUpdate; 7 | final void Function() onDelete; 8 | 9 | NoteForm( 10 | this.note, { 11 | required this.onUpdate, 12 | required this.onDelete, 13 | Key? key, 14 | }) : super(key: key); 15 | 16 | @override 17 | _NoteFormState createState() => _NoteFormState(); 18 | } 19 | 20 | class _NoteFormState extends State { 21 | final _formKey = GlobalKey(); 22 | 23 | late TextEditingController _noteController; 24 | 25 | @override 26 | void initState() { 27 | super.initState(); 28 | _noteController = TextEditingController(text: widget.note.note); 29 | } 30 | 31 | void _onChanged() { 32 | final note = Note( 33 | _noteController.text, 34 | ); 35 | if (widget.onUpdate != null) widget.onUpdate!(note); 36 | } 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | return ListTile( 41 | trailing: PopupMenuButton( 42 | itemBuilder: (context) => 43 | [PopupMenuItem(value: 'Delete', child: Text('Delete'))], 44 | onSelected: (_) => widget.onDelete(), 45 | ), 46 | subtitle: Padding( 47 | padding: const EdgeInsets.all(8.0), 48 | child: Form( 49 | key: _formKey, 50 | onChanged: _onChanged, 51 | child: Column( 52 | children: [ 53 | TextFormField( 54 | controller: _noteController, 55 | keyboardType: TextInputType.multiline, 56 | textCapitalization: TextCapitalization.sentences, 57 | maxLines: null, 58 | minLines: 3, 59 | decoration: InputDecoration(hintText: 'Note'), 60 | ), 61 | ], 62 | ), 63 | ), 64 | ), 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /example_full/lib/pages/form_components/phone_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_contacts/properties/phone.dart'; 3 | 4 | class PhoneForm extends StatefulWidget { 5 | final Phone phone; 6 | final void Function(Phone) onUpdate; 7 | final void Function() onDelete; 8 | 9 | PhoneForm( 10 | this.phone, { 11 | required this.onUpdate, 12 | required this.onDelete, 13 | Key? key, 14 | }) : super(key: key); 15 | 16 | @override 17 | _PhoneFormState createState() => _PhoneFormState(); 18 | } 19 | 20 | class _PhoneFormState extends State { 21 | final _formKey = GlobalKey(); 22 | static final _validLabels = PhoneLabel.values; 23 | 24 | late TextEditingController _numberController; 25 | late PhoneLabel _label; 26 | late TextEditingController _customLabelController; 27 | 28 | @override 29 | void initState() { 30 | super.initState(); 31 | _numberController = TextEditingController(text: widget.phone.number); 32 | _label = widget.phone.label; 33 | _customLabelController = 34 | TextEditingController(text: widget.phone.customLabel); 35 | } 36 | 37 | void _onChanged() { 38 | final phone = Phone(_numberController.text, 39 | label: _label, 40 | customLabel: 41 | _label == PhoneLabel.custom ? _customLabelController.text : ''); 42 | widget.onUpdate(phone); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return ListTile( 48 | trailing: PopupMenuButton( 49 | itemBuilder: (context) => 50 | [PopupMenuItem(value: 'Delete', child: Text('Delete'))], 51 | onSelected: (_) => widget.onDelete(), 52 | ), 53 | subtitle: Padding( 54 | padding: const EdgeInsets.all(8.0), 55 | child: Form( 56 | key: _formKey, 57 | onChanged: _onChanged, 58 | child: Column( 59 | children: [ 60 | TextFormField( 61 | controller: _numberController, 62 | keyboardType: TextInputType.phone, 63 | decoration: InputDecoration(hintText: 'Phone'), 64 | ), 65 | DropdownButtonFormField( 66 | isExpanded: true, // to avoid overflow 67 | items: _validLabels 68 | .map((e) => DropdownMenuItem( 69 | value: e, child: Text(e.toString()))) 70 | .toList(), 71 | value: _label, 72 | onChanged: (PhoneLabel? label) { 73 | setState(() { 74 | if (label != null) _label = label; 75 | }); 76 | // Unfortunately, the form's `onChanged` gets triggered before 77 | // the dropdown's `onChanged`, so it doesn't update the 78 | // contact when updating the dropdown, and we need to do it 79 | // explicitly here. 80 | _onChanged(); 81 | }, 82 | ), 83 | _label == PhoneLabel.custom 84 | ? TextFormField( 85 | controller: _customLabelController, 86 | textCapitalization: TextCapitalization.sentences, 87 | decoration: InputDecoration(hintText: 'Custom label'), 88 | ) 89 | : Container(), 90 | ], 91 | ), 92 | ), 93 | ), 94 | ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /example_full/lib/pages/form_components/website_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_contacts/properties/website.dart'; 3 | 4 | class WebsiteForm extends StatefulWidget { 5 | final Website website; 6 | final void Function(Website) onUpdate; 7 | final void Function() onDelete; 8 | 9 | WebsiteForm( 10 | this.website, { 11 | required this.onUpdate, 12 | required this.onDelete, 13 | Key? key, 14 | }) : super(key: key); 15 | 16 | @override 17 | _WebsiteFormState createState() => _WebsiteFormState(); 18 | } 19 | 20 | class _WebsiteFormState extends State { 21 | final _formKey = GlobalKey(); 22 | static final _validLabels = WebsiteLabel.values; 23 | 24 | late TextEditingController _urlController; 25 | late WebsiteLabel _label; 26 | late TextEditingController _customLabelController; 27 | 28 | @override 29 | void initState() { 30 | super.initState(); 31 | _urlController = TextEditingController(text: widget.website.url); 32 | _label = widget.website.label; 33 | _customLabelController = 34 | TextEditingController(text: widget.website.customLabel); 35 | } 36 | 37 | void _onChanged() { 38 | final website = Website( 39 | _urlController.text, 40 | label: _label, 41 | customLabel: 42 | _label == WebsiteLabel.custom ? _customLabelController.text : '', 43 | ); 44 | widget.onUpdate(website); 45 | } 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | return ListTile( 50 | trailing: PopupMenuButton( 51 | itemBuilder: (context) => 52 | [PopupMenuItem(value: 'Delete', child: Text('Delete'))], 53 | onSelected: (_) => widget.onDelete(), 54 | ), 55 | subtitle: Padding( 56 | padding: const EdgeInsets.all(8.0), 57 | child: Form( 58 | key: _formKey, 59 | onChanged: _onChanged, 60 | child: Column( 61 | children: [ 62 | TextFormField( 63 | controller: _urlController, 64 | keyboardType: TextInputType.url, 65 | decoration: InputDecoration(hintText: 'URL'), 66 | ), 67 | DropdownButtonFormField( 68 | isExpanded: true, // to avoid overflow 69 | items: _validLabels 70 | .map((e) => DropdownMenuItem( 71 | value: e, child: Text(e.toString()))) 72 | .toList(), 73 | value: _label, 74 | onChanged: (WebsiteLabel? label) { 75 | setState(() { 76 | if (label != null) _label = label; 77 | }); 78 | // Unfortunately, the form's `onChanged` gets triggered before 79 | // the dropdown's `onChanged`, so it doesn't update the 80 | // contact when updating the dropdown, and we need to do it 81 | // explicitly here. 82 | _onChanged(); 83 | }, 84 | ), 85 | _label == WebsiteLabel.custom 86 | ? TextFormField( 87 | controller: _customLabelController, 88 | textCapitalization: TextCapitalization.sentences, 89 | decoration: InputDecoration(hintText: 'Custom label'), 90 | ) 91 | : Container(), 92 | ], 93 | ), 94 | ), 95 | ), 96 | ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /example_full/lib/pages/groups_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:after_layout/after_layout.dart'; 2 | import 'package:flutter_contacts/flutter_contacts.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:prompt_dialog/prompt_dialog.dart'; 5 | 6 | class GroupsPage extends StatefulWidget { 7 | @override 8 | _GroupsPageState createState() => _GroupsPageState(); 9 | } 10 | 11 | class _GroupsPageState extends State 12 | with AfterLayoutMixin { 13 | List? _groups; 14 | 15 | @override 16 | void afterFirstLayout(BuildContext context) { 17 | _fetchGroups(); 18 | } 19 | 20 | Future _fetchGroups() async { 21 | final groups = await FlutterContacts.getGroups(); 22 | setState(() => _groups = groups); 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) => Scaffold( 27 | appBar: AppBar( 28 | title: Text('flutter_contacts_example - groups'), 29 | ), 30 | body: _body(), 31 | floatingActionButton: FloatingActionButton( 32 | onPressed: _newGroup, 33 | child: Icon(Icons.add), 34 | ), 35 | ); 36 | 37 | Widget _body() { 38 | if (_groups == null) { 39 | return Center(child: CircularProgressIndicator()); 40 | } 41 | return ListView.builder( 42 | itemCount: _groups!.length, 43 | itemBuilder: (context, i) { 44 | final group = _groups![i]; 45 | return ListTile( 46 | title: Text('${group.name} (id=${group.id})'), 47 | trailing: Row( 48 | mainAxisSize: MainAxisSize.min, 49 | children: [ 50 | IconButton( 51 | onPressed: () => _renameGroup(group), 52 | icon: Icon(Icons.edit), 53 | ), 54 | IconButton( 55 | onPressed: () => _deleteGroup(group), 56 | icon: Icon(Icons.delete), 57 | ), 58 | ], 59 | ), 60 | onTap: () => _renameGroup(group), 61 | ); 62 | }); 63 | } 64 | 65 | Future _newGroup() async { 66 | final name = await prompt(context); 67 | if (name != null && name.isNotEmpty) { 68 | final group = await FlutterContacts.insertGroup(Group('', name)); 69 | print('Inserted group $group'); 70 | await _fetchGroups(); 71 | } 72 | } 73 | 74 | Future _renameGroup(Group group) async { 75 | final name = await prompt(context, initialValue: group.name); 76 | if (name != null && name.isNotEmpty) { 77 | final updatedGroup = 78 | await FlutterContacts.updateGroup(Group(group.id, name)); 79 | print('Updated group $updatedGroup'); 80 | await _fetchGroups(); 81 | } 82 | } 83 | 84 | Future _deleteGroup(Group group) async { 85 | await FlutterContacts.deleteGroup(group); 86 | print('Deleted group $group'); 87 | await _fetchGroups(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /example_full/lib/util/avatar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_contacts/contact.dart'; 3 | 4 | Widget avatar(Contact contact, 5 | [double radius = 48.0, IconData defaultIcon = Icons.person]) { 6 | if (contact.photoOrThumbnail != null) { 7 | return CircleAvatar( 8 | backgroundImage: MemoryImage(contact.photoOrThumbnail!), 9 | radius: radius, 10 | ); 11 | } 12 | return CircleAvatar( 13 | radius: radius, 14 | child: Icon(defaultIcon), 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /example_full/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_contacts_example 2 | description: Demonstrates how to use the flutter_contacts plugin. 3 | publish_to: "none" 4 | 5 | environment: 6 | sdk: ">=2.12.0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | after_layout: ^1.2.0 12 | flutter_contacts: 13 | path: ../ 14 | image_picker: ^1.1.1 15 | pretty_json: ^2.0.0 16 | prompt_dialog: ^1.0.16 17 | 18 | flutter: 19 | uses-material-design: true 20 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuisApp/flutter_contacts/6d4b7cebd84059af04923cd206fbb58affab7f57/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/FlutterContactsPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FlutterContactsPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /ios/Classes/FlutterContactsPlugin.m: -------------------------------------------------------------------------------- 1 | #import "FlutterContactsPlugin.h" 2 | #if __has_include() 3 | #import 4 | #else 5 | // Support project import fallback if the generated compatibility header 6 | // is not copied when this plugin is created as a library. 7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 8 | #import "flutter_contacts-Swift.h" 9 | #endif 10 | 11 | @implementation FlutterContactsPlugin 12 | + (void)registerWithRegistrar:(NSObject*)registrar { 13 | [SwiftFlutterContactsPlugin registerWithRegistrar:registrar]; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Classes/properties/Account.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Account { 5 | var rawId: String 6 | // local, exchange, cardDAV or unassigned 7 | var type: String 8 | var name: String 9 | 10 | init(fromMap m: [String: Any]) { 11 | rawId = m["rawId"] as! String 12 | type = m["type"] as! String 13 | name = m["name"] as! String 14 | } 15 | 16 | init(fromContainer c: CNContainer) { 17 | rawId = c.identifier 18 | name = c.name 19 | switch c.type { 20 | case .local: 21 | type = "local" 22 | case .exchange: 23 | type = "exchange" 24 | case .cardDAV: 25 | type = "cardDAV" 26 | case .unassigned: 27 | type = "unassigned" 28 | default: 29 | type = "unassigned" 30 | } 31 | } 32 | 33 | func toMap() -> [String: Any] { [ 34 | "rawId": rawId, 35 | "type": type, 36 | "name": name, 37 | "mimetypes": [String](), // not available on iOS 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ios/Classes/properties/Email.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Email { 5 | var address: String 6 | // one of: home, iCloud, mobile, school, work, other, custom 7 | var label: String = "home" 8 | var customLabel: String = "" 9 | var isPrimary: Bool = false // not supported on iOS 10 | 11 | init(fromMap m: [String: Any]) { 12 | address = m["address"] as! String 13 | label = m["label"] as! String 14 | customLabel = m["customLabel"] as! String 15 | isPrimary = m["isPrimary"] as! Bool 16 | } 17 | 18 | init(fromEmail e: CNLabeledValue) { 19 | address = e.value as String 20 | switch e.label { 21 | case CNLabelHome: 22 | label = "home" 23 | case CNLabelEmailiCloud: 24 | label = "iCloud" 25 | case CNLabelWork: 26 | label = "work" 27 | case CNLabelOther: 28 | label = "other" 29 | default: 30 | if #available(iOS 13, *), e.label == CNLabelSchool { 31 | label = "school" 32 | } else { 33 | label = "custom" 34 | customLabel = e.label ?? "" 35 | } 36 | } 37 | } 38 | 39 | func toMap() -> [String: Any] { [ 40 | "address": address, 41 | "label": label, 42 | "customLabel": customLabel, 43 | "isPrimary": isPrimary, 44 | ] 45 | } 46 | 47 | func addTo(_ c: CNMutableContact) { 48 | var labelInv: String 49 | switch label { 50 | case "home": 51 | labelInv = CNLabelHome 52 | case "iCloud": 53 | labelInv = CNLabelEmailiCloud 54 | case "school": 55 | if #available(iOS 13, *) { 56 | labelInv = CNLabelSchool 57 | } else { 58 | labelInv = "school" 59 | } 60 | case "work": 61 | labelInv = CNLabelWork 62 | case "other": 63 | labelInv = CNLabelOther 64 | case "custom": 65 | labelInv = customLabel 66 | default: 67 | labelInv = label 68 | } 69 | c.emailAddresses.append( 70 | CNLabeledValue( 71 | label: labelInv, 72 | value: address as NSString 73 | ) 74 | ) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /ios/Classes/properties/Event.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Event { 5 | var year: Int? 6 | var month: Int 7 | var day: Int 8 | // one of: anniversary, birthday, other, custom 9 | var label: String = "birthday" 10 | var customLabel: String = "" 11 | 12 | init(fromMap m: [String: Any?]) { 13 | year = m["year"] as? Int 14 | month = m["month"] as! Int 15 | day = m["day"] as! Int 16 | label = m["label"] as! String 17 | customLabel = m["customLabel"] as! String 18 | } 19 | 20 | init(fromContact c: CNContact) { 21 | // It seems like NSDateComponents use 2^64-1 as a value for year when there is 22 | // no year. This should cover similar edge cases. 23 | let y = c.birthday!.year 24 | year = (y == nil || y! < -100_000 || y! > 100_000) ? nil : y 25 | year = c.birthday!.year 26 | month = c.birthday!.month ?? 1 27 | day = c.birthday!.day ?? 1 28 | label = "birthday" 29 | } 30 | 31 | init(fromDate d: CNLabeledValue) { 32 | // It seems like NSDateComponents use 2^64-1 as a value for year when there is 33 | // no year. This should cover similar edge cases. 34 | let y = d.value.year 35 | year = (y < -100_000 || y > 100_000) ? nil : y 36 | month = d.value.month 37 | day = d.value.day 38 | switch d.label { 39 | case CNLabelDateAnniversary: 40 | label = "anniversary" 41 | case CNLabelOther: 42 | label = "other" 43 | default: 44 | label = "custom" 45 | customLabel = d.label ?? "" 46 | } 47 | } 48 | 49 | func toMap() -> [String: Any?] { [ 50 | "year": year, 51 | "month": month, 52 | "day": day, 53 | "label": label, 54 | "customLabel": customLabel, 55 | ] 56 | } 57 | 58 | func addTo(_ c: CNMutableContact) { 59 | var dateComponents: DateComponents 60 | if year == nil { 61 | dateComponents = DateComponents(month: month, day: day) 62 | } else { 63 | dateComponents = DateComponents(year: year, month: month, day: day) 64 | } 65 | if label == "birthday" { 66 | c.birthday = dateComponents 67 | } else { 68 | var labelInv: String 69 | switch label { 70 | case "anniversary": 71 | labelInv = CNLabelDateAnniversary 72 | case "other": 73 | labelInv = CNLabelOther 74 | case "custom": 75 | labelInv = customLabel 76 | default: 77 | labelInv = label 78 | } 79 | c.dates.append( 80 | CNLabeledValue( 81 | label: labelInv, 82 | value: dateComponents as NSDateComponents 83 | ) 84 | ) 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /ios/Classes/properties/Group.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Group { 5 | var id: String 6 | var name: String 7 | 8 | init(fromMap m: [String: Any]) { 9 | id = m["id"] as! String 10 | name = m["name"] as! String 11 | } 12 | 13 | init(fromGroup g: CNGroup) { 14 | id = g.identifier 15 | name = g.name 16 | } 17 | 18 | func toMap() -> [String: Any] { [ 19 | "id": id, 20 | "name": name, 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Classes/properties/Name.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Name { 5 | var first: String = "" 6 | var last: String = "" 7 | var middle: String = "" 8 | var prefix: String = "" 9 | var suffix: String = "" 10 | var nickname: String = "" 11 | var firstPhonetic: String = "" 12 | var lastPhonetic: String = "" 13 | var middlePhonetic: String = "" 14 | 15 | init() {} 16 | 17 | init(fromMap m: [String: Any]) { 18 | first = m["first"] as! String 19 | last = m["last"] as! String 20 | middle = m["middle"] as! String 21 | prefix = m["prefix"] as! String 22 | suffix = m["suffix"] as! String 23 | nickname = m["nickname"] as! String 24 | firstPhonetic = m["firstPhonetic"] as! String 25 | lastPhonetic = m["lastPhonetic"] as! String 26 | middlePhonetic = m["middlePhonetic"] as! String 27 | } 28 | 29 | init(fromContact c: CNContact) { 30 | first = c.givenName 31 | last = c.familyName 32 | middle = c.middleName 33 | prefix = c.namePrefix 34 | suffix = c.nameSuffix 35 | nickname = c.nickname 36 | firstPhonetic = c.phoneticGivenName 37 | lastPhonetic = c.phoneticFamilyName 38 | middlePhonetic = c.phoneticMiddleName 39 | } 40 | 41 | func toMap() -> [String: Any] { [ 42 | "first": first, 43 | "last": last, 44 | "middle": middle, 45 | "prefix": prefix, 46 | "suffix": suffix, 47 | "nickname": nickname, 48 | "firstPhonetic": firstPhonetic, 49 | "lastPhonetic": lastPhonetic, 50 | "middlePhonetic": middlePhonetic, 51 | ] 52 | } 53 | 54 | func addTo(_ c: CNMutableContact) { 55 | c.givenName = first 56 | c.familyName = last 57 | c.middleName = middle 58 | c.namePrefix = prefix 59 | c.nameSuffix = suffix 60 | c.nickname = nickname 61 | c.phoneticGivenName = firstPhonetic 62 | c.phoneticFamilyName = lastPhonetic 63 | c.phoneticMiddleName = middlePhonetic 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ios/Classes/properties/Note.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Note { 5 | var note: String 6 | 7 | init(fromMap m: [String: Any]) { 8 | note = m["note"] as! String 9 | } 10 | 11 | init(fromContact c: CNContact) { 12 | note = c.note 13 | } 14 | 15 | func toMap() -> [String: Any] { [ 16 | "note": note, 17 | ] 18 | } 19 | 20 | func addTo(_ c: CNMutableContact) { 21 | c.note = note 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Classes/properties/Organization.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Organization { 5 | var company: String = "" 6 | var title: String = "" 7 | var department: String = "" 8 | var jobDescription: String = "" 9 | var symbol: String = "" 10 | var phoneticName: String = "" 11 | var officeLocation: String = "" 12 | 13 | init(fromMap m: [String: Any]) { 14 | company = m["company"] as! String 15 | title = m["title"] as! String 16 | department = m["department"] as! String 17 | jobDescription = m["jobDescription"] as! String 18 | symbol = m["symbol"] as! String 19 | phoneticName = m["phoneticName"] as! String 20 | officeLocation = m["officeLocation"] as! String 21 | } 22 | 23 | init(fromContact c: CNContact) { 24 | company = c.organizationName 25 | title = c.jobTitle 26 | department = c.departmentName 27 | // jobDescription, symbol and officeLocation not supported 28 | if #available(iOS 10, *) { 29 | phoneticName = c.phoneticOrganizationName 30 | } 31 | } 32 | 33 | func toMap() -> [String: Any] { [ 34 | "company": company, 35 | "title": title, 36 | "department": department, 37 | "jobDescription": jobDescription, 38 | "symbol": symbol, 39 | "phoneticName": phoneticName, 40 | "officeLocation": officeLocation, 41 | ] 42 | } 43 | 44 | func addTo(_ c: CNMutableContact) { 45 | c.organizationName = company 46 | c.jobTitle = title 47 | c.departmentName = department 48 | if #available(iOS 10, *) { 49 | c.phoneticOrganizationName = phoneticName 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ios/Classes/properties/Website.swift: -------------------------------------------------------------------------------- 1 | import Contacts 2 | 3 | @available(iOS 9.0, *) 4 | struct Website { 5 | var url: String 6 | // one of: blog, ftp, home, homepage, profile, school, work, other, custom 7 | var label: String = "homepage" 8 | var customLabel: String = "" 9 | 10 | init(fromMap m: [String: Any]) { 11 | url = m["url"] as! String 12 | label = m["label"] as! String 13 | customLabel = m["customLabel"] as! String 14 | } 15 | 16 | init(fromWebsite w: CNLabeledValue) { 17 | url = w.value as String 18 | switch w.label { 19 | case CNLabelHome: 20 | label = "home" 21 | case CNLabelURLAddressHomePage: 22 | label = "homepage" 23 | case CNLabelWork: 24 | label = "work" 25 | case CNLabelOther: 26 | label = "other" 27 | default: 28 | if #available(iOS 13, *), w.label == CNLabelSchool { 29 | label = "school" 30 | } else { 31 | label = "custom" 32 | customLabel = w.label ?? "" 33 | } 34 | } 35 | } 36 | 37 | func toMap() -> [String: Any] { [ 38 | "url": url, 39 | "label": label, 40 | "customLabel": customLabel, 41 | ] 42 | } 43 | 44 | func addTo(_ c: CNMutableContact) { 45 | var labelInv: String 46 | switch label { 47 | case "home": 48 | labelInv = CNLabelHome 49 | case "homepage": 50 | labelInv = CNLabelURLAddressHomePage 51 | case "school": 52 | if #available(iOS 13, *) { 53 | labelInv = CNLabelSchool 54 | } else { 55 | labelInv = "school" 56 | } 57 | case "work": 58 | labelInv = CNLabelWork 59 | case "other": 60 | labelInv = CNLabelOther 61 | case "custom": 62 | labelInv = customLabel 63 | default: 64 | labelInv = label 65 | } 66 | c.urlAddresses.append( 67 | CNLabeledValue( 68 | label: labelInv, 69 | value: url as NSString 70 | ) 71 | ) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ios/flutter_contacts.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint flutter_contacts.podspec' to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'flutter_contacts' 7 | s.version = '0.0.1' 8 | s.summary = 'A new flutter plugin project.' 9 | s.description = <<-DESC 10 | A new flutter plugin project. 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.dependency 'Flutter' 18 | s.platform = :ios, '8.0' 19 | 20 | # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. 21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } 22 | s.swift_version = '5.0' 23 | end 24 | -------------------------------------------------------------------------------- /lib/config.dart: -------------------------------------------------------------------------------- 1 | /// vCard version. 2 | enum VCardVersion { 3 | /// vCard version 3.0. 4 | /// 5 | /// This is described in https://tools.ietf.org/html/rfc2426 from 1998 and is 6 | /// the most commonly used format. 7 | v3, 8 | 9 | /// vCard version 4.0. 10 | /// 11 | /// This is described in https://tools.ietf.org/html/rfc6350 from 2011. 12 | v4, 13 | 14 | // V2.1 (described in https://tools.ietf.org/html/rfc2425 from 1998) is not 15 | // yet supported. 16 | } 17 | 18 | class FlutterContactsConfig { 19 | /// Whether to include notes in the properties on iOS13 and above. 20 | /// 21 | /// On iOS13+ the app needs to be explicitly approved by Apple (see 22 | /// https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_contacts_notes) 23 | /// and the app crashes when trying to read or write notes without 24 | /// entitlement. If your app got entitled, you can set this to true to access 25 | /// notes. 26 | bool includeNotesOnIos13AndAbove = false; 27 | 28 | /// Non-visible contacts on Android are contacts that are not part of a group, 29 | /// and are excluded by default. 30 | /// 31 | /// See https://stackoverflow.com/questions/28665587/what-does-contactscontract-contacts-in-visible-group-mean-in-android 32 | bool includeNonVisibleOnAndroid = false; 33 | 34 | /// Return unified contacts instead of raw contacts. 35 | /// 36 | /// On both iOS and Android there is a concept of raw and unified contacts. A 37 | /// single person might have two raw contacts (for example from Gmail and from 38 | /// iCloud) but will be merged into a single view called a unified contact. In 39 | /// a contact app you typically want unified contacts, so this is what's 40 | /// returned by default. When this is false, raw contacts are returned 41 | /// instead. 42 | bool returnUnifiedContacts = true; 43 | 44 | /// The vCard version to use when exporting to VCard. V4 is the most current, 45 | /// but V3 is the most commonly supported. 46 | VCardVersion vCardVersion = VCardVersion.v3; 47 | } 48 | -------------------------------------------------------------------------------- /lib/properties/account.dart: -------------------------------------------------------------------------------- 1 | /// Account information, which is exposed for information and debugging purposes 2 | /// and should be ignored in most cases. 3 | /// 4 | /// On Android this is the raw account, and there can be several accounts per 5 | /// unified contact (for example one for Gmail, one for Skype and one for 6 | /// WhatsApp). On iOS it is called container, and there can be only one 7 | /// container per contact. 8 | class Account { 9 | /// Raw account ID. 10 | String rawId; 11 | 12 | /// Account type, e.g. com.google or com.facebook.messenger. 13 | String type; 14 | 15 | /// Account name, e.g. john.doe@gmail.com. 16 | String name; 17 | 18 | /// Android mimetypes provided by this account. 19 | List mimetypes; 20 | 21 | Account(this.rawId, this.type, this.name, this.mimetypes); 22 | 23 | factory Account.fromJson(Map json) => Account( 24 | (json['rawId'] as String?) ?? '', 25 | (json['type'] as String?) ?? '', 26 | (json['name'] as String?) ?? '', 27 | (json['mimetypes'] as List?)?.map((e) => e as String).toList() ?? [], 28 | ); 29 | 30 | Map toJson() => { 31 | 'rawId': rawId, 32 | 'type': type, 33 | 'name': name, 34 | 'mimetypes': mimetypes, 35 | }; 36 | 37 | @override 38 | String toString() => 39 | 'Account(rawId=$rawId, type=$type, name=$name, mimetypes=$mimetypes)'; 40 | } 41 | -------------------------------------------------------------------------------- /lib/properties/group.dart: -------------------------------------------------------------------------------- 1 | /// Group (called label on Android and group on iOS). 2 | /// 3 | /// A contact may belong to zero, one or more groups. 4 | class Group { 5 | String id; 6 | String name; 7 | 8 | Group(this.id, this.name); 9 | 10 | factory Group.fromJson(Map json) => Group( 11 | (json['id'] as String?) ?? '', 12 | (json['name'] as String?) ?? '', 13 | ); 14 | 15 | Map toJson() => { 16 | 'id': id, 17 | 'name': name, 18 | }; 19 | 20 | @override 21 | String toString() => 'Group(id=$id, name=$name)'; 22 | } 23 | -------------------------------------------------------------------------------- /lib/properties/note.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_contacts/vcard.dart'; 2 | 3 | /// Note, i.e. a free-form string about the contact. 4 | /// 5 | /// Android allows multiple notes per contact, while iOS supports only one. 6 | /// 7 | /// On iOS13+ notes are no longer supported, as you need to request entitlement 8 | /// from Apple to use it in your app. See: 9 | /// https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_contacts_notes 10 | class Note { 11 | /// Note content. 12 | String note; 13 | 14 | Note(this.note); 15 | 16 | factory Note.fromJson(Map json) => 17 | Note((json['note'] as String?) ?? ''); 18 | 19 | Map toJson() => {'note': note}; 20 | 21 | @override 22 | int get hashCode => note.hashCode; 23 | 24 | @override 25 | bool operator ==(Object o) => o is Note && o.note == note; 26 | 27 | @override 28 | String toString() => 'Note(note=$note)'; 29 | 30 | List toVCard() { 31 | // NOTE (V3): https://tools.ietf.org/html/rfc2426#section-3.6.2 32 | // NOTE (V4): https://tools.ietf.org/html/rfc6350#section-6.7.2 33 | return ['NOTE:${vCardEncode(note)}']; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/properties/organization.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_contacts/vcard.dart'; 2 | 3 | /// Organization / job. 4 | class Organization { 5 | /// Company name. 6 | String company; 7 | 8 | /// Job title. 9 | String title; 10 | 11 | /// Department. 12 | String department; 13 | 14 | /// Job description (Android only). 15 | String jobDescription; 16 | 17 | /// Ticker symbol (Android only). 18 | String symbol; 19 | 20 | /// Phonetic company name (Android and iOS10+ only). 21 | String phoneticName; 22 | 23 | /// Office location (Android only). 24 | String officeLocation; 25 | 26 | Organization({ 27 | this.company = '', 28 | this.title = '', 29 | this.department = '', 30 | this.jobDescription = '', 31 | this.symbol = '', 32 | this.phoneticName = '', 33 | this.officeLocation = '', 34 | }); 35 | 36 | factory Organization.fromJson(Map json) => Organization( 37 | company: (json['company'] as String?) ?? '', 38 | title: (json['title'] as String?) ?? '', 39 | department: (json['department'] as String?) ?? '', 40 | jobDescription: (json['jobDescription'] as String?) ?? '', 41 | symbol: (json['symbol'] as String?) ?? '', 42 | phoneticName: (json['phoneticName'] as String?) ?? '', 43 | officeLocation: (json['officeLocation'] as String?) ?? '', 44 | ); 45 | 46 | Map toJson() => { 47 | 'company': company, 48 | 'title': title, 49 | 'department': department, 50 | 'jobDescription': jobDescription, 51 | 'symbol': symbol, 52 | 'phoneticName': phoneticName, 53 | 'officeLocation': officeLocation, 54 | }; 55 | 56 | @override 57 | int get hashCode => 58 | company.hashCode ^ 59 | title.hashCode ^ 60 | department.hashCode ^ 61 | jobDescription.hashCode ^ 62 | symbol.hashCode ^ 63 | phoneticName.hashCode ^ 64 | officeLocation.hashCode; 65 | 66 | @override 67 | bool operator ==(Object o) => 68 | o is Organization && 69 | o.company == company && 70 | o.title == title && 71 | o.department == department && 72 | o.jobDescription == jobDescription && 73 | o.symbol == symbol && 74 | o.phoneticName == phoneticName && 75 | o.officeLocation == officeLocation; 76 | 77 | @override 78 | String toString() => 79 | 'Organization(company=$company, title=$title, department=$department, ' 80 | 'jobDescription=$jobDescription, symbol=$symbol, ' 81 | 'phoneticName=$phoneticName, officeLocation=$officeLocation)'; 82 | 83 | List toVCard() { 84 | // ORG (V3): https://tools.ietf.org/html/rfc2426#section-3.5.5 85 | // TITLE (V3): https://tools.ietf.org/html/rfc2426#section-3.5.1 86 | // ROLE (V3): https://tools.ietf.org/html/rfc2426#section-3.5.2 87 | // ORG (V4): https://tools.ietf.org/html/rfc6350#section-6.6.4 88 | // TITLE (V4): https://tools.ietf.org/html/rfc6350#section-6.6.1 89 | // ROLE (V4): https://tools.ietf.org/html/rfc6350#section-6.6.2 90 | var lines = []; 91 | if (company.isNotEmpty || department.isNotEmpty) { 92 | var s = 'ORG:${vCardEncode(company)}'; 93 | if (department.isNotEmpty) { 94 | s += ';${vCardEncode(department)}'; 95 | } 96 | lines.add(s); 97 | } 98 | if (title.isNotEmpty) { 99 | lines.add('TITLE:${vCardEncode(title)}'); 100 | } 101 | if (jobDescription.isNotEmpty) { 102 | lines.add('ROLE:${vCardEncode(jobDescription)}'); 103 | } 104 | return lines; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /lib/properties/website.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_contacts/vcard.dart'; 2 | 3 | /// Labeled website. 4 | class Website { 5 | /// Website URL. 6 | String url; 7 | 8 | /// Label (default [WebsiteLabel.homepage]). 9 | WebsiteLabel label; 10 | 11 | /// Custom label, if [label] is [WebsiteLabel.custom]. 12 | String customLabel; 13 | 14 | Website(this.url, 15 | {this.label = WebsiteLabel.homepage, this.customLabel = ''}); 16 | 17 | factory Website.fromJson(Map json) => Website( 18 | (json['url'] as String?) ?? '', 19 | label: _stringToWebsiteLabel[json['label'] as String? ?? ''] ?? 20 | WebsiteLabel.homepage, 21 | customLabel: (json['customLabel'] as String?) ?? '', 22 | ); 23 | 24 | Map toJson() => { 25 | 'url': url, 26 | 'label': _websiteLabelToString[label], 27 | 'customLabel': customLabel, 28 | }; 29 | 30 | @override 31 | int get hashCode => url.hashCode ^ label.hashCode ^ customLabel.hashCode; 32 | 33 | @override 34 | bool operator ==(Object o) => 35 | o is Website && 36 | o.url == url && 37 | o.label == label && 38 | o.customLabel == customLabel; 39 | 40 | @override 41 | String toString() => 42 | 'Website(url=$url, label=$label, customLabel=$customLabel)'; 43 | 44 | List toVCard() { 45 | // URL (V3): https://tools.ietf.org/html/rfc2426#section-3.6.8 46 | // URL (V4): https://tools.ietf.org/html/rfc6350#section-6.7.8 47 | return ['URL:${vCardEncode(url)}']; 48 | } 49 | } 50 | 51 | /// Website labels. 52 | /// 53 | /// | Label | Android | iOS | 54 | /// |----------|:-------:|:---:| 55 | /// | blog | ✔ | ⨯ | 56 | /// | ftp | ✔ | ⨯ | 57 | /// | home | ✔ | ✔ | 58 | /// | homepage | ✔ | ✔ | 59 | /// | profile | ✔ | ⨯ | 60 | /// | school | ⨯ | ✔ | 61 | /// | work | ✔ | ✔ | 62 | /// | other | ✔ | ✔ | 63 | /// | custom | ✔ | ✔ | 64 | enum WebsiteLabel { 65 | blog, 66 | ftp, 67 | home, 68 | homepage, 69 | profile, 70 | school, 71 | work, 72 | other, 73 | custom, 74 | } 75 | 76 | final _websiteLabelToString = { 77 | WebsiteLabel.blog: 'blog', 78 | WebsiteLabel.ftp: 'ftp', 79 | WebsiteLabel.home: 'home', 80 | WebsiteLabel.homepage: 'homepage', 81 | WebsiteLabel.profile: 'profile', 82 | WebsiteLabel.school: 'school', 83 | WebsiteLabel.work: 'work', 84 | WebsiteLabel.other: 'other', 85 | WebsiteLabel.custom: 'custom', 86 | }; 87 | 88 | final _stringToWebsiteLabel = { 89 | 'blog': WebsiteLabel.blog, 90 | 'ftp': WebsiteLabel.ftp, 91 | 'home': WebsiteLabel.home, 92 | 'homepage': WebsiteLabel.homepage, 93 | 'profile': WebsiteLabel.profile, 94 | 'school': WebsiteLabel.school, 95 | 'work': WebsiteLabel.work, 96 | 'other': WebsiteLabel.other, 97 | 'custom': WebsiteLabel.custom, 98 | }; 99 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_contacts 2 | description: Flutter plugin to read, create, update, delete and observe native contacts on Android and iOS, with group support, vCard support, and contact permission handling 3 | version: 1.1.9+2 4 | homepage: https://github.com/QuisApp/flutter_contacts 5 | 6 | environment: 7 | sdk: ">=2.12.0 <4.0.0" 8 | flutter: ">=1.12.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | pedantic: ^1.11.0 18 | test: ^1.16.5 19 | 20 | flutter: 21 | plugin: 22 | platforms: 23 | android: 24 | package: co.quis.flutter_contacts 25 | pluginClass: FlutterContactsPlugin 26 | ios: 27 | pluginClass: FlutterContactsPlugin 28 | -------------------------------------------------------------------------------- /scripts/format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | dart format . 6 | 7 | swiftformat --swiftversion 5.2 . 8 | 9 | ktlint -F 10 | -------------------------------------------------------------------------------- /test/contact_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:flutter_contacts/flutter_contacts.dart'; 4 | 5 | void main() { 6 | TestWidgetsFlutterBinding.ensureInitialized(); 7 | 8 | test('new contact should have no null values except for photo', () { 9 | final contact = Contact(); 10 | final json = contact.toJson(); 11 | final nulls = nullValues(json); 12 | expect(nulls, ['/thumbnail', '/photo']); 13 | }); 14 | 15 | test('add phone numbers', () async { 16 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 17 | .setMockMethodCallHandler( 18 | const MethodChannel('github.com/QuisApp/flutter_contacts'), 19 | (MethodCall methodCall) async { 20 | if (methodCall.method == 'insert') { 21 | final c = methodCall.arguments[0]; 22 | c['displayName'] = '${c['name']['first']} ${c['name']['last']}'; 23 | c['id'] = '12345'; 24 | return c; 25 | } 26 | return null; 27 | }, 28 | ); 29 | final newContact = Contact() 30 | ..name = Name(first: 'John', last: 'Doe') 31 | ..phones = [ 32 | Phone('555-123-4567'), 33 | Phone('555-999-9999', label: PhoneLabel.work) 34 | ]; 35 | final returnedContact = await newContact.insert(); 36 | expect(returnedContact.displayName, 'John Doe'); 37 | expect(returnedContact.phones.length, 2); 38 | }); 39 | } 40 | 41 | List nullValues(dynamic x, {String path = ''}) { 42 | if (x is Map) { 43 | var nulls = []; 44 | x.forEach((k, v) => nulls.addAll(nullValues(v, path: '$path/$k'))); 45 | return nulls; 46 | } else if (x is List) { 47 | return nullValues(x.asMap(), path: path); 48 | } else if (x == null) { 49 | return [path]; 50 | } else { 51 | return []; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test/diacritics_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_contacts/diacritics.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | void main() { 5 | test('remove diacritics', () { 6 | expect(removeDiacritics('Édouard'), 'Edouard'); 7 | expect(removeDiacritics("Être contesté, c'est être constaté"), 8 | "Etre conteste, c'est etre constate"); 9 | expect(removeDiacritics('ÇƑⓃꝘNJǩꜩß'), 'CFNQNJktzss'); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/vcards/bvcard.com.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "", 3 | "displayName": "Dr John J Smith, Jr", 4 | "thumbnail": null, 5 | "photo": null, 6 | "isStarred": false, 7 | "name": { 8 | "first": "John", 9 | "last": "Smith", 10 | "middle": "J", 11 | "prefix": "Dr", 12 | "suffix": "Jr", 13 | "nickname": "", 14 | "firstPhonetic": "", 15 | "lastPhonetic": "", 16 | "middlePhonetic": "" 17 | }, 18 | "phones": [ 19 | { 20 | "number": "555-123-4567", 21 | "normalizedNumber": "", 22 | "label": "mobile", 23 | "customLabel": "", 24 | "isPrimary": false 25 | }, 26 | { 27 | "number": "555-999-9999", 28 | "normalizedNumber": "", 29 | "label": "faxHome", 30 | "customLabel": "", 31 | "isPrimary": false 32 | } 33 | ], 34 | "emails": [ 35 | { 36 | "address": "johnsmith@example.com", 37 | "label": "home", 38 | "customLabel": "", 39 | "isPrimary": false 40 | } 41 | ], 42 | "addresses": [ 43 | { 44 | "address": "123 Main St Apt 3 Portland TN 37148 USA", 45 | "label": "home", 46 | "customLabel": "", 47 | "street": "Apt 3", 48 | "pobox": "", 49 | "neighborhood": "", 50 | "city": "Portland", 51 | "state": "TN", 52 | "postalCode": "37148", 53 | "country": "USA", 54 | "isoCountry": "", 55 | "subAdminArea": "", 56 | "subLocality": "" 57 | } 58 | ], 59 | "organizations": [ 60 | { 61 | "company": "FlutterContacts", 62 | "title": "", 63 | "department": "", 64 | "jobDescription": "", 65 | "symbol": "", 66 | "phoneticName": "", 67 | "officeLocation": "" 68 | } 69 | ], 70 | "websites": [ 71 | { 72 | "url": "http://www.example.com", 73 | "label": "homepage", 74 | "customLabel": "" 75 | }, 76 | { 77 | "url": "http://linked.com/profile", 78 | "label": "homepage", 79 | "customLabel": "" 80 | }, 81 | { 82 | "url": "http://facebook.com/profile", 83 | "label": "homepage", 84 | "customLabel": "" 85 | }, 86 | { 87 | "url": "http://google.plus/profile", 88 | "label": "homepage", 89 | "customLabel": "" 90 | }, 91 | { 92 | "url": "http://twitter.com/profile", 93 | "label": "homepage", 94 | "customLabel": "" 95 | } 96 | ], 97 | "socialMedias": [], 98 | "events": [], 99 | "notes": [], 100 | "accounts": [], 101 | "groups": [] 102 | } -------------------------------------------------------------------------------- /test/testdata/vcards/bvcard.com.vcf: -------------------------------------------------------------------------------- 1 | BEGIN:VCARD 2 | VERSION:4.0 3 | PRODID:-//BBros.us llc//bvCard.com//EN 4 | N:Smith;John;J;Dr;Jr 5 | FN:Dr John J Smith, Jr 6 | EMAIL:johnsmith@example.com 7 | ORG:FlutterContacts 8 | TEL:555-123-4567 9 | TEL;type=FAX:555-999-9999 10 | URL;type=pref:http://www.example.com 11 | ADR:;123 Main St;Apt 3;Portland;TN;37148;USA 12 | URL:http://linked.com/profile 13 | URL:http://facebook.com/profile 14 | URL:http://google.plus/profile 15 | URL:http://twitter.com/profile 16 | END:VCARD -------------------------------------------------------------------------------- /test/testdata/vcards/qr-code-generator.com.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "", 3 | "displayName": "John Smith", 4 | "thumbnail": null, 5 | "photo": null, 6 | "isStarred": false, 7 | "name": { 8 | "first": "John", 9 | "last": "Smith", 10 | "middle": "", 11 | "prefix": "", 12 | "suffix": "", 13 | "nickname": "", 14 | "firstPhonetic": "", 15 | "lastPhonetic": "", 16 | "middlePhonetic": "" 17 | }, 18 | "phones": [ 19 | { 20 | "number": "555-123-4567", 21 | "normalizedNumber": "", 22 | "label": "mobile", 23 | "customLabel": "", 24 | "isPrimary": false 25 | }, 26 | { 27 | "number": "555-999-9999", 28 | "normalizedNumber": "", 29 | "label": "work", 30 | "customLabel": "", 31 | "isPrimary": false 32 | }, 33 | { 34 | "number": "555-888-8888", 35 | "normalizedNumber": "", 36 | "label": "faxWork", 37 | "customLabel": "", 38 | "isPrimary": false 39 | } 40 | ], 41 | "emails": [ 42 | { 43 | "address": "johnsmith@example.com", 44 | "label": "home", 45 | "customLabel": "", 46 | "isPrimary": true 47 | } 48 | ], 49 | "addresses": [ 50 | { 51 | "address": " ", 52 | "label": "work", 53 | "customLabel": "", 54 | "street": "", 55 | "pobox": "", 56 | "neighborhood": "", 57 | "city": "", 58 | "state": "", 59 | "postalCode": "", 60 | "country": "", 61 | "isoCountry": "", 62 | "subAdminArea": "", 63 | "subLocality": "" 64 | } 65 | ], 66 | "organizations": [ 67 | { 68 | "company": "FlutterContacts", 69 | "title": "Software Engineer", 70 | "department": "", 71 | "jobDescription": "", 72 | "symbol": "", 73 | "phoneticName": "", 74 | "officeLocation": "" 75 | } 76 | ], 77 | "websites": [ 78 | { 79 | "url": "www.example.com", 80 | "label": "homepage", 81 | "customLabel": "" 82 | } 83 | ], 84 | "socialMedias": [], 85 | "events": [], 86 | "notes": [ 87 | { 88 | "note": "Some notes line 1 Some notes line 2" 89 | } 90 | ], 91 | "accounts": [], 92 | "groups": [] 93 | } -------------------------------------------------------------------------------- /test/testdata/vcards/qr-code-generator.com.vcf: -------------------------------------------------------------------------------- 1 | BEGIN:VCARD 2 | VERSION:3.0 3 | PRODID:-//QR-Code-Generator.com//EN 4 | N:Smith;John;;; 5 | FN:John Smith 6 | ORG:FlutterContacts; 7 | TITLE:Software Engineer 8 | EMAIL;TYPE=PREF,INTERNET:johnsmith@example.com 9 | TEL;TYPE=CELL,voice:555-123-4567 10 | TEL;TYPE=WORK,voice:555-999-9999 11 | TEL;TYPE=WORK,fax:555-888-8888 12 | ADR;TYPE=WORK;type=pref:;; ;;;; 13 | URL:www.example.com 14 | 15 | NOTE:Some notes line 1 Some notes line 2 16 | 17 | REV:2008-04-24T19:52:43Z 18 | END:VCARD 19 | -------------------------------------------------------------------------------- /test/testdata/vcards/vcardmaker.com.vcf: -------------------------------------------------------------------------------- 1 | BEGIN:VCARD 2 | VERSION:3.0 3 | FN;CHARSET=UTF-8:John Jøhñ Smith 4 | N;CHARSET=UTF-8:Smith;John;Jøhñ;Dr;Jr 5 | NICKNAME;CHARSET=UTF-8:Nick 6 | GENDER:M 7 | UID;CHARSET=UTF-8:UID-1234 8 | BDAY:19830223 9 | ANNIVERSARY:20100323 10 | EMAIL;CHARSET=UTF-8;type=HOME,INTERNET:johnsmith@example.com 11 | EMAIL;CHARSET=UTF-8;type=WORK,INTERNET:john@smith.com 12 | LOGO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAwJCQkJCQwTDA4MDA4MExEUEA8QFBEeFxUVFx4iHRsdIiolJSo0MjRERFwBBAQEBAQEBAQEBAYGBQYGCAcHBwcIDAkJCQkJDBMMDgwMDgwTERQQDxAUER4XFRUXHiIdGx0iKiUlKjQyNEREXP/CABEIAAgACAMBIgACEQEDEQH/xAAUAAEAAAAAAAAAAAAAAAAAAAAI/9oACAEBAAAAAFZ//8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAhAAAAB//8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAxAAAAB//8QAIhAAAQEGBwAAAAAAAAAAAAAAAgQDBQYSExQAAQcVMTNi/9oACAEBAAE/AGr5iEdTmKQXXFJQ/Y2RkKJJtF125Kq09fxxLj//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAECAQE/AH//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAEDAQE/AH//2Q== 13 | PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAwJCQkJCQwTDA4MDA4MExEUEA8QFBEeFxUVFx4iHRsdIiolJSo0MjRERFwBBAQEBAQEBAQEBAYGBQYGCAcHBwcIDAkJCQkJDBMMDgwMDgwTERQQDxAUER4XFRUXHiIdGx0iKiUlKjQyNEREXP/CABEIAAgACAMBIgACEQEDEQH/xAAUAAEAAAAAAAAAAAAAAAAAAAAI/9oACAEBAAAAAFZ//8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAhAAAAB//8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAxAAAAB//8QAIhAAAQEGBwAAAAAAAAAAAAAAAgQDBQYSExQAAQcVMTNi/9oACAEBAAE/AGr5iEdTmKQXXFJQ/Y2RkKJJtF125Kq09fxxLj//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAECAQE/AH//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAEDAQE/AH//2Q== 14 | TEL;TYPE=CELL:555-123-4567 15 | TEL;TYPE=PAGER:555-888-8888 16 | TEL;TYPE=HOME,VOICE:+1-555-000-1111 17 | TEL;TYPE=WORK,VOICE:555-999-9999 18 | TEL;TYPE=HOME,FAX:555-777-7777 19 | TEL;TYPE=WORK,FAX:555-666-6666 20 | LABEL;CHARSET=UTF-8;TYPE=HOME:Home Label 21 | ADR;CHARSET=UTF-8;TYPE=HOME:;;123 Main St;Portland;TN;37148;USA 22 | ADR;CHARSET=UTF-8;TYPE=WORK:;;1600 Amphitheatre Pkwy\, Mountain View\, CA 94043;;;; 23 | TITLE;CHARSET=UTF-8:Software Engineer 24 | ROLE;CHARSET=UTF-8:Package maker 25 | ORG;CHARSET=UTF-8:FlutterContacts 26 | URL;CHARSET=UTF-8:www.example.com 27 | URL;type=WORK;CHARSET=UTF-8:https://pub.dev/packages/flutter_contacts 28 | NOTE;CHARSET=UTF-8:Some notes 29 | REV:2021-02-23T14:11:13.361Z 30 | END:VCARD 31 | --------------------------------------------------------------------------------