Skip to content

Implement GutenbergKit ViewModel Architecture#22087

Merged
oguzkocer merged 6 commits intotrunkfrom
gutenberg-kit-viewmodel
Aug 1, 2025
Merged

Implement GutenbergKit ViewModel Architecture#22087
oguzkocer merged 6 commits intotrunkfrom
gutenberg-kit-viewmodel

Conversation

@oguzkocer
Copy link
Contributor

Summary

Replaces static variable pattern in GutenbergKitEditorFragment with proper ViewModel architecture to improve state management and prevent memory leaks.

Key Changes

  • Create GutenbergKitViewModel with dependency injection
  • Replace static settings variable with ViewModel-based state management
  • Add Dagger injection support for GutenbergKitEditorFragment

Technical Benefits

  • Memory leak prevention: Eliminates static variables that retain references
  • Lifecycle awareness: Proper state management that survives configuration changes
  • Modern architecture: Follows Android ViewModel best practices

@oguzkocer oguzkocer added this to the 26.1 milestone Aug 1, 2025
@oguzkocer oguzkocer added Posting/Editing Gutenberg Editing and display of Gutenberg blocks. labels Aug 1, 2025
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Aug 1, 2025

WordPress📲 You can test the changes from this Pull Request in WordPress by scanning the QR code below to install the corresponding build.
App NameWordPress WordPress
FlavorJalapeno
Build TypeDebug
Versionpr22087-9408799
Commit9408799
Direct Downloadwordpress-prototype-build-pr22087-9408799.apk
Note: Google Login is not supported on these builds.

@oguzkocer oguzkocer requested a review from dcalhoun August 1, 2025 07:11
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Aug 1, 2025

Jetpack📲 You can test the changes from this Pull Request in Jetpack by scanning the QR code below to install the corresponding build.
App NameJetpack Jetpack
FlavorJalapeno
Build TypeDebug
Versionpr22087-9408799
Commit9408799
Direct Downloadjetpack-prototype-build-pr22087-9408799.apk
Note: Google Login is not supported on these builds.

@codecov
Copy link

codecov bot commented Aug 1, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 39.43%. Comparing base (232380a) to head (9408799).
⚠️ Report is 2 commits behind head on trunk.

Additional details and impacted files
@@           Coverage Diff           @@
##            trunk   #22087   +/-   ##
=======================================
  Coverage   39.43%   39.43%           
=======================================
  Files        2149     2149           
  Lines      101872   101872           
  Branches    15604    15604           
=======================================
  Hits        40177    40177           
  Misses      58126    58126           
  Partials     3569     3569           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@dcalhoun dcalhoun left a comment

Choose a reason for hiding this comment

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

These are significant stability and comprehensibility improvements. Thank you for completing this! 🙇🏻‍♂️

I stepped through each commit individually. Each of the commits a very logical and sound. Thank you for organizing the commit history so well.

I tested the experimental editor by performing documented test cases. I did not encounter any regressions aside from the remote editor load failure noted in a sibling PR: #22086 (review).

@oguzkocer oguzkocer force-pushed the convert-gutenberg-kit-fragment-to-kotlin branch from ab161e3 to a293fb3 Compare August 1, 2025 15:35
@oguzkocer oguzkocer force-pushed the gutenberg-kit-viewmodel branch from fe43d49 to ef8b42b Compare August 1, 2025 16:07
Base automatically changed from convert-gutenberg-kit-fragment-to-kotlin to trunk August 1, 2025 19:17
Replace the untyped Map<String, Any?> settings pattern with a proper data class
for better type safety and cleaner code in GutenbergKitEditorFragment.

Changes:
- Add GutenbergKitSettings data class with all required properties and proper types
- Use List<String> instead of Array<String> for better immutability and equals behavior
- Update createGutenbergKitSettings() to return typed data class instead of Map
- Replace generic getSetting<T>() helper methods with direct property access
- Simplify buildEditorConfiguration() method using typed properties
- Convert Lists to Arrays only when interfacing with external APIs (.toTypedArray())
- Add serialVersionUID for proper Serializable implementation

Benefits:
- Compile-time type safety instead of runtime casting
- Clearer API contract and better IDE support
- Eliminates potential ClassCastException errors
- Better equals/hashCode behavior with Lists vs Arrays
- More maintainable and readable code
Fixes Detekt SerialVersionUIDInSerializableClass violation by adding
required serialVersionUID constant to the Serializable data class.
Replace problematic static variable pattern with proper ViewModel architecture
for GutenbergKit editor settings management.

Changes:
- Create GutenbergKitViewModel with proper DI setup
- Update EditPostActivity to initialize ViewModel and pass settings through it
- Update GutenbergKitEditorFragment to observe ViewModel instead of Bundle/static settings
- Remove Bundle serialization and static companion object settings variable
- Add Dagger injection support for GutenbergKitEditorFragment
- Fix dependency injection timing by triggering DI in onCreate()

Benefits:
- Eliminates memory leaks from static variables
- Fixes WebViewGlobal serialization crashes
- Enables proper lifecycle-aware state management
- Provides foundation for reactive settings updates
Relocate GutenbergKitSettings data class from GutenbergKitEditorFragment
to GutenbergKitViewModel for improved code organization and cohesion.

Changes:
- Move GutenbergKitSettings data class to GutenbergKitViewModel.kt
- Update import statements in EditPostActivity and GutenbergKitEditorFragment
- Co-locate data model with its managing ViewModel
Resolve linting issues identified by Detekt:
- Remove unused import for GutenbergKitSettings in EditPostActivity
- Fix spacing between imports and class declaration
- Remove unused imports for WebViewGlobal and Serializable
Add a test to verify core functionality:
- Test that updateEditorSettings correctly stores and exposes settings
- Validates the primary use case of the ViewModel
- Ensures settings can be retrieved after being set
@oguzkocer oguzkocer force-pushed the gutenberg-kit-viewmodel branch from ef8b42b to 9408799 Compare August 1, 2025 20:22
@oguzkocer oguzkocer marked this pull request as ready for review August 1, 2025 20:22
@sonarqubecloud
Copy link

sonarqubecloud bot commented Aug 1, 2025

@oguzkocer oguzkocer merged commit 890d484 into trunk Aug 1, 2025
27 checks passed
@oguzkocer oguzkocer deleted the gutenberg-kit-viewmodel branch August 1, 2025 22:38
@sentry
Copy link

sentry bot commented Aug 2, 2025

Suspect Issues

This pull request was deployed and Sentry observed the following issues:

Did you find this useful? React with a 👍 or 👎

@oguzkocer
Copy link
Contributor Author

This pull request was deployed and Sentry observed the following issues:

The PR is not deployed, so that's not possible.

oguzkocer added a commit that referenced this pull request Aug 14, 2025
oguzkocer added a commit that referenced this pull request Aug 14, 2025
oguzkocer added a commit that referenced this pull request Aug 15, 2025
oguzkocer added a commit that referenced this pull request Aug 15, 2025
* Revert "Implement GutenbergKit ViewModel Architecture (#22087)" (#22127)

This reverts commit 890d484.

* Fix `GutenbergKit` editor issues during dark mode toggle (#22135)

* Remove isEditorStarted flag to fix content loss during activity restart

The isEditorStarted flag was preventing editor reinitialization during
activity restarts, but this caused content loss because:

1. Activity restart triggers new fragment creation
2. isEditorStarted gets reset to false in onDestroy()
3. startWithEditorSettings() gets called but always rebuilds from original data
4. Current editor content is lost instead of being preserved

Root cause: The flag was designed to prevent duplicate initialization within
a single fragment instance, but during activity restarts, we WANT the editor
to reinitialize with the current content, not block reinitialization entirely.

Changes:
- Remove isEditorStarted field and related state management
- Remove isEditorStarted checks in startWithEditorSettings()
- Allow editor to reinitialize after activity restart
- Fixes content loss during dark mode toggle

* Fix double ViewPager setup during auth state changes

Prevent duplicate editor initialization by:
1. Only calling fetchWpComCookies() if not already in Success state
2. Adding ViewPager state check to prevent duplicate setup
3. Using distinctUntilChanged() to prevent duplicate LiveData emissions
4. Consolidating Success handling logic in handleSuccessfulAuth()

Changes:
- Check auth state before calling fetchWpComCookies()
- Add ViewPager adapter check with error logging for duplicate setup attempts
- Add distinctUntilChanged() to auth state observer
- Extract handleSuccessfulAuth() for consistent Success state handling
- Remove debug logging from production code

* Update translations

* Update translations

* Bump version number

* Update WordPress metadata translations for 26.1

* Update Jetpack metadata translations for 26.1

---------

Co-authored-by: Oguz Kocer <oguzkocer@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Gutenberg Editing and display of Gutenberg blocks. Posting/Editing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants