Skip to content

Conversation

@zensgit
Copy link
Owner

@zensgit zensgit commented Sep 28, 2025

Changes

  • Capture Navigator/ScaffoldMessenger before awaits in TemplateAdminPage
  • Use mounted guards after awaits
  • Remove redundant analyzer ignores

Validation

  • flutter analyze: no blocking errors
  • flutter test: all tests passing

Notes

  • Keeping this PR small and focused; will follow up with theme/auth screens in next batch.

@Copilot Copilot AI review requested due to automatic review settings September 28, 2025 03:24
@gemini-code-assist
Copy link

Summary of Changes

Hello @zensgit, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on enhancing the stability and maintainability of the Flutter application by addressing common BuildContext usage pitfalls in asynchronous operations and resolving numerous static analyzer warnings. It also includes improvements to service layer consistency, a simplification of the sharing functionality, and better logging in the Rust backend. The changes aim to create a more robust and predictable application behavior.

Highlights

  • Flutter Context-Safety Refactor: Implemented a widespread refactoring to ensure Flutter's BuildContext is not used across asynchronous gaps. This was achieved by capturing Navigator.of(context) and ScaffoldMessenger.of(context) into local variables before await calls and replacing context.mounted checks with mounted.
  • Flutter Analyzer Warnings Addressed: Removed redundant analyzer ignores and converted numerous const SizedBox and const Text widgets to non-const SizedBox and Text where appropriate, resolving const_eval_method_invocation and invalid_constant warnings.
  • Service Layer Enhancements: Updated several service calls across the Flutter application to consistently use named parameters (e.g., familyId: widget.familyId) and refined return types for AuditService.getAuditStatistics and FamilySettingsService methods.
  • Share Service Simplification: The ShareService was simplified by removing stub implementations for Share, XFile, and ScreenshotController, and disabling image sharing functionality to prioritize stability with text-only sharing.
  • Backend Logging and Error Handling: Enhanced the Rust backend's AuthService with detailed tracing::info! and tracing::error! logs for user registration and family creation, alongside improved error handling for family creation failures.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves context safety in Flutter code by addressing use_build_context_synchronously warnings through capturing context-dependent objects before async operations and using mounted guards. The primary focus is on the TemplateAdminPage with systematic cleanup of analyzer warnings across multiple files.

  • Captured Navigator/ScaffoldMessenger before awaits and used mounted guards in TemplateAdminPage
  • Applied context-safety patterns to multiple dialog and widget files throughout the codebase
  • Removed redundant analyzer ignore comments and cleaned up unused imports/code

Reviewed Changes

Copilot reviewed 39 out of 43 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
jive-flutter/lib/screens/admin/template_admin_page.dart Applied context-safety pattern by capturing messenger/navigator before awaits and using mounted guards
jive-flutter/lib/widgets/theme_share_dialog.dart Updated to capture ScaffoldMessenger before async operations and use mounted guards
jive-flutter/lib/widgets/dialogs/accept_invitation_dialog.dart Removed unused imports and captured context objects before async calls
jive-flutter/lib/widgets/batch_operation_bar.dart Applied context-safety pattern with captured navigator/messenger and mounted guards
jive-flutter/lib/services/share_service.dart Cleaned up stub code and improved context handling for clipboard operations
jive-flutter/lib/widgets/states/loading_indicator.dart Removed const from SizedBox constructors with non-constant parameters

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 395 to 398
// ignore: use_build_context_synchronously
navigator.pop();
widget.onConfirm();
ScaffoldMessenger.of(context).showSnackBar(
// ignore: use_build_context_synchronously
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

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

The analyzer ignore comments are unnecessary since the Navigator and ScaffoldMessenger were captured before the async operation. These ignores should be removed as the context safety issue has been properly resolved.

Copilot uses AI. Check for mistakes.
Comment on lines 486 to 489
// ignore: use_build_context_synchronously
navigator.pop();
widget.onConfirm();
ScaffoldMessenger.of(context).showSnackBar(
// ignore: use_build_context_synchronously
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

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

Similar to the previous comment, these analyzer ignore directives are redundant since the context objects were properly captured before the async operation. Remove these ignore comments.

Copilot uses AI. Check for mistakes.
final result = await _authService.wechatLogin();

if (!context.mounted) return;
// ignore: use_build_context_synchronously
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

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

The ignore comment is misplaced. The ScaffoldMessenger is being captured at the right time (before the async operation), so this ignore comment should be removed. The actual usage of messenger later doesn't need ignoring since it was properly captured.

Suggested change
// ignore: use_build_context_synchronously

Copilot uses AI. Check for mistakes.
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request focuses on improving code quality and stability, particularly by addressing use_build_context_synchronously warnings in the Flutter codebase. The changes to capture BuildContext dependent objects like Navigator and ScaffoldMessenger before await calls are excellent and follow best practices. The Rust changes also improve logging and error handling.

However, I've identified a few instances where the use_build_context_synchronously fix was applied incorrectly, potentially hiding the issue with an ignore comment. There are also some minor regressions and opportunities for more idiomatic code. Additionally, some build artifacts have been included in the commit, which should be added to .gitignore.

Comment on lines 506 to 507
if (!context.mounted) return;
// ignore: use_build_context_synchronously
final messenger = ScaffoldMessenger.of(context);

Choose a reason for hiding this comment

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

high

This fix for use_build_context_synchronously is incorrect. The ScaffoldMessenger should be captured before the await call to ensure the BuildContext is still valid. The ignore comment is hiding a potential runtime error. Also, it's better to use the mounted property directly in a StatefulWidget's state.

Suggested change
if (!context.mounted) return;
// ignore: use_build_context_synchronously
final messenger = ScaffoldMessenger.of(context);
final messenger = ScaffoldMessenger.of(context);
final result = await _authService.wechatLogin();
if (!mounted) return;

Comment on lines 138 to 144
await Clipboard.setData(ClipboardData(text: text));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? '已复制到剪贴板'),
duration: const Duration(seconds: 2),
),
);
}
messenger.showSnackBar(
SnackBar(
content: Text(message ?? '已复制到剪贴板'),
duration: const Duration(seconds: 2),
),
);

Choose a reason for hiding this comment

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

high

The if (context.mounted) check was removed. It's important to keep this check after an await call to prevent errors if the widget is disposed before the async operation completes. While messenger is captured before the await, the check is still necessary before using it.

Suggested change
await Clipboard.setData(ClipboardData(text: text));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? '已复制到剪贴板'),
duration: const Duration(seconds: 2),
),
);
}
messenger.showSnackBar(
SnackBar(
content: Text(message ?? '已复制到剪贴板'),
duration: const Duration(seconds: 2),
),
);
await Clipboard.setData(ClipboardData(text: text));
if (!context.mounted) return;
messenger.showSnackBar(
SnackBar(
content: Text(message ?? '已复制到剪贴板'),
duration: const Duration(seconds: 2),
),
);

Comment on lines 392 to 402
if (!mounted) return;
Navigator.pop(context);
final navigator = Navigator.of(context);
final messenger = ScaffoldMessenger.of(context);
// ignore: use_build_context_synchronously
navigator.pop();
widget.onConfirm();
ScaffoldMessenger.of(context).showSnackBar(
// ignore: use_build_context_synchronously
messenger.showSnackBar(
SnackBar(
content: Text('已移动 ${widget.selectedIds.length} 个分类'),
),

Choose a reason for hiding this comment

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

high

This fix for use_build_context_synchronously is incorrect. The navigator and messenger are captured after the await call, and the problem is hidden with an ignore comment. These should be captured before the await to ensure the BuildContext is still valid when they are used.

            final navigator = Navigator.of(context);
            final messenger = ScaffoldMessenger.of(context);
            await provider.batchMoveCategories(
              widget.selectedIds,
              _targetParentId,
            );
            if (!mounted) return;
            navigator.pop();
            widget.onConfirm();
            messenger.showSnackBar(
              SnackBar(
                content: Text('已移动 ${widget.selectedIds.length} 个分类'),
              ),
            );

Comment on lines 483 to 493
}

Navigator.pop(context);
final navigator = Navigator.of(context);
final messenger = ScaffoldMessenger.of(context);
// ignore: use_build_context_synchronously
navigator.pop();
widget.onConfirm();
ScaffoldMessenger.of(context).showSnackBar(
// ignore: use_build_context_synchronously
messenger.showSnackBar(
SnackBar(
content: Text('已转换 ${widget.selectedIds.length} 个分类为标签'),
),

Choose a reason for hiding this comment

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

high

Similar to the other async operation in this file, this fix for use_build_context_synchronously is incorrect. The navigator and messenger are captured after the await call, and the problem is hidden with an ignore comment. These should be captured before the await to ensure the BuildContext is still valid.

            }
            final navigator = Navigator.of(context);
            final messenger = ScaffoldMessenger.of(context);
            navigator.pop();
            widget.onConfirm();
            messenger.showSnackBar(
              SnackBar(
                content: Text('已转换 ${widget.selectedIds.length} 个分类为标签'),
              ),
            );

Comment on lines 124 to 130
let family = match family_service.create_family(user_id, family_request).await {
Ok(f) => f,
Err(e) => {
tracing::error!(target: "auth_service", error = ?e, user_id = %user_id, "register_with_family: create_family failed");
return Err(e);
}
};

Choose a reason for hiding this comment

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

medium

While this match block works for logging the error, a more idiomatic and concise way to handle this in Rust is to use the map_err combinator. This avoids the explicit match and keeps the error-propagation flow of the ? operator, making the code cleaner.

        let family = family_service.create_family(user_id, family_request).await
            .map_err(|e| {
                tracing::error!(target: "auth_service", error = ?e, user_id = %user_id, "register_with_family: create_family failed");
                e
            })?;

Comment on lines 105 to 107
isOverBudget
? '超支 ${ref.read(currencyProvider.notifier).formatCurrency(-remaining, ref.read(baseCurrencyProvider).code)}'
: '剩余 ${ref.read(currencyProvider.notifier).formatCurrency(remaining, ref.read(baseCurrencyProvider).code)}',
? '超支 ${remaining.abs().toStringAsFixed(2)}'
: '剩余 ${remaining.toStringAsFixed(2)}',

Choose a reason for hiding this comment

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

medium

This change removes the currency formatting and replaces it with a hardcoded toStringAsFixed(2). This is a regression, as it loses the currency symbol and locale-specific formatting provided by currencyProvider. It's better to use the currency provider to ensure consistent formatting across the app.

Suggested change
isOverBudget
? '超支 ${ref.read(currencyProvider.notifier).formatCurrency(-remaining, ref.read(baseCurrencyProvider).code)}'
: '剩余 ${ref.read(currencyProvider.notifier).formatCurrency(remaining, ref.read(baseCurrencyProvider).code)}',
? '超支 ${remaining.abs().toStringAsFixed(2)}'
: '剩余 ${remaining.toStringAsFixed(2)}',
isOverBudget
? '超支 ${ref.read(currencyProvider.notifier).formatCurrency(remaining.abs(), ref.read(baseCurrencyProvider).code)}'
: '剩余 ${ref.read(currencyProvider.notifier).formatCurrency(remaining, ref.read(baseCurrencyProvider).code)}',

@@ -0,0 +1,349 @@
Resolving dependencies...

Choose a reason for hiding this comment

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

medium

This file and the local-artifacts directory appear to be build artifacts or local analyzer outputs. These types of files are generally not committed to source control. Please consider adding local-artifacts/ to your .gitignore file to prevent them from being tracked.

@zensgit zensgit merged commit d76695b into main Oct 8, 2025
7 checks passed
@zensgit zensgit deleted the flutter/context-cleanup-batch2 branch October 8, 2025 02:57
@zensgit zensgit mentioned this pull request Oct 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant