Skip to content

Commit

Permalink
Merge pull request #617 from breez/535-export-to-csv-is-missing
Browse files Browse the repository at this point in the history
  • Loading branch information
ubbabeck authored Sep 13, 2023
2 parents f83f83e + 4e7a7c4 commit 895998e
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 3 deletions.
130 changes: 130 additions & 0 deletions lib/bloc/csv_exporter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import 'dart:io';

import 'package:breez_sdk/bridge_generated.dart';
import 'package:breez_translations/breez_translations_locales.dart';
import 'package:c_breez/bloc/account/account_state.dart';
import 'package:c_breez/bloc/account/payment_filters.dart';
import 'package:c_breez/models/payment_minutiae.dart';
import 'package:c_breez/utils/date.dart';
import 'package:csv/csv.dart';
import 'package:fimber/fimber.dart';
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';

final _log = FimberLog("CsvExporter");

class CsvExporter {
final AccountState accountState;
final bool usesUtcTime;
final String fiatCurrency;
final PaymentTypeFilter filter;
final DateTime? startDate;
final DateTime? endDate;

CsvExporter(
this.filter,
this.fiatCurrency,
this.accountState, {
this.usesUtcTime = false,
this.startDate,
this.endDate,
});

Future<String> export() async {
_log.i("export payments started");
String tmpFilePath =
await _saveCsvFile(const ListToCsvConverter().convert(_generateList() as List<List>));
_log.i("export payments finished");
return tmpFilePath;
}

List _generateList() {
// fetch currencystate map values accordingly
_log.i("generating payment list started");

final texts = getSystemAppLocalizations();
final data = _filterPaymentData(accountState.payments, accountState.paymentFilters);
List<List<String>> paymentList = List.generate(data.length, (index) {
List<String> paymentItem = [];
final data = accountState.payments.elementAt(index);
final paymentInfo = data;
paymentItem.add(
BreezDateUtils.formatYearMonthDayHourMinute(
paymentInfo.paymentTime,
),
);
paymentItem.add(paymentInfo.title);
paymentItem.add(paymentInfo.description);
paymentItem.add(paymentInfo.destinationPubkey);
paymentItem.add(paymentInfo.amountSat.toString());
paymentItem.add(paymentInfo.paymentPreimage);
paymentItem.add(paymentInfo.id);
paymentItem.add(paymentInfo.feeSat.toString());
return paymentItem;
});
paymentList.insert(0, [
texts.csv_exporter_date_and_time,
texts.csv_exporter_title,
texts.csv_exporter_description,
texts.csv_exporter_node_id,
texts.csv_exporter_amount,
texts.csv_exporter_preimage,
texts.csv_exporter_tx_hash,
texts.csv_exporter_fee,
]);
_log.i("generating payment finished");
return paymentList;
}

List<PaymentMinutiae?> _filterPaymentData(List<PaymentMinutiae?> payments, PaymentFilters filter) {
if (payments.isEmpty) {
return payments;
}

if (startDate != null && endDate != null) {
List<PaymentMinutiae?> results = [];
for (var element in payments) {
if (element != null && BreezDateUtils.isBetween(element.paymentTime, startDate!, endDate!)) {
results.add(element);
}
}
return results;
}
return payments;
}

Future<String> _saveCsvFile(String csv) async {
_log.i("save breez payments to csv started");
String filePath = await _createCsvFilePath();
final file = File(filePath);
await file.writeAsString(csv);
_log.i("save breez payments to csv finished");
return file.path;
}

Future<String> _createCsvFilePath() async {
_log.i("create breez payments path started");
final directory = await getTemporaryDirectory();
String filePath = '${directory.path}/BreezPayments';
filePath = _appendFilterInformation(filePath);
filePath += ".csv";
_log.i("create breez payments path finished");
return filePath;
}

String _appendFilterInformation(String filePath) {
_log.i("add filter information to path started");
if (filter == PaymentTypeFilter.Sent) {
filePath += "_sent";
} else if (filter == PaymentTypeFilter.Received) {
filePath += "_received";
}
if (startDate != null && endDate != null) {
DateFormat dateFilterFormat = DateFormat("d.M.yy");
String dateFilter = '${dateFilterFormat.format(startDate!)}-${dateFilterFormat.format(endDate!)}';
filePath += "_$dateFilter";
}
_log.i("add filter information to path finished");
return filePath;
}
}
108 changes: 108 additions & 0 deletions lib/routes/home/widgets/payments_filter/payment_filter_exporter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'package:breez_sdk/bridge_generated.dart';
import 'package:breez_translations/breez_translations_locales.dart';
import 'package:c_breez/bloc/account/account_bloc.dart';
import 'package:c_breez/bloc/account/account_state.dart';
import 'package:c_breez/bloc/csv_exporter.dart';
import 'package:c_breez/bloc/currency/currency_bloc.dart';
import 'package:c_breez/theme/theme_provider.dart';
import 'package:c_breez/widgets/flushbar.dart';
import 'package:c_breez/widgets/loader.dart';
import 'package:fimber/fimber.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:share_plus/share_plus.dart';

class PaymentmentFilterExporter extends StatelessWidget {
final _log = FimberLog("PaymentmentFilterExporter");
final PaymentTypeFilter filter;

PaymentmentFilterExporter(
this.filter, {
Key? key,
}) : super(key: key);

@override
Widget build(BuildContext context) {
final texts = context.texts();
final themeData = Theme.of(context);

return BlocBuilder<AccountBloc, AccountState>(
builder: (context, account) {
return Padding(
padding: const EdgeInsets.only(right: 0.0),
child: PopupMenuButton(
color: themeData.colorScheme.background,
icon: Icon(
Icons.more_vert,
color: themeData.paymentItemTitleTextStyle.color,
),
padding: EdgeInsets.zero,
offset: const Offset(12, 24),
onSelected: _select,
itemBuilder: (context) => [
PopupMenuItem(
height: 36,
value: Choice(() => _exportPayments(context)),
child: Text(
texts.payments_filter_action_export,
style: themeData.textTheme.labelLarge,
),
),
],
));
},
);
}

void _select(Choice choice) {
choice.function();
}

Future _exportPayments(BuildContext context) async {
final texts = context.texts();
final navigator = Navigator.of(context);
final currencyState = context.read<CurrencyBloc>().state;
final accountState = context.read<AccountBloc>().state;
var loaderRoute = createLoaderRoute(context);
navigator.push(loaderRoute);
String filePath;

try {
if (accountState.paymentFilters.fromTimestamp != null ||
accountState.paymentFilters.toTimestamp != null) {
final startDate = DateTime.fromMillisecondsSinceEpoch(accountState.paymentFilters.fromTimestamp!);
final endDate = DateTime.fromMillisecondsSinceEpoch(accountState.paymentFilters.toTimestamp!);
filePath = await CsvExporter(filter, currencyState.fiatId, accountState,
startDate: startDate, endDate: endDate)
.export();
} else {
filePath = await CsvExporter(filter, currencyState.fiatId, accountState).export();
}
if (loaderRoute.isActive) {
navigator.removeRoute(loaderRoute);
}
Share.shareXFiles([XFile(filePath)]);
} catch (error) {
{
if (loaderRoute.isActive) {
navigator.removeRoute(loaderRoute);
}
_log.e("Received error: $error");
showFlushbar(
context,
message: texts.payments_filter_action_export_failed,
);
}
} finally {
if (loaderRoute.isActive) {
navigator.removeRoute(loaderRoute);
}
}
}
}

class Choice {
const Choice(this.function);

final Function function;
}
2 changes: 2 additions & 0 deletions lib/routes/home/widgets/payments_filter/payments_filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:breez_sdk/bridge_generated.dart';
import 'package:breez_translations/breez_translations_locales.dart';
import 'package:c_breez/bloc/account/account_bloc.dart';
import 'package:c_breez/bloc/account/account_state.dart';
import 'package:c_breez/routes/home/widgets/payments_filter/payment_filter_exporter.dart';
import 'package:c_breez/routes/home/widgets/payments_filter/payments_filter_calendar.dart';
import 'package:c_breez/routes/home/widgets/payments_filter/payments_filter_dropdown.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -48,6 +49,7 @@ class PaymentsFilterState extends State<PaymentsFilter> {

return Row(
children: [
PaymentmentFilterExporter(_getFilterType()),
PaymentsFilterCalendar(_getFilterType()),
PaymentsFilterDropdown(
_filter!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class PaymentsFilterCalendar extends StatelessWidget {
builder: (context, account) {
DateTime? firstDate;
if (account.payments.isNotEmpty) {
firstDate = account.payments.first.paymentTime;
// The list is backwards so the last element is the first in chronological order.
firstDate = account.payments.last.paymentTime;
}

return Padding(
Expand Down
10 changes: 10 additions & 0 deletions lib/utils/date.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ class BreezDateUtils {
}
}

static bool isBetween(
DateTime date,
DateTime fromDateTime,
DateTime toDateTime,
) {
final isAfter = date.isAfter(fromDateTime);
final isBefore = date.isBefore(toDateTime);
return isAfter && isBefore;
}

static String formatHourMinute(DateTime d) => _hourMinuteDayFormat.format(d);

static String formatFilterDateRange(DateTime startDate, DateTime endDate) {
Expand Down
8 changes: 8 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.2"
csv:
dependency: "direct main"
description:
name: csv
sha256: "016b31a51a913744a0a1655c74ff13c9379e1200e246a03d96c81c5d9ed297b5"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
dart_style:
dependency: transitive
description:
Expand Down
5 changes: 3 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: c_breez
description: A new Flutter project.
publish_to: 'none'
publish_to: "none"
version: 1.0.0+4

environment:
Expand All @@ -25,6 +25,7 @@ dependencies:
url: https://github.com/breez/Breez-Translations
ref: 815bae7c82d4260744fbeddbb91fa71453891ac8
clipboard_watcher: ^0.2.0
csv: ^5.0.2
connectivity_plus: ^4.0.2
drag_and_drop_lists: ^0.3.3
duration: ^3.0.13
Expand Down Expand Up @@ -122,7 +123,7 @@ flutter:
- src/icon/
- src/icon/animals/
- src/icon/vendors/
- src/animations/welcome/
- src/animations/welcome/
- assets/images/
- assets/icons/
fonts:
Expand Down

0 comments on commit 895998e

Please sign in to comment.