From 9d1eeae4e02c36e68b7b648e13e93e903a06c5a8 Mon Sep 17 00:00:00 2001 From: zensgit <77236085+zensgit@users.noreply.github.com> Date: Sat, 27 Sep 2025 21:17:21 +0800 Subject: [PATCH 1/4] =?UTF-8?q?flutter:=20Share=E2=86=92SharePlus=20migrat?= =?UTF-8?q?ion=20step=201=20=E2=80=94=20switch=20to=20SharePlus.instance.s?= =?UTF-8?q?hare/shareXFiles=20in=20QR=20+=20ShareService;=20remove=20local?= =?UTF-8?q?=20stub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jive-flutter/lib/services/share_service.dart | 28 ++++++++----------- .../lib/widgets/qr_code_generator.dart | 4 +-- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/jive-flutter/lib/services/share_service.dart b/jive-flutter/lib/services/share_service.dart index 63d9e214..a651b56b 100644 --- a/jive-flutter/lib/services/share_service.dart +++ b/jive-flutter/lib/services/share_service.dart @@ -10,14 +10,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:jive_money/providers/currency_provider.dart'; // Stub for Share class to resolve undefined_identifier errors during cleanup -class Share { - static Future share(String text, {String? subject}) async { - // TODO: Implement actual share functionality - debugPrint('Share text: $text'); - debugPrint('Share subject: $subject'); - } - - static Future shareXFiles(List files, {String? text}) async { +static Future shareXFiles(List files, {String? text}) async { // TODO: Implement actual share functionality debugPrint('Share files: ${files.length} files'); debugPrint('Share text: $text'); @@ -56,7 +49,7 @@ Jive Money - 您的智能家庭财务管家 '''; try { - await Share.share( + await SharePlus.instance.share( shareText, subject: '邀请你加入家庭「$familyName」', ); @@ -145,7 +138,7 @@ Jive Money - 您的智能家庭财务管家 ); } else { // 仅分享文字 - await Share.share(shareText); + await SharePlus.instance.share(shareText); if (!context.mounted) return; } } catch (e) { @@ -183,7 +176,7 @@ ${transaction.note?.isNotEmpty == true ? '📝 备注:${transaction.note}' : ' '''; try { - await Share.share(shareText); + await SharePlus.instance.share(shareText); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -233,7 +226,7 @@ ${transaction.note?.isNotEmpty == true ? '📝 备注:${transaction.note}' : ' try { // 根据平台定制分享内容(统一走系统分享,避免外部依赖) - await Share.share(shareContent); + await SharePlus.instance.share(shareContent); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -258,7 +251,7 @@ ${description ?? ''} $data '''; - await Share.share(shareText); + await SharePlus.instance.share(shareText); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -290,8 +283,9 @@ $data String? text, }) async { try { - final xFiles = images.map((file) => XFile(file.path)).toList(); - await Share.shareXFiles(xFiles, text: text); + final List xFiles = + images.map((file) => XFile(file.path)).toList(); + await Share.shareXFiles(xFiles as List, text: text); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -302,7 +296,7 @@ $data static Future _shareToWechat( BuildContext context, String content) async { // Stub: 使用系统分享 - await Share.share(content); + await SharePlus.instance.share(content); } static String _getRoleDisplayName(family_model.FamilyRole role) { @@ -512,7 +506,7 @@ class ShareDialog extends StatelessWidget { color: theme.colorScheme.primary, onPressed: onShareMore ?? () async { - await Share.share('$content\n\n$url'); + await SharePlus.instance.share('$content\n\n$url'); if (context.mounted) { Navigator.pop(context); } diff --git a/jive-flutter/lib/widgets/qr_code_generator.dart b/jive-flutter/lib/widgets/qr_code_generator.dart index 930f79ea..6f977795 100644 --- a/jive-flutter/lib/widgets/qr_code_generator.dart +++ b/jive-flutter/lib/widgets/qr_code_generator.dart @@ -87,9 +87,7 @@ class _QrCodeGeneratorState extends State await imageFile.writeAsBytes(image); // 分享 - await Share.shareXFiles( - [XFile(imagePath)], - text: '${widget.title}\n${widget.subtitle ?? ''}\n${widget.data}', + await SharePlus.instance.shareXFiles([XFile(imagePath)], text: '${widget.title}\n${widget.subtitle ?? ''}\n${widget.data}', ); // 触发回调 From 6301183a55a47b623b8c0feced9669d29387952f Mon Sep 17 00:00:00 2001 From: zensgit <77236085+zensgit@users.noreply.github.com> Date: Sat, 27 Sep 2025 21:51:04 +0800 Subject: [PATCH 2/4] flutter: clean QR widget placeholder + remove local Share stub; use share_plus directly --- jive-flutter/lib/services/share_service.dart | 31 ++++++------------- .../lib/widgets/qr_code_generator.dart | 21 ++++--------- 2 files changed, 16 insertions(+), 36 deletions(-) diff --git a/jive-flutter/lib/services/share_service.dart b/jive-flutter/lib/services/share_service.dart index a651b56b..100c3b81 100644 --- a/jive-flutter/lib/services/share_service.dart +++ b/jive-flutter/lib/services/share_service.dart @@ -9,13 +9,6 @@ import 'package:jive_money/models/transaction.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:jive_money/providers/currency_provider.dart'; -// Stub for Share class to resolve undefined_identifier errors during cleanup -static Future shareXFiles(List files, {String? text}) async { - // TODO: Implement actual share functionality - debugPrint('Share files: ${files.length} files'); - debugPrint('Share text: $text'); - } -} /// 分享服务 class ShareService { @@ -49,7 +42,7 @@ Jive Money - 您的智能家庭财务管家 '''; try { - await SharePlus.instance.share( + await Share.share( shareText, subject: '邀请你加入家庭「$familyName」', ); @@ -132,13 +125,10 @@ Jive Money - 您的智能家庭财务管家 // await imageFile.writeAsBytes(image); // 分享图片和文字 - await Share.shareXFiles( - [XFile(imagePath)], - text: shareText, - ); + await Share.shareXFiles([XFile(imagePath)], text: shareText); } else { // 仅分享文字 - await SharePlus.instance.share(shareText); + await Share.share(shareText); if (!context.mounted) return; } } catch (e) { @@ -176,7 +166,7 @@ ${transaction.note?.isNotEmpty == true ? '📝 备注:${transaction.note}' : ' '''; try { - await SharePlus.instance.share(shareText); + await Share.share(shareText); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -226,7 +216,7 @@ ${transaction.note?.isNotEmpty == true ? '📝 备注:${transaction.note}' : ' try { // 根据平台定制分享内容(统一走系统分享,避免外部依赖) - await SharePlus.instance.share(shareContent); + await Share.share(shareContent); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -251,7 +241,7 @@ ${description ?? ''} $data '''; - await SharePlus.instance.share(shareText); + await Share.share(shareText); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -283,9 +273,8 @@ $data String? text, }) async { try { - final List xFiles = - images.map((file) => XFile(file.path)).toList(); - await Share.shareXFiles(xFiles as List, text: text); + final xFiles = images.map((file) => XFile(file.path)).toList(); + await Share.shareXFiles(xFiles, text: text); if (!context.mounted) return; } catch (e) { _showError(context, '分享失败: $e'); @@ -296,7 +285,7 @@ $data static Future _shareToWechat( BuildContext context, String content) async { // Stub: 使用系统分享 - await SharePlus.instance.share(content); + await Share.share(content); } static String _getRoleDisplayName(family_model.FamilyRole role) { @@ -506,7 +495,7 @@ class ShareDialog extends StatelessWidget { color: theme.colorScheme.primary, onPressed: onShareMore ?? () async { - await SharePlus.instance.share('$content\n\n$url'); + await Share.share('$content\n\n$url'); if (context.mounted) { Navigator.pop(context); } diff --git a/jive-flutter/lib/widgets/qr_code_generator.dart b/jive-flutter/lib/widgets/qr_code_generator.dart index 6f977795..6eb2381c 100644 --- a/jive-flutter/lib/widgets/qr_code_generator.dart +++ b/jive-flutter/lib/widgets/qr_code_generator.dart @@ -87,7 +87,9 @@ class _QrCodeGeneratorState extends State await imageFile.writeAsBytes(image); // 分享 - await SharePlus.instance.shareXFiles([XFile(imagePath)], text: '${widget.title}\n${widget.subtitle ?? ''}\n${widget.data}', + await Share.shareXFiles( + [XFile(imagePath)], + text: '${widget.title}\n${widget.subtitle ?? ''}\n${widget.data}', ); // 触发回调 @@ -196,8 +198,8 @@ class _QrCodeGeneratorState extends State ? SizedBox( width: widget.size, height: widget.size, - child: const Center( - child: const CircularProgressIndicator(), + child: Center( + child: CircularProgressIndicator(), ), ) : ScaleTransition( @@ -299,11 +301,6 @@ class _QrCodeGeneratorState extends State ); } - // Stub methods for missing external dependencies - dynamic XFile(String path) { - return _StubXFile(path); - } - Widget QrImageView({ required String data, dynamic version, @@ -319,7 +316,7 @@ class _QrCodeGeneratorState extends State 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), @@ -539,9 +536,3 @@ class _InfoRow extends StatelessWidget { } } - -// Stub implementation for XFile -class _StubXFile { - final String path; - _StubXFile(this.path); -} From c1a00d28bac3cf1d7efc1d2300c1d178bb78e329 Mon Sep 17 00:00:00 2001 From: zensgit <77236085+zensgit@users.noreply.github.com> Date: Sat, 27 Sep 2025 22:13:51 +0800 Subject: [PATCH 3/4] flutter: fix use_build_context_synchronously in AcceptInvitationDialog and DeleteFamilyDialog --- .../dialogs/accept_invitation_dialog.dart | 21 ++++++++++++------- .../widgets/dialogs/delete_family_dialog.dart | 9 +++++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/jive-flutter/lib/widgets/dialogs/accept_invitation_dialog.dart b/jive-flutter/lib/widgets/dialogs/accept_invitation_dialog.dart index 81afc3ed..b936767f 100644 --- a/jive-flutter/lib/widgets/dialogs/accept_invitation_dialog.dart +++ b/jive-flutter/lib/widgets/dialogs/accept_invitation_dialog.dart @@ -6,7 +6,7 @@ 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'; +// import 'package:jive_money/utils/snackbar_utils.dart'; /// 接受邀请对话框 class AcceptInvitationDialog extends ConsumerStatefulWidget { @@ -48,6 +48,9 @@ class _AcceptInvitationDialogState }); try { + // Capture navigator and messenger before async gaps to avoid using context after await + final navigator = Navigator.of(context); + final messenger = ScaffoldMessenger.of(context); // 调用服务接受邀请 final success = await _invitationService.acceptInvitation( invitationId: invitation.id, @@ -60,22 +63,24 @@ class _AcceptInvitationDialogState if (!context.mounted) return; // 显示成功消息 - SnackbarUtils.showSuccess( - context, - '已成功加入 ${family.name}', + 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 messenger = ScaffoldMessenger.of(context); + messenger.showSnackBar( + SnackBar( + content: Text('接受邀请失败: ${e.toString()}'), + backgroundColor: Colors.red, + ), ); } } finally { diff --git a/jive-flutter/lib/widgets/dialogs/delete_family_dialog.dart b/jive-flutter/lib/widgets/dialogs/delete_family_dialog.dart index 8e6f3b38..48ca20ed 100644 --- a/jive-flutter/lib/widgets/dialogs/delete_family_dialog.dart +++ b/jive-flutter/lib/widgets/dialogs/delete_family_dialog.dart @@ -77,6 +77,9 @@ class _DeleteFamilyDialogState extends ConsumerState { }); try { + // Capture UI handles before async work + final navigator = Navigator.of(context); + final messenger = ScaffoldMessenger.of(context); final familyService = FamilyService(); await familyService.deleteFamily(widget.family.id); @@ -96,8 +99,8 @@ class _DeleteFamilyDialogState extends ConsumerState { } } - Navigator.of(context).pop(true); - ScaffoldMessenger.of(context).showSnackBar( + navigator.pop(true); + messenger.showSnackBar( SnackBar( content: Text('已删除 "${widget.family.name}"'), backgroundColor: Colors.green, @@ -105,7 +108,7 @@ class _DeleteFamilyDialogState extends ConsumerState { ); // 导航到Family列表或Dashboard - Navigator.of(context).pushNamedAndRemoveUntil( + navigator.pushNamedAndRemoveUntil( '/dashboard', (route) => false, ); From 5f0503e2d6f67dc1f8c1bcc733940f94e7a6ad0d Mon Sep 17 00:00:00 2001 From: zensgit <77236085+zensgit@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:09:01 +0800 Subject: [PATCH 4/4] flutter: bump share_plus to ^12.0.0 (prep for instance API) --- jive-flutter/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jive-flutter/pubspec.yaml b/jive-flutter/pubspec.yaml index 13755cc6..5427e9d7 100644 --- a/jive-flutter/pubspec.yaml +++ b/jive-flutter/pubspec.yaml @@ -78,7 +78,7 @@ dependencies: web_socket_channel: any mailer: any - share_plus: any + share_plus: ^12.0.0 screenshot: any uni_links: any qr_flutter: any