Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Merculiar committed Jan 12, 2025
1 parent 85da571 commit 204e316
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 127 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:injectable/injectable.dart';

import '../data/transaction_repository.dart';
import '../models/transaction.dart';

@injectable
class TokenActivitiesRepository {
const TokenActivitiesRepository(this._repository);

final TransactionRepository _repository;

Stream<List<ActivityGroup>> watchTokenActivities(String tokenAddress) =>
_repository.watchGroupedByDate(tokenAddress).map(_prepareActivityGroups);

List<ActivityGroup> _prepareActivityGroups(
Map<String, IList<TxCommon>> data,
) {
final sortedDates = data.keys.toList()..sort((a, b) => b.compareTo(a));

return sortedDates.map((date) {
final transactions = data[date] ?? IList<TxCommon>();

final sortedTxs = transactions.sort((a, b) {
final aCreated = a.created;
final bCreated = b.created;

return (aCreated != null && bCreated != null)
? bCreated.compareTo(aCreated)
: 0;
});

return ActivityGroup(date: date, transactions: sortedTxs);
}).toList();
}
}

class ActivityGroup {
const ActivityGroup({
required this.date,
required this.transactions,
});

final String date;
final IList<TxCommon> transactions;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

Expand All @@ -7,8 +6,7 @@ import '../../../l10n/l10n.dart';
import '../../../ui/colors.dart';
import '../../../ui/home_tile.dart';
import '../../../ui/theme.dart';
import '../data/transaction_repository.dart';
import '../models/transaction.dart';
import '../services/token_activities_repository.dart';
import 'common_tile.dart';
import 'odp_tile.dart';
import 'off_ramp_tile.dart';
Expand All @@ -32,152 +30,122 @@ class RecentTokenActivityWidget extends StatefulWidget {
}

class _RecentTokenActivityWidgetState extends State<RecentTokenActivityWidget> {
late final Stream<Map<String, IList<TxCommon>>> _groupedTxs;
late final Stream<List<ActivityGroup>> _groupedTxs;

@override
void initState() {
super.initState();
_groupedTxs =
sl<TransactionRepository>().watchGroupedByDate(widget.tokenAddress);
}

String _formatDate(String date) {
final parsedDate = DateTime.parse(date);
final now = DateTime.now();
final yesterday = now.subtract(const Duration(days: 1));

return (parsedDate.year == now.year &&
parsedDate.month == now.month &&
parsedDate.day == now.day)
? context.l10n.today
: (parsedDate.year == yesterday.year &&
parsedDate.month == yesterday.month &&
parsedDate.day == yesterday.day)
? context.l10n.yesterday
: DateFormat('MMM d, yyyy').format(parsedDate);
_groupedTxs = sl<TokenActivitiesRepository>()
.watchTokenActivities(widget.tokenAddress);
}

@override
Widget build(BuildContext context) =>
StreamBuilder<Map<String, IList<TxCommon>>>(
Widget build(BuildContext context) => StreamBuilder<List<ActivityGroup>>(
stream: _groupedTxs,
builder: (context, snapshot) {
final data = snapshot.data;
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}

if (data == null || data.isEmpty) {
return const Center(child: _NoActivity());
}
final groups = snapshot.data;

final sortedDates = data.keys.toList()
..sort((a, b) => b.compareTo(a));

return HomeTile(
padding: const EdgeInsets.symmetric(horizontal: 22, vertical: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 16),
...sortedDates.map((date) {
final transactions = data[date];
late final IList<TxCommon> sortedTxs;

if (transactions != null) {
sortedTxs = transactions.sort((a, b) {
final aCreated = a.created;
final bCreated = b.created;

return (aCreated != null && bCreated != null)
? bCreated.compareTo(aCreated)
: 0;
});
}

return Column(
return groups == null || groups.isEmpty
? const Center(child: _NoActivity())
: HomeTile(
padding:
const EdgeInsets.symmetric(horizontal: 22, vertical: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.only(left: 12.0, bottom: 9.0),
child: Text(
_formatDate(date),
style: dashboardSectionTitleTextStyle,
const SizedBox(height: 16),
...groups
.map((group) => _ActivityGroupWidget(group: group)),
const SizedBox(height: 8),
],
),
);
},
);
}

class _ActivityGroupWidget extends StatelessWidget {
const _ActivityGroupWidget({required this.group});

final ActivityGroup group;

@override
Widget build(BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 12.0, bottom: 9.0),
child: Text(
context.formatActivityDate(group.date),
style: dashboardSectionTitleTextStyle,
),
),
_Card(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: group.transactions.length * 60,
minWidth: MediaQuery.sizeOf(context).width,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: group.transactions
.map(
(tx) => tx.map(
common: (t) => CommonTile(
key: ValueKey(t.tx.id),
txCommon: t,
showIcon: false,
),
),
_Card(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: sortedTxs.length * 60,
minWidth: MediaQuery.sizeOf(context).width,
activity: (txActivity) => txActivity.activity.map(
outgoingPaymentRequest: (p) => PaymentRequestTile(
key: ValueKey(p.id),
id: p.id,
showIcon: false,
),
outgoingDirectPayment: (p) => ODPTile(
key: ValueKey(p.id),
activity: p,
showIcon: false,
),
outgoingLinkPayment: (p) => OLPTile(
key: ValueKey(p.id),
activity: p,
showIcon: false,
),
onRamp: (it) => OnRampTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
offRamp: (it) => OffRampTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
outgoingDlnPayment: (it) => OutgoingDlnTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: sortedTxs
.map(
(tx) => tx.map(
common: (t) => CommonTile(
key: ValueKey(t.tx.id),
txCommon: t,
showIcon: false,
),
activity: (txActivity) =>
txActivity.activity.map(
outgoingPaymentRequest: (p) =>
PaymentRequestTile(
key: ValueKey(p.id),
id: p.id,
showIcon: false,
),
outgoingDirectPayment: (p) => ODPTile(
key: ValueKey(p.id),
activity: p,
showIcon: false,
),
outgoingLinkPayment: (p) => OLPTile(
key: ValueKey(p.id),
activity: p,
showIcon: false,
),
onRamp: (it) => OnRampTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
offRamp: (it) => OffRampTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
outgoingDlnPayment: (it) =>
OutgoingDlnTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
transactionRequest: (it) => TrTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
kyc: (it) => const SizedBox.shrink(),
),
),
)
.toList(),
transactionRequest: (it) => TrTile(
key: ValueKey(it.id),
activity: it,
showIcon: false,
),
kyc: (it) => const SizedBox.shrink(),
),
),
const SizedBox(height: 40),
],
);
}),
const SizedBox(height: 8),
],
)
.toList(),
),
),
);
},
),
],
);
}

Expand Down Expand Up @@ -216,3 +184,21 @@ class _NoActivity extends StatelessWidget {
),
);
}

extension ActivityDateFormatting on BuildContext {
String formatActivityDate(String date) {
final parsedDate = DateTime.parse(date);
final now = DateTime.now();
final yesterday = now.subtract(const Duration(days: 1));

return (parsedDate.year == now.year &&
parsedDate.month == now.month &&
parsedDate.day == now.day)
? l10n.today
: (parsedDate.year == yesterday.year &&
parsedDate.month == yesterday.month &&
parsedDate.day == yesterday.day)
? l10n.yesterday
: DateFormat('MMM d, yyyy').format(parsedDate);
}
}

0 comments on commit 204e316

Please sign in to comment.