diff --git a/ios/Podfile.lock b/ios/Podfile.lock index c80a4790c..46bdb94ac 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -23,6 +23,8 @@ PODS: - Flutter - flutter_webview_plugin (0.0.1): - Flutter + - fluttercontactpicker (3.1.0): + - Flutter - fluttertoast (0.0.2): - Flutter - FMDB (2.7.5): @@ -79,6 +81,7 @@ DEPENDENCIES: - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_sodium (from `.symlinks/plugins/flutter_sodium/ios`) - flutter_webview_plugin (from `.symlinks/plugins/flutter_webview_plugin/ios`) + - fluttercontactpicker (from `.symlinks/plugins/fluttercontactpicker/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider (from `.symlinks/plugins/path_provider/ios`) @@ -123,6 +126,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_sodium/ios" flutter_webview_plugin: :path: ".symlinks/plugins/flutter_webview_plugin/ios" + fluttercontactpicker: + :path: ".symlinks/plugins/fluttercontactpicker/ios" fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" package_info_plus: @@ -158,6 +163,7 @@ SPEC CHECKSUMS: flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec flutter_sodium: c84426b4de738514b5b66cfdeb8a06634e72fe0b flutter_webview_plugin: ed9e8a6a96baf0c867e90e1bce2673913eeac694 + fluttercontactpicker: 3a69f749dcc3fab94b816ad68fa838a6f0a1cf0f fluttertoast: b644586ef3b16f67fae9a1f8754cef6b2d6b634b FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index c4ad6e3d8..bbb80c464 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -244,6 +244,7 @@ "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework", "${BUILT_PRODUCTS_DIR}/flutter_sodium/flutter_sodium.framework", "${BUILT_PRODUCTS_DIR}/flutter_webview_plugin/flutter_webview_plugin.framework", + "${BUILT_PRODUCTS_DIR}/fluttercontactpicker/fluttercontactpicker.framework", "${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework", "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", "${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework", @@ -275,6 +276,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_sodium.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_webview_plugin.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttercontactpicker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework", diff --git a/lib/ui/share_collection_widget.dart b/lib/ui/share_collection_widget.dart index 8821d83f8..2f3fe3c01 100644 --- a/lib/ui/share_collection_widget.dart +++ b/lib/ui/share_collection_widget.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; +import 'package:fluttercontactpicker/fluttercontactpicker.dart'; import 'package:logging/logging.dart'; import 'package:photos/core/configuration.dart'; import 'package:photos/db/public_keys_db.dart'; @@ -75,7 +76,7 @@ class _SharingDialogState extends State { child: button( "Add", onPressed: () { - _addEmailToCollection(_email, null); + _addEmailToCollection(_email); }, ), )); @@ -98,41 +99,58 @@ class _SharingDialogState extends State { } Widget _getEmailField() { - return TypeAheadField( - textFieldConfiguration: TextFieldConfiguration( - keyboardType: TextInputType.emailAddress, - autofocus: true, - decoration: InputDecoration( - border: InputBorder.none, - hintText: "email@your-friend.com", - ), - ), - hideOnEmpty: true, - loadingBuilder: (context) { - return loadWidget; - }, - suggestionsCallback: (pattern) async { - _email = pattern; - return PublicKeysDB.instance.searchByEmail(_email); - }, - itemBuilder: (context, suggestion) { - return Container( - padding: EdgeInsets.fromLTRB(12, 8, 12, 8), - child: Container( - child: Text( - suggestion.email, - overflow: TextOverflow.clip, + return Row( + children: [ + Expanded( + child: TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + keyboardType: TextInputType.emailAddress, + autofocus: true, + decoration: InputDecoration( + border: InputBorder.none, + hintText: "email@your-friend.com", + ), ), + hideOnEmpty: true, + loadingBuilder: (context) { + return loadWidget; + }, + suggestionsCallback: (pattern) async { + _email = pattern; + return PublicKeysDB.instance.searchByEmail(_email); + }, + itemBuilder: (context, suggestion) { + return Container( + padding: EdgeInsets.fromLTRB(12, 8, 12, 8), + child: Container( + child: Text( + suggestion.email, + overflow: TextOverflow.clip, + ), + ), + ); + }, + onSuggestionSelected: (PublicKey suggestion) { + _addEmailToCollection(suggestion.email, + publicKey: suggestion.publicKey); + }, ), - ); - }, - onSuggestionSelected: (PublicKey suggestion) { - _addEmailToCollection(suggestion.email, suggestion.publicKey); - }, + ), + IconButton( + icon: Icon(Icons.attach_email_outlined), + onPressed: () async { + final emailContact = await FlutterContactPicker.pickEmailContact( + askForPermission: true); + _addEmailToCollection(emailContact.email.email); + }), + ], ); } - Future _addEmailToCollection(String email, String publicKey) async { + Future _addEmailToCollection( + String email, { + String publicKey, + }) async { if (!isValidEmail(email)) { showErrorDialog(context, "Invalid email address", "Please enter a valid email address."); @@ -140,6 +158,10 @@ class _SharingDialogState extends State { } else if (email == Configuration.instance.getEmail()) { showErrorDialog(context, "Oops", "You cannot share with yourself."); return; + } else if (widget.collection.sharees.any((user) => user.email == email)) { + showErrorDialog( + context, "Oops", "You're already sharing this with " + email + "."); + return; } if (publicKey == null) { final dialog = createProgressDialog(context, "Searching for user..."); diff --git a/pubspec.lock b/pubspec.lock index 21eaff105..8620abe41 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -296,6 +296,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.3.11" + fluttercontactpicker: + dependency: "direct main" + description: + name: fluttercontactpicker + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" fluttertoast: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index f6b3717c8..1394a89a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: connectivity: ^2.0.1 pretty_dio_logger: ^1.1.1 url_launcher: ^5.7.10 + fluttercontactpicker: ^3.1.0 dev_dependencies: flutter_test: