From 3664d89f43f70ec47c12eb2f152c1dd1f7007faf Mon Sep 17 00:00:00 2001 From: Bretton <36870434+BrettM86@users.noreply.github.com> Date: Thu, 16 Jul 2026 05:04:35 -0700 Subject: [PATCH] fix(compose): reply drafts were never saved, restored, or cleared ReplyScreen looked up CommentsProvider with context.read from its own element context, but the screen is pushed on the root navigator where no CommentsProvider ancestor exists (the instance is handed in as widget.commentsProvider and only provided BELOW, to the preview subtree). Every saveDraft/getDraft/clearDraft threw ProviderNotFoundException and was swallowed by the debug-log catch, so cancel-with-draft silently lost the text. Use widget.commentsProvider directly. Verified on emulator via .maestro/e4_reply_draft.yaml: type, Cancel, reopen -> draft restored; Send -> reply lands in the thread. Co-Authored-By: Claude Fable 5 --- lib/screens/compose/reply_screen.dart | 64 ++++++++++----------------- 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/lib/screens/compose/reply_screen.dart b/lib/screens/compose/reply_screen.dart index 89e749d..d54bf7d 100644 --- a/lib/screens/compose/reply_screen.dart +++ b/lib/screens/compose/reply_screen.dart @@ -136,25 +136,21 @@ class _ReplyScreenState extends State with WidgetsBindingObserver { } /// Restore draft text if available for this reply context + /// + /// Uses [widget.commentsProvider] directly — this screen is pushed on the + /// root navigator, so `context.read()` would look above + /// the route and find nothing (the provider lives in the detail screen). void _restoreDraft() { - try { - final commentsProvider = context.read(); - final ourParentUri = widget.comment?.comment.uri; + final ourParentUri = widget.comment?.comment.uri; - // Get draft for this specific parent URI - final draft = commentsProvider.getDraft(parentUri: ourParentUri); + // Get draft for this specific parent URI + final draft = widget.commentsProvider.getDraft(parentUri: ourParentUri); - if (draft.isNotEmpty) { - _textController.text = draft; - setState(() { - _hasText = true; - }); - } - } on Exception catch (e) { - // CommentsProvider might not be available (e.g., during testing) - if (kDebugMode) { - debugPrint('📝 Draft not restored: $e'); - } + if (draft.isNotEmpty) { + _textController.text = draft; + setState(() { + _hasText = true; + }); } } @@ -249,18 +245,11 @@ class _ReplyScreenState extends State with WidgetsBindingObserver { final facets = FacetDetector.detectLinks(content); await widget.onSubmit(content, facets); - // Clear draft on success - try { - if (mounted) { - final parentUri = widget.comment?.comment.uri; - context.read().clearDraft(parentUri: parentUri); - } - } on Exception catch (e) { - // CommentsProvider might not be available - if (kDebugMode) { - debugPrint('📝 Draft not cleared: $e'); - } - } + // Clear draft on success (widget.commentsProvider, not context.read — + // the provider is not an ancestor of this pushed route) + widget.commentsProvider.clearDraft( + parentUri: widget.comment?.comment.uri, + ); // Pop screen after successful submission if (mounted) { Navigator.of(context).pop(); @@ -327,20 +316,13 @@ class _ReplyScreenState extends State with WidgetsBindingObserver { Navigator.of(context).pop(); } - /// Save current text as draft + /// Save current text as draft (widget.commentsProvider, not context.read — + /// the provider is not an ancestor of this pushed route) void _saveDraft() { - try { - final commentsProvider = context.read(); - commentsProvider.saveDraft( - _textController.text, - parentUri: widget.comment?.comment.uri, - ); - } on Exception catch (e) { - // CommentsProvider might not be available - if (kDebugMode) { - debugPrint('📝 Draft not saved: $e'); - } - } + widget.commentsProvider.saveDraft( + _textController.text, + parentUri: widget.comment?.comment.uri, + ); } @override -- 2.51.2