From 7f4912ae2c3efce336546fc2ef3dd8bc12cf492c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 10 Sep 2020 14:32:49 -0300 Subject: [PATCH 001/230] added WPANdroid bridge interface OnStoryCreatorRequestListener --- .../wordpress/android/ui/posts/EditPostActivity.java | 11 +++++++++++ .../android/editor/EditorFragmentAbstract.java | 1 + .../editor/gutenberg/GutenbergContainerFragment.java | 3 +++ .../editor/gutenberg/GutenbergEditorFragment.java | 6 ++++++ libs/gutenberg-mobile | 2 +- 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 48b48466de6c..b2a0c76c4b74 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -110,6 +110,7 @@ import org.wordpress.android.ui.ActivityId; import org.wordpress.android.ui.ActivityLauncher; import org.wordpress.android.ui.LocaleAwareActivity; +import org.wordpress.android.ui.PagePostCreationSourcesDetail; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog.PrivateAtCookieProgressDialogOnDismissListener; import org.wordpress.android.ui.RequestCodes; @@ -2952,6 +2953,16 @@ public void onTrackableEvent(TrackableEvent event, Map propertie mEditorTracker.trackEditorEvent(event, mEditorFragment.getEditorName(), properties); } + @Override public void onStoryComposerLoaderRequested(int postId) { + // TODO here trigger the StoryCreator in the listener, figure out which media ids the + // story block contains, etc. + + // ActivityLauncher.addNewStoryWithMediaIdsForResult + // TODO we'll create a new ActivityLauncher method that passes the actual block content for the Story, + // after having found it and deserialized from local repository + ActivityLauncher.addNewStoryForResult(this, getSite(), PagePostCreationSourcesDetail.NO_DETAIL); + } + // FluxC events @SuppressWarnings("unused") diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java index 84ddb0b4dc7a..fd8403e95d40 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java @@ -206,6 +206,7 @@ public interface EditorFragmentListener { void onGutenbergEditorSetStarterPageTemplatesTooltipShown(boolean tooltipShown); boolean onGutenbergEditorRequestStarterPageTemplatesTooltipShown(); String getErrorMessageFromMedia(int mediaId); + void onStoryComposerLoaderRequested(int postId); } /** diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 97483ba500fd..33fdf0efa525 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -25,6 +25,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaEditorListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorRequestListener; import java.util.ArrayList; @@ -62,6 +63,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidRequestUnsupportedBlockFallbackListener, AddMentionUtil addMentionUtil, OnStarterPageTemplatesTooltipShownEventListener onSPTTooltipShownEventListener, + OnStoryCreatorRequestListener onStoryCreatorRequestListener, boolean isDarkMode) { mWPAndroidGlueCode.attachToContainer( viewGroup, @@ -77,6 +79,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidRequestUnsupportedBlockFallbackListener, addMentionUtil, onSPTTooltipShownEventListener, + onStoryCreatorRequestListener, isDarkMode); } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 9d75659dead9..10e38c6c87e9 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -62,6 +62,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorRequestListener; import java.util.ArrayList; import java.util.HashMap; @@ -337,6 +338,11 @@ public boolean onRequestStarterPageTemplatesTooltipShown() { return mEditorFragmentListener.onGutenbergEditorRequestStarterPageTemplatesTooltipShown(); } }, + new OnStoryCreatorRequestListener() { + @Override public void onRequestStoryCreatorLoad(int postId) { + mEditorFragmentListener.onStoryComposerLoaderRequested(postId); + } + }, GutenbergUtils.isDarkMode(getActivity())); // request dependency injection. Do this after setting min/max dimensions diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index e4825b2569e2..60088f818f04 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit e4825b2569e25b962f2527596580814a6c05ee59 +Subproject commit 60088f818f04a6a3eefca661da5220e7e2d0dbe0 From 0735ef64e1e51b6fa8834d2ae94f27cbfb435a50 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 11 Sep 2020 17:43:48 -0300 Subject: [PATCH 002/230] adapted the gutenberg bridge usage to receive Story block's mediaFiles and clientId from Gutenberg when block editing is requested --- .../android/ui/ActivityLauncher.java | 15 ++++++++++++++ .../wordpress/android/ui/RequestCodes.java | 1 + .../android/ui/posts/EditPostActivity.java | 13 +++++++++--- .../editor/EditorFragmentAbstract.java | 2 +- .../gutenberg/GutenbergContainerFragment.java | 8 ++++++-- .../gutenberg/GutenbergEditorFragment.java | 20 ++++++++++++++----- libs/gutenberg-mobile | 2 +- 7 files changed, 49 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index aabd6ed392c1..c24181cf873d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -724,6 +724,21 @@ public static void addNewStoryWithMediaUrisForResult( activity.startActivityForResult(intent, RequestCodes.CREATE_STORY); } + public static void editStoryWithMediaIdsForResult( + Activity activity, + SiteModel site, + long[] mediaIds + ) { + if (site == null) { + return; + } + + Intent intent = new Intent(activity, StoryComposerActivity.class); + intent.putExtra(WordPress.SITE, site); + intent.putExtra(MediaBrowserActivity.RESULT_IDS, mediaIds); + activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); + } + public static void editPostOrPageForResult(Activity activity, SiteModel site, PostModel post) { editPostOrPageForResult(new Intent(activity, EditPostActivity.class), activity, site, post.getId(), false); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java b/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java index f41c0a7350a4..e7b9add340e8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java @@ -63,4 +63,5 @@ public class RequestCodes { // Story creator public static final int CREATE_STORY = 8000; + public static final int EDIT_STORY = 8001; } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index b2a0c76c4b74..b40bfeb75692 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -2070,7 +2070,8 @@ public Fragment getItem(int position) { isSiteUsingWpComRestApi, WordPress.getUserAgent(), mTenorFeatureConfig.isEnabled(), - gutenbergPropsBuilder + gutenbergPropsBuilder, + RequestCodes.EDIT_STORY ); } else { // If gutenberg editor is not selected, default to Aztec. @@ -2953,14 +2954,20 @@ public void onTrackableEvent(TrackableEvent event, Map propertie mEditorTracker.trackEditorEvent(event, mEditorFragment.getEditorName(), properties); } - @Override public void onStoryComposerLoaderRequested(int postId) { + @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { // TODO here trigger the StoryCreator in the listener, figure out which media ids the // story block contains, etc. // ActivityLauncher.addNewStoryWithMediaIdsForResult // TODO we'll create a new ActivityLauncher method that passes the actual block content for the Story, // after having found it and deserialized from local repository - ActivityLauncher.addNewStoryForResult(this, getSite(), PagePostCreationSourcesDetail.NO_DETAIL); + + ArrayList tmpMediaIds = new ArrayList<>(); + for (Object mediaFile : mediaFiles) { + long mediaId = new Double(((HashMap)mediaFile).get("id").toString()).longValue(); + tmpMediaIds.add(mediaId); + } + ActivityLauncher.editStoryWithMediaIdsForResult(this, getSite(), ListUtils.toLongArray(tmpMediaIds)); } // FluxC events diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java index fd8403e95d40..b023d94911ee 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java @@ -206,7 +206,7 @@ public interface EditorFragmentListener { void onGutenbergEditorSetStarterPageTemplatesTooltipShown(boolean tooltipShown); boolean onGutenbergEditorRequestStarterPageTemplatesTooltipShown(); String getErrorMessageFromMedia(int mediaId); - void onStoryComposerLoaderRequested(int postId); + void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId); } /** diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 33fdf0efa525..03f7d66228d9 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -25,7 +25,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaEditorListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; import java.util.ArrayList; @@ -63,7 +63,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidRequestUnsupportedBlockFallbackListener, AddMentionUtil addMentionUtil, OnStarterPageTemplatesTooltipShownEventListener onSPTTooltipShownEventListener, - OnStoryCreatorRequestListener onStoryCreatorRequestListener, + OnStoryCreatorLoadRequestListener onStoryCreatorRequestListener, boolean isDarkMode) { mWPAndroidGlueCode.attachToContainer( viewGroup, @@ -205,6 +205,10 @@ public void replaceUnsupportedBlock(String content, String blockId) { mWPAndroidGlueCode.replaceUnsupportedBlock(content, blockId); } + public void replaceStoryEditedBlock(String mediaFiles, String blockId) { + mWPAndroidGlueCode.replaceStoryEditedBlock(mediaFiles, blockId); + } + public void updateTheme(Bundle editorTheme) { mWPAndroidGlueCode.updateTheme(editorTheme); } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 10e38c6c87e9..1051bbc35ce5 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -62,7 +62,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; import java.util.ArrayList; import java.util.HashMap; @@ -91,6 +91,7 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements private static final String ARG_SITE_USER_AGENT = "param_user_agent"; private static final String ARG_TENOR_ENABLED = "param_tenor_enabled"; private static final String ARG_GUTENBERG_PROPS_BUILDER = "param_gutenberg_props_builder"; + private static final String ARG_STORY_EDITOR_REQUEST_CODE = "param_sory_editor_request_code"; private static final int CAPTURE_PHOTO_PERMISSION_REQUEST_CODE = 101; private static final int CAPTURE_VIDEO_PERMISSION_REQUEST_CODE = 102; @@ -108,6 +109,7 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements private Runnable mInvalidateOptionsRunnable; private LiveTextWatcher mTextWatcher = new LiveTextWatcher(); + private int mStoryBlockEditRequestCode; // pointer (to the Gutenberg container fragment) that outlives this fragment's Android lifecycle. The retained // fragment can be alive and accessible even before it gets attached to an activity. @@ -135,7 +137,8 @@ public static GutenbergEditorFragment newInstance(String title, boolean isSiteUsingWpComRestApi, String userAgent, boolean tenorEnabled, - GutenbergPropsBuilder gutenbergPropsBuilder) { + GutenbergPropsBuilder gutenbergPropsBuilder, + int storyBlockEditRequestCode) { GutenbergEditorFragment fragment = new GutenbergEditorFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM_TITLE, title); @@ -151,6 +154,7 @@ public static GutenbergEditorFragment newInstance(String title, args.putString(ARG_SITE_USER_AGENT, userAgent); args.putBoolean(ARG_TENOR_ENABLED, tenorEnabled); args.putParcelable(ARG_GUTENBERG_PROPS_BUILDER, gutenbergPropsBuilder); + args.putInt(ARG_STORY_EDITOR_REQUEST_CODE, storyBlockEditRequestCode); fragment.setArguments(args); return fragment; } @@ -197,6 +201,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa if (getArguments() != null) { mIsNewPost = getArguments().getBoolean(ARG_IS_NEW_POST); + mStoryBlockEditRequestCode = getArguments().getInt(ARG_STORY_EDITOR_REQUEST_CODE); } ViewGroup gutenbergContainer = view.findViewById(R.id.gutenberg_container); @@ -338,9 +343,9 @@ public boolean onRequestStarterPageTemplatesTooltipShown() { return mEditorFragmentListener.onGutenbergEditorRequestStarterPageTemplatesTooltipShown(); } }, - new OnStoryCreatorRequestListener() { - @Override public void onRequestStoryCreatorLoad(int postId) { - mEditorFragmentListener.onStoryComposerLoaderRequested(postId); + new OnStoryCreatorLoadRequestListener() { + @Override public void onRequestStoryCreatorLoad(ArrayList mediaFiles, String blockId) { + mEditorFragmentListener.onStoryComposerLoadRequested(mediaFiles, blockId); } }, GutenbergUtils.isDarkMode(getActivity())); @@ -425,6 +430,11 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d } else { trackWebViewClosed("dismiss"); } + } else if (requestCode == mStoryBlockEditRequestCode) { + // handle edited block content + String blockId = data.getStringExtra(WPGutenbergWebViewActivity.ARG_BLOCK_ID); + String content = data.getStringExtra(WPGutenbergWebViewActivity.ARG_BLOCK_CONTENT); + getGutenbergContainerFragment().replaceStoryEditedBlock(content, blockId); } } diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 60088f818f04..4def44feb730 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 60088f818f04a6a3eefca661da5220e7e2d0dbe0 +Subproject commit 4def44feb7302a36eda62f6a459e51d08449750c From ae9a0c3cf617d2da1ded3c2daf93e924654f7738 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 15 Sep 2020 08:25:51 -0300 Subject: [PATCH 003/230] introducing StoriesPrefs to save serialized Stories slides so these can be retrieved and edited later Gutenberg --- .../android/ui/posts/EditPostActivity.java | 16 +++- .../media/AddLocalMediaToPostUseCase.kt | 8 ++ .../posts/editor/media/EditorMediaListener.kt | 3 + .../stories/SaveStoryGutenbergBlockUseCase.kt | 25 +++++ .../ui/stories/StoryComposerActivity.kt | 5 + .../media/StoryMediaSaveUploadBridge.kt | 27 ++++++ .../android/ui/stories/prefs/StoriesPrefs.kt | 96 +++++++++++++++++++ libs/stories-android | 2 +- 8 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index b40bfeb75692..0fc0c12b7135 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -110,7 +110,6 @@ import org.wordpress.android.ui.ActivityId; import org.wordpress.android.ui.ActivityLauncher; import org.wordpress.android.ui.LocaleAwareActivity; -import org.wordpress.android.ui.PagePostCreationSourcesDetail; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog.PrivateAtCookieProgressDialogOnDismissListener; import org.wordpress.android.ui.RequestCodes; @@ -157,6 +156,7 @@ import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; +import org.wordpress.android.ui.stories.prefs.StoriesPrefs; import org.wordpress.android.ui.uploads.PostEvents; import org.wordpress.android.ui.uploads.UploadService; import org.wordpress.android.ui.uploads.UploadUtils; @@ -2963,10 +2963,17 @@ public void onTrackableEvent(TrackableEvent event, Map propertie // after having found it and deserialized from local repository ArrayList tmpMediaIds = new ArrayList<>(); + boolean allStorySlidesAreEditable = true; for (Object mediaFile : mediaFiles) { - long mediaId = new Double(((HashMap)mediaFile).get("id").toString()).longValue(); + long mediaId = new Double(((HashMap) mediaFile).get("id").toString()).longValue(); + if (allStorySlidesAreEditable + && !StoriesPrefs.isValidSlide(this, getImmutablePost().getLocalSiteId(), mediaId)) { + // flag this as soon as we find one media item not being really editable + allStorySlidesAreEditable = false; + } tmpMediaIds.add(mediaId); } + // TODO pass the allStorySlidesAreEditable boolean flag make sure to show the warning dialog ActivityLauncher.editStoryWithMediaIdsForResult(this, getSite(), ListUtils.toLongArray(tmpMediaIds)); } @@ -3196,6 +3203,11 @@ public void syncPostObjectWithUiAndSaveIt(@Nullable OnPostUpdatedFromUIListener WPMediaUtils.advertiseImageOptimization(this, listener::invoke); } + @Override + public void onMediaModelsCreatedFromOptimizedUris(@NotNull Map oldUriToMediaModels) { + // no op - we're not doing any special handling on MediaModels in EditPostActivity + } + @Override public Consumer getExceptionLogger() { return (Exception e) -> AppLog.e(T.EDITOR, e); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt index 06129dd43457..ccb97c3de05c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt @@ -67,6 +67,14 @@ class AddLocalMediaToPostUseCase @Inject constructor( optimizeMediaResult.optimizedMediaUris ) + // here we pass a map of "old" (before optimisation) Uris to the new MediaModels which contain + // both the mediaModel ids and the optimized media URLs. + // this way, the listener will be able to process from other models potining to the old URLs + // and make any needed updates + editorMediaListener.onMediaModelsCreatedFromOptimizedUris( + uriList.zip(createMediaModelsResult.mediaModels).toMap() + ) + // Add media to editor and optionally initiate upload addToEditorAndOptionallyUpload(createMediaModelsResult.mediaModels, editorMediaListener, doUploadAfterAdding) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/EditorMediaListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/EditorMediaListener.kt index bb8254f726d7..e9fadf48d011 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/EditorMediaListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/EditorMediaListener.kt @@ -1,5 +1,7 @@ package org.wordpress.android.ui.posts.editor.media +import android.net.Uri +import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel import org.wordpress.android.ui.posts.EditPostActivity.OnPostUpdatedFromUIListener import org.wordpress.android.util.helpers.MediaFile @@ -8,5 +10,6 @@ interface EditorMediaListener { fun appendMediaFiles(mediaFiles: Map) fun syncPostObjectWithUiAndSaveIt(listener: OnPostUpdatedFromUIListener? = null) fun advertiseImageOptimization(listener: () -> Unit) + fun onMediaModelsCreatedFromOptimizedUris(oldUriToMediaFiles: Map) fun getImmutablePost(): PostImmutableModel } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index beb2107a6659..64d8976bb0ef 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -1,8 +1,10 @@ package org.wordpress.android.ui.stories import com.google.gson.Gson +import org.wordpress.android.WordPress import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.ui.posts.EditPostRepository +import org.wordpress.android.ui.stories.prefs.StoriesPrefs import org.wordpress.android.util.StringUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -57,6 +59,29 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { id = mediaFile.mediaId.toInt() link = mediaFile.fileURL url = mediaFile.fileURL + + // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. + val localIdKey = mediaFile.id.toLong() + val remoteIdKey = mediaFile.mediaId.toLong() + val localSiteId = post.localSiteId.toLong() + StoriesPrefs.getSlide( + WordPress.getContext(), + localSiteId, + localIdKey + )?.let { + StoriesPrefs.saveSlide( + WordPress.getContext(), + localSiteId, + remoteIdKey, // use the new mediaId as key + it + ) + // now delete the old entry + StoriesPrefs.deleteSlide( + WordPress.getContext(), + localSiteId, + localIdKey + ) + } } post.setContent(createGBStoryBlockStringFromJson(requireNotNull(storyBlockData))) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 1feab1a932e4..c1881f931c31 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -26,6 +26,7 @@ import org.wordpress.android.WordPress import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.PREPUBLISHING_BOTTOM_SHEET_OPENED import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId +import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.PostStore @@ -343,6 +344,10 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), WPMediaUtils.advertiseImageOptimization(this) { listener.invoke() } } + override fun onMediaModelsCreatedFromOptimizedUris(oldUriToMediaFiles: Map) { + // no op - we're not doing any special handling while composing, only when saving in the UploadBridge + } + private fun updateAddingMediaToStoryComposerProgressDialogState(uiState: ProgressDialogUiState) { addingMediaToEditorProgressDialog = progressDialogHelper .updateProgressDialogState(this, addingMediaToEditorProgressDialog, uiState, uiHelpers) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 1b16d1c9dc9b..b3c65c86c1f7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.launch import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode.MAIN import org.wordpress.android.WordPress +import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.modules.UI_THREAD @@ -28,6 +29,7 @@ import org.wordpress.android.ui.posts.editor.media.EditorMediaListener import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase import org.wordpress.android.ui.stories.StoriesTrackerHelper import org.wordpress.android.ui.stories.StoryComposerActivity +import org.wordpress.android.ui.stories.prefs.StoriesPrefs import org.wordpress.android.ui.uploads.UploadServiceFacade import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.util.NetworkUtilsWrapper @@ -170,4 +172,29 @@ class StoryMediaSaveUploadBridge @Inject constructor( override fun advertiseImageOptimization(listener: () -> Unit) { // no op } + + override fun onMediaModelsCreatedFromOptimizedUris(oldUriToMediaFiles: Map) { + // in order to support Story editing capabilities, we save a serialized version of the Story slides + // after their composedFrameFiles have been processed. + + // here we change the ids on the actual StoryFrameItems, and also update the flattened / composed image + // urls with the new URLs which may have been replaced after image optimization + for (story in StoryRepository.getImmutableStories()) { + // find the MediaModel for a given Uri from composedFrameFile + for (frame in story.frames) { + // if the old URI in frame.composedFrameFile exists as a key in the passed map, then update that + // value with the new (probably optimized) URL and also keep track of the new id. + val mediaModel = oldUriToMediaFiles.get(Uri.fromFile(frame.composedFrameFile)) + mediaModel?.let { + StoriesPrefs.saveSlide( + appContext, + mediaModel.localSiteId.toLong(), + mediaModel.id.toLong(), // use the local id to save the original, will be replaced later + // with mediaModel.mediaId after uploading to the remote site + frame + ) + } + } + } + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt new file mode 100644 index 000000000000..ae0c94f55187 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -0,0 +1,96 @@ +package org.wordpress.android.ui.stories.prefs + +import android.content.Context +import android.net.Uri +import androidx.preference.PreferenceManager +import com.wordpress.stories.compose.story.StoryFrameItem +import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.FileBackgroundSource +import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.UriBackgroundSource +import com.wordpress.stories.compose.story.StorySerializerUtils + +object StoriesPrefs { + private const val KEY_PREFIX_STORIES_SLIDE_ID = "story_slide_id-" + + private fun buildSlideKey(siteId: Long, mediaId: Long): String { + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + mediaId.toString() + } + + private fun checkSlideIdExists(context: Context, siteId: Long, mediaId: Long): Boolean { + val slideIdKey = buildSlideKey(siteId, mediaId) + return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) + } + + private fun checkSlideOriginalBackgroundMediaExists(context: Context, siteId: Long, mediaId: Long): Boolean { + val storyFrameItem: StoryFrameItem? = getSlide(context, siteId, mediaId) + storyFrameItem?.let { frame -> + // now check the background media exists or is accessible on this device + frame.source.let { source -> + if (source is FileBackgroundSource) { + source.file?.let { + return it.exists() + } ?: return false + } else if (source is UriBackgroundSource) { + source.contentUri?.let { + return isUriAccessible(it, context) + } ?: return false + } + } + } + return false + } + + private fun isUriAccessible(uri: Uri, context: Context): Boolean { + if (uri.toString().startsWith("http")) { + // TODO: assume it'll be accessible - we'll figure out later + // potentially force external download using MediaUtils.downloadExternalMedia() here to ensure + return true + } + try { + val inputStream = context.contentResolver.openInputStream(uri) + if (inputStream != null) { + inputStream.close() + return true + } + } catch (e: java.lang.Exception) { + e.printStackTrace() + } + return false + } + + private fun saveSlide(context: Context, slideIdKey: String, storySlideJson: String) { + val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() + editor.putString(slideIdKey, storySlideJson) + editor.apply() + } + + @JvmStatic + fun isValidSlide(context: Context, siteId: Long, mediaId: Long): Boolean { + return checkSlideIdExists(context, siteId, mediaId) && + checkSlideOriginalBackgroundMediaExists(context, siteId, mediaId) + } + + private fun getSlideJson(context: Context, siteId: Long, mediaId: Long): String? { + val slideIdKey = buildSlideKey(siteId, mediaId) + return PreferenceManager.getDefaultSharedPreferences(context).getString(slideIdKey, null) + } + + fun getSlide(context: Context, siteId: Long, mediaId: Long): StoryFrameItem? { + val jsonSlide = getSlideJson(context, siteId, mediaId) + jsonSlide?.let { + return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) + } ?: return null + } + + fun saveSlide(context: Context, siteId: Long, mediaId: Long, storyFrameItem: StoryFrameItem) { + val slideIdKey = buildSlideKey(siteId, mediaId) +// storyFrameItem.id = slideIdKey + saveSlide(context, slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) + } + + fun deleteSlide(context: Context, siteId: Long, mediaId: Long) { + val slideIdKey = buildSlideKey(siteId, mediaId) + val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() + editor.remove(slideIdKey) + editor.apply() + } +} diff --git a/libs/stories-android b/libs/stories-android index 03a40da7be5a..c9ffa96cb84a 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 03a40da7be5ab7da8fce7c4895227c193e04b9b9 +Subproject commit c9ffa96cb84ae77b43f32ca87d77d2909d78f201 From 3298f038c0e6e6e0cf330db48b223bed244a8909 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 15 Sep 2020 15:56:22 -0300 Subject: [PATCH 004/230] added logic in onStoryComposerLoadRequested() to load a Story in the composer after tapping on a Story block for editing --- WordPress/src/main/AndroidManifest.xml | 1 + .../android/ui/ActivityLauncher.java | 26 ++++++++- .../android/ui/posts/EditPostActivity.java | 55 ++++++++++++++----- .../stories/SaveStoryGutenbergBlockUseCase.kt | 1 + .../ui/stories/StoryComposerActivity.kt | 11 +++- .../ui/stories/StoryComposerViewModel.kt | 8 ++- .../media/StoryMediaSaveUploadBridge.kt | 5 +- .../android/ui/stories/prefs/StoriesPrefs.kt | 8 ++- libs/stories-android | 2 +- 9 files changed, 93 insertions(+), 24 deletions(-) diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index 1e800e40ad02..c9eba1929991 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -227,6 +227,7 @@ android:name=".ui.stories.StoryComposerActivity" android:label="@string/app_name" android:screenOrientation="portrait" + android:launchMode="singleTop" android:theme="@style/WordPress.Stories.Immersive"> diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index 5e4a0ac6225f..725acb28a390 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -13,6 +13,8 @@ import androidx.core.app.TaskStackBuilder; import androidx.fragment.app.Fragment; +import com.wordpress.stories.compose.ComposeLoopFrameActivity; + import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.analytics.AnalyticsTracker; @@ -93,6 +95,7 @@ import java.util.List; import java.util.Map; +import static com.wordpress.stories.util.BundleUtilsKt.KEY_STORY_INDEX; import static org.wordpress.android.analytics.AnalyticsTracker.ACTIVITY_LOG_ACTIVITY_ID_KEY; import static org.wordpress.android.analytics.AnalyticsTracker.Stat.POST_LIST_ACCESS_ERROR; import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_ARTICLE_DETAIL_REBLOGGED; @@ -102,6 +105,7 @@ import static org.wordpress.android.login.LoginMode.WPCOM_LOGIN_ONLY; import static org.wordpress.android.ui.media.MediaBrowserActivity.ARG_BROWSER_TYPE; import static org.wordpress.android.ui.pages.PagesActivityKt.EXTRA_PAGE_REMOTE_ID_KEY; +import static org.wordpress.android.ui.stories.StoryComposerActivity.KEY_LAUNCHED_FROM_GUTENBERG; import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_ID_KEY; public class ActivityLauncher { @@ -723,7 +727,8 @@ public static void addNewStoryWithMediaUrisForResult( public static void editStoryWithMediaIdsForResult( Activity activity, SiteModel site, - long[] mediaIds + long[] mediaIds, + boolean launchingFromGutenberg ) { if (site == null) { return; @@ -735,6 +740,25 @@ public static void editStoryWithMediaIdsForResult( activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); } + public static void editStoryForResult( + Activity activity, + SiteModel site, + int storyIndex, + boolean allStorySlidesAreEditable, + boolean launchedFromGutenberg + ) { + if (site == null) { + return; + } + + // TODO pass the allStorySlidesAreEditable boolean flag make sure to show the warning dialog + Intent intent = new Intent(activity, StoryComposerActivity.class); + intent.putExtra(WordPress.SITE, site); + intent.putExtra(KEY_STORY_INDEX, storyIndex); + intent.putExtra(KEY_LAUNCHED_FROM_GUTENBERG, launchedFromGutenberg); + activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); + } + public static void editPostOrPageForResult(Activity activity, SiteModel site, PostModel post) { editPostOrPageForResult(new Intent(activity, EditPostActivity.class), activity, site, post.getId(), false); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index efbe227936a6..58aabbe17e88 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -40,6 +40,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; +import com.wordpress.stories.compose.story.StoryFrameItem; +import com.wordpress.stories.compose.story.StoryRepository; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -2999,26 +3001,53 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - // TODO here trigger the StoryCreator in the listener, figure out which media ids the - // story block contains, etc. - - // ActivityLauncher.addNewStoryWithMediaIdsForResult - // TODO we'll create a new ActivityLauncher method that passes the actual block content for the Story, - // after having found it and deserialized from local repository - - ArrayList tmpMediaIds = new ArrayList<>(); + ArrayList tmpMediaIdsLong = new ArrayList<>(); + ArrayList tmpMediaIdsString = new ArrayList<>(); boolean allStorySlidesAreEditable = true; for (Object mediaFile : mediaFiles) { - long mediaId = new Double(((HashMap) mediaFile).get("id").toString()).longValue(); + long mediaIdLong = new Double(((HashMap) mediaFile).get("id").toString()).longValue(); + String mediaIdString = String.valueOf(mediaIdLong); // convert back after stripping the decimals in original Double if (allStorySlidesAreEditable - && !StoriesPrefs.isValidSlide(this, getImmutablePost().getLocalSiteId(), mediaId)) { + && !StoriesPrefs.isValidSlide(this, mSite.getSiteId(), mediaIdLong)) { // flag this as soon as we find one media item not being really editable allStorySlidesAreEditable = false; } - tmpMediaIds.add(mediaId); + tmpMediaIdsLong.add(mediaIdLong); + tmpMediaIdsString.add(mediaIdString); + } + + // now look for a Story in the StoryRepository that has all these frames and, if not found, let's + // just build the Story object ourselves to keep these files arrangement + int storyIndex = StoryRepository.findStoryContainingStoryFrameItemsByIds(tmpMediaIdsString); + if (storyIndex == StoryRepository.DEFAULT_NONE_SELECTED) { + // the StoryRepository didn' have it but we have editable serialized slides so, + // create a new Story from scratch with these deserialized StoryFrameItems + StoryRepository.loadStory(storyIndex); + storyIndex = StoryRepository.currentStoryIndex; + for (String mediaId : tmpMediaIdsString) { + StoryFrameItem storyFrameItem = StoriesPrefs.getSlide(this, mSite.getSiteId(), Long.parseLong(mediaId)); + if (storyFrameItem != null) { + StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); + } else { + allStorySlidesAreEditable = false; + // create a new frame using the actual uploaded flattened media as a background + List mediaModelList = mMediaStore.getSiteMediaWithIds(mSite, tmpMediaIdsLong); + for (MediaModel mediaModel : mediaModelList) { + storyFrameItem = StoryFrameItem.Companion.getNewStoryFrameItemFromUri( + Uri.parse(mediaModel.getUrl()), + mediaModel.isVideo() + ); + storyFrameItem.setId(String.valueOf(mediaModel.getMediaId())); + StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); + } + } + // Story instance re-created! Load it + ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); + } + } else { + // Story found! Load it + ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); } - // TODO pass the allStorySlidesAreEditable boolean flag make sure to show the warning dialog - ActivityLauncher.editStoryWithMediaIdsForResult(this, getSite(), ListUtils.toLongArray(tmpMediaIds)); } // FluxC events diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 64d8976bb0ef..6ff3b070d04e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -69,6 +69,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { localSiteId, localIdKey )?.let { + it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID StoriesPrefs.saveSlide( WordPress.getContext(), localSiteId, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index a418eae79202..2201e797d251 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.stories +import android.app.Activity import android.app.PendingIntent import android.app.ProgressDialog import android.content.Intent @@ -26,6 +27,7 @@ import org.wordpress.android.R.id import org.wordpress.android.WordPress import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.PREPUBLISHING_BOTTOM_SHEET_OPENED +import org.wordpress.android.editor.EditorImageMetaData import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel @@ -101,6 +103,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), const val STATE_KEY_POST_LOCAL_ID = "state_key_post_model_local_id" const val STATE_KEY_EDITOR_SESSION_DATA = "stateKeyEditorSessionData" const val KEY_POST_LOCAL_ID = "key_post_model_local_id" + const val KEY_LAUNCHED_FROM_GUTENBERG = "key_launched_from_gutenberg" const val UNUSED_KEY = "unused_key" const val BASE_FRAME_MEDIA_ERROR_NOTIFICATION_ID: Int = 72300 } @@ -396,7 +399,13 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } override fun onStoryDiscarded() { - viewModel.onStoryDiscarded() + val launchedFromGutenberg = intent.getBooleanExtra(KEY_LAUNCHED_FROM_GUTENBERG, false) + viewModel.onStoryDiscarded(!launchedFromGutenberg) + + if (launchedFromGutenberg) { + setResult(Activity.RESULT_CANCELED) + finish() + } } private fun openPrepublishingBottomSheet() { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerViewModel.kt index eefab234efb8..0e79012021b3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerViewModel.kt @@ -112,9 +112,11 @@ class StoryComposerViewModel @Inject constructor( outState.putSerializable(StoryComposerActivity.STATE_KEY_EDITOR_SESSION_DATA, postEditorAnalyticsSession) } - fun onStoryDiscarded() { - // delete empty post from database - dispatcher.dispatch(PostActionBuilder.newRemovePostAction(editPostRepository.getEditablePost())) + fun onStoryDiscarded(deleteDiscardedPost: Boolean) { + if (deleteDiscardedPost) { + // delete empty post from database + dispatcher.dispatch(PostActionBuilder.newRemovePostAction(editPostRepository.getEditablePost())) + } postEditorAnalyticsSession.setOutcome(CANCEL) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index b3c65c86c1f7..a1829d2daf96 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -186,10 +186,11 @@ class StoryMediaSaveUploadBridge @Inject constructor( // value with the new (probably optimized) URL and also keep track of the new id. val mediaModel = oldUriToMediaFiles.get(Uri.fromFile(frame.composedFrameFile)) mediaModel?.let { + frame.id = it.id.toString() StoriesPrefs.saveSlide( appContext, - mediaModel.localSiteId.toLong(), - mediaModel.id.toLong(), // use the local id to save the original, will be replaced later + it.localSiteId.toLong(), + it.id.toLong(), // use the local id to save the original, will be replaced later // with mediaModel.mediaId after uploading to the remote site frame ) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index ae0c94f55187..fbd94db60fb2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -15,12 +15,14 @@ object StoriesPrefs { return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + mediaId.toString() } - private fun checkSlideIdExists(context: Context, siteId: Long, mediaId: Long): Boolean { + @JvmStatic + fun checkSlideIdExists(context: Context, siteId: Long, mediaId: Long): Boolean { val slideIdKey = buildSlideKey(siteId, mediaId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } - private fun checkSlideOriginalBackgroundMediaExists(context: Context, siteId: Long, mediaId: Long): Boolean { + @JvmStatic + fun checkSlideOriginalBackgroundMediaExists(context: Context, siteId: Long, mediaId: Long): Boolean { val storyFrameItem: StoryFrameItem? = getSlide(context, siteId, mediaId) storyFrameItem?.let { frame -> // now check the background media exists or is accessible on this device @@ -74,6 +76,7 @@ object StoriesPrefs { return PreferenceManager.getDefaultSharedPreferences(context).getString(slideIdKey, null) } + @JvmStatic fun getSlide(context: Context, siteId: Long, mediaId: Long): StoryFrameItem? { val jsonSlide = getSlideJson(context, siteId, mediaId) jsonSlide?.let { @@ -83,7 +86,6 @@ object StoriesPrefs { fun saveSlide(context: Context, siteId: Long, mediaId: Long, storyFrameItem: StoryFrameItem) { val slideIdKey = buildSlideKey(siteId, mediaId) -// storyFrameItem.id = slideIdKey saveSlide(context, slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) } diff --git a/libs/stories-android b/libs/stories-android index ae06c31785a2..22b8d57c9ae5 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit ae06c31785a2e124566a20c9c8639bc62552856f +Subproject commit 22b8d57c9ae5d48849f7f54f986dfa392e8c43a8 From d5ba9a3ad7b127700e2b2e81f5d72a4af3d08d76 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 15 Sep 2020 15:58:55 -0300 Subject: [PATCH 005/230] removed unused import --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 2201e797d251..4f827f055e92 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -27,7 +27,6 @@ import org.wordpress.android.R.id import org.wordpress.android.WordPress import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.PREPUBLISHING_BOTTOM_SHEET_OPENED -import org.wordpress.android.editor.EditorImageMetaData import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel From 556c7ccccd0bef6a529ae7a426679a131f7cf6fb Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 15 Sep 2020 23:46:02 -0300 Subject: [PATCH 006/230] fixed bug that had the Activity start as many times as slides where added --- WordPress/src/main/AndroidManifest.xml | 1 - .../org/wordpress/android/ui/posts/EditPostActivity.java | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index c9eba1929991..1e800e40ad02 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -227,7 +227,6 @@ android:name=".ui.stories.StoryComposerActivity" android:label="@string/app_name" android:screenOrientation="portrait" - android:launchMode="singleTop" android:theme="@style/WordPress.Stories.Immersive"> diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 58aabbe17e88..0c1917ffff87 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3041,13 +3041,10 @@ public void onTrackableEvent(TrackableEvent event, Map propertie StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); } } - // Story instance re-created! Load it - ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); } - } else { - // Story found! Load it - ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); } + // Story instance loaded or re-created! Load it + ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); } // FluxC events From 667a8dbeee64a34e79ec43b76fbdc6c7400b4165 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 08:32:45 -0300 Subject: [PATCH 007/230] removed unused import, removed comment --- .../main/java/org/wordpress/android/ui/ActivityLauncher.java | 2 -- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index 725acb28a390..df9c7833fae5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -13,8 +13,6 @@ import androidx.core.app.TaskStackBuilder; import androidx.fragment.app.Fragment; -import com.wordpress.stories.compose.ComposeLoopFrameActivity; - import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.analytics.AnalyticsTracker; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 0c1917ffff87..a21b95426895 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3006,7 +3006,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie boolean allStorySlidesAreEditable = true; for (Object mediaFile : mediaFiles) { long mediaIdLong = new Double(((HashMap) mediaFile).get("id").toString()).longValue(); - String mediaIdString = String.valueOf(mediaIdLong); // convert back after stripping the decimals in original Double + String mediaIdString = String.valueOf(mediaIdLong); if (allStorySlidesAreEditable && !StoriesPrefs.isValidSlide(this, mSite.getSiteId(), mediaIdLong)) { // flag this as soon as we find one media item not being really editable From 34f858e6cb6dcbe248cfc56400d1a7729f41ad5b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 09:00:55 -0300 Subject: [PATCH 008/230] fixed loading flattened slides for editing --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 7 ++++--- libs/stories-android | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index a21b95426895..c96cfe4dc250 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3001,7 +3001,6 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - ArrayList tmpMediaIdsLong = new ArrayList<>(); ArrayList tmpMediaIdsString = new ArrayList<>(); boolean allStorySlidesAreEditable = true; for (Object mediaFile : mediaFiles) { @@ -3012,7 +3011,6 @@ public void onTrackableEvent(TrackableEvent event, Map propertie // flag this as soon as we find one media item not being really editable allStorySlidesAreEditable = false; } - tmpMediaIdsLong.add(mediaIdLong); tmpMediaIdsString.add(mediaIdString); } @@ -3030,7 +3028,10 @@ public void onTrackableEvent(TrackableEvent event, Map propertie StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); } else { allStorySlidesAreEditable = false; - // create a new frame using the actual uploaded flattened media as a background + + // for this missing frame we'll create a new frame using the actual uploaded flattened media + ArrayList tmpMediaIdsLong = new ArrayList<>(); + tmpMediaIdsLong.add(Long.parseLong(mediaId)); List mediaModelList = mMediaStore.getSiteMediaWithIds(mSite, tmpMediaIdsLong); for (MediaModel mediaModel : mediaModelList) { storyFrameItem = StoryFrameItem.Companion.getNewStoryFrameItemFromUri( diff --git a/libs/stories-android b/libs/stories-android index 22b8d57c9ae5..821a8cd96c89 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 22b8d57c9ae5d48849f7f54f986dfa392e8c43a8 +Subproject commit 821a8cd96c8991533476ce5b6b11c720009d808f From e27fea5c6213bf8669b6b1c50b4fc8b7d2340adb Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 09:45:49 -0300 Subject: [PATCH 009/230] fixed and added new test for onStoryDiscarded --- .../ui/stories/StoryComposerViewModelTest.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/StoryComposerViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/StoryComposerViewModelTest.kt index 33127f3c799a..e10f3519b2cc 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/StoryComposerViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/StoryComposerViewModelTest.kt @@ -192,15 +192,25 @@ class StoryComposerViewModelTest : BaseUnitTest() { } @Test - fun `If onStoryDiscarded is called then the post is removed with the dispatcher`() { + fun `If onStoryDiscarded is called then the post is removed with the dispatcher when deleteDiscardedPost true `() { // act viewModel.start(site, editPostRepository, LocalId(0), mock(), mock()) - viewModel.onStoryDiscarded() + viewModel.onStoryDiscarded(deleteDiscardedPost = true) // assert verify(dispatcher, times(1)).dispatch(any>()) } + @Test + fun `If onStoryDiscarded is called then the post is not removed when deleteDiscardedPost false `() { + // act + viewModel.start(site, editPostRepository, LocalId(0), mock(), mock()) + viewModel.onStoryDiscarded(deleteDiscardedPost = false) + + // assert + verify(dispatcher, times(0)).dispatch(any>()) + } + @Test fun `verify that triggering onStorySaveButtonPressed will trigger the associated openPrepublishingBottomSheet`() { // act From a7be9d3a5553e7ef1f7c34ac4381baf348b60aa3 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 10:22:48 -0300 Subject: [PATCH 010/230] updated stories lib hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 821a8cd96c89..add3c28aaf69 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 821a8cd96c8991533476ce5b6b11c720009d808f +Subproject commit add3c28aaf69ebb401a8036eeae019923be00adc From 2bc41c93b6dd67629e90cdfbb23366ffae564129 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 10:53:17 -0300 Subject: [PATCH 011/230] using site localid for slide retrieval from StoriesPrefs --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index c96cfe4dc250..74fc61e9dd2a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3007,7 +3007,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie long mediaIdLong = new Double(((HashMap) mediaFile).get("id").toString()).longValue(); String mediaIdString = String.valueOf(mediaIdLong); if (allStorySlidesAreEditable - && !StoriesPrefs.isValidSlide(this, mSite.getSiteId(), mediaIdLong)) { + && !StoriesPrefs.isValidSlide(this, mSite.getId(), mediaIdLong)) { // flag this as soon as we find one media item not being really editable allStorySlidesAreEditable = false; } @@ -3023,7 +3023,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie StoryRepository.loadStory(storyIndex); storyIndex = StoryRepository.currentStoryIndex; for (String mediaId : tmpMediaIdsString) { - StoryFrameItem storyFrameItem = StoriesPrefs.getSlide(this, mSite.getSiteId(), Long.parseLong(mediaId)); + StoryFrameItem storyFrameItem = StoriesPrefs.getSlide(this, mSite.getId(), Long.parseLong(mediaId)); if (storyFrameItem != null) { StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); } else { From 9ad4a87d2039d2ee48b112697c1112a9e7f8fde9 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 11:10:21 -0300 Subject: [PATCH 012/230] updated stories lib commit hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index add3c28aaf69..56deb4537e1d 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit add3c28aaf69ebb401a8036eeae019923be00adc +Subproject commit 56deb4537e1dabc8551231fb5fc00b94e7df9131 From e755a7413e419ef461e5d8f0aa8e6057e2880b64 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 11:45:03 -0300 Subject: [PATCH 013/230] introducing LocalMediaId and RemoteMediaId data classes to enforce meaning, plus using a differentiated prefix when buildng keys to avoid the chance of local/remote overlapping ids --- .../android/ui/posts/EditPostActivity.java | 9 +++- .../stories/SaveStoryGutenbergBlockUseCase.kt | 14 ++--- .../media/StoryMediaSaveUploadBridge.kt | 6 ++- .../android/ui/stories/prefs/StoriesPrefs.kt | 52 ++++++++++++++----- 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 74fc61e9dd2a..aa8a9b8068ed 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -161,6 +161,7 @@ import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; import org.wordpress.android.ui.stories.prefs.StoriesPrefs; +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId; import org.wordpress.android.ui.uploads.PostEvents; import org.wordpress.android.ui.uploads.UploadService; import org.wordpress.android.ui.uploads.UploadUtils; @@ -3007,7 +3008,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie long mediaIdLong = new Double(((HashMap) mediaFile).get("id").toString()).longValue(); String mediaIdString = String.valueOf(mediaIdLong); if (allStorySlidesAreEditable - && !StoriesPrefs.isValidSlide(this, mSite.getId(), mediaIdLong)) { + && !StoriesPrefs.isValidSlide(this, mSite.getId(), new RemoteMediaId(mediaIdLong))) { // flag this as soon as we find one media item not being really editable allStorySlidesAreEditable = false; } @@ -3023,7 +3024,11 @@ public void onTrackableEvent(TrackableEvent event, Map propertie StoryRepository.loadStory(storyIndex); storyIndex = StoryRepository.currentStoryIndex; for (String mediaId : tmpMediaIdsString) { - StoryFrameItem storyFrameItem = StoriesPrefs.getSlide(this, mSite.getId(), Long.parseLong(mediaId)); + StoryFrameItem storyFrameItem = StoriesPrefs.getSlideWithRemoteId( + this, + mSite.getId(), + new RemoteMediaId(Long.parseLong(mediaId)) + ); if (storyFrameItem != null) { StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); } else { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 6ff3b070d04e..e9c22e279c03 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -5,6 +5,8 @@ import org.wordpress.android.WordPress import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.LocalMediaId +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId import org.wordpress.android.util.StringUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -64,23 +66,23 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { val localIdKey = mediaFile.id.toLong() val remoteIdKey = mediaFile.mediaId.toLong() val localSiteId = post.localSiteId.toLong() - StoriesPrefs.getSlide( + StoriesPrefs.getSlideWithLocalId( WordPress.getContext(), localSiteId, - localIdKey + LocalMediaId(localIdKey) )?.let { it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID - StoriesPrefs.saveSlide( + StoriesPrefs.saveSlideWithRemoteId( WordPress.getContext(), localSiteId, - remoteIdKey, // use the new mediaId as key + RemoteMediaId(remoteIdKey), // use the new mediaId as key it ) // now delete the old entry - StoriesPrefs.deleteSlide( + StoriesPrefs.deleteSlideWithLocalId( WordPress.getContext(), localSiteId, - localIdKey + LocalMediaId(localIdKey) ) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index a1829d2daf96..d45c809556d7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -30,6 +30,7 @@ import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase import org.wordpress.android.ui.stories.StoriesTrackerHelper import org.wordpress.android.ui.stories.StoryComposerActivity import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.LocalMediaId import org.wordpress.android.ui.uploads.UploadServiceFacade import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.util.NetworkUtilsWrapper @@ -187,11 +188,12 @@ class StoryMediaSaveUploadBridge @Inject constructor( val mediaModel = oldUriToMediaFiles.get(Uri.fromFile(frame.composedFrameFile)) mediaModel?.let { frame.id = it.id.toString() - StoriesPrefs.saveSlide( + StoriesPrefs.saveSlideWithLocalId( appContext, it.localSiteId.toLong(), - it.id.toLong(), // use the local id to save the original, will be replaced later + // use the local id to save the original, will be replaced later // with mediaModel.mediaId after uploading to the remote site + LocalMediaId(it.id.toLong()), frame ) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index fbd94db60fb2..4dc3a8b850b8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -10,20 +10,26 @@ import com.wordpress.stories.compose.story.StorySerializerUtils object StoriesPrefs { private const val KEY_PREFIX_STORIES_SLIDE_ID = "story_slide_id-" + private const val KEY_PREFIX_LOCAL_MEDIA_ID = "l-" + private const val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" - private fun buildSlideKey(siteId: Long, mediaId: Long): String { - return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + mediaId.toString() + private fun buildSlideKey(siteId: Long, mediaId: RemoteMediaId): String { + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.toString() + } + + private fun buildSlideKey(siteId: Long, mediaId: LocalMediaId): String { + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.toString() } @JvmStatic - fun checkSlideIdExists(context: Context, siteId: Long, mediaId: Long): Boolean { + fun checkSlideIdExists(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { val slideIdKey = buildSlideKey(siteId, mediaId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } @JvmStatic - fun checkSlideOriginalBackgroundMediaExists(context: Context, siteId: Long, mediaId: Long): Boolean { - val storyFrameItem: StoryFrameItem? = getSlide(context, siteId, mediaId) + fun checkSlideOriginalBackgroundMediaExists(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { + val storyFrameItem: StoryFrameItem? = getSlideWithRemoteId(context, siteId, mediaId) storyFrameItem?.let { frame -> // now check the background media exists or is accessible on this device frame.source.let { source -> @@ -66,33 +72,55 @@ object StoriesPrefs { } @JvmStatic - fun isValidSlide(context: Context, siteId: Long, mediaId: Long): Boolean { + fun isValidSlide(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { return checkSlideIdExists(context, siteId, mediaId) && checkSlideOriginalBackgroundMediaExists(context, siteId, mediaId) } - private fun getSlideJson(context: Context, siteId: Long, mediaId: Long): String? { - val slideIdKey = buildSlideKey(siteId, mediaId) + private fun getSlideJson(context: Context, slideIdKey: String): String? { return PreferenceManager.getDefaultSharedPreferences(context).getString(slideIdKey, null) } @JvmStatic - fun getSlide(context: Context, siteId: Long, mediaId: Long): StoryFrameItem? { - val jsonSlide = getSlideJson(context, siteId, mediaId) + fun getSlideWithRemoteId(context: Context, siteId: Long, mediaId: RemoteMediaId): StoryFrameItem? { + val jsonSlide = getSlideJson(context, buildSlideKey(siteId, mediaId)) + jsonSlide?.let { + return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) + } ?: return null + } + + @JvmStatic + fun getSlideWithLocalId(context: Context, siteId: Long, mediaId: LocalMediaId): StoryFrameItem? { + val jsonSlide = getSlideJson(context, buildSlideKey(siteId, mediaId)) jsonSlide?.let { return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) } ?: return null } - fun saveSlide(context: Context, siteId: Long, mediaId: Long, storyFrameItem: StoryFrameItem) { + fun saveSlideWithLocalId(context: Context, siteId: Long, mediaId: LocalMediaId, storyFrameItem: StoryFrameItem) { + val slideIdKey = buildSlideKey(siteId, mediaId) + saveSlide(context, slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) + } + + fun saveSlideWithRemoteId(context: Context, siteId: Long, mediaId: RemoteMediaId, storyFrameItem: StoryFrameItem) { val slideIdKey = buildSlideKey(siteId, mediaId) saveSlide(context, slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) } - fun deleteSlide(context: Context, siteId: Long, mediaId: Long) { + fun deleteSlideWithLocalId(context: Context, siteId: Long, mediaId: LocalMediaId) { + val slideIdKey = buildSlideKey(siteId, mediaId) + val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() + editor.remove(slideIdKey) + editor.apply() + } + + fun deleteSlideWithRemoteId(context: Context, siteId: Long, mediaId: RemoteMediaId) { val slideIdKey = buildSlideKey(siteId, mediaId) val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() editor.remove(slideIdKey) editor.apply() } + + data class RemoteMediaId(val mediaId: Long) + data class LocalMediaId(val id: Long) } From 9c032f6710f87d986cad2487490429f2a428680b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 13:05:24 -0300 Subject: [PATCH 014/230] using setUseTempCaptureFile on the stories library to keep captured media --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 1 + libs/stories-android | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 4f827f055e92..ca0da66f8e22 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -119,6 +119,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), setNotificationTrackerProvider((application as WordPress).getStoryNotificationTrackerProvider()) setPrepublishingEventProvider(this) setPermissionDialogProvider(this) + setUseTempCaptureFile(false) // we need to keep the captured files for later Story editing initViewModel(savedInstanceState) } diff --git a/libs/stories-android b/libs/stories-android index 56deb4537e1d..5b9460ac6a86 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 56deb4537e1dabc8551231fb5fc00b94e7df9131 +Subproject commit 5b9460ac6a86ab7c1f8f1f5b43a62d57d2aa994e From 0232b7c4111839daec1ac0b8ab20c333c6530f88 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 14:18:52 -0300 Subject: [PATCH 015/230] converting intent extra KEY_LAUNCHED_FROM_GUTENBERG to stories KEY_STORY_EDIT_MODE so we can show discard dialog messaging properly --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 3 +++ libs/stories-android | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index ca0da66f8e22..697367f752ad 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -21,6 +21,7 @@ import com.wordpress.stories.compose.SnackbarProvider import com.wordpress.stories.compose.StoryDiscardListener import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult import com.wordpress.stories.compose.story.StoryIndex +import com.wordpress.stories.util.KEY_STORY_EDIT_MODE import com.wordpress.stories.util.KEY_STORY_INDEX import com.wordpress.stories.util.KEY_STORY_SAVE_RESULT import org.wordpress.android.R.id @@ -108,6 +109,8 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } override fun onCreate(savedInstanceState: Bundle?) { + // convert our WPAndroid KEY_LAUNCHED_FROM_GUTENBERG flag into Stories general purpose EDIT_MODE flag + intent.putExtra(KEY_STORY_EDIT_MODE, intent.getBooleanExtra(KEY_LAUNCHED_FROM_GUTENBERG, false)) super.onCreate(savedInstanceState) (application as WordPress).component().inject(this) setSnackbarProvider(this) diff --git a/libs/stories-android b/libs/stories-android index 5b9460ac6a86..78b87d4cd5cc 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 5b9460ac6a86ab7c1f8f1f5b43a62d57d2aa994e +Subproject commit 78b87d4cd5cc1dab9a3eb22ab902b66143f4b08d From a35d6c236eec486265ea54187f10dd4fe62b377b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 15:31:07 -0300 Subject: [PATCH 016/230] implemented the GenericAnnouncementDialogProvider interface and showing the limited editing dialog when a Story slide to be eidted hasnt been found in StoriesPrefs --- .../android/ui/ActivityLauncher.java | 3 ++- .../ui/stories/StoryComposerActivity.kt | 24 ++++++++++++++++--- WordPress/src/main/res/values/strings.xml | 3 +++ libs/stories-android | 2 +- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index df9c7833fae5..28d25cf97060 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -103,6 +103,7 @@ import static org.wordpress.android.login.LoginMode.WPCOM_LOGIN_ONLY; import static org.wordpress.android.ui.media.MediaBrowserActivity.ARG_BROWSER_TYPE; import static org.wordpress.android.ui.pages.PagesActivityKt.EXTRA_PAGE_REMOTE_ID_KEY; +import static org.wordpress.android.ui.stories.StoryComposerActivity.KEY_ALL_UNFLATTENED_LOADED_SLIDES; import static org.wordpress.android.ui.stories.StoryComposerActivity.KEY_LAUNCHED_FROM_GUTENBERG; import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_ID_KEY; @@ -749,11 +750,11 @@ public static void editStoryForResult( return; } - // TODO pass the allStorySlidesAreEditable boolean flag make sure to show the warning dialog Intent intent = new Intent(activity, StoryComposerActivity.class); intent.putExtra(WordPress.SITE, site); intent.putExtra(KEY_STORY_INDEX, storyIndex); intent.putExtra(KEY_LAUNCHED_FROM_GUTENBERG, launchedFromGutenberg); + intent.putExtra(KEY_ALL_UNFLATTENED_LOADED_SLIDES, allStorySlidesAreEditable); activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 697367f752ad..ff44aa5e536a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -12,6 +12,8 @@ import androidx.lifecycle.ViewModelProviders import com.google.android.material.snackbar.Snackbar import com.wordpress.stories.compose.AuthenticationHeadersProvider import com.wordpress.stories.compose.ComposeLoopFrameActivity +import com.wordpress.stories.compose.FrameSaveErrorDialog +import com.wordpress.stories.compose.GenericAnnouncementDialogProvider import com.wordpress.stories.compose.MediaPickerProvider import com.wordpress.stories.compose.MetadataProvider import com.wordpress.stories.compose.NotificationIntentLoader @@ -24,7 +26,7 @@ import com.wordpress.stories.compose.story.StoryIndex import com.wordpress.stories.util.KEY_STORY_EDIT_MODE import com.wordpress.stories.util.KEY_STORY_INDEX import com.wordpress.stories.util.KEY_STORY_SAVE_RESULT -import org.wordpress.android.R.id +import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.PREPUBLISHING_BOTTOM_SHEET_OPENED @@ -79,7 +81,8 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), EditPostActivityHook, PrepublishingEventProvider, PrepublishingBottomSheetListener, - PermanentPermissionDenialDialogProvider { + PermanentPermissionDenialDialogProvider, + GenericAnnouncementDialogProvider { private var site: SiteModel? = null @Inject lateinit var storyEditorMedia: StoryEditorMedia @@ -100,10 +103,12 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), override fun getEditPostRepository() = editPostRepository companion object { + protected const val FRAGMENT_ANNOUNCEMENT_DIALOG = "story_announcement_dialog" const val STATE_KEY_POST_LOCAL_ID = "state_key_post_model_local_id" const val STATE_KEY_EDITOR_SESSION_DATA = "stateKeyEditorSessionData" const val KEY_POST_LOCAL_ID = "key_post_model_local_id" const val KEY_LAUNCHED_FROM_GUTENBERG = "key_launched_from_gutenberg" + const val KEY_ALL_UNFLATTENED_LOADED_SLIDES = "key_all_unflattened_laoded_slides" const val UNUSED_KEY = "unused_key" const val BASE_FRAME_MEDIA_ERROR_NOTIFICATION_ID: Int = 72300 } @@ -122,6 +127,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), setNotificationTrackerProvider((application as WordPress).getStoryNotificationTrackerProvider()) setPrepublishingEventProvider(this) setPermissionDialogProvider(this) + setGenericAnnouncementDialogProvider(this) setUseTempCaptureFile(false) // we need to keep the captured files for later Story editing initViewModel(savedInstanceState) @@ -324,7 +330,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), if (messageHolder != null) { WPSnackbar .make( - findViewById(id.editor_activity), + findViewById(org.wordpress.android.R.id.editor_activity), uiHelpers.getTextOfUiString(this, messageHolder.message), Snackbar.LENGTH_SHORT ) @@ -434,4 +440,16 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), override fun showPermissionPermanentlyDeniedDialog(permission: String) { WPPermissionUtils.showPermissionAlwaysDeniedDialog(this, permission) } + + override fun showGenericAnnouncementDialog() { + if (intent.getBooleanExtra(KEY_LAUNCHED_FROM_GUTENBERG, false)) { + if (!intent.getBooleanExtra(KEY_ALL_UNFLATTENED_LOADED_SLIDES, false)) { + // not all slides in this Story could be unflattened so, show the warning informative dialog + FrameSaveErrorDialog.newInstance( + title = getString(R.string.dialog_edit_story_limited_title), + message = getString(R.string.dialog_edit_story_limited_message) + ).show(supportFragmentManager, FRAGMENT_ANNOUNCEMENT_DIALOG) + } + } + } } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index fb2454bca40c..4d066ad74c38 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2871,6 +2871,9 @@ %s selected %s + + Limited Story Editing + This story was edited on a different device and the ability to edit certain objects may be limited. Capture Flip camera Flash diff --git a/libs/stories-android b/libs/stories-android index 78b87d4cd5cc..44deeb3a86c0 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 78b87d4cd5cc1dab9a3eb22ab902b66143f4b08d +Subproject commit 44deeb3a86c0b37220e6aa606753a7cdae775543 From 3f5da8d2394c5ce36fd929b661927d2666101caa Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 16 Sep 2020 18:23:12 -0300 Subject: [PATCH 017/230] updated stories lib hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 44deeb3a86c0..b9322a3f440b 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 44deeb3a86c0b37220e6aa606753a7cdae775543 +Subproject commit b9322a3f440bd33b6b5d919e67617c60dacea36b From c21e3e3bb25ad70d54a92f8862d0e1d2f2323739 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 17 Sep 2020 07:45:28 -0300 Subject: [PATCH 018/230] passing blockId, mediaFiles and state in result --- .../android/ui/ActivityLauncher.java | 5 ++++- .../android/ui/posts/EditPostActivity.java | 11 +++++++++-- .../stories/SaveStoryGutenbergBlockUseCase.kt | 12 ++++++++++++ .../ui/stories/StoryComposerActivity.kt | 19 ++++++++++++++++++- .../gutenberg/GutenbergEditorFragment.java | 16 ++++++++++++---- 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index 28d25cf97060..bfeca6f88b35 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -99,6 +99,7 @@ import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_ARTICLE_DETAIL_REBLOGGED; import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_ARTICLE_REBLOGGED; import static org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_ACCESS_ERROR; +import static org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_ID; import static org.wordpress.android.imageeditor.preview.PreviewImageFragment.ARG_EDIT_IMAGE_DATA; import static org.wordpress.android.login.LoginMode.WPCOM_LOGIN_ONLY; import static org.wordpress.android.ui.media.MediaBrowserActivity.ARG_BROWSER_TYPE; @@ -744,7 +745,8 @@ public static void editStoryForResult( SiteModel site, int storyIndex, boolean allStorySlidesAreEditable, - boolean launchedFromGutenberg + boolean launchedFromGutenberg, + String storyBlockId ) { if (site == null) { return; @@ -755,6 +757,7 @@ public static void editStoryForResult( intent.putExtra(KEY_STORY_INDEX, storyIndex); intent.putExtra(KEY_LAUNCHED_FROM_GUTENBERG, launchedFromGutenberg); intent.putExtra(KEY_ALL_UNFLATTENED_LOADED_SLIDES, allStorySlidesAreEditable); + intent.putExtra(ARG_STORY_BLOCK_ID, storyBlockId); activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index aa8a9b8068ed..fd657dcefb53 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3049,8 +3049,15 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } } } - // Story instance loaded or re-created! Load it - ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); + // Story instance loaded or re-created! Load it onto the StoryComposer for editing now + ActivityLauncher.editStoryForResult( + this, + mSite, + storyIndex, + allStorySlidesAreEditable, + true, + blockId + ); } // FluxC events diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index e9c22e279c03..e485d05eaa54 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -29,6 +29,18 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { } } + fun buildJetpackStoryBlockMediaFilesJsonString( + mediaFiles: Map + ): String { + val jsonArrayMediaFiles = ArrayList() // holds media files + for (entry in mediaFiles.entries) { + jsonArrayMediaFiles.add(buildMediaFileData(entry.value)) + } + val storyBlock = StoryBlockData(mediaFiles = jsonArrayMediaFiles) + val gson = Gson() + return gson.toJson(storyBlock) + } + private fun buildMediaFileData(mediaFile: MediaFile): StoryMediaFileData { return StoryMediaFileData( alt = "", diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index ff44aa5e536a..7dd3b7df72d7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -30,6 +30,9 @@ import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.PREPUBLISHING_BOTTOM_SHEET_OPENED +import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_ID +import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_MEDIA_FILES +import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel @@ -95,6 +98,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), @Inject lateinit var analyticsUtilsWrapper: AnalyticsUtilsWrapper @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory @Inject internal lateinit var mediaPickerLauncher: MediaPickerLauncher + @Inject lateinit var saveStoryGutenbergBlockUseCase: SaveStoryGutenbergBlockUseCase private lateinit var viewModel: StoryComposerViewModel private var addingMediaToEditorProgressDialog: ProgressDialog? = null @@ -430,7 +434,20 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } override fun onStorySaveButtonPressed() { - viewModel.onStorySaveButtonPressed() + if (intent.getBooleanExtra(KEY_LAUNCHED_FROM_GUTENBERG, false)) { + val savedContentIntent = Intent() + val blockId = intent.extras.getString(ARG_STORY_BLOCK_ID) + savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) + // TODO + // here take the StoryFrameItems from the current Story, and build a + // val mediaFiles= saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockMediaFilesJsonString() + // savedContentIntent.putExtra(ARG_STORY_BLOCK_MEDIA_FILES, mediaFiles) + savedContentIntent.putExtra(ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA, true) + setResult(Activity.RESULT_OK, savedContentIntent) + finish() + } else { + viewModel.onStorySaveButtonPressed() + } } override fun onSubmitButtonClicked(publishPost: PublishPost) { diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 2285f3f9c8d6..2938472628ee 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -85,6 +85,9 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements private static final String ARG_TENOR_ENABLED = "param_tenor_enabled"; private static final String ARG_GUTENBERG_PROPS_BUILDER = "param_gutenberg_props_builder"; private static final String ARG_STORY_EDITOR_REQUEST_CODE = "param_sory_editor_request_code"; + public static final String ARG_STORY_BLOCK_ID = "block_id"; + public static final String ARG_STORY_BLOCK_MEDIA_FILES = "block_media_files"; + public static final String ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA = "status_wait_for_flattened_media"; private static final int CAPTURE_PHOTO_PERMISSION_REQUEST_CODE = 101; private static final int CAPTURE_VIDEO_PERMISSION_REQUEST_CODE = 102; @@ -407,10 +410,15 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d trackWebViewClosed("dismiss"); } } else if (requestCode == mStoryBlockEditRequestCode) { - // handle edited block content - String blockId = data.getStringExtra(WPGutenbergWebViewActivity.ARG_BLOCK_ID); - String content = data.getStringExtra(WPGutenbergWebViewActivity.ARG_BLOCK_CONTENT); - getGutenbergContainerFragment().replaceStoryEditedBlock(content, blockId); + if (resultCode == Activity.RESULT_OK) { + // handle edited block content + String blockId = data.getStringExtra(ARG_STORY_BLOCK_ID); + String mediaFiles = data.getStringExtra(ARG_STORY_BLOCK_MEDIA_FILES); + getGutenbergContainerFragment().replaceStoryEditedBlock(mediaFiles, blockId); + // TODO maybe we need to track something here? + } else { + // TODO maybe we need to track something here? + } } } From b9212ef71d275c1e1cf0ef064382973b3095568c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 17 Sep 2020 08:02:59 -0300 Subject: [PATCH 019/230] connect onActivityResult in EditPostActivity to call GutenbergEditorFragment's --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index fd657dcefb53..983c022d8ec1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -2396,6 +2396,13 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } } + if (requestCode == RequestCodes.EDIT_STORY) { + if (mEditorFragment instanceof GutenbergEditorFragment) { + mEditorFragment.onActivityResult(requestCode, resultCode, data); + return; + } + } + if (data != null || ((requestCode == RequestCodes.TAKE_PHOTO || requestCode == RequestCodes.TAKE_VIDEO || requestCode == RequestCodes.PHOTO_PICKER))) { switch (requestCode) { From acf2ef85dec828467e9f2eca4ba82b051c5b3924 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 17 Sep 2020 20:55:57 -0300 Subject: [PATCH 020/230] refactor to reuse block mediaFiles building --- .../stories/SaveStoryGutenbergBlockUseCase.kt | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index e485d05eaa54..e86876a16d80 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -14,31 +14,23 @@ import javax.inject.Inject class SaveStoryGutenbergBlockUseCase @Inject constructor() { fun buildJetpackStoryBlockInPost( editPostRepository: EditPostRepository, - mediaFiles: Map + mediaFiles: ArrayList ) { - val jsonArrayMediaFiles = ArrayList() // holds media files - for (entry in mediaFiles.entries) { - jsonArrayMediaFiles.add(buildMediaFileData(entry.value)) - } - - val storyBlock = StoryBlockData(mediaFiles = jsonArrayMediaFiles) - editPostRepository.update { postModel: PostModel -> - postModel.setContent(createGBStoryBlockStringFromJson(storyBlock)) + postModel.setContent(buildJetpackStoryBlockString(mediaFiles)) true } } - fun buildJetpackStoryBlockMediaFilesJsonString( - mediaFiles: Map + fun buildJetpackStoryBlockString( + mediaFiles: List ): String { val jsonArrayMediaFiles = ArrayList() // holds media files - for (entry in mediaFiles.entries) { - jsonArrayMediaFiles.add(buildMediaFileData(entry.value)) + for (mediaFile in mediaFiles) { + jsonArrayMediaFiles.add(buildMediaFileData(mediaFile)) } val storyBlock = StoryBlockData(mediaFiles = jsonArrayMediaFiles) - val gson = Gson() - return gson.toJson(storyBlock) + return createGBStoryBlockStringFromJson(storyBlock) } private fun buildMediaFileData(mediaFile: MediaFile): StoryMediaFileData { From cd42ffb6f0ba4cfd6f534e41d2639ac13f06613e Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 17 Sep 2020 20:56:34 -0300 Subject: [PATCH 021/230] connected the DONE button to pass the updated content story block back to Gutenberg --- .../ui/stories/StoryComposerActivity.kt | 37 +++++++++++++++++-- .../media/StoryMediaSaveUploadBridge.kt | 5 ++- .../gutenberg/GutenbergEditorFragment.java | 8 ++-- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 7dd3b7df72d7..3a735bc19964 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -23,6 +23,8 @@ import com.wordpress.stories.compose.SnackbarProvider import com.wordpress.stories.compose.StoryDiscardListener import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult import com.wordpress.stories.compose.story.StoryIndex +import com.wordpress.stories.compose.story.StoryRepository +import com.wordpress.stories.compose.story.StoryRepository.DEFAULT_NONE_SELECTED import com.wordpress.stories.util.KEY_STORY_EDIT_MODE import com.wordpress.stories.util.KEY_STORY_INDEX import com.wordpress.stories.util.KEY_STORY_SAVE_RESULT @@ -31,12 +33,13 @@ import org.wordpress.android.WordPress import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.PREPUBLISHING_BOTTOM_SHEET_OPENED import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_ID -import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_MEDIA_FILES +import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_UPDATED_CONTENT import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.fluxc.store.PostStore import org.wordpress.android.push.NotificationType import org.wordpress.android.push.NotificationsProcessingService @@ -62,6 +65,7 @@ import org.wordpress.android.ui.stories.media.StoryEditorMedia import org.wordpress.android.ui.stories.media.StoryEditorMedia.AddMediaToStoryPostUiState import org.wordpress.android.ui.utils.AuthenticationUtils import org.wordpress.android.ui.utils.UiHelpers +import org.wordpress.android.util.FluxCUtilsWrapper import org.wordpress.android.util.ListUtils import org.wordpress.android.util.WPMediaUtils import org.wordpress.android.util.WPPermissionUtils @@ -99,6 +103,9 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory @Inject internal lateinit var mediaPickerLauncher: MediaPickerLauncher @Inject lateinit var saveStoryGutenbergBlockUseCase: SaveStoryGutenbergBlockUseCase + @Inject lateinit var mediaStore: MediaStore + @Inject lateinit var fluxCUtilsWrapper: FluxCUtilsWrapper + private lateinit var viewModel: StoryComposerViewModel private var addingMediaToEditorProgressDialog: ProgressDialog? = null @@ -440,16 +447,40 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) // TODO // here take the StoryFrameItems from the current Story, and build a - // val mediaFiles= saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockMediaFilesJsonString() - // savedContentIntent.putExtra(ARG_STORY_BLOCK_MEDIA_FILES, mediaFiles) + val storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) + val updatedStoryBlock= + saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockString( + getMediaFilesFromBackgroundMediaIdsInStory(storyIndex) + ) + savedContentIntent.putExtra(ARG_STORY_BLOCK_UPDATED_CONTENT, updatedStoryBlock) savedContentIntent.putExtra(ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA, true) setResult(Activity.RESULT_OK, savedContentIntent) finish() } else { + // assume this is a new Post, and proceed to PrePublish bottom sheet viewModel.onStorySaveButtonPressed() } } + private fun getMediaFilesFromBackgroundMediaIdsInStory(storyIdx: StoryIndex) : List { + val mediaFiles = ArrayList() + val story = StoryRepository.getStoryAtIndex(storyIdx) + for (frame in story.frames) { + frame.id?.let { + // WARNING: we assume the only path to creation is by using the Story Creator (not mobile gutenberg + // by inserting a new block from the block picker) so, we ALWAYS should have a remote mediaId + // here. If things change, we'll need to cover the situation for finding a MediaModel from both + // a local ID (if not yet uploaded to the site) and a remote ID (after uploading to the site). + val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) + val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) + mediaFile?.let { + mediaFiles.add(it) + } + } + } + return mediaFiles + } + override fun onSubmitButtonClicked(publishPost: PublishPost) { viewModel.onSubmitButtonClicked() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index d45c809556d7..7592c889bc16 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -157,7 +157,10 @@ class StoryMediaSaveUploadBridge @Inject constructor( } override fun appendMediaFiles(mediaFiles: Map) { - saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost(editPostRepository, mediaFiles) + saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost( + editPostRepository, + ArrayList(mediaFiles.values) + ) } override fun getImmutablePost(): PostImmutableModel { diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 2938472628ee..0d18afdec9e6 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -85,8 +85,8 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements private static final String ARG_TENOR_ENABLED = "param_tenor_enabled"; private static final String ARG_GUTENBERG_PROPS_BUILDER = "param_gutenberg_props_builder"; private static final String ARG_STORY_EDITOR_REQUEST_CODE = "param_sory_editor_request_code"; - public static final String ARG_STORY_BLOCK_ID = "block_id"; - public static final String ARG_STORY_BLOCK_MEDIA_FILES = "block_media_files"; + public static final String ARG_STORY_BLOCK_ID = "story_block_id"; + public static final String ARG_STORY_BLOCK_UPDATED_CONTENT = "story_block_updated_content"; public static final String ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA = "status_wait_for_flattened_media"; private static final int CAPTURE_PHOTO_PERMISSION_REQUEST_CODE = 101; @@ -413,8 +413,8 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d if (resultCode == Activity.RESULT_OK) { // handle edited block content String blockId = data.getStringExtra(ARG_STORY_BLOCK_ID); - String mediaFiles = data.getStringExtra(ARG_STORY_BLOCK_MEDIA_FILES); - getGutenbergContainerFragment().replaceStoryEditedBlock(mediaFiles, blockId); + String updatedBlockContent = data.getStringExtra(ARG_STORY_BLOCK_UPDATED_CONTENT); + getGutenbergContainerFragment().replaceStoryEditedBlock(updatedBlockContent, blockId); // TODO maybe we need to track something here? } else { // TODO maybe we need to track something here? From 8fa059d29563eafbe53ea48c379fdd4232ab545b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 07:47:31 -0300 Subject: [PATCH 022/230] initializing request codes right away in onCreate before calling super() to make sure these can be properly evaluated on creation --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index ff44aa5e536a..90a0c67e01fe 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -116,10 +116,10 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), override fun onCreate(savedInstanceState: Bundle?) { // convert our WPAndroid KEY_LAUNCHED_FROM_GUTENBERG flag into Stories general purpose EDIT_MODE flag intent.putExtra(KEY_STORY_EDIT_MODE, intent.getBooleanExtra(KEY_LAUNCHED_FROM_GUTENBERG, false)) + setMediaPickerProvider(this) super.onCreate(savedInstanceState) (application as WordPress).component().inject(this) setSnackbarProvider(this) - setMediaPickerProvider(this) setAuthenticationProvider(this) setNotificationExtrasLoader(this) setMetadataProvider(this) From df91b54a0b87a32c9c0ceb383d28b9979b9ebdef Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 09:05:44 -0300 Subject: [PATCH 023/230] refactored code, introducing LoadStoryFromStoriesPrefsUseCase --- .../android/ui/posts/EditPostActivity.java | 60 ++++-------- .../ui/stories/StoryRepositoryWrapper.kt | 5 + .../android/ui/stories/prefs/StoriesPrefs.kt | 4 +- .../LoadStoryFromStoriesPrefsUseCase.kt | 91 +++++++++++++++++++ libs/stories-android | 2 +- 5 files changed, 119 insertions(+), 43 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index aa8a9b8068ed..9987050575c7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -160,8 +160,11 @@ import org.wordpress.android.ui.prefs.SiteSettingsInterface; import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; +import org.wordpress.android.ui.stories.StoryRepositoryWrapper; import org.wordpress.android.ui.stories.prefs.StoriesPrefs; import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId; +import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; +import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; import org.wordpress.android.ui.uploads.UploadService; import org.wordpress.android.ui.uploads.UploadUtils; @@ -3002,52 +3005,29 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - ArrayList tmpMediaIdsString = new ArrayList<>(); - boolean allStorySlidesAreEditable = true; - for (Object mediaFile : mediaFiles) { - long mediaIdLong = new Double(((HashMap) mediaFile).get("id").toString()).longValue(); - String mediaIdString = String.valueOf(mediaIdLong); - if (allStorySlidesAreEditable - && !StoriesPrefs.isValidSlide(this, mSite.getId(), new RemoteMediaId(mediaIdLong))) { - // flag this as soon as we find one media item not being really editable - allStorySlidesAreEditable = false; - } - tmpMediaIdsString.add(mediaIdString); - } + LoadStoryFromStoriesPrefsUseCase loadStoryFromStoriesPrefsUseCase = new LoadStoryFromStoriesPrefsUseCase( + new StoryRepositoryWrapper(), + mSite, + mMediaStore, + this + ); + ArrayList mediaIds = + loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles); + boolean allStorySlidesAreEditable = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(mSite, mediaIds); // now look for a Story in the StoryRepository that has all these frames and, if not found, let's // just build the Story object ourselves to keep these files arrangement - int storyIndex = StoryRepository.findStoryContainingStoryFrameItemsByIds(tmpMediaIdsString); + int storyIndex = StoryRepository.findStoryContainingStoryFrameItemsByIds(mediaIds); if (storyIndex == StoryRepository.DEFAULT_NONE_SELECTED) { - // the StoryRepository didn' have it but we have editable serialized slides so, + // the StoryRepository didn't have it but we have editable serialized slides so, // create a new Story from scratch with these deserialized StoryFrameItems - StoryRepository.loadStory(storyIndex); - storyIndex = StoryRepository.currentStoryIndex; - for (String mediaId : tmpMediaIdsString) { - StoryFrameItem storyFrameItem = StoriesPrefs.getSlideWithRemoteId( - this, - mSite.getId(), - new RemoteMediaId(Long.parseLong(mediaId)) - ); - if (storyFrameItem != null) { - StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); - } else { - allStorySlidesAreEditable = false; - - // for this missing frame we'll create a new frame using the actual uploaded flattened media - ArrayList tmpMediaIdsLong = new ArrayList<>(); - tmpMediaIdsLong.add(Long.parseLong(mediaId)); - List mediaModelList = mMediaStore.getSiteMediaWithIds(mSite, tmpMediaIdsLong); - for (MediaModel mediaModel : mediaModelList) { - storyFrameItem = StoryFrameItem.Companion.getNewStoryFrameItemFromUri( - Uri.parse(mediaModel.getUrl()), - mediaModel.isVideo() - ); - storyFrameItem.setId(String.valueOf(mediaModel.getMediaId())); - StoryRepository.addStoryFrameItemToCurrentStory(storyFrameItem); - } - } + ReCreateStoryResult result = + loadStoryFromStoriesPrefsUseCase.loadOrReCreateStoryFromStoriesPrefs(mediaIds); + if (allStorySlidesAreEditable) { + // double check and override if we found at least one couldn't be inflated + allStorySlidesAreEditable = result.getAllStorySlidesAreEditable(); } + storyIndex = result.getStoryIndex(); } // Story instance loaded or re-created! Load it ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt index ee6deefcb3eb..7b89cea9bbda 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt @@ -1,5 +1,7 @@ package org.wordpress.android.ui.stories +import com.wordpress.stories.compose.story.StoryFrameItem +import com.wordpress.stories.compose.story.StoryIndex import com.wordpress.stories.compose.story.StoryRepository import javax.inject.Inject @@ -7,4 +9,7 @@ class StoryRepositoryWrapper @Inject constructor() { fun setCurrentStoryTitle(title: String) = StoryRepository.setCurrentStoryTitle(title) fun getCurrentStoryThumbnailUrl() = StoryRepository.getCurrentStoryThumbnailUrl() fun getCurrentStoryTitle() = StoryRepository.getCurrentStoryTitle() + fun getCurrentStoryIndex(): StoryIndex = StoryRepository.currentStoryIndex + fun loadStory(storyIndex: StoryIndex) = StoryRepository.loadStory(storyIndex) + fun addStoryFrameItemToCurrentStory(item: StoryFrameItem) = StoryRepository.addStoryFrameItemToCurrentStory(item) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 4dc3a8b850b8..82b924756a21 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -14,11 +14,11 @@ object StoriesPrefs { private const val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" private fun buildSlideKey(siteId: Long, mediaId: RemoteMediaId): String { - return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.toString() + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.mediaId.toString() } private fun buildSlideKey(siteId: Long, mediaId: LocalMediaId): String { - return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.toString() + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.id.toString() } @JvmStatic diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt new file mode 100644 index 000000000000..def87ba9aa2b --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -0,0 +1,91 @@ +package org.wordpress.android.ui.stories.usecase + +import android.content.Context +import android.net.Uri +import com.wordpress.stories.compose.story.StoryFrameItem +import com.wordpress.stories.compose.story.StoryIndex +import com.wordpress.stories.compose.story.StoryRepository +import dagger.Reusable +import org.wordpress.android.fluxc.model.MediaModel +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.MediaStore +import org.wordpress.android.ui.stories.StoryRepositoryWrapper +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.getSlideWithRemoteId +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.isValidSlide +import java.util.ArrayList +import java.util.HashMap +import javax.inject.Inject + +@Reusable +class LoadStoryFromStoriesPrefsUseCase @Inject constructor( + private val storyRepositoryWrapper: StoryRepositoryWrapper, + private val site: SiteModel, + private val mediaStore: MediaStore, + private val context: Context +) { + fun getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles: ArrayList): ArrayList { + val mediaIds = ArrayList() + for (mediaFile in mediaFiles) { + val mediaIdLong = (mediaFile as HashMap)["id"] + .toString() + .toDouble() // this conversion is needed to strip off decimals that can come from RN + .toLong() + val mediaIdString = mediaIdLong.toString() + mediaIds.add(mediaIdString) + } + return mediaIds + } + + fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { + for (mediaId in mediaIds) { + if (!isValidSlide(context, site.getId().toLong(), RemoteMediaId(mediaId.toLong()))) { + return false + } + } + return true + } + + fun loadOrReCreateStoryFromStoriesPrefs(mediaIds: ArrayList): ReCreateStoryResult { + // the StoryRepository didn't have it but we have editable serialized slides so, + // create a new Story from scratch with these deserialized StoryFrameItems + var allStorySlidesAreEditable: Boolean = true + var storyIndex = StoryRepository.DEFAULT_NONE_SELECTED + storyRepositoryWrapper.loadStory(storyIndex) + storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() + for (mediaId in mediaIds) { + var storyFrameItem = getSlideWithRemoteId( + context, + site.getId().toLong(), + RemoteMediaId(mediaId.toLong()) + ) + if (storyFrameItem != null) { + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + } else { + allStorySlidesAreEditable = false + + // for this missing frame we'll create a new frame using the actual uploaded flattened media + val tmpMediaIdsLong = ArrayList() + tmpMediaIdsLong.add(mediaId.toLong()) + val mediaModelList: List = mediaStore.getSiteMediaWithIds( + site, + tmpMediaIdsLong + ) + for (mediaModel in mediaModelList) { + storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( + Uri.parse(mediaModel.url), + mediaModel.isVideo + ) + storyFrameItem.id = mediaModel.mediaId.toString() + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + } + } + } + + return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable) + } + + data class ReCreateStoryResult(val storyIndex: StoryIndex, val allStorySlidesAreEditable: Boolean) +} + + diff --git a/libs/stories-android b/libs/stories-android index b9322a3f440b..68fc2ec21ccc 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit b9322a3f440bd33b6b5d919e67617c60dacea36b +Subproject commit 68fc2ec21ccce9af40f89bca3dcc57a914dd291e From 448dffd9005b1be3c91d1af38e711b62f409ad25 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 09:56:48 -0300 Subject: [PATCH 024/230] added path for story media not fetched locally --- .../android/ui/posts/EditPostActivity.java | 50 +++++++++++++++++-- .../LoadStoryFromStoriesPrefsUseCase.kt | 26 ++++++---- WordPress/src/main/res/values/strings.xml | 2 + 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 9987050575c7..ac5871c852fc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -40,7 +40,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; -import com.wordpress.stories.compose.story.StoryFrameItem; import com.wordpress.stories.compose.story.StoryRepository; import org.greenrobot.eventbus.EventBus; @@ -75,6 +74,7 @@ import org.wordpress.android.fluxc.action.AccountAction; import org.wordpress.android.fluxc.generated.AccountActionBuilder; import org.wordpress.android.fluxc.generated.EditorThemeActionBuilder; +import org.wordpress.android.fluxc.generated.MediaActionBuilder; import org.wordpress.android.fluxc.generated.PostActionBuilder; import org.wordpress.android.fluxc.generated.SiteActionBuilder; import org.wordpress.android.fluxc.model.AccountModel; @@ -95,9 +95,11 @@ import org.wordpress.android.fluxc.store.EditorThemeStore.FetchEditorThemePayload; import org.wordpress.android.fluxc.store.EditorThemeStore.OnEditorThemeChanged; import org.wordpress.android.fluxc.store.MediaStore; +import org.wordpress.android.fluxc.store.MediaStore.FetchMediaListPayload; import org.wordpress.android.fluxc.store.MediaStore.MediaError; import org.wordpress.android.fluxc.store.MediaStore.MediaErrorType; import org.wordpress.android.fluxc.store.MediaStore.OnMediaChanged; +import org.wordpress.android.fluxc.store.MediaStore.OnMediaListFetched; import org.wordpress.android.fluxc.store.MediaStore.OnMediaUploaded; import org.wordpress.android.fluxc.store.PostStore; import org.wordpress.android.fluxc.store.PostStore.OnPostChanged; @@ -185,6 +187,7 @@ import org.wordpress.android.util.LocaleManager; import org.wordpress.android.util.LocaleManagerWrapper; import org.wordpress.android.util.MediaUtils; +import org.wordpress.android.util.NetworkUtils; import org.wordpress.android.util.PermissionUtils; import org.wordpress.android.util.ReblogUtils; import org.wordpress.android.util.ShortcutUtils; @@ -611,6 +614,13 @@ protected void onCreate(Bundle savedInstanceState) { } if (!mIsNewPost) { + // if we are opening an existing Post, and it contains a Story block, pre-fetch the media in case + // the user wants to edit the block (we'll need to download it first if the slides images weren't + // created on this device) + if (PostUtils.contentContainsWPStoryGutenbergBlocks(mEditPostRepository.getPost().getContent())) { + fetchMediaList(); + } + // if we are opening a Post for which an error notification exists, we need to remove it from the dashboard // to prevent the user from tapping RETRY on a Post that is being currently edited UploadService.cancelFinalNotification(this, mEditPostRepository.getPost()); @@ -3014,6 +3024,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie ArrayList mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles); boolean allStorySlidesAreEditable = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(mSite, mediaIds); + boolean failedLoadingOrReCreatingStory = false; // now look for a Story in the StoryRepository that has all these frames and, if not found, let's // just build the Story object ourselves to keep these files arrangement @@ -3023,14 +3034,29 @@ public void onTrackableEvent(TrackableEvent event, Map propertie // create a new Story from scratch with these deserialized StoryFrameItems ReCreateStoryResult result = loadStoryFromStoriesPrefsUseCase.loadOrReCreateStoryFromStoriesPrefs(mediaIds); + failedLoadingOrReCreatingStory = result.getNoSlidesLoaded(); if (allStorySlidesAreEditable) { // double check and override if we found at least one couldn't be inflated allStorySlidesAreEditable = result.getAllStorySlidesAreEditable(); } storyIndex = result.getStoryIndex(); } - // Story instance loaded or re-created! Load it - ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); + + if (!failedLoadingOrReCreatingStory) { + // Story instance loaded or re-created! Load it + ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); + } else { + // unfortunately we couldn't even load the remote media Ids indicated by the StoryBLock so we can't allow + // editing at this time :( + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); + builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); + builder.setMessage(getString(R.string.dialog_edit_story_unavailable_message)); + builder.setPositiveButton(R.string.yes, (dialog, id) -> { + dialog.dismiss(); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + } } // FluxC events @@ -3065,6 +3091,13 @@ public void onMediaUploaded(OnMediaUploaded event) { // FluxC events + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMediaListFetched(OnMediaListFetched event) { + // no op - we don't need to check anything just now, but declaring the method so it's + // clear we make a request to FetchMedia in this class. + } + @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onPostChanged(OnPostChanged event) { @@ -3190,6 +3223,17 @@ private void refreshEditorTheme() { mDispatcher.dispatch(EditorThemeActionBuilder.newFetchEditorThemeAction(payload)); } + private void fetchMediaList() { + // do not refresh if there is no network + if (!NetworkUtils.isNetworkAvailable(this)) { + return; + } + FetchMediaListPayload payload = + new FetchMediaListPayload(mSite, MediaStore.DEFAULT_NUM_MEDIA_PER_FETCH, false); + mDispatcher.dispatch(MediaActionBuilder.newFetchMediaListAction(payload)); + } + + @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN_ORDERED) public void onEditorThemeChanged(OnEditorThemeChanged event) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index def87ba9aa2b..07ad84298e8d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -50,6 +50,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( // the StoryRepository didn't have it but we have editable serialized slides so, // create a new Story from scratch with these deserialized StoryFrameItems var allStorySlidesAreEditable: Boolean = true + var noSlidesLoaded = false var storyIndex = StoryRepository.DEFAULT_NONE_SELECTED storyRepositoryWrapper.loadStory(storyIndex) storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() @@ -71,21 +72,28 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( site, tmpMediaIdsLong ) - for (mediaModel in mediaModelList) { - storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( - Uri.parse(mediaModel.url), - mediaModel.isVideo - ) - storyFrameItem.id = mediaModel.mediaId.toString() - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + if (mediaModelList.size == 0) { + noSlidesLoaded = true + } else { + for (mediaModel in mediaModelList) { + storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( + Uri.parse(mediaModel.url), + mediaModel.isVideo + ) + storyFrameItem.id = mediaModel.mediaId.toString() + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + } } } } - return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable) + return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable, noSlidesLoaded) } - data class ReCreateStoryResult(val storyIndex: StoryIndex, val allStorySlidesAreEditable: Boolean) + data class ReCreateStoryResult( + val storyIndex: StoryIndex, + val allStorySlidesAreEditable: Boolean, + val noSlidesLoaded: Boolean) } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 4d066ad74c38..a4dc6e748ade 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2874,6 +2874,8 @@ Limited Story Editing This story was edited on a different device and the ability to edit certain objects may be limited. + Can\'t edit Story + This story was created on a different device and can\'t be edited at this moment. Capture Flip camera Flash From 190b1b7a6f4d71a441dfb8e0744cdf3dcfb4ed79 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 10:39:15 -0300 Subject: [PATCH 025/230] updated stories lib hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 68fc2ec21ccc..a44d8e2937d9 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 68fc2ec21ccce9af40f89bca3dcc57a914dd291e +Subproject commit a44d8e2937d97ac1a04670add18869c99304b6a0 From 4698adefd2cc5a7eb8a880fda0d3b13110972d56 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 10:51:14 -0300 Subject: [PATCH 026/230] removed unused imports --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index ac5871c852fc..e1ea792be876 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -163,8 +163,6 @@ import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; import org.wordpress.android.ui.stories.StoryRepositoryWrapper; -import org.wordpress.android.ui.stories.prefs.StoriesPrefs; -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; From 143eb2e0d1e14ebea4e5961374c909711b660177 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 10:55:44 -0300 Subject: [PATCH 027/230] updated dialog OK button label --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index e1ea792be876..ecda0a9db427 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3049,7 +3049,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); builder.setMessage(getString(R.string.dialog_edit_story_unavailable_message)); - builder.setPositiveButton(R.string.yes, (dialog, id) -> { + builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { dialog.dismiss(); }); AlertDialog dialog = builder.create(); From aacfac78edae8c2b9bd3ffd962b1140d4dad7c07 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 10:57:18 -0300 Subject: [PATCH 028/230] fixed merge conflict, moving call within failedLoadingOrReCreatingStory check --- .../android/ui/posts/EditPostActivity.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index b902bfb94aa9..6ac488e243a6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3048,8 +3048,15 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } if (!failedLoadingOrReCreatingStory) { - // Story instance loaded or re-created! Load it - ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); + // Story instance loaded or re-created! Load it onto the StoryComposer for editing now + ActivityLauncher.editStoryForResult( + this, + mSite, + storyIndex, + allStorySlidesAreEditable, + true, + blockId + ); } else { // unfortunately we couldn't even load the remote media Ids indicated by the StoryBLock so we can't allow // editing at this time :( @@ -3062,16 +3069,6 @@ public void onTrackableEvent(TrackableEvent event, Map propertie AlertDialog dialog = builder.create(); dialog.show(); } - - // Story instance loaded or re-created! Load it onto the StoryComposer for editing now - ActivityLauncher.editStoryForResult( - this, - mSite, - storyIndex, - allStorySlidesAreEditable, - true, - blockId - ); } // FluxC events From 587960f7252af94373e4c687779b4be2aff1b973 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 11:15:30 -0300 Subject: [PATCH 029/230] fixed lint warnings --- .../org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 6 ++++-- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 82b924756a21..b2c88bb789c2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -14,11 +14,13 @@ object StoriesPrefs { private const val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" private fun buildSlideKey(siteId: Long, mediaId: RemoteMediaId): String { - return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.mediaId.toString() + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + + KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.mediaId.toString() } private fun buildSlideKey(siteId: Long, mediaId: LocalMediaId): String { - return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.id.toString() + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + + KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.id.toString() } @JvmStatic diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 07ad84298e8d..ca3fe97647a5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -93,7 +93,6 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( data class ReCreateStoryResult( val storyIndex: StoryIndex, val allStorySlidesAreEditable: Boolean, - val noSlidesLoaded: Boolean) + val noSlidesLoaded: Boolean + ) } - - From 9ef826de822f84173ad66caa078755ac6e1a8b1b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 18 Sep 2020 11:43:50 -0300 Subject: [PATCH 030/230] fixed lint warnings --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 9d2be45cd60a..8a85a273d29c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -448,7 +448,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), // TODO // here take the StoryFrameItems from the current Story, and build a val storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) - val updatedStoryBlock= + val updatedStoryBlock = saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockString( getMediaFilesFromBackgroundMediaIdsInStory(storyIndex) ) @@ -462,7 +462,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } } - private fun getMediaFilesFromBackgroundMediaIdsInStory(storyIdx: StoryIndex) : List { + private fun getMediaFilesFromBackgroundMediaIdsInStory(storyIdx: StoryIndex): List { val mediaFiles = ArrayList() val story = StoryRepository.getStoryAtIndex(storyIdx) for (frame in story.frames) { From d7884c8b370d223eac776a57162000c371ba006c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 21 Sep 2020 13:15:54 -0300 Subject: [PATCH 031/230] modified the bridge to have instances of EditorMedialListener so these know if this is an edit mode operation for each SaveResult --- .../media/StoryMediaSaveUploadBridge.kt | 110 +++++++++--------- 1 file changed, 58 insertions(+), 52 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 7592c889bc16..2ccba4300b4a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -55,7 +55,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( private val postUtils: PostUtilsWrapper, private val eventBusWrapper: EventBusWrapper, @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher -) : CoroutineScope, LifecycleObserver, EditorMediaListener { +) : CoroutineScope, LifecycleObserver { // region Fields private var job: Job = Job() private lateinit var appContext: Context @@ -92,17 +92,71 @@ class StoryMediaSaveUploadBridge @Inject constructor( // let's invoke the UploadService and enqueue all the files that were saved by the FrameSaveService val frames = StoryRepository.getStoryAtIndex(saveResult.storyIndex).frames val uriList = frames.map { Uri.fromFile(it.composedFrameFile) } - addNewMediaItemsToPostAsync(site, uriList) + addNewMediaItemsToPostAsync(site, uriList, saveResult.isEditMode) } - private fun addNewMediaItemsToPostAsync(site: SiteModel, uriList: List) { + private fun addNewMediaItemsToPostAsync(site: SiteModel, uriList: List, isEditMode: Boolean) { // this is similar to addNewMediaItemsToEditorAsync in EditorMedia launch { + val localEditorMediaListener = object: EditorMediaListener { + override fun appendMediaFiles(mediaFiles: Map) { + if (!isEditMode) { + saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost( + editPostRepository, + ArrayList(mediaFiles.values) + ) + } else { + // no op: in edit mode, we're handling replacing of the block's mediaFiles in Gutenberg + } + } + + override fun getImmutablePost(): PostImmutableModel { + return editPostRepository.getPost()!! + } + + override fun syncPostObjectWithUiAndSaveIt(listener: OnPostUpdatedFromUIListener?) { + // no op + // WARNING: don't remove this, we need to call the listener no matter what, so save & upload actually happen + listener?.onPostUpdatedFromUI(null) + } + + override fun advertiseImageOptimization(listener: () -> Unit) { + // no op + } + + override fun onMediaModelsCreatedFromOptimizedUris(oldUriToMediaFiles: Map) { + // in order to support Story editing capabilities, we save a serialized version of the Story slides + // after their composedFrameFiles have been processed. + + // here we change the ids on the actual StoryFrameItems, and also update the flattened / composed image + // urls with the new URLs which may have been replaced after image optimization + for (story in StoryRepository.getImmutableStories()) { + // find the MediaModel for a given Uri from composedFrameFile + for (frame in story.frames) { + // if the old URI in frame.composedFrameFile exists as a key in the passed map, then update that + // value with the new (probably optimized) URL and also keep track of the new id. + val mediaModel = oldUriToMediaFiles.get(Uri.fromFile(frame.composedFrameFile)) + mediaModel?.let { + frame.id = it.id.toString() + StoriesPrefs.saveSlideWithLocalId( + appContext, + it.localSiteId.toLong(), + // use the local id to save the original, will be replaced later + // with mediaModel.mediaId after uploading to the remote site + LocalMediaId(it.id.toLong()), + frame + ) + } + } + } + } + } + addLocalMediaToPostUseCase.addNewMediaToEditorAsync( uriList, site, freshlyTaken = false, // we don't care about this - editorMediaListener = this@StoryMediaSaveUploadBridge, + editorMediaListener = localEditorMediaListener, doUploadAfterAdding = true ) postUtils.preparePostForPublish(requireNotNull(editPostRepository.getEditablePost()), site) @@ -155,52 +209,4 @@ class StoryMediaSaveUploadBridge @Inject constructor( return (event.isSuccess() && event.frameSaveResult.size == StoryRepository.getStoryAtIndex(event.storyIndex).frames.size) } - - override fun appendMediaFiles(mediaFiles: Map) { - saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost( - editPostRepository, - ArrayList(mediaFiles.values) - ) - } - - override fun getImmutablePost(): PostImmutableModel { - return editPostRepository.getPost()!! - } - - override fun syncPostObjectWithUiAndSaveIt(listener: OnPostUpdatedFromUIListener?) { - // no op - // WARNING: don't remove this, we need to call the listener no matter what, so save & upload actually happen - listener?.onPostUpdatedFromUI(null) - } - - override fun advertiseImageOptimization(listener: () -> Unit) { - // no op - } - - override fun onMediaModelsCreatedFromOptimizedUris(oldUriToMediaFiles: Map) { - // in order to support Story editing capabilities, we save a serialized version of the Story slides - // after their composedFrameFiles have been processed. - - // here we change the ids on the actual StoryFrameItems, and also update the flattened / composed image - // urls with the new URLs which may have been replaced after image optimization - for (story in StoryRepository.getImmutableStories()) { - // find the MediaModel for a given Uri from composedFrameFile - for (frame in story.frames) { - // if the old URI in frame.composedFrameFile exists as a key in the passed map, then update that - // value with the new (probably optimized) URL and also keep track of the new id. - val mediaModel = oldUriToMediaFiles.get(Uri.fromFile(frame.composedFrameFile)) - mediaModel?.let { - frame.id = it.id.toString() - StoriesPrefs.saveSlideWithLocalId( - appContext, - it.localSiteId.toLong(), - // use the local id to save the original, will be replaced later - // with mediaModel.mediaId after uploading to the remote site - LocalMediaId(it.id.toLong()), - frame - ) - } - } - } - } } From 7f5453b98d305154b2054c32f356a639b27d3f13 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 21 Sep 2020 15:15:31 -0300 Subject: [PATCH 032/230] udpated stories lib hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index a44d8e2937d9..ffc024efceca 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit a44d8e2937d97ac1a04670add18869c99304b6a0 +Subproject commit ffc024efcecaafe5055925ac9fb92e50e4fce453 From 1e41de1bcc1e60c159d03313d4ff24bb5250d89c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 21 Sep 2020 18:53:28 -0300 Subject: [PATCH 033/230] added all listeners to handle Story Save progress when editing a Story in Gutenberg --- .../android/ui/posts/EditPostActivity.java | 10 ++++++ .../media/AddLocalMediaToPostUseCase.kt | 2 +- .../ui/stories/StoryComposerActivity.kt | 7 ++-- .../media/StoryEditorMediaSaveListener.kt | 10 ++++++ .../gutenberg/GutenbergContainerFragment.java | 19 +++++++++++ .../gutenberg/GutenbergEditorFragment.java | 34 ++++++++++++++++++- .../gutenberg/StorySaveMediaListener.java | 10 ++++++ libs/gutenberg-mobile | 2 +- 8 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt create mode 100644 libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 6ac488e243a6..0e5e833bd541 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -163,6 +163,7 @@ import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; import org.wordpress.android.ui.stories.StoryRepositoryWrapper; +import org.wordpress.android.ui.stories.media.StoryEditorMediaSaveListener; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; @@ -329,6 +330,7 @@ enum RestartEditorOptions { private EditorFragmentAbstract mEditorFragment; private EditPostSettingsFragment mEditPostSettingsFragment; private EditorMediaUploadListener mEditorMediaUploadListener; + private StoryEditorMediaSaveListener mStoryEditorMediaSaveListener; private EditorPhotoPicker mEditorPhotoPicker; private ProgressDialog mProgressDialog; @@ -563,6 +565,10 @@ protected void onCreate(Bundle savedInstanceState) { if (mEditorFragment instanceof EditorMediaUploadListener) { mEditorMediaUploadListener = (EditorMediaUploadListener) mEditorFragment; } + + if (mEditorFragment instanceof StoryEditorMediaSaveListener) { + mStoryEditorMediaSaveListener = (StoryEditorMediaSaveListener) mEditorFragment; + } } if (mSite == null) { @@ -2142,6 +2148,10 @@ public Fragment getItem(int position) { reattachUploadingMediaForAztec(); } + + if (mEditorFragment instanceof StoryEditorMediaSaveListener) { + mStoryEditorMediaSaveListener = (StoryEditorMediaSaveListener) mEditorFragment; + } break; case PAGE_SETTINGS: mEditPostSettingsFragment = (EditPostSettingsFragment) fragment; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt index ccb97c3de05c..6deae0e3139f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt @@ -69,7 +69,7 @@ class AddLocalMediaToPostUseCase @Inject constructor( // here we pass a map of "old" (before optimisation) Uris to the new MediaModels which contain // both the mediaModel ids and the optimized media URLs. - // this way, the listener will be able to process from other models potining to the old URLs + // this way, the listener will be able to process from other models pointing to the old URLs // and make any needed updates editorMediaListener.onMediaModelsCreatedFromOptimizedUris( uriList.zip(createMediaModelsResult.mediaModels).toMap() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 8a85a273d29c..f43cb7361806 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -445,8 +445,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), val savedContentIntent = Intent() val blockId = intent.extras.getString(ARG_STORY_BLOCK_ID) savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) - // TODO - // here take the StoryFrameItems from the current Story, and build a + val storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) val updatedStoryBlock = saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockString( @@ -455,6 +454,10 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), savedContentIntent.putExtra(ARG_STORY_BLOCK_UPDATED_CONTENT, updatedStoryBlock) savedContentIntent.putExtra(ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA, true) setResult(Activity.RESULT_OK, savedContentIntent) + + // TODO add tracks + processStorySaving() + finish() } else { // assume this is a new Post, and proceed to PrePublish bottom sheet diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt new file mode 100644 index 000000000000..04715ef2cafd --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt @@ -0,0 +1,10 @@ +package org.wordpress.android.ui.stories.media + +import org.wordpress.android.util.helpers.MediaFile + +interface StoryEditorMediaSaveListener { + fun onMediaSaveReattached(localId: String?, currentProgress: Float) + fun onMediaSaveSucceeded(localId: String?, mediaFile: MediaFile?) + fun onMediaSaveProgress(localId: String?, progress: Float) + fun onMediaSaveFailed(localId: String?) +} diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 944f7f0b1aed..690a76110e06 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -27,6 +27,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStorySavingReattachQueryListener; import java.util.ArrayList; @@ -53,6 +54,7 @@ public boolean hasReceivedAnyContent() { public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onMediaLibraryButtonListener, OnReattachQueryListener onReattachQueryListener, + OnStorySavingReattachQueryListener onStorySavingReattachQueryListener, OnEditorMountListener onEditorMountListener, OnEditorAutosaveListener onEditorAutosaveListener, OnAuthHeaderRequestedListener onAuthHeaderRequestedListener, @@ -70,6 +72,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener viewGroup, onMediaLibraryButtonListener, onReattachQueryListener, + onStorySavingReattachQueryListener, onEditorMountListener, onEditorAutosaveListener, onAuthHeaderRequestedListener, @@ -218,4 +221,20 @@ public void updateCapabilities(GutenbergPropsBuilder gutenbergPropsBuilder) { GutenbergProps gutenbergProps = gutenbergPropsBuilder.build(getActivity(), mHtmlModeEnabled); mWPAndroidGlueCode.updateCapabilities(gutenbergProps); } + + public void clearFileSaveStatus(final int mediaId) { + mWPAndroidGlueCode.clearFileSaveStatus(mediaId); + } + + public void mediaFileSaveProgress(final int mediaId, final float progress) { + mWPAndroidGlueCode.mediaFileSaveProgress(mediaId, progress); + } + + public void mediaFileSaveFailed(final int mediaId) { + mWPAndroidGlueCode.mediaFileSaveFailed(mediaId); + } + + public void mediaFileSaveSucceeded(final int mediaId, final String mediaUrl, final int serverMediaId) { + mWPAndroidGlueCode.mediaFileSaveSucceeded(mediaId, mediaUrl, serverMediaId); + } } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 0d18afdec9e6..3fe5f0b178e7 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -63,6 +63,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStorySavingReattachQueryListener; import java.util.ArrayList; import java.util.HashMap; @@ -76,7 +77,8 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements EditorMediaUploadListener, IHistoryListener, - EditorThemeUpdateListener { + EditorThemeUpdateListener, + StorySaveMediaListener { private static final String GUTENBERG_EDITOR_NAME = "gutenberg"; private static final String KEY_HTML_MODE_ENABLED = "KEY_HTML_MODE_ENABLED"; private static final String KEY_EDITOR_DID_MOUNT = "KEY_EDITOR_DID_MOUNT"; @@ -270,6 +272,14 @@ public void onQueryCurrentProgressForUploadingMedia() { updateMediaProgress(); } }, + new OnStorySavingReattachQueryListener() { + @Override public void onQueryCurrentProgressForStoryMediaSaving() { + // TODO: probably go through mFailedMediaIds, and see if any block in the post content + // has these mediaFIleIds. If there's a match, mark such a block in FAILED state. + updateFailedMediaState(); + updateMediaProgress(); + } + }, new OnEditorMountListener() { @Override public void onEditorDidMount(ArrayList unsupportedBlocks) { @@ -997,4 +1007,26 @@ public void onGalleryMediaUploadSucceeded(final long galleryId, long remoteMedia public void onEditorThemeUpdated(Bundle editorTheme) { getGutenbergContainerFragment().updateTheme(editorTheme); } + + @Override public void onMediaSaveReattached(String localId, float currentProgress) { + mUploadingMediaProgressMax.put(localId, currentProgress); + getGutenbergContainerFragment().mediaFileSaveProgress(Integer.valueOf(localId), currentProgress); + } + + @Override public void onMediaSaveSucceeded(String localId, MediaFile mediaFile) { + mUploadingMediaProgressMax.remove(localId); + getGutenbergContainerFragment().mediaFileSaveSucceeded(Integer.valueOf(localId), mediaFile.getFileURL(), + Integer.valueOf(mediaFile.getMediaId())); + } + + @Override public void onMediaSaveProgress(String localId, float progress) { + mUploadingMediaProgressMax.put(localId, progress); + getGutenbergContainerFragment().mediaFileSaveProgress(Integer.valueOf(localId), progress); + } + + @Override public void onMediaSaveFailed(String localId) { + getGutenbergContainerFragment().mediaFileSaveFailed(Integer.valueOf(localId)); + mFailedMediaIds.add(localId); + mUploadingMediaProgressMax.remove(localId); + } } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java new file mode 100644 index 000000000000..a7fa806713cb --- /dev/null +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java @@ -0,0 +1,10 @@ +package org.wordpress.android.editor.gutenberg; + +import org.wordpress.android.util.helpers.MediaFile; + +public interface StorySaveMediaListener { + void onMediaSaveReattached(String localId, float currentProgress); + void onMediaSaveSucceeded(String localId, MediaFile mediaFile); + void onMediaSaveProgress(String localId, float progress); + void onMediaSaveFailed(String localId); +} diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 00a0cc0b7e84..0dcfe93057eb 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 00a0cc0b7e849521595d428d5161dea557aa29e9 +Subproject commit 0dcfe93057eb868ced7edd5c4029ec95d2c05c8d From e532633ee37f282b810e01032a47a286fbcc8d41 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 21 Sep 2020 21:11:07 -0300 Subject: [PATCH 034/230] updated stories library commit hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index ffc024efceca..676da24d18e5 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit ffc024efcecaafe5055925ac9fb92e50e4fce453 +Subproject commit 676da24d18e560d609170e51893031c18a5f2a0e From 2a74a3580f8838a26b2100e91ba9283b859c7f4b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 22 Sep 2020 09:06:07 -0300 Subject: [PATCH 035/230] removed unused param constant key --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 2 -- .../android/editor/gutenberg/GutenbergEditorFragment.java | 1 - 2 files changed, 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index f43cb7361806..ed5ee07be6e7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -34,7 +34,6 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.PREPUBLISHING_BOTTOM_SHEET_OPENED import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_ID import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_UPDATED_CONTENT -import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel @@ -452,7 +451,6 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), getMediaFilesFromBackgroundMediaIdsInStory(storyIndex) ) savedContentIntent.putExtra(ARG_STORY_BLOCK_UPDATED_CONTENT, updatedStoryBlock) - savedContentIntent.putExtra(ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA, true) setResult(Activity.RESULT_OK, savedContentIntent) // TODO add tracks diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 3fe5f0b178e7..e2877088165d 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -89,7 +89,6 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements private static final String ARG_STORY_EDITOR_REQUEST_CODE = "param_sory_editor_request_code"; public static final String ARG_STORY_BLOCK_ID = "story_block_id"; public static final String ARG_STORY_BLOCK_UPDATED_CONTENT = "story_block_updated_content"; - public static final String ARG_STORY_STATUS_WAIT_FOR_FLATTENED_MEDIA = "status_wait_for_flattened_media"; private static final int CAPTURE_PHOTO_PERMISSION_REQUEST_CODE = 101; private static final int CAPTURE_VIDEO_PERMISSION_REQUEST_CODE = 102; From b545212b018425cb00993cfebc95f0f223d8a419 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 22 Sep 2020 09:06:56 -0300 Subject: [PATCH 036/230] added FrameSaveXyz status EventBus events for Story frame flattened media being saved --- .../android/ui/posts/EditPostActivity.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 0e5e833bd541..21e5b30f267a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -40,6 +40,10 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveCompleted; +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed; +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress; +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart; import com.wordpress.stories.compose.story.StoryRepository; import org.greenrobot.eventbus.EventBus; @@ -3081,6 +3085,59 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } } + // Story Frame Save Service events + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onStoryFrameSaveStart(FrameSaveStart event) { + if (isFinishing()) { + return; + } + String localMediaId = String.valueOf(event.getFrameId()); + if (mStoryEditorMediaSaveListener != null) { + mStoryEditorMediaSaveListener.onMediaSaveReattached(localMediaId, 0.0f); + } + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onStoryFrameSaveProgress(FrameSaveProgress event) { + if (isFinishing()) { + return; + } + String localMediaId = String.valueOf(event.getFrameId()); + if (mStoryEditorMediaSaveListener != null) { + mStoryEditorMediaSaveListener.onMediaSaveProgress(localMediaId, event.getProgress()); + } + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onStoryFrameSaveCompleted(FrameSaveCompleted event) { + if (isFinishing()) { + return; + } + String localMediaId = String.valueOf(event.getFrameId()); + if (mStoryEditorMediaSaveListener != null) { + MediaModel mediaModel = mMediaStore.getSiteMediaWithId(mSite, Long.parseLong(localMediaId)); + if (mediaModel != null) { + MediaFile mediaFile = FluxCUtils.mediaFileFromMediaModel(mediaModel); + mStoryEditorMediaSaveListener.onMediaSaveSucceeded(localMediaId, mediaFile); + } + } + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onStoryFrameSaveFailed(FrameSaveFailed event) { + if (isFinishing()) { + return; + } + String localMediaId = String.valueOf(event.getFrameId()); + if (mStoryEditorMediaSaveListener != null) { + mStoryEditorMediaSaveListener.onMediaSaveFailed(localMediaId); + } + } + // FluxC events @SuppressWarnings("unused") From baaad61feece01913108e95d8aa4d77fbc1857ee Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 23 Sep 2020 21:53:51 -0300 Subject: [PATCH 037/230] using StorySaveMediaListener and removed redundant interface StoryEditorMediaSaveListener --- .../android/ui/posts/EditPostActivity.java | 28 +++++++++---------- .../media/StoryEditorMediaSaveListener.kt | 10 ------- 2 files changed, 14 insertions(+), 24 deletions(-) delete mode 100644 WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 21e5b30f267a..483c01cc6c5a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -74,6 +74,7 @@ import org.wordpress.android.editor.gutenberg.GutenbergEditorFragment; import org.wordpress.android.editor.gutenberg.GutenbergPropsBuilder; import org.wordpress.android.editor.gutenberg.GutenbergWebViewAuthorizationData; +import org.wordpress.android.editor.gutenberg.StorySaveMediaListener; import org.wordpress.android.fluxc.Dispatcher; import org.wordpress.android.fluxc.action.AccountAction; import org.wordpress.android.fluxc.generated.AccountActionBuilder; @@ -167,7 +168,6 @@ import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; import org.wordpress.android.ui.stories.StoryRepositoryWrapper; -import org.wordpress.android.ui.stories.media.StoryEditorMediaSaveListener; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; @@ -334,7 +334,7 @@ enum RestartEditorOptions { private EditorFragmentAbstract mEditorFragment; private EditPostSettingsFragment mEditPostSettingsFragment; private EditorMediaUploadListener mEditorMediaUploadListener; - private StoryEditorMediaSaveListener mStoryEditorMediaSaveListener; + private StorySaveMediaListener mStorySaveMediaListener; private EditorPhotoPicker mEditorPhotoPicker; private ProgressDialog mProgressDialog; @@ -570,8 +570,8 @@ protected void onCreate(Bundle savedInstanceState) { mEditorMediaUploadListener = (EditorMediaUploadListener) mEditorFragment; } - if (mEditorFragment instanceof StoryEditorMediaSaveListener) { - mStoryEditorMediaSaveListener = (StoryEditorMediaSaveListener) mEditorFragment; + if (mEditorFragment instanceof StorySaveMediaListener) { + mStorySaveMediaListener = (StorySaveMediaListener) mEditorFragment; } } @@ -2153,8 +2153,8 @@ public Fragment getItem(int position) { reattachUploadingMediaForAztec(); } - if (mEditorFragment instanceof StoryEditorMediaSaveListener) { - mStoryEditorMediaSaveListener = (StoryEditorMediaSaveListener) mEditorFragment; + if (mEditorFragment instanceof StorySaveMediaListener) { + mStorySaveMediaListener = (StorySaveMediaListener) mEditorFragment; } break; case PAGE_SETTINGS: @@ -3093,8 +3093,8 @@ public void onStoryFrameSaveStart(FrameSaveStart event) { return; } String localMediaId = String.valueOf(event.getFrameId()); - if (mStoryEditorMediaSaveListener != null) { - mStoryEditorMediaSaveListener.onMediaSaveReattached(localMediaId, 0.0f); + if (mStorySaveMediaListener != null) { + mStorySaveMediaListener.onMediaSaveReattached(localMediaId, 0.0f); } } @@ -3105,8 +3105,8 @@ public void onStoryFrameSaveProgress(FrameSaveProgress event) { return; } String localMediaId = String.valueOf(event.getFrameId()); - if (mStoryEditorMediaSaveListener != null) { - mStoryEditorMediaSaveListener.onMediaSaveProgress(localMediaId, event.getProgress()); + if (mStorySaveMediaListener != null) { + mStorySaveMediaListener.onMediaSaveProgress(localMediaId, event.getProgress()); } } @@ -3117,11 +3117,11 @@ public void onStoryFrameSaveCompleted(FrameSaveCompleted event) { return; } String localMediaId = String.valueOf(event.getFrameId()); - if (mStoryEditorMediaSaveListener != null) { + if (mStorySaveMediaListener != null) { MediaModel mediaModel = mMediaStore.getSiteMediaWithId(mSite, Long.parseLong(localMediaId)); if (mediaModel != null) { MediaFile mediaFile = FluxCUtils.mediaFileFromMediaModel(mediaModel); - mStoryEditorMediaSaveListener.onMediaSaveSucceeded(localMediaId, mediaFile); + mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, mediaFile); } } } @@ -3133,8 +3133,8 @@ public void onStoryFrameSaveFailed(FrameSaveFailed event) { return; } String localMediaId = String.valueOf(event.getFrameId()); - if (mStoryEditorMediaSaveListener != null) { - mStoryEditorMediaSaveListener.onMediaSaveFailed(localMediaId); + if (mStorySaveMediaListener != null) { + mStorySaveMediaListener.onMediaSaveFailed(localMediaId); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt deleted file mode 100644 index 04715ef2cafd..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMediaSaveListener.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.wordpress.android.ui.stories.media - -import org.wordpress.android.util.helpers.MediaFile - -interface StoryEditorMediaSaveListener { - fun onMediaSaveReattached(localId: String?, currentProgress: Float) - fun onMediaSaveSucceeded(localId: String?, mediaFile: MediaFile?) - fun onMediaSaveProgress(localId: String?, progress: Float) - fun onMediaSaveFailed(localId: String?) -} From a2e5aaab7d80c6fe86d39e9e2579c9f499b1b0b8 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 23 Sep 2020 21:55:21 -0300 Subject: [PATCH 038/230] using made-up temporaryIds out of StoryIndex-FrameIndex to paint save progress states on Story blocks that are currently being processsed --- .../stories/SaveStoryGutenbergBlockUseCase.kt | 177 +++++++++++++----- .../ui/stories/StoryComposerActivity.kt | 39 ++-- .../media/StoryMediaSaveUploadBridge.kt | 7 + .../LoadStoryFromStoriesPrefsUseCase.kt | 1 + 4 files changed, 164 insertions(+), 60 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index e86876a16d80..fbd5da32f4f9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -29,14 +29,19 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { for (mediaFile in mediaFiles) { jsonArrayMediaFiles.add(buildMediaFileData(mediaFile)) } - val storyBlock = StoryBlockData(mediaFiles = jsonArrayMediaFiles) - return createGBStoryBlockStringFromJson(storyBlock) + return buildJetpackStoryBlockStringFromStoryMediaFileData(jsonArrayMediaFiles) + } + + fun buildJetpackStoryBlockStringFromStoryMediaFileData( + storyMediaFileDataList: ArrayList + ): String { + return createGBStoryBlockStringFromJson(StoryBlockData(mediaFiles = storyMediaFileDataList)) } private fun buildMediaFileData(mediaFile: MediaFile): StoryMediaFileData { return StoryMediaFileData( alt = "", - id = mediaFile.id, + id = mediaFile.id.toString(), link = StringUtils.notNullStr(mediaFile.fileURL), type = if (mediaFile.isVideo) "video" else "image", mime = StringUtils.notNullStr(mediaFile.mimeType), @@ -45,52 +50,123 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { ) } - fun replaceLocalMediaIdsWithRemoteMediaIdsInPost(post: PostModel, mediaFile: MediaFile) { - // here we're going to first find the block header, obtain the JSON object, re-parse it, and re-build the block - // WARNING note we're assuming to have only one Story block here so, beware of that!! this will find - // the first match only, always. (shouldn't be a problem because we're always creating a new Post in the - // app, but this won't make the cut if we decide to allow editing. Which we'll do by integrating with - // the gutenberg parser / validator anyway. - val content = post.content - val jsonString: String = content.substring( - content.indexOf(HEADING_START) + HEADING_START.length, - content.indexOf(HEADING_END) + fun buildMediaFileDataWithTemporaryId(mediaFile: MediaFile, temporaryId: String): StoryMediaFileData { + return StoryMediaFileData( + alt = "", // notation abuse: we're repurposing this field to + // hold a temporaryId + id = TEMPORARY_ID_PREFIX + temporaryId, // mediaFile.id, + link = StringUtils.notNullStr(mediaFile.fileURL), + type = if (mediaFile.isVideo) "video" else "image", + mime = StringUtils.notNullStr(mediaFile.mimeType), + caption = "", + url = StringUtils.notNullStr(mediaFile.fileURL) ) - val gson = Gson() - val storyBlockData: StoryBlockData? = gson.fromJson(jsonString, StoryBlockData::class.java) - - val localMediaId = mediaFile.id - // now replace matching localMediaId with remoteMediaId in the mediaFileObjects, obtain the URLs and replace - storyBlockData?.mediaFiles?.filter { it.id == localMediaId }?.get(0)?.apply { - id = mediaFile.mediaId.toInt() - link = mediaFile.fileURL - url = mediaFile.fileURL - - // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. - val localIdKey = mediaFile.id.toLong() - val remoteIdKey = mediaFile.mediaId.toLong() - val localSiteId = post.localSiteId.toLong() - StoriesPrefs.getSlideWithLocalId( - WordPress.getContext(), - localSiteId, - LocalMediaId(localIdKey) - )?.let { - it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID - StoriesPrefs.saveSlideWithRemoteId( - WordPress.getContext(), - localSiteId, - RemoteMediaId(remoteIdKey), // use the new mediaId as key - it - ) - // now delete the old entry - StoriesPrefs.deleteSlideWithLocalId( - WordPress.getContext(), - localSiteId, - LocalMediaId(localIdKey) - ) + } + + fun cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost(editPostRepository: EditPostRepository) { + editPostRepository.update { postModel: PostModel -> + val gson = Gson() + findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( + postModel, + object : DoWithMediaFilesListener { + override fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String { + var processedContent = content + val storyBlockData: StoryBlockData? + = gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) + storyBlockData?.let { + if (hasTemporaryIdsInStoryData(it)) { + // here remove the whole mediaFiles attribute + processedContent = content.replace(mediaFilesJsonString, "") + } + } + return processedContent + } + } + ) + true + } + } + + private fun hasTemporaryIdsInStoryData(storyBlockData: StoryBlockData): Boolean { + val temporaryIds = storyBlockData.mediaFiles.filter { + it.alt.startsWith(TEMPORARY_ID_PREFIX) + } + return temporaryIds.size > 0 + } + + fun findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( + postModel: PostModel, + listener: DoWithMediaFilesListener + ) { + var content = postModel.content + // val contentMutable = StringBuilder(postModel.content) + + // find next Story Block + // evaluate if this has a temporary id mediafile + // --> remove mediaFiles entirely + // set start index and go up. + var storyBlockStartIndex = 0 + while (storyBlockStartIndex > -1 && storyBlockStartIndex < content.length) { + storyBlockStartIndex = content.indexOf(HEADING_START, storyBlockStartIndex) + if (storyBlockStartIndex > -1) { + val jsonString: String = content.substring( + storyBlockStartIndex + HEADING_START.length, + content.indexOf(HEADING_END)) + content = listener.doWithMediaFilesJsonString(content, jsonString) + storyBlockStartIndex += HEADING_START.length } } - post.setContent(createGBStoryBlockStringFromJson(requireNotNull(storyBlockData))) + + postModel.setContent(content) + } + + fun replaceLocalMediaIdsWithRemoteMediaIdsInPost(postModel: PostModel, mediaFile: MediaFile) { + val gson = Gson() + findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( + postModel, + object : DoWithMediaFilesListener { + override fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String { + var processedContent = content + val storyBlockData: StoryBlockData? + = gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) + storyBlockData?.let { storyBlockDataNonNull -> + val localMediaId = mediaFile.id.toString() + // now replace matching localMediaId with remoteMediaId in the mediaFileObjects, obtain the URLs and replace + storyBlockDataNonNull.mediaFiles?.filter { it.id == localMediaId }?.get(0)?.apply { + id = mediaFile.mediaId + link = mediaFile.fileURL + url = mediaFile.fileURL + + // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. + val localIdKey = mediaFile.id.toLong() + val remoteIdKey = mediaFile.mediaId.toLong() + val localSiteId = postModel.localSiteId.toLong() + StoriesPrefs.getSlideWithLocalId( + WordPress.getContext(), + localSiteId, + LocalMediaId(localIdKey) + )?.let { + it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID + StoriesPrefs.saveSlideWithRemoteId( + WordPress.getContext(), + localSiteId, + RemoteMediaId(remoteIdKey), // use the new mediaId as key + it + ) + // now delete the old entry + StoriesPrefs.deleteSlideWithLocalId( + WordPress.getContext(), + localSiteId, + LocalMediaId(localIdKey) + ) + } + } + processedContent = content.replace(mediaFilesJsonString, gson.toJson(storyBlockDataNonNull)) + } + return processedContent + } + } + ) } private fun createGBStoryBlockStringFromJson(storyBlock: StoryBlockData): String { @@ -98,13 +174,17 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { return HEADING_START + gson.toJson(storyBlock) + HEADING_END + DIV_PART + CLOSING_TAG } + interface DoWithMediaFilesListener { + fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String + } + data class StoryBlockData( val mediaFiles: List ) data class StoryMediaFileData( - val alt: String, - var id: Int, + var alt: String, + var id: String, var link: String, val type: String, val mime: String, @@ -113,6 +193,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { ) companion object { + const val TEMPORARY_ID_PREFIX = "tempid-" const val HEADING_START = "\n" const val DIV_PART = "
\n" diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index ed5ee07be6e7..6efdc7a8f549 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -22,6 +22,7 @@ import com.wordpress.stories.compose.PrepublishingEventProvider import com.wordpress.stories.compose.SnackbarProvider import com.wordpress.stories.compose.StoryDiscardListener import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import com.wordpress.stories.compose.story.StoryFrameItemType.VIDEO import com.wordpress.stories.compose.story.StoryIndex import com.wordpress.stories.compose.story.StoryRepository import com.wordpress.stories.compose.story.StoryRepository.DEFAULT_NONE_SELECTED @@ -60,12 +61,14 @@ import org.wordpress.android.ui.posts.PublishPost import org.wordpress.android.ui.posts.editor.media.AddExistingMediaSource.WP_MEDIA_LIBRARY import org.wordpress.android.ui.posts.editor.media.EditorMediaListener import org.wordpress.android.ui.posts.prepublishing.PrepublishingBottomSheetListener +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.StoryMediaFileData import org.wordpress.android.ui.stories.media.StoryEditorMedia import org.wordpress.android.ui.stories.media.StoryEditorMedia.AddMediaToStoryPostUiState import org.wordpress.android.ui.utils.AuthenticationUtils import org.wordpress.android.ui.utils.UiHelpers import org.wordpress.android.util.FluxCUtilsWrapper import org.wordpress.android.util.ListUtils +import org.wordpress.android.util.StringUtils import org.wordpress.android.util.WPMediaUtils import org.wordpress.android.util.WPPermissionUtils import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper @@ -446,10 +449,18 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) val storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) + // if we are editing this Story Block, then the id is assured to be a remote media file id, but + // the frame no longer points to such media Id on the site given we are just about to save a + // new flattened media. Hence, we need to set a new temporary Id we can use to identify + // this frame within the Gutenberg Story block inside a Post, and match it to an existing Story frame in + // our StoryRepository. + // All of this while still keeping a valid "old" remote URl and mediaId so the block is still + // rendered as non-empty on mobile gutenberg while the actual flattening happens on the service. val updatedStoryBlock = - saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockString( - getMediaFilesFromBackgroundMediaIdsInStory(storyIndex) + saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockStringFromStoryMediaFileData( + buildStoryMediaFileDataListFromStoryFrameIndexes(storyIndex) ) + savedContentIntent.putExtra(ARG_STORY_BLOCK_UPDATED_CONTENT, updatedStoryBlock) setResult(Activity.RESULT_OK, savedContentIntent) @@ -463,23 +474,27 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } } - private fun getMediaFilesFromBackgroundMediaIdsInStory(storyIdx: StoryIndex): List { - val mediaFiles = ArrayList() - val story = StoryRepository.getStoryAtIndex(storyIdx) - for (frame in story.frames) { + private fun buildStoryMediaFileDataListFromStoryFrameIndexes( + storyIndex: StoryIndex + ): ArrayList { + val storyMediaFileDataList = ArrayList() // holds media files + val story = StoryRepository.getStoryAtIndex(storyIndex) + for ((frameIndex, frame) in story.frames.withIndex()) { frame.id?.let { - // WARNING: we assume the only path to creation is by using the Story Creator (not mobile gutenberg - // by inserting a new block from the block picker) so, we ALWAYS should have a remote mediaId - // here. If things change, we'll need to cover the situation for finding a MediaModel from both - // a local ID (if not yet uploaded to the site) and a remote ID (after uploading to the site). val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) mediaFile?.let { - mediaFiles.add(it) + val storyMediaFileData = + saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( + mediaFile = it, + temporaryId = "$storyIndex-$frameIndex" + ) + frame.id = storyMediaFileData.id + storyMediaFileDataList.add(storyMediaFileData) } } } - return mediaFiles + return storyMediaFileDataList } override fun onSubmitButtonClicked(publishPost: PublishPost) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 2ccba4300b4a..5d859c59ee2d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -199,6 +199,13 @@ class StoryMediaSaveUploadBridge @Inject constructor( event.metadata?.let { val site = it.getSerializable(WordPress.SITE) as SiteModel editPostRepository.loadPostByLocalPostId(it.getInt(StoryComposerActivity.KEY_POST_LOCAL_ID)) + if (event.isEditMode) { + // we're done using the temporary ids, let's clean mediaFiles attribute from the blocks that have + // those + saveStoryGutenbergBlockUseCase.cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost( + editPostRepository + ) + } // media upload tracking already in addLocalMediaToPostUseCase.addNewMediaToEditorAsync addNewStoryFrameMediaItemsToPostAndUploadAsync(site, event) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index ca3fe97647a5..a4521e1cd8bc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -9,6 +9,7 @@ import dagger.Reusable import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId import org.wordpress.android.ui.stories.prefs.StoriesPrefs.getSlideWithRemoteId From e5adabf6d0ac27dbf04771ff312ea0b380f34ad3 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 24 Sep 2020 08:14:35 -0300 Subject: [PATCH 039/230] made changes to support String mediaIds as opposed to ints, so we can repurpose them and also hold temporary-prefixed mediaIds while saving --- .../android/ui/posts/EditPostActivity.java | 26 ++++++++++++++----- .../ui/stories/StoryRepositoryWrapper.kt | 1 + .../gutenberg/GutenbergContainerFragment.java | 10 +++---- .../gutenberg/GutenbergEditorFragment.java | 11 ++++---- .../gutenberg/StorySaveMediaListener.java | 4 +-- libs/gutenberg-mobile | 2 +- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 483c01cc6c5a..77a14621b2e5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -44,6 +44,7 @@ import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart; +import com.wordpress.stories.compose.story.StoryFrameItem; import com.wordpress.stories.compose.story.StoryRepository; import org.greenrobot.eventbus.EventBus; @@ -236,6 +237,7 @@ import static org.wordpress.android.analytics.AnalyticsTracker.Stat.APP_REVIEWS_EVENT_INCREMENTED_BY_PUBLISHING_POST_OR_PAGE; import static org.wordpress.android.imageeditor.preview.PreviewImageFragment.PREVIEW_IMAGE_REDUCED_SIZE_FACTOR; import static org.wordpress.android.ui.history.HistoryDetailContainerFragment.KEY_REVISION; +import static org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.TEMPORARY_ID_PREFIX; import kotlin.Unit; import kotlin.jvm.functions.Function0; @@ -391,6 +393,7 @@ enum RestartEditorOptions { @Inject ModalLayoutPickerFeatureConfig mModalLayoutPickerFeatureConfig; @Inject CrashLogging mCrashLogging; @Inject MediaPickerLauncher mMediaPickerLauncher; + @Inject StoryRepositoryWrapper mStoryRepositoryWrapper; private StorePostViewModel mViewModel; @@ -3035,7 +3038,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { LoadStoryFromStoriesPrefsUseCase loadStoryFromStoriesPrefsUseCase = new LoadStoryFromStoriesPrefsUseCase( - new StoryRepositoryWrapper(), + mStoryRepositoryWrapper, mSite, mMediaStore, this @@ -3116,12 +3119,23 @@ public void onStoryFrameSaveCompleted(FrameSaveCompleted event) { if (isFinishing()) { return; } - String localMediaId = String.valueOf(event.getFrameId()); + String localMediaId = event.getFrameId(); if (mStorySaveMediaListener != null) { - MediaModel mediaModel = mMediaStore.getSiteMediaWithId(mSite, Long.parseLong(localMediaId)); - if (mediaModel != null) { - MediaFile mediaFile = FluxCUtils.mediaFileFromMediaModel(mediaModel); - mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, mediaFile); + // check whether this is a temporary file being just saved (so we don't have a proper local MediaModel yet) + // catch ( NumberFormatException e) + if (localMediaId.startsWith(TEMPORARY_ID_PREFIX)) { + StoryFrameItem frame = + mStoryRepositoryWrapper.getStoryAtIndex( + event.getStoryIndex()).getFrames().get(event.getFrameIndex() + ); + mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, + frame.getComposedFrameFile().getAbsolutePath()); + } else { + MediaModel mediaModel = mMediaStore.getSiteMediaWithId(mSite, Long.parseLong(localMediaId)); + if (mediaModel != null) { + MediaFile mediaFile = FluxCUtils.mediaFileFromMediaModel(mediaModel); + mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, mediaFile.getFileURL()); + } } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt index 7b89cea9bbda..f735e71a50d7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt @@ -12,4 +12,5 @@ class StoryRepositoryWrapper @Inject constructor() { fun getCurrentStoryIndex(): StoryIndex = StoryRepository.currentStoryIndex fun loadStory(storyIndex: StoryIndex) = StoryRepository.loadStory(storyIndex) fun addStoryFrameItemToCurrentStory(item: StoryFrameItem) = StoryRepository.addStoryFrameItemToCurrentStory(item) + fun getStoryAtIndex(index: StoryIndex) = StoryRepository.getStoryAtIndex(index) } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 690a76110e06..4bf0e1b587df 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -222,19 +222,19 @@ public void updateCapabilities(GutenbergPropsBuilder gutenbergPropsBuilder) { mWPAndroidGlueCode.updateCapabilities(gutenbergProps); } - public void clearFileSaveStatus(final int mediaId) { + public void clearFileSaveStatus(final String mediaId) { mWPAndroidGlueCode.clearFileSaveStatus(mediaId); } - public void mediaFileSaveProgress(final int mediaId, final float progress) { + public void mediaFileSaveProgress(final String mediaId, final float progress) { mWPAndroidGlueCode.mediaFileSaveProgress(mediaId, progress); } - public void mediaFileSaveFailed(final int mediaId) { + public void mediaFileSaveFailed(final String mediaId) { mWPAndroidGlueCode.mediaFileSaveFailed(mediaId); } - public void mediaFileSaveSucceeded(final int mediaId, final String mediaUrl, final int serverMediaId) { - mWPAndroidGlueCode.mediaFileSaveSucceeded(mediaId, mediaUrl, serverMediaId); + public void mediaFileSaveSucceeded(final String mediaId, final String mediaUrl) { + mWPAndroidGlueCode.mediaFileSaveSucceeded(mediaId, mediaUrl); } } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index e2877088165d..f6834f4e8415 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -1009,22 +1009,21 @@ public void onEditorThemeUpdated(Bundle editorTheme) { @Override public void onMediaSaveReattached(String localId, float currentProgress) { mUploadingMediaProgressMax.put(localId, currentProgress); - getGutenbergContainerFragment().mediaFileSaveProgress(Integer.valueOf(localId), currentProgress); + getGutenbergContainerFragment().mediaFileSaveProgress(localId, currentProgress); } - @Override public void onMediaSaveSucceeded(String localId, MediaFile mediaFile) { + @Override public void onMediaSaveSucceeded(String localId, String mediaUrl) { mUploadingMediaProgressMax.remove(localId); - getGutenbergContainerFragment().mediaFileSaveSucceeded(Integer.valueOf(localId), mediaFile.getFileURL(), - Integer.valueOf(mediaFile.getMediaId())); + getGutenbergContainerFragment().mediaFileSaveSucceeded(localId, mediaUrl); } @Override public void onMediaSaveProgress(String localId, float progress) { mUploadingMediaProgressMax.put(localId, progress); - getGutenbergContainerFragment().mediaFileSaveProgress(Integer.valueOf(localId), progress); + getGutenbergContainerFragment().mediaFileSaveProgress(localId, progress); } @Override public void onMediaSaveFailed(String localId) { - getGutenbergContainerFragment().mediaFileSaveFailed(Integer.valueOf(localId)); + getGutenbergContainerFragment().mediaFileSaveFailed(localId); mFailedMediaIds.add(localId); mUploadingMediaProgressMax.remove(localId); } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java index a7fa806713cb..0872141119bd 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java @@ -1,10 +1,8 @@ package org.wordpress.android.editor.gutenberg; -import org.wordpress.android.util.helpers.MediaFile; - public interface StorySaveMediaListener { void onMediaSaveReattached(String localId, float currentProgress); - void onMediaSaveSucceeded(String localId, MediaFile mediaFile); + void onMediaSaveSucceeded(String localId, String mediaUrl); void onMediaSaveProgress(String localId, float progress); void onMediaSaveFailed(String localId); } diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 0dcfe93057eb..1697f9f731f5 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 0dcfe93057eb868ced7edd5c4029ec95d2c05c8d +Subproject commit 1697f9f731f5f31822dac08e86c1f499f7306c34 From 3db323532dd78d6e9b5331efc39f7e3f2a37e845 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 24 Sep 2020 08:32:04 -0300 Subject: [PATCH 040/230] using StoryRepositoryWrapper so it's injectable and lets StoryMediaSaveUploadBridge in good testability state --- .../android/ui/stories/StoryRepositoryWrapper.kt | 1 + .../ui/stories/media/StoryMediaSaveUploadBridge.kt | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt index f735e71a50d7..16d21f948df1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt @@ -13,4 +13,5 @@ class StoryRepositoryWrapper @Inject constructor() { fun loadStory(storyIndex: StoryIndex) = StoryRepository.loadStory(storyIndex) fun addStoryFrameItemToCurrentStory(item: StoryFrameItem) = StoryRepository.addStoryFrameItemToCurrentStory(item) fun getStoryAtIndex(index: StoryIndex) = StoryRepository.getStoryAtIndex(index) + fun getImmutableStories() = StoryRepository.getImmutableStories() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 5d859c59ee2d..38bebbd89391 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -8,7 +8,6 @@ import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.OnLifecycleEvent import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult -import com.wordpress.stories.compose.story.StoryRepository import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -29,6 +28,7 @@ import org.wordpress.android.ui.posts.editor.media.EditorMediaListener import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase import org.wordpress.android.ui.stories.StoriesTrackerHelper import org.wordpress.android.ui.stories.StoryComposerActivity +import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs import org.wordpress.android.ui.stories.prefs.StoriesPrefs.LocalMediaId import org.wordpress.android.ui.uploads.UploadServiceFacade @@ -54,6 +54,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( private val networkUtils: NetworkUtilsWrapper, private val postUtils: PostUtilsWrapper, private val eventBusWrapper: EventBusWrapper, + private val storyRepositoryWrapper: StoryRepositoryWrapper, @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher ) : CoroutineScope, LifecycleObserver { // region Fields @@ -90,7 +91,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( // region Adding new composed / processed frames to a Story post private fun addNewStoryFrameMediaItemsToPostAndUploadAsync(site: SiteModel, saveResult: StorySaveResult) { // let's invoke the UploadService and enqueue all the files that were saved by the FrameSaveService - val frames = StoryRepository.getStoryAtIndex(saveResult.storyIndex).frames + val frames = storyRepositoryWrapper.getStoryAtIndex(saveResult.storyIndex).frames val uriList = frames.map { Uri.fromFile(it.composedFrameFile) } addNewMediaItemsToPostAsync(site, uriList, saveResult.isEditMode) } @@ -130,7 +131,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( // here we change the ids on the actual StoryFrameItems, and also update the flattened / composed image // urls with the new URLs which may have been replaced after image optimization - for (story in StoryRepository.getImmutableStories()) { + for (story in storyRepositoryWrapper.getImmutableStories()) { // find the MediaModel for a given Uri from composedFrameFile for (frame in story.frames) { // if the old URI in frame.composedFrameFile exists as a key in the passed map, then update that @@ -214,6 +215,6 @@ class StoryMediaSaveUploadBridge @Inject constructor( private fun isStorySavingComplete(event: StorySaveResult): Boolean { return (event.isSuccess() && - event.frameSaveResult.size == StoryRepository.getStoryAtIndex(event.storyIndex).frames.size) + event.frameSaveResult.size == storyRepositoryWrapper.getStoryAtIndex(event.storyIndex).frames.size) } } From d2af486bcc02a8739b95944d959e0d84d5c7a26e Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 25 Sep 2020 10:43:03 -0300 Subject: [PATCH 041/230] updated gutenberg-mobile commit hash, also passing overall story save progress calculation in progress event --- .../android/ui/posts/EditPostActivity.java | 20 +++++++++++++++---- libs/gutenberg-mobile | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 77a14621b2e5..693a40fe42b2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -40,10 +40,12 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; +import com.wordpress.stories.compose.frame.StorySaveEvents; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveCompleted; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart; +import com.wordpress.stories.compose.story.Story; import com.wordpress.stories.compose.story.StoryFrameItem; import com.wordpress.stories.compose.story.StoryRepository; @@ -3124,12 +3126,22 @@ public void onStoryFrameSaveCompleted(FrameSaveCompleted event) { // check whether this is a temporary file being just saved (so we don't have a proper local MediaModel yet) // catch ( NumberFormatException e) if (localMediaId.startsWith(TEMPORARY_ID_PREFIX)) { - StoryFrameItem frame = - mStoryRepositoryWrapper.getStoryAtIndex( - event.getStoryIndex()).getFrames().get(event.getFrameIndex() - ); + Story story = mStoryRepositoryWrapper.getStoryAtIndex(event.getStoryIndex()); + StoryFrameItem frame = story.getFrames().get(event.getFrameIndex()); mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, frame.getComposedFrameFile().getAbsolutePath()); + + // calculate progress and emit overall story progress update signal + int successCount = 0; + for (StoryFrameItem frameItem : story.getFrames()) { + if (frameItem.getComposedFrameFile() != null + && frameItem.getSaveResultReason() instanceof StorySaveEvents.SaveResultReason.SaveSuccess) { + successCount++; + } + } + + float totalProgress = successCount / story.getFrames().size(); + mStorySaveMediaListener.onMediaSaveProgress(localMediaId, totalProgress); } else { MediaModel mediaModel = mMediaStore.getSiteMediaWithId(mSite, Long.parseLong(localMediaId)); if (mediaModel != null) { diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 1697f9f731f5..7e0dc26f505b 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 1697f9f731f5f31822dac08e86c1f499f7306c34 +Subproject commit 7e0dc26f505ba096cf8f3da27b3f806f18fb8827 From 5874a4863187b3393a3274ce9a242396e0ac55e8 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 25 Sep 2020 16:08:50 -0300 Subject: [PATCH 042/230] added progress calculation and progress calls --- .../android/ui/posts/EditPostActivity.java | 58 ++++++++++++++----- .../ui/stories/StoryRepositoryWrapper.kt | 2 + libs/stories-android | 2 +- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 693a40fe42b2..9f3578ec9ec1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -45,6 +45,7 @@ import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart; +import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult; import com.wordpress.stories.compose.story.Story; import com.wordpress.stories.compose.story.StoryFrameItem; import com.wordpress.stories.compose.story.StoryRepository; @@ -3099,7 +3100,8 @@ public void onStoryFrameSaveStart(FrameSaveStart event) { } String localMediaId = String.valueOf(event.getFrameId()); if (mStorySaveMediaListener != null) { - mStorySaveMediaListener.onMediaSaveReattached(localMediaId, 0.0f); + float progress = mStoryRepositoryWrapper.getCurrentStorySaveProgress(event.getStoryIndex(), 0.0f); + mStorySaveMediaListener.onMediaSaveReattached(localMediaId, progress); } } @@ -3111,7 +3113,11 @@ public void onStoryFrameSaveProgress(FrameSaveProgress event) { } String localMediaId = String.valueOf(event.getFrameId()); if (mStorySaveMediaListener != null) { - mStorySaveMediaListener.onMediaSaveProgress(localMediaId, event.getProgress()); + float progress = mStoryRepositoryWrapper.getCurrentStorySaveProgress( + event.getStoryIndex(), + event.getProgress() + ); + mStorySaveMediaListener.onMediaSaveProgress(localMediaId, progress); } } @@ -3127,20 +3133,14 @@ public void onStoryFrameSaveCompleted(FrameSaveCompleted event) { // catch ( NumberFormatException e) if (localMediaId.startsWith(TEMPORARY_ID_PREFIX)) { Story story = mStoryRepositoryWrapper.getStoryAtIndex(event.getStoryIndex()); + + // first, update the media's url StoryFrameItem frame = story.getFrames().get(event.getFrameIndex()); mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, - frame.getComposedFrameFile().getAbsolutePath()); - - // calculate progress and emit overall story progress update signal - int successCount = 0; - for (StoryFrameItem frameItem : story.getFrames()) { - if (frameItem.getComposedFrameFile() != null - && frameItem.getSaveResultReason() instanceof StorySaveEvents.SaveResultReason.SaveSuccess) { - successCount++; - } - } + Uri.fromFile(frame.getComposedFrameFile()).toString()); - float totalProgress = successCount / story.getFrames().size(); + // now update progress + float totalProgress = mStoryRepositoryWrapper.getCurrentStorySaveProgress(event.getStoryIndex(), 0.0f); mStorySaveMediaListener.onMediaSaveProgress(localMediaId, totalProgress); } else { MediaModel mediaModel = mMediaStore.getSiteMediaWithId(mSite, Long.parseLong(localMediaId)); @@ -3159,8 +3159,38 @@ public void onStoryFrameSaveFailed(FrameSaveFailed event) { return; } String localMediaId = String.valueOf(event.getFrameId()); +// if (mStorySaveMediaListener != null) { +// mStorySaveMediaListener.onMediaSaveFailed(localMediaId); +// } + // just update progress, we may have still some other frames in this story that need be saved. + // we will send the Failed signal once all the Story frames have been processed if (mStorySaveMediaListener != null) { - mStorySaveMediaListener.onMediaSaveFailed(localMediaId); + float progress = mStoryRepositoryWrapper.getCurrentStorySaveProgress(event.getStoryIndex(), 0.0f); + mStorySaveMediaListener.onMediaSaveReattached(localMediaId, progress); + } + } + + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onStorySaveProcessFinished(StorySaveResult event) { + if (isFinishing()) { + return; + } + + Story story = mStoryRepositoryWrapper.getStoryAtIndex(event.getStoryIndex()); + if (event.isSuccess() && event.getFrameSaveResult().size() == story.getFrames().size()) { + // take the first frame IDs and mediaUri + String localMediaId = String.valueOf(story.getFrames().get(0).getId()); + String mediaUrl = Uri.fromFile(story.getFrames().get(0).getComposedFrameFile()).toString(); + if (mStorySaveMediaListener != null) { + mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, mediaUrl); + } + } else { + String localMediaId = String.valueOf(story.getFrames().get(0).getId()); + if (mStorySaveMediaListener != null) { + mStorySaveMediaListener.onMediaSaveFailed(localMediaId); + } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt index 16d21f948df1..d5846c8652b7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt @@ -14,4 +14,6 @@ class StoryRepositoryWrapper @Inject constructor() { fun addStoryFrameItemToCurrentStory(item: StoryFrameItem) = StoryRepository.addStoryFrameItemToCurrentStory(item) fun getStoryAtIndex(index: StoryIndex) = StoryRepository.getStoryAtIndex(index) fun getImmutableStories() = StoryRepository.getImmutableStories() + fun getCurrentStorySaveProgress(storyIndex: StoryIndex, oneItemActualProgress: Float = 0.0F) + = StoryRepository.getCurrentStorySaveProgress(storyIndex, oneItemActualProgress) } diff --git a/libs/stories-android b/libs/stories-android index 676da24d18e5..823ab8aa66f0 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 676da24d18e560d609170e51893031c18a5f2a0e +Subproject commit 823ab8aa66f065f32fa69f66260569bce6ae7cee From fcef7a815c10c12ee499df0908f4231131acd1b5 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 25 Sep 2020 17:15:07 -0300 Subject: [PATCH 043/230] implemented new onStorySaveResult gutenberg bridge method --- .../android/editor/gutenberg/GutenbergContainerFragment.java | 4 ++++ .../android/editor/gutenberg/GutenbergEditorFragment.java | 4 ++++ .../android/editor/gutenberg/StorySaveMediaListener.java | 1 + libs/gutenberg-mobile | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 4bf0e1b587df..c93e8d6ba4cf 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -237,4 +237,8 @@ public void mediaFileSaveFailed(final String mediaId) { public void mediaFileSaveSucceeded(final String mediaId, final String mediaUrl) { mWPAndroidGlueCode.mediaFileSaveSucceeded(mediaId, mediaUrl); } + + public void onStorySaveResult(final String storyFirstMediaId, final boolean success) { + mWPAndroidGlueCode.storySaveResult(storyFirstMediaId, success); + } } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index f6834f4e8415..0cdb2daeeaea 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -1027,4 +1027,8 @@ public void onEditorThemeUpdated(Bundle editorTheme) { mFailedMediaIds.add(localId); mUploadingMediaProgressMax.remove(localId); } + + @Override public void onStorySaveResult(String storyFirstMediaId, boolean success) { + getGutenbergContainerFragment().onStorySaveResult(storyFirstMediaId, success); + } } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java index 0872141119bd..bd8fe7f362bc 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java @@ -5,4 +5,5 @@ public interface StorySaveMediaListener { void onMediaSaveSucceeded(String localId, String mediaUrl); void onMediaSaveProgress(String localId, float progress); void onMediaSaveFailed(String localId); + void onStorySaveResult(String storyFirstMediaId, boolean success); } diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 7e0dc26f505b..888d6c8dd0b3 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 7e0dc26f505ba096cf8f3da27b3f806f18fb8827 +Subproject commit 888d6c8dd0b387c5058a00e109d02973dfd9eeb1 From edbc1e7bf32b430ce3202c787234501f0e2af826 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 28 Sep 2020 15:53:27 -0300 Subject: [PATCH 044/230] udpated commit hash for gutenberg mobile with stories block update --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 888d6c8dd0b3..4cae822a707c 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 888d6c8dd0b387c5058a00e109d02973dfd9eeb1 +Subproject commit 4cae822a707c65bbcda7b5b517ca2a035e90dca0 From 83a977ed91c5adaa4956c5f2b024e40ddb305028 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 28 Sep 2020 19:55:01 -0300 Subject: [PATCH 045/230] added StoryFrameMediaModelCreatedEvent event to signal Gutenberg of the new MediaModel id for a given Story frame, and implemented the new bridge method onMediaModelCreated --- .../android/ui/posts/EditPostActivity.java | 13 ++++++++++++ .../media/StoryMediaSaveUploadBridge.kt | 20 ++++++++++++++++++- .../gutenberg/GutenbergContainerFragment.java | 4 ++++ .../gutenberg/GutenbergEditorFragment.java | 4 ++++ .../gutenberg/StorySaveMediaListener.java | 1 + libs/gutenberg-mobile | 2 +- 6 files changed, 42 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 9f3578ec9ec1..3b57b8da8291 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -172,6 +172,7 @@ import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; import org.wordpress.android.ui.stories.StoryRepositoryWrapper; +import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; @@ -3152,6 +3153,18 @@ public void onStoryFrameSaveCompleted(FrameSaveCompleted event) { } } + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onStoryFrameMediaModelCreated(StoryFrameMediaModelCreatedEvent event) { + if (isFinishing()) { + return; + } + + if (mStorySaveMediaListener != null) { + mStorySaveMediaListener.onMediaModelCreatedForFile(event.getOldId(), event.getNewId(), event.getOldUrl()); + } + } + @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onStoryFrameSaveFailed(FrameSaveFailed event) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 38bebbd89391..ea539f176ae0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode.MAIN import org.wordpress.android.WordPress @@ -136,8 +137,10 @@ class StoryMediaSaveUploadBridge @Inject constructor( for (frame in story.frames) { // if the old URI in frame.composedFrameFile exists as a key in the passed map, then update that // value with the new (probably optimized) URL and also keep track of the new id. - val mediaModel = oldUriToMediaFiles.get(Uri.fromFile(frame.composedFrameFile)) + val oldUri = Uri.fromFile(frame.composedFrameFile) + val mediaModel = oldUriToMediaFiles.get(oldUri) mediaModel?.let { + val oldTemporaryId = frame.id ?: "" frame.id = it.id.toString() StoriesPrefs.saveSlideWithLocalId( appContext, @@ -147,6 +150,19 @@ class StoryMediaSaveUploadBridge @Inject constructor( LocalMediaId(it.id.toLong()), frame ) + + // for editMode, we'll need to tell the Gutenberg Editor to replace their mediaFiles + // ids with the new MediaModel local ids so, broadcasting the event. + if (isEditMode) { + // finally send the event that this frameId has changed + EventBus.getDefault().post( + StoryFrameMediaModelCreatedEvent( + oldTemporaryId, + it.id.toString(), + oldUri.toString() + ) + ) + } } } } @@ -217,4 +233,6 @@ class StoryMediaSaveUploadBridge @Inject constructor( return (event.isSuccess() && event.frameSaveResult.size == storyRepositoryWrapper.getStoryAtIndex(event.storyIndex).frames.size) } + + data class StoryFrameMediaModelCreatedEvent (val oldId: String, val newId: String, val oldUrl: String) } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index c93e8d6ba4cf..ead028c13fe2 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -241,4 +241,8 @@ public void mediaFileSaveSucceeded(final String mediaId, final String mediaUrl) public void onStorySaveResult(final String storyFirstMediaId, final boolean success) { mWPAndroidGlueCode.storySaveResult(storyFirstMediaId, success); } + + public void onMediaModelCreatedForFile(String oldId, String newId, String oldUrl) { + mWPAndroidGlueCode.mediaModelCreatedForFile(oldId, newId, oldUrl); + } } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 0cdb2daeeaea..8e623b23da48 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -1031,4 +1031,8 @@ public void onEditorThemeUpdated(Bundle editorTheme) { @Override public void onStorySaveResult(String storyFirstMediaId, boolean success) { getGutenbergContainerFragment().onStorySaveResult(storyFirstMediaId, success); } + + @Override public void onMediaModelCreatedForFile(String oldId, String newId, String oldUrl) { + getGutenbergContainerFragment().onMediaModelCreatedForFile(oldId, newId, oldUrl); + } } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java index bd8fe7f362bc..40eec3651fe7 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/StorySaveMediaListener.java @@ -6,4 +6,5 @@ public interface StorySaveMediaListener { void onMediaSaveProgress(String localId, float progress); void onMediaSaveFailed(String localId); void onStorySaveResult(String storyFirstMediaId, boolean success); + void onMediaModelCreatedForFile(String oldId, String newId, String oldUrl); } diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 4cae822a707c..85bf8acadf83 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 4cae822a707c65bbcda7b5b517ca2a035e90dca0 +Subproject commit 85bf8acadf8343fde0e1e79b922ab2df5cab5e65 From a2f01118ec41ac53c0aa01854b8c148725f83683 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 28 Sep 2020 21:20:00 -0300 Subject: [PATCH 046/230] updated gutenberg hash, fixed media upload succesful mediaID and remote URl updates in Story block --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 85bf8acadf83..a7bc72c32822 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 85bf8acadf8343fde0e1e79b922ab2df5cab5e65 +Subproject commit a7bc72c32822f852f7030600d7f9388b7d7de01f From e0a108dcb4aa96d29990667e326aaa6fe94b9d02 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 07:34:27 -0300 Subject: [PATCH 047/230] making sure to pass the Post's localId so it's loaded back in the bridge when editing a Story block --- .../main/java/org/wordpress/android/ui/ActivityLauncher.java | 4 ++++ .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index bfeca6f88b35..73c730557ca5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -18,6 +18,7 @@ import org.wordpress.android.analytics.AnalyticsTracker; import org.wordpress.android.analytics.AnalyticsTracker.Stat; import org.wordpress.android.datasets.ReaderPostTable; +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId; import org.wordpress.android.fluxc.model.PostImmutableModel; import org.wordpress.android.fluxc.model.PostModel; import org.wordpress.android.fluxc.model.SiteModel; @@ -106,6 +107,7 @@ import static org.wordpress.android.ui.pages.PagesActivityKt.EXTRA_PAGE_REMOTE_ID_KEY; import static org.wordpress.android.ui.stories.StoryComposerActivity.KEY_ALL_UNFLATTENED_LOADED_SLIDES; import static org.wordpress.android.ui.stories.StoryComposerActivity.KEY_LAUNCHED_FROM_GUTENBERG; +import static org.wordpress.android.ui.stories.StoryComposerActivity.KEY_POST_LOCAL_ID; import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_ID_KEY; public class ActivityLauncher { @@ -743,6 +745,7 @@ public static void editStoryWithMediaIdsForResult( public static void editStoryForResult( Activity activity, SiteModel site, + LocalId localPostId, int storyIndex, boolean allStorySlidesAreEditable, boolean launchedFromGutenberg, @@ -754,6 +757,7 @@ public static void editStoryForResult( Intent intent = new Intent(activity, StoryComposerActivity.class); intent.putExtra(WordPress.SITE, site); + intent.putExtra(KEY_POST_LOCAL_ID, localPostId.getValue()); intent.putExtra(KEY_STORY_INDEX, storyIndex); intent.putExtra(KEY_LAUNCHED_FROM_GUTENBERG, launchedFromGutenberg); intent.putExtra(KEY_ALL_UNFLATTENED_LOADED_SLIDES, allStorySlidesAreEditable); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 3b57b8da8291..68de0ad0ef5b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -40,7 +40,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; -import com.wordpress.stories.compose.frame.StorySaveEvents; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveCompleted; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed; import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress; @@ -91,6 +90,7 @@ import org.wordpress.android.fluxc.model.CauseOfOnPostChanged.RemoteAutoSavePost; import org.wordpress.android.fluxc.model.EditorTheme; import org.wordpress.android.fluxc.model.EditorThemeSupport; +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId; import org.wordpress.android.fluxc.model.MediaModel; import org.wordpress.android.fluxc.model.MediaModel.MediaUploadState; import org.wordpress.android.fluxc.model.PostImmutableModel; @@ -3073,6 +3073,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie ActivityLauncher.editStoryForResult( this, mSite, + new LocalId(mEditPostRepository.getId()), storyIndex, allStorySlidesAreEditable, true, From 12b25635b3a39618cbb6f64e5c67ac3c19ef6461 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 07:54:19 -0300 Subject: [PATCH 048/230] avoid IOBException by making sure the list is non-emtpy --- .../stories/SaveStoryGutenbergBlockUseCase.kt | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index fbd5da32f4f9..cb3bdf482b0f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -132,33 +132,36 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { storyBlockData?.let { storyBlockDataNonNull -> val localMediaId = mediaFile.id.toString() // now replace matching localMediaId with remoteMediaId in the mediaFileObjects, obtain the URLs and replace - storyBlockDataNonNull.mediaFiles?.filter { it.id == localMediaId }?.get(0)?.apply { - id = mediaFile.mediaId - link = mediaFile.fileURL - url = mediaFile.fileURL - - // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. - val localIdKey = mediaFile.id.toLong() - val remoteIdKey = mediaFile.mediaId.toLong() - val localSiteId = postModel.localSiteId.toLong() - StoriesPrefs.getSlideWithLocalId( - WordPress.getContext(), - localSiteId, - LocalMediaId(localIdKey) - )?.let { - it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID - StoriesPrefs.saveSlideWithRemoteId( - WordPress.getContext(), - localSiteId, - RemoteMediaId(remoteIdKey), // use the new mediaId as key - it - ) - // now delete the old entry - StoriesPrefs.deleteSlideWithLocalId( + val mediaFiles = storyBlockDataNonNull.mediaFiles.filter { it.id == localMediaId } + if (mediaFiles.isNotEmpty()) { + mediaFiles[0].apply { + id = mediaFile.mediaId + link = mediaFile.fileURL + url = mediaFile.fileURL + + // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. + val localIdKey = mediaFile.id.toLong() + val remoteIdKey = mediaFile.mediaId.toLong() + val localSiteId = postModel.localSiteId.toLong() + StoriesPrefs.getSlideWithLocalId( WordPress.getContext(), localSiteId, LocalMediaId(localIdKey) - ) + )?.let { + it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID + StoriesPrefs.saveSlideWithRemoteId( + WordPress.getContext(), + localSiteId, + RemoteMediaId(remoteIdKey), // use the new mediaId as key + it + ) + // now delete the old entry + StoriesPrefs.deleteSlideWithLocalId( + WordPress.getContext(), + localSiteId, + LocalMediaId(localIdKey) + ) + } } } processedContent = content.replace(mediaFilesJsonString, gson.toJson(storyBlockDataNonNull)) From 77d27cffab204c6a6e0175114acd6bdf13cceb21 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 07:55:06 -0300 Subject: [PATCH 049/230] only save a post in the bridge if we are not editing it - if we are editing, let the Editor (Gutenberg) handle this --- .../media/StoryMediaSaveUploadBridge.kt | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index ea539f176ae0..327ad136c430 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -176,22 +176,27 @@ class StoryMediaSaveUploadBridge @Inject constructor( editorMediaListener = localEditorMediaListener, doUploadAfterAdding = true ) - postUtils.preparePostForPublish(requireNotNull(editPostRepository.getEditablePost()), site) - savePostToDbUseCase.savePostToDb(editPostRepository, site) - - if (networkUtils.isNetworkAvailable()) { - postUtils.trackSavePostAnalytics( - editPostRepository.getPost(), - site - ) - uploadService.uploadPost(appContext, editPostRepository.id, true) - // SAVED_ONLINE - storiesTrackerHelper.trackStoryPostSavedEvent(uriList.size, site, false) - } else { - // SAVED_LOCALLY - storiesTrackerHelper.trackStoryPostSavedEvent(uriList.size, site, true) - // no op, when network is available the offline mode in WPAndroid will gather the queued Post - // and try to upload. + + // only save this post if we're not currently in edit mode + // In edit mode, we'll let the Gutenberg editor save the edited block if / when needed. + if (!isEditMode) { + postUtils.preparePostForPublish(requireNotNull(editPostRepository.getEditablePost()), site) + savePostToDbUseCase.savePostToDb(editPostRepository, site) + + if (networkUtils.isNetworkAvailable()) { + postUtils.trackSavePostAnalytics( + editPostRepository.getPost(), + site + ) + uploadService.uploadPost(appContext, editPostRepository.id, true) + // SAVED_ONLINE + storiesTrackerHelper.trackStoryPostSavedEvent(uriList.size, site, false) + } else { + // SAVED_LOCALLY + storiesTrackerHelper.trackStoryPostSavedEvent(uriList.size, site, true) + // no op, when network is available the offline mode in WPAndroid will gather the queued Post + // and try to upload. + } } } } From 6114c61b10d6f303b469474a9131d8967a283d74 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 08:06:34 -0300 Subject: [PATCH 050/230] fixed bug, was using the 'alt' field to look for a temporary id, should have referenced 'id' instead --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index cb3bdf482b0f..148ca7ee8a28 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -89,7 +89,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { private fun hasTemporaryIdsInStoryData(storyBlockData: StoryBlockData): Boolean { val temporaryIds = storyBlockData.mediaFiles.filter { - it.alt.startsWith(TEMPORARY_ID_PREFIX) + it.id.startsWith(TEMPORARY_ID_PREFIX) } return temporaryIds.size > 0 } From 0b016d6df3a11d31abdd6f1150a68c592b53b180 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 09:42:03 -0300 Subject: [PATCH 051/230] fixed comment --- .../android/ui/stories/media/StoryMediaSaveUploadBridge.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 327ad136c430..93d34751c375 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -152,7 +152,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( ) // for editMode, we'll need to tell the Gutenberg Editor to replace their mediaFiles - // ids with the new MediaModel local ids so, broadcasting the event. + // ids with the new MediaModel local ids are created so, broadcasting the event. if (isEditMode) { // finally send the event that this frameId has changed EventBus.getDefault().post( From 23fcff53e56fae259e56200eb696bf7fa3b6d1dc Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 10:28:08 -0300 Subject: [PATCH 052/230] refactored and added method StoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide() to be used both by the bridge and EditPostACtivity when a composed frame media has just been uploaded to the remote, so we keep track of edtiable slides in StoriesPrefs --- .../android/ui/posts/EditPostActivity.java | 18 ++++++++- .../stories/SaveStoryGutenbergBlockUseCase.kt | 37 +++++-------------- .../android/ui/stories/prefs/StoriesPrefs.kt | 24 ++++++++++++ .../ui/uploads/MediaUploadReadyProcessor.java | 2 +- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 68de0ad0ef5b..945a9d66fdc5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -173,6 +173,7 @@ import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; import org.wordpress.android.ui.stories.StoryRepositoryWrapper; import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent; +import org.wordpress.android.ui.stories.prefs.StoriesPrefs; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; @@ -1589,9 +1590,22 @@ private void onUploadSuccess(MediaModel media) { .getId()) { setFeaturedImageId(media.getMediaId()); } - } - + // if this is a Story media item, then make sure to keep up with the StoriesPrefs serialized slides + // this looks for the slide saved with the local id key (media.getId()), and re-converts it to + // mediaId. + // Also: we don't need to worry about checking if this mediaModel corresponds to a media upload within + // a story block: we will only replace items for which a local-keyed frame has been created before, + // which can only happen when using the Story Creator. + if (PostUtils.contentContainsWPStoryGutenbergBlocks(mEditPostRepository.getContent())) { + StoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + this, + media.getId(), + media.getMediaId(), + mSite.getId() + ); + } + } private void onUploadProgress(MediaModel media, float progress) { String localMediaId = String.valueOf(media.getId()); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 148ca7ee8a28..9e5a69080428 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -1,12 +1,10 @@ package org.wordpress.android.ui.stories +import android.content.Context import com.google.gson.Gson -import org.wordpress.android.WordPress import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.stories.prefs.StoriesPrefs -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.LocalMediaId -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId import org.wordpress.android.util.StringUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -120,7 +118,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { postModel.setContent(content) } - fun replaceLocalMediaIdsWithRemoteMediaIdsInPost(postModel: PostModel, mediaFile: MediaFile) { + fun replaceLocalMediaIdsWithRemoteMediaIdsInPost(context: Context, postModel: PostModel, mediaFile: MediaFile) { val gson = Gson() findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( postModel, @@ -139,29 +137,14 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { link = mediaFile.fileURL url = mediaFile.fileURL - // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. - val localIdKey = mediaFile.id.toLong() - val remoteIdKey = mediaFile.mediaId.toLong() - val localSiteId = postModel.localSiteId.toLong() - StoriesPrefs.getSlideWithLocalId( - WordPress.getContext(), - localSiteId, - LocalMediaId(localIdKey) - )?.let { - it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID - StoriesPrefs.saveSlideWithRemoteId( - WordPress.getContext(), - localSiteId, - RemoteMediaId(remoteIdKey), // use the new mediaId as key - it - ) - // now delete the old entry - StoriesPrefs.deleteSlideWithLocalId( - WordPress.getContext(), - localSiteId, - LocalMediaId(localIdKey) - ) - } + // look for the slide saved with the local id key (mediaFile.id), and re-convert to + // mediaId. + StoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + context, + mediaFile.id.toLong(), + mediaFile.mediaId.toLong(), + postModel.localSiteId.toLong() + ) } } processedContent = content.replace(mediaFilesJsonString, gson.toJson(storyBlockDataNonNull)) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index b2c88bb789c2..57793a39c7fa 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -123,6 +123,30 @@ object StoriesPrefs { editor.apply() } + @JvmStatic + fun replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide(context: Context, localIdKey: Long, remoteIdKey: Long, localSiteId: Long) { + // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. + getSlideWithLocalId( + context, + localSiteId, + LocalMediaId(localIdKey) + )?.let { + it.id = remoteIdKey.toString() // update the StoryFrameItem id to hold the same value as the remote mediaID + saveSlideWithRemoteId( + context, + localSiteId, + RemoteMediaId(remoteIdKey), // use the new mediaId as key + it + ) + // now delete the old entry + deleteSlideWithLocalId( + context, + localSiteId, + LocalMediaId(localIdKey) + ) + } + } + data class RemoteMediaId(val mediaId: Long) data class LocalMediaId(val id: Long) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java index 8ff1bbdc09d1..f047260336b9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java @@ -23,7 +23,7 @@ public PostModel replaceMediaFileWithUrlInPost(@Nullable PostModel post, String if (PostUtils.contentContainsWPStoryGutenbergBlocks(post.getContent())) { SaveStoryGutenbergBlockUseCase saveStoryGutenbergBlockUseCase = new SaveStoryGutenbergBlockUseCase(); saveStoryGutenbergBlockUseCase - .replaceLocalMediaIdsWithRemoteMediaIdsInPost(post, mediaFile); + .replaceLocalMediaIdsWithRemoteMediaIdsInPost(WordPress.getContext(), post, mediaFile); } else if (showGutenbergEditor && PostUtils.contentContainsGutenbergBlocks(post.getContent())) { post.setContent( PostUtils.replaceMediaFileWithUrlInGutenbergPost(post.getContent(), localMediaId, mediaFile, From a8bfdb3c7ef2b70c3a69758a64c732120aceb363 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 10:29:43 -0300 Subject: [PATCH 053/230] enclosed one check for media !=null needed by all other checks --- .../android/ui/posts/EditPostActivity.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 945a9d66fdc5..19d80cd3b89c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -1582,28 +1582,28 @@ private ActivityFinishState savePostOnline(boolean isFirstTimePublish) { } private void onUploadSuccess(MediaModel media) { - // TODO Should this statement check media.getLocalPostId() == mEditPostRepository.getId()? - if (media != null && !media.getMarkedLocallyAsFeatured() && mEditorMediaUploadListener != null) { - mEditorMediaUploadListener.onMediaUploadSucceeded(String.valueOf(media.getId()), - FluxCUtils.mediaFileFromMediaModel(media)); - } else if (media != null && media.getMarkedLocallyAsFeatured() && media.getLocalPostId() == mEditPostRepository - .getId()) { - setFeaturedImageId(media.getMediaId()); - } - - // if this is a Story media item, then make sure to keep up with the StoriesPrefs serialized slides - // this looks for the slide saved with the local id key (media.getId()), and re-converts it to - // mediaId. - // Also: we don't need to worry about checking if this mediaModel corresponds to a media upload within - // a story block: we will only replace items for which a local-keyed frame has been created before, - // which can only happen when using the Story Creator. - if (PostUtils.contentContainsWPStoryGutenbergBlocks(mEditPostRepository.getContent())) { - StoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( - this, - media.getId(), - media.getMediaId(), - mSite.getId() - ); + if (media != null) { + // TODO Should this statement check media.getLocalPostId() == mEditPostRepository.getId()? + if (!media.getMarkedLocallyAsFeatured() && mEditorMediaUploadListener != null) { + mEditorMediaUploadListener.onMediaUploadSucceeded(String.valueOf(media.getId()), + FluxCUtils.mediaFileFromMediaModel(media)); + } else if (media.getMarkedLocallyAsFeatured() && media.getLocalPostId() == mEditPostRepository + .getId()) { + setFeaturedImageId(media.getMediaId()); + } else if (PostUtils.contentContainsWPStoryGutenbergBlocks(mEditPostRepository.getContent())) { + // if this is a Story media item, then make sure to keep up with the StoriesPrefs serialized slides + // this looks for the slide saved with the local id key (media.getId()), and re-converts it to + // mediaId. + // Also: we don't need to worry about checking if this mediaModel corresponds to a media upload within + // a story block: we will only replace items for which a local-keyed frame has been created before, + // which can only happen when using the Story Creator. + StoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + this, + media.getId(), + media.getMediaId(), + mSite.getId() + ); + } } } From b0ccacd349fd54a6f998b61db854bdd27c03761d Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 10:50:27 -0300 Subject: [PATCH 054/230] moved else if, wasn't ever going to run otherwise --- .../android/ui/posts/EditPostActivity.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 19d80cd3b89c..984e091b9f0b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -1587,22 +1587,23 @@ private void onUploadSuccess(MediaModel media) { if (!media.getMarkedLocallyAsFeatured() && mEditorMediaUploadListener != null) { mEditorMediaUploadListener.onMediaUploadSucceeded(String.valueOf(media.getId()), FluxCUtils.mediaFileFromMediaModel(media)); + if (PostUtils.contentContainsWPStoryGutenbergBlocks(mEditPostRepository.getContent())) { + // if this is a Story media item, then make sure to keep up with the StoriesPrefs serialized slides + // this looks for the slide saved with the local id key (media.getId()), and re-converts it to + // mediaId. + // Also: we don't need to worry about checking if this mediaModel corresponds to a media upload + // within a story block in this post: we will only replace items for which a local-keyed frame has + // been created before, which can only happen when using the Story Creator. + StoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + this, + media.getId(), + media.getMediaId(), + mSite.getId() + ); + } } else if (media.getMarkedLocallyAsFeatured() && media.getLocalPostId() == mEditPostRepository .getId()) { setFeaturedImageId(media.getMediaId()); - } else if (PostUtils.contentContainsWPStoryGutenbergBlocks(mEditPostRepository.getContent())) { - // if this is a Story media item, then make sure to keep up with the StoriesPrefs serialized slides - // this looks for the slide saved with the local id key (media.getId()), and re-converts it to - // mediaId. - // Also: we don't need to worry about checking if this mediaModel corresponds to a media upload within - // a story block: we will only replace items for which a local-keyed frame has been created before, - // which can only happen when using the Story Creator. - StoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( - this, - media.getId(), - media.getMediaId(), - mSite.getId() - ); } } } From ce599122deca21ac2ca53c6652ede0b46bcb26d5 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 11:07:16 -0300 Subject: [PATCH 055/230] added call to updateAndSavePostAsync after adding a remote media to the Story --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 984e091b9f0b..cde12d4297c7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -1588,6 +1588,8 @@ private void onUploadSuccess(MediaModel media) { mEditorMediaUploadListener.onMediaUploadSucceeded(String.valueOf(media.getId()), FluxCUtils.mediaFileFromMediaModel(media)); if (PostUtils.contentContainsWPStoryGutenbergBlocks(mEditPostRepository.getContent())) { + // make sure to sync the local post object with the UI and save + updateAndSavePostAsync(); // if this is a Story media item, then make sure to keep up with the StoriesPrefs serialized slides // this looks for the slide saved with the local id key (media.getId()), and re-converts it to // mediaId. From 9749799bf068ecea154a19e2e09b7d45d8bb7b84 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 11:10:47 -0300 Subject: [PATCH 056/230] fixed line length --- .../org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 57793a39c7fa..c9890bb40e2f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -124,7 +124,12 @@ object StoriesPrefs { } @JvmStatic - fun replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide(context: Context, localIdKey: Long, remoteIdKey: Long, localSiteId: Long) { + fun replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + context: Context, + localIdKey: Long, + remoteIdKey: Long, + localSiteId: Long + ) { // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. getSlideWithLocalId( context, From fcfb771bea72df6847b26cb6928e0b3caa33f592 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 11:27:08 -0300 Subject: [PATCH 057/230] updated stories lib hash to keep up with camera preview launch fix --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 823ab8aa66f0..9affc818faa7 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 823ab8aa66f065f32fa69f66260569bce6ae7cee +Subproject commit 9affc818faa77cb9bbe93a41e32ca811c336710e From 3b6095c464a46ab3d9660df438396c4a0173220f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 12:19:33 -0300 Subject: [PATCH 058/230] updated gutenberg-mobile hash, commented lines --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index a7bc72c32822..21b823b4f333 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit a7bc72c32822f852f7030600d7f9388b7d7de01f +Subproject commit 21b823b4f33313fc5b134e7d37d5ef0a4d4bd943 From 9bc74f334bfe74bb544a19ee926de38537a1aee9 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 29 Sep 2020 19:23:26 -0300 Subject: [PATCH 059/230] using StoryRepositoryWrapper --- .../wordpress/android/ui/stories/StoryComposerActivity.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 6efdc7a8f549..05237799bec6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -22,9 +22,7 @@ import com.wordpress.stories.compose.PrepublishingEventProvider import com.wordpress.stories.compose.SnackbarProvider import com.wordpress.stories.compose.StoryDiscardListener import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult -import com.wordpress.stories.compose.story.StoryFrameItemType.VIDEO import com.wordpress.stories.compose.story.StoryIndex -import com.wordpress.stories.compose.story.StoryRepository import com.wordpress.stories.compose.story.StoryRepository.DEFAULT_NONE_SELECTED import com.wordpress.stories.util.KEY_STORY_EDIT_MODE import com.wordpress.stories.util.KEY_STORY_INDEX @@ -107,6 +105,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), @Inject lateinit var saveStoryGutenbergBlockUseCase: SaveStoryGutenbergBlockUseCase @Inject lateinit var mediaStore: MediaStore @Inject lateinit var fluxCUtilsWrapper: FluxCUtilsWrapper + @Inject lateinit var storyRepositoryWrapper: StoryRepositoryWrapper private lateinit var viewModel: StoryComposerViewModel @@ -478,7 +477,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), storyIndex: StoryIndex ): ArrayList { val storyMediaFileDataList = ArrayList() // holds media files - val story = StoryRepository.getStoryAtIndex(storyIndex) + val story = storyRepositoryWrapper.getStoryAtIndex(storyIndex) for ((frameIndex, frame) in story.frames.withIndex()) { frame.id?.let { val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) From 7fedb76db93c80ff0a3050887b4b29aa1b9fd05b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 08:28:20 -0300 Subject: [PATCH 060/230] updated stories cmomit hash with bugfixes --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 9affc818faa7..05cc667c0a14 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 9affc818faa77cb9bbe93a41e32ca811c336710e +Subproject commit 05cc667c0a14dac23ede3955eea4e5bd8a4c943e From d9978b97fbe01afa558ecef8d3c38dc297cea618 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 08:33:15 -0300 Subject: [PATCH 061/230] updated stories lib hash - fixed lint warnings --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 05cc667c0a14..dab279ee26cc 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 05cc667c0a14dac23ede3955eea4e5bd8a4c943e +Subproject commit dab279ee26ccd966f88f575b6cd51c19cfbc9ad2 From 2ec71f97268bb54cffd9232381fc778e94b4c7ff Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 10:58:15 -0300 Subject: [PATCH 062/230] removed old comment --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 9e5a69080428..8a7d01d6e805 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -50,8 +50,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { fun buildMediaFileDataWithTemporaryId(mediaFile: MediaFile, temporaryId: String): StoryMediaFileData { return StoryMediaFileData( - alt = "", // notation abuse: we're repurposing this field to - // hold a temporaryId + alt = "", id = TEMPORARY_ID_PREFIX + temporaryId, // mediaFile.id, link = StringUtils.notNullStr(mediaFile.fileURL), type = if (mediaFile.isVideo) "video" else "image", From e9dc8308916e7ebaa113dec55b0f7601c3ce2dc7 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 12:01:39 -0300 Subject: [PATCH 063/230] add support for editing an existing uploaded Story and adding a frame to it --- .../stories/SaveStoryGutenbergBlockUseCase.kt | 12 ++++++ .../ui/stories/StoryComposerActivity.kt | 42 +++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 8a7d01d6e805..b68d2f9848b3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -60,6 +60,18 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { ) } + fun buildMediaFileDataWithTemporaryIdNoMediaFile(temporaryId: String, url: String, isVideo: Boolean): StoryMediaFileData { + return StoryMediaFileData( + alt = "", + id = TEMPORARY_ID_PREFIX + temporaryId, // mediaFile.id, + link = url, + type = if (isVideo) "video" else "image", + mime = "", + caption = "", + url = url + ) + } + fun cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost(editPostRepository: EditPostRepository) { editPostRepository.update { postModel: PostModel -> val gson = Gson() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 05237799bec6..9e3fb2ace80a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -22,6 +22,9 @@ import com.wordpress.stories.compose.PrepublishingEventProvider import com.wordpress.stories.compose.SnackbarProvider import com.wordpress.stories.compose.StoryDiscardListener import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.FileBackgroundSource +import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.UriBackgroundSource +import com.wordpress.stories.compose.story.StoryFrameItemType.VIDEO import com.wordpress.stories.compose.story.StoryIndex import com.wordpress.stories.compose.story.StoryRepository.DEFAULT_NONE_SELECTED import com.wordpress.stories.util.KEY_STORY_EDIT_MODE @@ -66,7 +69,6 @@ import org.wordpress.android.ui.utils.AuthenticationUtils import org.wordpress.android.ui.utils.UiHelpers import org.wordpress.android.util.FluxCUtilsWrapper import org.wordpress.android.util.ListUtils -import org.wordpress.android.util.StringUtils import org.wordpress.android.util.WPMediaUtils import org.wordpress.android.util.WPPermissionUtils import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper @@ -479,18 +481,42 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), val storyMediaFileDataList = ArrayList() // holds media files val story = storyRepositoryWrapper.getStoryAtIndex(storyIndex) for ((frameIndex, frame) in story.frames.withIndex()) { - frame.id?.let { - val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) - val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) - mediaFile?.let { + when (frame.id) { + // if the frame.id is null, this is a new frame that has been added to an edited Story + // so, we don't have much information yet. We do have the background source (not the flattened + // image yet) so, let's use that for now, and assign the temporaryID we'll use to send + // save progress events to Gutenberg. + null -> { val storyMediaFileData = - saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( - mediaFile = it, - temporaryId = "$storyIndex-$frameIndex" + saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryIdNoMediaFile( + temporaryId = "$storyIndex-$frameIndex", + url = if (frame.source is FileBackgroundSource) { + (frame.source as FileBackgroundSource).file.toString() + } else { + (frame.source as UriBackgroundSource).contentUri.toString() + }, + isVideo = (frame.frameItemType is VIDEO) ) frame.id = storyMediaFileData.id storyMediaFileDataList.add(storyMediaFileData) } + // if the frame.id is populated, this should be an actual MediaModel mediaId so, + // let's use that to obtain the mediaFile and then replace it with the temporary frame.id + else -> { + frame.id?.let { + val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) + val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) + mediaFile?.let { + val storyMediaFileData = + saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( + mediaFile = it, + temporaryId = "$storyIndex-$frameIndex" + ) + frame.id = storyMediaFileData.id + storyMediaFileDataList.add(storyMediaFileData) + } + } + } } } return storyMediaFileDataList From 4e005ae2d06f106310025a55521120c2bf8bcfa7 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 13:04:41 -0300 Subject: [PATCH 064/230] implemented git onFrameRemove() listener method and cleaning StoriesPrefs when a frame is discarded in the composer --- .../ui/stories/StoryComposerActivity.kt | 31 +++++++++++++++++++ libs/stories-android | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 9e3fb2ace80a..b2272c099396 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -65,6 +65,9 @@ import org.wordpress.android.ui.posts.prepublishing.PrepublishingBottomSheetList import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.StoryMediaFileData import org.wordpress.android.ui.stories.media.StoryEditorMedia import org.wordpress.android.ui.stories.media.StoryEditorMedia.AddMediaToStoryPostUiState +import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.LocalMediaId +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId import org.wordpress.android.ui.utils.AuthenticationUtils import org.wordpress.android.ui.utils.UiHelpers import org.wordpress.android.util.FluxCUtilsWrapper @@ -112,6 +115,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), private lateinit var viewModel: StoryComposerViewModel private var addingMediaToEditorProgressDialog: ProgressDialog? = null + private val frameIdsToRemove = ArrayList() override fun getSite() = site override fun getEditPostRepository() = editPostRepository @@ -431,6 +435,19 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } } + override fun onFrameRemove(storyIndex: StoryIndex, storyFrameIndex: Int) { + // keep record of the frames users deleted. + // But we'll only actually do cleanup once they tap on the DONE/SAVE button, because they could + // still bail out of the StoryComposer by tapping back or the cross and then admiting they want to lose + // the changes they made (this means, they'd want to keep the stories). + val story = storyRepositoryWrapper.getStoryAtIndex(storyIndex) + if (storyFrameIndex < story.frames.size) { + story.frames[storyFrameIndex].id?.let { + frameIdsToRemove.add(it) + } + } + } + private fun openPrepublishingBottomSheet() { val fragment = supportFragmentManager.findFragmentByTag(PrepublishingBottomSheetFragment.TAG) if (fragment == null) { @@ -445,6 +462,20 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), override fun onStorySaveButtonPressed() { if (intent.getBooleanExtra(KEY_LAUNCHED_FROM_GUTENBERG, false)) { + // first of all, remove any StoriesPref for removed slides + site?.let { + val siteLocalId = it.id.toLong() + for (frameId in frameIdsToRemove) { + if (StoriesPrefs.checkSlideIdExists(this, siteLocalId, RemoteMediaId(frameId.toLong()))) { + StoriesPrefs.deleteSlideWithRemoteId(this, siteLocalId, RemoteMediaId(frameId.toLong())) + } else { + // shouldn't happen but just in case the story frame has just been created but not yet uploaded + // let's delete the local slide pref. + StoriesPrefs.deleteSlideWithLocalId(this, siteLocalId, LocalMediaId(frameId.toLong())) + } + } + } + val savedContentIntent = Intent() val blockId = intent.extras.getString(ARG_STORY_BLOCK_ID) savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) diff --git a/libs/stories-android b/libs/stories-android index dab279ee26cc..19ac403d23dd 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit dab279ee26ccd966f88f575b6cd51c19cfbc9ad2 +Subproject commit 19ac403d23ddfc3211bcd78e2c3d20c3f21f2275 From 144e3ced00cfa850bd0a940c50dec9b1b8807121 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 15:33:44 -0300 Subject: [PATCH 065/230] updated commit hash for stories library --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 19ac403d23dd..c0512c9b6b02 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 19ac403d23ddfc3211bcd78e2c3d20c3f21f2275 +Subproject commit c0512c9b6b0246a7619bb906d026118246a4f26a From 64cc559d2591ea6273b163221e12f4cdcb8448d7 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 16:14:12 -0300 Subject: [PATCH 066/230] safeguard against a Story being corrupt (for example a crash when saving), to indicate this cannot be edited --- .../android/ui/posts/EditPostActivity.java | 14 ++++++++++++++ .../usecase/LoadStoryFromStoriesPrefsUseCase.kt | 15 ++++++++++++++- WordPress/src/main/res/values/strings.xml | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index cde12d4297c7..d80ae21eab1c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3064,6 +3064,20 @@ public void onTrackableEvent(TrackableEvent event, Map propertie mMediaStore, this ); + + if (loadStoryFromStoriesPrefsUseCase.anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles)) { + // unfortunately the medaiIds seem corrupt so, show a dialog and bail + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); + builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); + builder.setMessage(getString(R.string.dialog_edit_story_corrupt_message)); + builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { + dialog.dismiss(); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + return; + } + ArrayList mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles); boolean allStorySlidesAreEditable = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(mSite, mediaIds); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index a4521e1cd8bc..e2c328bf9826 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -9,7 +9,6 @@ import dagger.Reusable import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore -import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId import org.wordpress.android.ui.stories.prefs.StoriesPrefs.getSlideWithRemoteId @@ -38,6 +37,20 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( return mediaIds } + fun anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles: ArrayList): Boolean { + for (mediaFile in mediaFiles) { + try { + (mediaFile as HashMap)["id"] + .toString() + .toDouble() // this conversion is needed to strip off decimals that can come from RN + .toLong() + } catch (exception: NumberFormatException) { + return true + } + } + return false + } + fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { for (mediaId in mediaIds) { if (!isValidSlide(context, site.getId().toLong(), RemoteMediaId(mediaId.toLong()))) { diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index a4dc6e748ade..2c14a38040bc 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2876,6 +2876,7 @@ This story was edited on a different device and the ability to edit certain objects may be limited. Can\'t edit Story This story was created on a different device and can\'t be edited at this moment. + There was a problem saving this story and can\'t be edited at this moment. Capture Flip camera Flash From de7a2ba39e9c52e052c7aa0629bdc5215c0dc493 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 16:33:40 -0300 Subject: [PATCH 067/230] updated gutenberg mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 21b823b4f333..7f9313f1704e 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 21b823b4f33313fc5b134e7d37d5ef0a4d4bd943 +Subproject commit 7f9313f1704e9d8d69994df8a33bcb4ae7909e38 From 7c04d20ec7c09aa6e01944b86a54b551f49ab61d Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 16:40:09 -0300 Subject: [PATCH 068/230] fixed lint warnings --- .../ui/stories/SaveStoryGutenbergBlockUseCase.kt | 14 +++++++++----- .../android/ui/stories/StoryRepositoryWrapper.kt | 7 ++++--- .../ui/stories/media/StoryMediaSaveUploadBridge.kt | 4 ++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index b68d2f9848b3..018b3b52e300 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -60,7 +60,11 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { ) } - fun buildMediaFileDataWithTemporaryIdNoMediaFile(temporaryId: String, url: String, isVideo: Boolean): StoryMediaFileData { + fun buildMediaFileDataWithTemporaryIdNoMediaFile( + temporaryId: String, + url: String, + isVideo: Boolean + ): StoryMediaFileData { return StoryMediaFileData( alt = "", id = TEMPORARY_ID_PREFIX + temporaryId, // mediaFile.id, @@ -80,8 +84,8 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { object : DoWithMediaFilesListener { override fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String { var processedContent = content - val storyBlockData: StoryBlockData? - = gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) + val storyBlockData: StoryBlockData? = + gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) storyBlockData?.let { if (hasTemporaryIdsInStoryData(it)) { // here remove the whole mediaFiles attribute @@ -136,8 +140,8 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { object : DoWithMediaFilesListener { override fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String { var processedContent = content - val storyBlockData: StoryBlockData? - = gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) + val storyBlockData: StoryBlockData? = + gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) storyBlockData?.let { storyBlockDataNonNull -> val localMediaId = mediaFile.id.toString() // now replace matching localMediaId with remoteMediaId in the mediaFileObjects, obtain the URLs and replace diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt index d5846c8652b7..dcd109264b6d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt @@ -11,9 +11,10 @@ class StoryRepositoryWrapper @Inject constructor() { fun getCurrentStoryTitle() = StoryRepository.getCurrentStoryTitle() fun getCurrentStoryIndex(): StoryIndex = StoryRepository.currentStoryIndex fun loadStory(storyIndex: StoryIndex) = StoryRepository.loadStory(storyIndex) - fun addStoryFrameItemToCurrentStory(item: StoryFrameItem) = StoryRepository.addStoryFrameItemToCurrentStory(item) + fun addStoryFrameItemToCurrentStory(item: StoryFrameItem) = + StoryRepository.addStoryFrameItemToCurrentStory(item) fun getStoryAtIndex(index: StoryIndex) = StoryRepository.getStoryAtIndex(index) fun getImmutableStories() = StoryRepository.getImmutableStories() - fun getCurrentStorySaveProgress(storyIndex: StoryIndex, oneItemActualProgress: Float = 0.0F) - = StoryRepository.getCurrentStorySaveProgress(storyIndex, oneItemActualProgress) + fun getCurrentStorySaveProgress(storyIndex: StoryIndex, oneItemActualProgress: Float = 0.0F) = + StoryRepository.getCurrentStorySaveProgress(storyIndex, oneItemActualProgress) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 93d34751c375..e0b154fca9de 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -100,7 +100,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( private fun addNewMediaItemsToPostAsync(site: SiteModel, uriList: List, isEditMode: Boolean) { // this is similar to addNewMediaItemsToEditorAsync in EditorMedia launch { - val localEditorMediaListener = object: EditorMediaListener { + val localEditorMediaListener = object : EditorMediaListener { override fun appendMediaFiles(mediaFiles: Map) { if (!isEditMode) { saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost( @@ -239,5 +239,5 @@ class StoryMediaSaveUploadBridge @Inject constructor( event.frameSaveResult.size == storyRepositoryWrapper.getStoryAtIndex(event.storyIndex).frames.size) } - data class StoryFrameMediaModelCreatedEvent (val oldId: String, val newId: String, val oldUrl: String) + data class StoryFrameMediaModelCreatedEvent(val oldId: String, val newId: String, val oldUrl: String) } From 0d554b4e9243fa37a1c09f1fa8e0195f3a0f650f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 30 Sep 2020 16:42:57 -0300 Subject: [PATCH 069/230] updated mobile gutenberg commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 7f9313f1704e..430fd3c7e0b3 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 7f9313f1704e9d8d69994df8a33bcb4ae7909e38 +Subproject commit 430fd3c7e0b3284734e80b52cda7b1749807e917 From 35f2f55c82ad63fafb9791562019a687b163979a Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 1 Oct 2020 00:35:05 -0300 Subject: [PATCH 070/230] updated commit hash for gutenberg mobile with fix in gutenberg mobile demo app --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 430fd3c7e0b3..fd317778b43b 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 430fd3c7e0b3284734e80b52cda7b1749807e917 +Subproject commit fd317778b43bf5229a4a033dfe76ae8e1c750b1d From 8c0a245106dc1eb39a9eebc68ad3cca1e148c24b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 1 Oct 2020 10:24:10 -0300 Subject: [PATCH 071/230] updated gutenberg-mobile and jetpack story block commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index fd317778b43b..e39c4ea51d09 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit fd317778b43bf5229a4a033dfe76ae8e1c750b1d +Subproject commit e39c4ea51d09d5a4ae7d444df9a88f1b27fe63c0 From 95903d9105055fd638fd792a99d27a5af7458fb9 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 1 Oct 2020 16:32:39 -0300 Subject: [PATCH 072/230] updated commit hash for mobile gutenberg --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 00a0cc0b7e84..b2685445fa4f 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 00a0cc0b7e849521595d428d5161dea557aa29e9 +Subproject commit b2685445fa4fda8b03799a5a71606adb348bd12b From 8311a30867d6cbcf75a2e33d58f95c8c05b88333 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 1 Oct 2020 17:24:56 -0300 Subject: [PATCH 073/230] updated gutenbeg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index b2685445fa4f..33f2addaab7f 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit b2685445fa4fda8b03799a5a71606adb348bd12b +Subproject commit 33f2addaab7f5338f791d968680cb6f1e97b4ffa From 111378b765f816aa297e0917fc3434cb8f7f667b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 1 Oct 2020 17:40:57 -0300 Subject: [PATCH 074/230] added missing method declaration --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index dfa611a75fbb..bcf70b56ff64 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -414,6 +414,10 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } } + override fun onFrameRemove(storyIndex: StoryIndex, storyFrameIndex: Int) { + // TODO will implement later + } + private fun openPrepublishingBottomSheet() { val fragment = supportFragmentManager.findFragmentByTag(PrepublishingBottomSheetFragment.TAG) if (fragment == null) { From 34509cb4d4f2994ae4d4873a6ac4fe0cced4d994 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 1 Oct 2020 18:18:11 -0300 Subject: [PATCH 075/230] added explicit null check --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index e529b6e1190c..01e6e8222883 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -474,7 +474,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } val savedContentIntent = Intent() - val blockId = intent.extras.getString(ARG_STORY_BLOCK_ID) + val blockId = intent.extras?.getString(ARG_STORY_BLOCK_ID) savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) val storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) From 85a10afb0ca709db4e193a4d08ad14930d34c5ef Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 1 Oct 2020 18:54:10 -0300 Subject: [PATCH 076/230] updated commit hash for mobile-gutenberg --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index f78b24fb30ee..b1de4df250b2 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit f78b24fb30eef7d1fc07161d46eb95d5d5fc766e +Subproject commit b1de4df250b2dc0c27f15aa94db8d1f1c0a6a65e From 0f4d87c25bde9da952d91fa9a5902a189acc0ed2 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 09:15:05 -0300 Subject: [PATCH 077/230] refactored onStoryComposerLoadRequested logic into LoadStoryFromStoriesPrefsUseCase --- .../android/ui/posts/EditPostActivity.java | 38 ++++--------------- .../ui/stories/StoryRepositoryWrapper.kt | 4 +- .../android/ui/stories/prefs/StoriesPrefs.kt | 5 --- .../LoadStoryFromStoriesPrefsUseCase.kt | 27 ++++++++++++- libs/stories-android | 2 +- 5 files changed, 36 insertions(+), 40 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 916f8aa71075..ea0096acf06c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -41,7 +41,6 @@ import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; -import com.wordpress.stories.compose.story.StoryRepository; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -163,7 +162,6 @@ import org.wordpress.android.ui.prefs.SiteSettingsInterface; import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; -import org.wordpress.android.ui.stories.StoryRepositoryWrapper; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; @@ -392,6 +390,7 @@ enum RestartEditorOptions { @Inject ModalLayoutPickerFeatureConfig mModalLayoutPickerFeatureConfig; @Inject CrashLogging mCrashLogging; @Inject MediaPickerLauncher mMediaPickerLauncher; + @Inject LoadStoryFromStoriesPrefsUseCase mLoadStoryFromStoriesPrefsUseCase; private StorePostViewModel mViewModel; @@ -3066,36 +3065,13 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - LoadStoryFromStoriesPrefsUseCase loadStoryFromStoriesPrefsUseCase = new LoadStoryFromStoriesPrefsUseCase( - new StoryRepositoryWrapper(), - mSite, - mMediaStore, - this - ); - ArrayList mediaIds = - loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles); - boolean allStorySlidesAreEditable = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(mSite, mediaIds); - boolean failedLoadingOrReCreatingStory = false; - - // now look for a Story in the StoryRepository that has all these frames and, if not found, let's - // just build the Story object ourselves to keep these files arrangement - int storyIndex = StoryRepository.findStoryContainingStoryFrameItemsByIds(mediaIds); - if (storyIndex == StoryRepository.DEFAULT_NONE_SELECTED) { - // the StoryRepository didn't have it but we have editable serialized slides so, - // create a new Story from scratch with these deserialized StoryFrameItems - ReCreateStoryResult result = - loadStoryFromStoriesPrefsUseCase.loadOrReCreateStoryFromStoriesPrefs(mediaIds); - failedLoadingOrReCreatingStory = result.getNoSlidesLoaded(); - if (allStorySlidesAreEditable) { - // double check and override if we found at least one couldn't be inflated - allStorySlidesAreEditable = result.getAllStorySlidesAreEditable(); - } - storyIndex = result.getStoryIndex(); - } - - if (!failedLoadingOrReCreatingStory) { + ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase + .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); + if (!result.getNoSlidesLoaded()) { // Story instance loaded or re-created! Load it - ActivityLauncher.editStoryForResult(this, mSite, storyIndex, allStorySlidesAreEditable, true); + ActivityLauncher.editStoryForResult( + this, mSite, result.getStoryIndex(), result.getAllStorySlidesAreEditable(), true + ); } else { // unfortunately we couldn't even load the remote media Ids indicated by the StoryBLock so we can't allow // editing at this time :( diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt index 7b89cea9bbda..570db83441ed 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt @@ -12,4 +12,6 @@ class StoryRepositoryWrapper @Inject constructor() { fun getCurrentStoryIndex(): StoryIndex = StoryRepository.currentStoryIndex fun loadStory(storyIndex: StoryIndex) = StoryRepository.loadStory(storyIndex) fun addStoryFrameItemToCurrentStory(item: StoryFrameItem) = StoryRepository.addStoryFrameItemToCurrentStory(item) -} + fun findStoryContainingStoryFrameItemsByIds(ids: ArrayList) = + StoryRepository.findStoryContainingStoryFrameItemsByIds(ids) + } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index b2c88bb789c2..58024377eb65 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -23,13 +23,11 @@ object StoriesPrefs { KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.id.toString() } - @JvmStatic fun checkSlideIdExists(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { val slideIdKey = buildSlideKey(siteId, mediaId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } - @JvmStatic fun checkSlideOriginalBackgroundMediaExists(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { val storyFrameItem: StoryFrameItem? = getSlideWithRemoteId(context, siteId, mediaId) storyFrameItem?.let { frame -> @@ -73,7 +71,6 @@ object StoriesPrefs { editor.apply() } - @JvmStatic fun isValidSlide(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { return checkSlideIdExists(context, siteId, mediaId) && checkSlideOriginalBackgroundMediaExists(context, siteId, mediaId) @@ -83,7 +80,6 @@ object StoriesPrefs { return PreferenceManager.getDefaultSharedPreferences(context).getString(slideIdKey, null) } - @JvmStatic fun getSlideWithRemoteId(context: Context, siteId: Long, mediaId: RemoteMediaId): StoryFrameItem? { val jsonSlide = getSlideJson(context, buildSlideKey(siteId, mediaId)) jsonSlide?.let { @@ -91,7 +87,6 @@ object StoriesPrefs { } ?: return null } - @JvmStatic fun getSlideWithLocalId(context: Context, siteId: Long, mediaId: LocalMediaId): StoryFrameItem? { val jsonSlide = getSlideJson(context, buildSlideKey(siteId, mediaId)) jsonSlide?.let { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index ca3fe97647a5..978f52f750dd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -20,7 +20,6 @@ import javax.inject.Inject @Reusable class LoadStoryFromStoriesPrefsUseCase @Inject constructor( private val storyRepositoryWrapper: StoryRepositoryWrapper, - private val site: SiteModel, private val mediaStore: MediaStore, private val context: Context ) { @@ -46,7 +45,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( return true } - fun loadOrReCreateStoryFromStoriesPrefs(mediaIds: ArrayList): ReCreateStoryResult { + private fun loadOrReCreateStoryFromStoriesPrefs(site: SiteModel, mediaIds: ArrayList): ReCreateStoryResult { // the StoryRepository didn't have it but we have editable serialized slides so, // create a new Story from scratch with these deserialized StoryFrameItems var allStorySlidesAreEditable: Boolean = true @@ -90,6 +89,30 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable, noSlidesLoaded) } + fun loadStoryFromMemoryOrRecreateFromPrefs(site: SiteModel, mediaFiles: ArrayList): ReCreateStoryResult { + val mediaIds = getMediaIdsFromStoryBlockBridgeMediaFiles( + mediaFiles + ) + var allStorySlidesAreEditable = areAllStorySlidesEditable( + site, + mediaIds + ) + + // now look for a Story in the StoryRepository that has all these frames and, if not found, let's + // just build the Story object ourselves to keep these files arrangement + var storyIndex = storyRepositoryWrapper.findStoryContainingStoryFrameItemsByIds(mediaIds) + if (storyIndex == StoryRepository.DEFAULT_NONE_SELECTED) { + // the StoryRepository didn't have it but we have editable serialized slides so, + // create a new Story from scratch with these deserialized StoryFrameItems + return loadOrReCreateStoryFromStoriesPrefs( + site, + mediaIds + ) + } else { + return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable, false) + } + } + data class ReCreateStoryResult( val storyIndex: StoryIndex, val allStorySlidesAreEditable: Boolean, diff --git a/libs/stories-android b/libs/stories-android index 2082538ec174..7966a7c7364c 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 2082538ec174aadf312ecd0fb2c5272efa33381b +Subproject commit 7966a7c7364c347170ba6986c8259018d69f9009 From 834be35827697bea6e67e62bc0394bf34f8341b3 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 7 Oct 2020 09:24:55 -0300 Subject: [PATCH 078/230] Update WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java Co-authored-by: Joel Dean --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index ea0096acf06c..168f3ad232c9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3073,7 +3073,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie this, mSite, result.getStoryIndex(), result.getAllStorySlidesAreEditable(), true ); } else { - // unfortunately we couldn't even load the remote media Ids indicated by the StoryBLock so we can't allow + // unfortunately we couldn't even load the remote media Ids indicated by the StoryBlock so we can't allow // editing at this time :( AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); From 10a8a9e9f9b83f0e8b2e54c096a1d1218b61c78a Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 7 Oct 2020 09:27:40 -0300 Subject: [PATCH 079/230] Update WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt Co-authored-by: Joel Dean --- .../android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt index ccb97c3de05c..6deae0e3139f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/media/AddLocalMediaToPostUseCase.kt @@ -69,7 +69,7 @@ class AddLocalMediaToPostUseCase @Inject constructor( // here we pass a map of "old" (before optimisation) Uris to the new MediaModels which contain // both the mediaModel ids and the optimized media URLs. - // this way, the listener will be able to process from other models potining to the old URLs + // this way, the listener will be able to process from other models pointing to the old URLs // and make any needed updates editorMediaListener.onMediaModelsCreatedFromOptimizedUris( uriList.zip(createMediaModelsResult.mediaModels).toMap() From f6d92d293ce64df43f5e5f08705c655203d9c74f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 10:16:42 -0300 Subject: [PATCH 080/230] made StoriesPrefs a @Singleton annotated injectable class --- .../stories/SaveStoryGutenbergBlockUseCase.kt | 14 ++--- .../media/StoryMediaSaveUploadBridge.kt | 4 +- .../android/ui/stories/prefs/StoriesPrefs.kt | 57 +++++++++++-------- .../LoadStoryFromStoriesPrefsUseCase.kt | 13 ++--- .../ui/uploads/MediaUploadReadyProcessor.java | 5 +- 5 files changed, 49 insertions(+), 44 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index e9c22e279c03..d8b43ff0a138 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -1,7 +1,6 @@ package org.wordpress.android.ui.stories import com.google.gson.Gson -import org.wordpress.android.WordPress import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.stories.prefs.StoriesPrefs @@ -11,7 +10,9 @@ import org.wordpress.android.util.StringUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject -class SaveStoryGutenbergBlockUseCase @Inject constructor() { +class SaveStoryGutenbergBlockUseCase @Inject constructor( + private val storiesPrefs: StoriesPrefs +) { fun buildJetpackStoryBlockInPost( editPostRepository: EditPostRepository, mediaFiles: Map @@ -66,21 +67,18 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor() { val localIdKey = mediaFile.id.toLong() val remoteIdKey = mediaFile.mediaId.toLong() val localSiteId = post.localSiteId.toLong() - StoriesPrefs.getSlideWithLocalId( - WordPress.getContext(), + storiesPrefs.getSlideWithLocalId( localSiteId, LocalMediaId(localIdKey) )?.let { it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID - StoriesPrefs.saveSlideWithRemoteId( - WordPress.getContext(), + storiesPrefs.saveSlideWithRemoteId( localSiteId, RemoteMediaId(remoteIdKey), // use the new mediaId as key it ) // now delete the old entry - StoriesPrefs.deleteSlideWithLocalId( - WordPress.getContext(), + storiesPrefs.deleteSlideWithLocalId( localSiteId, LocalMediaId(localIdKey) ) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index d45c809556d7..7c29f1928d49 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -50,6 +50,7 @@ import kotlin.coroutines.CoroutineContext class StoryMediaSaveUploadBridge @Inject constructor( private val addLocalMediaToPostUseCase: AddLocalMediaToPostUseCase, private val savePostToDbUseCase: SavePostToDbUseCase, + private val storiesPrefs: StoriesPrefs, private val uploadService: UploadServiceFacade, private val networkUtils: NetworkUtilsWrapper, private val postUtils: PostUtilsWrapper, @@ -188,8 +189,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( val mediaModel = oldUriToMediaFiles.get(Uri.fromFile(frame.composedFrameFile)) mediaModel?.let { frame.id = it.id.toString() - StoriesPrefs.saveSlideWithLocalId( - appContext, + storiesPrefs.saveSlideWithLocalId( it.localSiteId.toLong(), // use the local id to save the original, will be replaced later // with mediaModel.mediaId after uploading to the remote site diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 58024377eb65..f4bae3b9bb6c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -7,11 +7,18 @@ import com.wordpress.stories.compose.story.StoryFrameItem import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.FileBackgroundSource import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.UriBackgroundSource import com.wordpress.stories.compose.story.StorySerializerUtils - -object StoriesPrefs { - private const val KEY_PREFIX_STORIES_SLIDE_ID = "story_slide_id-" - private const val KEY_PREFIX_LOCAL_MEDIA_ID = "l-" - private const val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class StoriesPrefs @Inject constructor( + private val context: Context +) { + companion object { + private val KEY_PREFIX_STORIES_SLIDE_ID = "story_slide_id-" + private val KEY_PREFIX_LOCAL_MEDIA_ID = "l-" + private val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" + } private fun buildSlideKey(siteId: Long, mediaId: RemoteMediaId): String { return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + @@ -23,13 +30,13 @@ object StoriesPrefs { KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.id.toString() } - fun checkSlideIdExists(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { + fun checkSlideIdExists(siteId: Long, mediaId: RemoteMediaId): Boolean { val slideIdKey = buildSlideKey(siteId, mediaId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } - fun checkSlideOriginalBackgroundMediaExists(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { - val storyFrameItem: StoryFrameItem? = getSlideWithRemoteId(context, siteId, mediaId) + fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: RemoteMediaId): Boolean { + val storyFrameItem: StoryFrameItem? = getSlideWithRemoteId(siteId, mediaId) storyFrameItem?.let { frame -> // now check the background media exists or is accessible on this device frame.source.let { source -> @@ -39,7 +46,7 @@ object StoriesPrefs { } ?: return false } else if (source is UriBackgroundSource) { source.contentUri?.let { - return isUriAccessible(it, context) + return isUriAccessible(it) } ?: return false } } @@ -47,7 +54,7 @@ object StoriesPrefs { return false } - private fun isUriAccessible(uri: Uri, context: Context): Boolean { + private fun isUriAccessible(uri: Uri): Boolean { if (uri.toString().startsWith("http")) { // TODO: assume it'll be accessible - we'll figure out later // potentially force external download using MediaUtils.downloadExternalMedia() here to ensure @@ -65,53 +72,53 @@ object StoriesPrefs { return false } - private fun saveSlide(context: Context, slideIdKey: String, storySlideJson: String) { + private fun saveSlide(slideIdKey: String, storySlideJson: String) { val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() editor.putString(slideIdKey, storySlideJson) editor.apply() } - fun isValidSlide(context: Context, siteId: Long, mediaId: RemoteMediaId): Boolean { - return checkSlideIdExists(context, siteId, mediaId) && - checkSlideOriginalBackgroundMediaExists(context, siteId, mediaId) + fun isValidSlide(siteId: Long, mediaId: RemoteMediaId): Boolean { + return checkSlideIdExists(siteId, mediaId) && + checkSlideOriginalBackgroundMediaExists(siteId, mediaId) } - private fun getSlideJson(context: Context, slideIdKey: String): String? { + private fun getSlideJson(slideIdKey: String): String? { return PreferenceManager.getDefaultSharedPreferences(context).getString(slideIdKey, null) } - fun getSlideWithRemoteId(context: Context, siteId: Long, mediaId: RemoteMediaId): StoryFrameItem? { - val jsonSlide = getSlideJson(context, buildSlideKey(siteId, mediaId)) + fun getSlideWithRemoteId(siteId: Long, mediaId: RemoteMediaId): StoryFrameItem? { + val jsonSlide = getSlideJson(buildSlideKey(siteId, mediaId)) jsonSlide?.let { return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) } ?: return null } - fun getSlideWithLocalId(context: Context, siteId: Long, mediaId: LocalMediaId): StoryFrameItem? { - val jsonSlide = getSlideJson(context, buildSlideKey(siteId, mediaId)) + fun getSlideWithLocalId(siteId: Long, mediaId: LocalMediaId): StoryFrameItem? { + val jsonSlide = getSlideJson(buildSlideKey(siteId, mediaId)) jsonSlide?.let { return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) } ?: return null } - fun saveSlideWithLocalId(context: Context, siteId: Long, mediaId: LocalMediaId, storyFrameItem: StoryFrameItem) { + fun saveSlideWithLocalId(siteId: Long, mediaId: LocalMediaId, storyFrameItem: StoryFrameItem) { val slideIdKey = buildSlideKey(siteId, mediaId) - saveSlide(context, slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) + saveSlide(slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) } - fun saveSlideWithRemoteId(context: Context, siteId: Long, mediaId: RemoteMediaId, storyFrameItem: StoryFrameItem) { + fun saveSlideWithRemoteId(siteId: Long, mediaId: RemoteMediaId, storyFrameItem: StoryFrameItem) { val slideIdKey = buildSlideKey(siteId, mediaId) - saveSlide(context, slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) + saveSlide(slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) } - fun deleteSlideWithLocalId(context: Context, siteId: Long, mediaId: LocalMediaId) { + fun deleteSlideWithLocalId(siteId: Long, mediaId: LocalMediaId) { val slideIdKey = buildSlideKey(siteId, mediaId) val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() editor.remove(slideIdKey) editor.apply() } - fun deleteSlideWithRemoteId(context: Context, siteId: Long, mediaId: RemoteMediaId) { + fun deleteSlideWithRemoteId(siteId: Long, mediaId: RemoteMediaId) { val slideIdKey = buildSlideKey(siteId, mediaId) val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() editor.remove(slideIdKey) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 978f52f750dd..088619301dfb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -1,6 +1,5 @@ package org.wordpress.android.ui.stories.usecase -import android.content.Context import android.net.Uri import com.wordpress.stories.compose.story.StoryFrameItem import com.wordpress.stories.compose.story.StoryIndex @@ -10,9 +9,8 @@ import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.ui.stories.StoryRepositoryWrapper +import org.wordpress.android.ui.stories.prefs.StoriesPrefs import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.getSlideWithRemoteId -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.isValidSlide import java.util.ArrayList import java.util.HashMap import javax.inject.Inject @@ -20,8 +18,8 @@ import javax.inject.Inject @Reusable class LoadStoryFromStoriesPrefsUseCase @Inject constructor( private val storyRepositoryWrapper: StoryRepositoryWrapper, - private val mediaStore: MediaStore, - private val context: Context + private val storiesPrefs: StoriesPrefs, + private val mediaStore: MediaStore ) { fun getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles: ArrayList): ArrayList { val mediaIds = ArrayList() @@ -38,7 +36,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { for (mediaId in mediaIds) { - if (!isValidSlide(context, site.getId().toLong(), RemoteMediaId(mediaId.toLong()))) { + if (!storiesPrefs.isValidSlide(site.getId().toLong(), RemoteMediaId(mediaId.toLong()))) { return false } } @@ -54,8 +52,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( storyRepositoryWrapper.loadStory(storyIndex) storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() for (mediaId in mediaIds) { - var storyFrameItem = getSlideWithRemoteId( - context, + var storyFrameItem = storiesPrefs.getSlideWithRemoteId( site.getId().toLong(), RemoteMediaId(mediaId.toLong()) ) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java index 8ff1bbdc09d1..1e1a6b419858 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java @@ -9,6 +9,7 @@ import org.wordpress.android.ui.posts.PostUtils; import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase; +import org.wordpress.android.ui.stories.prefs.StoriesPrefs; import org.wordpress.android.util.helpers.MediaFile; @@ -21,7 +22,9 @@ public PostModel replaceMediaFileWithUrlInPost(@Nullable PostModel post, String boolean showGutenbergEditor = AppPrefs.isGutenbergEditorEnabled(); if (PostUtils.contentContainsWPStoryGutenbergBlocks(post.getContent())) { - SaveStoryGutenbergBlockUseCase saveStoryGutenbergBlockUseCase = new SaveStoryGutenbergBlockUseCase(); + SaveStoryGutenbergBlockUseCase saveStoryGutenbergBlockUseCase = new SaveStoryGutenbergBlockUseCase( + new StoriesPrefs(WordPress.getContext()) + ); saveStoryGutenbergBlockUseCase .replaceLocalMediaIdsWithRemoteMediaIdsInPost(post, mediaFile); } else if (showGutenbergEditor && PostUtils.contentContainsGutenbergBlocks(post.getContent())) { From 34d4effeacc4f6b9356cb0c780bdbb8b2f73bd4e Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 10:20:20 -0300 Subject: [PATCH 081/230] kotlinified expression --- .../org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index f4bae3b9bb6c..6f256a6f663b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -61,9 +61,8 @@ class StoriesPrefs @Inject constructor( return true } try { - val inputStream = context.contentResolver.openInputStream(uri) - if (inputStream != null) { - inputStream.close() + context.contentResolver.openInputStream(uri)?.let { + it.close() return true } } catch (e: java.lang.Exception) { From a0faf8ac175f71a7812ee038d7ca6c43c7169659 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 7 Oct 2020 10:24:25 -0300 Subject: [PATCH 082/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt Co-authored-by: Joel Dean --- .../org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 6f256a6f663b..4b632a3a8bb6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -119,9 +119,10 @@ class StoriesPrefs @Inject constructor( fun deleteSlideWithRemoteId(siteId: Long, mediaId: RemoteMediaId) { val slideIdKey = buildSlideKey(siteId, mediaId) - val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() - editor.remove(slideIdKey) - editor.apply() + PreferenceManager.getDefaultSharedPreferences(context).edit().apply { + remove(slideIdKey) + apply() + } } data class RemoteMediaId(val mediaId: Long) From 34631b73f799058600f1395c8a08ef3531a25bcf Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 7 Oct 2020 10:25:05 -0300 Subject: [PATCH 083/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt Co-authored-by: Joel Dean --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 088619301dfb..d711a273c5f4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -21,7 +21,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( private val storiesPrefs: StoriesPrefs, private val mediaStore: MediaStore ) { - fun getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles: ArrayList): ArrayList { + fun getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles: ArrayList): ArrayList { val mediaIds = ArrayList() for (mediaFile in mediaFiles) { val mediaIdLong = (mediaFile as HashMap)["id"] From aba2177e498778e78ad10b1b4fcce518249c3771 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 10:28:40 -0300 Subject: [PATCH 084/230] fixed method signature --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index d711a273c5f4..e5bb1365ca4f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -86,7 +86,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable, noSlidesLoaded) } - fun loadStoryFromMemoryOrRecreateFromPrefs(site: SiteModel, mediaFiles: ArrayList): ReCreateStoryResult { + fun loadStoryFromMemoryOrRecreateFromPrefs(site: SiteModel, mediaFiles: ArrayList): ReCreateStoryResult { val mediaIds = getMediaIdsFromStoryBlockBridgeMediaFiles( mediaFiles ) From df5b594e2667dc1d94efa845553ae1e88bb71748 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 7 Oct 2020 10:32:01 -0300 Subject: [PATCH 085/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt Co-authored-by: Joel Dean --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index e5bb1365ca4f..6f477f556f58 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -68,7 +68,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( site, tmpMediaIdsLong ) - if (mediaModelList.size == 0) { + if (mediaModelList.isEmpty()) { noSlidesLoaded = true } else { for (mediaModel in mediaModelList) { From 99efe00984b0504395b4d1121b538c937c27379d Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 10:33:15 -0300 Subject: [PATCH 086/230] using implicit getter --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 6f477f556f58..14056fda4035 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -36,7 +36,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { for (mediaId in mediaIds) { - if (!storiesPrefs.isValidSlide(site.getId().toLong(), RemoteMediaId(mediaId.toLong()))) { + if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteMediaId(mediaId.toLong()))) { return false } } From ddcda8b0698df5350af06a51397d7469d0dee3d8 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 10:50:04 -0300 Subject: [PATCH 087/230] using FluxC's LocalOrRemoteId sealed class variants --- .../stories/SaveStoryGutenbergBlockUseCase.kt | 12 +++---- .../media/StoryMediaSaveUploadBridge.kt | 4 +-- .../android/ui/stories/prefs/StoriesPrefs.kt | 33 +++++++++---------- .../LoadStoryFromStoriesPrefsUseCase.kt | 6 ++-- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index d8b43ff0a138..9b3fcbab5d8a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -1,11 +1,11 @@ package org.wordpress.android.ui.stories import com.google.gson.Gson +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId +import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.stories.prefs.StoriesPrefs -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.LocalMediaId -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId import org.wordpress.android.util.StringUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -64,23 +64,23 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( url = mediaFile.fileURL // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. - val localIdKey = mediaFile.id.toLong() + val localIdKey = mediaFile.id.toInt() val remoteIdKey = mediaFile.mediaId.toLong() val localSiteId = post.localSiteId.toLong() storiesPrefs.getSlideWithLocalId( localSiteId, - LocalMediaId(localIdKey) + LocalId(localIdKey) )?.let { it.id = mediaFile.mediaId // update the StoryFrameItem id to hold the same value as the remote mediaID storiesPrefs.saveSlideWithRemoteId( localSiteId, - RemoteMediaId(remoteIdKey), // use the new mediaId as key + RemoteId(remoteIdKey), // use the new mediaId as key it ) // now delete the old entry storiesPrefs.deleteSlideWithLocalId( localSiteId, - LocalMediaId(localIdKey) + LocalId(localIdKey) ) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 7c29f1928d49..41d1d5938a5a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.launch import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode.MAIN import org.wordpress.android.WordPress +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.PostImmutableModel import org.wordpress.android.fluxc.model.SiteModel @@ -30,7 +31,6 @@ import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase import org.wordpress.android.ui.stories.StoriesTrackerHelper import org.wordpress.android.ui.stories.StoryComposerActivity import org.wordpress.android.ui.stories.prefs.StoriesPrefs -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.LocalMediaId import org.wordpress.android.ui.uploads.UploadServiceFacade import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.util.NetworkUtilsWrapper @@ -193,7 +193,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( it.localSiteId.toLong(), // use the local id to save the original, will be replaced later // with mediaModel.mediaId after uploading to the remote site - LocalMediaId(it.id.toLong()), + LocalId(it.id.toInt()), frame ) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 4b632a3a8bb6..aed7d5e74f88 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -7,6 +7,8 @@ import com.wordpress.stories.compose.story.StoryFrameItem import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.FileBackgroundSource import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.UriBackgroundSource import com.wordpress.stories.compose.story.StorySerializerUtils +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId +import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId import javax.inject.Inject import javax.inject.Singleton @@ -20,22 +22,22 @@ class StoriesPrefs @Inject constructor( private val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" } - private fun buildSlideKey(siteId: Long, mediaId: RemoteMediaId): String { + private fun buildSlideKey(siteId: Long, mediaId: RemoteId): String { return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + - KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.mediaId.toString() + KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.value.toString() } - private fun buildSlideKey(siteId: Long, mediaId: LocalMediaId): String { + private fun buildSlideKey(siteId: Long, mediaId: LocalId): String { return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + - KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.id.toString() + KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.value.toString() } - fun checkSlideIdExists(siteId: Long, mediaId: RemoteMediaId): Boolean { + fun checkSlideIdExists(siteId: Long, mediaId: RemoteId): Boolean { val slideIdKey = buildSlideKey(siteId, mediaId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } - fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: RemoteMediaId): Boolean { + fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: RemoteId): Boolean { val storyFrameItem: StoryFrameItem? = getSlideWithRemoteId(siteId, mediaId) storyFrameItem?.let { frame -> // now check the background media exists or is accessible on this device @@ -77,7 +79,7 @@ class StoriesPrefs @Inject constructor( editor.apply() } - fun isValidSlide(siteId: Long, mediaId: RemoteMediaId): Boolean { + fun isValidSlide(siteId: Long, mediaId: RemoteId): Boolean { return checkSlideIdExists(siteId, mediaId) && checkSlideOriginalBackgroundMediaExists(siteId, mediaId) } @@ -86,45 +88,42 @@ class StoriesPrefs @Inject constructor( return PreferenceManager.getDefaultSharedPreferences(context).getString(slideIdKey, null) } - fun getSlideWithRemoteId(siteId: Long, mediaId: RemoteMediaId): StoryFrameItem? { + fun getSlideWithRemoteId(siteId: Long, mediaId: RemoteId): StoryFrameItem? { val jsonSlide = getSlideJson(buildSlideKey(siteId, mediaId)) jsonSlide?.let { return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) } ?: return null } - fun getSlideWithLocalId(siteId: Long, mediaId: LocalMediaId): StoryFrameItem? { + fun getSlideWithLocalId(siteId: Long, mediaId: LocalId): StoryFrameItem? { val jsonSlide = getSlideJson(buildSlideKey(siteId, mediaId)) jsonSlide?.let { return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) } ?: return null } - fun saveSlideWithLocalId(siteId: Long, mediaId: LocalMediaId, storyFrameItem: StoryFrameItem) { + fun saveSlideWithLocalId(siteId: Long, mediaId: LocalId, storyFrameItem: StoryFrameItem) { val slideIdKey = buildSlideKey(siteId, mediaId) saveSlide(slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) } - fun saveSlideWithRemoteId(siteId: Long, mediaId: RemoteMediaId, storyFrameItem: StoryFrameItem) { + fun saveSlideWithRemoteId(siteId: Long, mediaId: RemoteId, storyFrameItem: StoryFrameItem) { val slideIdKey = buildSlideKey(siteId, mediaId) saveSlide(slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) } - fun deleteSlideWithLocalId(siteId: Long, mediaId: LocalMediaId) { + fun deleteSlideWithLocalId(siteId: Long, mediaId: LocalId) { val slideIdKey = buildSlideKey(siteId, mediaId) val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() editor.remove(slideIdKey) editor.apply() } - fun deleteSlideWithRemoteId(siteId: Long, mediaId: RemoteMediaId) { + fun deleteSlideWithRemoteId(siteId: Long, mediaId: RemoteId) { val slideIdKey = buildSlideKey(siteId, mediaId) - PreferenceManager.getDefaultSharedPreferences(context).edit().apply { + PreferenceManager.getDefaultSharedPreferences(context).edit().apply { remove(slideIdKey) apply() } } - - data class RemoteMediaId(val mediaId: Long) - data class LocalMediaId(val id: Long) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 14056fda4035..e7fb88edf057 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -5,12 +5,12 @@ import com.wordpress.stories.compose.story.StoryFrameItem import com.wordpress.stories.compose.story.StoryIndex import com.wordpress.stories.compose.story.StoryRepository import dagger.Reusable +import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.RemoteMediaId import java.util.ArrayList import java.util.HashMap import javax.inject.Inject @@ -36,7 +36,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { for (mediaId in mediaIds) { - if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteMediaId(mediaId.toLong()))) { + if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteId(mediaId.toLong()))) { return false } } @@ -54,7 +54,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( for (mediaId in mediaIds) { var storyFrameItem = storiesPrefs.getSlideWithRemoteId( site.getId().toLong(), - RemoteMediaId(mediaId.toLong()) + RemoteId(mediaId.toLong()) ) if (storyFrameItem != null) { storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) From 240aebb4bdf7d164d1ab5ebba29875335511e787 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 15:26:12 -0300 Subject: [PATCH 088/230] changed method signature for kotlin's Any --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 7e80baa6d018..3fec56348ac8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -34,7 +34,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( return mediaIds } - fun anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles: ArrayList): Boolean { + fun anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles: ArrayList): Boolean { for (mediaFile in mediaFiles) { try { (mediaFile as HashMap)["id"] From a6dee817a13eddd0aecfbda821b5d0767dc8f508 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 7 Oct 2020 15:28:23 -0300 Subject: [PATCH 089/230] moved FrameSaveListener methods to StoriesEventListener lifecycle observer --- .../android/ui/posts/EditPostActivity.java | 134 +-------------- .../ui/posts/editor/StoriesEventListener.kt | 158 ++++++++++++++++++ 2 files changed, 164 insertions(+), 128 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 97bce8aa4f86..ad670889b5f0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -41,13 +41,6 @@ import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; -import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveCompleted; -import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed; -import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress; -import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart; -import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult; -import com.wordpress.stories.compose.story.Story; -import com.wordpress.stories.compose.story.StoryFrameItem; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -159,6 +152,7 @@ import org.wordpress.android.ui.posts.editor.StorePostViewModel.ActivityFinishState; import org.wordpress.android.ui.posts.editor.StorePostViewModel.UpdateFromEditor; import org.wordpress.android.ui.posts.editor.StorePostViewModel.UpdateFromEditor.PostFields; +import org.wordpress.android.ui.posts.editor.StoriesEventListener; import org.wordpress.android.ui.posts.editor.media.AddExistingMediaSource; import org.wordpress.android.ui.posts.editor.media.EditorMedia; import org.wordpress.android.ui.posts.editor.media.EditorMediaListener; @@ -172,7 +166,6 @@ import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; import org.wordpress.android.ui.stories.StoryRepositoryWrapper; -import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent; import org.wordpress.android.ui.stories.prefs.StoriesPrefs; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; @@ -243,7 +236,6 @@ import static org.wordpress.android.analytics.AnalyticsTracker.Stat.APP_REVIEWS_EVENT_INCREMENTED_BY_PUBLISHING_POST_OR_PAGE; import static org.wordpress.android.imageeditor.preview.PreviewImageFragment.PREVIEW_IMAGE_REDUCED_SIZE_FACTOR; import static org.wordpress.android.ui.history.HistoryDetailContainerFragment.KEY_REVISION; -import static org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.TEMPORARY_ID_PREFIX; import kotlin.Unit; import kotlin.jvm.functions.Function0; @@ -343,7 +335,6 @@ enum RestartEditorOptions { private EditorFragmentAbstract mEditorFragment; private EditPostSettingsFragment mEditPostSettingsFragment; private EditorMediaUploadListener mEditorMediaUploadListener; - private StorySaveMediaListener mStorySaveMediaListener; private EditorPhotoPicker mEditorPhotoPicker; private ProgressDialog mProgressDialog; @@ -407,7 +398,7 @@ enum RestartEditorOptions { @Inject StoryRepositoryWrapper mStoryRepositoryWrapper; @Inject LoadStoryFromStoriesPrefsUseCase mLoadStoryFromStoriesPrefsUseCase; @Inject StoriesPrefs mStoriesPrefs; - + @Inject StoriesEventListener mStoriesEventListener; private StorePostViewModel mViewModel; @@ -590,7 +581,7 @@ protected void onCreate(Bundle savedInstanceState) { } if (mEditorFragment instanceof StorySaveMediaListener) { - mStorySaveMediaListener = (StorySaveMediaListener) mEditorFragment; + mStoriesEventListener.setSaveMediaListener((StorySaveMediaListener) mEditorFragment); } } @@ -668,6 +659,8 @@ protected void onCreate(Bundle savedInstanceState) { ActivityId.trackLastActivity(ActivityId.POST_EDITOR); setupPrepublishingBottomSheetRunnable(); + + mStoriesEventListener.start(this.getLifecycle(), mSite); } private void fetchSiteSettings() { @@ -2200,7 +2193,7 @@ public Fragment getItem(int position) { } if (mEditorFragment instanceof StorySaveMediaListener) { - mStorySaveMediaListener = (StorySaveMediaListener) mEditorFragment; + mStoriesEventListener.setSaveMediaListener((StorySaveMediaListener) mEditorFragment); } break; case PAGE_SETTINGS: @@ -3154,121 +3147,6 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } } - // Story Frame Save Service events - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onStoryFrameSaveStart(FrameSaveStart event) { - if (isFinishing()) { - return; - } - String localMediaId = String.valueOf(event.getFrameId()); - if (mStorySaveMediaListener != null) { - float progress = mStoryRepositoryWrapper.getCurrentStorySaveProgress(event.getStoryIndex(), 0.0f); - mStorySaveMediaListener.onMediaSaveReattached(localMediaId, progress); - } - } - - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onStoryFrameSaveProgress(FrameSaveProgress event) { - if (isFinishing()) { - return; - } - String localMediaId = String.valueOf(event.getFrameId()); - if (mStorySaveMediaListener != null) { - float progress = mStoryRepositoryWrapper.getCurrentStorySaveProgress( - event.getStoryIndex(), - event.getProgress() - ); - mStorySaveMediaListener.onMediaSaveProgress(localMediaId, progress); - } - } - - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onStoryFrameSaveCompleted(FrameSaveCompleted event) { - if (isFinishing()) { - return; - } - String localMediaId = event.getFrameId(); - if (mStorySaveMediaListener != null) { - // check whether this is a temporary file being just saved (so we don't have a proper local MediaModel yet) - // catch ( NumberFormatException e) - if (localMediaId.startsWith(TEMPORARY_ID_PREFIX)) { - Story story = mStoryRepositoryWrapper.getStoryAtIndex(event.getStoryIndex()); - - // first, update the media's url - StoryFrameItem frame = story.getFrames().get(event.getFrameIndex()); - mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, - Uri.fromFile(frame.getComposedFrameFile()).toString()); - - // now update progress - float totalProgress = mStoryRepositoryWrapper.getCurrentStorySaveProgress(event.getStoryIndex(), 0.0f); - mStorySaveMediaListener.onMediaSaveProgress(localMediaId, totalProgress); - } else { - MediaModel mediaModel = mMediaStore.getSiteMediaWithId(mSite, Long.parseLong(localMediaId)); - if (mediaModel != null) { - MediaFile mediaFile = FluxCUtils.mediaFileFromMediaModel(mediaModel); - mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, mediaFile.getFileURL()); - } - } - } - } - - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onStoryFrameMediaModelCreated(StoryFrameMediaModelCreatedEvent event) { - if (isFinishing()) { - return; - } - - if (mStorySaveMediaListener != null) { - mStorySaveMediaListener.onMediaModelCreatedForFile(event.getOldId(), event.getNewId(), event.getOldUrl()); - } - } - - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onStoryFrameSaveFailed(FrameSaveFailed event) { - if (isFinishing()) { - return; - } - String localMediaId = String.valueOf(event.getFrameId()); -// if (mStorySaveMediaListener != null) { -// mStorySaveMediaListener.onMediaSaveFailed(localMediaId); -// } - // just update progress, we may have still some other frames in this story that need be saved. - // we will send the Failed signal once all the Story frames have been processed - if (mStorySaveMediaListener != null) { - float progress = mStoryRepositoryWrapper.getCurrentStorySaveProgress(event.getStoryIndex(), 0.0f); - mStorySaveMediaListener.onMediaSaveReattached(localMediaId, progress); - } - } - - - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onStorySaveProcessFinished(StorySaveResult event) { - if (isFinishing()) { - return; - } - - Story story = mStoryRepositoryWrapper.getStoryAtIndex(event.getStoryIndex()); - if (event.isSuccess() && event.getFrameSaveResult().size() == story.getFrames().size()) { - // take the first frame IDs and mediaUri - String localMediaId = String.valueOf(story.getFrames().get(0).getId()); - String mediaUrl = Uri.fromFile(story.getFrames().get(0).getComposedFrameFile()).toString(); - if (mStorySaveMediaListener != null) { - mStorySaveMediaListener.onMediaSaveSucceeded(localMediaId, mediaUrl); - } - } else { - String localMediaId = String.valueOf(story.getFrames().get(0).getId()); - if (mStorySaveMediaListener != null) { - mStorySaveMediaListener.onMediaSaveFailed(localMediaId); - } - } - } - // FluxC events @SuppressWarnings("unused") diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt new file mode 100644 index 000000000000..4a2045aae724 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -0,0 +1,158 @@ +package org.wordpress.android.ui.posts.editor + +import android.net.Uri +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.Lifecycle.State.CREATED +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.OnLifecycleEvent +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveCompleted +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress +import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart +import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import org.wordpress.android.editor.gutenberg.StorySaveMediaListener +import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.model.MediaModel +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.MediaStore +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX +import org.wordpress.android.ui.stories.StoryRepositoryWrapper +import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent +import org.wordpress.android.util.FluxCUtils +import org.wordpress.android.util.helpers.MediaFile +import javax.inject.Inject + +class StoriesEventListener @Inject constructor( + private val dispatcher: Dispatcher, + private val mediaStore: MediaStore, + private val storyRepositoryWrapper: StoryRepositoryWrapper +) : LifecycleObserver { + private lateinit var lifecycle: Lifecycle + private lateinit var site: SiteModel + private var storySaveMediaListener: StorySaveMediaListener? = null + + @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) + private fun onCreate() { + dispatcher.register(this) + EventBus.getDefault().register(this) + } + + /** + * Handles the [Lifecycle.Event.ON_DESTROY] event to cleanup the registration for dispatcher and removing the + * observer for lifecycle. + */ + @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) + private fun onDestroy() { + lifecycle.removeObserver(this) + dispatcher.unregister(this) + EventBus.getDefault().unregister(this) + } + + fun start(lifecycle: Lifecycle, site: SiteModel) { + this.site = site + this.lifecycle = lifecycle + this.lifecycle.addObserver(this) + } + + fun setSaveMediaListener(newListener: StorySaveMediaListener) { + storySaveMediaListener = newListener + } + + // Story Frame Save Service events + @Subscribe(threadMode = ThreadMode.MAIN) + fun onStoryFrameSaveStart(event: FrameSaveStart) { + if (!lifecycle.currentState.isAtLeast(CREATED)) { + return + } + val localMediaId = event.frameId.toString() + val progress: Float = storyRepositoryWrapper.getCurrentStorySaveProgress(event.storyIndex, 0.0f) + storySaveMediaListener?.onMediaSaveReattached(localMediaId, progress) + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onStoryFrameSaveProgress(event: FrameSaveProgress) { + if (!lifecycle.currentState.isAtLeast(CREATED)) { + return + } + val localMediaId = event.frameId.toString() + val progress: Float = storyRepositoryWrapper.getCurrentStorySaveProgress( + event.storyIndex, + event.progress + ) + storySaveMediaListener?.onMediaSaveProgress(localMediaId, progress) + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onStoryFrameSaveCompleted(event: FrameSaveCompleted) { + if (!lifecycle.currentState.isAtLeast(CREATED)) { + return + } + val localMediaId = requireNotNull(event.frameId) + + // check whether this is a temporary file being just saved (so we don't have a proper local MediaModel yet) + // catch ( NumberFormatException e) + if (localMediaId.startsWith(TEMPORARY_ID_PREFIX)) { + val (frames) = storyRepositoryWrapper.getStoryAtIndex(event.storyIndex) + + // first, update the media's url + val frame = frames[event.frameIndex] + storySaveMediaListener?.onMediaSaveSucceeded( + localMediaId, + Uri.fromFile(frame.composedFrameFile).toString() + ) + + // now update progress + val totalProgress: Float = storyRepositoryWrapper.getCurrentStorySaveProgress( + event.storyIndex, + 0.0f + ) + storySaveMediaListener?.onMediaSaveProgress(localMediaId, totalProgress) + } else { + val mediaModel: MediaModel = mediaStore.getSiteMediaWithId(site, localMediaId.toLong()) + if (mediaModel != null) { + val mediaFile: MediaFile = FluxCUtils.mediaFileFromMediaModel(mediaModel) + storySaveMediaListener?.onMediaSaveSucceeded(localMediaId, mediaFile.getFileURL()) + } + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onStoryFrameMediaModelCreated(event: StoryFrameMediaModelCreatedEvent) { + if (!lifecycle.currentState.isAtLeast(CREATED)) { + return + } + storySaveMediaListener?.onMediaModelCreatedForFile(event.oldId, event.newId, event.oldUrl) + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onStoryFrameSaveFailed(event: FrameSaveFailed) { + if (!lifecycle.currentState.isAtLeast(CREATED)) { + return + } + val localMediaId = event.frameId.toString() + // just update progress, we may have still some other frames in this story that need be saved. + // we will send the Failed signal once all the Story frames have been processed + val progress: Float = storyRepositoryWrapper.getCurrentStorySaveProgress(event.storyIndex, 0.0f) + storySaveMediaListener?.onMediaSaveReattached(localMediaId, progress) + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onStorySaveProcessFinished(event: StorySaveResult) { + if (!lifecycle.currentState.isAtLeast(CREATED)) { + return + } + val story = storyRepositoryWrapper.getStoryAtIndex(event.storyIndex) + if (event.isSuccess() && event.frameSaveResult.size == story.frames.size) { + // take the first frame IDs and mediaUri + val localMediaId = story.frames[0].id.toString() + val mediaUrl: String = Uri.fromFile(story.frames[0].composedFrameFile).toString() + storySaveMediaListener?.onMediaSaveSucceeded(localMediaId, mediaUrl) + } else { + val localMediaId = story.frames[0].id.toString() + storySaveMediaListener?.onMediaSaveFailed(localMediaId) + } + } +} From 2c54019f4edb6e1d905ec05f9a31c7a796ea334c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 8 Oct 2020 15:48:53 -0300 Subject: [PATCH 090/230] made MediaUploadReadyProcessor injectable, and injecting SaveStoryGutenbergBlockUseCase --- .../wordpress/android/modules/AppComponent.java | 3 +++ .../ui/uploads/MediaUploadReadyProcessor.java | 16 ++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java index de63dfa201aa..1b4ed181b6fe 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java @@ -182,6 +182,7 @@ import org.wordpress.android.ui.themes.ThemeBrowserActivity; import org.wordpress.android.ui.themes.ThemeBrowserFragment; import org.wordpress.android.ui.uploads.MediaUploadHandler; +import org.wordpress.android.ui.uploads.MediaUploadReadyProcessor; import org.wordpress.android.ui.uploads.PostUploadHandler; import org.wordpress.android.ui.uploads.UploadService; import org.wordpress.android.ui.whatsnew.FeatureAnnouncementDialogFragment; @@ -584,6 +585,8 @@ public interface AppComponent extends AndroidInjector { void inject(MediaPickerFragment object); + void inject(MediaUploadReadyProcessor object); + // Allows us to inject the application without having to instantiate any modules, and provides the Application // in the app graph @Component.Builder diff --git a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java index 1e1a6b419858..7eb3180df08d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadReadyProcessor.java @@ -9,11 +9,18 @@ import org.wordpress.android.ui.posts.PostUtils; import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase; -import org.wordpress.android.ui.stories.prefs.StoriesPrefs; import org.wordpress.android.util.helpers.MediaFile; +import javax.inject.Inject; + public class MediaUploadReadyProcessor implements MediaUploadReadyListener { + @Inject SaveStoryGutenbergBlockUseCase mSaveStoryGutenbergBlockUseCase; + + @Inject public MediaUploadReadyProcessor() { + ((WordPress) WordPress.getContext().getApplicationContext()).component().inject(this); + } + @Override public PostModel replaceMediaFileWithUrlInPost(@Nullable PostModel post, String localMediaId, MediaFile mediaFile, String siteUrl) { @@ -22,11 +29,8 @@ public PostModel replaceMediaFileWithUrlInPost(@Nullable PostModel post, String boolean showGutenbergEditor = AppPrefs.isGutenbergEditorEnabled(); if (PostUtils.contentContainsWPStoryGutenbergBlocks(post.getContent())) { - SaveStoryGutenbergBlockUseCase saveStoryGutenbergBlockUseCase = new SaveStoryGutenbergBlockUseCase( - new StoriesPrefs(WordPress.getContext()) - ); - saveStoryGutenbergBlockUseCase - .replaceLocalMediaIdsWithRemoteMediaIdsInPost(post, mediaFile); + mSaveStoryGutenbergBlockUseCase + .replaceLocalMediaIdsWithRemoteMediaIdsInPost(post, mediaFile); } else if (showGutenbergEditor && PostUtils.contentContainsGutenbergBlocks(post.getContent())) { post.setContent( PostUtils.replaceMediaFileWithUrlInGutenbergPost(post.getContent(), localMediaId, mediaFile, From cadf22b4df7d65b78aa6c3d37ef339dbca0aea22 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 8 Oct 2020 15:53:42 -0300 Subject: [PATCH 091/230] modified comment --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index e7fb88edf057..9d717a4bef5d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -96,7 +96,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( ) // now look for a Story in the StoryRepository that has all these frames and, if not found, let's - // just build the Story object ourselves to keep these files arrangement + // just build the Story object ourselves to match the order in which the media files were passed. var storyIndex = storyRepositoryWrapper.findStoryContainingStoryFrameItemsByIds(mediaIds) if (storyIndex == StoryRepository.DEFAULT_NONE_SELECTED) { // the StoryRepository didn't have it but we have editable serialized slides so, From 62fec15aded73be7233ca1b13fdc3cb06122e7e9 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 8 Oct 2020 16:20:33 -0300 Subject: [PATCH 092/230] adding specific error dialogs in case we dont find the backing media for a given story slide so to make it editable --- .../android/ui/posts/EditPostActivity.java | 38 +++++++++++++++---- WordPress/src/main/res/values/strings.xml | 4 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 168f3ad232c9..65f156da84ca 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -398,6 +398,8 @@ enum RestartEditorOptions { private SiteSettingsInterface mSiteSettings; private boolean mIsJetpackSsoEnabled; + private boolean mNetworkErrorOnLastMediaFetchAttempt = false; + public static boolean checkToRestart(@NonNull Intent data) { return data.hasExtra(EditPostActivity.EXTRA_RESTART_EDITOR) && RestartEditorOptions.valueOf(data.getStringExtra(EditPostActivity.EXTRA_RESTART_EDITOR)) @@ -3075,14 +3077,30 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } else { // unfortunately we couldn't even load the remote media Ids indicated by the StoryBlock so we can't allow // editing at this time :( - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); - builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); - builder.setMessage(getString(R.string.dialog_edit_story_unavailable_message)); - builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { - dialog.dismiss(); - }); - AlertDialog dialog = builder.create(); - dialog.show(); + if (mNetworkErrorOnLastMediaFetchAttempt) { + // there was an error fetching media when we were loading the editor, + // we *may* still have a possibility, tell the user they may try refreshing the media again + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); + builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); + builder.setMessage(getString(R.string.dialog_edit_story_unavailable_message)); + builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { + // try another fetchMedia request + fetchMediaList(); + dialog.dismiss(); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + } else { + // unrecoverable error, nothing we can do, inform the user :(. + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); + builder.setTitle(getString(R.string.dialog_edit_story_unrecoverable_title)); + builder.setMessage(getString(R.string.dialog_edit_story_unrecoverable_message)); + builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { + dialog.dismiss(); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + } } } @@ -3123,6 +3141,9 @@ public void onMediaUploaded(OnMediaUploaded event) { public void onMediaListFetched(OnMediaListFetched event) { // no op - we don't need to check anything just now, but declaring the method so it's // clear we make a request to FetchMedia in this class. + if (event != null) { + mNetworkErrorOnLastMediaFetchAttempt = event.isError(); + } } @SuppressWarnings("unused") @@ -3253,6 +3274,7 @@ private void refreshEditorTheme() { private void fetchMediaList() { // do not refresh if there is no network if (!NetworkUtils.isNetworkAvailable(this)) { + mNetworkErrorOnLastMediaFetchAttempt = true; return; } FetchMediaListPayload payload = diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index aa8a9915c1cd..5a4ed6dda55a 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2886,7 +2886,9 @@ Limited Story Editing This story was edited on a different device and the ability to edit certain objects may be limited. Can\'t edit Story - This story was created on a different device and can\'t be edited at this moment. + Unable to load media for this story. Check your internet connection and try again in a moment. + Can\'t edit Story + We couldn\'t find the media for your story on this site. Capture Flip camera Flash From 1e5e84d6e753000f216d961fa829eb323e3dcab6 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 8 Oct 2020 17:54:35 -0300 Subject: [PATCH 093/230] fixed method signature --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index b438e9b7fa54..f53f4a94915b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -1,6 +1,5 @@ package org.wordpress.android.ui.stories -import android.content.Context import com.google.gson.Gson import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.ui.posts.EditPostRepository @@ -135,7 +134,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( postModel.setContent(content) } - fun replaceLocalMediaIdsWithRemoteMediaIdsInPost(context: Context, postModel: PostModel, mediaFile: MediaFile) { + fun replaceLocalMediaIdsWithRemoteMediaIdsInPost(postModel: PostModel, mediaFile: MediaFile) { val gson = Gson() findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( postModel, From 437c44b9500328b15976834a97639f293f0d1c91 Mon Sep 17 00:00:00 2001 From: mzorz Date: Thu, 8 Oct 2020 22:47:56 -0300 Subject: [PATCH 094/230] Update WordPress/src/main/res/values/strings.xml Co-authored-by: Alex --- WordPress/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 5a4ed6dda55a..017e32f35f7e 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2888,7 +2888,7 @@ Can\'t edit Story Unable to load media for this story. Check your internet connection and try again in a moment. Can\'t edit Story - We couldn\'t find the media for your story on this site. + We couldn\'t find the media for this story on the site. Capture Flip camera Flash From 13e5bfd2ca54ff0635dabe11769dc847dddb8f7f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 9 Oct 2020 10:25:02 -0300 Subject: [PATCH 095/230] removed comment --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 65f156da84ca..71e5b1e78b1d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3139,8 +3139,6 @@ public void onMediaUploaded(OnMediaUploaded event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onMediaListFetched(OnMediaListFetched event) { - // no op - we don't need to check anything just now, but declaring the method so it's - // clear we make a request to FetchMedia in this class. if (event != null) { mNetworkErrorOnLastMediaFetchAttempt = event.isError(); } From f74f63bcca376a0fe6d5754577d83f4ccc578427 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 9 Oct 2020 13:23:27 -0300 Subject: [PATCH 096/230] udpated gutenberg-mobile and submodules --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 33f2addaab7f..0f8916f5a4dc 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 33f2addaab7f5338f791d968680cb6f1e97b4ffa +Subproject commit 0f8916f5a4dccd263cfbecfb88e1a6df61cf09f2 From 0d193db0a15985d69e5b477889fadbcaa598bc17 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 9 Oct 2020 15:41:15 -0300 Subject: [PATCH 097/230] updated gutenberg-mobile hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 0f8916f5a4dc..7c7430cf0261 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 0f8916f5a4dccd263cfbecfb88e1a6df61cf09f2 +Subproject commit 7c7430cf026148db0bfea6392cf938f27c43e237 From 1f91b0f1991857004aacd9ebbe368384035a6fe4 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 9 Oct 2020 15:56:39 -0300 Subject: [PATCH 098/230] updated gutenberg-mobile hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 7c7430cf0261..6360f4c43299 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 7c7430cf026148db0bfea6392cf938f27c43e237 +Subproject commit 6360f4c43299fcac464a775196a8e7627d47fa81 From 78ed9dba6033b99b73899dc32e60e4046d5cb8d4 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 10 Oct 2020 11:50:05 -0300 Subject: [PATCH 099/230] updated gutenberg mobile commit hash to fix initial html data setup --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 6360f4c43299..aa1b58b4d8ca 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 6360f4c43299fcac464a775196a8e7627d47fa81 +Subproject commit aa1b58b4d8cae446cf8a84542709b0fde1a40fc2 From 670fb0810376b9356e90381a636b50a6fc37bba0 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 10 Oct 2020 11:59:35 -0300 Subject: [PATCH 100/230] updated gutenberg mobile hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 8eb45016dac8..445bdec90982 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 8eb45016dac8b3c3a478fbfef52cd2f74e2406fe +Subproject commit 445bdec909822945a2cc33cf3c193dfe7d7e5bc9 From f3c949e6fd2b9b8c6d5a6c2e45062c5b2f2a0520 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 10 Oct 2020 13:28:25 -0300 Subject: [PATCH 101/230] using new method names for gutetnberg-mobile bridge --- .../gutenberg/GutenbergContainerFragment.java | 12 ++++++------ .../gutenberg/GutenbergEditorFragment.java | 17 ++++++++++------- libs/gutenberg-mobile | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index b38465c240dc..36e657ba4234 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -23,12 +23,12 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnGutenbergDidSendButtonPressedActionListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnImageFullscreenPreviewListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnLogGutenbergUserEventListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachMediaSavingQueryListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachMediaUploadQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaEditorListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStorySavingReattachQueryListener; import java.util.ArrayList; @@ -54,8 +54,8 @@ public boolean hasReceivedAnyContent() { } public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onMediaLibraryButtonListener, - OnReattachQueryListener onReattachQueryListener, - OnStorySavingReattachQueryListener onStorySavingReattachQueryListener, + OnReattachMediaUploadQueryListener onReattachQueryListener, + OnReattachMediaSavingQueryListener onStorySavingReattachQueryListener, OnEditorMountListener onEditorMountListener, OnEditorAutosaveListener onEditorAutosaveListener, OnAuthHeaderRequestedListener onAuthHeaderRequestedListener, @@ -214,7 +214,7 @@ public void replaceUnsupportedBlock(String content, String blockId) { } public void replaceStoryEditedBlock(String mediaFiles, String blockId) { - mWPAndroidGlueCode.replaceStoryEditedBlock(mediaFiles, blockId); + mWPAndroidGlueCode.replaceMediaFilesEditedBlock(mediaFiles, blockId); } public void updateTheme(Bundle editorTheme) { @@ -243,7 +243,7 @@ public void mediaFileSaveSucceeded(final String mediaId, final String mediaUrl) } public void onStorySaveResult(final String storyFirstMediaId, final boolean success) { - mWPAndroidGlueCode.storySaveResult(storyFirstMediaId, success); + mWPAndroidGlueCode.mediaCollectionFinalSaveResult(storyFirstMediaId, success); } public void onMediaModelCreatedForFile(String oldId, String newId, String oldUrl) { diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index c34b07ff7f6f..ded2ebc514bf 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -60,11 +60,11 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnGutenbergDidRequestUnsupportedBlockFallbackListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnGutenbergDidSendButtonPressedActionListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnLogGutenbergUserEventListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachMediaSavingQueryListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachMediaUploadQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStorySavingReattachQueryListener; import java.util.ArrayList; import java.util.HashMap; @@ -265,15 +265,15 @@ public void onOtherMediaButtonClicked(String mediaSource, boolean allowMultipleS } } }, - new OnReattachQueryListener() { + new OnReattachMediaUploadQueryListener() { @Override public void onQueryCurrentProgressForUploadingMedia() { updateFailedMediaState(); updateMediaProgress(); } }, - new OnStorySavingReattachQueryListener() { - @Override public void onQueryCurrentProgressForStoryMediaSaving() { + new OnReattachMediaSavingQueryListener() { + @Override public void onQueryCurrentProgressForSavingMedia() { // TODO: probably go through mFailedMediaIds, and see if any block in the post content // has these mediaFIleIds. If there's a match, mark such a block in FAILED state. updateFailedMediaState(); @@ -512,8 +512,11 @@ private void updateFailedMediaState() { private void updateMediaProgress() { for (String mediaId : mUploadingMediaProgressMax.keySet()) { - getGutenbergContainerFragment().mediaFileUploadProgress(Integer.valueOf(mediaId), - mUploadingMediaProgressMax.get(mediaId)); + // upload progress should work on numeric mediaIds only + if (!TextUtils.isEmpty(mediaId) && TextUtils.isDigitsOnly(mediaId)) { + getGutenbergContainerFragment().mediaFileUploadProgress(Integer.valueOf(mediaId), + mUploadingMediaProgressMax.get(mediaId)); + } } } diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 445bdec90982..5e873998f92d 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 445bdec909822945a2cc33cf3c193dfe7d7e5bc9 +Subproject commit 5e873998f92dd361dedc538fd5c0f5a9031c2166 From 69b1aa2a0daf5bb04af426bd766a30be97012dbc Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 10 Oct 2020 13:33:30 -0300 Subject: [PATCH 102/230] updated gutenberg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 5e873998f92d..c6319697105b 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 5e873998f92dd361dedc538fd5c0f5a9031c2166 +Subproject commit c6319697105b55fae3581fa802ef7c277684aa98 From f7c9657f00f6122ebd10a2c7370ae4253ebd4f66 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 10 Oct 2020 20:05:22 -0300 Subject: [PATCH 103/230] renamed bridge methods to more generic onMediaFilesEditorLoadRequestListener --- .../editor/gutenberg/GutenbergContainerFragment.java | 6 +++--- .../android/editor/gutenberg/GutenbergEditorFragment.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 36e657ba4234..9e37c239742e 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -28,7 +28,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaEditorListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaFilesEditorLoadRequestListener; import java.util.ArrayList; @@ -69,7 +69,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidSendButtonPressedActionListener, AddMentionUtil addMentionUtil, OnStarterPageTemplatesTooltipShownEventListener onSPTTooltipShownEventListener, - OnStoryCreatorLoadRequestListener onStoryCreatorRequestListener, + OnMediaFilesEditorLoadRequestListener onMediaFilesEditorLoadRequestListener, boolean isDarkMode) { mWPAndroidGlueCode.attachToContainer( viewGroup, @@ -87,7 +87,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidSendButtonPressedActionListener, addMentionUtil, onSPTTooltipShownEventListener, - onStoryCreatorRequestListener, + onMediaFilesEditorLoadRequestListener, isDarkMode); } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index ded2ebc514bf..c511f9362eda 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -64,7 +64,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachMediaUploadQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStoryCreatorLoadRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaFilesEditorLoadRequestListener; import java.util.ArrayList; import java.util.HashMap; @@ -343,8 +343,8 @@ public boolean onRequestStarterPageTemplatesTooltipShown() { return mEditorFragmentListener.onGutenbergEditorRequestStarterPageTemplatesTooltipShown(); } }, - new OnStoryCreatorLoadRequestListener() { - @Override public void onRequestStoryCreatorLoad(ArrayList mediaFiles, String blockId) { + new OnMediaFilesEditorLoadRequestListener() { + @Override public void onRequestMediaFilesEditorLoad(ArrayList mediaFiles, String blockId) { mEditorFragmentListener.onStoryComposerLoadRequested(mediaFiles, blockId); } }, From 864317f7a355790e7c0d8a548273f5c036e91d1a Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 10 Oct 2020 20:06:51 -0300 Subject: [PATCH 104/230] updated gutenberg-mobile commit hash with bridge method renames --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index c6319697105b..e8aea4af51d5 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit c6319697105b55fae3581fa802ef7c277684aa98 +Subproject commit e8aea4af51d58d1a5d4941414d550dd411161394 From 88fdf9df946f7500086f94c98b4d0853df211bb6 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sun, 11 Oct 2020 07:57:17 -0300 Subject: [PATCH 105/230] updated commit hash for gutenberg-mobile and stories-android, minor linter fixes --- libs/gutenberg-mobile | 2 +- libs/stories-android | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index e8aea4af51d5..be942f006cef 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit e8aea4af51d58d1a5d4941414d550dd411161394 +Subproject commit be942f006ceffb9850044ba6ad04f299a63e275d diff --git a/libs/stories-android b/libs/stories-android index 7966a7c7364c..2395566a4470 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 7966a7c7364c347170ba6986c8259018d69f9009 +Subproject commit 2395566a4470d6751bdb547bd231f9fdb31f2ca0 From 745a1c71ce6d55515740746fd877be8289827701 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sun, 11 Oct 2020 08:04:31 -0300 Subject: [PATCH 106/230] updated gutenberg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index be942f006cef..e4b907c3e9a9 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit be942f006ceffb9850044ba6ad04f299a63e275d +Subproject commit e4b907c3e9a971c8e0021e310ba4b86dcdb92076 From 8e415babbf281f77d11b057b8e01d3145ea78aa3 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sun, 11 Oct 2020 10:46:12 -0300 Subject: [PATCH 107/230] wired in storySaveMediaListener.onStorySaveResult() correctly --- .../android/ui/posts/editor/StoriesEventListener.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index 4a2045aae724..15e023817247 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -137,6 +137,7 @@ class StoriesEventListener @Inject constructor( // we will send the Failed signal once all the Story frames have been processed val progress: Float = storyRepositoryWrapper.getCurrentStorySaveProgress(event.storyIndex, 0.0f) storySaveMediaListener?.onMediaSaveReattached(localMediaId, progress) + // storySaveMediaListener?.onMediaSaveFailed(localMediaId) } @Subscribe(threadMode = ThreadMode.MAIN) @@ -145,14 +146,10 @@ class StoriesEventListener @Inject constructor( return } val story = storyRepositoryWrapper.getStoryAtIndex(event.storyIndex) - if (event.isSuccess() && event.frameSaveResult.size == story.frames.size) { + if (event.frameSaveResult.size == story.frames.size) { // take the first frame IDs and mediaUri val localMediaId = story.frames[0].id.toString() - val mediaUrl: String = Uri.fromFile(story.frames[0].composedFrameFile).toString() - storySaveMediaListener?.onMediaSaveSucceeded(localMediaId, mediaUrl) - } else { - val localMediaId = story.frames[0].id.toString() - storySaveMediaListener?.onMediaSaveFailed(localMediaId) + storySaveMediaListener?.onStorySaveResult(localMediaId, event.isSuccess()) } } } From 477f23139954f28f7cb0bcaa4523751ce6c93a62 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sun, 11 Oct 2020 10:46:55 -0300 Subject: [PATCH 108/230] cover the case for signaling temporal ids in media file save progress and failure --- .../editor/gutenberg/GutenbergEditorFragment.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index c511f9362eda..c81f7fdb9606 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -506,7 +506,12 @@ public void resetUploadingMediaToFailed(Set failedMediaIds) { private void updateFailedMediaState() { for (String mediaId : mFailedMediaIds) { - getGutenbergContainerFragment().mediaFileUploadFailed(Integer.valueOf(mediaId)); + // upload progress should work on numeric mediaIds only + if (!TextUtils.isEmpty(mediaId) && TextUtils.isDigitsOnly(mediaId)) { + getGutenbergContainerFragment().mediaFileUploadFailed(Integer.valueOf(mediaId)); + } else { + getGutenbergContainerFragment().mediaFileSaveFailed(mediaId); + } } } @@ -516,6 +521,9 @@ private void updateMediaProgress() { if (!TextUtils.isEmpty(mediaId) && TextUtils.isDigitsOnly(mediaId)) { getGutenbergContainerFragment().mediaFileUploadProgress(Integer.valueOf(mediaId), mUploadingMediaProgressMax.get(mediaId)); + } else { + getGutenbergContainerFragment().mediaFileSaveProgress(mediaId, + mUploadingMediaProgressMax.get(mediaId)); } } } From dc429da468ac567b5251fb368a53827b7bf68b68 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sun, 11 Oct 2020 11:00:25 -0300 Subject: [PATCH 109/230] updated gutenberg-mobile commit hash for error handling WIP --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index e4b907c3e9a9..90f84ac9da86 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit e4b907c3e9a971c8e0021e310ba4b86dcdb92076 +Subproject commit 90f84ac9da86e576232508e83c8efed8cbeb07b9 From 823404cfd8ea5032a6646598c0788369bc903fcf Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 10:16:07 -0300 Subject: [PATCH 110/230] added upload retry and cancel bridge methods for mediaFiles collection based block Story block --- .../android/ui/posts/EditPostActivity.java | 57 ++++++++++++++++ WordPress/src/main/res/values/strings.xml | 1 + .../editor/EditorFragmentAbstract.java | 4 +- .../gutenberg/GutenbergContainerFragment.java | 6 +- .../gutenberg/GutenbergEditorFragment.java | 67 ++++++++++++++++++- libs/gutenberg-mobile | 2 +- 6 files changed, 130 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 174fce50cd68..36cb23e11d5a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3165,6 +3165,63 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } } + @Override public void onRetryUploadForMediaCollection(ArrayList mediaFiles) { + ArrayList mediaIdsToRetry = new ArrayList<>(); + for (Object mediaFile : mediaFiles) { + int localMediaId + = StringUtils.stringToInt(((HashMap) mediaFile).toString(), 0); + if (localMediaId != 0) { + MediaModel media = mMediaStore.getMediaWithLocalId(localMediaId); + // if we find at least one item in the mediaFiles collection passed + // for which we don't have a local MediaModel, just tell the user and bail + if (media == null) { + AppLog.e(T.MEDIA, "Can't find media with local id: " + localMediaId); + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); + builder.setTitle(getString(R.string.cannot_retry_deleted_media_item_fatal)); + builder.setPositiveButton(R.string.yes, (dialog, id) -> { + dialog.dismiss(); + }); + + builder.setNegativeButton(getString(R.string.no), (dialog, id) -> dialog.dismiss()); + + AlertDialog dialog = builder.create(); + dialog.show(); + + return; + } + + if (media.getUrl() != null && media.getUploadState().equals(MediaUploadState.UPLOADED.toString())) { + // Note: we should actually do this when the editor fragment starts instead of waiting for user input. + // Notify the editor fragment upload was successful and it should replace the local url by the remote url. + if (mEditorMediaUploadListener != null) { + mEditorMediaUploadListener.onMediaUploadSucceeded(String.valueOf(media.getId()), + FluxCUtils.mediaFileFromMediaModel(media)); + } + } else { + UploadService.cancelFinalNotification(this, mEditPostRepository.getPost()); + UploadService.cancelFinalNotificationForMedia(this, mSite); + mediaIdsToRetry.add(localMediaId); + } + } + } + + if (!mediaIdsToRetry.isEmpty()) { + mEditorMedia.retryFailedMediaAsync(mediaIdsToRetry); + } + AnalyticsTracker.track(Stat.EDITOR_UPLOAD_MEDIA_RETRIED); + } + + @Override public void onCancelUploadForMediaCollection(ArrayList mediaFiles) { + // just cancel upload for each media + for (Object mediaFile : mediaFiles) { + int localMediaId + = StringUtils.stringToInt(((HashMap) mediaFile).get("id").toString(), 0); + if (localMediaId != 0) { + mEditorMedia.cancelMediaUploadAsync(localMediaId, false); + } + } + } + // FluxC events @SuppressWarnings("unused") diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 502d7f9a0212..ff075553c4da 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -205,6 +205,7 @@ Some media can\'t be deleted at this time. Try again later. Media has been removed. Delete it from this post? + Media has been removed. Try editing your Story. You don\'t have any media No media matching your search You don\'t have any images diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java index 277e0e3bf4b6..11bd1dfe3fff 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java @@ -206,8 +206,10 @@ public interface EditorFragmentListener { void onGutenbergEditorSetStarterPageTemplatesTooltipShown(boolean tooltipShown); boolean onGutenbergEditorRequestStarterPageTemplatesTooltipShown(); String getErrorMessageFromMedia(int mediaId); - void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId); void showJetpackSettings(); + void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId); + void onRetryUploadForMediaCollection(ArrayList mediaFiles); + void onCancelUploadForMediaCollection(ArrayList mediaFiles); } /** diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 9e37c239742e..4bed0d26769f 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -28,7 +28,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaEditorListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaFilesEditorLoadRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaFilesCollectionBasedBlockEditorListener; import java.util.ArrayList; @@ -69,7 +69,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidSendButtonPressedActionListener, AddMentionUtil addMentionUtil, OnStarterPageTemplatesTooltipShownEventListener onSPTTooltipShownEventListener, - OnMediaFilesEditorLoadRequestListener onMediaFilesEditorLoadRequestListener, + OnMediaFilesCollectionBasedBlockEditorListener onMediaFilesCollectionBasedBlockEditorListener, boolean isDarkMode) { mWPAndroidGlueCode.attachToContainer( viewGroup, @@ -87,7 +87,7 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidSendButtonPressedActionListener, addMentionUtil, onSPTTooltipShownEventListener, - onMediaFilesEditorLoadRequestListener, + onMediaFilesCollectionBasedBlockEditorListener, isDarkMode); } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index c81f7fdb9606..9202ef2361ed 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -46,6 +46,7 @@ import org.wordpress.android.util.AppLog.T; import org.wordpress.android.util.PermissionUtils; import org.wordpress.android.util.ProfilingUtils; +import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.ToastUtils; import org.wordpress.android.util.helpers.MediaFile; import org.wordpress.android.util.helpers.MediaGallery; @@ -64,7 +65,7 @@ import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnReattachMediaUploadQueryListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnStarterPageTemplatesTooltipShownEventListener; import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaLibraryButtonListener; -import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaFilesEditorLoadRequestListener; +import org.wordpress.mobile.WPAndroidGlue.WPAndroidGlueCode.OnMediaFilesCollectionBasedBlockEditorListener; import java.util.ArrayList; import java.util.HashMap; @@ -343,10 +344,18 @@ public boolean onRequestStarterPageTemplatesTooltipShown() { return mEditorFragmentListener.onGutenbergEditorRequestStarterPageTemplatesTooltipShown(); } }, - new OnMediaFilesEditorLoadRequestListener() { + new OnMediaFilesCollectionBasedBlockEditorListener() { @Override public void onRequestMediaFilesEditorLoad(ArrayList mediaFiles, String blockId) { mEditorFragmentListener.onStoryComposerLoadRequested(mediaFiles, blockId); } + + @Override public void onCancelUploadForMediaCollection(ArrayList mediaFiles) { + showCancelMediaCollectionUploadDialog(mediaFiles); + } + + @Override public void onRetryUploadForMediaCollection(ArrayList mediaFiles) { + showRetryMediaCollectionUploadDialog(mediaFiles); + } }, GutenbergUtils.isDarkMode(getActivity())); @@ -610,6 +619,60 @@ public void onClick(DialogInterface dialog, int id) { dialog.show(); } + private void showCancelMediaCollectionUploadDialog(ArrayList mediaFiles) { + // Display 'cancel upload' dialog + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(getActivity()); + builder.setTitle(getString(R.string.stop_upload_dialog_title)); + builder.setPositiveButton(R.string.stop_upload_dialog_button_yes, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + mEditorFragmentListener.onCancelUploadForMediaCollection(mediaFiles); + // now signal Gutenberg upload failed, and remove the mediaIds from our tracking map + for (Object mediaFile : mediaFiles) { + // this conversion is needed to strip off decimals that can come from RN when using int as + // string + int localMediaId + = StringUtils.stringToInt( + ((HashMap) mediaFile).get("id").toString(), 0); + getGutenbergContainerFragment().mediaFileUploadFailed(localMediaId); + mUploadingMediaProgressMax.remove(localMediaId); + } + dialog.dismiss(); + } + }); + + builder.setNegativeButton(R.string.stop_upload_dialog_button_no, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } + + private void showRetryMediaCollectionUploadDialog(ArrayList mediaFiles) { + // Display 'retry upload' dialog + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(getActivity()); + builder.setTitle(getString(R.string.retry_failed_upload_title)); + builder.setPositiveButton(R.string.retry_failed_upload_yes, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + mEditorFragmentListener.onRetryUploadForMediaCollection(mediaFiles); + dialog.dismiss(); + } + }); + + builder.setNegativeButton(R.string.retry_failed_upload_remove, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } + private void showImplicitKeyboard() { InputMethodManager keyboard = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); keyboard.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0); diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 90f84ac9da86..246d3a706ccd 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 90f84ac9da86e576232508e83c8efed8cbeb07b9 +Subproject commit 246d3a706ccdbba266710ba5175dd461d39c18c7 From 02defebfa1efbbe48ae9a074a8d40fa62a51b185 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 10:58:47 -0300 Subject: [PATCH 111/230] updated commit hash for gutenberg-mobile, deep copy of mediaFiles when udpating id or url --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 246d3a706ccd..4a09adc333c2 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 246d3a706ccdbba266710ba5175dd461d39c18c7 +Subproject commit 4a09adc333c25d34edebfc9a059d9249df5ac492 From f69413d0328dd03bf700805265dfc1f6afb47f26 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 12:17:38 -0300 Subject: [PATCH 112/230] implemented requestMediaFilesSaveCancelDialog bridge method, just showing message that saving cannot be cancelled --- .../android/ui/posts/EditPostActivity.java | 10 ++++++++++ .../editor/EditorFragmentAbstract.java | 1 + .../gutenberg/GutenbergEditorFragment.java | 20 +++++++++++++++++++ .../src/main/res/values/strings.xml | 4 ++++ libs/gutenberg-mobile | 2 +- 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 36cb23e11d5a..92a624c6550c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3222,6 +3222,16 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } } + @Override public void onCancelSaveForMediaCollection(ArrayList mediaFiles) { + // just cancel upload for each media + for (Object mediaFile : mediaFiles) { + int localMediaId + = StringUtils.stringToInt(((HashMap) mediaFile).get("id").toString(), 0); + if (localMediaId != 0) { + } + } + } + // FluxC events @SuppressWarnings("unused") diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java index 11bd1dfe3fff..5230c67e3eff 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java @@ -210,6 +210,7 @@ public interface EditorFragmentListener { void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId); void onRetryUploadForMediaCollection(ArrayList mediaFiles); void onCancelUploadForMediaCollection(ArrayList mediaFiles); + void onCancelSaveForMediaCollection(ArrayList mediaFiles); } /** diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 9202ef2361ed..bb8431e150e1 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -356,6 +356,10 @@ public boolean onRequestStarterPageTemplatesTooltipShown() { @Override public void onRetryUploadForMediaCollection(ArrayList mediaFiles) { showRetryMediaCollectionUploadDialog(mediaFiles); } + + @Override public void onCancelSaveForMediaCollection(ArrayList mediaFiles) { + showCancelMediaCollectionSaveDialog(mediaFiles); + } }, GutenbergUtils.isDarkMode(getActivity())); @@ -673,6 +677,22 @@ public void onClick(DialogInterface dialog, int id) { dialog.show(); } + private void showCancelMediaCollectionSaveDialog(ArrayList mediaFiles) { + // Display 'cancel upload' dialog + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(getActivity()); + builder.setTitle(getString(R.string.stop_save_dialog_title)); + builder.setMessage(getString(R.string.stop_save_dialog_message)); + builder.setPositiveButton(R.string.stop_save_dialog_ok_button, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } + private void showImplicitKeyboard() { InputMethodManager keyboard = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); keyboard.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0); diff --git a/libs/editor/WordPressEditor/src/main/res/values/strings.xml b/libs/editor/WordPressEditor/src/main/res/values/strings.xml index 3473aa1ea6c1..5f0296797549 100644 --- a/libs/editor/WordPressEditor/src/main/res/values/strings.xml +++ b/libs/editor/WordPressEditor/src/main/res/values/strings.xml @@ -20,6 +20,10 @@ Stop uploading? Can\'t stop the upload because it\'s already finished + Files saving + Please wait until all files have been saved + OK + bold italic blockquote diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 4a09adc333c2..8f30bdf272b8 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 4a09adc333c25d34edebfc9a059d9249df5ac492 +Subproject commit 8f30bdf272b8cfdd67531690ab3222762a688ef3 From a7451cd86234963e8c254ee9a16b34670c0d562b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 12:40:26 -0300 Subject: [PATCH 113/230] fixed lint errors, and added TODO for cancellation (not going to implement it right now) --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 8 +------- .../editor/gutenberg/GutenbergContainerFragment.java | 3 ++- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 92a624c6550c..ad36534bde65 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3223,13 +3223,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onCancelSaveForMediaCollection(ArrayList mediaFiles) { - // just cancel upload for each media - for (Object mediaFile : mediaFiles) { - int localMediaId - = StringUtils.stringToInt(((HashMap) mediaFile).get("id").toString(), 0); - if (localMediaId != 0) { - } - } + // TODO implement cancelling save process for media collection } // FluxC events diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 4bed0d26769f..10c9daae3784 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -69,7 +69,8 @@ public void attachToContainer(ViewGroup viewGroup, OnMediaLibraryButtonListener onGutenbergDidSendButtonPressedActionListener, AddMentionUtil addMentionUtil, OnStarterPageTemplatesTooltipShownEventListener onSPTTooltipShownEventListener, - OnMediaFilesCollectionBasedBlockEditorListener onMediaFilesCollectionBasedBlockEditorListener, + OnMediaFilesCollectionBasedBlockEditorListener + onMediaFilesCollectionBasedBlockEditorListener, boolean isDarkMode) { mWPAndroidGlueCode.attachToContainer( viewGroup, From 33bf90d3c0c7a077e874d1adbf23f22ab2c65cdc Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 12:55:36 -0300 Subject: [PATCH 114/230] removed unnecessary toInt conversion call --- .../android/ui/stories/media/StoryMediaSaveUploadBridge.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 7507f4431069..8b02052d01e6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -147,7 +147,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( it.localSiteId.toLong(), // use the local id to save the original, will be replaced later // with mediaModel.mediaId after uploading to the remote site - LocalId(it.id.toInt()), + LocalId(it.id), frame ) From e0f364004adda3a2e9cf83450f9ecabcf163dbc9 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 12:56:51 -0300 Subject: [PATCH 115/230] broke comment lines to avoid exceeding 120 chars max length --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index ad36534bde65..9400070cabc2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3191,8 +3191,10 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } if (media.getUrl() != null && media.getUploadState().equals(MediaUploadState.UPLOADED.toString())) { - // Note: we should actually do this when the editor fragment starts instead of waiting for user input. - // Notify the editor fragment upload was successful and it should replace the local url by the remote url. + // Note: we should actually do this when the editor fragment starts instead of waiting for user + // input. + // Notify the editor fragment upload was successful and it should replace the local url by the + // remote url. if (mEditorMediaUploadListener != null) { mEditorMediaUploadListener.onMediaUploadSucceeded(String.valueOf(media.getId()), FluxCUtils.mediaFileFromMediaModel(media)); From 1039293674c52e9f81683167c0096098561f700b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 13:18:57 -0300 Subject: [PATCH 116/230] removed unnecessary toInt() conversion --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index f53f4a94915b..71868421d4de 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -156,7 +156,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( // look for the slide saved with the local id key (mediaFile.id), and re-convert to // mediaId. storiesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( - mediaFile.id.toInt(), + mediaFile.id, mediaFile.mediaId.toLong(), postModel.localSiteId.toLong() ) From f8b3dea41e6181004b580850e1a913430632b1df Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 12 Oct 2020 13:19:13 -0300 Subject: [PATCH 117/230] clarified comment --- .../wordpress/android/ui/posts/editor/StoriesEventListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index 15e023817247..51c0bb99eb8c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -134,7 +134,7 @@ class StoriesEventListener @Inject constructor( } val localMediaId = event.frameId.toString() // just update progress, we may have still some other frames in this story that need be saved. - // we will send the Failed signal once all the Story frames have been processed + // we will send the Failed signal once all the Story frames have been processed (see onStorySaveProcessFinished) val progress: Float = storyRepositoryWrapper.getCurrentStorySaveProgress(event.storyIndex, 0.0f) storySaveMediaListener?.onMediaSaveReattached(localMediaId, progress) // storySaveMediaListener?.onMediaSaveFailed(localMediaId) From 471d7f407b3d6b9292a23d1c562af17248b12761 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 13 Oct 2020 09:06:28 -0300 Subject: [PATCH 118/230] updated bridge method names from mediaModelCreatedForFile to mediaIdChanged --- .../wordpress/android/ui/posts/editor/StoriesEventListener.kt | 4 ++-- .../android/ui/stories/media/StoryMediaSaveUploadBridge.kt | 4 ++-- .../android/editor/gutenberg/GutenbergContainerFragment.java | 2 +- libs/gutenberg-mobile | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index 51c0bb99eb8c..4b1f86649993 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -20,7 +20,7 @@ import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper -import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent +import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaIdChangeEvent import org.wordpress.android.util.FluxCUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -120,7 +120,7 @@ class StoriesEventListener @Inject constructor( } @Subscribe(threadMode = ThreadMode.MAIN) - fun onStoryFrameMediaModelCreated(event: StoryFrameMediaModelCreatedEvent) { + fun onStoryFrameMediaIdChanged(event: StoryFrameMediaIdChangeEvent) { if (!lifecycle.currentState.isAtLeast(CREATED)) { return } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 8b02052d01e6..1b8c3f521648 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -156,7 +156,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( if (isEditMode) { // finally send the event that this frameId has changed EventBus.getDefault().post( - StoryFrameMediaModelCreatedEvent( + StoryFrameMediaIdChangeEvent( oldTemporaryId, it.id.toString(), oldUri.toString() @@ -239,5 +239,5 @@ class StoryMediaSaveUploadBridge @Inject constructor( event.frameSaveResult.size == storyRepositoryWrapper.getStoryAtIndex(event.storyIndex).frames.size) } - data class StoryFrameMediaModelCreatedEvent(val oldId: String, val newId: String, val oldUrl: String) + data class StoryFrameMediaIdChangeEvent(val oldId: String, val newId: String, val oldUrl: String) } diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java index 10c9daae3784..a691c1b8b3b8 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergContainerFragment.java @@ -248,6 +248,6 @@ public void onStorySaveResult(final String storyFirstMediaId, final boolean succ } public void onMediaModelCreatedForFile(String oldId, String newId, String oldUrl) { - mWPAndroidGlueCode.mediaModelCreatedForFile(oldId, newId, oldUrl); + mWPAndroidGlueCode.mediaIdChanged(oldId, newId, oldUrl); } } diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 8f30bdf272b8..433e2cb33c22 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 8f30bdf272b8cfdd67531690ab3222762a688ef3 +Subproject commit 433e2cb33c22cefcb8aadfcc390d2cd720e61188 From 032a7415fd61661d5a63f02a2764172c10757f8d Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 13 Oct 2020 10:03:07 -0300 Subject: [PATCH 119/230] rolled back rename of event class StoryFrameMediaModelCreatedEvent, it better represents the changes on the WPAndroid side of things (was changed before to the more generic StoryFrameMediaIdChangeEvent which is used in the bridge) --- .../wordpress/android/ui/posts/editor/StoriesEventListener.kt | 4 ++-- .../android/ui/stories/media/StoryMediaSaveUploadBridge.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index 4b1f86649993..adf8ba3aa624 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -20,7 +20,7 @@ import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper -import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaIdChangeEvent +import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent import org.wordpress.android.util.FluxCUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -120,7 +120,7 @@ class StoriesEventListener @Inject constructor( } @Subscribe(threadMode = ThreadMode.MAIN) - fun onStoryFrameMediaIdChanged(event: StoryFrameMediaIdChangeEvent) { + fun onStoryFrameMediaIdChanged(event: StoryFrameMediaModelCreatedEvent) { if (!lifecycle.currentState.isAtLeast(CREATED)) { return } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 1b8c3f521648..8b02052d01e6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -156,7 +156,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( if (isEditMode) { // finally send the event that this frameId has changed EventBus.getDefault().post( - StoryFrameMediaIdChangeEvent( + StoryFrameMediaModelCreatedEvent( oldTemporaryId, it.id.toString(), oldUri.toString() @@ -239,5 +239,5 @@ class StoryMediaSaveUploadBridge @Inject constructor( event.frameSaveResult.size == storyRepositoryWrapper.getStoryAtIndex(event.storyIndex).frames.size) } - data class StoryFrameMediaIdChangeEvent(val oldId: String, val newId: String, val oldUrl: String) + data class StoryFrameMediaModelCreatedEvent(val oldId: String, val newId: String, val oldUrl: String) } From 1bcf38d19179ab2efb4a00026c3a77c065db1d8d Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 13 Oct 2020 16:02:28 -0300 Subject: [PATCH 120/230] built logic to save temporary ids to prefs as well --- .../android/ui/posts/EditPostActivity.java | 2 +- .../ui/posts/editor/StoriesEventListener.kt | 6 +- .../stories/SaveStoryGutenbergBlockUseCase.kt | 33 +++++- .../ui/stories/StoryComposerActivity.kt | 8 +- .../media/StoryMediaSaveUploadBridge.kt | 48 +++++--- .../android/ui/stories/prefs/StoriesPrefs.kt | 109 +++++++++++++++++- .../LoadStoryFromStoriesPrefsUseCase.kt | 8 +- 7 files changed, 192 insertions(+), 22 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 9400070cabc2..9d9028101501 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -1614,7 +1614,7 @@ private void onUploadSuccess(MediaModel media) { // Also: we don't need to worry about checking if this mediaModel corresponds to a media upload // within a story block in this post: we will only replace items for which a local-keyed frame has // been created before, which can only happen when using the Story Creator. - mStoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + mStoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide_Phase2( media.getId(), media.getMediaId(), mSite.getId() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index adf8ba3aa624..3f5245f2a145 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -15,12 +15,15 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.editor.gutenberg.StorySaveMediaListener import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent +import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.TempId import org.wordpress.android.util.FluxCUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -33,6 +36,7 @@ class StoriesEventListener @Inject constructor( private lateinit var lifecycle: Lifecycle private lateinit var site: SiteModel private var storySaveMediaListener: StorySaveMediaListener? = null + @Inject lateinit var storiesPrefs: StoriesPrefs @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) private fun onCreate() { @@ -124,7 +128,7 @@ class StoriesEventListener @Inject constructor( if (!lifecycle.currentState.isAtLeast(CREATED)) { return } - storySaveMediaListener?.onMediaModelCreatedForFile(event.oldId, event.newId, event.oldUrl) + storySaveMediaListener?.onMediaModelCreatedForFile(event.oldId, event.newId.toString(), event.oldUrl) } @Subscribe(threadMode = ThreadMode.MAIN) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 71868421d4de..118212cf54c7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -1,9 +1,14 @@ package org.wordpress.android.ui.stories import com.google.gson.Gson +import com.wordpress.stories.compose.frame.FrameIndex +import com.wordpress.stories.compose.story.StoryFrameItem +import com.wordpress.stories.compose.story.StoryIndex import org.wordpress.android.fluxc.model.PostModel +import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.TempId import org.wordpress.android.util.StringUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -52,7 +57,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( fun buildMediaFileDataWithTemporaryId(mediaFile: MediaFile, temporaryId: String): StoryMediaFileData { return StoryMediaFileData( alt = "", - id = TEMPORARY_ID_PREFIX + temporaryId, // mediaFile.id, + id = temporaryId, // mediaFile.id, link = StringUtils.notNullStr(mediaFile.fileURL), type = if (mediaFile.isVideo) "video" else "image", mime = StringUtils.notNullStr(mediaFile.mimeType), @@ -68,7 +73,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( ): StoryMediaFileData { return StoryMediaFileData( alt = "", - id = TEMPORARY_ID_PREFIX + temporaryId, // mediaFile.id, + id = temporaryId, // mediaFile.id, link = url, type = if (isVideo) "video" else "image", mime = "", @@ -77,6 +82,10 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( ) } + fun getTempIdForStoryFrame(tempIdBase: Long, storyIndex: StoryIndex, frameIndex: FrameIndex): String { + return TEMPORARY_ID_PREFIX + "$tempIdBase-$storyIndex-$frameIndex" + } + fun cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost(editPostRepository: EditPostRepository) { editPostRepository.update { postModel: PostModel -> val gson = Gson() @@ -155,7 +164,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( // look for the slide saved with the local id key (mediaFile.id), and re-convert to // mediaId. - storiesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + storiesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide_Phase2( mediaFile.id, mediaFile.mediaId.toLong(), postModel.localSiteId.toLong() @@ -170,6 +179,24 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( ) } + fun saveNewLocalFilesToStoriesPrefsTempSlides(site: SiteModel, storyIndex: StoryIndex, frames: ArrayList) { + for ((frameIndex, frame) in frames.withIndex()) { + if (frame.id == null) { + val assignedTempId = getTempIdForStoryFrame( + storiesPrefs.getNewIncrementalTempId(), + storyIndex, + frameIndex + ) + frame.id = assignedTempId + } + storiesPrefs.saveSlideWithTempId( + site.id.toLong(), + TempId(requireNotNull(frame.id)), // should not be null at this point + frame + ) + } + } + private fun createGBStoryBlockStringFromJson(storyBlock: StoryBlockData): String { val gson = Gson() return HEADING_START + gson.toJson(storyBlock) + HEADING_END + DIV_PART + CLOSING_TAG diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 647e03d92d33..563175bb482e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -509,6 +509,10 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), val storyMediaFileDataList = ArrayList() // holds media files val story = storyRepositoryWrapper.getStoryAtIndex(storyIndex) for ((frameIndex, frame) in story.frames.withIndex()) { + val newTempId = storiesPrefs.getNewIncrementalTempId() + val assignedTempId = saveStoryGutenbergBlockUseCase.getTempIdForStoryFrame( + newTempId, storyIndex, frameIndex + ) when (frame.id) { // if the frame.id is null, this is a new frame that has been added to an edited Story // so, we don't have much information yet. We do have the background source (not the flattened @@ -517,7 +521,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), null -> { val storyMediaFileData = saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryIdNoMediaFile( - temporaryId = "$storyIndex-$frameIndex", + temporaryId = assignedTempId, url = if (frame.source is FileBackgroundSource) { (frame.source as FileBackgroundSource).file.toString() } else { @@ -538,7 +542,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), val storyMediaFileData = saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( mediaFile = it, - temporaryId = "$storyIndex-$frameIndex" + temporaryId = assignedTempId ) frame.id = storyMediaFileData.id storyMediaFileDataList.add(storyMediaFileData) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 8b02052d01e6..326c1482126c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.OnLifecycleEvent import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import com.wordpress.stories.compose.story.StoryFrameItem import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -32,6 +33,7 @@ import org.wordpress.android.ui.stories.StoriesTrackerHelper import org.wordpress.android.ui.stories.StoryComposerActivity import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.TempId import org.wordpress.android.ui.uploads.UploadServiceFacade import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.util.NetworkUtilsWrapper @@ -143,7 +145,14 @@ class StoryMediaSaveUploadBridge @Inject constructor( mediaModel?.let { val oldTemporaryId = frame.id ?: "" frame.id = it.id.toString() - storiesPrefs.saveSlideWithLocalId( + + // if prefs has this Slide with the temporary key, replace it + // if not, let's now save the new slide with the local key + storiesPrefs.replaceTempMediaIdKeyedSlideWithLocalMediaIdKeyedSlide_Phase1( + TempId(oldTemporaryId), + LocalId(it.id), + it.localSiteId.toLong() + ) ?: storiesPrefs.saveSlideWithLocalId( it.localSiteId.toLong(), // use the local id to save the original, will be replaced later // with mediaModel.mediaId after uploading to the remote site @@ -158,8 +167,9 @@ class StoryMediaSaveUploadBridge @Inject constructor( EventBus.getDefault().post( StoryFrameMediaModelCreatedEvent( oldTemporaryId, - it.id.toString(), - oldUri.toString() + it.id, + oldUri.toString(), + frame ) ) } @@ -211,15 +221,22 @@ class StoryMediaSaveUploadBridge @Inject constructor( // track event storiesTrackerHelper.trackStorySaveResultEvent(event) - // only trigger the bridge preparation and the UploadService if the Story is now complete - // otherwise we can be receiving successful retry events for individual frames we shouldn't care about just - // yet. - if (isStorySavingComplete(event)) { - // only remove it if it was successful - we want to keep it and show a snackbar once when the user - // comes back to the app if it wasn't, see MySiteFrament for details. - eventBusWrapper.removeStickyEvent(event) - event.metadata?.let { - val site = it.getSerializable(WordPress.SITE) as SiteModel + event.metadata?.let { + val site = it.getSerializable(WordPress.SITE) as SiteModel + val story = storyRepositoryWrapper.getStoryAtIndex(event.storyIndex) + saveStoryGutenbergBlockUseCase.saveNewLocalFilesToStoriesPrefsTempSlides( + site, + event.storyIndex, + story.frames + ) + + // only trigger the bridge preparation and the UploadService if the Story is now complete + // otherwise we can be receiving successful retry events for individual frames we shouldn't care about just + // yet. + if (isStorySavingComplete(event)) { + // only remove it if it was successful - we want to keep it and show a snackbar once when the user + // comes back to the app if it wasn't, see MySiteFrament for details. + eventBusWrapper.removeStickyEvent(event) editPostRepository.loadPostByLocalPostId(it.getInt(StoryComposerActivity.KEY_POST_LOCAL_ID)) if (event.isEditMode) { // we're done using the temporary ids, let's clean mediaFiles attribute from the blocks that have @@ -239,5 +256,10 @@ class StoryMediaSaveUploadBridge @Inject constructor( event.frameSaveResult.size == storyRepositoryWrapper.getStoryAtIndex(event.storyIndex).frames.size) } - data class StoryFrameMediaModelCreatedEvent(val oldId: String, val newId: String, val oldUrl: String) + data class StoryFrameMediaModelCreatedEvent( + val oldId: String, + val newId: Int, + val oldUrl: String, + val frame: StoryFrameItem + ) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index d09d7b3234b4..87ceead46a61 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.stories.prefs +import android.annotation.SuppressLint import android.content.Context import android.net.Uri import androidx.preference.PreferenceManager @@ -17,7 +18,9 @@ class StoriesPrefs @Inject constructor( private val context: Context ) { companion object { + private val KEY_STORIES_SLIDE_INCREMENTAL_ID = "incremental_id" private val KEY_PREFIX_STORIES_SLIDE_ID = "story_slide_id-" + private val KEY_PREFIX_TEMP_MEDIA_ID = "t-" private val KEY_PREFIX_LOCAL_MEDIA_ID = "l-" private val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" } @@ -32,13 +35,60 @@ class StoriesPrefs @Inject constructor( KEY_PREFIX_LOCAL_MEDIA_ID + mediaId.value.toString() } + private fun buildSlideKey(siteId: Long, tempId: TempId): String { + return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + + KEY_PREFIX_TEMP_MEDIA_ID + tempId.id + } + + @SuppressLint("ApplySharedPref") + @Synchronized + fun getNewIncrementalTempId(): Long { + var currentIncrementalId = getIncrementalTempId() + currentIncrementalId++ + val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() + editor.putLong(KEY_STORIES_SLIDE_INCREMENTAL_ID, currentIncrementalId) + editor.commit() + return currentIncrementalId + } + + fun getIncrementalTempId(): Long { + return PreferenceManager.getDefaultSharedPreferences(context).getLong( + KEY_STORIES_SLIDE_INCREMENTAL_ID, + 0 + ) + } + fun checkSlideIdExists(siteId: Long, mediaId: RemoteId): Boolean { val slideIdKey = buildSlideKey(siteId, mediaId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } + fun checkSlideIdExists(siteId: Long, tempId: TempId): Boolean { + val slideIdKey = buildSlideKey(siteId, tempId) + return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) + } + + fun checkSlideIdExists(siteId: Long, localId: LocalId): Boolean { + val slideIdKey = buildSlideKey(siteId, localId) + return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) + } + fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: RemoteId): Boolean { val storyFrameItem: StoryFrameItem? = getSlideWithRemoteId(siteId, mediaId) + return checkSlideOriginalBackgroundMediaExists(storyFrameItem) + } + + fun checkSlideOriginalBackgroundMediaExists(siteId: Long, tempId: TempId): Boolean { + val storyFrameItem: StoryFrameItem? = getSlideWithTempId(siteId, tempId) + return checkSlideOriginalBackgroundMediaExists(storyFrameItem) + } + + fun checkSlideOriginalBackgroundMediaExists(siteId: Long, localId: LocalId): Boolean { + val storyFrameItem: StoryFrameItem? = getSlideWithLocalId(siteId, localId) + return checkSlideOriginalBackgroundMediaExists(storyFrameItem) + } + + private fun checkSlideOriginalBackgroundMediaExists(storyFrameItem: StoryFrameItem?): Boolean { storyFrameItem?.let { frame -> // now check the background media exists or is accessible on this device frame.source.let { source -> @@ -84,6 +134,16 @@ class StoriesPrefs @Inject constructor( checkSlideOriginalBackgroundMediaExists(siteId, mediaId) } + fun isValidSlide(siteId: Long, tempId: TempId): Boolean { + return checkSlideIdExists(siteId, tempId) && + checkSlideOriginalBackgroundMediaExists(siteId, tempId) + } + + fun isValidSlide(siteId: Long, localId: LocalId): Boolean { + return checkSlideIdExists(siteId, localId) && + checkSlideOriginalBackgroundMediaExists(siteId, localId) + } + private fun getSlideJson(slideIdKey: String): String? { return PreferenceManager.getDefaultSharedPreferences(context).getString(slideIdKey, null) } @@ -102,6 +162,18 @@ class StoriesPrefs @Inject constructor( } ?: return null } + fun getSlideWithTempId(siteId: Long, tempId: TempId): StoryFrameItem? { + val jsonSlide = getSlideJson(buildSlideKey(siteId, tempId)) + jsonSlide?.let { + return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) + } ?: return null + } + + fun saveSlideWithTempId(siteId: Long, tempId: TempId, storyFrameItem: StoryFrameItem) { + val slideIdKey = buildSlideKey(siteId, tempId) + saveSlide(slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) + } + fun saveSlideWithLocalId(siteId: Long, mediaId: LocalId, storyFrameItem: StoryFrameItem) { val slideIdKey = buildSlideKey(siteId, mediaId) saveSlide(slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) @@ -112,6 +184,13 @@ class StoriesPrefs @Inject constructor( saveSlide(slideIdKey, StorySerializerUtils.serializeStoryFrameItem(storyFrameItem)) } + fun deleteSlideWithTempId(siteId: Long, tempId: TempId) { + val slideIdKey = buildSlideKey(siteId, tempId) + val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() + editor.remove(slideIdKey) + editor.apply() + } + fun deleteSlideWithLocalId(siteId: Long, mediaId: LocalId) { val slideIdKey = buildSlideKey(siteId, mediaId) val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() @@ -127,7 +206,7 @@ class StoriesPrefs @Inject constructor( } } - fun replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( + fun replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide_Phase2( localIdKey: Int, remoteIdKey: Long, localSiteId: Long @@ -150,4 +229,32 @@ class StoriesPrefs @Inject constructor( ) } } + + fun replaceTempMediaIdKeyedSlideWithLocalMediaIdKeyedSlide_Phase1( + tempId: TempId, + localId: LocalId, + localSiteId: Long + ): StoryFrameItem? { + // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. + getSlideWithTempId( + localSiteId, + tempId + )?.let { + it.id = localId.value.toString() + saveSlideWithLocalId( + localSiteId, + localId, // use the new localId as key + it + ) + // now delete the old entry + deleteSlideWithTempId( + localSiteId, + tempId + ) + return it + } + return null + } + + data class TempId(val id: String) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 08ea59a5d2f0..c993c917f5ea 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -5,12 +5,15 @@ import com.wordpress.stories.compose.story.StoryFrameItem import com.wordpress.stories.compose.story.StoryIndex import com.wordpress.stories.compose.story.StoryRepository import dagger.Reusable +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.TempId +import org.wordpress.android.util.StringUtils import java.util.ArrayList import java.util.HashMap import javax.inject.Inject @@ -50,7 +53,10 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { for (mediaId in mediaIds) { - if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteId(mediaId.toLong()))) { + // if this is not a remote nor a local / temporary slide, return false + if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteId(mediaId.toLong())) + && !storiesPrefs.isValidSlide(site.id.toLong(), LocalId(StringUtils.stringToInt(mediaId))) + && !storiesPrefs.isValidSlide(site.id.toLong(), TempId(mediaId))) { return false } } From 246c4fef03277bf796a45e9de379149fef049b93 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 13 Oct 2020 16:58:19 -0300 Subject: [PATCH 121/230] accounting for Story re-creation out of temporary saved slides --- .../android/ui/posts/EditPostActivity.java | 24 ++--- .../LoadStoryFromStoriesPrefsUseCase.kt | 92 ++++++++++++------- 2 files changed, 71 insertions(+), 45 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 9d9028101501..79f25da089d5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3109,18 +3109,18 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - if (mLoadStoryFromStoriesPrefsUseCase.anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles)) { - // unfortunately the medaiIds seem corrupt so, show a dialog and bail - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); - builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); - builder.setMessage(getString(R.string.dialog_edit_story_corrupt_message)); - builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { - dialog.dismiss(); - }); - AlertDialog dialog = builder.create(); - dialog.show(); - return; - } +// if (mLoadStoryFromStoriesPrefsUseCase.anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles)) { +// // unfortunately the medaiIds seem corrupt so, show a dialog and bail +// AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); +// builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); +// builder.setMessage(getString(R.string.dialog_edit_story_corrupt_message)); +// builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { +// dialog.dismiss(); +// }); +// AlertDialog dialog = builder.create(); +// dialog.show(); +// return; +// } ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index c993c917f5ea..0554898e9576 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -10,6 +10,7 @@ import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs import org.wordpress.android.ui.stories.prefs.StoriesPrefs.TempId @@ -27,12 +28,17 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( fun getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles: ArrayList): ArrayList { val mediaIds = ArrayList() for (mediaFile in mediaFiles) { - val mediaIdLong = (mediaFile as HashMap)["id"] - .toString() - .toDouble() // this conversion is needed to strip off decimals that can come from RN - .toLong() - val mediaIdString = mediaIdLong.toString() - mediaIds.add(mediaIdString) + val rawIdField = (mediaFile as HashMap)["id"] as String + if (rawIdField.startsWith(TEMPORARY_ID_PREFIX)) { + mediaIds.add(rawIdField) + } else { + val mediaIdLong = (mediaFile as HashMap)["id"] + .toString() + .toDouble() // this conversion is needed to strip off decimals that can come from RN + .toLong() + val mediaIdString = mediaIdLong.toString() + mediaIds.add(mediaIdString) + } } return mediaIds } @@ -54,10 +60,15 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { for (mediaId in mediaIds) { // if this is not a remote nor a local / temporary slide, return false - if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteId(mediaId.toLong())) - && !storiesPrefs.isValidSlide(site.id.toLong(), LocalId(StringUtils.stringToInt(mediaId))) - && !storiesPrefs.isValidSlide(site.id.toLong(), TempId(mediaId))) { - return false + if (mediaId.startsWith(TEMPORARY_ID_PREFIX)) { + if (!storiesPrefs.isValidSlide(site.id.toLong(), TempId(mediaId))) { + return false + } + } else { + if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteId(mediaId.toLong())) + && !storiesPrefs.isValidSlide(site.id.toLong(), LocalId(StringUtils.stringToInt(mediaId)))) { + return false + } } } return true @@ -71,38 +82,53 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( var storyIndex = StoryRepository.DEFAULT_NONE_SELECTED storyRepositoryWrapper.loadStory(storyIndex) storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() + var tempSlidesLoadedCount: Int = 0 for (mediaId in mediaIds) { - var storyFrameItem = storiesPrefs.getSlideWithRemoteId( - site.getId().toLong(), - RemoteId(mediaId.toLong()) - ) - if (storyFrameItem != null) { - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + // let's check if this is a temporary id + if (mediaId.startsWith(TEMPORARY_ID_PREFIX)) { + var storyFrameItem = storiesPrefs.getSlideWithTempId( + site.getId().toLong(), + TempId(mediaId) + ) + if (storyFrameItem != null) { + tempSlidesLoadedCount++ + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + } } else { - allStorySlidesAreEditable = false - - // for this missing frame we'll create a new frame using the actual uploaded flattened media - val tmpMediaIdsLong = ArrayList() - tmpMediaIdsLong.add(mediaId.toLong()) - val mediaModelList: List = mediaStore.getSiteMediaWithIds( - site, - tmpMediaIdsLong + var storyFrameItem = storiesPrefs.getSlideWithRemoteId( + site.getId().toLong(), + RemoteId(mediaId.toLong()) ) - if (mediaModelList.isEmpty()) { - noSlidesLoaded = true + if (storyFrameItem != null) { + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) } else { - for (mediaModel in mediaModelList) { - storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( - Uri.parse(mediaModel.url), - mediaModel.isVideo - ) - storyFrameItem.id = mediaModel.mediaId.toString() - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + allStorySlidesAreEditable = false + + // for this missing frame we'll create a new frame using the actual uploaded flattened media + val tmpMediaIdsLong = ArrayList() + tmpMediaIdsLong.add(mediaId.toLong()) + val mediaModelList: List = mediaStore.getSiteMediaWithIds( + site, + tmpMediaIdsLong + ) + if (mediaModelList.isEmpty()) { + noSlidesLoaded = true + } else { + for (mediaModel in mediaModelList) { + storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( + Uri.parse(mediaModel.url), + mediaModel.isVideo + ) + storyFrameItem.id = mediaModel.mediaId.toString() + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + } } } } } + noSlidesLoaded = (!noSlidesLoaded && tempSlidesLoadedCount == 0) + return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable, noSlidesLoaded) } From 3958007f218447ffc93594e7a781105a4536589e Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 06:39:21 -0300 Subject: [PATCH 122/230] updated gutenberg-mobile commit hash, removed commented out code --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 433e2cb33c22..875112c46153 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 433e2cb33c22cefcb8aadfcc390d2cd720e61188 +Subproject commit 875112c46153b0a2169d2ddc7a6144b537728a5f From d7c646a2556321b09cce047a287fa2a7e4aada79 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 08:00:19 -0300 Subject: [PATCH 123/230] kotlinified / streamlined logic for recreating Story from prefs --- .../LoadStoryFromStoriesPrefsUseCase.kt | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 0554898e9576..ac996821e083 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -82,26 +82,22 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( var storyIndex = StoryRepository.DEFAULT_NONE_SELECTED storyRepositoryWrapper.loadStory(storyIndex) storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() - var tempSlidesLoadedCount: Int = 0 for (mediaId in mediaIds) { // let's check if this is a temporary id if (mediaId.startsWith(TEMPORARY_ID_PREFIX)) { - var storyFrameItem = storiesPrefs.getSlideWithTempId( + storiesPrefs.getSlideWithTempId( site.getId().toLong(), TempId(mediaId) - ) - if (storyFrameItem != null) { - tempSlidesLoadedCount++ - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) + )?.let { + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(it) } } else { - var storyFrameItem = storiesPrefs.getSlideWithRemoteId( + storiesPrefs.getSlideWithRemoteId( site.getId().toLong(), RemoteId(mediaId.toLong()) - ) - if (storyFrameItem != null) { - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) - } else { + )?.let { + storyRepositoryWrapper.addStoryFrameItemToCurrentStory(it) + } ?: run { allStorySlidesAreEditable = false // for this missing frame we'll create a new frame using the actual uploaded flattened media @@ -115,7 +111,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( noSlidesLoaded = true } else { for (mediaModel in mediaModelList) { - storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( + val storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( Uri.parse(mediaModel.url), mediaModel.isVideo ) @@ -127,7 +123,7 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( } } - noSlidesLoaded = (!noSlidesLoaded && tempSlidesLoadedCount == 0) + noSlidesLoaded = storyRepositoryWrapper.getStoryAtIndex(storyIndex).frames.size == 0 return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable, noSlidesLoaded) } From d75a6f9cd94ac267aabb5c38676bca67ef62e045 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 08:00:54 -0300 Subject: [PATCH 124/230] if story is unsuccessful, add id to failedMediaIds and remove from progressMax map --- .../android/editor/gutenberg/GutenbergEditorFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index bb8431e150e1..47cd12d0288d 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -1130,6 +1130,10 @@ public void onEditorThemeUpdated(Bundle editorTheme) { } @Override public void onStorySaveResult(String storyFirstMediaId, boolean success) { + if (!success) { + mFailedMediaIds.add(storyFirstMediaId); + mUploadingMediaProgressMax.remove(storyFirstMediaId); + } getGutenbergContainerFragment().onStorySaveResult(storyFirstMediaId, success); } From 20e8f715fc69394e32d00826be1e9745d84af247 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 09:39:10 -0300 Subject: [PATCH 125/230] make sure not to cast id coming from Gutenberg mediaFiles as String, as it may have been replaced by Double with final remote mediaIds --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index ac996821e083..799f5cfb5ad1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -28,11 +28,11 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( fun getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles: ArrayList): ArrayList { val mediaIds = ArrayList() for (mediaFile in mediaFiles) { - val rawIdField = (mediaFile as HashMap)["id"] as String - if (rawIdField.startsWith(TEMPORARY_ID_PREFIX)) { + val rawIdField = (mediaFile as HashMap)["id"] + if (rawIdField is String && rawIdField.startsWith(TEMPORARY_ID_PREFIX)) { mediaIds.add(rawIdField) } else { - val mediaIdLong = (mediaFile as HashMap)["id"] + val mediaIdLong = rawIdField .toString() .toDouble() // this conversion is needed to strip off decimals that can come from RN .toLong() From cd82b8d5867e03a9ba87f8b6d9f6f9cfff6b26b7 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 09:40:19 -0300 Subject: [PATCH 126/230] only proceed with readding a saved slide if this is a final StorySaveResult and not a single slide save Retry event --- .../ui/posts/editor/StoriesEventListener.kt | 2 +- .../stories/media/StoryMediaSaveUploadBridge.kt | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index 3f5245f2a145..ba59411fe3cb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -150,7 +150,7 @@ class StoriesEventListener @Inject constructor( return } val story = storyRepositoryWrapper.getStoryAtIndex(event.storyIndex) - if (event.frameSaveResult.size == story.frames.size) { + if (!event.isRetry && event.frameSaveResult.size == story.frames.size) { // take the first frame IDs and mediaUri val localMediaId = story.frames[0].id.toString() storySaveMediaListener?.onStorySaveResult(localMediaId, event.isSuccess()) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 326c1482126c..4a8dde186011 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -233,18 +233,18 @@ class StoryMediaSaveUploadBridge @Inject constructor( // only trigger the bridge preparation and the UploadService if the Story is now complete // otherwise we can be receiving successful retry events for individual frames we shouldn't care about just // yet. - if (isStorySavingComplete(event)) { + if (isStorySavingComplete(event) && !event.isRetry) { // only remove it if it was successful - we want to keep it and show a snackbar once when the user // comes back to the app if it wasn't, see MySiteFrament for details. eventBusWrapper.removeStickyEvent(event) editPostRepository.loadPostByLocalPostId(it.getInt(StoryComposerActivity.KEY_POST_LOCAL_ID)) - if (event.isEditMode) { - // we're done using the temporary ids, let's clean mediaFiles attribute from the blocks that have - // those - saveStoryGutenbergBlockUseCase.cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost( - editPostRepository - ) - } +// if (event.isEditMode) { +// // we're done using the temporary ids, let's clean mediaFiles attribute from the blocks that have +// // those +// saveStoryGutenbergBlockUseCase.cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost( +// editPostRepository +// ) +// } // media upload tracking already in addLocalMediaToPostUseCase.addNewMediaToEditorAsync addNewStoryFrameMediaItemsToPostAndUploadAsync(site, event) } From 8b3e7e8243be091eea7024103188f986cc482d78 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 09:41:32 -0300 Subject: [PATCH 127/230] processing media slides with buildStoryMediaFileDataForTemporarySlide for both the case the id hasn't been assigned yet or the case where this is already a temporary slide that has a tempid, but has failed being saved --- .../ui/stories/StoryComposerActivity.kt | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 563175bb482e..be2ed22a3325 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -22,6 +22,7 @@ import com.wordpress.stories.compose.PrepublishingEventProvider import com.wordpress.stories.compose.SnackbarProvider import com.wordpress.stories.compose.StoryDiscardListener import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import com.wordpress.stories.compose.story.StoryFrameItem import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.FileBackgroundSource import com.wordpress.stories.compose.story.StoryFrameItem.BackgroundSource.UriBackgroundSource import com.wordpress.stories.compose.story.StoryFrameItemType.VIDEO @@ -62,6 +63,7 @@ import org.wordpress.android.ui.posts.PublishPost import org.wordpress.android.ui.posts.editor.media.AddExistingMediaSource.WP_MEDIA_LIBRARY import org.wordpress.android.ui.posts.editor.media.EditorMediaListener import org.wordpress.android.ui.posts.prepublishing.PrepublishingBottomSheetListener +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.StoryMediaFileData import org.wordpress.android.ui.stories.media.StoryEditorMedia import org.wordpress.android.ui.stories.media.StoryEditorMedia.AddMediaToStoryPostUiState @@ -519,33 +521,36 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), // image yet) so, let's use that for now, and assign the temporaryID we'll use to send // save progress events to Gutenberg. null -> { - val storyMediaFileData = - saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryIdNoMediaFile( - temporaryId = assignedTempId, - url = if (frame.source is FileBackgroundSource) { - (frame.source as FileBackgroundSource).file.toString() - } else { - (frame.source as UriBackgroundSource).contentUri.toString() - }, - isVideo = (frame.frameItemType is VIDEO) - ) + val storyMediaFileData = buildStoryMediaFileDataForTemporarySlide( + frame, + assignedTempId + ) frame.id = storyMediaFileData.id storyMediaFileDataList.add(storyMediaFileData) } - // if the frame.id is populated, this should be an actual MediaModel mediaId so, + // if the frame.id is populated and is not a temporary id, this should be an actual MediaModel mediaId so, // let's use that to obtain the mediaFile and then replace it with the temporary frame.id else -> { frame.id?.let { - val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) - val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) - mediaFile?.let { - val storyMediaFileData = - saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( - mediaFile = it, - temporaryId = assignedTempId - ) - frame.id = storyMediaFileData.id + if (it.startsWith(TEMPORARY_ID_PREFIX)) { + val storyMediaFileData = buildStoryMediaFileDataForTemporarySlide( + frame, + it + ) + // frame.id = storyMediaFileData.id storyMediaFileDataList.add(storyMediaFileData) + } else { + val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) + val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) + mediaFile?.let { + val storyMediaFileData = + saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( + mediaFile = it, + temporaryId = assignedTempId + ) + frame.id = storyMediaFileData.id + storyMediaFileDataList.add(storyMediaFileData) + } } } } @@ -554,6 +559,20 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), return storyMediaFileDataList } + private fun buildStoryMediaFileDataForTemporarySlide(frame: StoryFrameItem, tempId: String): StoryMediaFileData { + val storyMediaFileData = + saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryIdNoMediaFile( + temporaryId = tempId, + url = if (frame.source is FileBackgroundSource) { + (frame.source as FileBackgroundSource).file.toString() + } else { + (frame.source as UriBackgroundSource).contentUri.toString() + }, + isVideo = (frame.frameItemType is VIDEO) + ) + return storyMediaFileData + } + override fun onSubmitButtonClicked(publishPost: PublishPost) { viewModel.onSubmitButtonClicked() } From a4996049a67893a7473ce339c32191e00af8de31 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 09:43:05 -0300 Subject: [PATCH 128/230] removed no longer used cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost --- .../stories/SaveStoryGutenbergBlockUseCase.kt | 31 ------------------- .../media/StoryMediaSaveUploadBridge.kt | 7 ----- 2 files changed, 38 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 118212cf54c7..b27894457404 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -86,37 +86,6 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( return TEMPORARY_ID_PREFIX + "$tempIdBase-$storyIndex-$frameIndex" } - fun cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost(editPostRepository: EditPostRepository) { - editPostRepository.update { postModel: PostModel -> - val gson = Gson() - findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( - postModel, - object : DoWithMediaFilesListener { - override fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String { - var processedContent = content - val storyBlockData: StoryBlockData? = - gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) - storyBlockData?.let { - if (hasTemporaryIdsInStoryData(it)) { - // here remove the whole mediaFiles attribute - processedContent = content.replace(mediaFilesJsonString, "") - } - } - return processedContent - } - } - ) - true - } - } - - private fun hasTemporaryIdsInStoryData(storyBlockData: StoryBlockData): Boolean { - val temporaryIds = storyBlockData.mediaFiles.filter { - it.id.startsWith(TEMPORARY_ID_PREFIX) - } - return temporaryIds.size > 0 - } - fun findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( postModel: PostModel, listener: DoWithMediaFilesListener diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 4a8dde186011..c53ba1fca142 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -238,13 +238,6 @@ class StoryMediaSaveUploadBridge @Inject constructor( // comes back to the app if it wasn't, see MySiteFrament for details. eventBusWrapper.removeStickyEvent(event) editPostRepository.loadPostByLocalPostId(it.getInt(StoryComposerActivity.KEY_POST_LOCAL_ID)) -// if (event.isEditMode) { -// // we're done using the temporary ids, let's clean mediaFiles attribute from the blocks that have -// // those -// saveStoryGutenbergBlockUseCase.cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost( -// editPostRepository -// ) -// } // media upload tracking already in addLocalMediaToPostUseCase.addNewMediaToEditorAsync addNewStoryFrameMediaItemsToPostAndUploadAsync(site, event) } From dd312efde932e274572ca9caca4afd19290eecb5 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 09:52:22 -0300 Subject: [PATCH 129/230] fixed linter warnings --- .../android/ui/posts/editor/StoriesEventListener.kt | 2 -- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 6 +++++- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index ba59411fe3cb..18073b7bc209 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -15,7 +15,6 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.editor.gutenberg.StorySaveMediaListener import org.wordpress.android.fluxc.Dispatcher -import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore @@ -23,7 +22,6 @@ import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent import org.wordpress.android.ui.stories.prefs.StoriesPrefs -import org.wordpress.android.ui.stories.prefs.StoriesPrefs.TempId import org.wordpress.android.util.FluxCUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index b27894457404..f1d3ae7285f6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -148,7 +148,11 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( ) } - fun saveNewLocalFilesToStoriesPrefsTempSlides(site: SiteModel, storyIndex: StoryIndex, frames: ArrayList) { + fun saveNewLocalFilesToStoriesPrefsTempSlides( + site: SiteModel, + storyIndex: StoryIndex, + frames: ArrayList + ) { for ((frameIndex, frame) in frames.withIndex()) { if (frame.id == null) { val assignedTempId = getTempIdForStoryFrame( diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 799f5cfb5ad1..8a8dc49dda64 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -65,8 +65,8 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( return false } } else { - if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteId(mediaId.toLong())) - && !storiesPrefs.isValidSlide(site.id.toLong(), LocalId(StringUtils.stringToInt(mediaId)))) { + if (!storiesPrefs.isValidSlide(site.id.toLong(), RemoteId(mediaId.toLong())) && + !storiesPrefs.isValidSlide(site.id.toLong(), LocalId(StringUtils.stringToInt(mediaId)))) { return false } } From b8d6c4f7ca81bfc2c55025f48173c70ee3434d0f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 10:09:12 -0300 Subject: [PATCH 130/230] removed no longer needed check for anyMediaIdsInGutenbergStoryBlockAreCorrupt --- .../android/ui/posts/EditPostActivity.java | 13 ------------- .../usecase/LoadStoryFromStoriesPrefsUseCase.kt | 14 -------------- WordPress/src/main/res/values/strings.xml | 1 - 3 files changed, 28 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 79f25da089d5..49d6790a705f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3109,19 +3109,6 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { -// if (mLoadStoryFromStoriesPrefsUseCase.anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles)) { -// // unfortunately the medaiIds seem corrupt so, show a dialog and bail -// AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); -// builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); -// builder.setMessage(getString(R.string.dialog_edit_story_corrupt_message)); -// builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { -// dialog.dismiss(); -// }); -// AlertDialog dialog = builder.create(); -// dialog.show(); -// return; -// } - ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); if (!result.getNoSlidesLoaded()) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt index 8a8dc49dda64..4b7d0e694015 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt @@ -43,20 +43,6 @@ class LoadStoryFromStoriesPrefsUseCase @Inject constructor( return mediaIds } - fun anyMediaIdsInGutenbergStoryBlockAreCorrupt(mediaFiles: ArrayList): Boolean { - for (mediaFile in mediaFiles) { - try { - (mediaFile as HashMap)["id"] - .toString() - .toDouble() // this conversion is needed to strip off decimals that can come from RN - .toLong() - } catch (exception: NumberFormatException) { - return true - } - } - return false - } - fun areAllStorySlidesEditable(site: SiteModel, mediaIds: ArrayList): Boolean { for (mediaId in mediaIds) { // if this is not a remote nor a local / temporary slide, return false diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index ff075553c4da..ed5197aa7070 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2887,7 +2887,6 @@ Limited Story Editing This story was edited on a different device and the ability to edit certain objects may be limited. Can\'t edit Story - There was a problem saving this story and can\'t be edited at this moment. Unable to load media for this story. Check your internet connection and try again in a moment. Can\'t edit Story We couldn\'t find the media for this story on the site. From de53b35595ff3d999ccb5bad10e8c5b56a1c9a3f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 10:31:11 -0300 Subject: [PATCH 131/230] fixed bad indirection reference --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 49d6790a705f..1dc46d4c47f4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3156,7 +3156,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie ArrayList mediaIdsToRetry = new ArrayList<>(); for (Object mediaFile : mediaFiles) { int localMediaId - = StringUtils.stringToInt(((HashMap) mediaFile).toString(), 0); + = StringUtils.stringToInt(((HashMap) mediaFile).get("id").toString(), 0); if (localMediaId != 0) { MediaModel media = mMediaStore.getMediaWithLocalId(localMediaId); // if we find at least one item in the mediaFiles collection passed From 5406c63842a5938984cd8eb6e0d344d1cf8d24e1 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 10:35:10 -0300 Subject: [PATCH 132/230] using cancel label for cancel button --- .../android/editor/gutenberg/GutenbergEditorFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 47cd12d0288d..1b8767ea5eb4 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -667,7 +667,7 @@ public void onClick(DialogInterface dialog, int id) { } }); - builder.setNegativeButton(R.string.retry_failed_upload_remove, new DialogInterface.OnClickListener() { + builder.setNegativeButton(R.string.dialog_button_cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } From d065c92af47bedcae4cf0826765a60e80c75d0b4 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 10:52:20 -0300 Subject: [PATCH 133/230] using eventBusWrapper --- .../android/ui/posts/editor/StoriesEventListener.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index 4a2045aae724..fc853b1c4370 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -10,7 +10,6 @@ import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult -import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.editor.gutenberg.StorySaveMediaListener @@ -21,6 +20,7 @@ import org.wordpress.android.fluxc.store.MediaStore import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent +import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.util.FluxCUtils import org.wordpress.android.util.helpers.MediaFile import javax.inject.Inject @@ -28,6 +28,7 @@ import javax.inject.Inject class StoriesEventListener @Inject constructor( private val dispatcher: Dispatcher, private val mediaStore: MediaStore, + private val eventBusWrapper: EventBusWrapper, private val storyRepositoryWrapper: StoryRepositoryWrapper ) : LifecycleObserver { private lateinit var lifecycle: Lifecycle @@ -37,7 +38,7 @@ class StoriesEventListener @Inject constructor( @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) private fun onCreate() { dispatcher.register(this) - EventBus.getDefault().register(this) + eventBusWrapper.register(this) } /** @@ -48,7 +49,7 @@ class StoriesEventListener @Inject constructor( private fun onDestroy() { lifecycle.removeObserver(this) dispatcher.unregister(this) - EventBus.getDefault().unregister(this) + eventBusWrapper.unregister(this) } fun start(lifecycle: Lifecycle, site: SiteModel) { From 29f27c856d52600c92bd118e2ea37e91b3ed0743 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 14 Oct 2020 10:55:01 -0300 Subject: [PATCH 134/230] Update WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt Co-authored-by: Joel Dean --- .../wordpress/android/ui/posts/editor/StoriesEventListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index fc853b1c4370..b8c5b7ffb9a0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -69,7 +69,7 @@ class StoriesEventListener @Inject constructor( return } val localMediaId = event.frameId.toString() - val progress: Float = storyRepositoryWrapper.getCurrentStorySaveProgress(event.storyIndex, 0.0f) + val progress = storyRepositoryWrapper.getCurrentStorySaveProgress(event.storyIndex, 0.0f) storySaveMediaListener?.onMediaSaveReattached(localMediaId, progress) } From 5505f7d27cb608d73db2c77750566ab6f29e68e0 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 14 Oct 2020 10:57:21 -0300 Subject: [PATCH 135/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt Co-authored-by: Joel Dean --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index f53f4a94915b..7f78f1f8c58f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -21,7 +21,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( } } - fun buildJetpackStoryBlockString( + private fun buildJetpackStoryBlockString( mediaFiles: List ): String { val jsonArrayMediaFiles = ArrayList() // holds media files From 8b9885f6c968a5f5bec45ecf8a67eec8ac791c25 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 11:02:16 -0300 Subject: [PATCH 136/230] stripped String type from method name, as it can be inferred from the parameter type --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 7f78f1f8c58f..568c7cfd7f0d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -83,7 +83,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( postModel, object : DoWithMediaFilesListener { - override fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String { + override fun doWithMediaFilesJson(content: String, mediaFilesJsonString: String): String { var processedContent = content val storyBlockData: StoryBlockData? = gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) @@ -126,7 +126,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( val jsonString: String = content.substring( storyBlockStartIndex + HEADING_START.length, content.indexOf(HEADING_END)) - content = listener.doWithMediaFilesJsonString(content, jsonString) + content = listener.doWithMediaFilesJson(content, jsonString) storyBlockStartIndex += HEADING_START.length } } @@ -139,7 +139,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( postModel, object : DoWithMediaFilesListener { - override fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String { + override fun doWithMediaFilesJson(content: String, mediaFilesJsonString: String): String { var processedContent = content val storyBlockData: StoryBlockData? = gson.fromJson(mediaFilesJsonString, StoryBlockData::class.java) @@ -176,7 +176,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( } interface DoWithMediaFilesListener { - fun doWithMediaFilesJsonString(content: String, mediaFilesJsonString: String): String + fun doWithMediaFilesJson(content: String, mediaFilesJsonString: String): String } data class StoryBlockData( From f0c509d5c91577b7a162c8b80780b9b946408ce9 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 14 Oct 2020 11:02:59 -0300 Subject: [PATCH 137/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt Co-authored-by: Joel Dean --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 647e03d92d33..eb97bf399291 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -435,7 +435,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), override fun onFrameRemove(storyIndex: StoryIndex, storyFrameIndex: Int) { // keep record of the frames users deleted. // But we'll only actually do cleanup once they tap on the DONE/SAVE button, because they could - // still bail out of the StoryComposer by tapping back or the cross and then admiting they want to lose + // still bail out of the StoryComposer by tapping back or the cross and then admitting they want to lose // the changes they made (this means, they'd want to keep the stories). val story = storyRepositoryWrapper.getStoryAtIndex(storyIndex) if (storyFrameIndex < story.frames.size) { From 8def90fff7d33482f56027391de0efa2baee43cf Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 14 Oct 2020 11:03:15 -0300 Subject: [PATCH 138/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt Co-authored-by: Joel Dean --- .../android/ui/stories/media/StoryMediaSaveUploadBridge.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 7507f4431069..38d77f22b07b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -106,7 +106,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( if (!isEditMode) { saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost( editPostRepository, - ArrayList(mediaFiles.values) + ArrayList(mediaFiles.values) ) } else { // no op: in edit mode, we're handling replacing of the block's mediaFiles in Gutenberg From eff3b2881afce174e8fc62ec329b92ba581e312c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 11:20:19 -0300 Subject: [PATCH 139/230] renamed to shorten name --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 568c7cfd7f0d..81f1fd87a6dd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -80,7 +80,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( fun cleanTemporaryMediaFilesStructFoundInAnyStoryBlockInPost(editPostRepository: EditPostRepository) { editPostRepository.update { postModel: PostModel -> val gson = Gson() - findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( + findAllStoryBlocksInPostAndPerformOnEachMediaFilesJson( postModel, object : DoWithMediaFilesListener { override fun doWithMediaFilesJson(content: String, mediaFilesJsonString: String): String { @@ -108,7 +108,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( return temporaryIds.size > 0 } - fun findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( + fun findAllStoryBlocksInPostAndPerformOnEachMediaFilesJson( postModel: PostModel, listener: DoWithMediaFilesListener ) { @@ -136,7 +136,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( fun replaceLocalMediaIdsWithRemoteMediaIdsInPost(postModel: PostModel, mediaFile: MediaFile) { val gson = Gson() - findAllStoryBlocksInPostContentAndPerformOnEachMediaFilesJsonString( + findAllStoryBlocksInPostAndPerformOnEachMediaFilesJson( postModel, object : DoWithMediaFilesListener { override fun doWithMediaFilesJson(content: String, mediaFilesJsonString: String): String { From 873a364d290b970a53efccaa9901d1bb0c7b3a49 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 11:49:56 -0300 Subject: [PATCH 140/230] updated gutenberg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index e4b907c3e9a9..a76e41781e4e 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit e4b907c3e9a971c8e0021e310ba4b86dcdb92076 +Subproject commit a76e41781e4e8a4791c8006804aaf9eb06edbd04 From bb63fc3bb243eb0f024f045e063cd2580bc81ab5 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 12:00:27 -0300 Subject: [PATCH 141/230] updated commit hash for gutenberg-mobile --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index a76e41781e4e..3130e2449ca3 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit a76e41781e4e8a4791c8006804aaf9eb06edbd04 +Subproject commit 3130e2449ca3c390474a579654076f90ee58555c From 640183eb2fc24de718635b15552d8654a4df745b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 14:04:00 -0300 Subject: [PATCH 142/230] updated commit hash after merge --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 3130e2449ca3..03d3abe6590b 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 3130e2449ca3c390474a579654076f90ee58555c +Subproject commit 03d3abe6590b4c46e7db2176d0633b62325f7ef0 From cb1305d36188591b8a513ce2635161892c9de717 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 14 Oct 2020 14:56:24 -0300 Subject: [PATCH 143/230] updated gutenberg-mobile branch --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 03d3abe6590b..de365b19dd79 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 03d3abe6590b4c46e7db2176d0633b62325f7ef0 +Subproject commit de365b19dd795a5843b08ec36ca349eeb617703b From 05f424d189c762682aed23b6655818dc8b97c150 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 15 Oct 2020 21:08:19 -0300 Subject: [PATCH 144/230] updated gutenberg-mobile hash' --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index de365b19dd79..afedc7e30ca7 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit de365b19dd795a5843b08ec36ca349eeb617703b +Subproject commit afedc7e30ca7c7dc5e86a00c8a9be7f9a276cd2a From c56d2db21766334b01ed6cbd32f2c9c5ed8db376 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 16 Oct 2020 16:47:08 -0300 Subject: [PATCH 145/230] updated gutenberg-mobile hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index afedc7e30ca7..56f2eda8e029 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit afedc7e30ca7c7dc5e86a00c8a9be7f9a276cd2a +Subproject commit 56f2eda8e02967c76ff1fb0dc23a25cc5915edc7 From 27feee8f913cd11ee22786514cd0b00edd535d0f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 16 Oct 2020 19:31:52 -0300 Subject: [PATCH 146/230] updated gutenberg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 56f2eda8e029..1e637673eeb9 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 56f2eda8e02967c76ff1fb0dc23a25cc5915edc7 +Subproject commit 1e637673eeb98d93981ff7a0b2c4c0921e197108 From b09a3c954f7ca62fe6894ac21a226bdafefcad1f Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 16 Oct 2020 20:21:36 -0300 Subject: [PATCH 147/230] updated gutenberg-mobile hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 875112c46153..6274268bb958 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 875112c46153b0a2169d2ddc7a6144b537728a5f +Subproject commit 6274268bb9589eb1ffde2df4f616413281350299 From 550f2e134259bd9d37a0aff8249e0bafb5f12ef1 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 16 Oct 2020 20:21:53 -0300 Subject: [PATCH 148/230] updates stories lib hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 2395566a4470..ec323840d236 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 2395566a4470d6751bdb547bd231f9fdb31f2ca0 +Subproject commit ec323840d2360bb8421b63f59f5e7249689332d4 From 012aac76a4af1f31e3f55cfc9836983ae169efd5 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 17 Oct 2020 09:59:56 -0300 Subject: [PATCH 149/230] update gutenberg-mobile commit hash to point to bundling DEV flag lifting for internal release --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 6274268bb958..5606cc683c73 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 6274268bb9589eb1ffde2df4f616413281350299 +Subproject commit 5606cc683c732256217fa009973de8a1888ebe00 From f38dd3f568b1b1a4d61f2857e61e1c123f12ed82 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 17 Oct 2020 11:10:26 -0300 Subject: [PATCH 150/230] updated gutenberg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 5606cc683c73..f0374d931e8e 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 5606cc683c732256217fa009973de8a1888ebe00 +Subproject commit f0374d931e8e415055b3690335468bb2f8c6823e From 64f084d4503e06f7ab3f98ddde1f57cba8d3df56 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 17 Oct 2020 11:23:03 -0300 Subject: [PATCH 151/230] added temporary alert dialog for alpha when users tap on an empty story block --- .../wordpress/android/ui/posts/EditPostActivity.java | 12 ++++++++++++ WordPress/src/main/res/values/strings.xml | 2 ++ 2 files changed, 14 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index cc26947a5ace..fa8a894c4f69 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3252,6 +3252,18 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { + if (mediaFiles.isEmpty()) { + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); + builder.setTitle(getString(R.string.dialog_edit_story_no_new_blocks_title)); + builder.setMessage(getString(R.string.dialog_edit_story_no_new_blocks_message)); + builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { + dialog.dismiss(); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + return; + } + ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); if (!result.getNoSlidesLoaded()) { diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 6f47ea49191f..7705271cf669 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2906,6 +2906,8 @@ Unable to load media for this story. Check your internet connection and try again in a moment. Can\'t edit Story We couldn\'t find the media for this story on the site. + Can\'t create Story + Alpha - we can\'t create a Story here for now ¯\_(ツ)_/¯ - use the main menu or Posts list entry points Capture Flip camera Flash From 9495a36e293eca76697025859459aee536a6c04a Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Sat, 17 Oct 2020 11:25:01 -0300 Subject: [PATCH 152/230] updated string --- WordPress/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 7705271cf669..af4a02915eaf 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2907,7 +2907,7 @@ Can\'t edit Story We couldn\'t find the media for this story on the site. Can\'t create Story - Alpha - we can\'t create a Story here for now ¯\_(ツ)_/¯ - use the main menu or Posts list entry points + Alpha - we can\'t create a Story here for now ¯\\_(ツ)_/¯ - use the main menu or Posts list entry points Capture Flip camera Flash From 037b679ede139f08c6bff05ea351e9fc0bdeeff1 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 08:57:37 -0300 Subject: [PATCH 153/230] changed name --- WordPress/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index af4a02915eaf..7051dbad0cb9 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2907,7 +2907,7 @@ Can\'t edit Story We couldn\'t find the media for this story on the site. Can\'t create Story - Alpha - we can\'t create a Story here for now ¯\\_(ツ)_/¯ - use the main menu or Posts list entry points + Internal Beta - we can\'t create a Story here for now ¯\\_(ツ)_/¯ - use the main menu or Posts list entry points Capture Flip camera Flash From ae1010043868d6f7f99cb612d601faab5cd494b8 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 09:24:15 -0300 Subject: [PATCH 154/230] updated stories lib hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 93390586f1f8..f7f20e13e397 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 93390586f1f852761fac44ba9ec6b1b1dfc9bc09 +Subproject commit f7f20e13e39793949b432c31e8e7ffca8d0644ad From 75e8942ddf0eb9eacfa47cf861314c90ec506a63 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 11:07:55 -0300 Subject: [PATCH 155/230] opening the editor in capture mode when an empty blocked is tapped to allow adding slides --- .../android/ui/ActivityLauncher.java | 19 +++++++++++++++++++ .../android/ui/posts/EditPostActivity.java | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index 9f684944a8b0..54d1b3d0f7f6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -771,6 +771,25 @@ public static void editStoryForResult( activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); } + public static void editEmptyStoryForResult( + Activity activity, + SiteModel site, + int storyIndex, + String storyBlockId + ) { + if (site == null) { + return; + } + + Intent intent = new Intent(activity, StoryComposerActivity.class); + intent.putExtra(WordPress.SITE, site); + intent.putExtra(KEY_LAUNCHED_FROM_GUTENBERG, true); + intent.putExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, true); + intent.putExtra(KEY_STORY_INDEX, storyIndex); + intent.putExtra(ARG_STORY_BLOCK_ID, storyBlockId); + activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); + } + public static void editPostOrPageForResult(Activity activity, SiteModel site, PostModel post) { editPostOrPageForResult(new Intent(activity, EditPostActivity.class), activity, site, post.getId(), false); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index cc26947a5ace..c80232b0ad4c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -119,6 +119,7 @@ import org.wordpress.android.ui.ActivityId; import org.wordpress.android.ui.ActivityLauncher; import org.wordpress.android.ui.LocaleAwareActivity; +import org.wordpress.android.ui.PagePostCreationSourcesDetail; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog.PrivateAtCookieProgressDialogOnDismissListener; import org.wordpress.android.ui.RequestCodes; @@ -3254,6 +3255,16 @@ public void onTrackableEvent(TrackableEvent event, Map propertie @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); + if (mediaFiles.isEmpty()) { + ActivityLauncher.editEmptyStoryForResult( + this, + mSite, + mStoryRepositoryWrapper.getCurrentStoryIndex(), + blockId + ); + return; + } + if (!result.getNoSlidesLoaded()) { // Story instance loaded or re-created! Load it onto the StoryComposer for editing now ActivityLauncher.editStoryForResult( From 67c9bea1250d85366abe4948936ed3f2aa6e7844 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 11:23:33 -0300 Subject: [PATCH 156/230] load an existing story if KEY_STORY_INDEX passed, or load current story if not passed, or load a new story if unselected --- .../wordpress/android/ui/stories/StoryComposerActivity.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 4f321cea2ccf..ff21dc49bc98 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -480,7 +480,12 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), val blockId = intent.extras?.getString(ARG_STORY_BLOCK_ID) savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) - val storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) + var storyIndex = intent.getIntExtra(KEY_STORY_INDEX, storyRepositoryWrapper.getCurrentStoryIndex()) + if (storyIndex == DEFAULT_NONE_SELECTED) { + // load a new empty story + storyRepositoryWrapper.loadStory(DEFAULT_NONE_SELECTED) + storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() + } // if we are editing this Story Block, then the id is assured to be a remote media file id, but // the frame no longer points to such media Id on the site given we are just about to save a // new flattened media. Hence, we need to set a new temporary Id we can use to identify From 6d1cdc3c5fc0ef05f2b5b13fc07c6f84242ee000 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 11:43:40 -0300 Subject: [PATCH 157/230] got activity launcher call for stories back, for the case of empty mediaFiles --- .../android/ui/posts/EditPostActivity.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 4ac4b6e7d8b7..3aacec115202 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3254,14 +3254,20 @@ public void onTrackableEvent(TrackableEvent event, Map propertie @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { if (mediaFiles.isEmpty()) { - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); - builder.setTitle(getString(R.string.dialog_edit_story_no_new_blocks_title)); - builder.setMessage(getString(R.string.dialog_edit_story_no_new_blocks_message)); - builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { - dialog.dismiss(); - }); - AlertDialog dialog = builder.create(); - dialog.show(); +// AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); +// builder.setTitle(getString(R.string.dialog_edit_story_no_new_blocks_title)); +// builder.setMessage(getString(R.string.dialog_edit_story_no_new_blocks_message)); +// builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { +// dialog.dismiss(); +// }); +// AlertDialog dialog = builder.create(); +// dialog.show(); + ActivityLauncher.editEmptyStoryForResult( + this, + mSite, + mStoryRepositoryWrapper.getCurrentStoryIndex(), + blockId + ); return; } From 35f45a64b18f4cc977c0bd36fac661e60ca9925b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 11:46:06 -0300 Subject: [PATCH 158/230] added TODO comment --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 3aacec115202..2128b4c444d1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3254,6 +3254,7 @@ public void onTrackableEvent(TrackableEvent event, Map propertie @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { if (mediaFiles.isEmpty()) { + // TODO remove this code and related string resources after beta // AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); // builder.setTitle(getString(R.string.dialog_edit_story_no_new_blocks_title)); // builder.setMessage(getString(R.string.dialog_edit_story_no_new_blocks_message)); From 48302482b70defe5c0c464e56188e143859da951 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 12:24:05 -0300 Subject: [PATCH 159/230] fixed story index loading --- .../wordpress/android/ui/stories/StoryComposerActivity.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index ff21dc49bc98..0e5ebdc6e28b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -480,10 +480,10 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), val blockId = intent.extras?.getString(ARG_STORY_BLOCK_ID) savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) - var storyIndex = intent.getIntExtra(KEY_STORY_INDEX, storyRepositoryWrapper.getCurrentStoryIndex()) + // check if story index has been passed through intent + var storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) if (storyIndex == DEFAULT_NONE_SELECTED) { - // load a new empty story - storyRepositoryWrapper.loadStory(DEFAULT_NONE_SELECTED) + // if not, let's use the current Story storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() } // if we are editing this Story Block, then the id is assured to be a remote media file id, but From 6f0928f2c6c538b9d15d6ea4c081aab34e120f7b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 12:24:24 -0300 Subject: [PATCH 160/230] passing localPostId to correctly update it --- .../java/org/wordpress/android/ui/ActivityLauncher.java | 2 ++ .../org/wordpress/android/ui/posts/EditPostActivity.java | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index 54d1b3d0f7f6..2c674ce7e86e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -774,6 +774,7 @@ public static void editStoryForResult( public static void editEmptyStoryForResult( Activity activity, SiteModel site, + LocalId localPostId, int storyIndex, String storyBlockId ) { @@ -785,6 +786,7 @@ public static void editEmptyStoryForResult( intent.putExtra(WordPress.SITE, site); intent.putExtra(KEY_LAUNCHED_FROM_GUTENBERG, true); intent.putExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, true); + intent.putExtra(KEY_POST_LOCAL_ID, localPostId.getValue()); intent.putExtra(KEY_STORY_INDEX, storyIndex); intent.putExtra(ARG_STORY_BLOCK_ID, storyBlockId); activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index c80232b0ad4c..e969385d84dc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3253,18 +3253,20 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase - .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); if (mediaFiles.isEmpty()) { ActivityLauncher.editEmptyStoryForResult( this, mSite, + new LocalId(mEditPostRepository.getId()), mStoryRepositoryWrapper.getCurrentStoryIndex(), blockId ); return; } + ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase + .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); + if (!result.getNoSlidesLoaded()) { // Story instance loaded or re-created! Load it onto the StoryComposer for editing now ActivityLauncher.editStoryForResult( From 946941376122fa7f06471b76fbf89bb406a274b9 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Mon, 19 Oct 2020 12:36:00 -0300 Subject: [PATCH 161/230] removed unused import --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index e969385d84dc..9978df937d00 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -119,7 +119,6 @@ import org.wordpress.android.ui.ActivityId; import org.wordpress.android.ui.ActivityLauncher; import org.wordpress.android.ui.LocaleAwareActivity; -import org.wordpress.android.ui.PagePostCreationSourcesDetail; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog; import org.wordpress.android.ui.PrivateAtCookieRefreshProgressDialog.PrivateAtCookieProgressDialogOnDismissListener; import org.wordpress.android.ui.RequestCodes; From ca2bc90286f104b9babf12f02a7658a47eb01898 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 20 Oct 2020 08:09:20 -0300 Subject: [PATCH 162/230] updated commit hash for gutenberg-mobile, with new media placehodler for empty block --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index f0374d931e8e..73b2f1fd0bbf 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit f0374d931e8e415055b3690335468bb2f8c6823e +Subproject commit 73b2f1fd0bbfe774a5293347ce08e16a99a22ab6 From 423068ac7f19989a4cbd970ca9c1df4249021d71 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 20 Oct 2020 08:27:37 -0300 Subject: [PATCH 163/230] removed old commented dialog and related string resourced --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 9 --------- WordPress/src/main/res/values/strings.xml | 2 -- 2 files changed, 11 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 772ea78bdfb6..9978df937d00 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3253,15 +3253,6 @@ public void onTrackableEvent(TrackableEvent event, Map propertie @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { if (mediaFiles.isEmpty()) { - // TODO remove this code and related string resources after beta -// AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); -// builder.setTitle(getString(R.string.dialog_edit_story_no_new_blocks_title)); -// builder.setMessage(getString(R.string.dialog_edit_story_no_new_blocks_message)); -// builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { -// dialog.dismiss(); -// }); -// AlertDialog dialog = builder.create(); -// dialog.show(); ActivityLauncher.editEmptyStoryForResult( this, mSite, diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 7051dbad0cb9..6f47ea49191f 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2906,8 +2906,6 @@ Unable to load media for this story. Check your internet connection and try again in a moment. Can\'t edit Story We couldn\'t find the media for this story on the site. - Can\'t create Story - Internal Beta - we can\'t create a Story here for now ¯\\_(ツ)_/¯ - use the main menu or Posts list entry points Capture Flip camera Flash From ef587b644105ee2b30bd4a98e91a6449824e293c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 20 Oct 2020 10:34:06 -0300 Subject: [PATCH 164/230] updated commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 6274268bb958..080a970f72b6 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 6274268bb9589eb1ffde2df4f616413281350299 +Subproject commit 080a970f72b6c7e64884d58cafe6345efc7855c2 From 76bc10097b85878411b1266ee113c30307548000 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 20 Oct 2020 12:06:29 -0300 Subject: [PATCH 165/230] updated gutenberg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 080a970f72b6..ed36dfc682ec 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 080a970f72b6c7e64884d58cafe6345efc7855c2 +Subproject commit ed36dfc682ec2203fe8f7b9995ca0dc94b90065d From 1e5220fa113216e062e3269924c8cd5afeafb887 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 11:19:46 -0300 Subject: [PATCH 166/230] moved logic for Stories-related load/retry/cancel handling from EditPostActivity to dedicated class StoriesEventListener --- .../android/ui/posts/EditPostActivity.java | 111 ++----------- .../ui/posts/editor/StoriesEventListener.kt | 154 +++++++++++++++++- 2 files changed, 167 insertions(+), 98 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index cc26947a5ace..3714347c3bb6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -171,7 +171,6 @@ import org.wordpress.android.ui.stories.StoryRepositoryWrapper; import org.wordpress.android.ui.stories.prefs.StoriesPrefs; import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase; -import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase.ReCreateStoryResult; import org.wordpress.android.ui.uploads.PostEvents; import org.wordpress.android.ui.uploads.UploadService; import org.wordpress.android.ui.uploads.UploadUtils; @@ -677,7 +676,7 @@ protected void onCreate(Bundle savedInstanceState) { setupPrepublishingBottomSheetRunnable(); - mStoriesEventListener.start(this.getLifecycle(), mSite); + mStoriesEventListener.start(this.getLifecycle(), mSite, mEditPostRepository); setupPreviewUI(); } @@ -3252,110 +3251,30 @@ public void onTrackableEvent(TrackableEvent event, Map propertie } @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - ReCreateStoryResult result = mLoadStoryFromStoriesPrefsUseCase - .loadStoryFromMemoryOrRecreateFromPrefs(mSite, mediaFiles); - if (!result.getNoSlidesLoaded()) { - // Story instance loaded or re-created! Load it onto the StoryComposer for editing now - ActivityLauncher.editStoryForResult( - this, - mSite, - new LocalId(mEditPostRepository.getId()), - result.getStoryIndex(), - result.getAllStorySlidesAreEditable(), - true, - blockId - ); - } else { - // unfortunately we couldn't even load the remote media Ids indicated by the StoryBlock so we can't allow - // editing at this time :( - if (mNetworkErrorOnLastMediaFetchAttempt) { - // there was an error fetching media when we were loading the editor, - // we *may* still have a possibility, tell the user they may try refreshing the media again - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); - builder.setTitle(getString(R.string.dialog_edit_story_unavailable_title)); - builder.setMessage(getString(R.string.dialog_edit_story_unavailable_message)); - builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { - // try another fetchMedia request - fetchMediaList(); - dialog.dismiss(); - }); - AlertDialog dialog = builder.create(); - dialog.show(); - } else { - // unrecoverable error, nothing we can do, inform the user :(. - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); - builder.setTitle(getString(R.string.dialog_edit_story_unrecoverable_title)); - builder.setMessage(getString(R.string.dialog_edit_story_unrecoverable_message)); - builder.setPositiveButton(R.string.dialog_button_ok, (dialog, id) -> { - dialog.dismiss(); - }); - AlertDialog dialog = builder.create(); - dialog.show(); - } + boolean noSlidesLoaded = mStoriesEventListener.onRequestMediaFilesEditorLoad( + this, + new LocalId(mEditPostRepository.getId()), + mNetworkErrorOnLastMediaFetchAttempt, + mediaFiles, + blockId + ); + + if (mNetworkErrorOnLastMediaFetchAttempt && noSlidesLoaded) { + // try another fetchMedia request + fetchMediaList(); } } @Override public void onRetryUploadForMediaCollection(ArrayList mediaFiles) { - ArrayList mediaIdsToRetry = new ArrayList<>(); - for (Object mediaFile : mediaFiles) { - int localMediaId - = StringUtils.stringToInt(((HashMap) mediaFile).get("id").toString(), 0); - if (localMediaId != 0) { - MediaModel media = mMediaStore.getMediaWithLocalId(localMediaId); - // if we find at least one item in the mediaFiles collection passed - // for which we don't have a local MediaModel, just tell the user and bail - if (media == null) { - AppLog.e(T.MEDIA, "Can't find media with local id: " + localMediaId); - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); - builder.setTitle(getString(R.string.cannot_retry_deleted_media_item_fatal)); - builder.setPositiveButton(R.string.yes, (dialog, id) -> { - dialog.dismiss(); - }); - - builder.setNegativeButton(getString(R.string.no), (dialog, id) -> dialog.dismiss()); - - AlertDialog dialog = builder.create(); - dialog.show(); - - return; - } - - if (media.getUrl() != null && media.getUploadState().equals(MediaUploadState.UPLOADED.toString())) { - // Note: we should actually do this when the editor fragment starts instead of waiting for user - // input. - // Notify the editor fragment upload was successful and it should replace the local url by the - // remote url. - if (mEditorMediaUploadListener != null) { - mEditorMediaUploadListener.onMediaUploadSucceeded(String.valueOf(media.getId()), - FluxCUtils.mediaFileFromMediaModel(media)); - } - } else { - UploadService.cancelFinalNotification(this, mEditPostRepository.getPost()); - UploadService.cancelFinalNotificationForMedia(this, mSite); - mediaIdsToRetry.add(localMediaId); - } - } - } - - if (!mediaIdsToRetry.isEmpty()) { - mEditorMedia.retryFailedMediaAsync(mediaIdsToRetry); - } - AnalyticsTracker.track(Stat.EDITOR_UPLOAD_MEDIA_RETRIED); + mStoriesEventListener.onRetryUploadForMediaCollection(this, mediaFiles, mEditorMediaUploadListener); } @Override public void onCancelUploadForMediaCollection(ArrayList mediaFiles) { - // just cancel upload for each media - for (Object mediaFile : mediaFiles) { - int localMediaId - = StringUtils.stringToInt(((HashMap) mediaFile).get("id").toString(), 0); - if (localMediaId != 0) { - mEditorMedia.cancelMediaUploadAsync(localMediaId, false); - } - } + mStoriesEventListener.onCancelUploadForMediaCollection(mediaFiles); } @Override public void onCancelSaveForMediaCollection(ArrayList mediaFiles) { - // TODO implement cancelling save process for media collection + mStoriesEventListener.onCancelSaveForMediaCollection(mediaFiles); } // FluxC events diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index 4469a26bb3a8..2732766f11db 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -1,10 +1,14 @@ package org.wordpress.android.ui.posts.editor +import android.app.Activity +import android.content.DialogInterface import android.net.Uri +import androidx.appcompat.app.AlertDialog.Builder import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle.State.CREATED import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveCompleted import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress @@ -12,27 +16,47 @@ import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode +import org.wordpress.android.R +import org.wordpress.android.R.string +import org.wordpress.android.analytics.AnalyticsTracker +import org.wordpress.android.analytics.AnalyticsTracker.Stat.EDITOR_UPLOAD_MEDIA_RETRIED +import org.wordpress.android.editor.EditorMediaUploadListener import org.wordpress.android.editor.gutenberg.StorySaveMediaListener import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.MediaModel +import org.wordpress.android.fluxc.model.MediaModel.MediaUploadState.UPLOADED import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore +import org.wordpress.android.ui.ActivityLauncher +import org.wordpress.android.ui.posts.EditPostRepository +import org.wordpress.android.ui.posts.editor.media.EditorMedia import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.media.StoryMediaSaveUploadBridge.StoryFrameMediaModelCreatedEvent +import org.wordpress.android.ui.stories.usecase.LoadStoryFromStoriesPrefsUseCase +import org.wordpress.android.ui.uploads.UploadService +import org.wordpress.android.util.AppLog +import org.wordpress.android.util.AppLog.T.MEDIA import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.util.FluxCUtils +import org.wordpress.android.util.StringUtils import org.wordpress.android.util.helpers.MediaFile +import java.util.ArrayList +import java.util.HashMap import javax.inject.Inject class StoriesEventListener @Inject constructor( private val dispatcher: Dispatcher, private val mediaStore: MediaStore, private val eventBusWrapper: EventBusWrapper, + private val editorMedia: EditorMedia, + private val loadStoryFromStoriesPrefsUseCase: LoadStoryFromStoriesPrefsUseCase, private val storyRepositoryWrapper: StoryRepositoryWrapper ) : LifecycleObserver { private lateinit var lifecycle: Lifecycle private lateinit var site: SiteModel + private lateinit var editPostRepository: EditPostRepository private var storySaveMediaListener: StorySaveMediaListener? = null @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) @@ -43,7 +67,7 @@ class StoriesEventListener @Inject constructor( /** * Handles the [Lifecycle.Event.ON_DESTROY] event to cleanup the registration for dispatcher and removing the - * observer for lifecycle. + * observer for lifecycle . */ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) private fun onDestroy() { @@ -52,8 +76,9 @@ class StoriesEventListener @Inject constructor( eventBusWrapper.unregister(this) } - fun start(lifecycle: Lifecycle, site: SiteModel) { + fun start(lifecycle: Lifecycle, site: SiteModel, editPostRepository: EditPostRepository) { this.site = site + this.editPostRepository = editPostRepository this.lifecycle = lifecycle this.lifecycle.addObserver(this) } @@ -153,4 +178,129 @@ class StoriesEventListener @Inject constructor( storySaveMediaListener?.onStorySaveResult(localMediaId, event.isSuccess()) } } + + // Editor load / cancel events + fun onRequestMediaFilesEditorLoad( + activity: Activity, + postId: LocalId, + networkErrorOnLastMediaFetchAttempt: Boolean, + mediaFiles: ArrayList, + blockId: String + ): Boolean { + val reCreateStoryResult = loadStoryFromStoriesPrefsUseCase + .loadStoryFromMemoryOrRecreateFromPrefs(site, mediaFiles) + if (!reCreateStoryResult.noSlidesLoaded) { + // Story instance loaded or re-created! Load it onto the StoryComposer for editing now + ActivityLauncher.editStoryForResult( + activity, + site, + postId, + reCreateStoryResult.storyIndex, + reCreateStoryResult.allStorySlidesAreEditable, + true, + blockId + ) + } else { + // unfortunately we couldn't even load the remote media Ids indicated by the StoryBlock so we can't allow + // editing at this time :( + if (networkErrorOnLastMediaFetchAttempt) { + // there was an error fetching media when we were loading the editor, + // we *may* still have a possibility, tell the user they may try refreshing the media again + val builder: Builder = MaterialAlertDialogBuilder( + activity + ) + builder.setTitle(activity.getString(R.string.dialog_edit_story_unavailable_title)) + builder.setMessage(activity.getString(R.string.dialog_edit_story_unavailable_message)) + builder.setPositiveButton(R.string.dialog_button_ok) { dialog, id -> + dialog.dismiss() + } + val dialog = builder.create() + dialog.show() + } else { + // unrecoverable error, nothing we can do, inform the user :(. + val builder: Builder = MaterialAlertDialogBuilder( + activity + ) + builder.setTitle(activity.getString(R.string.dialog_edit_story_unrecoverable_title)) + builder.setMessage(activity.getString(R.string.dialog_edit_story_unrecoverable_message)) + builder.setPositiveButton(R.string.dialog_button_ok) { dialog, id -> dialog.dismiss() } + val dialog = builder.create() + dialog.show() + } + } + return reCreateStoryResult.noSlidesLoaded + } + + fun onCancelUploadForMediaCollection(mediaFiles: ArrayList) { + // just cancel upload for each media + for (mediaFile in mediaFiles) { + val localMediaId = StringUtils.stringToInt( + (mediaFile as HashMap)["id"].toString(), 0 + ) + if (localMediaId != 0) { + editorMedia.cancelMediaUploadAsync(localMediaId, false) + } + } + } + + fun onRetryUploadForMediaCollection( + activity: Activity, + mediaFiles: ArrayList, + editorMediaUploadListener: EditorMediaUploadListener? + ) { + val mediaIdsToRetry = ArrayList() + for (mediaFile in mediaFiles) { + val localMediaId = StringUtils.stringToInt( + (mediaFile as HashMap)["id"].toString(), 0 + ) + if (localMediaId != 0) { + val media: MediaModel = mediaStore.getMediaWithLocalId(localMediaId) + // if we find at least one item in the mediaFiles collection passed + // for which we don't have a local MediaModel, just tell the user and bail + if (media == null) { + AppLog.e( + MEDIA, + "Can't find media with local id: $localMediaId" + ) + val builder: Builder = MaterialAlertDialogBuilder( + activity + ) + builder.setTitle(activity.getString(string.cannot_retry_deleted_media_item_fatal)) + builder.setPositiveButton(string.yes) { dialog, id -> dialog.dismiss() } + builder.setNegativeButton(activity.getString(string.no), + DialogInterface.OnClickListener { dialog: DialogInterface, id: Int -> dialog.dismiss() } + ) + val dialog = builder.create() + dialog.show() + return + } + if (media.url != null && media.uploadState == UPLOADED.toString()) { + // Note: we should actually do this when the editor fragment starts instead of waiting for user + // input. + // Notify the editor fragment upload was successful and it should replace the local url by the + // remote url. + editorMediaUploadListener?.onMediaUploadSucceeded( + media.id.toString(), + FluxCUtils.mediaFileFromMediaModel(media) + ) + } else { + UploadService.cancelFinalNotification( + activity, + editPostRepository.getPost() + ) + UploadService.cancelFinalNotificationForMedia(activity, site) + mediaIdsToRetry.add(localMediaId) + } + } + } + + if (!mediaIdsToRetry.isEmpty()) { + editorMedia.retryFailedMediaAsync(mediaIdsToRetry) + } + AnalyticsTracker.track(EDITOR_UPLOAD_MEDIA_RETRIED) + } + + fun onCancelSaveForMediaCollection(mediaFiles: ArrayList) { + // TODO implement cancelling save process for media collection + } } From 6d01bff26e8751421ca81becaa899fe24953e637 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 12:07:04 -0300 Subject: [PATCH 167/230] updated stories commit hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index f7f20e13e397..621c36488b99 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit f7f20e13e39793949b432c31e8e7ffca8d0644ad +Subproject commit 621c36488b999208617b9e72b3291f4a83c02d0a From 546b6671b8527c24a98e05bae750f6069c1ccc08 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:11:26 -0300 Subject: [PATCH 168/230] adding unit tests for LoadStoryFromStoriesPrefsUseCase class - partial --- .../LoadStoryFromStoriesPrefsUseCaseTest.kt | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt new file mode 100644 index 000000000000..a4608bdd348c --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt @@ -0,0 +1,120 @@ +package org.wordpress.android.ui.stories.usecase + +import android.content.Context +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import org.assertj.core.api.Assertions +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnitRunner +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId +import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.MediaStore +import org.wordpress.android.ui.posts.EditPostRepository +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX +import org.wordpress.android.ui.stories.StoryRepositoryWrapper +import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.ui.stories.prefs.StoriesPrefs.TempId + +@RunWith(MockitoJUnitRunner::class) +class LoadStoryFromStoriesPrefsUseCaseTest { + private lateinit var loadStoryFromStoriesPrefsUseCase: LoadStoryFromStoriesPrefsUseCase + @Mock lateinit var storyRepositoryWrapper: StoryRepositoryWrapper + @Mock lateinit var mediaStore: MediaStore + @Mock lateinit var storiesPrefs: StoriesPrefs + @Mock lateinit var context: Context + @Mock lateinit var postRepository: EditPostRepository + private lateinit var siteModel: SiteModel + + @Before + fun setUp() { + loadStoryFromStoriesPrefsUseCase = LoadStoryFromStoriesPrefsUseCase( + storyRepositoryWrapper, + storiesPrefs, + mediaStore + ) + siteModel = SiteModel() + } + + @Test + fun `obtain empty media ids list from empty mediaFiles array`() { + // Given + val mediaFiles: ArrayList> = setupMediaFiles(emptyList = true) + + // When + val mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles as ArrayList) + + // Then + Assertions.assertThat(mediaIds).isEmpty() + } + + @Test + fun `obtain media ids list from non empty mediaFiles array`() { + // Given + val mediaFiles: ArrayList> = setupMediaFiles(emptyList = false) + + // When + val mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles as ArrayList) + + // Then + Assertions.assertThat(mediaIds).isNotEmpty + Assertions.assertThat(mediaIds).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9", "10") + } + + @Test + fun `verify all story slides are editable with temporary ids`() { + // Given + val mediaIdsTemp = setupTestSildes(sayValid = true, useTempPrefix = true, useRemoteId = false) + + // When + val result = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(siteModel, mediaIdsTemp) + + // Then + Assertions.assertThat(result).isTrue() + } + + private fun setupMediaFiles( + emptyList: Boolean + ): ArrayList> { + when (emptyList) { + true -> return ArrayList>() + false -> { + val mediaFiles = ArrayList>() + for (i in 1..10) { + val oneMediaFile = HashMap() + oneMediaFile.put("mime", "image/jpeg") + oneMediaFile.put("link", "https://testmzorz3.files.wordpress.com/2020/10/wp-0000000.jpg") + oneMediaFile.put("type", "image") + oneMediaFile.put("id", i.toString()) + mediaFiles.add(oneMediaFile) + } + return mediaFiles + } + } + } + + private fun setupTestSildes( + sayValid: Boolean, + useTempPrefix: Boolean, + useRemoteId: Boolean + ): ArrayList { + val mediaIds = ArrayList() + + for (i in 1..10) { + mediaIds.add((if (useTempPrefix) TEMPORARY_ID_PREFIX else "") + i.toString()) + } + + if (useTempPrefix) { + whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), mock())).thenReturn(sayValid) + } else if (useRemoteId) { + whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), mock())).thenReturn(sayValid) + } else { + whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), mock())).thenReturn(sayValid) + } + + return mediaIds + } +} From 7ab26a533238e770f19d65ae3b5ea3e917e0a8e1 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:30:37 -0300 Subject: [PATCH 169/230] added test cases for method areAllStorySlidesEditable --- .../LoadStoryFromStoriesPrefsUseCaseTest.kt | 78 ++++++++++++++++--- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt index a4608bdd348c..48856e2b7567 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt @@ -76,6 +76,66 @@ class LoadStoryFromStoriesPrefsUseCaseTest { Assertions.assertThat(result).isTrue() } + @Test + fun `verify all story slides are editable with local ids`() { + // Given + val mediaIdsLocal = setupTestSildes(sayValid = true, useTempPrefix = false, useRemoteId = false) + + // When + val result = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(siteModel, mediaIdsLocal) + + // Then + Assertions.assertThat(result).isTrue() + } + + @Test + fun `verify all story slides are editable with remote ids`() { + // Given + val mediaIdsLocal = setupTestSildes(sayValid = true, useTempPrefix = false, useRemoteId = true) + + // When + val result = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(siteModel, mediaIdsLocal) + + // Then + Assertions.assertThat(result).isTrue() + } + + @Test + fun `verify not all story slides are editable with temporary ids`() { + // Given + val mediaIdsLocal = setupTestSildes(sayValid = false, useTempPrefix = true, useRemoteId = false) + + // When + val result = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(siteModel, mediaIdsLocal) + + // Then + Assertions.assertThat(result).isFalse() + } + + @Test + fun `verify not all story slides are editable with remote ids`() { + // Given + val mediaIdsLocal = setupTestSildes(sayValid = false, useTempPrefix = false, useRemoteId = true) + + // When + val result = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(siteModel, mediaIdsLocal) + + // Then + Assertions.assertThat(result).isFalse() + } + + @Test + fun `verify not all story slides are editable with local ids`() { + // Given + val mediaIdsLocal = setupTestSildes(sayValid = false, useTempPrefix = false, useRemoteId = false) + + // When + val result = loadStoryFromStoriesPrefsUseCase.areAllStorySlidesEditable(siteModel, mediaIdsLocal) + + // Then + Assertions.assertThat(result).isFalse() + } + private fun setupMediaFiles( emptyList: Boolean ): ArrayList> { @@ -104,15 +164,15 @@ class LoadStoryFromStoriesPrefsUseCaseTest { val mediaIds = ArrayList() for (i in 1..10) { - mediaIds.add((if (useTempPrefix) TEMPORARY_ID_PREFIX else "") + i.toString()) - } - - if (useTempPrefix) { - whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), mock())).thenReturn(sayValid) - } else if (useRemoteId) { - whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), mock())).thenReturn(sayValid) - } else { - whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), mock())).thenReturn(sayValid) + val mediaId = (if (useTempPrefix) TEMPORARY_ID_PREFIX else "") + i.toString() + mediaIds.add(mediaId) + if (useTempPrefix) { + whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), TempId(mediaId))).thenReturn(sayValid) + } else if (useRemoteId) { + whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), RemoteId(mediaId.toLong()))).thenReturn(sayValid) + } else { + whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), LocalId(mediaId.toInt()))).thenReturn(sayValid) + } } return mediaIds From d5d5731bdac77f525d8a05c6ddc5c36cb40b6164 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:37:18 -0300 Subject: [PATCH 170/230] removed unused imports --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt index 48856e2b7567..c62f61452dd7 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt @@ -1,7 +1,6 @@ package org.wordpress.android.ui.stories.usecase import android.content.Context -import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever import org.assertj.core.api.Assertions import org.junit.Before From 5e55e168f61e44be0c5ae1baaec9ce21c164cdae Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:40:49 -0300 Subject: [PATCH 171/230] removed commented line --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 4f321cea2ccf..0e7424acd391 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -538,7 +538,6 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), frame, it ) - // frame.id = storyMediaFileData.id storyMediaFileDataList.add(storyMediaFileData) } else { val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) From 4d1eaa16d6fe7b754da2380a761d21bba613e722 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:42:27 -0300 Subject: [PATCH 172/230] giving parameter explicit name --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index 0e7424acd391..b75ecef1f1b8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -542,10 +542,10 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } else { val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) - mediaFile?.let { + mediaFile?.let { mediafile -> val storyMediaFileData = saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( - mediaFile = it, + mediaFile = mediafile, temporaryId = assignedTempId ) frame.id = storyMediaFileData.id From 6bb0e31cf37b9e48aa900087e4494e1c95cbec41 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:47:06 -0300 Subject: [PATCH 173/230] removed unnecessary val declaration --- .../org/wordpress/android/ui/stories/StoryComposerActivity.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt index b75ecef1f1b8..9ccdb705ae61 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt @@ -560,8 +560,7 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), } private fun buildStoryMediaFileDataForTemporarySlide(frame: StoryFrameItem, tempId: String): StoryMediaFileData { - val storyMediaFileData = - saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryIdNoMediaFile( + return saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryIdNoMediaFile( temporaryId = tempId, url = if (frame.source is FileBackgroundSource) { (frame.source as FileBackgroundSource).file.toString() @@ -570,7 +569,6 @@ class StoryComposerActivity : ComposeLoopFrameActivity(), }, isVideo = (frame.frameItemType is VIDEO) ) - return storyMediaFileData } override fun onSubmitButtonClicked(publishPost: PublishPost) { From 9b80af491ae999fd001ca4df65e615af7be255d0 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:53:12 -0300 Subject: [PATCH 174/230] renamed _Phase1 and _Phase2 postfixed method names and added comments to illustrate how id assignment for media works in two phases --- .../wordpress/android/ui/posts/EditPostActivity.java | 2 +- .../ui/stories/SaveStoryGutenbergBlockUseCase.kt | 2 +- .../ui/stories/media/StoryMediaSaveUploadBridge.kt | 2 +- .../wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 10 ++++++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index cc26947a5ace..982d90addf21 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -1685,7 +1685,7 @@ private void onUploadSuccess(MediaModel media) { // Also: we don't need to worry about checking if this mediaModel corresponds to a media upload // within a story block in this post: we will only replace items for which a local-keyed frame has // been created before, which can only happen when using the Story Creator. - mStoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide_Phase2( + mStoriesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( media.getId(), media.getMediaId(), mSite.getId() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 968d3063edc1..8dae05f35665 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -133,7 +133,7 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( // look for the slide saved with the local id key (mediaFile.id), and re-convert to // mediaId. - storiesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide_Phase2( + storiesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( mediaFile.id, mediaFile.mediaId.toLong(), postModel.localSiteId.toLong() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 11dc97eda47c..5b6c2fc6de9a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -148,7 +148,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( // if prefs has this Slide with the temporary key, replace it // if not, let's now save the new slide with the local key - storiesPrefs.replaceTempMediaIdKeyedSlideWithLocalMediaIdKeyedSlide_Phase1( + storiesPrefs.replaceTempMediaIdKeyedSlideWithLocalMediaIdKeyedSlide( TempId(oldTemporaryId), LocalId(it.id), it.localSiteId.toLong() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 87ceead46a61..a485fa2b088b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -206,7 +206,10 @@ class StoriesPrefs @Inject constructor( } } - fun replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide_Phase2( + // Phase 2: this method is likely used after a first phase in which a local media which only has a temporary id has + // then be replaced by a local id. At this point, we now have a remote Id and we can replace the local + // media id with the remote media id. + fun replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( localIdKey: Int, remoteIdKey: Long, localSiteId: Long @@ -230,7 +233,10 @@ class StoriesPrefs @Inject constructor( } } - fun replaceTempMediaIdKeyedSlideWithLocalMediaIdKeyedSlide_Phase1( + // Phase 1: this method is likely used at the beginning when a local media which only has a temporary id needs now + // to be assigned with a localMediaId. At a later point when the media is uploaded to the server, it will be + // assigned a remote Id which will replace this localId. + fun replaceTempMediaIdKeyedSlideWithLocalMediaIdKeyedSlide( tempId: TempId, localId: LocalId, localSiteId: Long From d7986d0f8c6152424c4f700bbd28af4252116649 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 21 Oct 2020 15:55:06 -0300 Subject: [PATCH 175/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt Co-authored-by: Joel Dean --- .../android/ui/stories/media/StoryMediaSaveUploadBridge.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt index 5b6c2fc6de9a..51917328a1a5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt @@ -235,7 +235,7 @@ class StoryMediaSaveUploadBridge @Inject constructor( // yet. if (isStorySavingComplete(event) && !event.isRetry) { // only remove it if it was successful - we want to keep it and show a snackbar once when the user - // comes back to the app if it wasn't, see MySiteFrament for details. + // comes back to the app if it wasn't, see MySiteFragment for details. eventBusWrapper.removeStickyEvent(event) editPostRepository.loadPostByLocalPostId(it.getInt(StoryComposerActivity.KEY_POST_LOCAL_ID)) // media upload tracking already in addLocalMediaToPostUseCase.addNewMediaToEditorAsync From 695fed6d0b3d819d531ef6f8e3efba6d1795ee15 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:56:05 -0300 Subject: [PATCH 176/230] added const prefix --- .../wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index a485fa2b088b..adb44991713a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -18,11 +18,11 @@ class StoriesPrefs @Inject constructor( private val context: Context ) { companion object { - private val KEY_STORIES_SLIDE_INCREMENTAL_ID = "incremental_id" - private val KEY_PREFIX_STORIES_SLIDE_ID = "story_slide_id-" - private val KEY_PREFIX_TEMP_MEDIA_ID = "t-" - private val KEY_PREFIX_LOCAL_MEDIA_ID = "l-" - private val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" + private const val KEY_STORIES_SLIDE_INCREMENTAL_ID = "incremental_id" + private const val KEY_PREFIX_STORIES_SLIDE_ID = "story_slide_id-" + private const val KEY_PREFIX_TEMP_MEDIA_ID = "t-" + private const val KEY_PREFIX_LOCAL_MEDIA_ID = "l-" + private const val KEY_PREFIX_REMOTE_MEDIA_ID = "r-" } private fun buildSlideKey(siteId: Long, mediaId: RemoteId): String { From 2bcc13e08d4c59e9aa6ff0ec8be21260c7376901 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 15:56:55 -0300 Subject: [PATCH 177/230] added private scope modifier to private fun --- .../java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index adb44991713a..f885dde01f71 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -51,7 +51,7 @@ class StoriesPrefs @Inject constructor( return currentIncrementalId } - fun getIncrementalTempId(): Long { + private fun getIncrementalTempId(): Long { return PreferenceManager.getDefaultSharedPreferences(context).getLong( KEY_STORIES_SLIDE_INCREMENTAL_ID, 0 From c5e23b3216ceee2c06495effbfc91961d2a098a3 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 21 Oct 2020 16:02:58 -0300 Subject: [PATCH 178/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt Co-authored-by: Joel Dean --- .../java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index f885dde01f71..98defa4ee552 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -63,7 +63,7 @@ class StoriesPrefs @Inject constructor( return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } - fun checkSlideIdExists(siteId: Long, tempId: TempId): Boolean { + private fun checkSlideIdExists(siteId: Long, tempId: TempId): Boolean { val slideIdKey = buildSlideKey(siteId, tempId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } From dc19f996aea577808347af9277ffb26b06547065 Mon Sep 17 00:00:00 2001 From: mzorz Date: Wed, 21 Oct 2020 16:03:08 -0300 Subject: [PATCH 179/230] Update WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt Co-authored-by: Joel Dean --- .../java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 98defa4ee552..7a1ed8842c09 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -68,7 +68,7 @@ class StoriesPrefs @Inject constructor( return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } - fun checkSlideIdExists(siteId: Long, localId: LocalId): Boolean { + private fun checkSlideIdExists(siteId: Long, localId: LocalId): Boolean { val slideIdKey = buildSlideKey(siteId, localId) return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } From 798da18e171d81b78ed5de155b073aea5172d09a Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 16:08:47 -0300 Subject: [PATCH 180/230] renamed parameters, simplified logic removing local val and modified scope for checkSlideOriginalBackgroundMediaExists set of methods --- .../android/ui/stories/prefs/StoriesPrefs.kt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt index 7a1ed8842c09..a96b2cdb8f48 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt @@ -73,19 +73,16 @@ class StoriesPrefs @Inject constructor( return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) } - fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: RemoteId): Boolean { - val storyFrameItem: StoryFrameItem? = getSlideWithRemoteId(siteId, mediaId) - return checkSlideOriginalBackgroundMediaExists(storyFrameItem) + private fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: RemoteId): Boolean { + return checkSlideOriginalBackgroundMediaExists(getSlideWithRemoteId(siteId, mediaId)) } - fun checkSlideOriginalBackgroundMediaExists(siteId: Long, tempId: TempId): Boolean { - val storyFrameItem: StoryFrameItem? = getSlideWithTempId(siteId, tempId) - return checkSlideOriginalBackgroundMediaExists(storyFrameItem) + private fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: TempId): Boolean { + return checkSlideOriginalBackgroundMediaExists(getSlideWithTempId(siteId, mediaId)) } - fun checkSlideOriginalBackgroundMediaExists(siteId: Long, localId: LocalId): Boolean { - val storyFrameItem: StoryFrameItem? = getSlideWithLocalId(siteId, localId) - return checkSlideOriginalBackgroundMediaExists(storyFrameItem) + private fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: LocalId): Boolean { + return checkSlideOriginalBackgroundMediaExists(getSlideWithLocalId(siteId, mediaId)) } private fun checkSlideOriginalBackgroundMediaExists(storyFrameItem: StoryFrameItem?): Boolean { From 1f36898147e2699febe0c063ba3ba82a323ea74c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 16:53:25 -0300 Subject: [PATCH 181/230] updated gutenberg-mobile commit hash --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index ed36dfc682ec..ba4df52f4482 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit ed36dfc682ec2203fe8f7b9995ca0dc94b90065d +Subproject commit ba4df52f44826817d29f3a3c255963b062b2fde8 From fa5e87a9cd43a807034832220240a1dda5ea4750 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 17:04:31 -0300 Subject: [PATCH 182/230] removed unused var and import --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt index c62f61452dd7..3220ace9b852 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt @@ -12,7 +12,6 @@ import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.MediaStore -import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX import org.wordpress.android.ui.stories.StoryRepositoryWrapper import org.wordpress.android.ui.stories.prefs.StoriesPrefs @@ -25,7 +24,6 @@ class LoadStoryFromStoriesPrefsUseCaseTest { @Mock lateinit var mediaStore: MediaStore @Mock lateinit var storiesPrefs: StoriesPrefs @Mock lateinit var context: Context - @Mock lateinit var postRepository: EditPostRepository private lateinit var siteModel: SiteModel @Before From 74c62e73ebe7566a324b7d4abf02dbe42b222d07 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 18:43:32 -0300 Subject: [PATCH 183/230] renamed site name in test example --- .../ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt index 3220ace9b852..58cac5ff0b71 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt @@ -143,7 +143,7 @@ class LoadStoryFromStoriesPrefsUseCaseTest { for (i in 1..10) { val oneMediaFile = HashMap() oneMediaFile.put("mime", "image/jpeg") - oneMediaFile.put("link", "https://testmzorz3.files.wordpress.com/2020/10/wp-0000000.jpg") + oneMediaFile.put("link", "https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg") oneMediaFile.put("type", "image") oneMediaFile.put("id", i.toString()) mediaFiles.add(oneMediaFile) From f53da473f74f03466620dac4ff3e7c63d9bdf165 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 18:43:56 -0300 Subject: [PATCH 184/230] added unit tests for SaveStoryGutenbergBlockUseCase class --- .../SaveStoryGutenbergBlockUseCaseTest.kt | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt new file mode 100644 index 000000000000..82ece3fc522c --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -0,0 +1,128 @@ +package org.wordpress.android.ui.stories + +import android.content.Context +import com.nhaarman.mockitokotlin2.mock +import kotlinx.coroutines.InternalCoroutinesApi +import org.assertj.core.api.Assertions +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnitRunner +import org.wordpress.android.BaseUnitTest +import org.wordpress.android.TEST_DISPATCHER +import org.wordpress.android.fluxc.model.PostModel +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.PostStore +import org.wordpress.android.ui.posts.EditPostRepository +import org.wordpress.android.ui.stories.prefs.StoriesPrefs +import org.wordpress.android.util.helpers.MediaFile + +@RunWith(MockitoJUnitRunner::class) +class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { + private lateinit var saveStoryGutenbergBlockUseCase: SaveStoryGutenbergBlockUseCase + private lateinit var editPostRepository: EditPostRepository + private lateinit var siteModel: SiteModel + @Mock lateinit var storiesPrefs: StoriesPrefs + @Mock lateinit var context: Context + @Mock lateinit var postStore: PostStore + + @InternalCoroutinesApi + @Before + fun setUp() { + saveStoryGutenbergBlockUseCase = SaveStoryGutenbergBlockUseCase(storiesPrefs) + siteModel = SiteModel() + editPostRepository = EditPostRepository( + mock(), + postStore, + mock(), + TEST_DISPATCHER, + TEST_DISPATCHER + ) + } + + @Test + fun `post with empty Story block is set given an empty mediaFiles array`() { + // Given + val mediaFiles: ArrayList = setupFluxCMediaFiles(emptyList = true) + editPostRepository.set { PostModel() } + + // When + saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost( + editPostRepository, + mediaFiles + ) + + // Then + Assertions.assertThat(editPostRepository.content).isEqualTo(blockWithEmptyMediaFiles) + } + + @Test + fun `post with non-empty Story block is set given a non-empty mediaFiles array`() { + // Given + val mediaFiles: ArrayList = setupFluxCMediaFiles(emptyList = false) + editPostRepository.set { PostModel() } + + // When + saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockInPost( + editPostRepository, + mediaFiles + ) + + // Then + Assertions.assertThat(editPostRepository.content).isEqualTo(blockWithNonEmptyMediaFiles) + } + + private fun setupFluxCMediaFiles( + emptyList: Boolean + ): ArrayList { + when (emptyList) { + true -> return ArrayList() + false -> { + val mediaFiles = ArrayList() + for (i in 1..10) { + val oneMediaFile = MediaFile() + oneMediaFile.id = i + oneMediaFile.mediaId = (i + 1000).toString() + oneMediaFile.mimeType = "image/jpeg" + oneMediaFile.fileURL = "https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg" + mediaFiles.add(oneMediaFile) + } + return mediaFiles + } + } + } + + companion object { + private const val blockWithEmptyMediaFiles = "\n" + + "
\n" + + "" + private const val blockWithNonEmptyMediaFiles = "\n" + + "
\n" + + "" + } +} From 83ee3c286580c23bb4b6c5181a5b607f7fdd8c7c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 19:10:48 -0300 Subject: [PATCH 185/230] added more tests --- .../SaveStoryGutenbergBlockUseCaseTest.kt | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt index 82ece3fc522c..b18fc5ca373f 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -15,6 +15,8 @@ import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.PostStore import org.wordpress.android.ui.posts.EditPostRepository +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX +import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.StoryMediaFileData import org.wordpress.android.ui.stories.prefs.StoriesPrefs import org.wordpress.android.util.helpers.MediaFile @@ -73,6 +75,55 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { Assertions.assertThat(editPostRepository.content).isEqualTo(blockWithNonEmptyMediaFiles) } + @Test + fun `builds non-empty story block string from non-empty mediaFiles array`() { + // Given + val mediaFileDataList: ArrayList = setupMediaFileDataList(emptyList = false) + + // When + val result = saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockStringFromStoryMediaFileData( + mediaFileDataList + ) + + // Then + Assertions.assertThat(result).isEqualTo(blockWithNonEmptyMediaFiles) + } + + @Test + fun `builds empty story block string from empty mediaFiles array`() { + // Given + val mediaFileDataList: ArrayList = setupMediaFileDataList(emptyList = true) + + // When + val result = saveStoryGutenbergBlockUseCase.buildJetpackStoryBlockStringFromStoryMediaFileData( + mediaFileDataList + ) + + // Then + Assertions.assertThat(result).isEqualTo(blockWithEmptyMediaFiles) + } + + @Test + fun `obtain a mediaFileData from a MediaFile with a temporary id`() { + // Given + val mediaFile = getOneMediaFile(1) + + // When + val mediaFileData = saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( + mediaFile, + TEMPORARY_ID_PREFIX + 1 + ) + + // Then + Assertions.assertThat(mediaFileData.alt).isEqualTo("") + Assertions.assertThat(mediaFileData.id).isEqualTo(TEMPORARY_ID_PREFIX + 1) + Assertions.assertThat(mediaFileData.link).isEqualTo("https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg") + Assertions.assertThat(mediaFileData.type).isEqualTo("image") + Assertions.assertThat(mediaFileData.mime).isEqualTo(mediaFile.mimeType) + Assertions.assertThat(mediaFileData.caption).isEqualTo("") + Assertions.assertThat(mediaFileData.url).isEqualTo(mediaFile.fileURL) + } + private fun setupFluxCMediaFiles( emptyList: Boolean ): ArrayList { @@ -93,6 +144,39 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { } } + private fun getOneMediaFile(id: Int): MediaFile { + val oneMediaFile = MediaFile() + oneMediaFile.id = id + oneMediaFile.mediaId = (id + 1000).toString() + oneMediaFile.mimeType = "image/jpeg" + oneMediaFile.fileURL = "https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg" + return oneMediaFile + } + + private fun setupMediaFileDataList( + emptyList: Boolean + ): ArrayList { + when (emptyList) { + true -> return ArrayList() + false -> { + val mediaFiles = ArrayList() + for (i in 1..10) { + val oneMediaFile = StoryMediaFileData( + id = i.toString(), + mime = "image/jpeg", + link = "https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg", + url = "https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg", + alt = "", + type = "image", + caption = "" + ) + mediaFiles.add(oneMediaFile) + } + return mediaFiles + } + } + } + companion object { private const val blockWithEmptyMediaFiles = "\n" + "
\n" + From c59fa66ead937a600231ff94dc83238794bc31dd Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Wed, 21 Oct 2020 19:22:04 -0300 Subject: [PATCH 186/230] added test case --- .../SaveStoryGutenbergBlockUseCaseTest.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt index b18fc5ca373f..49b80127192f 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -124,6 +124,23 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { Assertions.assertThat(mediaFileData.url).isEqualTo(mediaFile.fileURL) } + @Test + fun `local media id is found and gets replaced with remote media id`() { + // Given + val mediaFile = getOneMediaFile(1) + val onePost = PostModel() + onePost.setContent(blockWithNonEmptyMediaFiles) + + // When + saveStoryGutenbergBlockUseCase.replaceLocalMediaIdsWithRemoteMediaIdsInPost( + onePost, + mediaFile + ) + + // Then + Assertions.assertThat(onePost.content).isEqualTo(blockWithNonEmptyMediaFilesWithOneRemoteId) + } + private fun setupFluxCMediaFiles( emptyList: Boolean ): ArrayList { @@ -208,5 +225,33 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { "ption\":\"\",\"url\":\"https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg\"}]} -->\n" + "
\n" + "" + private const val blockWithNonEmptyMediaFilesWithOneRemoteId = "\n" + + "
\n" + + "" + } } From 773495a9b684db9254bd1a0c6199219d31746437 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 22 Oct 2020 08:59:01 -0300 Subject: [PATCH 187/230] added failing test for review --- .../SaveStoryGutenbergBlockUseCaseTest.kt | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt index 49b80127192f..d336ac9bd54f 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -1,12 +1,21 @@ package org.wordpress.android.ui.stories import android.content.Context +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.eq import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.times +import com.nhaarman.mockitokotlin2.verify +import com.nhaarman.mockitokotlin2.whenever +import com.wordpress.stories.compose.frame.StorySaveEvents.SaveResultReason.SaveSuccess +import com.wordpress.stories.compose.story.StoryFrameItem +import com.wordpress.stories.compose.story.StoryFrameItemType.IMAGE import kotlinx.coroutines.InternalCoroutinesApi import org.assertj.core.api.Assertions import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner import org.wordpress.android.BaseUnitTest @@ -141,6 +150,32 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { Assertions.assertThat(onePost.content).isEqualTo(blockWithNonEmptyMediaFilesWithOneRemoteId) } + @Test + fun `slides are saved locally`() { + // Given + val frames = ArrayList() + frames.add(getOneStoryFrameItem("1")) + frames.add(getOneStoryFrameItem("2")) + frames.add(getOneStoryFrameItem("3")) +// frames.add(mock()) +// frames.add(mock()) +// frames.add(mock()) + whenever(storiesPrefs.saveSlideWithTempId(ArgumentMatchers.anyLong(), any(), any())) + .then { } + + // When + saveStoryGutenbergBlockUseCase.saveNewLocalFilesToStoriesPrefsTempSlides( + siteModel, + 0, + frames + ) + + // Then + // eq(expectedPostId.value) + verify(storiesPrefs, times(3)).saveSlideWithTempId(siteModel.siteId, mock(), mock()) + // Assertions.assertThat(onePost.content).isEqualTo(blockWithNonEmptyMediaFilesWithOneRemoteId) + } + private fun setupFluxCMediaFiles( emptyList: Boolean ): ArrayList { @@ -170,6 +205,16 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { return oneMediaFile } + private fun getOneStoryFrameItem(id: String): StoryFrameItem { + return StoryFrameItem( + source = mock(), + frameItemType = IMAGE, + saveResultReason = SaveSuccess, + composedFrameFile = mock(), + id = id + ) + } + private fun setupMediaFileDataList( emptyList: Boolean ): ArrayList { @@ -252,6 +297,5 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { "ption\":\"\",\"url\":\"https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg\"}]} -->\n" + "
\n" + "" - } } From 77cb234d2990e88ab88287a6f88d12a197521641 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 22 Oct 2020 17:20:16 -0300 Subject: [PATCH 188/230] fixed test, added needed test dependency --- WordPress/build.gradle | 1 + .../stories/SaveStoryGutenbergBlockUseCaseTest.kt | 14 ++------------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 1b74daef3347..73548a0781af 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -184,6 +184,7 @@ androidExtensions { dependencies { implementation project(path:':libs:stories-android:stories') + testImplementation project(path:':photoeditor') implementation project(path:':libs:image-editor::ImageEditor') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt index d336ac9bd54f..f81599aa368a 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -151,17 +151,12 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { } @Test - fun `slides are saved locally`() { + fun `slides are saved locally to storiedPrefs`() { // Given val frames = ArrayList() frames.add(getOneStoryFrameItem("1")) frames.add(getOneStoryFrameItem("2")) frames.add(getOneStoryFrameItem("3")) -// frames.add(mock()) -// frames.add(mock()) -// frames.add(mock()) - whenever(storiesPrefs.saveSlideWithTempId(ArgumentMatchers.anyLong(), any(), any())) - .then { } // When saveStoryGutenbergBlockUseCase.saveNewLocalFilesToStoriesPrefsTempSlides( @@ -171,9 +166,7 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { ) // Then - // eq(expectedPostId.value) - verify(storiesPrefs, times(3)).saveSlideWithTempId(siteModel.siteId, mock(), mock()) - // Assertions.assertThat(onePost.content).isEqualTo(blockWithNonEmptyMediaFilesWithOneRemoteId) + verify(storiesPrefs, times(3)).saveSlideWithTempId(any(), any(), any()) } private fun setupFluxCMediaFiles( @@ -208,9 +201,6 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { private fun getOneStoryFrameItem(id: String): StoryFrameItem { return StoryFrameItem( source = mock(), - frameItemType = IMAGE, - saveResultReason = SaveSuccess, - composedFrameFile = mock(), id = id ) } From d9ed477b947dfbfe142f91751c8f4ee489012c31 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 22 Oct 2020 17:34:47 -0300 Subject: [PATCH 189/230] fixed lint warnings --- .../SaveStoryGutenbergBlockUseCaseTest.kt | 11 ++++------ .../LoadStoryFromStoriesPrefsUseCaseTest.kt | 21 +++++++++++++++---- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt index f81599aa368a..bf7dd8f8a157 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -2,20 +2,15 @@ package org.wordpress.android.ui.stories import android.content.Context import com.nhaarman.mockitokotlin2.any -import com.nhaarman.mockitokotlin2.eq import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.times import com.nhaarman.mockitokotlin2.verify -import com.nhaarman.mockitokotlin2.whenever -import com.wordpress.stories.compose.frame.StorySaveEvents.SaveResultReason.SaveSuccess import com.wordpress.stories.compose.story.StoryFrameItem -import com.wordpress.stories.compose.story.StoryFrameItemType.IMAGE import kotlinx.coroutines.InternalCoroutinesApi import org.assertj.core.api.Assertions import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner import org.wordpress.android.BaseUnitTest @@ -30,7 +25,7 @@ import org.wordpress.android.ui.stories.prefs.StoriesPrefs import org.wordpress.android.util.helpers.MediaFile @RunWith(MockitoJUnitRunner::class) -class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { +class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { private lateinit var saveStoryGutenbergBlockUseCase: SaveStoryGutenbergBlockUseCase private lateinit var editPostRepository: EditPostRepository private lateinit var siteModel: SiteModel @@ -126,7 +121,9 @@ class SaveStoryGutenbergBlockUseCaseTest: BaseUnitTest() { // Then Assertions.assertThat(mediaFileData.alt).isEqualTo("") Assertions.assertThat(mediaFileData.id).isEqualTo(TEMPORARY_ID_PREFIX + 1) - Assertions.assertThat(mediaFileData.link).isEqualTo("https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg") + Assertions.assertThat(mediaFileData.link).isEqualTo( + "https://testsite.files.wordpress.com/2020/10/wp-0000000.jpg" + ) Assertions.assertThat(mediaFileData.type).isEqualTo("image") Assertions.assertThat(mediaFileData.mime).isEqualTo(mediaFile.mimeType) Assertions.assertThat(mediaFileData.caption).isEqualTo("") diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt index 58cac5ff0b71..374850180a4f 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCaseTest.kt @@ -42,7 +42,9 @@ class LoadStoryFromStoriesPrefsUseCaseTest { val mediaFiles: ArrayList> = setupMediaFiles(emptyList = true) // When - val mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles as ArrayList) + val mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles( + mediaFiles as ArrayList + ) // Then Assertions.assertThat(mediaIds).isEmpty() @@ -54,7 +56,9 @@ class LoadStoryFromStoriesPrefsUseCaseTest { val mediaFiles: ArrayList> = setupMediaFiles(emptyList = false) // When - val mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles as ArrayList) + val mediaIds = loadStoryFromStoriesPrefsUseCase.getMediaIdsFromStoryBlockBridgeMediaFiles( + mediaFiles as ArrayList + ) // Then Assertions.assertThat(mediaIds).isNotEmpty @@ -166,9 +170,18 @@ class LoadStoryFromStoriesPrefsUseCaseTest { if (useTempPrefix) { whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), TempId(mediaId))).thenReturn(sayValid) } else if (useRemoteId) { - whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), RemoteId(mediaId.toLong()))).thenReturn(sayValid) + whenever( + storiesPrefs.isValidSlide( + siteModel.id.toLong(), + RemoteId(mediaId.toLong()) + ) + ).thenReturn(sayValid) } else { - whenever(storiesPrefs.isValidSlide(siteModel.id.toLong(), LocalId(mediaId.toInt()))).thenReturn(sayValid) + whenever(storiesPrefs.isValidSlide( + siteModel.id.toLong(), + LocalId(mediaId.toInt()) + ) + ).thenReturn(sayValid) } } From f8fb3048a9f259a179cba76a820223e614f9a8f5 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 22 Oct 2020 18:01:38 -0300 Subject: [PATCH 190/230] removed unused resources --- WordPress/src/main/res/values/strings.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 6f47ea49191f..7708031650ca 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2910,7 +2910,6 @@ Flip camera Flash Stickers - More Text Sound Flip @@ -2921,8 +2920,6 @@ Saved to photos SHARE Share to - Done - Next Close Saved Retry @@ -2932,7 +2929,6 @@ errored Change text alignment Change text color - Delete slide Delete story slide? This slide will be removed from your story. This slide has not been saved yet. If you delete this slide, you will lose any edits you have made. From 875c8aaa277de2962e8bdddd3fb05675d407632c Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 22 Oct 2020 18:12:06 -0300 Subject: [PATCH 191/230] removed unused resource in stories library --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 621c36488b99..952e70540fa2 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 621c36488b999208617b9e72b3291f4a83c02d0a +Subproject commit 952e70540fa295a7f0458804d5fd33350c5d5417 From 6b27610f4efae24eaa5e350cae772954921870cb Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 22 Oct 2020 18:29:21 -0300 Subject: [PATCH 192/230] mocking siteModel --- .../android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt index bf7dd8f8a157..f5d4c160ce94 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -16,7 +16,6 @@ import org.mockito.junit.MockitoJUnitRunner import org.wordpress.android.BaseUnitTest import org.wordpress.android.TEST_DISPATCHER import org.wordpress.android.fluxc.model.PostModel -import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.PostStore import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.stories.SaveStoryGutenbergBlockUseCase.Companion.TEMPORARY_ID_PREFIX @@ -28,7 +27,6 @@ import org.wordpress.android.util.helpers.MediaFile class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { private lateinit var saveStoryGutenbergBlockUseCase: SaveStoryGutenbergBlockUseCase private lateinit var editPostRepository: EditPostRepository - private lateinit var siteModel: SiteModel @Mock lateinit var storiesPrefs: StoriesPrefs @Mock lateinit var context: Context @Mock lateinit var postStore: PostStore @@ -37,7 +35,6 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { @Before fun setUp() { saveStoryGutenbergBlockUseCase = SaveStoryGutenbergBlockUseCase(storiesPrefs) - siteModel = SiteModel() editPostRepository = EditPostRepository( mock(), postStore, @@ -157,7 +154,7 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { // When saveStoryGutenbergBlockUseCase.saveNewLocalFilesToStoriesPrefsTempSlides( - siteModel, + mock(), 0, frames ) From 0575171172ca47dbbb42e376bc3d469e7529a930 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 22 Oct 2020 18:31:05 -0300 Subject: [PATCH 193/230] applying naming convention for constants :) --- .../SaveStoryGutenbergBlockUseCaseTest.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt index f5d4c160ce94..4b499a9e1f35 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCaseTest.kt @@ -57,7 +57,7 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { ) // Then - Assertions.assertThat(editPostRepository.content).isEqualTo(blockWithEmptyMediaFiles) + Assertions.assertThat(editPostRepository.content).isEqualTo(BLOCK_WITH_EMPTY_MEDIA_FILES) } @Test @@ -73,7 +73,7 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { ) // Then - Assertions.assertThat(editPostRepository.content).isEqualTo(blockWithNonEmptyMediaFiles) + Assertions.assertThat(editPostRepository.content).isEqualTo(BLOCK_WITH_NON_EMPTY_MEDIA_FILES) } @Test @@ -87,7 +87,7 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { ) // Then - Assertions.assertThat(result).isEqualTo(blockWithNonEmptyMediaFiles) + Assertions.assertThat(result).isEqualTo(BLOCK_WITH_NON_EMPTY_MEDIA_FILES) } @Test @@ -101,7 +101,7 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { ) // Then - Assertions.assertThat(result).isEqualTo(blockWithEmptyMediaFiles) + Assertions.assertThat(result).isEqualTo(BLOCK_WITH_EMPTY_MEDIA_FILES) } @Test @@ -132,7 +132,7 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { // Given val mediaFile = getOneMediaFile(1) val onePost = PostModel() - onePost.setContent(blockWithNonEmptyMediaFiles) + onePost.setContent(BLOCK_WITH_NON_EMPTY_MEDIA_FILES) // When saveStoryGutenbergBlockUseCase.replaceLocalMediaIdsWithRemoteMediaIdsInPost( @@ -141,7 +141,7 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { ) // Then - Assertions.assertThat(onePost.content).isEqualTo(blockWithNonEmptyMediaFilesWithOneRemoteId) + Assertions.assertThat(onePost.content).isEqualTo(BLOCK_WITH_NON_EMPTY_MEDIA_FILES_WITH_ONE_REMOTE_ID) } @Test @@ -224,10 +224,10 @@ class SaveStoryGutenbergBlockUseCaseTest : BaseUnitTest() { } companion object { - private const val blockWithEmptyMediaFiles = "\n" + + private const val BLOCK_WITH_EMPTY_MEDIA_FILES = "\n" + "
\n" + "" - private const val blockWithNonEmptyMediaFiles = "\n" + "
\n" + "" - private const val blockWithNonEmptyMediaFilesWithOneRemoteId = "