Skip to content

Commit 3d55ca2

Browse files
author
Artyom Vlasov
authored
Merge pull request #19747 from wordpress-mobile/fix/19157-TransactionTooLargeException
Replaces bundle usage in the editor with a local database
2 parents 30b131c + 4e38515 commit 3d55ca2

File tree

11 files changed

+360
-34
lines changed

11 files changed

+360
-34
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.wordpress.android.editor.savedinstance
2+
3+
import android.os.Parcelable
4+
import dagger.hilt.android.testing.HiltAndroidTest
5+
import org.junit.Assert.assertArrayEquals
6+
import org.junit.Assert.assertEquals
7+
import org.junit.Before
8+
import org.junit.Test
9+
10+
@HiltAndroidTest
11+
class ParcelableObjectTest {
12+
private lateinit var parcelable: Parcelable
13+
14+
@Before
15+
fun setUp() {
16+
parcelable = TestParcelable("testData")
17+
}
18+
19+
@Test
20+
fun testConstructorWithParcelable() {
21+
val parcelableObject = ParcelableObject(parcelable)
22+
val parcelData = parcelableObject.toBytes()
23+
val objectFromParcel = ParcelableObject(parcelData)
24+
assertArrayEquals(objectFromParcel.toBytes(), parcelData)
25+
}
26+
27+
@Test
28+
fun testConstructorWithByteArray() {
29+
val parcelableObject = ParcelableObject(parcelable)
30+
val data = parcelableObject.toBytes()
31+
val parcelableResult = ParcelableObject(data)
32+
assertArrayEquals(parcelableObject.toBytes(), parcelableResult.toBytes())
33+
}
34+
35+
@Test
36+
fun getParcelReturnsTheSameParcelObject() {
37+
val parcelableObject = ParcelableObject(parcelable)
38+
val initialParcel = parcelableObject.getParcel()
39+
val nextParcel = parcelableObject.getParcel()
40+
assertEquals(initialParcel, nextParcel)
41+
}
42+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package org.wordpress.android.editor.savedinstance
2+
3+
import android.content.Context
4+
import dagger.hilt.android.testing.HiltAndroidRule
5+
import dagger.hilt.android.testing.HiltAndroidTest
6+
import kotlinx.parcelize.parcelableCreator
7+
import org.junit.Assert.assertEquals
8+
import org.junit.Assert.assertFalse
9+
import org.junit.Assert.assertTrue
10+
import org.junit.Before
11+
import org.junit.Rule
12+
import org.junit.Test
13+
import javax.inject.Inject
14+
15+
@HiltAndroidTest
16+
class SavedInstanceDatabaseTest {
17+
@get:Rule
18+
val hiltRule = HiltAndroidRule(this)
19+
20+
@Inject
21+
lateinit var context: Context
22+
23+
private lateinit var db: SavedInstanceDatabase
24+
25+
@Before
26+
fun setUp() {
27+
hiltRule.inject()
28+
db = SavedInstanceDatabase.getDatabase(context)!!
29+
db.reset(db.writableDatabase)
30+
}
31+
32+
@Test
33+
fun testStoreAndRetrieve() {
34+
val parcelId = "testParcelId"
35+
val parcelData = TestParcelable("testData")
36+
db.addParcel(parcelId, parcelData)
37+
val result = db.getParcel(parcelId, parcelableCreator<TestParcelable>())
38+
assertEquals(parcelData, result)
39+
}
40+
41+
@Test
42+
fun testHasParcel() {
43+
val parcelId = "testParcelId"
44+
val parcelData = TestParcelable("testData")
45+
db.addParcel(parcelId, parcelData)
46+
val result = db.hasParcel(parcelId)
47+
assertTrue(result)
48+
}
49+
50+
@Test
51+
fun testHasNoParcel() {
52+
val parcelId1 = "testParcelId1"
53+
val parcelId2 = "testParcelId2"
54+
val parcelData = TestParcelable("testData")
55+
db.addParcel(parcelId1, parcelData)
56+
val result = db.hasParcel(parcelId2)
57+
assertFalse(result)
58+
}
59+
60+
@Test
61+
fun testNullParcel() {
62+
val parcelId = "testParcelId"
63+
db.addParcel(parcelId, null)
64+
val result = db.hasParcel(parcelId)
65+
assertFalse(result)
66+
}
67+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.wordpress.android.editor.savedinstance
2+
3+
import android.os.Parcelable
4+
import kotlinx.parcelize.Parcelize
5+
6+
@Parcelize
7+
data class TestParcelable(val data: String) : Parcelable

WordPress/src/main/java/org/wordpress/android/ui/history/HistoryDetailContainerFragment.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.wordpress.android.analytics.AnalyticsTracker.Stat;
3131
import org.wordpress.android.databinding.HistoryDetailContainerFragmentBinding;
3232
import org.wordpress.android.editor.EditorMediaUtils;
33+
import org.wordpress.android.editor.savedinstance.SavedInstanceDatabase;
3334
import org.wordpress.android.fluxc.model.revisions.RevisionModel;
3435
import org.wordpress.android.fluxc.store.PostStore;
3536
import org.wordpress.android.ui.history.HistoryListItem.Revision;
@@ -245,7 +246,10 @@ public void onPrepareOptionsMenu(@NonNull Menu menu) {
245246
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
246247
if (item.getItemId() == R.id.history_load) {
247248
Intent intent = new Intent();
248-
intent.putExtra(KEY_REVISION, mRevision);
249+
SavedInstanceDatabase db = SavedInstanceDatabase.Companion.getDatabase(WordPress.getContext());
250+
if (db != null) {
251+
db.addParcel(KEY_REVISION, mRevision);
252+
}
249253

250254
requireActivity().setResult(Activity.RESULT_OK, intent);
251255
requireActivity().finish();

WordPress/src/main/java/org/wordpress/android/ui/history/HistoryDetailFragment.kt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import android.view.LayoutInflater
55
import android.view.View
66
import android.view.ViewGroup
77
import androidx.fragment.app.Fragment
8+
import kotlinx.parcelize.parcelableCreator
89
import org.wordpress.android.R
10+
import org.wordpress.android.WordPress
11+
import org.wordpress.android.editor.savedinstance.SavedInstanceDatabase.Companion.getDatabase
912
import org.wordpress.android.ui.history.HistoryListItem.Revision
10-
import org.wordpress.android.util.extensions.getParcelableCompat
1113
import org.wordpress.android.widgets.DiffView
1214

1315
class HistoryDetailFragment : Fragment() {
@@ -16,10 +18,10 @@ class HistoryDetailFragment : Fragment() {
1618
override fun onCreate(savedInstanceState: Bundle?) {
1719
super.onCreate(savedInstanceState)
1820

19-
mRevision = if (savedInstanceState != null) {
20-
savedInstanceState.getParcelableCompat(KEY_REVISION)
21+
mRevision = if (getDatabase(WordPress.getContext())?.hasParcel(KEY_REVISION) == true) {
22+
getDatabase(WordPress.getContext())?.getParcel(KEY_REVISION, parcelableCreator<Revision>())
2123
} else {
22-
arguments?.getParcelableCompat(EXTRA_REVISION)
24+
getDatabase(WordPress.getContext())?.getParcel(EXTRA_REVISION, parcelableCreator<Revision>())
2325
}
2426
}
2527

@@ -32,19 +34,16 @@ class HistoryDetailFragment : Fragment() {
3234

3335
override fun onSaveInstanceState(outState: Bundle) {
3436
super.onSaveInstanceState(outState)
35-
outState.putParcelable(KEY_REVISION, mRevision)
37+
getDatabase(WordPress.getContext())?.addParcel(KEY_REVISION, mRevision)
3638
}
3739

3840
companion object {
3941
const val EXTRA_REVISION = "EXTRA_REVISION"
4042
const val KEY_REVISION = "KEY_REVISION"
4143

4244
fun newInstance(revision: Revision): HistoryDetailFragment {
43-
val fragment = HistoryDetailFragment()
44-
val bundle = Bundle()
45-
bundle.putParcelable(EXTRA_REVISION, revision)
46-
fragment.arguments = bundle
47-
return fragment
45+
getDatabase(WordPress.getContext())?.addParcel(EXTRA_REVISION, revision)
46+
return HistoryDetailFragment()
4847
}
4948
}
5049
}

WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import org.wordpress.android.editor.EditorMediaUtils;
7272
import org.wordpress.android.editor.EditorThemeUpdateListener;
7373
import org.wordpress.android.editor.ExceptionLogger;
74+
import org.wordpress.android.editor.savedinstance.SavedInstanceDatabase;
7475
import org.wordpress.android.editor.gutenberg.DialogVisibility;
7576
import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment;
7677
import org.wordpress.android.editor.gutenberg.GutenbergPropsBuilder;
@@ -710,7 +711,11 @@ public void handleOnBackPressed() {
710711
mIsNewPost = savedInstanceState.getBoolean(STATE_KEY_IS_NEW_POST, false);
711712
updatePostLoadingAndDialogState(PostLoadingState.fromInt(
712713
savedInstanceState.getInt(STATE_KEY_POST_LOADING_STATE, 0)));
713-
mRevision = savedInstanceState.getParcelable(STATE_KEY_REVISION);
714+
715+
if (getDB() != null) {
716+
mRevision = getDB().getParcel(STATE_KEY_REVISION, Revision.CREATOR);
717+
}
718+
714719
mPostEditorAnalyticsSession = PostEditorAnalyticsSession
715720
.fromBundle(savedInstanceState, STATE_KEY_EDITOR_SESSION_DATA, mAnalyticsTrackerWrapper);
716721

@@ -1166,7 +1171,10 @@ protected void onSaveInstanceState(Bundle outState) {
11661171
outState.putBoolean(STATE_KEY_UNDO, mMenuHasUndo);
11671172
outState.putBoolean(STATE_KEY_REDO, mMenuHasRedo);
11681173
outState.putSerializable(WordPress.SITE, mSite);
1169-
outState.putParcelable(STATE_KEY_REVISION, mRevision);
1174+
1175+
if (getDB() != null) {
1176+
getDB().addParcel(STATE_KEY_REVISION, mRevision);
1177+
}
11701178

11711179
outState.putSerializable(STATE_KEY_EDITOR_SESSION_DATA, mPostEditorAnalyticsSession);
11721180
mIsConfigChange = true; // don't call sessionData.end() in onDestroy() if this is an Android config change
@@ -2373,8 +2381,7 @@ public Fragment getItem(int position) {
23732381
mIsJetpackSsoEnabled);
23742382

23752383
return GutenbergEditorFragment.newInstance(
2376-
"",
2377-
"",
2384+
WordPress.getContext(),
23782385
mIsNewPost,
23792386
gutenbergWebViewAuthorizationData,
23802387
gutenbergPropsBuilder,
@@ -2877,10 +2884,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
28772884
}
28782885
break;
28792886
case RequestCodes.HISTORY_DETAIL:
2880-
if (data.hasExtra(KEY_REVISION)) {
2887+
if (getDB() != null && getDB().hasParcel(KEY_REVISION)) {
28812888
mViewPager.setCurrentItem(PAGE_CONTENT);
28822889

2883-
mRevision = data.getParcelableExtra(KEY_REVISION);
2890+
mRevision = getDB().getParcel(KEY_REVISION, Revision.CREATOR);
28842891
new Handler().postDelayed(this::loadRevision,
28852892
getResources().getInteger(R.integer.full_screen_dialog_animation_duration));
28862893
}
@@ -3949,4 +3956,8 @@ public void showJetpackSettings() {
39493956
public LiveData<DialogVisibility> getSavingInProgressDialogVisibility() {
39503957
return mViewModel.getSavingInProgressDialogVisibility();
39513958
}
3959+
3960+
@Nullable private SavedInstanceDatabase getDB() {
3961+
return SavedInstanceDatabase.Companion.getDatabase(WordPress.getContext());
3962+
}
39523963
}

libs/editor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.wordpress.android.editor.gutenberg;
22

33
import android.app.Activity;
4+
import android.content.Context;
45
import android.os.Bundle;
56
import android.view.ViewGroup;
67

@@ -14,6 +15,7 @@
1415
import org.wordpress.android.editor.BuildConfig;
1516
import org.wordpress.android.editor.ExceptionLogger;
1617
import org.wordpress.android.editor.R;
18+
import org.wordpress.android.editor.savedinstance.SavedInstanceDatabase;
1719
import org.wordpress.mobile.WPAndroidGlue.ShowSuggestionsUtil;
1820
import org.wordpress.mobile.WPAndroidGlue.GutenbergProps;
1921
import org.wordpress.mobile.WPAndroidGlue.RequestExecutor;
@@ -53,11 +55,12 @@ public class GutenbergContainerFragment extends Fragment {
5355
private boolean mHasReceivedAnyContent;
5456

5557
private WPAndroidGlueCode mWPAndroidGlueCode;
56-
public static GutenbergContainerFragment newInstance(GutenbergPropsBuilder gutenbergPropsBuilder) {
58+
public static GutenbergContainerFragment newInstance(Context context, GutenbergPropsBuilder gutenbergPropsBuilder) {
5759
GutenbergContainerFragment fragment = new GutenbergContainerFragment();
58-
Bundle args = new Bundle();
59-
args.putParcelable(ARG_GUTENBERG_PROPS_BUILDER, gutenbergPropsBuilder);
60-
fragment.setArguments(args);
60+
SavedInstanceDatabase db = SavedInstanceDatabase.Companion.getDatabase(context);
61+
if (db != null) {
62+
db.addParcel(ARG_GUTENBERG_PROPS_BUILDER, gutenbergPropsBuilder);
63+
}
6164
return fragment;
6265
}
6366

@@ -124,7 +127,11 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener
124127
public void onCreate(@Nullable Bundle savedInstanceState) {
125128
super.onCreate(savedInstanceState);
126129

127-
GutenbergPropsBuilder gutenbergPropsBuilder = getArguments().getParcelable(ARG_GUTENBERG_PROPS_BUILDER);
130+
GutenbergPropsBuilder gutenbergPropsBuilder = null;
131+
SavedInstanceDatabase db = SavedInstanceDatabase.Companion.getDatabase(getContext());
132+
if (db != null) {
133+
gutenbergPropsBuilder = db.getParcel(ARG_GUTENBERG_PROPS_BUILDER, GutenbergPropsBuilder.CREATOR);
134+
}
128135

129136
Consumer<Exception> exceptionLogger = null;
130137
Consumer<String> breadcrumbLogger = null;

libs/editor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.wordpress.android.editor.EditorThemeUpdateListener;
4848
import org.wordpress.android.editor.LiveTextWatcher;
4949
import org.wordpress.android.editor.R;
50+
import org.wordpress.android.editor.savedinstance.SavedInstanceDatabase;
5051
import org.wordpress.android.editor.WPGutenbergWebViewActivity;
5152
import org.wordpress.android.editor.gutenberg.GutenbergDialogFragment.GutenbergDialogNegativeClickInterface;
5253
import org.wordpress.android.editor.gutenberg.GutenbergDialogFragment.GutenbergDialogPositiveClickInterface;
@@ -161,23 +162,23 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements
161162

162163
private ProgressDialog mSavingContentProgressDialog;
163164

164-
public static GutenbergEditorFragment newInstance(String title,
165-
String content,
165+
public static GutenbergEditorFragment newInstance(Context context,
166166
boolean isNewPost,
167167
GutenbergWebViewAuthorizationData webViewAuthorizationData,
168168
GutenbergPropsBuilder gutenbergPropsBuilder,
169169
int storyBlockEditRequestCode,
170170
boolean jetpackFeaturesEnabled) {
171171
GutenbergEditorFragment fragment = new GutenbergEditorFragment();
172172
Bundle args = new Bundle();
173-
args.putString(ARG_PARAM_TITLE, title);
174-
args.putString(ARG_PARAM_CONTENT, content);
175173
args.putBoolean(ARG_IS_NEW_POST, isNewPost);
176-
args.putParcelable(ARG_GUTENBERG_WEB_VIEW_AUTH_DATA, webViewAuthorizationData);
177-
args.putParcelable(ARG_GUTENBERG_PROPS_BUILDER, gutenbergPropsBuilder);
178174
args.putInt(ARG_STORY_EDITOR_REQUEST_CODE, storyBlockEditRequestCode);
179175
args.putBoolean(ARG_JETPACK_FEATURES_ENABLED, jetpackFeaturesEnabled);
180176
fragment.setArguments(args);
177+
SavedInstanceDatabase db = SavedInstanceDatabase.Companion.getDatabase(context);
178+
if (db != null) {
179+
db.addParcel(ARG_GUTENBERG_WEB_VIEW_AUTH_DATA, webViewAuthorizationData);
180+
db.addParcel(ARG_GUTENBERG_PROPS_BUILDER, gutenbergPropsBuilder);
181+
}
181182
return fragment;
182183
}
183184

@@ -199,12 +200,17 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
199200
super.onCreate(savedInstanceState);
200201

201202
if (getGutenbergContainerFragment() == null) {
202-
GutenbergPropsBuilder gutenbergPropsBuilder = getArguments().getParcelable(ARG_GUTENBERG_PROPS_BUILDER);
203+
GutenbergPropsBuilder gutenbergPropsBuilder = null;
204+
SavedInstanceDatabase db = SavedInstanceDatabase.Companion.getDatabase(getContext());
205+
if (db != null) {
206+
gutenbergPropsBuilder = db.getParcel(ARG_GUTENBERG_PROPS_BUILDER, GutenbergPropsBuilder.CREATOR);
207+
}
203208
mCurrentGutenbergPropsBuilder = gutenbergPropsBuilder;
204209

205210
FragmentManager fragmentManager = getChildFragmentManager();
206211
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
207-
GutenbergContainerFragment fragment = GutenbergContainerFragment.newInstance(gutenbergPropsBuilder);
212+
GutenbergContainerFragment fragment =
213+
GutenbergContainerFragment.newInstance(requireContext(), gutenbergPropsBuilder);
208214
fragment.setRetainInstance(true);
209215
fragmentTransaction.add(fragment, GutenbergContainerFragment.TAG);
210216
fragmentTransaction.commitNow();
@@ -645,9 +651,16 @@ private void initializeSavingProgressDialog() {
645651
}
646652
}
647653

654+
private GutenbergWebViewAuthorizationData getGutenbergWebViewAuthorizationData() {
655+
SavedInstanceDatabase db = SavedInstanceDatabase.Companion.getDatabase(getContext());
656+
if (db != null) {
657+
return db.getParcel(ARG_GUTENBERG_WEB_VIEW_AUTH_DATA, GutenbergWebViewAuthorizationData.CREATOR);
658+
}
659+
return null;
660+
}
661+
648662
private void openGutenbergWebViewActivity(String content, String blockId, String blockName, String blockTitle) {
649-
GutenbergWebViewAuthorizationData gutenbergWebViewAuthData =
650-
getArguments().getParcelable(ARG_GUTENBERG_WEB_VIEW_AUTH_DATA);
663+
GutenbergWebViewAuthorizationData gutenbergWebViewAuthData = getGutenbergWebViewAuthorizationData();
651664

652665
// There is a chance that isJetpackSsoEnabled has changed on the server
653666
// so we need to make sure that we have fresh value of it.
@@ -727,8 +740,8 @@ private ArrayList<MediaOption> initOtherMediaImageOptions() {
727740
}
728741

729742
boolean jetpackFeaturesEnabled = arguments.getBoolean(ARG_JETPACK_FEATURES_ENABLED);
730-
GutenbergWebViewAuthorizationData gutenbergWebViewAuthorizationData =
731-
arguments.getParcelable(ARG_GUTENBERG_WEB_VIEW_AUTH_DATA);
743+
GutenbergWebViewAuthorizationData gutenbergWebViewAuthorizationData = getGutenbergWebViewAuthorizationData();
744+
732745
boolean supportStockPhotos = gutenbergWebViewAuthorizationData.isSiteUsingWPComRestAPI()
733746
&& jetpackFeaturesEnabled;
734747
boolean supportsTenor = jetpackFeaturesEnabled;

0 commit comments

Comments
 (0)