-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement a list transaction fragment
refs #1
- Loading branch information
Showing
12 changed files
with
763 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class BottomLoader extends StatelessWidget { | ||
const BottomLoader({Key? key}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return const Center( | ||
child: SizedBox( | ||
height: 24, | ||
width: 24, | ||
child: CircularProgressIndicator(strokeWidth: 1.5), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
packages/fragments/list_transactions/lib/list_transactions.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
library list_transactions_fragment; | ||
|
||
export 'src/bloc/list_tx_bloc.dart'; | ||
export 'src/models/model.dart'; | ||
export 'src/views/list_tx_view.dart'; | ||
export 'src/widgets/tx_list_item.dart'; |
88 changes: 88 additions & 0 deletions
88
packages/fragments/list_transactions/lib/src/bloc/list_tx_bloc.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import 'dart:async'; | ||
import 'dart:convert'; | ||
|
||
import 'package:authentication/authentication.dart'; | ||
import 'package:bloc/bloc.dart'; | ||
import 'package:common/common.dart'; | ||
import 'package:equatable/equatable.dart'; | ||
import 'package:meta/meta.dart'; | ||
import 'package:subscription_repository/subscription_repository.dart'; | ||
|
||
import '../models/transaction.dart'; | ||
|
||
part 'list_tx_event.dart'; | ||
part 'list_tx_state.dart'; | ||
|
||
class ListTxBloc extends Bloc<ListTxEvent, ListTxState> { | ||
final AuthRepo _authRepo; | ||
final SubscriptionRepository _subRepo; | ||
late final StreamSubscription<Map<String, dynamic>>? _sub; | ||
|
||
bool _isLoading = false; | ||
|
||
ListTxBloc(this._authRepo, this._subRepo) : super(const ListTxState()) { | ||
on<LoadMoreTx>(_onLoadMoreTx); | ||
_sub = _subRepo.filteredStream([ | ||
SseEventTypes.lnPaymentStatus, | ||
SseEventTypes.lnInvoiceStatus, | ||
])?.listen( | ||
(event) { | ||
// TODO: implement me. Update the status of the payment / invoice | ||
}, | ||
); | ||
} | ||
|
||
void dispose() async { | ||
await _sub?.cancel(); | ||
} | ||
|
||
Future<void> _onLoadMoreTx(event, emit) async { | ||
if (state.hasReachedMax || _isLoading) return; | ||
try { | ||
if (state.status == ListTxStatus.initial) { | ||
final txs = await _fetchTransactions(event); | ||
return emit( | ||
state.copyWith( | ||
status: ListTxStatus.success, | ||
txs: txs, | ||
hasReachedMax: false, | ||
), | ||
); | ||
} | ||
final transactions = await _fetchTransactions(event); | ||
emit( | ||
transactions.isEmpty | ||
? state.copyWith(hasReachedMax: true) | ||
: state.copyWith( | ||
status: ListTxStatus.success, | ||
txs: List.of(state.txs)..addAll(transactions), | ||
hasReachedMax: false, | ||
), | ||
); | ||
} catch (_) { | ||
emit(state.copyWith(status: ListTxStatus.failure)); | ||
} | ||
} | ||
|
||
Future<List<Transaction>> _fetchTransactions(LoadMoreTx event) async { | ||
_isLoading = true; | ||
var i = state.txs.isEmpty ? 0 : state.txs.last.index + 1; | ||
try { | ||
final url = | ||
'${_authRepo.baseUrl()}/latest/lightning/list-all-tx?index_offset=$i&max_tx=${event.maxTx}'; | ||
final response = await fetch(Uri.parse(url), _authRepo.token()); | ||
final js = jsonDecode(response.body); | ||
final txs = <Transaction>[]; | ||
for (var tx in js) { | ||
txs.add(Transaction.fromJson(tx)); | ||
} | ||
return txs; | ||
} catch (e) { | ||
BlitzLog().e(e.toString()); | ||
} finally { | ||
_isLoading = false; | ||
} | ||
|
||
return []; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
packages/fragments/list_transactions/lib/src/bloc/list_tx_event.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
part of 'list_tx_bloc.dart'; | ||
|
||
@immutable | ||
abstract class ListTxEvent {} | ||
|
||
class LoadMoreTx extends ListTxEvent { | ||
final int maxTx; | ||
|
||
/// Loads more transactions up to [maxTx]. | ||
/// | ||
/// If [maxTx] is set to 0, the bloc attempt to load all | ||
/// available transactions at once. | ||
LoadMoreTx([this.maxTx = 25]); | ||
} |
35 changes: 35 additions & 0 deletions
35
packages/fragments/list_transactions/lib/src/bloc/list_tx_state.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
part of 'list_tx_bloc.dart'; | ||
|
||
enum ListTxStatus { initial, success, failure } | ||
|
||
class ListTxState extends Equatable { | ||
const ListTxState({ | ||
this.status = ListTxStatus.initial, | ||
this.txs = const <Transaction>[], | ||
this.hasReachedMax = false, | ||
}); | ||
|
||
final ListTxStatus status; | ||
final List<Transaction> txs; | ||
final bool hasReachedMax; | ||
|
||
ListTxState copyWith({ | ||
ListTxStatus? status, | ||
List<Transaction>? txs, | ||
bool? hasReachedMax, | ||
}) { | ||
return ListTxState( | ||
status: status ?? this.status, | ||
txs: txs ?? this.txs, | ||
hasReachedMax: hasReachedMax ?? this.hasReachedMax, | ||
); | ||
} | ||
|
||
@override | ||
String toString() { | ||
return '''ListTxState { status: $status, hasReachedMax: $hasReachedMax, posts: ${txs.length} }'''; | ||
} | ||
|
||
@override | ||
List<Object> get props => [status, txs, hasReachedMax]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export 'transaction.dart'; |
43 changes: 43 additions & 0 deletions
43
packages/fragments/list_transactions/lib/src/models/transaction.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
class Transaction { | ||
final int index; | ||
final String id; | ||
final String category; | ||
final String type; | ||
final int amount; | ||
final int timeStamp; | ||
final String comment; | ||
final String status; | ||
final int? blockHeight; | ||
final int? numConfs; | ||
final int? totalFees; | ||
|
||
Transaction({ | ||
required this.index, | ||
required this.id, | ||
required this.category, | ||
required this.type, | ||
required this.amount, | ||
required this.timeStamp, | ||
required this.comment, | ||
required this.status, | ||
required this.blockHeight, | ||
required this.numConfs, | ||
required this.totalFees, | ||
}); | ||
|
||
static Transaction fromJson(Map<String, dynamic> json) { | ||
return Transaction( | ||
index: json['index'] ?? -1, | ||
id: json['id'] ?? '', | ||
category: json['category'] ?? 'unknown', | ||
type: json['type'] ?? 'unknown', | ||
amount: json['amount'] ?? 0, | ||
timeStamp: json['time_stamp'] ?? 0, | ||
comment: json['comment'] ?? '', | ||
status: json['status'] ?? 'unknown', | ||
blockHeight: json['block_height'] ?? 0, | ||
numConfs: json['num_confs'] ?? 0, | ||
totalFees: json['total_fees'] ?? 0, | ||
); | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
packages/fragments/list_transactions/lib/src/views/list_tx_view.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import 'package:common/common.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/rendering.dart'; | ||
import 'package:flutter_bloc/flutter_bloc.dart'; | ||
import '../bloc/list_tx_bloc.dart'; | ||
import '../widgets/tx_list_item.dart'; | ||
|
||
class FundsPage extends StatefulWidget { | ||
final Function(bool) _setFABVisible; | ||
|
||
const FundsPage(this._setFABVisible, {Key? key}) : super(key: key); | ||
|
||
@override | ||
_FundsPageState createState() => _FundsPageState(); | ||
} | ||
|
||
class _FundsPageState extends State<FundsPage> { | ||
late ScrollController _scrollController; | ||
var _fabVisible = true; | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
_scrollController = ScrollController(); | ||
_scrollController.addListener(() { | ||
if (_scrollController.position.userScrollDirection == | ||
ScrollDirection.reverse) { | ||
if (_fabVisible == true) { | ||
_fabVisible = false; | ||
widget._setFABVisible(_fabVisible); | ||
} | ||
if (_isBottom) { | ||
context.read<ListTxBloc>().add(LoadMoreTx()); | ||
} | ||
} else { | ||
if (_scrollController.position.userScrollDirection == | ||
ScrollDirection.forward) { | ||
if (_fabVisible == false) { | ||
_fabVisible = true; | ||
widget._setFABVisible(_fabVisible); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
super.dispose(); | ||
|
||
_scrollController.dispose(); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return BlocBuilder<ListTxBloc, ListTxState>( | ||
builder: (context, txState) { | ||
switch (txState.status) { | ||
case ListTxStatus.failure: | ||
return const Center(child: Text('Failed to fetch transactions')); | ||
case ListTxStatus.success: | ||
if (txState.txs.isEmpty) { | ||
return const Center(child: Text('no transactions')); | ||
} | ||
|
||
return ListView.builder( | ||
itemBuilder: (BuildContext context, int i) { | ||
return i >= txState.txs.length | ||
? const BottomLoader() | ||
: TxListItem(tx: txState.txs[i]); | ||
}, | ||
itemCount: txState.hasReachedMax | ||
? txState.txs.length | ||
: txState.txs.length + 1, | ||
controller: _scrollController, | ||
); | ||
default: | ||
return const Center(child: CircularProgressIndicator()); | ||
} | ||
}, | ||
); | ||
} | ||
|
||
bool get _isBottom { | ||
if (!_scrollController.hasClients) return false; | ||
final maxScroll = _scrollController.position.maxScrollExtent; | ||
final currentScroll = _scrollController.offset; | ||
return currentScroll >= (maxScroll * 0.9); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
packages/fragments/list_transactions/lib/src/widgets/tx_list_item.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import 'package:flutter/material.dart'; | ||
import '../models/transaction.dart'; | ||
|
||
class TxListItem extends StatelessWidget { | ||
const TxListItem({Key? key, required this.tx}) : super(key: key); | ||
|
||
final Transaction tx; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return ListTile( | ||
leading: Text('${tx.index}'), | ||
title: Text(tx.category), | ||
); | ||
} | ||
} |
Oops, something went wrong.