Skip to content
Snippets Groups Projects
Commit 970d5f97 authored by vjrj's avatar vjrj
Browse files

Improve contacts cache

parent 5a57e102
No related branches found
No related tags found
No related merge requests found
import 'dart:convert';
import 'dart:typed_data';
Uint8List? uIntFromList(dynamic value) {
if (value is List<int> && value.isNotEmpty) {
return Uint8List.fromList(value);
} else if (value is String && value.isNotEmpty) {
return base64Decode(value);
} else if (value is List<dynamic> && value.isNotEmpty) {
return Uint8List.fromList(value.map((dynamic e) => e as int).toList());
} else {
return null;
}
......
......@@ -17,11 +17,13 @@ class ContactsCache {
ContactsCache._internal();
static ContactsCache? _instance;
final Map<String, List<Completer<Contact>>> _pendingRequests = {};
final Map<String, List<Completer<Contact>>> _pendingRequests =
<String, List<Completer<Contact>>>{};
Future<Contact> getContact(String pubKey) async {
final String cacheKey = 'avatar-$pubKey';
const Duration duration = Duration(days: 3);
final String cacheKey = 'contact-$pubKey';
const Duration duration =
kReleaseMode ? Duration(days: 3) : Duration(minutes: 5);
try {
final String? cachedValue = window.localStorage[cacheKey];
......@@ -35,7 +37,7 @@ class ContactsCache {
final Contact contact =
Contact.fromJson(decodedValue['data'] as Map<String, dynamic>);
if (!kReleaseMode) {
logger('Returning cached contact $contact');
// logger('Returning cached contact $contact');
}
return contact;
}
......@@ -61,7 +63,7 @@ class ContactsCache {
});
window.localStorage[cacheKey] = encodedValue;
if (!kReleaseMode) {
logger('Returning non cached contact $contact');
// logger('Returning non cached contact $contact');
}
// Send to listeners
for (final Completer<Contact> completer in _pendingRequests[pubKey]!) {
......
......@@ -25,176 +25,186 @@ class TransactionListItem extends StatelessWidget {
final int index;
@override
Widget build(BuildContext context) => BlocBuilder<TransactionsCubit,
Widget build(BuildContext context) =>
BlocBuilder<TransactionsCubit,
TransactionsAndBalanceState>(
builder: (BuildContext context,
builder: (BuildContext context,
TransactionsAndBalanceState transBalanceState) =>
FutureBuilder<Contact>(
future: _fetchContact(pubKey, transaction),
builder: (BuildContext context, AsyncSnapshot<Contact> snapshot) {
if (snapshot.hasData) {
IconData? icon;
Color? iconColor;
String statusText;
final String amountS =
'${transaction.amount < 0 ? "" : "+"}${formatKAmount(context, transaction.amount)}';
statusText = tr('transaction_${transaction.type.name}');
FutureBuilder<Contact>(
future: _fetchContact(pubKey, transaction),
builder: (BuildContext context,
AsyncSnapshot<Contact> snapshot) {
if (snapshot.hasData) {
return _buildTransactionItem(context, snapshot.data!);
} else if (snapshot.hasError) {
return Text('Error ${snapshot.error}');
} else {
return _buildTransactionItem(context, Contact(
pubKey: isIncoming(transaction.type) ? transaction
.from : transaction.to));
}
}));
switch (transaction.type) {
case TransactionType.pending:
icon = Icons.timelapse;
iconColor = Colors.grey;
break;
case TransactionType.sending:
icon = Icons.flight_takeoff;
iconColor = Colors.grey;
break;
case TransactionType.receiving:
icon = Icons.flight_land;
iconColor = Colors.grey;
break;
case TransactionType.sent:
break;
case TransactionType.received:
break;
}
final String myPubKey = SharedPreferencesHelper().getPubKey();
final ContactsCubit contactsCubit =
context.read<ContactsCubit>();
return Slidable(
// Specify a key if the Slidable is dismissible.
key: const ValueKey<int>(0),
// The end action pane is the one at the right or the bottom side.
endActionPane: ActionPane(
motion: const ScrollMotion(),
children: <SlidableAction>[
SlidableAction(
onPressed: (BuildContext c) {
if (snapshot.hasData)
contactsCubit.addContact(snapshot.data!);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(tr('contact_added')),
),
);
},
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Colors.white,
icon: Icons.contacts,
label: tr('add_contact'),
),
],
Slidable _buildTransactionItem(BuildContext context,
Contact contact) {
IconData? icon;
Color? iconColor;
String statusText;
final String amountS =
'${transaction.amount < 0 ? "" : "+"}${formatKAmount(
context, transaction.amount)}';
statusText = tr('transaction_${transaction.type.name}');
switch (transaction.type) {
case TransactionType.pending:
icon = Icons.timelapse;
iconColor = Colors.grey;
break;
case TransactionType.sending:
icon = Icons.flight_takeoff;
iconColor = Colors.grey;
break;
case TransactionType.receiving:
icon = Icons.flight_land;
iconColor = Colors.grey;
break;
case TransactionType.sent:
break;
case TransactionType.received:
break;
}
final String myPubKey = SharedPreferencesHelper().getPubKey();
final ContactsCubit contactsCubit =
context.read<ContactsCubit>();
return Slidable(
// Specify a key if the Slidable is dismissible.
key: const ValueKey<int>(0),
// The end action pane is the one at the right or the bottom side.
endActionPane: ActionPane(
motion: const ScrollMotion(),
children: <SlidableAction>[
SlidableAction(
onPressed: (BuildContext c) {
contactsCubit.addContact(contact);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(tr('contact_added')),
),
);
},
backgroundColor: Theme
.of(context)
.primaryColor,
foregroundColor: Colors.white,
icon: Icons.contacts,
label: tr('add_contact'),
),
],
),
child: ListTile(
leading: (icon != null)
? Icon(
icon,
color: iconColor,
)
: null,
tileColor: tileColor(index, context),
title: Row(
children: <Widget>[
// if (avatar != null) avatar,
const SizedBox(width: 8.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
statusText,
style: const TextStyle(
fontSize: 12.0,
color: Colors.grey,
),
child: ListTile(
leading: (icon != null)
? Icon(
icon,
color: iconColor,
)
: null,
tileColor: tileColor(index, context),
title: Row(
children: <Widget>[
// if (avatar != null) avatar,
const SizedBox(width: 8.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
statusText,
style: const TextStyle(
fontSize: 12.0,
color: Colors.grey,
),
),
const SizedBox(height: 4.0),
Text.rich(
TextSpan(
children: <InlineSpan>[
/* TextSpan(
text: isIncoming(transaction.type)
? 'Recibido de '
: 'Pago a ',
style: const TextStyle(
fontSize: 14.0,
// fontWeight: FontWeight.bold,
),
), */
/* WidgetSpan(
child: avatar != null
? const SizedBox(width: 8.0)
: const SizedBox.shrink(),
), */
WidgetSpan(
child: Text(
tr('transaction_from_to',
namedArgs: <String, String>{
'from': humanizeFromToPubKey(
myPubKey,
transaction.from),
'to': humanizeFromToPubKey(
myPubKey, transaction.to)
}),
style: const TextStyle(
fontSize: 14.0,
// fontWeight: FontWeight.bold,
),
),
),
],
),
),
],
),
),
],
),
subtitle: Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 0, 10),
child: Text(transaction.comment,
),
const SizedBox(height: 4.0),
Text.rich(
TextSpan(
children: <InlineSpan>[
/* TextSpan(
text: isIncoming(transaction.type)
? 'Recibido de '
: 'Pago a ',
style: const TextStyle(
fontSize: 14.0,
// fontWeight: FontWeight.bold,
),
), */
/* WidgetSpan(
child: avatar != null
? const SizedBox(width: 8.0)
: const SizedBox.shrink(),
), */
WidgetSpan(
child: Text(
tr('transaction_from_to',
namedArgs: <String, String>{
'from': humanizeFromToPubKey(
myPubKey,
transaction.from),
'to': humanizeFromToPubKey(
myPubKey, transaction.to)
}),
style: const TextStyle(
fontStyle: FontStyle.italic,
color: Colors.grey,
)),
),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(
amountS,
style: TextStyle(
fontSize: 14.0,
// fontWeight: FontWeight.bold,
color: transaction.type ==
TransactionType.received ||
transaction.type ==
TransactionType.receiving
? Colors.blue
: Colors.red,
),
),
const SizedBox(height: 4.0),
Text(
humanizeTime(
transaction.time, context.locale.toString())!,
style: const TextStyle(
fontSize: 12.0,
color: Colors.grey,
),
),
],
),
));
} else if (snapshot.hasError) {
return Text('Error ${snapshot.error}');
} else {
return const Text('Loading');
}
}));
),
],
),
),
],
),
),
],
),
subtitle: Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 0, 10),
child: Text(transaction.comment,
style: const TextStyle(
fontStyle: FontStyle.italic,
color: Colors.grey,
)),
),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(
amountS,
style: TextStyle(
// fontWeight: FontWeight.bold,
color: transaction.type ==
TransactionType.received ||
transaction.type ==
TransactionType.receiving
? Colors.blue
: Colors.red,
),
),
const SizedBox(height: 4.0),
Text(
humanizeTime(
transaction.time, context.locale.toString())!,
style: const TextStyle(
fontSize: 12.0,
color: Colors.grey,
),
),
],
),
));
}
Future<Contact> _fetchContact(String pubKey, Transaction transaction) async {
return Contact(pubKey: pubKey);
// return Contact(pubKey: pubKey);
if (pubKey == transaction.from) {
return ContactsCache().getContact(transaction.to);
} else {
......
......@@ -4,13 +4,10 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../data/models/contact.dart';
import '../../../data/models/node_list_cubit.dart';
import '../../../data/models/transaction.dart';
import '../../../data/models/transaction_cubit.dart';
import '../../../shared_prefs.dart';
import '../../contacts_cache.dart';
import '../../logger.dart';
import '../../ui_helpers.dart';
import 'transaction_chart.dart';
import 'transaction_item.dart';
......@@ -64,15 +61,6 @@ class _TransactionsAndBalanceWidgetState
@override
Widget build(BuildContext context) {
final String myPubKey = SharedPreferencesHelper().getPubKey();
if (!kReleaseMode) {
ContactsCache()
.getContact('6DrGg8cftpkgffv4Y4Lse9HSjgc8coEQor3yvMPHAnVH');
ContactsCache()
.getContact('A1Fc1VoCLKHyPYmXimYECSmjmsceqwRSZcTBXfgG9JaB');
ContactsCache()
.getContact('6DrGg8cftpkgffv4Y4Lse9HSjgc8coEQor3yvMPHAnVH');
ContactsCache().getContact(myPubKey).then((Contact c) => logger(c));
}
return BlocBuilder<TransactionsCubit, TransactionsAndBalanceState>(builder:
(BuildContext context, TransactionsAndBalanceState transBalanceState) {
final List<Transaction> transactions = transBalanceState.transactions;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment