ente/lib/ui/share_collection_widget.dart

244 lines
7.1 KiB
Dart
Raw Normal View History

2020-08-07 10:21:56 +00:00
import 'package:flutter/cupertino.dart';
2020-05-17 12:39:38 +00:00
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
2020-10-31 13:17:17 +00:00
import 'package:logging/logging.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/db/public_keys_db.dart';
2020-10-09 23:51:20 +00:00
import 'package:photos/models/collection.dart';
import 'package:photos/models/public_key.dart';
2020-10-09 23:51:20 +00:00
import 'package:photos/services/collections_service.dart';
import 'package:photos/services/sync_service.dart';
2020-10-09 23:51:20 +00:00
import 'package:photos/services/user_service.dart';
import 'package:photos/ui/common_elements.dart';
2020-05-17 12:39:38 +00:00
import 'package:photos/ui/loading_widget.dart';
2020-08-07 10:21:56 +00:00
import 'package:photos/utils/dialog_util.dart';
2020-10-09 23:51:20 +00:00
import 'package:photos/utils/email_util.dart';
import 'package:photos/utils/share_util.dart';
2020-07-07 21:46:14 +00:00
import 'package:photos/utils/toast_util.dart';
2020-05-17 12:39:38 +00:00
2020-10-13 06:23:45 +00:00
class SharingDialog extends StatefulWidget {
final Collection collection;
final List<String> sharees;
2020-10-29 12:56:30 +00:00
SharingDialog(this.collection, this.sharees, {Key key}) : super(key: key);
2020-10-13 06:23:45 +00:00
@override
_SharingDialogState createState() => _SharingDialogState();
}
class _SharingDialogState extends State<SharingDialog> {
bool _showEntryField = false;
List<String> _sharees;
String _email;
@override
Widget build(BuildContext context) {
_sharees = widget.sharees;
2020-08-07 10:21:56 +00:00
final children = List<Widget>();
2020-10-13 05:22:20 +00:00
if (!_showEntryField &&
2020-10-13 06:23:45 +00:00
(widget.collection == null || _sharees.length == 0)) {
2020-10-09 23:51:20 +00:00
children.add(Text("Click the + button to share this folder."));
} else {
2020-10-13 06:23:45 +00:00
for (final email in _sharees) {
2020-10-31 13:17:17 +00:00
children.add(EmailItemWidget(widget.collection.id, email));
2020-10-09 23:51:20 +00:00
}
2020-08-07 10:21:56 +00:00
}
if (_showEntryField) {
children.add(_getEmailField());
2020-08-07 10:21:56 +00:00
}
children.add(Padding(
padding: EdgeInsets.all(8),
));
2020-10-09 23:51:20 +00:00
if (!_showEntryField) {
children.add(Container(
width: 220,
child: OutlineButton(
child: Icon(
Icons.add,
),
onPressed: () {
setState(() {
_showEntryField = true;
});
},
2020-05-17 12:39:38 +00:00
),
2020-10-09 23:51:20 +00:00
));
} else {
children.add(Container(
width: 220,
child: button(
"Add",
onPressed: () {
_addEmailToCollection(_email, null);
2020-10-09 23:51:20 +00:00
},
),
));
}
2020-10-13 05:22:20 +00:00
return AlertDialog(
title: Text("Sharing"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
children: children,
)),
],
),
),
);
2020-10-09 23:51:20 +00:00
}
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,
),
),
);
},
onSuggestionSelected: (PublicKey suggestion) {
_addEmailToCollection(suggestion.email, suggestion.publicKey);
},
);
}
Future<void> _addEmailToCollection(String email, String publicKey) async {
if (!isValidEmail(email)) {
2020-10-09 23:51:20 +00:00
showErrorDialog(context, "Invalid email address",
"Please enter a valid email address.");
return;
} else if (email == Configuration.instance.getEmail()) {
2020-10-29 12:56:30 +00:00
showErrorDialog(context, "Oops", "You cannot share with yourself.");
2020-10-09 23:51:20 +00:00
return;
}
if (publicKey == null) {
final dialog = createProgressDialog(context, "Searching for user...");
await dialog.show();
2020-10-29 12:56:30 +00:00
publicKey = await UserService.instance.getPublicKey(email);
await dialog.hide();
}
2020-10-09 23:51:20 +00:00
if (publicKey == null) {
Navigator.of(context).pop();
final dialog = AlertDialog(
title: Text("Invite to ente?"),
content: Text("Looks like " +
email +
2020-10-09 23:51:20 +00:00
" hasn't signed up for ente yet. Would you like to invite them?"),
actions: [
FlatButton(
child: Text("Invite"),
onPressed: () {
shareText(
2020-10-29 12:56:30 +00:00
"Hey, I have some really nice photos to share. Please install ente.io so that I can share them privately.");
2020-10-09 23:51:20 +00:00
},
),
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
2020-08-07 10:21:56 +00:00
},
2020-10-09 23:51:20 +00:00
);
} else {
final dialog = createProgressDialog(context, "Sharing...");
await dialog.show();
final collection = widget.collection;
if (collection.type == CollectionType.folder) {
final path =
CollectionsService.instance.decryptCollectionPath(collection);
if (!Configuration.instance.getPathsToBackUp().contains(path)) {
await Configuration.instance.addPathToFoldersToBeBackedUp(path);
SyncService.instance.sync();
}
}
try {
2020-10-29 12:56:30 +00:00
await CollectionsService.instance
.share(widget.collection.id, email, publicKey);
await dialog.hide();
2020-10-29 12:56:30 +00:00
showToast("Shared successfully!");
2020-10-13 06:23:45 +00:00
setState(() {
_sharees.add(email);
2020-10-13 06:23:45 +00:00
_showEntryField = false;
});
} catch (e) {
await dialog.hide();
showGenericErrorDialog(context);
}
2020-10-09 23:51:20 +00:00
}
2020-08-07 10:21:56 +00:00
}
}
class EmailItemWidget extends StatelessWidget {
2020-10-31 13:17:17 +00:00
final int collectionID;
2020-08-07 10:21:56 +00:00
final String email;
2020-10-31 13:17:17 +00:00
2020-08-07 10:21:56 +00:00
const EmailItemWidget(
2020-10-31 13:17:17 +00:00
this.collectionID,
2020-08-07 10:21:56 +00:00
this.email, {
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
2020-10-09 23:51:20 +00:00
padding: const EdgeInsets.fromLTRB(0, 4, 0, 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text(
email,
style: TextStyle(fontSize: 16),
),
2020-10-09 23:51:20 +00:00
),
2020-10-31 13:17:17 +00:00
IconButton(
icon: Icon(Icons.delete_forever),
2020-10-09 23:51:20 +00:00
color: Colors.redAccent,
2020-10-31 13:17:17 +00:00
onPressed: () async {
final dialog = createProgressDialog(context, "Please wait...");
await dialog.show();
try {
await CollectionsService.instance
.unshare(collectionID, email);
await dialog.hide();
showToast("Stopped sharing with " + email + ".");
Navigator.of(context).pop();
2020-10-31 13:17:17 +00:00
} catch (e, s) {
Logger("EmailItemWidget").severe(e, s);
await dialog.hide();
showGenericErrorDialog(context);
}
},
2020-10-09 23:51:20 +00:00
),
],
));
2020-05-17 12:39:38 +00:00
}
}