Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions jive-flutter/lib/widgets/dialogs/accept_invitation_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:jive_money/models/user.dart';
import 'package:jive_money/services/invitation_service.dart';
import 'package:jive_money/providers/family_provider.dart';
import 'package:jive_money/providers/auth_provider.dart';
import 'package:jive_money/utils/snackbar_utils.dart';

/// 接受邀请对话框
class AcceptInvitationDialog extends ConsumerStatefulWidget {
Expand Down Expand Up @@ -48,6 +47,8 @@ class _AcceptInvitationDialogState
});

try {
final messenger = ScaffoldMessenger.of(context);
final navigator = Navigator.of(context);
// 调用服务接受邀请
final success = await _invitationService.acceptInvitation(
invitationId: invitation.id,
Expand All @@ -57,25 +58,27 @@ class _AcceptInvitationDialogState
if (success && mounted) {
// 刷新家庭列表
await ref.read(familyControllerProvider.notifier).loadUserFamilies();
if (!context.mounted) return;
if (!mounted) return;

// 显示成功消息
SnackbarUtils.showSuccess(
context,
'已成功加入 ${family.name}',
messenger.hideCurrentSnackBar();
messenger.showSnackBar(
SnackBar(content: Text('已成功加入 ${family.name}')),
);

// 关闭对话框
Navigator.of(context).pop(true);
navigator.pop(true);

// 触发回调
widget.onAccepted?.call();
}
} catch (e) {
if (mounted) {
SnackbarUtils.showError(
context,
'接受邀请失败: ${e.toString()}',
final messengerErr = ScaffoldMessenger.of(context);
messengerErr.showSnackBar(
SnackBar(
content: Text('接受邀请失败: ${e.toString()}'),
backgroundColor: Colors.red,
),
);
Comment on lines +76 to 82

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While this is safe because of the mounted check, to be more consistent with the goal of this PR (capturing context-dependent objects before async gaps), you could define messenger before the try block. This would allow you to reuse it here in the catch block, avoiding another call to ScaffoldMessenger.of(context) and making the code cleaner.

Example:

// In _acceptInvitation() method, before the try block
final messenger = ScaffoldMessenger.of(context);
final navigator = Navigator.of(context);

try {
  // ... async operations
} catch (e) {
  if (mounted) {
    messenger.showSnackBar(
      SnackBar(
        content: Text('接受邀请失败: ${e.toString()}'),
        backgroundColor: Colors.red,
      ),
    );
  }
}
// ...

}
} finally {
Expand All @@ -90,8 +93,6 @@ class _AcceptInvitationDialogState
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final currentUser = ref.watch(authStateProvider).value;

return AlertDialog(
title: Text(_showConfirmation ? '确认加入' : '邀请详情'),
content: SingleChildScrollView(
Expand Down
15 changes: 9 additions & 6 deletions jive-flutter/lib/widgets/dialogs/delete_family_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class _DeleteFamilyDialogState extends ConsumerState<DeleteFamilyDialog> {
Future<void> _deleteFamily() async {
if (!_isNameValid) return;

final navigator = Navigator.of(context);
final messenger = ScaffoldMessenger.of(context);

// 二次确认
final secondConfirm = await showDialog<bool>(
context: context,
Expand Down Expand Up @@ -81,7 +84,7 @@ class _DeleteFamilyDialogState extends ConsumerState<DeleteFamilyDialog> {
await familyService.deleteFamily(widget.family.id);

// 刷新Family列表
ref.refresh(userFamiliesProvider);
final _ = ref.refresh(userFamiliesProvider);

if (mounted) {
// 如果删除的是当前Family,切换到其他Family或显示空状态
Expand All @@ -91,21 +94,21 @@ class _DeleteFamilyDialogState extends ConsumerState<DeleteFamilyDialog> {
if (families.isNotEmpty) {
// 切换到第一个可用的Family
await familyService.switchFamily(families.first.family.id);
if (!context.mounted) return;
ref.refresh(currentFamilyProvider);
if (!mounted) return;
final _ = ref.refresh(currentFamilyProvider);
}
}

Navigator.of(context).pop(true);
ScaffoldMessenger.of(context).showSnackBar(
navigator.pop(true);
messenger.showSnackBar(
SnackBar(
content: Text('已删除 "${widget.family.name}"'),
backgroundColor: Colors.green,
),
);

// 导航到Family列表或Dashboard
Navigator.of(context).pushNamedAndRemoveUntil(
navigator.pushNamedAndRemoveUntil(
'/dashboard',
(route) => false,
);
Expand Down
6 changes: 3 additions & 3 deletions jive-flutter/lib/widgets/qr_code_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ class _QrCodeGeneratorState extends State<QrCodeGenerator>
? SizedBox(
width: widget.size,
height: widget.size,
child: const Center(
child: const CircularProgressIndicator(),
child: Center(
child: CircularProgressIndicator(),
),
)
: ScaleTransition(
Expand Down Expand Up @@ -321,7 +321,7 @@ class _QrCodeGeneratorState extends State<QrCodeGenerator>
width: size ?? 200,
height: size ?? 200,
color: backgroundColor ?? Colors.white,
child: const Center(
child: Center(
child: Text(
'QR Code Placeholder',
style: TextStyle(color: foregroundColor ?? Colors.black),
Expand Down
6 changes: 3 additions & 3 deletions jive-flutter/lib/widgets/states/loading_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class LoadingIndicator extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(
SizedBox(
width: size,
height: size,
child: CircularProgressIndicator(
Expand All @@ -35,7 +35,7 @@ class LoadingIndicator extends StatelessWidget {
),
),
if (message != null) ...[
const SizedBox(height: 16),
SizedBox(height: 16),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This SizedBox can be a const constructor. Using const where possible is a Flutter best practice for performance optimization, as it helps avoid unnecessary widget rebuilds. Since this PR is focused on const cleanup, it would be good to ensure we are using const where it is valid.

Suggested change
SizedBox(height: 16),
const SizedBox(height: 16),

Text(
message!,
style: theme.textTheme.bodyMedium?.copyWith(
Expand Down Expand Up @@ -115,7 +115,7 @@ class LoadingButton extends StatelessWidget {
onPressed: isLoading ? null : onPressed,
style: style,
child: isLoading
? const SizedBox(
? SizedBox(
width: loadingSize,
height: loadingSize,
child: CircularProgressIndicator(
Expand Down