Skip to content

fix: don't mark filter edit dirty on render#247

Open
salmon-21 wants to merge 1 commit into
F0x1d:masterfrom
salmon-21:fix/filter-edit-dirty-pr
Open

fix: don't mark filter edit dirty on render#247
salmon-21 wants to merge 1 commit into
F0x1d:masterfrom
salmon-21:fix/filter-edit-dirty-pr

Conversation

@salmon-21

@salmon-21 salmon-21 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Closes #248.

Summary

The filter edit screen shows the "Discard changes?" dialog (added in #245) even when the user changed nothing.

render() pushes state into the fields via setTextIfDifferent(...) → EditText.setText(...). That setText fires the field's doAfterTextChanged watcher, which sends an Update… command, and the reducer flips isDirty = true — so a pure render is mistaken for a user edit.

Because the watcher is attached on onResume / detached on onPause (core/ui/base/.../TextViewExt.kt), the spurious dirty reliably triggers after any onPause→onResume cycle (app switch, dialog, etc.) where a render runs with the watcher attached.

Fix

doAfterTextChanged now returns a setter that detaches the watcher while applying a programmatic update, then restores the lifecycle's attachment state. render() uses that setter (via setTextIfDifferent) instead of setText(), so rendering state back into the form no longer looks like a user edit. Genuine typing still flows through the watcher unchanged.

This keeps the isDirty-in-reducer design and the TEA back-routing exactly as reviewed in #245 — only the programmatic-setText path is made watcher-safe.

Test plan

  • :core:ui:base and :feature:filters:presentation compile clean.
  • On-device (SM-S948Q / Android 16): open a filter, touch nothing, back → no dialog.
  • Same but after an onPause→onResume cycle (home then resume) → still no dialog.
  • Make a real edit (toggle Including) then back → "Discard changes?" still appears; No keeps editing, Yes discards.

🤖 Generated with Claude Code

Rendering state back into the edit form called EditText.setText(), which
fired the field's text-changed watcher and sent an Update command, flipping
isDirty to true even though the user changed nothing. Returning to the
filter list then wrongly prompted "Discard changes?".

doAfterTextChanged now returns a setter that suppresses the watcher while
applying a programmatic update, and render() uses it instead of setText().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

Filter edit screen shows "Discard changes?" without any edit

1 participant