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

@@ -23,7 +23,7 @@ Future<double> socialCredits(Ref ref) async {
return response.data?.toDouble() ?? 0.0;
}
final socialCreditHistoryNotifierProvider = AsyncNotifierProvider(
final socialCreditHistoryNotifierProvider = AsyncNotifierProvider.autoDispose(
SocialCreditHistoryNotifier.new,
);
@@ -45,11 +45,10 @@ class SocialCreditHistoryNotifier
totalCount = int.parse(response.headers.value('X-Total') ?? '0');
final records =
response.data
.map((json) => SnSocialCreditRecord.fromJson(json))
.cast<SnSocialCreditRecord>()
.toList();
final records = response.data
.map((json) => SnSocialCreditRecord.fromJson(json))
.cast<SnSocialCreditRecord>()
.toList();
return records;
}
@@ -68,39 +67,36 @@ class SocialCreditsTab extends HookConsumerWidget {
margin: const EdgeInsets.only(left: 16, right: 16, top: 8),
child: socialCredits
.when(
data:
(credits) => Stack(
data: (credits) => Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
credits < 100
? 'socialCreditsLevelPoor'.tr()
: credits < 150
? 'socialCreditsLevelNormal'.tr()
: credits < 200
? 'socialCreditsLevelGood'.tr()
: 'socialCreditsLevelExcellent'.tr(),
).tr().bold().fontSize(20),
Text(
'${credits.toStringAsFixed(2)} pts',
).fontSize(14),
const Gap(8),
LinearProgressIndicator(value: credits / 200),
],
),
Positioned(
right: 0,
top: 0,
child: IconButton(
onPressed: () {},
icon: const Icon(Symbols.info),
tooltip: 'socialCreditsDescription'.tr(),
),
),
Text(
credits < 100
? 'socialCreditsLevelPoor'.tr()
: credits < 150
? 'socialCreditsLevelNormal'.tr()
: credits < 200
? 'socialCreditsLevelGood'.tr()
: 'socialCreditsLevelExcellent'.tr(),
).tr().bold().fontSize(20),
Text('${credits.toStringAsFixed(2)} pts').fontSize(14),
const Gap(8),
LinearProgressIndicator(value: credits / 200),
],
),
Positioned(
right: 0,
top: 0,
child: IconButton(
onPressed: () {},
icon: const Icon(Symbols.info),
tooltip: 'socialCreditsDescription'.tr(),
),
),
],
),
error: (_, _) => Text('Error loading credits'),
loading: () => const LinearProgressIndicator(),
)
@@ -119,15 +115,14 @@ class SocialCreditsTab extends HookConsumerWidget {
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
title: Text(
record.reason,
style:
isExpired
? TextStyle(
decoration: TextDecoration.lineThrough,
color: Theme.of(
context,
).colorScheme.onSurface.withOpacity(0.8),
)
: null,
style: isExpired
? TextStyle(
decoration: TextDecoration.lineThrough,
color: Theme.of(
context,
).colorScheme.onSurface.withOpacity(0.8),
)
: null,
),
subtitle: Row(
spacing: 4,

View File

@@ -14,7 +14,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:island/widgets/paging/pagination_list.dart';
import 'package:styled_widget/styled_widget.dart';
final levelingHistoryNotifierProvider = AsyncNotifierProvider(
final levelingHistoryNotifierProvider = AsyncNotifierProvider.autoDispose(
LevelingHistoryNotifier.new,
);
@@ -35,11 +35,10 @@ class LevelingHistoryNotifier extends AsyncNotifier<List<SnExperienceRecord>>
totalCount = int.parse(response.headers.value('X-Total') ?? '0');
final List<SnExperienceRecord> records =
response.data
.map((json) => SnExperienceRecord.fromJson(json))
.cast<SnExperienceRecord>()
.toList();
final List<SnExperienceRecord> records = response.data
.map((json) => SnExperienceRecord.fromJson(json))
.cast<SnExperienceRecord>()
.toList();
return records;
}
@@ -162,8 +161,9 @@ class LevelingScreen extends HookConsumerWidget {
stopIndicatorRadius: 0,
trackGap: 0,
color: Theme.of(context).colorScheme.primary,
backgroundColor:
Theme.of(context).colorScheme.surfaceContainerHigh,
backgroundColor: Theme.of(
context,
).colorScheme.surfaceContainerHigh,
borderRadius: BorderRadius.circular(32),
),
],
@@ -186,38 +186,35 @@ class LevelingScreen extends HookConsumerWidget {
notifier: levelingHistoryNotifierProvider.notifier,
isRefreshable: false,
isSliver: true,
itemBuilder:
(context, idx, record) => ListTile(
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(record.reason),
Row(
spacing: 4,
children: [
Text(
record.createdAt.formatRelative(context),
).fontSize(13),
Text('·').fontSize(13).bold(),
Text(record.createdAt.formatSystem()).fontSize(13),
],
).opacity(0.8),
],
),
subtitle: Row(
spacing: 8,
itemBuilder: (context, idx, record) => ListTile(
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(record.reason),
Row(
spacing: 4,
children: [
Text(
'${record.delta > 0 ? '+' : ''}${record.delta} EXP',
),
if (record.bonusMultiplier != 1.0)
Text('x${record.bonusMultiplier}'),
record.createdAt.formatRelative(context),
).fontSize(13),
Text('·').fontSize(13).bold(),
Text(record.createdAt.formatSystem()).fontSize(13),
],
),
minTileHeight: 56,
contentPadding: EdgeInsets.symmetric(horizontal: 4),
),
).opacity(0.8),
],
),
subtitle: Row(
spacing: 8,
children: [
Text('${record.delta > 0 ? '+' : ''}${record.delta} EXP'),
if (record.bonusMultiplier != 1.0)
Text('x${record.bonusMultiplier}'),
],
),
minTileHeight: 56,
contentPadding: EdgeInsets.symmetric(horizontal: 4),
),
),
SliverGap(20),
@@ -249,11 +246,10 @@ class LevelStairsPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint =
Paint()
..color = surfaceColor.withOpacity(0.2)
..strokeWidth = 1.5
..style = PaintingStyle.stroke;
final paint = Paint()
..color = surfaceColor.withOpacity(0.2)
..strokeWidth = 1.5
..style = PaintingStyle.stroke;
// Draw connecting lines between stairs
for (int i = 0; i < totalLevels - 1; i++) {

View File

@@ -29,7 +29,7 @@ Future<List<SnRelationship>> sentFriendRequest(Ref ref) async {
.toList();
}
final relationshipListNotifierProvider = AsyncNotifierProvider(
final relationshipListNotifierProvider = AsyncNotifierProvider.autoDispose(
RelationshipListNotifier.new,
);
@@ -45,11 +45,10 @@ class RelationshipListNotifier extends AsyncNotifier<List<SnRelationship>>
queryParameters: {'offset': fetchedCount.toString(), 'take': take},
);
final List<SnRelationship> items =
(response.data as List)
.map((e) => SnRelationship.fromJson(e as Map<String, dynamic>))
.cast<SnRelationship>()
.toList();
final List<SnRelationship> items = (response.data as List)
.map((e) => SnRelationship.fromJson(e as Map<String, dynamic>))
.cast<SnRelationship>()
.toList();
totalCount = int.tryParse(response.headers['x-total']?.first ?? '') ?? 0;
@@ -83,8 +82,9 @@ class RelationshipListTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
final account =
showRelatedAccount ? relationship.related : relationship.account;
final account = showRelatedAccount
? relationship.related
: relationship.account;
final isPending =
relationship.status == 0 && relationship.relatedId == currentUserId;
final isWaiting =
@@ -138,64 +138,56 @@ class RelationshipListTile extends StatelessWidget {
],
),
subtitle: Text('@${account.name}'),
trailing:
showActions
? Row(
mainAxisSize: MainAxisSize.min,
children: [
if (isPending && onAccept != null)
IconButton(
padding: EdgeInsets.zero,
onPressed: submitting ? null : onAccept,
icon: const Icon(Symbols.check),
),
if (isPending && onDecline != null)
IconButton(
padding: EdgeInsets.zero,
onPressed: submitting ? null : onDecline,
icon: const Icon(Symbols.close),
),
if (isWaiting && onCancel != null)
IconButton(
padding: EdgeInsets.zero,
onPressed: submitting ? null : onCancel,
icon: const Icon(Symbols.close),
),
if (isEstablished && onUpdateStatus != null)
PopupMenuButton(
padding: EdgeInsets.zero,
icon: const Icon(Symbols.more_vert),
itemBuilder:
(context) => [
if (relationship.status >= 100) // If friend
PopupMenuItem(
child: ListTile(
leading: const Icon(Symbols.block),
title: Text('blockUser').tr(),
contentPadding: EdgeInsets.zero,
),
onTap:
() => onUpdateStatus?.call(
relationship,
-100,
),
)
else if (relationship.status <= -100) // If blocked
PopupMenuItem(
child: ListTile(
leading: const Icon(Symbols.person_add),
title: Text('unblockUser').tr(),
contentPadding: EdgeInsets.zero,
),
onTap:
() =>
onUpdateStatus?.call(relationship, 100),
),
],
),
],
)
: null,
trailing: showActions
? Row(
mainAxisSize: MainAxisSize.min,
children: [
if (isPending && onAccept != null)
IconButton(
padding: EdgeInsets.zero,
onPressed: submitting ? null : onAccept,
icon: const Icon(Symbols.check),
),
if (isPending && onDecline != null)
IconButton(
padding: EdgeInsets.zero,
onPressed: submitting ? null : onDecline,
icon: const Icon(Symbols.close),
),
if (isWaiting && onCancel != null)
IconButton(
padding: EdgeInsets.zero,
onPressed: submitting ? null : onCancel,
icon: const Icon(Symbols.close),
),
if (isEstablished && onUpdateStatus != null)
PopupMenuButton(
padding: EdgeInsets.zero,
icon: const Icon(Symbols.more_vert),
itemBuilder: (context) => [
if (relationship.status >= 100) // If friend
PopupMenuItem(
child: ListTile(
leading: const Icon(Symbols.block),
title: Text('blockUser').tr(),
contentPadding: EdgeInsets.zero,
),
onTap: () => onUpdateStatus?.call(relationship, -100),
)
else if (relationship.status <= -100) // If blocked
PopupMenuItem(
child: ListTile(
leading: const Icon(Symbols.person_add),
title: Text('unblockUser').tr(),
contentPadding: EdgeInsets.zero,
),
onTap: () => onUpdateStatus?.call(relationship, 100),
),
],
),
],
)
: null,
);
}
}
@@ -299,6 +291,7 @@ class RelationshipScreen extends HookConsumerWidget {
const Divider(height: 1),
Expanded(
child: PaginationList(
padding: EdgeInsets.zero,
provider: relationshipListNotifierProvider,
notifier: relationshipListNotifierProvider.notifier,
itemBuilder: (context, index, relationship) {
@@ -380,28 +373,26 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
const Divider(height: 1),
Expanded(
child: requests.when(
data:
(items) =>
items.isEmpty
? Center(
child: Text(
'friendSentRequestEmpty'.tr(),
textAlign: TextAlign.center,
),
)
: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (context, index) {
final request = items[index];
return RelationshipListTile(
relationship: request,
onCancel: () => cancelRequest(request),
currentUserId: user.value?.id,
showRelatedAccount: true,
);
},
),
data: (items) => items.isEmpty
? Center(
child: Text(
'friendSentRequestEmpty'.tr(),
textAlign: TextAlign.center,
),
)
: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (context, index) {
final request = items[index];
return RelationshipListTile(
relationship: request,
onCancel: () => cancelRequest(request),
currentUserId: user.value?.id,
showRelatedAccount: true,
);
},
),
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(child: Text('Error: $error')),
),

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff