Prefer auto dispose riverpods

This commit is contained in:
2025-12-06 21:13:18 +08:00
parent 25f23f7f93
commit 71c372ab6c
10 changed files with 600 additions and 671 deletions

View File

@@ -14,7 +14,7 @@ Future<Map<String, dynamic>?> billingUsage(Ref ref) async {
return response.data; return response.data;
} }
final indexedCloudFileListProvider = AsyncNotifierProvider( final indexedCloudFileListProvider = AsyncNotifierProvider.autoDispose(
IndexedCloudFileListNotifier.new, IndexedCloudFileListNotifier.new,
); );
@@ -76,10 +76,10 @@ class IndexedCloudFileListNotifier extends AsyncNotifier<List<FileListItem>>
queryParameters: queryParameters, queryParameters: queryParameters,
); );
final List<String> folders = final List<String> folders = (response.data['folders'] as List)
(response.data['folders'] as List).map((e) => e as String).toList(); .map((e) => e as String)
final List<SnCloudFileIndex> files = .toList();
(response.data['files'] as List) final List<SnCloudFileIndex> files = (response.data['files'] as List)
.map((e) => SnCloudFileIndex.fromJson(e as Map<String, dynamic>)) .map((e) => SnCloudFileIndex.fromJson(e as Map<String, dynamic>))
.toList(); .toList();
@@ -92,7 +92,7 @@ class IndexedCloudFileListNotifier extends AsyncNotifier<List<FileListItem>>
} }
} }
final unindexedFileListProvider = AsyncNotifierProvider( final unindexedFileListProvider = AsyncNotifierProvider.autoDispose(
UnindexedFileListNotifier.new, UnindexedFileListNotifier.new,
); );
@@ -165,13 +165,13 @@ class UnindexedFileListNotifier extends AsyncNotifier<List<FileListItem>>
totalCount = int.tryParse(response.headers.value('x-total') ?? '0') ?? 0; totalCount = int.tryParse(response.headers.value('x-total') ?? '0') ?? 0;
final List<SnCloudFile> files = final List<SnCloudFile> files = (response.data as List)
(response.data as List)
.map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>)) .map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>))
.toList(); .toList();
final List<FileListItem> items = final List<FileListItem> items = files
files.map((file) => FileListItem.unindexedFile(file)).toList(); .map((file) => FileListItem.unindexedFile(file))
.toList();
return items; return items;
} }

View File

@@ -23,7 +23,7 @@ Future<double> socialCredits(Ref ref) async {
return response.data?.toDouble() ?? 0.0; return response.data?.toDouble() ?? 0.0;
} }
final socialCreditHistoryNotifierProvider = AsyncNotifierProvider( final socialCreditHistoryNotifierProvider = AsyncNotifierProvider.autoDispose(
SocialCreditHistoryNotifier.new, SocialCreditHistoryNotifier.new,
); );
@@ -45,8 +45,7 @@ class SocialCreditHistoryNotifier
totalCount = int.parse(response.headers.value('X-Total') ?? '0'); totalCount = int.parse(response.headers.value('X-Total') ?? '0');
final records = final records = response.data
response.data
.map((json) => SnSocialCreditRecord.fromJson(json)) .map((json) => SnSocialCreditRecord.fromJson(json))
.cast<SnSocialCreditRecord>() .cast<SnSocialCreditRecord>()
.toList(); .toList();
@@ -68,8 +67,7 @@ class SocialCreditsTab extends HookConsumerWidget {
margin: const EdgeInsets.only(left: 16, right: 16, top: 8), margin: const EdgeInsets.only(left: 16, right: 16, top: 8),
child: socialCredits child: socialCredits
.when( .when(
data: data: (credits) => Stack(
(credits) => Stack(
children: [ children: [
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -83,9 +81,7 @@ class SocialCreditsTab extends HookConsumerWidget {
? 'socialCreditsLevelGood'.tr() ? 'socialCreditsLevelGood'.tr()
: 'socialCreditsLevelExcellent'.tr(), : 'socialCreditsLevelExcellent'.tr(),
).tr().bold().fontSize(20), ).tr().bold().fontSize(20),
Text( Text('${credits.toStringAsFixed(2)} pts').fontSize(14),
'${credits.toStringAsFixed(2)} pts',
).fontSize(14),
const Gap(8), const Gap(8),
LinearProgressIndicator(value: credits / 200), LinearProgressIndicator(value: credits / 200),
], ],
@@ -119,8 +115,7 @@ class SocialCreditsTab extends HookConsumerWidget {
contentPadding: const EdgeInsets.symmetric(horizontal: 24), contentPadding: const EdgeInsets.symmetric(horizontal: 24),
title: Text( title: Text(
record.reason, record.reason,
style: style: isExpired
isExpired
? TextStyle( ? TextStyle(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
color: Theme.of( color: Theme.of(

View File

@@ -14,7 +14,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:island/widgets/paging/pagination_list.dart'; import 'package:island/widgets/paging/pagination_list.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
final levelingHistoryNotifierProvider = AsyncNotifierProvider( final levelingHistoryNotifierProvider = AsyncNotifierProvider.autoDispose(
LevelingHistoryNotifier.new, LevelingHistoryNotifier.new,
); );
@@ -35,8 +35,7 @@ class LevelingHistoryNotifier extends AsyncNotifier<List<SnExperienceRecord>>
totalCount = int.parse(response.headers.value('X-Total') ?? '0'); totalCount = int.parse(response.headers.value('X-Total') ?? '0');
final List<SnExperienceRecord> records = final List<SnExperienceRecord> records = response.data
response.data
.map((json) => SnExperienceRecord.fromJson(json)) .map((json) => SnExperienceRecord.fromJson(json))
.cast<SnExperienceRecord>() .cast<SnExperienceRecord>()
.toList(); .toList();
@@ -162,8 +161,9 @@ class LevelingScreen extends HookConsumerWidget {
stopIndicatorRadius: 0, stopIndicatorRadius: 0,
trackGap: 0, trackGap: 0,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
backgroundColor: backgroundColor: Theme.of(
Theme.of(context).colorScheme.surfaceContainerHigh, context,
).colorScheme.surfaceContainerHigh,
borderRadius: BorderRadius.circular(32), borderRadius: BorderRadius.circular(32),
), ),
], ],
@@ -186,8 +186,7 @@ class LevelingScreen extends HookConsumerWidget {
notifier: levelingHistoryNotifierProvider.notifier, notifier: levelingHistoryNotifierProvider.notifier,
isRefreshable: false, isRefreshable: false,
isSliver: true, isSliver: true,
itemBuilder: itemBuilder: (context, idx, record) => ListTile(
(context, idx, record) => ListTile(
title: Column( title: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -208,9 +207,7 @@ class LevelingScreen extends HookConsumerWidget {
subtitle: Row( subtitle: Row(
spacing: 8, spacing: 8,
children: [ children: [
Text( Text('${record.delta > 0 ? '+' : ''}${record.delta} EXP'),
'${record.delta > 0 ? '+' : ''}${record.delta} EXP',
),
if (record.bonusMultiplier != 1.0) if (record.bonusMultiplier != 1.0)
Text('x${record.bonusMultiplier}'), Text('x${record.bonusMultiplier}'),
], ],
@@ -249,8 +246,7 @@ class LevelStairsPainter extends CustomPainter {
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
final paint = final paint = Paint()
Paint()
..color = surfaceColor.withOpacity(0.2) ..color = surfaceColor.withOpacity(0.2)
..strokeWidth = 1.5 ..strokeWidth = 1.5
..style = PaintingStyle.stroke; ..style = PaintingStyle.stroke;

View File

@@ -29,7 +29,7 @@ Future<List<SnRelationship>> sentFriendRequest(Ref ref) async {
.toList(); .toList();
} }
final relationshipListNotifierProvider = AsyncNotifierProvider( final relationshipListNotifierProvider = AsyncNotifierProvider.autoDispose(
RelationshipListNotifier.new, RelationshipListNotifier.new,
); );
@@ -45,8 +45,7 @@ class RelationshipListNotifier extends AsyncNotifier<List<SnRelationship>>
queryParameters: {'offset': fetchedCount.toString(), 'take': take}, queryParameters: {'offset': fetchedCount.toString(), 'take': take},
); );
final List<SnRelationship> items = final List<SnRelationship> items = (response.data as List)
(response.data as List)
.map((e) => SnRelationship.fromJson(e as Map<String, dynamic>)) .map((e) => SnRelationship.fromJson(e as Map<String, dynamic>))
.cast<SnRelationship>() .cast<SnRelationship>()
.toList(); .toList();
@@ -83,8 +82,9 @@ class RelationshipListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final account = final account = showRelatedAccount
showRelatedAccount ? relationship.related : relationship.account; ? relationship.related
: relationship.account;
final isPending = final isPending =
relationship.status == 0 && relationship.relatedId == currentUserId; relationship.status == 0 && relationship.relatedId == currentUserId;
final isWaiting = final isWaiting =
@@ -138,8 +138,7 @@ class RelationshipListTile extends StatelessWidget {
], ],
), ),
subtitle: Text('@${account.name}'), subtitle: Text('@${account.name}'),
trailing: trailing: showActions
showActions
? Row( ? Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@@ -165,8 +164,7 @@ class RelationshipListTile extends StatelessWidget {
PopupMenuButton( PopupMenuButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
icon: const Icon(Symbols.more_vert), icon: const Icon(Symbols.more_vert),
itemBuilder: itemBuilder: (context) => [
(context) => [
if (relationship.status >= 100) // If friend if (relationship.status >= 100) // If friend
PopupMenuItem( PopupMenuItem(
child: ListTile( child: ListTile(
@@ -174,11 +172,7 @@ class RelationshipListTile extends StatelessWidget {
title: Text('blockUser').tr(), title: Text('blockUser').tr(),
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
), ),
onTap: onTap: () => onUpdateStatus?.call(relationship, -100),
() => onUpdateStatus?.call(
relationship,
-100,
),
) )
else if (relationship.status <= -100) // If blocked else if (relationship.status <= -100) // If blocked
PopupMenuItem( PopupMenuItem(
@@ -187,9 +181,7 @@ class RelationshipListTile extends StatelessWidget {
title: Text('unblockUser').tr(), title: Text('unblockUser').tr(),
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
), ),
onTap: onTap: () => onUpdateStatus?.call(relationship, 100),
() =>
onUpdateStatus?.call(relationship, 100),
), ),
], ],
), ),
@@ -299,6 +291,7 @@ class RelationshipScreen extends HookConsumerWidget {
const Divider(height: 1), const Divider(height: 1),
Expanded( Expanded(
child: PaginationList( child: PaginationList(
padding: EdgeInsets.zero,
provider: relationshipListNotifierProvider, provider: relationshipListNotifierProvider,
notifier: relationshipListNotifierProvider.notifier, notifier: relationshipListNotifierProvider.notifier,
itemBuilder: (context, index, relationship) { itemBuilder: (context, index, relationship) {
@@ -380,9 +373,7 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
const Divider(height: 1), const Divider(height: 1),
Expanded( Expanded(
child: requests.when( child: requests.when(
data: data: (items) => items.isEmpty
(items) =>
items.isEmpty
? Center( ? Center(
child: Text( child: Text(
'friendSentRequestEmpty'.tr(), 'friendSentRequestEmpty'.tr(),

View File

@@ -12,7 +12,7 @@ import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/paging/pagination_list.dart'; import 'package:island/widgets/paging/pagination_list.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
final marketplaceWebFeedsNotifierProvider = AsyncNotifierProvider( final marketplaceWebFeedsNotifierProvider = AsyncNotifierProvider.autoDispose(
MarketplaceWebFeedsNotifier.new, MarketplaceWebFeedsNotifier.new,
); );

View File

@@ -23,7 +23,7 @@ class DiscoveryRealmsScreen extends HookConsumerWidget {
children: [ children: [
CustomScrollView( CustomScrollView(
slivers: [ slivers: [
SliverGap(80), SliverGap(88),
SliverRealmList( SliverRealmList(
query: currentQuery.value, query: currentQuery.value,
key: ValueKey(currentQuery.value), key: ValueKey(currentQuery.value),

View File

@@ -163,7 +163,7 @@ class NotificationUnreadCountNotifier
} }
} }
final notificationListProvider = AsyncNotifierProvider( final notificationListProvider = AsyncNotifierProvider.autoDispose(
NotificationListNotifier.new, NotificationListNotifier.new,
); );

View File

@@ -28,9 +28,8 @@ sealed class MarketplaceStickerQuery with _$MarketplaceStickerQuery {
}) = _MarketplaceStickerQuery; }) = _MarketplaceStickerQuery;
} }
final marketplaceStickerPacksNotifierProvider = AsyncNotifierProvider( final marketplaceStickerPacksNotifierProvider =
MarketplaceStickerPacksNotifier.new, AsyncNotifierProvider.autoDispose(MarketplaceStickerPacksNotifier.new);
);
class MarketplaceStickerPacksNotifier extends AsyncNotifier<List<SnStickerPack>> class MarketplaceStickerPacksNotifier extends AsyncNotifier<List<SnStickerPack>>
with with

View File

@@ -112,8 +112,8 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
), ),
), ),
), ),
onTapOutside: onTapOutside: (_) =>
(_) => FocusManager.instance.primaryFocus?.unfocus(), FocusManager.instance.primaryFocus?.unfocus(),
), ),
const Gap(16), const Gap(16),
@@ -137,8 +137,7 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
), ),
), ),
), ),
items: items: kCurrencyIconData.keys.map((currency) {
kCurrencyIconData.keys.map((currency) {
return DropdownMenuItem( return DropdownMenuItem(
value: currency, value: currency,
child: Row( child: Row(
@@ -178,8 +177,7 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
inputFormatters: [FilteringTextInputFormatter.digitsOnly], inputFormatters: [FilteringTextInputFormatter.digitsOnly],
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'enterNumberOfSplits'.tr(), labelText: 'enterNumberOfSplits'.tr(),
hintText: hintText: selectedRecipients.isNotEmpty
selectedRecipients.isNotEmpty
? selectedRecipients.length.toString() ? selectedRecipients.length.toString()
: '1', : '1',
border: OutlineInputBorder( border: OutlineInputBorder(
@@ -188,12 +186,12 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
), ),
), ),
), ),
onTapOutside: onTapOutside: (_) =>
(_) => FocusManager.instance.primaryFocus?.unfocus(), FocusManager.instance.primaryFocus?.unfocus(),
onChanged: (value) { onChanged: (value) {
if (value.isEmpty && selectedRecipients.isNotEmpty) { if (value.isEmpty && selectedRecipients.isNotEmpty) {
splitsController.text = splitsController.text = selectedRecipients.length
selectedRecipients.length.toString(); .toString();
} }
}, },
), ),
@@ -261,8 +259,7 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
).colorScheme.outline.withOpacity(0.2), ).colorScheme.outline.withOpacity(0.2),
), ),
), ),
child: child: selectedRecipients.isNotEmpty
selectedRecipients.isNotEmpty
? Column( ? Column(
children: [ children: [
...selectedRecipients.map((recipient) { ...selectedRecipients.map((recipient) {
@@ -283,26 +280,23 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
), ),
subtitle: Text( subtitle: Text(
'selectedRecipient'.tr(), 'selectedRecipient'.tr(),
style: Theme.of( style: Theme.of(context).textTheme.bodySmall
context, ?.copyWith(
).textTheme.bodySmall?.copyWith( color: Theme.of(
color:
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
), ),
trailing: IconButton( trailing: IconButton(
onPressed: onPressed: () => setState(
() => setState( () =>
() => selectedRecipients.remove( selectedRecipients.remove(recipient),
recipient,
),
), ),
icon: Icon( icon: Icon(
Icons.clear, Icons.clear,
color: color: Theme.of(
Theme.of(context).colorScheme.error, context,
).colorScheme.error,
), ),
tooltip: 'Remove recipient', tooltip: 'Remove recipient',
), ),
@@ -316,19 +310,16 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
Icon( Icon(
Icons.person_add_outlined, Icons.person_add_outlined,
size: 48, size: 48,
color: color: Theme.of(
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
const Gap(8), const Gap(8),
Text( Text(
'noRecipientsSelected'.tr(), 'noRecipientsSelected'.tr(),
style: Theme.of( style: Theme.of(context).textTheme.bodyMedium
context, ?.copyWith(
).textTheme.bodyMedium?.copyWith( color: Theme.of(
color:
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
@@ -336,11 +327,9 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
const Gap(4), const Gap(4),
Text( Text(
'selectRecipientsToSendFund'.tr(), 'selectRecipientsToSendFund'.tr(),
style: Theme.of( style: Theme.of(context).textTheme.bodySmall
context, ?.copyWith(
).textTheme.bodySmall?.copyWith( color: Theme.of(
color:
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
@@ -399,8 +388,8 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
), ),
), ),
maxLines: 3, maxLines: 3,
onTapOutside: onTapOutside: (_) =>
(_) => FocusManager.instance.primaryFocus?.unfocus(), FocusManager.instance.primaryFocus?.unfocus(),
), ),
], ],
), ),
@@ -441,13 +430,10 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
isScrollControlled: true, isScrollControlled: true,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
useSafeArea: true, useSafeArea: true,
builder: builder: (context) => Container(
(context) => Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical( borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
top: Radius.circular(16),
),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
@@ -473,10 +459,10 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
const Gap(24), const Gap(24),
OtpTextField( OtpTextField(
numberOfFields: 6, numberOfFields: 6,
borderColor: borderColor: Theme.of(context).colorScheme.outline,
Theme.of(context).colorScheme.outline, focusedBorderColor: Theme.of(
focusedBorderColor: context,
Theme.of(context).colorScheme.primary, ).colorScheme.primary,
showFieldAsBox: true, showFieldAsBox: true,
obscureText: true, obscureText: true,
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
@@ -484,9 +470,7 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
fieldHeight: 56, fieldHeight: 56,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderWidth: 1, borderWidth: 1,
textStyle: Theme.of(context) textStyle: Theme.of(context).textTheme.headlineSmall
.textTheme
.headlineSmall
?.copyWith(fontWeight: FontWeight.w600), ?.copyWith(fontWeight: FontWeight.w600),
onSubmit: (pin) { onSubmit: (pin) {
enteredPin = pin; enteredPin = pin;
@@ -552,8 +536,7 @@ class _CreateFundSheetState extends State<CreateFundSheet> {
'split_type': selectedSplitType, 'split_type': selectedSplitType,
'amount_of_splits': splits, 'amount_of_splits': splits,
'recipient_account_ids': selectedRecipients.map((r) => r.id).toList(), 'recipient_account_ids': selectedRecipients.map((r) => r.id).toList(),
'message': 'message': messageController.text.trim().isEmpty
messageController.text.trim().isEmpty
? null ? null
: messageController.text.trim(), : messageController.text.trim(),
'pin_code': '', // Will be filled by PIN verification 'pin_code': '', // Will be filled by PIN verification
@@ -632,8 +615,8 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
), ),
), ),
), ),
onTapOutside: onTapOutside: (_) =>
(_) => FocusManager.instance.primaryFocus?.unfocus(), FocusManager.instance.primaryFocus?.unfocus(),
), ),
const Gap(16), const Gap(16),
@@ -657,8 +640,7 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
), ),
), ),
), ),
items: items: kCurrencyIconData.keys.map((currency) {
kCurrencyIconData.keys.map((currency) {
return DropdownMenuItem( return DropdownMenuItem(
value: currency, value: currency,
child: Row( child: Row(
@@ -702,8 +684,7 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
).colorScheme.outline.withOpacity(0.2), ).colorScheme.outline.withOpacity(0.2),
), ),
), ),
child: child: selectedPayee != null
selectedPayee != null
? ListTile( ? ListTile(
contentPadding: const EdgeInsets.only( contentPadding: const EdgeInsets.only(
left: 20, left: 20,
@@ -721,18 +702,16 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
), ),
subtitle: Text( subtitle: Text(
'selectedPayee'.tr(), 'selectedPayee'.tr(),
style: Theme.of( style: Theme.of(context).textTheme.bodySmall
context, ?.copyWith(
).textTheme.bodySmall?.copyWith( color: Theme.of(
color:
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
), ),
trailing: IconButton( trailing: IconButton(
onPressed: onPressed: () =>
() => setState(() => selectedPayee = null), setState(() => selectedPayee = null),
icon: Icon( icon: Icon(
Icons.clear, Icons.clear,
color: Theme.of(context).colorScheme.error, color: Theme.of(context).colorScheme.error,
@@ -746,19 +725,16 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
Icon( Icon(
Icons.person_add_outlined, Icons.person_add_outlined,
size: 48, size: 48,
color: color: Theme.of(
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
const Gap(8), const Gap(8),
Text( Text(
'noPayeeSelected'.tr(), 'noPayeeSelected'.tr(),
style: Theme.of( style: Theme.of(context).textTheme.bodyMedium
context, ?.copyWith(
).textTheme.bodyMedium?.copyWith( color: Theme.of(
color:
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
@@ -766,11 +742,9 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
const Gap(4), const Gap(4),
Text( Text(
'selectPayeeToTransfer'.tr(), 'selectPayeeToTransfer'.tr(),
style: Theme.of( style: Theme.of(context).textTheme.bodySmall
context, ?.copyWith(
).textTheme.bodySmall?.copyWith( color: Theme.of(
color:
Theme.of(
context, context,
).colorScheme.onSurfaceVariant, ).colorScheme.onSurfaceVariant,
), ),
@@ -824,8 +798,8 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
), ),
), ),
maxLines: 3, maxLines: 3,
onTapOutside: onTapOutside: (_) =>
(_) => FocusManager.instance.primaryFocus?.unfocus(), FocusManager.instance.primaryFocus?.unfocus(),
), ),
], ],
), ),
@@ -866,13 +840,10 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
isScrollControlled: true, isScrollControlled: true,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
useSafeArea: true, useSafeArea: true,
builder: builder: (context) => Container(
(context) => Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical( borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
top: Radius.circular(16),
),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
@@ -898,10 +869,10 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
const Gap(24), const Gap(24),
OtpTextField( OtpTextField(
numberOfFields: 6, numberOfFields: 6,
borderColor: borderColor: Theme.of(context).colorScheme.outline,
Theme.of(context).colorScheme.outline, focusedBorderColor: Theme.of(
focusedBorderColor: context,
Theme.of(context).colorScheme.primary, ).colorScheme.primary,
showFieldAsBox: true, showFieldAsBox: true,
obscureText: true, obscureText: true,
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
@@ -909,9 +880,7 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
fieldHeight: 56, fieldHeight: 56,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderWidth: 1, borderWidth: 1,
textStyle: Theme.of(context) textStyle: Theme.of(context).textTheme.headlineSmall
.textTheme
.headlineSmall
?.copyWith(fontWeight: FontWeight.w600), ?.copyWith(fontWeight: FontWeight.w600),
onSubmit: (pin) { onSubmit: (pin) {
enteredPin = pin; enteredPin = pin;
@@ -974,8 +943,7 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
'amount': amount, 'amount': amount,
'currency': selectedCurrency, 'currency': selectedCurrency,
'payee_account_id': selectedPayee!.id, 'payee_account_id': selectedPayee!.id,
'remark': 'remark': remarkController.text.trim().isEmpty
remarkController.text.trim().isEmpty
? null ? null
: remarkController.text.trim(), : remarkController.text.trim(),
}; };
@@ -991,7 +959,7 @@ class _CreateTransferSheetState extends State<CreateTransferSheet> {
} }
} }
final transactionListProvider = AsyncNotifierProvider( final transactionListProvider = AsyncNotifierProvider.autoDispose(
TransactionListNotifier.new, TransactionListNotifier.new,
); );
@@ -1012,14 +980,17 @@ class TransactionListNotifier extends AsyncNotifier<List<SnTransaction>>
); );
totalCount = int.parse(response.headers.value('X-Total') ?? '0'); totalCount = int.parse(response.headers.value('X-Total') ?? '0');
final List<dynamic> data = response.data; final List<dynamic> data = response.data;
final transactions = final transactions = data
data.map((json) => SnTransaction.fromJson(json)).toList(); .map((json) => SnTransaction.fromJson(json))
.toList();
return transactions; return transactions;
} }
} }
final walletFundsProvider = AsyncNotifierProvider(WalletFundsNotifier.new); final walletFundsProvider = AsyncNotifierProvider.autoDispose(
WalletFundsNotifier.new,
);
class WalletFundsNotifier extends AsyncNotifier<List<SnWalletFund>> class WalletFundsNotifier extends AsyncNotifier<List<SnWalletFund>>
with AsyncPaginationController<SnWalletFund> { with AsyncPaginationController<SnWalletFund> {
@@ -1034,8 +1005,9 @@ class WalletFundsNotifier extends AsyncNotifier<List<SnWalletFund>>
'/pass/wallets/funds?offset=$offset&take=$pageSize', '/pass/wallets/funds?offset=$offset&take=$pageSize',
); );
// Assuming total count header is present or we just check if list is empty // Assuming total count header is present or we just check if list is empty
final list = final list = (response.data as List)
(response.data as List).map((e) => SnWalletFund.fromJson(e)).toList(); .map((e) => SnWalletFund.fromJson(e))
.toList();
if (list.length < pageSize) { if (list.length < pageSize) {
totalCount = fetchedCount + list.length; totalCount = fetchedCount + list.length;
} }
@@ -1043,7 +1015,7 @@ class WalletFundsNotifier extends AsyncNotifier<List<SnWalletFund>>
} }
} }
final walletFundRecipientsProvider = AsyncNotifierProvider( final walletFundRecipientsProvider = AsyncNotifierProvider.autoDispose(
WalletFundRecipientsNotifier.new, WalletFundRecipientsNotifier.new,
); );
@@ -1060,8 +1032,7 @@ class WalletFundRecipientsNotifier
final response = await client.get( final response = await client.get(
'/pass/wallets/funds/recipients?offset=$offset&take=$_pageSize', '/pass/wallets/funds/recipients?offset=$offset&take=$_pageSize',
); );
final list = final list = (response.data as List)
(response.data as List)
.map((e) => SnWalletFundRecipient.fromJson(e)) .map((e) => SnWalletFundRecipient.fromJson(e))
.toList(); .toList();
@@ -1312,8 +1283,7 @@ class WalletScreen extends HookConsumerWidget {
return allCurrencies.map((currency) { return allCurrencies.map((currency) {
final existingPocket = pockets.firstWhere( final existingPocket = pockets.firstWhere(
(p) => p.currency == currency, (p) => p.currency == currency,
orElse: orElse: () => SnWalletPocket(
() => SnWalletPocket(
id: '', id: '',
currency: currency, currency: currency,
amount: 0.0, amount: 0.0,
@@ -1338,10 +1308,10 @@ class WalletScreen extends HookConsumerWidget {
? Symbols.money_bag ? Symbols.money_bag
: Symbols.swap_horiz, : Symbols.swap_horiz,
), ),
onPressed: onPressed: currentTabIndex.value == 1
currentTabIndex.value == 1 ? createFund : createTransfer, ? createFund
tooltip: : createTransfer,
currentTabIndex.value == 1 tooltip: currentTabIndex.value == 1
? 'createFund'.tr() ? 'createFund'.tr()
: 'createTransfer'.tr(), : 'createTransfer'.tr(),
), ),
@@ -1368,8 +1338,7 @@ class WalletScreen extends HookConsumerWidget {
} }
return NestedScrollView( return NestedScrollView(
headerSliverBuilder: headerSliverBuilder: (context, innerBoxIsScrolled) => [
(context, innerBoxIsScrolled) => [
// Wallet Overview // Wallet Overview
SliverToBoxAdapter( SliverToBoxAdapter(
child: Column( child: Column(
@@ -1388,11 +1357,8 @@ class WalletScreen extends HookConsumerWidget {
kCurrencyIconData[pocket.currency] ?? kCurrencyIconData[pocket.currency] ??
Symbols.universal_currency_alt, Symbols.universal_currency_alt,
), ),
title: title: Text(
Text( getCurrencyTranslationKey(pocket.currency),
getCurrencyTranslationKey(
pocket.currency,
),
).tr(), ).tr(),
subtitle: Text( subtitle: Text(
'${pocket.amount.toStringAsFixed(2)} ${getCurrencyTranslationKey(pocket.currency, isShort: true).tr()}', '${pocket.amount.toStringAsFixed(2)} ${getCurrencyTranslationKey(pocket.currency, isShort: true).tr()}',
@@ -1438,10 +1404,8 @@ class WalletScreen extends HookConsumerWidget {
context: context, context: context,
useRootNavigator: true, useRootNavigator: true,
isScrollControlled: true, isScrollControlled: true,
builder: builder: (context) =>
(context) => TransactionDetailSheet( TransactionDetailSheet(transaction: transaction),
transaction: transaction,
),
); );
}, },
child: ListTile( child: ListTile(
@@ -1479,8 +1443,7 @@ class WalletScreen extends HookConsumerWidget {
), ),
); );
}, },
error: error: (error, stackTrace) => ResponseErrorWidget(
(error, stackTrace) => ResponseErrorWidget(
error: error, error: error,
onRetry: () => ref.invalidate(walletCurrentProvider), onRetry: () => ref.invalidate(walletCurrentProvider),
), ),
@@ -1554,8 +1517,9 @@ class WalletScreen extends HookConsumerWidget {
itemCount: fundList.length, itemCount: fundList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final fund = fundList[index]; final fund = fundList[index];
final claimedCount = final claimedCount = fund.recipients
fund.recipients.where((r) => r.isReceived).length; .where((r) => r.isReceived)
.length;
final totalRecipients = fund.recipients.length; final totalRecipients = fund.recipients.length;
return Card( return Card(
@@ -1724,16 +1688,14 @@ class WalletScreen extends HookConsumerWidget {
), ),
); );
}, },
loading: loading: () => Card(
() => Card(
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
child: const Padding( child: const Padding(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
child: Center(child: CircularProgressIndicator()), child: Center(child: CircularProgressIndicator()),
), ),
), ),
error: error: (error, stack) => Card(
(error, stack) => Card(
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
child: Padding( child: Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),

View File

@@ -1,11 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/realm.dart'; import 'package:island/models/realm.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/pods/paging.dart'; import 'package:island/pods/paging.dart';
import 'package:island/widgets/paging/pagination_list.dart'; import 'package:island/widgets/paging/pagination_list.dart';
import 'package:island/widgets/realm/realm_card.dart'; import 'package:island/widgets/realm/realm_list_tile.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
final realmListNotifierProvider = AsyncNotifierProvider.autoDispose final realmListNotifierProvider = AsyncNotifierProvider.autoDispose
@@ -51,25 +50,12 @@ class SliverRealmList extends HookConsumerWidget {
notifier: provider.notifier, notifier: provider.notifier,
isSliver: true, isSliver: true,
isRefreshable: false, isRefreshable: false,
spacing: 8,
itemBuilder: (context, index, realm) { itemBuilder: (context, index, realm) {
return Column( return ConstrainedBox(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child:
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 540), constraints: const BoxConstraints(maxWidth: 540),
child: RealmCard(realm: realm), child: RealmListTile(realm: realm),
).center(), ).center();
),
if (index <
(ref.read(provider).value?.length ?? 0) -
1) // Add gap except for last item? Actually PaginationList handles loading indicator which might look like last item.
// Wait, ref.read(provider).value?.length might change.
// Simpler to just add bottom padding to all, or Gap.
const Gap(8),
],
);
}, },
); );
} }