Show emails as copyable links in the datatable

This commit is contained in:
Hillel Coren 2022-04-25 17:04:23 +03:00
parent 3614243bdd
commit e836a415c1
6 changed files with 54 additions and 17 deletions

View File

@ -6,24 +6,24 @@ import 'package:invoiceninja_flutter/utils/localization.dart';
class CopyToClipboard extends StatelessWidget { class CopyToClipboard extends StatelessWidget {
const CopyToClipboard({ const CopyToClipboard({
Key key, Key key,
@required this.child,
@required this.value, @required this.value,
this.child,
this.showBorder = false,
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget child;
final String value; final String value;
final bool showBorder;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (value == null) { if ((value ?? '').isEmpty) {
return child; return child;
} }
final widget = child == null ? Text(value) : child;
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final onTap = () {
return InkWell(
child: child,
onTap: () {
Clipboard.setData(ClipboardData(text: value)); Clipboard.setData(ClipboardData(text: value));
showToast( showToast(
localization.copiedToClipboard.replaceFirst( localization.copiedToClipboard.replaceFirst(
@ -31,7 +31,27 @@ class CopyToClipboard extends StatelessWidget {
value.replaceAll('\n', ' '), value.replaceAll('\n', ' '),
), ),
); );
}, };
if (showBorder) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: widget,
),
);
} else {
return InkWell(
child: widget,
onTap: onTap,
); );
} }
} }
}

View File

@ -1383,6 +1383,7 @@ class _ContactUsDialogState extends State<ContactUsDialog> {
'message': _message, 'message': _message,
'send_logs': _includeLogs ? 'true' : '', 'send_logs': _includeLogs ? 'true' : '',
'platform': getPlatformLetter(), 'platform': getPlatformLetter(),
'version': state.appVersion,
})) }))
.then((dynamic response) async { .then((dynamic response) async {
setState(() => _isSaving = false); setState(() => _isSaving = false);

View File

@ -7,6 +7,7 @@ import 'package:flutter_redux/flutter_redux.dart';
// Project imports: // Project imports:
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/copy_to_clipboard.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
@ -64,7 +65,10 @@ class ClientPresenter extends EntityPresenter {
case ClientFields.contactName: case ClientFields.contactName:
return Text(client.primaryContact.fullName); return Text(client.primaryContact.fullName);
case ClientFields.contactEmail: case ClientFields.contactEmail:
return Text(client.primaryContact.email); return CopyToClipboard(
value: client.primaryContact.email,
showBorder: true,
);
case ClientFields.contactPhone: case ClientFields.contactPhone:
return Text(client.primaryContact.phone); return Text(client.primaryContact.phone);
case ClientFields.address1: case ClientFields.address1:

View File

@ -8,6 +8,7 @@ import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/credit/credit_selectors.dart'; import 'package:invoiceninja_flutter/redux/credit/credit_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/copy_to_clipboard.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_status_chip.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_status_chip.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
@ -142,7 +143,10 @@ class CreditPresenter extends EntityPresenter {
if (field == CreditFields.contactName) { if (field == CreditFields.contactName) {
return Text(contact?.fullName ?? ''); return Text(contact?.fullName ?? '');
} }
return Text(contact?.email ?? ''); return CopyToClipboard(
value: contact?.email ?? '',
showBorder: true,
);
case CreditFields.partial: case CreditFields.partial:
return Text(formatNumber(credit.partial, context)); return Text(formatNumber(credit.partial, context));
case CreditFields.partialDueDate: case CreditFields.partialDueDate:

View File

@ -8,6 +8,7 @@ import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart'; import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/copy_to_clipboard.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_status_chip.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_status_chip.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
@ -161,7 +162,10 @@ class InvoicePresenter extends EntityPresenter {
if (field == InvoiceFields.contactName) { if (field == InvoiceFields.contactName) {
return Text(contact?.fullName ?? ''); return Text(contact?.fullName ?? '');
} }
return Text(contact?.email ?? ''); return CopyToClipboard(
value: contact?.email ?? '',
showBorder: true,
);
case InvoiceFields.partial: case InvoiceFields.partial:
return Text(formatNumber(invoice.partial, context)); return Text(formatNumber(invoice.partial, context));
case InvoiceFields.partialDueDate: case InvoiceFields.partialDueDate:

View File

@ -9,6 +9,7 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/data/models/quote_model.dart'; import 'package:invoiceninja_flutter/data/models/quote_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_selectors.dart'; import 'package:invoiceninja_flutter/redux/quote/quote_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/copy_to_clipboard.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_status_chip.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_status_chip.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
@ -135,7 +136,10 @@ class QuotePresenter extends EntityPresenter {
if (field == QuoteFields.contactName) { if (field == QuoteFields.contactName) {
return Text(contact?.fullName ?? ''); return Text(contact?.fullName ?? '');
} }
return Text(contact?.email ?? ''); return CopyToClipboard(
value: contact?.email ?? '',
showBorder: true,
);
case QuoteFields.partial: case QuoteFields.partial:
return Text(formatNumber(quote.partial, context)); return Text(formatNumber(quote.partial, context));
case QuoteFields.partialDueDate: case QuoteFields.partialDueDate: