diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 01454109f51d..39e50203e72b 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -2,6 +2,9 @@ 24.4 ----- +* [***] [Jetpack-only] Improved Notifications experience with richer UI elements and interactions [https://github.com/wordpress-mobile/WordPress-Android/pull/20072] +* [**] [Jetpack-only] Block editor: Introduce VideoPress v5 support, to fix issues using video block with dotcom and Jetpack sites [https://github.com/wordpress-mobile/gutenberg-mobile/pull/6634] +* [**] [internal] Removed the Stories from the codebase [https://github.com/wordpress-mobile/WordPress-Android/pull/20016] [***] [Jetpack-only] Stats: Introducing Traffic tab, delivering improved graphs, and combining Days/Weeks/Months/Years tabs into one, behind a feature flag. [https://github.com/wordpress-mobile/WordPress-Android/pull/19942] [***] [Jetpack-only] Improved Notifications experience with richer UI elements and interactions [https://github.com/wordpress-mobile/WordPress-Android/pull/20072] * [**] [Jetpack-only] Block editor: Introduce VideoPress v5 support, to fix issues using video block with dotcom and Jetpack sites [https://github.com/wordpress-mobile/gutenberg-mobile/pull/6634] diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 1a7c673ac696..6329c75f8e74 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -38,7 +38,6 @@ repositories { includeGroup "org.wordpress.gutenberg-mobile" includeGroupByRegex "org.wordpress.react-native-libraries.*" includeGroup "com.automattic" - includeGroup "com.automattic.stories" includeGroup "com.automattic.tracks" } } @@ -375,11 +374,6 @@ dependencies { exclude group: 'org.wordpress', module: 'utils' } implementation "$gradle.ext.aboutAutomatticBinaryPath:$automatticAboutVersion" - implementation ("$gradle.ext.storiesAndroidPath:$automatticStoriesVersion") { - exclude group: 'androidx.navigation', module: 'navigation-fragment-ktx' - exclude group: 'androidx.navigation', module: 'navigation-ui-ktx' - } - implementation "$gradle.ext.storiesAndroidMp4ComposePath:$automatticStoriesVersion" implementation("$gradle.ext.tracksBinaryPath") { version { @@ -470,8 +464,6 @@ dependencies { implementation "com.google.dagger:hilt-android:$gradle.ext.daggerVersion" kapt "com.google.dagger:hilt-compiler:$gradle.ext.daggerVersion" - testImplementation "$gradle.ext.storiesAndroidPhotoEditorPath:$automatticStoriesVersion" - testImplementation("androidx.arch.core:core-testing:$androidxArchCoreVersion", { exclude group: 'com.android.support', module: 'support-compat' exclude group: 'com.android.support', module: 'support-annotations' diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index 28599bd22e30..bcb7a2b06e5a 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -250,14 +250,6 @@ android:value=".ui.posts.PostsListActivity" /> - - - - NotificationType.STORY_SAVE_SUCCESS - STORY_SAVE_ERROR -> NotificationType.STORY_SAVE_ERROR - STORY_FRAME_SAVE_SUCCESS -> NotificationType.STORY_FRAME_SAVE_SUCCESS - STORY_FRAME_SAVE_ERROR -> NotificationType.STORY_FRAME_SAVE_ERROR - } - } - - override fun trackShownNotification(storyNotificationType: StoryNotificationType) { - systemNotificationsTracker.trackShownNotification(translateNotificationTypes(storyNotificationType)) - } - - override fun trackTappedNotification(storyNotificationType: StoryNotificationType) { - systemNotificationsTracker.trackTappedNotification(translateNotificationTypes(storyNotificationType)) - } - - override fun trackDismissedNotification(storyNotificationType: StoryNotificationType) { - systemNotificationsTracker.trackDismissedNotification(translateNotificationTypes(storyNotificationType)) - } - } - private fun updateNotificationSettings() { if (!jetpackFeatureRemovalPhaseHelper.shouldShowNotifications()) { NotificationsUtils.cancelAllNotifications(application) diff --git a/WordPress/src/main/java/org/wordpress/android/WordPress.kt b/WordPress/src/main/java/org/wordpress/android/WordPress.kt index 6918015aae05..928455ca34c0 100644 --- a/WordPress/src/main/java/org/wordpress/android/WordPress.kt +++ b/WordPress/src/main/java/org/wordpress/android/WordPress.kt @@ -4,7 +4,6 @@ import android.app.Application import android.content.Context import com.android.volley.RequestQueue import dagger.hilt.EntryPoints -import org.wordpress.android.AppInitializer.StoryNotificationTrackerProvider import org.wordpress.android.fluxc.tools.FluxCImageLoader import org.wordpress.android.modules.AppComponent @@ -13,9 +12,6 @@ import org.wordpress.android.modules.AppComponent * application. Containing public static variables and methods to be accessed by other classes. */ abstract class WordPress : Application() { - val storyNotificationTrackerProvider: StoryNotificationTrackerProvider - get() = initializer().storyNotificationTrackerProvider - abstract fun initializer(): AppInitializer fun component(): AppComponent = EntryPoints.get(this, AppComponent::class.java) diff --git a/WordPress/src/main/java/org/wordpress/android/localcontentmigration/UserFlagsProviderHelper.kt b/WordPress/src/main/java/org/wordpress/android/localcontentmigration/UserFlagsProviderHelper.kt index 839474dc2f14..5d8a75087824 100644 --- a/WordPress/src/main/java/org/wordpress/android/localcontentmigration/UserFlagsProviderHelper.kt +++ b/WordPress/src/main/java/org/wordpress/android/localcontentmigration/UserFlagsProviderHelper.kt @@ -68,7 +68,6 @@ class UserFlagsProviderHelper @Inject constructor( UndeletablePrefKey.BOOKMARKS_SAVED_LOCALLY_DIALOG_SHOWN.name, UndeletablePrefKey.SWIPE_TO_NAVIGATE_NOTIFICATIONS.name, UndeletablePrefKey.SWIPE_TO_NAVIGATE_READER.name, - UndeletablePrefKey.SHOULD_SHOW_STORIES_INTRO.name, UndeletablePrefKey.SHOULD_SHOW_STORAGE_WARNING.name, UndeletablePrefKey.LAST_USED_USER_ID.name, contextProvider.getContext().getString(R.string.pref_key_app_theme), 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 f1f8aadc6697..2384e438dd45 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java @@ -173,8 +173,6 @@ import org.wordpress.android.ui.stats.refresh.lists.widget.weeks.WeekViewsWidgetListProvider; import org.wordpress.android.ui.stats.refresh.lists.widget.weeks.WeekWidgetBlockListProviderFactory; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; -import org.wordpress.android.ui.stories.StoryComposerActivity; -import org.wordpress.android.ui.stories.intro.StoriesIntroDialogFragment; import org.wordpress.android.ui.suggestion.SuggestionActivity; import org.wordpress.android.ui.suggestion.adapters.SuggestionAdapter; import org.wordpress.android.ui.themes.ThemeBrowserFragment; @@ -458,11 +456,6 @@ public interface AppComponent { void inject(FeatureAnnouncementDialogFragment object); void inject(FeatureAnnouncementListAdapter object); - - void inject(StoryComposerActivity object); - - void inject(StoriesIntroDialogFragment object); - void inject(ReaderDiscoverFragment object); void inject(ReaderSearchActivity object); diff --git a/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java b/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java index 1f8bb88b6ac3..cbd2ff792a84 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java @@ -72,8 +72,6 @@ import org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsSiteSelectionViewModel; import org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsWidgetConfigureViewModel; import org.wordpress.android.ui.stats.refresh.lists.widget.minified.StatsMinifiedWidgetConfigureViewModel; -import org.wordpress.android.ui.stories.StoryComposerViewModel; -import org.wordpress.android.ui.stories.intro.StoriesIntroViewModel; import org.wordpress.android.ui.suggestion.SuggestionViewModel; import org.wordpress.android.ui.whatsnew.FeatureAnnouncementViewModel; import org.wordpress.android.viewmodel.ViewModelFactory; @@ -359,16 +357,6 @@ abstract class ViewModelModule { @ViewModelKey(PrepublishingPublishSettingsViewModel.class) abstract ViewModel prepublishingPublishSettingsViewModel(PrepublishingPublishSettingsViewModel viewModel); - @Binds - @IntoMap - @ViewModelKey(StoryComposerViewModel.class) - abstract ViewModel storyComposerViewModel(StoryComposerViewModel viewModel); - - @Binds - @IntoMap - @ViewModelKey(StoriesIntroViewModel.class) - abstract ViewModel storiesIntroViewModel(StoriesIntroViewModel viewModel); - @Binds @IntoMap @ViewModelKey(PhotoPickerViewModel.class) diff --git a/WordPress/src/main/java/org/wordpress/android/push/NotificationType.kt b/WordPress/src/main/java/org/wordpress/android/push/NotificationType.kt index 63f9f2155910..f4c6b971bbcc 100644 --- a/WordPress/src/main/java/org/wordpress/android/push/NotificationType.kt +++ b/WordPress/src/main/java/org/wordpress/android/push/NotificationType.kt @@ -22,10 +22,6 @@ enum class NotificationType { MEDIA_UPLOAD_SUCCESS, MEDIA_UPLOAD_ERROR, POST_PUBLISHED, - STORY_SAVE_SUCCESS, - STORY_SAVE_ERROR, - STORY_FRAME_SAVE_SUCCESS, - STORY_FRAME_SAVE_ERROR, BLOGGING_REMINDERS, CREATE_SITE, WEEKLY_ROUNDUP, 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 860e6e865a35..58120cf6a227 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -16,16 +16,12 @@ import androidx.core.app.TaskStackBuilder; import androidx.fragment.app.Fragment; -import com.wordpress.stories.compose.frame.FrameSaveNotifier; -import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult; - import org.wordpress.android.BuildConfig; import org.wordpress.android.R; import org.wordpress.android.WordPress; 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; @@ -85,8 +81,6 @@ import org.wordpress.android.ui.pages.PageParentActivity; import org.wordpress.android.ui.pages.PagesActivity; import org.wordpress.android.ui.people.PeopleManagementActivity; -import org.wordpress.android.ui.photopicker.MediaPickerConstants; -import org.wordpress.android.ui.photopicker.PhotoPickerActivity; import org.wordpress.android.ui.plans.PlansActivity; import org.wordpress.android.ui.plugins.PluginBrowserActivity; import org.wordpress.android.ui.plugins.PluginDetailActivity; @@ -124,7 +118,6 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementActivity; import org.wordpress.android.ui.stats.refresh.utils.StatsLaunchedFrom; import org.wordpress.android.ui.stockmedia.StockMediaPickerActivity; -import org.wordpress.android.ui.stories.StoryComposerActivity; import org.wordpress.android.ui.suggestion.SuggestionActivity; import org.wordpress.android.ui.suggestion.SuggestionType; import org.wordpress.android.ui.themes.ThemeBrowserActivity; @@ -145,14 +138,11 @@ import java.util.List; import java.util.Map; -import static com.wordpress.stories.util.BundleUtilsKt.KEY_STORY_INDEX; -import static com.wordpress.stories.util.BundleUtilsKt.KEY_STORY_SAVE_RESULT; 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; 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.JETPACK_LOGIN_ONLY; import static org.wordpress.android.login.LoginMode.WPCOM_LOGIN_ONLY; @@ -168,9 +158,6 @@ import static org.wordpress.android.ui.media.MediaBrowserActivity.ARG_BROWSER_TYPE; import static org.wordpress.android.ui.pages.PagesActivityKt.EXTRA_PAGE_LIST_TYPE_KEY; 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_ARE_BUTTONS_VISIBLE_KEY; import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_ID_KEY; import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_IS_DASHBOARD_CARD_ENTRY_KEY; @@ -253,33 +240,6 @@ private static Intent createSitePickerIntent(Context context, SiteModel site, Si return intent; } - /** - * Use {@link org.wordpress.android.ui.photopicker.MediaPickerLauncher::showPhotoPickerForResult} instead - */ - @Deprecated - public static void showPhotoPickerForResult(Activity activity, - @NonNull MediaBrowserType browserType, - @Nullable SiteModel site, - @Nullable Integer localPostId) { - Intent intent = createShowPhotoPickerIntent(activity, browserType, site, localPostId); - activity.startActivityForResult(intent, RequestCodes.PHOTO_PICKER); - } - - private static Intent createShowPhotoPickerIntent(Context context, - @NonNull MediaBrowserType browserType, - @Nullable SiteModel site, - @Nullable Integer localPostId) { - Intent intent = new Intent(context, PhotoPickerActivity.class); - intent.putExtra(ARG_BROWSER_TYPE, browserType); - if (site != null) { - intent.putExtra(WordPress.SITE, site); - } - if (localPostId != null) { - intent.putExtra(MediaPickerConstants.LOCAL_POST_ID, localPostId.intValue()); - } - return intent; - } - /** * Use {@link org.wordpress.android.ui.photopicker.MediaPickerLauncher::showStockMediaPickerForResult} instead */ @@ -1028,102 +988,6 @@ public static void addNewPostForResult( activity.startActivityForResult(intent, RequestCodes.EDIT_POST); } - public static void addNewStoryForResult( - Activity activity, - SiteModel site, - PagePostCreationSourcesDetail source - ) { - if (site == null) { - return; - } - - Intent intent = new Intent(activity, StoryComposerActivity.class); - intent.putExtra(WordPress.SITE, site); - intent.putExtra(AnalyticsUtils.EXTRA_CREATION_SOURCE_DETAIL, source); - intent.putExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, true); - activity.startActivityForResult(intent, RequestCodes.CREATE_STORY); - } - - public static void addNewStoryWithMediaIdsForResult( - Activity activity, - SiteModel site, - PagePostCreationSourcesDetail source, - long[] mediaIds - ) { - if (site == null) { - return; - } - - Intent intent = new Intent(activity, StoryComposerActivity.class); - intent.putExtra(WordPress.SITE, site); - intent.putExtra(MediaBrowserActivity.RESULT_IDS, mediaIds); - intent.putExtra(AnalyticsUtils.EXTRA_CREATION_SOURCE_DETAIL, source); - activity.startActivityForResult(intent, RequestCodes.CREATE_STORY); - } - - public static void addNewStoryWithMediaUrisForResult( - Activity activity, - SiteModel site, - PagePostCreationSourcesDetail source, - String[] mediaUris - ) { - if (site == null) { - return; - } - - Intent intent = new Intent(activity, StoryComposerActivity.class); - intent.putExtra(WordPress.SITE, site); - intent.putExtra(MediaPickerConstants.EXTRA_MEDIA_URIS, mediaUris); - intent.putExtra(AnalyticsUtils.EXTRA_CREATION_SOURCE_DETAIL, source); - activity.startActivityForResult(intent, RequestCodes.CREATE_STORY); - } - - - public static void editStoryForResult( - Activity activity, - SiteModel site, - LocalId localPostId, - int storyIndex, - boolean allStorySlidesAreEditable, - boolean launchedFromGutenberg, - String storyBlockId - ) { - if (site == null) { - return; - } - - 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); - intent.putExtra(ARG_STORY_BLOCK_ID, storyBlockId); - activity.startActivityForResult(intent, RequestCodes.EDIT_STORY); - } - - public static void editEmptyStoryForResult( - Activity activity, - SiteModel site, - LocalId localPostId, - int storyIndex, - String storyBlockId - ) { - if (site == null) { - return; - } - - AnalyticsTracker.track(Stat.STORY_BLOCK_ADD_MEDIA_TAPPED); - 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_MEDIA_PICKER_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); - } - public static void editPostOrPageForResult(Activity activity, SiteModel site, PostModel post) { editPostOrPageForResult(new Intent(activity, EditPostActivity.class), activity, site, post.getId(), false); } @@ -1382,22 +1246,6 @@ public static void viewNotificationsSettings(Activity activity) { activity.startActivity(intent); } - public static void viewStories(Activity activity, SiteModel site, StorySaveResult event) { - Intent intent = new Intent(activity, StoryComposerActivity.class); - intent.putExtra(KEY_STORY_SAVE_RESULT, event); - intent.putExtra(WordPress.SITE, site); - - // we need to have a way to cancel the related error notification when the user comes - // from tapping on MANAGE on the snackbar (otherwise they'll be able to discard the - // errored story but the error notification will remain existing in the system dashboard) - intent.setAction(String.valueOf(FrameSaveNotifier.getNotificationIdForError( - StoryComposerActivity.BASE_FRAME_MEDIA_ERROR_NOTIFICATION_ID, - event.getStoryIndex() - ))); - - activity.startActivity(intent); - } - public static void viewJetpackSecuritySettingsForResult(Activity activity, SiteModel site) { AnalyticsTracker.track(Stat.SITE_SETTINGS_JETPACK_SECURITY_SETTINGS_VIEWED); Intent intent = new Intent(activity, JetpackSecuritySettingsActivity.class); 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 e46b5cd8a090..41de68d08d9c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java @@ -71,10 +71,6 @@ public class RequestCodes { // Other public static final int SELECTED_USER_MENTION = 7000; - // Story creator - public static final int CREATE_STORY = 8000; - public static final int EDIT_STORY = 8001; - // Reader Interests public static final int READER_INTERESTS = 9001; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/compose/components/buttons/ImageButton.kt b/WordPress/src/main/java/org/wordpress/android/ui/compose/components/buttons/ImageButton.kt index b48e648319ac..8ec3f0f00af8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/compose/components/buttons/ImageButton.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/compose/components/buttons/ImageButton.kt @@ -39,10 +39,10 @@ fun PreviewDrawButton() { Color.Gray, shape = RoundedCornerShape(6.dp) ), - drawableLeft = Drawable(R.drawable.ic_story_icon_24dp), - drawableRight = Drawable(R.drawable.ic_story_icon_24dp), - drawableTop = Drawable(R.drawable.ic_story_icon_24dp), - drawableBottom = Drawable(R.drawable.ic_story_icon_24dp), + drawableLeft = Drawable(R.drawable.ic_pages_white_24dp), + drawableRight = Drawable(R.drawable.ic_pages_white_24dp), + drawableTop = Drawable(R.drawable.ic_pages_white_24dp), + drawableBottom = Drawable(R.drawable.ic_pages_white_24dp), button = Button(text = UiString.UiStringText("Button Text")), onClick = {} ) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpackoverlay/JetpackFeatureRemovalPhaseHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpackoverlay/JetpackFeatureRemovalPhaseHelper.kt index 49ec25df3d7f..77f8d6512f34 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpackoverlay/JetpackFeatureRemovalPhaseHelper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpackoverlay/JetpackFeatureRemovalPhaseHelper.kt @@ -86,9 +86,6 @@ class JetpackFeatureRemovalPhaseHelper @Inject constructor( } } - @Suppress("FunctionOnlyReturningConstant") - fun shouldShowStoryPost(): Boolean = false - fun shouldShowJetpackPoweredEditorFeatures(): Boolean { val currentPhase = getCurrentPhase() ?: return true return when (currentPhase) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/MainActionListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/main/MainActionListItem.kt index cfbac905fc29..126808598e6c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/main/MainActionListItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/main/MainActionListItem.kt @@ -13,7 +13,6 @@ sealed class MainActionListItem { CREATE_NEW_PAGE, CREATE_NEW_PAGE_FROM_PAGES_CARD, CREATE_NEW_POST, - CREATE_NEW_STORY, ANSWER_BLOGGING_PROMPT } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java index 6c2e4bf43a3d..25afd022eb4a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java @@ -139,7 +139,6 @@ import org.wordpress.android.ui.sitecreation.misc.SiteCreationSource; import org.wordpress.android.ui.stats.StatsTimeframe; import org.wordpress.android.ui.stats.refresh.utils.StatsLaunchedFrom; -import org.wordpress.android.ui.stories.intro.StoriesIntroDialogFragment; import org.wordpress.android.ui.uploads.UploadActionUseCase; import org.wordpress.android.ui.uploads.UploadUtils; import org.wordpress.android.ui.uploads.UploadUtilsWrapper; @@ -187,7 +186,6 @@ import static androidx.lifecycle.Lifecycle.State.STARTED; import static org.wordpress.android.WordPress.SITE; -import static org.wordpress.android.editor.gutenberg.GutenbergEditorFragment.ARG_STORY_BLOCK_ID; import static org.wordpress.android.fluxc.store.SiteStore.CompleteQuickStartVariant.NEXT_STEPS; import static org.wordpress.android.login.LoginAnalyticsListener.CreatedAccountSource.EMAIL; import static org.wordpress.android.push.NotificationsProcessingService.ARG_NOTIFICATION_TYPE; @@ -721,9 +719,6 @@ private void initViewModel() { case CREATE_NEW_PAGE_FROM_PAGES_CARD: triggerCreatePageFlow(createAction); break; - case CREATE_NEW_STORY: - handleNewStoryAction(); - break; case ANSWER_BLOGGING_PROMPT: case NO_ACTION: break; // noop - we handle ANSWER_BLOGGING_PROMPT through live data event @@ -1302,25 +1297,6 @@ private void handleNewPostAction(PagePostCreationSourcesDetail source, ActivityLauncher.addNewPostForResult(this, getSelectedSite(), false, source, promptId, entryPoint); } - private void handleNewStoryAction() { - if (!mSiteStore.hasSite()) { - // No site yet - Move to My Sites fragment that shows the create new site screen - mBottomNav.setCurrentSelectedPage(PageType.MY_SITE); - return; - } - - SiteModel selectedSite = getSelectedSite(); - if (selectedSite != null) { - // TODO: evaluate to include the QuickStart logic like in the handleNewPostAction - if (AppPrefs.shouldShowStoriesIntro()) { - StoriesIntroDialogFragment.newInstance(selectedSite) - .show(getSupportFragmentManager(), StoriesIntroDialogFragment.TAG); - } else { - mMediaPickerLauncher.showStoriesPhotoPickerForResultAndTrack(this, selectedSite); - } - } - } - private void trackLastVisiblePage(@NonNull final PageType pageType) { switch (pageType) { case MY_SITE: @@ -1412,17 +1388,6 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { ); } break; - case RequestCodes.CREATE_STORY: - SiteModel selectedSite = getSelectedSite(); - if (selectedSite != null) { - boolean isNewStory = data == null || data.getStringExtra(ARG_STORY_BLOCK_ID) == null; - mBloggingRemindersViewModel.onPublishingPost( - selectedSite.getId(), - isNewStory - ); - mReviewViewModel.onPublishingPost(isNewStory); - } - break; case RequestCodes.CREATE_SITE: QuickStartUtils.cancelQuickStartReminder(this); AppPrefs.setQuickStartNoticeRequired(false); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserType.java b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserType.java index f30ab8f2ca27..c4995c671eb8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserType.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserType.java @@ -14,8 +14,7 @@ public enum MediaBrowserType { GUTENBERG_SINGLE_MEDIA_PICKER, // select a single image or video to insert into a post GUTENBERG_MEDIA_PICKER, // select multiple images or videos to insert into a post GUTENBERG_SINGLE_FILE_PICKER, // select a file to insert into a post - GUTENBERG_SINGLE_AUDIO_FILE_PICKER, // select an audio file to insert into a post - WP_STORIES_MEDIA_PICKER; // select multiple images or videos to insert as Story frames in a Story + GUTENBERG_SINGLE_AUDIO_FILE_PICKER; // select an audio file to insert into a post public boolean isPicker() { return this != BROWSER; @@ -42,7 +41,6 @@ public boolean isImagePicker() { || this == GUTENBERG_SINGLE_IMAGE_PICKER || this == GUTENBERG_SINGLE_MEDIA_PICKER || this == GUTENBERG_MEDIA_PICKER - || this == WP_STORIES_MEDIA_PICKER || this == GUTENBERG_SINGLE_FILE_PICKER; } @@ -53,7 +51,6 @@ public boolean isVideoPicker() { || this == GUTENBERG_SINGLE_VIDEO_PICKER || this == GUTENBERG_SINGLE_MEDIA_PICKER || this == GUTENBERG_MEDIA_PICKER - || this == WP_STORIES_MEDIA_PICKER || this == GUTENBERG_SINGLE_FILE_PICKER; } @@ -76,10 +73,6 @@ public boolean isGutenbergPicker() { || this == GUTENBERG_SINGLE_AUDIO_FILE_PICKER; } - public boolean isWPStoriesPicker() { - return this == WP_STORIES_MEDIA_PICKER; - } - public boolean isSingleFilePicker() { return this == GUTENBERG_SINGLE_FILE_PICKER; } @@ -96,8 +89,7 @@ public boolean canMultiselect() { return this == EDITOR_PICKER || this == AZTEC_EDITOR_PICKER || this == GUTENBERG_IMAGE_PICKER - || this == GUTENBERG_VIDEO_PICKER - || this == WP_STORIES_MEDIA_PICKER; + || this == GUTENBERG_VIDEO_PICKER; } public boolean canFilter() { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerActivity.kt index 46d141ac72c7..4f989fa1160a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerActivity.kt @@ -27,7 +27,6 @@ import org.wordpress.android.ui.mediapicker.MediaPickerActivity.MediaPickerMedia import org.wordpress.android.ui.mediapicker.MediaPickerFragment.Companion.newInstance import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.OpenCameraForPhotos -import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.OpenCameraForWPStories import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.OpenSystemPicker import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.SwitchMediaPicker import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerListener @@ -37,7 +36,6 @@ import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.GIF_LIBR import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.STOCK_LIBRARY import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.WP_LIBRARY import org.wordpress.android.ui.photopicker.MediaPickerConstants -import org.wordpress.android.ui.photopicker.MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED import org.wordpress.android.ui.photopicker.MediaPickerConstants.EXTRA_MEDIA_ID import org.wordpress.android.ui.photopicker.MediaPickerConstants.EXTRA_MEDIA_QUEUED_URIS import org.wordpress.android.ui.photopicker.MediaPickerConstants.EXTRA_MEDIA_SOURCE @@ -251,13 +249,6 @@ class MediaPickerActivity : LocaleAwareActivity(), MediaPickerListener { WPMediaUtils.launchChooserWithContext(this, openSystemPicker, uiHelpers, MEDIA_LIBRARY) } - private fun launchWPStoriesCamera() { - val intent = Intent() - .putExtra(EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, true) - setResult(Activity.RESULT_OK, intent) - finish() - } - private fun Intent.putUris( mediaUris: List ) { @@ -321,7 +312,6 @@ class MediaPickerActivity : LocaleAwareActivity(), MediaPickerListener { is OpenSystemPicker -> { launchChooserWithContext(action, uiHelpers) } - is OpenCameraForWPStories -> launchWPStoriesCamera() is SwitchMediaPicker -> { startActivityForResult(buildIntent(this, action.mediaPickerSetup, site, localPostId), PHOTO_PICKER) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerFragment.kt index f5a87762415c..f976bc882eca 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerFragment.kt @@ -45,7 +45,6 @@ import org.wordpress.android.ui.mediapicker.MediaNavigationEvent.PreviewUrl import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIconType.ANDROID_CHOOSE_FROM_DEVICE import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIconType.CAPTURE_PHOTO import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIconType.SWITCH_SOURCE -import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIconType.WP_STORIES_CAPTURE import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource import org.wordpress.android.ui.mediapicker.MediaPickerViewModel.ActionModeUiModel import org.wordpress.android.ui.mediapicker.MediaPickerViewModel.BrowseMenuUiModel.BrowseAction.DEVICE @@ -86,7 +85,6 @@ class MediaPickerFragment : Fragment(), MenuProvider { enum class MediaPickerIconType { ANDROID_CHOOSE_FROM_DEVICE, SWITCH_SOURCE, - WP_STORIES_CAPTURE, CAPTURE_PHOTO; companion object { @@ -117,7 +115,6 @@ class MediaPickerFragment : Fragment(), MenuProvider { val allowMultipleSelection: Boolean ) : MediaPickerAction() - data class OpenCameraForWPStories(val allowMultipleSelection: Boolean) : MediaPickerAction() object OpenCameraForPhotos : MediaPickerAction() data class SwitchMediaPicker(val mediaPickerSetup: MediaPickerSetup) : MediaPickerAction() } @@ -128,8 +125,6 @@ class MediaPickerFragment : Fragment(), MenuProvider { ) : MediaPickerIcon(ANDROID_CHOOSE_FROM_DEVICE) data class SwitchSource(val dataSource: DataSource) : MediaPickerIcon(SWITCH_SOURCE) - - object WpStoriesCapture : MediaPickerIcon(WP_STORIES_CAPTURE) object CapturePhoto : MediaPickerIcon(CAPTURE_PHOTO) fun toBundle(bundle: Bundle) { @@ -145,7 +140,6 @@ class MediaPickerFragment : Fragment(), MenuProvider { bundle.putInt(KEY_LAST_TAPPED_ICON_DATA_SOURCE, this.dataSource.ordinal) } is CapturePhoto -> Unit // Do nothing - is WpStoriesCapture -> Unit // Do nothing } } @@ -164,7 +158,6 @@ class MediaPickerFragment : Fragment(), MenuProvider { }.toSet() ChooseFromAndroidDevice(allowedTypes) } - WP_STORIES_CAPTURE -> WpStoriesCapture CAPTURE_PHOTO -> CapturePhoto SWITCH_SOURCE -> { val ordinal = bundle.getInt(KEY_LAST_TAPPED_ICON_DATA_SOURCE, -1) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerSetup.kt b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerSetup.kt index 5cb2ebf4c0ca..3752aee242d0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerSetup.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerSetup.kt @@ -24,7 +24,7 @@ data class MediaPickerSetup( } enum class CameraSetup { - STORIES, ENABLED, HIDDEN + ENABLED, HIDDEN } fun toBundle(bundle: Bundle) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerTracker.kt index 874a7687211c..79e2186af4e5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerTracker.kt @@ -10,7 +10,6 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_D import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_GIF_LIBRARY import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_STOCK_LIBRARY import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_WP_MEDIA -import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_WP_STORIES_CAPTURE import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_PREVIEW_OPENED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_RECENT_MEDIA_SELECTED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_SEARCH_COLLAPSED @@ -80,10 +79,6 @@ class MediaPickerTracker fun trackIconClick(icon: MediaPickerIcon, mediaPickerSetup: MediaPickerSetup) { when (icon) { - is MediaPickerIcon.WpStoriesCapture -> analyticsTrackerWrapper.track( - MEDIA_PICKER_OPEN_WP_STORIES_CAPTURE, - mediaPickerSetup.toProperties() - ) is MediaPickerIcon.ChooseFromAndroidDevice -> analyticsTrackerWrapper.track( MEDIA_PICKER_OPEN_DEVICE_LIBRARY, mediaPickerSetup.toProperties() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerViewModel.kt index 78fd876ae461..829bd0f78252 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mediapicker/MediaPickerViewModel.kt @@ -25,17 +25,14 @@ import org.wordpress.android.ui.mediapicker.MediaNavigationEvent.PreviewUrl import org.wordpress.android.ui.mediapicker.MediaPickerFragment.ChooserContext import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.OpenCameraForPhotos -import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.OpenCameraForWPStories import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.OpenSystemPicker import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerAction.SwitchMediaPicker import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIcon import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIcon.CapturePhoto import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIcon.ChooseFromAndroidDevice import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIcon.SwitchSource -import org.wordpress.android.ui.mediapicker.MediaPickerFragment.MediaPickerIcon.WpStoriesCapture import org.wordpress.android.ui.mediapicker.MediaPickerSetup.CameraSetup.ENABLED import org.wordpress.android.ui.mediapicker.MediaPickerSetup.CameraSetup.HIDDEN -import org.wordpress.android.ui.mediapicker.MediaPickerSetup.CameraSetup.STORIES import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.DEVICE import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.GIF_LIBRARY import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.STOCK_LIBRARY @@ -496,7 +493,7 @@ class MediaPickerViewModel @Inject constructor( private fun clickIcon(icon: MediaPickerIcon) { mediaPickerTracker.trackIconClick(icon, mediaPickerSetup) - if (icon is WpStoriesCapture || icon is CapturePhoto) { + if (icon is CapturePhoto) { if (!permissionsHandler.hasPermissionsToTakePhoto()) { _onCameraPermissionsRequested.value = Event(Unit) lastTappedIcon = icon @@ -510,7 +507,6 @@ class MediaPickerViewModel @Inject constructor( private fun clickOnCamera() { when (mediaPickerSetup.cameraSetup) { - STORIES -> clickIcon(WpStoriesCapture) ENABLED -> clickIcon(CapturePhoto) HIDDEN -> { // Do nothing @@ -547,7 +543,6 @@ class MediaPickerViewModel @Inject constructor( } OpenSystemPicker(context, types.toList(), canMultiselect) } - is WpStoriesCapture -> OpenCameraForWPStories(canMultiselect) is CapturePhoto -> OpenCameraForPhotos is SwitchSource -> { SwitchMediaPicker( diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt index ed8f46b9fed8..e616663ca474 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt @@ -256,9 +256,6 @@ class MySiteFragment : Fragment(R.layout.my_site_fragment), } } RequestCodes.STORIES_PHOTO_PICKER, - RequestCodes.PHOTO_PICKER -> if (resultCode == Activity.RESULT_OK) { - viewModel.handleStoriesPhotoPickerResult(data) - } UCrop.REQUEST_CROP -> { if (resultCode == UCrop.RESULT_ERROR) { AppLog.e( @@ -618,21 +615,6 @@ class MySiteFragment : Fragment(R.layout.my_site_fragment), ActivityLauncher.viewConnectJetpackForStats(activity, action.site) is SiteNavigationAction.StartWPComLoginForJetpackStats -> ActivityLauncher.loginForJetpackStats(this@MySiteFragment) - is SiteNavigationAction.OpenStories -> ActivityLauncher.viewStories(activity, action.site, action.event) - is SiteNavigationAction.AddNewStory -> - ActivityLauncher.addNewStoryForResult(activity, action.site, action.source) - is SiteNavigationAction.AddNewStoryWithMediaIds -> ActivityLauncher.addNewStoryWithMediaIdsForResult( - activity, - action.site, - action.source, - action.mediaIds.toLongArray() - ) - is SiteNavigationAction.AddNewStoryWithMediaUris -> ActivityLauncher.addNewStoryWithMediaUrisForResult( - activity, - action.site, - action.source, - action.mediaUris.toTypedArray() - ) is SiteNavigationAction.OpenDomains -> ActivityLauncher.viewDomainsDashboardActivity( activity, action.site diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index 2c51f7655bc6..bc6134e7308a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -2,7 +2,6 @@ package org.wordpress.android.ui.mysite -import android.content.Intent import android.net.Uri import androidx.annotation.StringRes import androidx.lifecycle.LiveData @@ -20,8 +19,8 @@ import org.wordpress.android.R import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.fluxc.model.dashboard.CardModel.DynamicCardsModel import org.wordpress.android.fluxc.model.dashboard.CardModel.ActivityCardModel +import org.wordpress.android.fluxc.model.dashboard.CardModel.DynamicCardsModel import org.wordpress.android.fluxc.model.dashboard.CardModel.PagesCardModel import org.wordpress.android.fluxc.model.dashboard.CardModel.PostsCardModel import org.wordpress.android.fluxc.model.dashboard.CardModel.TodaysStatsCardModel @@ -35,7 +34,6 @@ import org.wordpress.android.localcontentmigration.ContentMigrationAnalyticsTrac import org.wordpress.android.models.JetpackPoweredScreen import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.modules.UI_THREAD -import org.wordpress.android.ui.PagePostCreationSourcesDetail.STORY_FROM_MY_SITE import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalOverlayUtil import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalOverlayUtil.JetpackFeatureCollectionOverlaySource.FEATURE_CARD import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalPhaseHelper @@ -125,7 +123,6 @@ class MySiteViewModel @Inject constructor( private val accountStore: AccountStore, private val selectedSiteRepository: SelectedSiteRepository, private val siteIconUploadHandler: SiteIconUploadHandler, - private val siteStoriesHandler: SiteStoriesHandler, private val displayUtilsWrapper: DisplayUtilsWrapper, private val quickStartRepository: QuickStartRepository, private val quickStartCardBuilder: QuickStartCardBuilder, @@ -206,7 +203,6 @@ class MySiteViewModel @Inject constructor( } val onSnackbarMessage = merge( _onSnackbarMessage, - siteStoriesHandler.onSnackbar, quickStartRepository.onSnackbar, siteItemsViewModelSlice.onSnackbarMessage, bloggingPromptCardViewModelSlice.onSnackbarMessage, @@ -221,7 +217,6 @@ class MySiteViewModel @Inject constructor( val onNavigation = merge( _onNavigation, - siteStoriesHandler.onNavigation, blazeCardViewModelSlice.onNavigation, pagesCardViewModelSlice.onNavigation, todaysStatsViewModelSlice.onNavigation, @@ -781,19 +776,12 @@ class MySiteViewModel @Inject constructor( override fun onCleared() { siteIconUploadHandler.clear() - siteStoriesHandler.clear() quickStartRepository.clear() mySiteSourceManager.clear() dispatcher.unregister(this) super.onCleared() } - fun handleStoriesPhotoPickerResult(data: Intent) { - selectedSiteRepository.getSelectedSite()?.let { - siteStoriesHandler.handleStoriesResult(it, data, STORY_FROM_MY_SITE) - } - } - fun onSitePicked() { selectedSiteRepository.getSelectedSite()?.let { val siteLocalId = it.id.toLong() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt index 95fe3002cd46..422a82a81a4c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt @@ -1,11 +1,9 @@ package org.wordpress.android.ui.mysite import androidx.annotation.StringRes -import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.QuickStartStore.QuickStartTaskType import org.wordpress.android.models.ReaderTag -import org.wordpress.android.ui.PagePostCreationSourcesDetail import org.wordpress.android.ui.blaze.BlazeFlowSource import org.wordpress.android.ui.blaze.blazecampaigns.campaigndetail.CampaignDetailPageSource import org.wordpress.android.ui.blaze.blazecampaigns.campaignlisting.CampaignListingPageSource @@ -45,24 +43,6 @@ sealed class SiteNavigationAction { object StartWPComLoginForJetpackStats : SiteNavigationAction() data class OpenStats(val site: SiteModel) : SiteNavigationAction() data class ConnectJetpackForStats(val site: SiteModel) : SiteNavigationAction() - data class OpenStories(val site: SiteModel, val event: StorySaveResult) : SiteNavigationAction() - data class AddNewStory( - val site: SiteModel, - val source: PagePostCreationSourcesDetail - ) : SiteNavigationAction() - - data class AddNewStoryWithMediaIds( - val site: SiteModel, - val source: PagePostCreationSourcesDetail, - val mediaIds: List - ) : SiteNavigationAction() - - data class AddNewStoryWithMediaUris( - val site: SiteModel, - val source: PagePostCreationSourcesDetail, - val mediaUris: List - ) : SiteNavigationAction() - data class OpenDomainRegistration(val site: SiteModel) : SiteNavigationAction() data class OpenPaidDomainSearch(val site: SiteModel) : SiteNavigationAction() data class OpenFreeDomainSearch(val site: SiteModel) : SiteNavigationAction() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt deleted file mode 100644 index 6c064d580b08..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt +++ /dev/null @@ -1,101 +0,0 @@ -package org.wordpress.android.ui.mysite - -import android.content.Intent -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import com.wordpress.stories.compose.frame.FrameSaveNotifier -import com.wordpress.stories.compose.frame.StorySaveEvents -import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveProcessStart -import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult -import com.wordpress.stories.compose.story.StoryRepository -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode -import org.wordpress.android.R -import org.wordpress.android.analytics.AnalyticsTracker.Stat.STORY_SAVE_ERROR_SNACKBAR_MANAGE_TAPPED -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.ui.PagePostCreationSourcesDetail -import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenStories -import org.wordpress.android.ui.pages.SnackbarMessageHolder -import org.wordpress.android.ui.stories.StoriesMediaPickerResultHandler -import org.wordpress.android.ui.stories.StoriesTrackerHelper -import org.wordpress.android.ui.utils.UiString.UiStringRes -import org.wordpress.android.ui.utils.UiString.UiStringText -import org.wordpress.android.util.EventBusWrapper -import org.wordpress.android.util.merge -import org.wordpress.android.viewmodel.ContextProvider -import org.wordpress.android.viewmodel.Event -import org.wordpress.android.viewmodel.ResourceProvider -import javax.inject.Inject - -class SiteStoriesHandler -@Inject constructor( - private val eventBusWrapper: EventBusWrapper, - private val resourceProvider: ResourceProvider, - private val storiesTrackerHelper: StoriesTrackerHelper, - private val contextProvider: ContextProvider, - private val selectedSiteRepository: SelectedSiteRepository, - private val storiesMediaPickerResultHandler: StoriesMediaPickerResultHandler -) { - private val _onSnackbar = MutableLiveData>() - val onSnackbar = _onSnackbar as LiveData> - private val _onNavigation = MutableLiveData>() - val onNavigation = merge(_onNavigation, storiesMediaPickerResultHandler.onNavigation) - - init { - eventBusWrapper.register(this) - } - - fun clear() { - eventBusWrapper.unregister(this) - } - - @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - fun onEventMainThread(event: StorySaveResult) { - eventBusWrapper.removeStickyEvent(event) - if (!event.isSuccess()) { - // note: no tracking added here as we'll perform tracking in StoryMediaSaveUploadBridge - val errorText = String.format( - resourceProvider.getString(R.string.story_saving_snackbar_finished_with_error), - StoryRepository.getStoryAtIndex(event.storyIndex).title - ) - val snackbarMessage = FrameSaveNotifier.buildSnackbarErrorMessage( - contextProvider.getContext(), - StorySaveEvents.allErrorsInResult(event.frameSaveResult).size, - errorText - ) - - _onSnackbar.postValue( - Event( - SnackbarMessageHolder( - UiStringText(snackbarMessage), - UiStringRes(R.string.story_saving_failed_quick_action_manage), - buttonAction = { - val selectedSite = selectedSiteRepository.getSelectedSite() - ?: return@SnackbarMessageHolder - _onNavigation.postValue(Event(OpenStories(selectedSite, event))) - storiesTrackerHelper.trackStorySaveResultEvent( - event, - STORY_SAVE_ERROR_SNACKBAR_MANAGE_TAPPED - ) - }, - onDismissAction = { } - ) - ) - ) - } - } - - @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - fun onStorySaveStart(event: StorySaveProcessStart) { - eventBusWrapper.removeStickyEvent(event) - val snackbarMessage = String.format( - resourceProvider.getString(R.string.story_saving_snackbar_started), - StoryRepository.getStoryAtIndex(event.storyIndex).title - ) - _onSnackbar.postValue(Event(SnackbarMessageHolder(UiStringText(snackbarMessage)))) - } - - fun handleStoriesResult(siteModel: SiteModel, data: Intent, source: PagePostCreationSourcesDetail) { - storiesMediaPickerResultHandler.handleMediaPickerResultForStories(data, siteModel, source) - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/menu/MenuActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/menu/MenuActivity.kt index 77ac0aa5d5c1..d35ba2380565 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/menu/MenuActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/menu/MenuActivity.kt @@ -425,7 +425,7 @@ fun MySiteListItemPreviewWithSecondaryImage() { MenuItemState.MenuListItem( primaryIcon = R.drawable.ic_posts_white_24dp, primaryText = UiString.UiStringText("Plans"), - secondaryIcon = R.drawable.ic_story_icon_24dp, + secondaryIcon = R.drawable.ic_pages_white_24dp, secondaryText = null, showFocusPoint = false, onClick = ListItemInteraction.create { onClick() }, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/SystemNotificationsTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/notifications/SystemNotificationsTracker.kt index 5ec418cecfe7..c0d8fa1e5177 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/SystemNotificationsTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/SystemNotificationsTracker.kt @@ -23,10 +23,6 @@ import org.wordpress.android.push.NotificationType.POST_PUBLISHED import org.wordpress.android.push.NotificationType.POST_UPLOAD_ERROR import org.wordpress.android.push.NotificationType.POST_UPLOAD_SUCCESS import org.wordpress.android.push.NotificationType.QUICK_START_REMINDER -import org.wordpress.android.push.NotificationType.STORY_FRAME_SAVE_ERROR -import org.wordpress.android.push.NotificationType.STORY_FRAME_SAVE_SUCCESS -import org.wordpress.android.push.NotificationType.STORY_SAVE_ERROR -import org.wordpress.android.push.NotificationType.STORY_SAVE_SUCCESS import org.wordpress.android.push.NotificationType.TEST_NOTE import org.wordpress.android.push.NotificationType.UNKNOWN_NOTE import org.wordpress.android.push.NotificationType.WEEKLY_ROUNDUP @@ -104,10 +100,6 @@ class SystemNotificationsTracker MEDIA_UPLOAD_SUCCESS -> MEDIA_UPLOAD_SUCCESS_TYPE_VALUE MEDIA_UPLOAD_ERROR -> MEDIA_UPLOAD_ERROR_TYPE_VALUE POST_PUBLISHED -> POST_PUBLISHED_TYPE_VALUE - STORY_SAVE_SUCCESS -> STORY_SAVE_SUCCESS_TYPE_VALUE - STORY_SAVE_ERROR -> STORY_SAVE_ERROR_TYPE_VALUE - STORY_FRAME_SAVE_SUCCESS -> STORY_FRAME_SAVE_SUCCESS_TYPE_VALUE - STORY_FRAME_SAVE_ERROR -> STORY_FRAME_SAVE_ERROR_TYPE_VALUE PENDING_DRAFTS -> PENDING_DRAFT_TYPE_VALUE ZENDESK -> ZENDESK_MESSAGE_TYPE_VALUE BLOGGING_REMINDERS -> BLOGGING_REMINDERS_TYPE_VALUE @@ -139,10 +131,6 @@ class SystemNotificationsTracker private const val MEDIA_UPLOAD_SUCCESS_TYPE_VALUE = "media_upload_success" private const val MEDIA_UPLOAD_ERROR_TYPE_VALUE = "media_upload_error" private const val POST_PUBLISHED_TYPE_VALUE = "post_published" - private const val STORY_SAVE_SUCCESS_TYPE_VALUE = "story_save_success" - private const val STORY_SAVE_ERROR_TYPE_VALUE = "story_save_error" - private const val STORY_FRAME_SAVE_SUCCESS_TYPE_VALUE = "story_frame_save_success" - private const val STORY_FRAME_SAVE_ERROR_TYPE_VALUE = "story_frame_save_error" private const val PENDING_DRAFT_TYPE_VALUE = "pending_draft" private const val ZENDESK_MESSAGE_TYPE_VALUE = "zendesk_message" private const val BLOGGING_REMINDERS_TYPE_VALUE = "blogging_reminders" diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerConstants.kt b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerConstants.kt index 86c2161cc617..7b964b8d8f7d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerConstants.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerConstants.kt @@ -4,8 +4,6 @@ object MediaPickerConstants { const val EXTRA_MEDIA_URIS = "media_uris" const val EXTRA_MEDIA_QUEUED_URIS = "queued_media_uris" const val EXTRA_MEDIA_ID = "media_id" - const val EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED = "launch_wpstories_camera_requested" - const val EXTRA_LAUNCH_WPSTORIES_MEDIA_PICKER_REQUESTED = "launch_wpstories_media_picker_requested" const val EXTRA_SAVED_MEDIA_MODEL_LOCAL_IDS = "saved_media_model_local_ids" // the enum name of the source will be returned as a string in EXTRA_MEDIA_SOURCE diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerLauncher.kt b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerLauncher.kt index 5170e3b31ab1..ab52b8e2bb43 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerLauncher.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/MediaPickerLauncher.kt @@ -5,18 +5,14 @@ import android.content.Intent import androidx.annotation.StringRes import androidx.fragment.app.Fragment import org.wordpress.android.R -import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.media.MediaBrowserType import org.wordpress.android.ui.media.MediaBrowserType.FEATURED_IMAGE_PICKER -import org.wordpress.android.ui.media.MediaBrowserType.WP_STORIES_MEDIA_PICKER import org.wordpress.android.ui.mediapicker.MediaPickerActivity import org.wordpress.android.ui.mediapicker.MediaPickerSetup import org.wordpress.android.ui.mediapicker.MediaPickerSetup.CameraSetup.ENABLED import org.wordpress.android.ui.mediapicker.MediaPickerSetup.CameraSetup.HIDDEN -import org.wordpress.android.ui.mediapicker.MediaPickerSetup.CameraSetup.STORIES import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.DEVICE import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.GIF_LIBRARY import org.wordpress.android.ui.mediapicker.MediaPickerSetup.DataSource.STOCK_LIBRARY @@ -26,12 +22,9 @@ import org.wordpress.android.ui.mediapicker.MediaType.AUDIO import org.wordpress.android.ui.mediapicker.MediaType.DOCUMENT import org.wordpress.android.ui.mediapicker.MediaType.IMAGE import org.wordpress.android.ui.mediapicker.MediaType.VIDEO -import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import javax.inject.Inject -class MediaPickerLauncher @Inject constructor( - private val analyticsTrackerWrapper: AnalyticsTrackerWrapper -) { +class MediaPickerLauncher @Inject constructor() { fun showFeaturedImagePicker( activity: Activity, site: SiteModel?, @@ -117,19 +110,6 @@ class MediaPickerLauncher @Inject constructor( activity.startActivityForResult(intent, RequestCodes.PHOTO_PICKER) } - fun showStoriesPhotoPickerForResultAndTrack(activity: Activity, site: SiteModel?) { - analyticsTrackerWrapper.track(Stat.MEDIA_PICKER_OPEN_FOR_STORIES) - showStoriesPhotoPickerForResult(activity, site) - } - - @Suppress("DEPRECATION") - fun showStoriesPhotoPickerForResult( - activity: Activity, - site: SiteModel? - ) { - ActivityLauncher.showPhotoPickerForResult(activity, WP_STORIES_MEDIA_PICKER, site, null) - } - @Suppress("DEPRECATION") fun showGravatarPicker(fragment: Fragment) { val mediaPickerSetup = MediaPickerSetup( @@ -299,12 +279,12 @@ class MediaPickerLauncher @Inject constructor( } return MediaPickerSetup( primaryDataSource = DEVICE, - availableDataSources = if (browserType.isWPStoriesPicker) setOf(WP_LIBRARY) else setOf(), + availableDataSources = setOf(), canMultiselect = browserType.canMultiselect(), requiresPhotosVideosPermissions = browserType.isImagePicker || browserType.isVideoPicker, requiresMusicAudioPermissions = browserType.isAudioPicker, allowedTypes = allowedTypes, - cameraSetup = if (browserType.isWPStoriesPicker) STORIES else HIDDEN, + cameraSetup = HIDDEN, systemPickerEnabled = true, editingEnabled = browserType.isImagePicker, queueResults = browserType == FEATURED_IMAGE_PICKER, @@ -337,7 +317,7 @@ class MediaPickerLauncher @Inject constructor( requiresPhotosVideosPermissions = false, requiresMusicAudioPermissions = false, allowedTypes = allowedTypes, - cameraSetup = if (browserType.isWPStoriesPicker) STORIES else HIDDEN, + cameraSetup = HIDDEN, systemPickerEnabled = false, editingEnabled = false, queueResults = false, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java index 74688c461e54..ecb826c1a67f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java @@ -258,13 +258,6 @@ private void launchStockMediaPicker() { } } - private void launchWPStoriesCamera() { - Intent intent = new Intent() - .putExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, true); - setResult(RESULT_OK, intent); - finish(); - } - private void doMediaUrisSelected(@NonNull List mediaUris, @NonNull PhotoPickerMediaSource source) { // if user chose a featured image, we need to upload it and return the uploaded media object if (mBrowserType == MediaBrowserType.FEATURED_IMAGE_PICKER) { @@ -289,12 +282,12 @@ public void doNext(Uri uri) { switch (queueImageResult) { case FILE_NOT_FOUND: Toast.makeText(getApplicationContext(), - R.string.file_not_found, Toast.LENGTH_SHORT) + R.string.file_not_found, Toast.LENGTH_SHORT) .show(); break; case INVALID_POST_ID: Toast.makeText(getApplicationContext(), - R.string.error_generic, Toast.LENGTH_SHORT) + R.string.error_generic, Toast.LENGTH_SHORT) .show(); break; case SUCCESS: @@ -319,24 +312,19 @@ public void doNext(Uri uri) { private void doMediaIdsSelected(ArrayList mediaIds, @NonNull PhotoPickerMediaSource source) { if (mediaIds != null && mediaIds.size() > 0) { - if (mBrowserType == MediaBrowserType.WP_STORIES_MEDIA_PICKER) { - // TODO WPSTORIES add TRACKS (see how it's tracked below? maybe do along the same lines) - getPickerFragment().mediaIdsSelectedFromWPMediaPicker(mediaIds); - } else { - // if user chose a featured image, track image picked event - if (mBrowserType == MediaBrowserType.FEATURED_IMAGE_PICKER) { - mFeaturedImageHelper.trackFeaturedImageEvent( - FeaturedImageHelper.TrackableEvent.IMAGE_PICKED_POST_SETTINGS, - mLocalPostId - ); - } - - Intent data = new Intent() - .putExtra(MediaPickerConstants.EXTRA_MEDIA_ID, mediaIds.get(0)) - .putExtra(MediaPickerConstants.EXTRA_MEDIA_SOURCE, source.name()); - setResult(RESULT_OK, data); - finish(); + // if user chose a featured image, track image picked event + if (mBrowserType == MediaBrowserType.FEATURED_IMAGE_PICKER) { + mFeaturedImageHelper.trackFeaturedImageEvent( + FeaturedImageHelper.TrackableEvent.IMAGE_PICKED_POST_SETTINGS, + mLocalPostId + ); } + + Intent data = new Intent() + .putExtra(MediaPickerConstants.EXTRA_MEDIA_ID, mediaIds.get(0)) + .putExtra(MediaPickerConstants.EXTRA_MEDIA_SOURCE, source.name()); + setResult(RESULT_OK, data); + finish(); } else { throw new IllegalArgumentException("call to doMediaIdsSelected with null or empty mediaIds array"); } @@ -367,9 +355,6 @@ public void onPhotoPickerIconClicked(@NonNull PhotoPickerFragment.PhotoPickerIco case STOCK_MEDIA: launchStockMediaPicker(); break; - case WP_STORIES_CAPTURE: - launchWPStoriesCamera(); - break; } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt index dceb7c412570..37400630c2df 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt @@ -57,8 +57,7 @@ class PhotoPickerFragment : Fragment(R.layout.photo_picker_fragment) { ANDROID_CHOOSE_PHOTO_OR_VIDEO(true), WP_MEDIA(false), STOCK_MEDIA(true), - GIF(true), - WP_STORIES_CAPTURE(true); + GIF(true); fun requiresUploadPermission(): Boolean { return mRequiresUploadPermission @@ -204,7 +203,6 @@ class PhotoPickerFragment : Fragment(R.layout.photo_picker_fragment) { ) { isShowingActionMode = false } - setupFab(uiState.fabUiModel) setupPartialAccessPrompt(uiState.isPartialMediaAccessPromptVisible) } } @@ -256,18 +254,6 @@ class PhotoPickerFragment : Fragment(R.layout.photo_picker_fragment) { } } - @Suppress("DEPRECATION") - private fun PhotoPickerFragmentBinding.setupFab(fabUiModel: PhotoPickerViewModel.FabUiModel) { - if (fabUiModel.show) { - wpStoriesTakePicture.visibility = View.VISIBLE - wpStoriesTakePicture.setOnClickListener { - fabUiModel.action() - } - } else { - wpStoriesTakePicture.visibility = View.GONE - } - } - private fun PhotoPickerFragmentBinding.setupPartialAccessPrompt(isVisible: Boolean) { partialMediaAccessPrompt.root.isVisible = isVisible partialMediaAccessPrompt.partialAccessPromptSelectMoreButton.setOnClickListener { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt index f14ab93a5f90..1c73533f5935 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt @@ -13,7 +13,6 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_CAPTURE_MEDIA import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_DEVICE_LIBRARY import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_WP_MEDIA -import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_WP_STORIES_CAPTURE import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_PREVIEW_OPENED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_RECENT_MEDIA_SELECTED import org.wordpress.android.fluxc.model.SiteModel @@ -97,9 +96,6 @@ class PhotoPickerViewModel @Inject constructor( softAskRequest?.show == true, ), buildSoftAskView(softAskRequest), - FabUiModel(browserType.isWPStoriesPicker && selectedIds.isNullOrEmpty()) { - clickIcon(PhotoPickerFragment.PhotoPickerIcon.WP_STORIES_CAPTURE) - }, buildActionModeUiModel(selectedIds), progressDialogModel ?: ProgressDialogUiModel.Hidden, showPartialAccessPrompt ?: false, @@ -205,7 +201,7 @@ class PhotoPickerViewModel @Inject constructor( } val insertEditTextBarVisible = count != 0 && browserType.isGutenbergPicker && !isVideoSelected - val showCamera = !browserType.isGutenbergPicker && !browserType.isWPStoriesPicker + val showCamera = !browserType.isGutenbergPicker return BottomBarUiModel( type = defaultBottomBar, insertEditTextBarVisible = insertEditTextBarVisible, @@ -319,8 +315,7 @@ class PhotoPickerViewModel @Inject constructor( @Suppress("DEPRECATION") fun clickIcon(icon: PhotoPickerFragment.PhotoPickerIcon) { if (icon == PhotoPickerFragment.PhotoPickerIcon.ANDROID_CAPTURE_PHOTO || - icon == PhotoPickerFragment.PhotoPickerIcon.ANDROID_CAPTURE_VIDEO || - icon == PhotoPickerFragment.PhotoPickerIcon.WP_STORIES_CAPTURE + icon == PhotoPickerFragment.PhotoPickerIcon.ANDROID_CAPTURE_VIDEO ) { if (!permissionsHandler.hasPermissionsToTakePhoto()) { _onCameraPermissionsRequested.value = Event(Unit) @@ -352,10 +347,6 @@ class PhotoPickerViewModel @Inject constructor( PhotoPickerFragment.PhotoPickerIcon.WP_MEDIA -> AnalyticsTracker.track(MEDIA_PICKER_OPEN_WP_MEDIA) PhotoPickerFragment.PhotoPickerIcon.STOCK_MEDIA -> Unit // Do nothing PhotoPickerFragment.PhotoPickerIcon.GIF -> Unit // Do nothing - PhotoPickerFragment.PhotoPickerIcon.WP_STORIES_CAPTURE -> AnalyticsTracker.track( - MEDIA_PICKER_OPEN_WP_STORIES_CAPTURE - ) - PhotoPickerFragment.PhotoPickerIcon.ANDROID_CHOOSE_PHOTO_OR_VIDEO -> Unit // Do nothing } _onIconClicked.postValue(Event(IconClickEvent(icon, browserType.canMultiselect()))) @@ -412,12 +403,9 @@ class PhotoPickerViewModel @Inject constructor( items.add(PopupMenuUiModel.PopupMenuItem(UiStringRes(R.string.photo_picker_stock_media)) { clickIcon(PhotoPickerFragment.PhotoPickerIcon.STOCK_MEDIA) }) - // only show GIF picker from Tenor if this is NOT the WPStories picker - if (!browserType.isWPStoriesPicker) { - items.add(PopupMenuUiModel.PopupMenuItem(UiStringRes(R.string.photo_picker_gif)) { - clickIcon(PhotoPickerFragment.PhotoPickerIcon.GIF) - }) - } + items.add(PopupMenuUiModel.PopupMenuItem(UiStringRes(R.string.photo_picker_gif)) { + clickIcon(PhotoPickerFragment.PhotoPickerIcon.GIF) + }) } if (items.size == 1) { items[0].action() @@ -535,7 +523,6 @@ class PhotoPickerViewModel @Inject constructor( val photoListUiModel: PhotoListUiModel, val bottomBarUiModel: BottomBarUiModel, val softAskViewUiModel: SoftAskViewUiModel, - val fabUiModel: FabUiModel, val actionModeUiModel: ActionModeUiModel, val progressDialogUiModel: ProgressDialogUiModel, val isPartialMediaAccessPromptVisible: Boolean, @@ -572,8 +559,6 @@ class PhotoPickerViewModel @Inject constructor( object Hidden : SoftAskViewUiModel() } - data class FabUiModel(val show: Boolean, val action: () -> Unit) - sealed class ActionModeUiModel { data class Visible( val actionModeTitle: UiString? = null, 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 81623b8f49c6..20d861c576fd 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 @@ -76,7 +76,6 @@ import org.wordpress.android.editor.gutenberg.GutenbergNetworkConnectionListener; 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.editor.savedinstance.SavedInstanceDatabase; import org.wordpress.android.fluxc.Dispatcher; import org.wordpress.android.fluxc.action.AccountAction; @@ -90,7 +89,6 @@ 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; @@ -169,7 +167,6 @@ 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.XPostsCapabilityChecker; import org.wordpress.android.ui.posts.editor.media.AddExistingMediaSource; import org.wordpress.android.ui.posts.editor.media.EditorMedia; @@ -184,9 +181,6 @@ import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.prefs.SiteSettingsInterface; import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper; -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.suggestion.SuggestionActivity; import org.wordpress.android.ui.suggestion.SuggestionType; import org.wordpress.android.ui.uploads.PostEvents; @@ -285,6 +279,7 @@ import static org.wordpress.android.ui.posts.EditPostActivityConstants.EXTRA_UPLOAD_NOT_STARTED; import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_DROPPED_MEDIA_URIS; import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_EDITOR_FRAGMENT; +import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_EDITOR_SESSION_DATA; import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_GUTENBERG_IS_SHOWN; import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_HTML_MODE_ON; import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_IS_NEW_POST; @@ -296,7 +291,6 @@ import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_REDO; import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_REVISION; import static org.wordpress.android.ui.posts.EditPostActivityConstants.STATE_KEY_UNDO; -import static org.wordpress.android.ui.stories.StoryComposerActivity.STATE_KEY_EDITOR_SESSION_DATA; public class EditPostActivity extends LocaleAwareActivity implements EditorFragmentActivity, @@ -423,10 +417,6 @@ enum RestartEditorOptions { @Inject XPostsCapabilityChecker mXpostsCapabilityChecker; @Inject CrashLogging mCrashLogging; @Inject MediaPickerLauncher mMediaPickerLauncher; - @Inject StoryRepositoryWrapper mStoryRepositoryWrapper; - @Inject LoadStoryFromStoriesPrefsUseCase mLoadStoryFromStoriesPrefsUseCase; - @Inject StoriesPrefs mStoriesPrefs; - @Inject StoriesEventListener mStoriesEventListener; @Inject UpdateFeaturedImageUseCase mUpdateFeaturedImageUseCase; @Inject GlobalStyleSupportFeatureConfig mGlobalStyleSupportFeatureConfig; @Inject ZendeskHelper mZendeskHelper; @@ -442,7 +432,6 @@ enum RestartEditorOptions { private SiteModel mSite; private SiteSettingsInterface mSiteSettings; private boolean mIsJetpackSsoEnabled; - private boolean mStoryEditingCancelled = false; private boolean mNetworkErrorOnLastMediaFetchAttempt = false; @@ -730,10 +719,6 @@ public void handleOnBackPressed() { if (mEditorFragment instanceof EditorMediaUploadListener) { mEditorMediaUploadListener = (EditorMediaUploadListener) mEditorFragment; } - - if (mEditorFragment instanceof StorySaveMediaListener) { - mStoriesEventListener.setSaveMediaListener((StorySaveMediaListener) mEditorFragment); - } } if (mSite == null) { @@ -785,13 +770,6 @@ public void handleOnBackPressed() { } 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()); @@ -812,8 +790,6 @@ public void handleOnBackPressed() { setupPrepublishingBottomSheetRunnable(); - mStoriesEventListener.start(this.getLifecycle(), mSite, mEditPostRepository, this); - // The check on savedInstanceState should allow to show the dialog only on first start // (even in cases when the VM could be re-created like when activity is destroyed in the background) mStorageUtilsViewModel.start(savedInstanceState == null); @@ -1503,30 +1479,12 @@ private boolean handleBackPressed() { } else if (mEditorPhotoPicker.isPhotoPickerShowing()) { mEditorPhotoPicker.hidePhotoPicker(); } else { - performWhenNoStoriesBeingSaved(new DoWhenNoStoriesBeingSavedCallback() { - @Override public void doWhenNoStoriesBeingSaved() { - savePostAndOptionallyFinish(true, false); - } - }); + savePostAndOptionallyFinish(true, false); } return true; } - interface DoWhenNoStoriesBeingSavedCallback { - void doWhenNoStoriesBeingSaved(); - } - - private void performWhenNoStoriesBeingSaved(DoWhenNoStoriesBeingSavedCallback callback) { - if (mStoriesEventListener.getStoriesSavingInProgress().isEmpty()) { - callback.doWhenNoStoriesBeingSaved(); - } else { - // Oops! A story is still being saved, let's wait - ToastUtils.showToast(EditPostActivity.this, - getString(R.string.toast_edit_story_update_in_progress_title)); - } - } - private RemotePreviewLogicHelper.RemotePreviewHelperFunctions getEditPostActivityStrategyFunctions() { return new RemotePreviewLogicHelper.RemotePreviewHelperFunctions() { @Override @@ -1689,7 +1647,7 @@ private boolean performSecondaryAction() { case PUBLISH_NOW: mAnalyticsTrackerWrapper.track(Stat.EDITOR_POST_PUBLISH_TAPPED); mPublishPostImmediatelyUseCase.updatePostToPublishImmediately(mEditPostRepository, mIsNewPost); - checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet(); + showPrepublishingNudgeBottomSheet(); return true; case NONE: throw new IllegalStateException("Switch in `secondaryAction` shouldn't go through the NONE case"); @@ -1787,13 +1745,13 @@ private void performPrimaryAction() { switch (getPrimaryAction()) { case PUBLISH_NOW: mAnalyticsTrackerWrapper.track(Stat.EDITOR_POST_PUBLISH_TAPPED); - checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet(); + showPrepublishingNudgeBottomSheet(); return; case UPDATE: case CONTINUE: case SCHEDULE: case SUBMIT_FOR_REVIEW: - checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet(); + showPrepublishingNudgeBottomSheet(); return; case SAVE: uploadPost(false); @@ -1851,13 +1809,6 @@ private void onUploadSuccess(MediaModel media) { if (!media.getMarkedLocallyAsFeatured() && mEditorMediaUploadListener != null) { 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 - // then post the event for StoriesEventListener to process - updateAndSavePostAsync( - updatePostResult -> mStoriesEventListener.postStoryMediaUploadedEvent(media) - ); - } } else if (media.getMarkedLocallyAsFeatured() && media.getLocalPostId() == mEditPostRepository .getId()) { setFeaturedImageId(media.getMediaId(), false, false); @@ -2156,20 +2107,12 @@ private void setupPrepublishingBottomSheetRunnable() { PrepublishingBottomSheetFragment.TAG); if (fragment == null) { PrepublishingBottomSheetFragment prepublishingFragment = - PrepublishingBottomSheetFragment.newInstance(getSite(), mIsPage, false); + PrepublishingBottomSheetFragment.newInstance(getSite(), mIsPage); prepublishingFragment.show(getSupportFragmentManager(), PrepublishingBottomSheetFragment.TAG); } }; } - private void checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet() { - performWhenNoStoriesBeingSaved(new DoWhenNoStoriesBeingSavedCallback() { - @Override public void doWhenNoStoriesBeingSaved() { - showPrepublishingNudgeBottomSheet(); - } - }); - } - private void showPrepublishingNudgeBottomSheet() { mViewPager.setCurrentItem(PAGE_CONTENT); ActivityUtils.hideKeyboard(this); @@ -2381,7 +2324,6 @@ public Fragment getItem(int position) { mIsNewPost, gutenbergWebViewAuthorizationData, gutenbergPropsBuilder, - RequestCodes.EDIT_STORY, mJetpackFeatureRemovalPhaseHelper.shouldShowJetpackPoweredEditorFeatures() ); } else { @@ -2419,10 +2361,6 @@ public Fragment getItem(int position) { reattachUploadingMediaForAztec(); } - - if (mEditorFragment instanceof StorySaveMediaListener) { - mStoriesEventListener.setSaveMediaListener((StorySaveMediaListener) mEditorFragment); - } break; case PAGE_SETTINGS: mEditPostSettingsFragment = (EditPostSettingsFragment) fragment; @@ -2810,23 +2748,12 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { case RequestCodes.STOCK_MEDIA_PICKER_SINGLE_SELECT_FOR_GUTENBERG_BLOCK: mEditorFragment.mediaSelectionCancelled(); return; - case RequestCodes.EDIT_STORY: - mStoryEditingCancelled = true; - return; default: // noop return; } } - if (requestCode == RequestCodes.EDIT_STORY) { - mStoryEditingCancelled = false; - 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) { @@ -3486,30 +3413,11 @@ public void onEditorFragmentContentReady( mPostEditorAnalyticsSession.start(unsupportedBlocksList, themeSupportsGalleryWithImageBlocks(), entryPoint); presentNewPageNoticeIfNeeded(); - // don't start listening for Story events just now if we're waiting for a block to be replaced, - // unless the user cancelled editing in which case we should continue as normal and attach the listener - if (!replaceBlockActionWaiting || mStoryEditingCancelled) { - mStoriesEventListener.startListening(); - } - // Start VM, load prompt and populate Editor with content after edit IS ready. final int promptId = getIntent().getIntExtra(EXTRA_PROMPT_ID, -1); mEditorBloggingPromptsViewModel.start(mSite, promptId); } - @Override - public void onReplaceStoryEditedBlockActionSent() { - // when a replaceBlock signal has been sent, it uses the DeferredEventEmitter so we have to wait for - // the block replacement to be completed before we can start throwing block-related events at it - // otherwise these events will miss their target - mStoriesEventListener.pauseListening(); - } - - @Override - public void onReplaceStoryEditedBlockActionReceived() { - mStoriesEventListener.startListening(); - } - private void logTemplateSelection() { final String template = getIntent().getStringExtra(EXTRA_PAGE_TEMPLATE); if (template == null) { @@ -3566,36 +3474,6 @@ public void onTrackableEvent(TrackableEvent event, Map propertie mEditorTracker.trackEditorEvent(event, mEditorFragment.getEditorName(), properties); } - @Override public void onStoryComposerLoadRequested(ArrayList mediaFiles, String blockId) { - // we need to save the latest before editing - updateAndSavePostAsync(updatePostResult -> { - boolean noSlidesLoaded = mStoriesEventListener.onRequestMediaFilesEditorLoad( - EditPostActivity.this, - new LocalId(mEditPostRepository.getId()), - mNetworkErrorOnLastMediaFetchAttempt, - mediaFiles, - blockId - ); - - if (mNetworkErrorOnLastMediaFetchAttempt && noSlidesLoaded) { - // try another fetchMedia request - fetchMediaList(); - } - }); - } - - @Override public void onRetryUploadForMediaCollection(ArrayList mediaFiles) { - mStoriesEventListener.onRetryUploadForMediaCollection(this, mediaFiles, mEditorMediaUploadListener); - } - - @Override public void onCancelUploadForMediaCollection(ArrayList mediaFiles) { - mStoriesEventListener.onCancelUploadForMediaCollection(mediaFiles); - } - - @Override public void onCancelSaveForMediaCollection(ArrayList mediaFiles) { - mStoriesEventListener.onCancelSaveForMediaCollection(mediaFiles); - } - @Override public boolean showPreview() { PreviewLogicOperationResult opResult = mRemotePreviewLogicHelper.runPostPreviewLogic( this, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt index 2835aae9db5f..46df0deb597a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt @@ -153,10 +153,6 @@ class PostActionHandler( triggerPostListAction(PostListAction.NewPost(site)) } - fun newStoryPost() { - triggerPostListAction(PostListAction.NewStoryPost(site)) - } - fun handleEditPostResult(data: Intent?) { val localPostId = data?.getIntExtra(EditPostActivityConstants.EXTRA_POST_LOCAL_ID, 0) if (localPostId == null || localPostId == 0) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListAction.kt index 6954fe44dca5..2243935050b1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListAction.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListAction.kt @@ -8,19 +8,15 @@ import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.PagePostCreationSourcesDetail.POST_FROM_POSTS_LIST import org.wordpress.android.ui.blaze.BlazeFeatureUtils import org.wordpress.android.ui.blaze.BlazeFlowSource -import org.wordpress.android.ui.photopicker.MediaPickerLauncher import org.wordpress.android.ui.posts.RemotePreviewLogicHelper.RemotePreviewType -import org.wordpress.android.ui.prefs.AppPrefs import org.wordpress.android.ui.reader.ReaderActivityLauncher import org.wordpress.android.ui.reader.ReaderPostPagerActivity -import org.wordpress.android.ui.stories.intro.StoriesIntroDialogFragment import org.wordpress.android.ui.uploads.UploadService import org.wordpress.android.viewmodel.helpers.ToastMessageHolder sealed class PostListAction { class EditPost(val site: SiteModel, val post: PostModel, val loadAutoSaveRevision: Boolean) : PostListAction() class NewPost(val site: SiteModel, val isPromo: Boolean = false) : PostListAction() - class NewStoryPost(val site: SiteModel) : PostListAction() class PreviewPost( val site: SiteModel, val post: PostModel, @@ -54,7 +50,6 @@ fun handlePostListAction( action: PostListAction, remotePreviewLogicHelper: RemotePreviewLogicHelper, previewStateHelper: PreviewStateHelper, - mediaPickerLauncher: MediaPickerLauncher, blazeFeatureUtils: BlazeFeatureUtils ) { when (action) { @@ -64,14 +59,6 @@ fun handlePostListAction( is PostListAction.NewPost -> { ActivityLauncher.addNewPostForResult(activity, action.site, action.isPromo, POST_FROM_POSTS_LIST, -1, null) } - is PostListAction.NewStoryPost -> { - if (AppPrefs.shouldShowStoriesIntro()) { - StoriesIntroDialogFragment.newInstance(action.site) - .show(activity.supportFragmentManager, StoriesIntroDialogFragment.TAG) - } else { - mediaPickerLauncher.showStoriesPhotoPickerForResultAndTrack(activity, action.site) - } - } is PostListAction.PreviewPost -> { val helperFunctions = previewStateHelper.getUploadStrategyFunctions(activity, action) remotePreviewLogicHelper.runPostPreviewLogic( diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostUtils.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostUtils.java index f56a0bc857c0..ae3c3b0fcbf4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostUtils.java @@ -54,7 +54,6 @@ public class PostUtils { private static final HashSet SHORTCODE_TABLE = new HashSet<>(); private static final String GUTENBERG_BLOCK_START = " remove mediaFiles entirely - // set start index and go up. - var storyBlockStartIndex = 0 - var hasMediaFiles = true - while (storyBlockStartIndex > -1 && storyBlockStartIndex < content.length && hasMediaFiles) { - storyBlockStartIndex = content.indexOf(HEADING_START, storyBlockStartIndex) - if (storyBlockStartIndex > -1) { - val storyBlockEndIndex = content.indexOf(HEADING_END_NO_NEW_LINE, storyBlockStartIndex) - val mediaFilesStartIndex = storyBlockStartIndex + HEADING_START.length - hasMediaFiles = mediaFilesStartIndex < storyBlockEndIndex - if (!hasMediaFiles) { - break - } - try { - val jsonString: String = content.substring( - mediaFilesStartIndex, - storyBlockEndIndex - ) - content = listener.doWithMediaFilesJson(content, jsonString) - storyBlockStartIndex += HEADING_START.length - } catch (exception: StringIndexOutOfBoundsException) { - logException(exception, postModel, siteModel) - } - } - } - - postModel.setContent(content) - } - - private fun logException(exception: Throwable, postModel: PostModel, siteModel: SiteModel?) { - AppLog.e(EDITOR, "Error while parsing Story blocks: ${exception.message}") - if (shouldLogContent(siteModel, postModel)) { - AppLog.e(EDITOR, "HTML content of the post before the crash: ${postModel.content}") - } - crashLogging.sendReportWithTag(exception = exception, tag = EDITOR) - } - - // See: https://git.io/JqfhK - private fun shouldLogContent(siteModel: SiteModel?, postModel: PostModel) = siteModel != null && - siteModel.isWPCom && - !siteModel.isPrivate && - postModel.password.isEmpty() && - postModel.status != PRIVATE.toString() - - fun replaceLocalMediaIdsWithRemoteMediaIdsInPost( - postModel: PostModel, - siteModel: SiteModel?, - mediaFile: MediaFile - ) { - if (TextUtils.isEmpty(mediaFile.mediaId)) { - // if for any reason we couldn't obtain a remote mediaId, it's not worth spending time - // looking to replace anything in the Post. Skip processing for later in error handling. - return - } - val gson = Gson() - findAllStoryBlocksInPostAndPerformOnEachMediaFilesJson( - postModel, - siteModel, - object : DoWithMediaFilesListener { - override fun doWithMediaFilesJson(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 - 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. - storiesPrefs.replaceLocalMediaIdKeyedSlideWithRemoteMediaIdKeyedSlide( - mediaFile.id, - mediaFile.mediaId.toLong(), - postModel.localSiteId.toLong() - ) - } - } - processedContent = content.replace(mediaFilesJsonString, gson.toJson(storyBlockDataNonNull)) - } - return processedContent - } - } - ) - } - - 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 - ) - } - } - - fun assignAltOnEachMediaFile( - frames: List, - mediaFiles: ArrayList - ): List { - return mediaFiles.mapIndexed { index, mediaFile -> - run { - mediaFile.alt = StoryFrameItem.getAltTextFromFrameAddedViews(frames[index]) - mediaFile - } - mediaFile - } - } - - private fun createGBStoryBlockStringFromJson(storyBlock: StoryBlockData): String { - val gson = Gson() - return HEADING_START + gson.toJson(storyBlock) + HEADING_END + DIV_PART + CLOSING_TAG - } - - interface DoWithMediaFilesListener { - fun doWithMediaFilesJson(content: String, mediaFilesJsonString: String): String - } - - data class StoryBlockData( - val mediaFiles: List - ) - - @Suppress("DataClassShouldBeImmutable") - data class StoryMediaFileData( - val alt: String, - var id: String, - var link: String, - val type: String, - val mime: String, - val caption: String, - var url: String - ) - - companion object { - const val TEMPORARY_ID_PREFIX = "tempid-" - const val HEADING_START = "\n" - const val HEADING_END_NO_NEW_LINE = " -->" - const val DIV_PART = "
\n" - const val CLOSING_TAG = "" - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesAnalyticsReceiver.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesAnalyticsReceiver.kt deleted file mode 100644 index 1b64d844f8cd..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesAnalyticsReceiver.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.wordpress.android.ui.stories - -import com.wordpress.stories.compose.StoriesAnalyticsListener -import org.wordpress.android.analytics.AnalyticsTracker -import org.wordpress.android.analytics.AnalyticsTracker.Stat - -/** - * Receives tracker-agnostic analytics events from the Stories library and forwards them to [AnalyticsTracker]. - */ -class StoriesAnalyticsReceiver : StoriesAnalyticsListener { - override fun trackStoryTextChanged(properties: Map) { - AnalyticsTracker.track(Stat.STORY_TEXT_CHANGED, properties) - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt deleted file mode 100644 index fd6b57d8626b..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt +++ /dev/null @@ -1,120 +0,0 @@ -package org.wordpress.android.ui.stories - -import android.app.Activity -import android.content.Intent -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.ui.ActivityLauncher -import org.wordpress.android.ui.PagePostCreationSourcesDetail -import org.wordpress.android.ui.media.MediaBrowserActivity -import org.wordpress.android.ui.media.MediaBrowserType -import org.wordpress.android.ui.mysite.SiteNavigationAction -import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStory -import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStoryWithMediaIds -import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStoryWithMediaUris -import org.wordpress.android.ui.photopicker.MediaPickerConstants -import org.wordpress.android.util.AppLog -import org.wordpress.android.util.AppLog.T.UTILS -import org.wordpress.android.util.extensions.getSerializableExtraCompat -import org.wordpress.android.viewmodel.Event -import javax.inject.Inject - -class StoriesMediaPickerResultHandler -@Inject constructor() { - private val _onNavigation = MutableLiveData>() - val onNavigation = _onNavigation as LiveData> - - @Deprecated("Use rather the other handle method and the live data navigation.") - fun handleMediaPickerResultForStories( - data: Intent, - activity: Activity?, - selectedSite: SiteModel?, - source: PagePostCreationSourcesDetail - ): Boolean { - if (selectedSite == null) { - return false - } - when (val navigationAction = buildNavigationAction(data, selectedSite, source)) { - is AddNewStory -> ActivityLauncher.addNewStoryForResult( - activity, - navigationAction.site, - navigationAction.source - ) - is AddNewStoryWithMediaIds -> ActivityLauncher.addNewStoryWithMediaIdsForResult( - activity, - navigationAction.site, - navigationAction.source, - navigationAction.mediaIds.toLongArray() - ) - is AddNewStoryWithMediaUris -> ActivityLauncher.addNewStoryWithMediaUrisForResult( - activity, - navigationAction.site, - navigationAction.source, - navigationAction.mediaUris.toTypedArray() - ) - else -> { - return false - } - } - - return true - } - - fun handleMediaPickerResultForStories( - data: Intent, - selectedSite: SiteModel, - source: PagePostCreationSourcesDetail - ): Boolean { - val navigationAction = buildNavigationAction(data, selectedSite, source) - return if (navigationAction != null) { - _onNavigation.postValue(Event(navigationAction)) - true - } else { - false - } - } - - private fun buildNavigationAction( - data: Intent, - selectedSite: SiteModel, - source: PagePostCreationSourcesDetail - ): SiteNavigationAction? { - if (data.getBooleanExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, false)) { - return AddNewStory(selectedSite, source) - } else if (isWPStoriesMediaBrowserTypeResult(data)) { - if (data.hasExtra(MediaBrowserActivity.RESULT_IDS)) { - val mediaIds = data.getLongArrayExtra(MediaBrowserActivity.RESULT_IDS)?.asList() ?: listOf() - return AddNewStoryWithMediaIds(selectedSite, source, mediaIds) - } else { - val mediaUriStringsArray = data.getStringArrayExtra( - MediaPickerConstants.EXTRA_MEDIA_URIS - ) - if (mediaUriStringsArray.isNullOrEmpty()) { - AppLog.e( - UTILS, - "Can't resolve picked or captured image" - ) - return null - } - val mediaUris = mediaUriStringsArray.asList() - return AddNewStoryWithMediaUris( - selectedSite, - source, - mediaUris = mediaUris - ) - } - } - return null - } - - private fun isWPStoriesMediaBrowserTypeResult(data: Intent): Boolean { - if (data.hasExtra(MediaBrowserActivity.ARG_BROWSER_TYPE)) { - val browserType = requireNotNull( - data.getSerializableExtraCompat(MediaBrowserActivity.ARG_BROWSER_TYPE) - ) - return browserType.isWPStoriesPicker - } - return false - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesTrackerHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesTrackerHelper.kt deleted file mode 100644 index 76771fed8ad1..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesTrackerHelper.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.wordpress.android.ui.stories - -import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult -import org.wordpress.android.WordPress -import org.wordpress.android.analytics.AnalyticsTracker -import org.wordpress.android.analytics.AnalyticsTracker.Stat -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.util.analytics.AnalyticsUtils -import org.wordpress.android.util.extensions.getSerializableCompat -import javax.inject.Inject - -class StoriesTrackerHelper @Inject constructor() { - fun trackStorySaveResultEvent(event: StorySaveResult) { - val stat = if (event.isSuccess()) Stat.STORY_SAVE_SUCCESSFUL else Stat.STORY_SAVE_ERROR - trackStorySaveResultEvent(event, stat) - } - - fun trackStoryPostSavedEvent(frameQty: Int, site: SiteModel, locallySaved: Boolean) { - val stat = if (locallySaved) Stat.STORY_POST_SAVE_LOCALLY else Stat.STORY_POST_SAVE_REMOTELY - val properties: HashMap = HashMap() - properties.put("slide_qty", frameQty) - AnalyticsUtils.trackWithSiteDetails(stat, site, properties) - } - - private fun getCommonProperties(event: StorySaveResult): HashMap { - val properties: HashMap = HashMap() - properties.put("is_retry", event.isRetry) - properties.put("slide_qty", event.frameSaveResult.size) - properties.put("elapsed_time", event.elapsedTime) - return properties - } - - fun trackStorySaveResultEvent(event: StorySaveResult, stat: Stat) { - val properties = getCommonProperties(event) - var siteModel: SiteModel? = null - event.metadata?.let { - siteModel = it.getSerializableCompat(WordPress.SITE) - } - - siteModel?.let { - AnalyticsUtils.trackWithSiteDetails(stat, it, properties) - } ?: AnalyticsTracker.track(stat, properties) - } -} 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 deleted file mode 100644 index 50055bc6f87a..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerActivity.kt +++ /dev/null @@ -1,724 +0,0 @@ -@file:Suppress("DEPRECATION") - -package org.wordpress.android.ui.stories - -import android.app.Activity -import android.app.PendingIntent -import android.app.ProgressDialog -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.view.View -import androidx.fragment.app.DialogFragment -import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProvider -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.FrameSaveErrorDialogOk -import com.wordpress.stories.compose.GenericAnnouncementDialogProvider -import com.wordpress.stories.compose.MediaPickerProvider -import com.wordpress.stories.compose.MetadataProvider -import com.wordpress.stories.compose.NotificationIntentLoader -import com.wordpress.stories.compose.PermanentPermissionDenialDialogProvider -import com.wordpress.stories.compose.PrepublishingEventProvider -import com.wordpress.stories.compose.SnackbarProvider -import com.wordpress.stories.compose.StoryDiscardListener -import com.wordpress.stories.compose.frame.StoryLoadEvents.StoryLoadEnd -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 -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 -import com.wordpress.stories.util.KEY_STORY_INDEX -import com.wordpress.stories.util.KEY_STORY_SAVE_RESULT -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode -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_UPDATED_CONTENT -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.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 -import org.wordpress.android.push.NotificationsProcessingService.ARG_NOTIFICATION_TYPE -import org.wordpress.android.ui.RequestCodes -import org.wordpress.android.ui.media.MediaBrowserActivity -import org.wordpress.android.ui.photopicker.MediaPickerConstants -import org.wordpress.android.ui.photopicker.MediaPickerLauncher -import org.wordpress.android.ui.posts.EditPostActivity.OnPostUpdatedFromUIListener -import org.wordpress.android.ui.posts.EditPostRepository -import org.wordpress.android.ui.posts.EditPostSettingsFragment.EditPostActivityHook -import org.wordpress.android.ui.posts.PostEditorAnalyticsSession -import org.wordpress.android.ui.posts.prepublishing.PrepublishingBottomSheetFragment -import org.wordpress.android.ui.posts.ProgressDialogHelper -import org.wordpress.android.ui.posts.ProgressDialogUiState -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.home.PublishPost -import org.wordpress.android.ui.posts.prepublishing.listeners.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 -import org.wordpress.android.ui.stories.prefs.StoriesPrefs -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.MediaUtils -import org.wordpress.android.util.ToastUtils -import org.wordpress.android.util.ToastUtils.Duration.LONG -import org.wordpress.android.util.WPPermissionUtils -import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper -import org.wordpress.android.util.analytics.AnalyticsUtilsWrapper -import org.wordpress.android.util.extensions.getParcelableCompat -import org.wordpress.android.util.extensions.getParcelableExtraCompat -import org.wordpress.android.util.extensions.getSerializableCompat -import org.wordpress.android.util.extensions.getSerializableExtraCompat -import org.wordpress.android.util.helpers.MediaFile -import org.wordpress.android.viewmodel.observeEvent -import org.wordpress.android.widgets.WPSnackbar -import java.util.Objects -import javax.inject.Inject -import com.wordpress.stories.R as StoriesR - -class StoryComposerActivity : ComposeLoopFrameActivity(), - SnackbarProvider, - MediaPickerProvider, - EditorMediaListener, - AuthenticationHeadersProvider, - NotificationIntentLoader, - MetadataProvider, - StoryDiscardListener, - EditPostActivityHook, - PrepublishingEventProvider, - PrepublishingBottomSheetListener, - PermanentPermissionDenialDialogProvider, - GenericAnnouncementDialogProvider { - private var site: SiteModel? = null - - @Inject - lateinit var storyEditorMedia: StoryEditorMedia - - @Inject - lateinit var progressDialogHelper: ProgressDialogHelper - - @Inject - lateinit var uiHelpers: UiHelpers - - @Inject - lateinit var postStore: PostStore - - @Inject - lateinit var authenticationUtils: AuthenticationUtils - - @Inject - internal lateinit var editPostRepository: EditPostRepository - - @Inject - lateinit var analyticsTrackerWrapper: AnalyticsTrackerWrapper - - @Inject - lateinit var analyticsUtilsWrapper: AnalyticsUtilsWrapper - - @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 - - @Inject - lateinit var storyRepositoryWrapper: StoryRepositoryWrapper - - @Inject - lateinit var storiesPrefs: StoriesPrefs - - private lateinit var viewModel: StoryComposerViewModel - - @Suppress("DEPRECATION") - private var addingMediaToEditorProgressDialog: ProgressDialog? = null - private val frameIdsToRemove = ArrayList() - - override fun getSite() = site - 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 STATE_KEY_ORIGINAL_STORY_SAVE_RESULT = "stateKeyOriginalSaveResult" - 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 - } - - 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) - (application as WordPress).component().inject(this) - initSite(savedInstanceState) - setSnackbarProvider(this) - setAuthenticationProvider(this) - setNotificationExtrasLoader(this) - setMetadataProvider(this) - setStoryDiscardListener(this) - setStoriesAnalyticsListener(StoriesAnalyticsReceiver()) - setNotificationTrackerProvider((application as WordPress).storyNotificationTrackerProvider) - setPrepublishingEventProvider(this) - setPermissionDialogProvider(this) - setGenericAnnouncementDialogProvider(this) - - initViewModel(savedInstanceState) - super.onCreate(savedInstanceState) - - setUseTempCaptureFile(false) // we need to keep the captured files for later Story editing - } - - private fun initSite(savedInstanceState: Bundle?) { - site = if (savedInstanceState == null) { - intent.getSerializableExtraCompat(WordPress.SITE) - } else { - savedInstanceState.getSerializableCompat(WordPress.SITE) - } - } - - private fun initViewModel(savedInstanceState: Bundle?) { - var localPostId = 0 - var notificationType: NotificationType? = null - var originalStorySaveResult: StorySaveResult? = null - - if (savedInstanceState == null) { - localPostId = getBackingPostIdFromIntent() - originalStorySaveResult = intent.getParcelableExtraCompat(KEY_STORY_SAVE_RESULT) - - if (intent.hasExtra(ARG_NOTIFICATION_TYPE)) { - notificationType = intent.getSerializableExtraCompat(ARG_NOTIFICATION_TYPE) - } - } else { - if (savedInstanceState.containsKey(STATE_KEY_POST_LOCAL_ID)) { - localPostId = savedInstanceState.getInt(STATE_KEY_POST_LOCAL_ID) - } - if (savedInstanceState.containsKey(STATE_KEY_ORIGINAL_STORY_SAVE_RESULT)) { - originalStorySaveResult = - savedInstanceState.getParcelableCompat(STATE_KEY_ORIGINAL_STORY_SAVE_RESULT) - } - } - - val postEditorAnalyticsSession = savedInstanceState?.let { bundle -> - PostEditorAnalyticsSession.fromBundle(bundle, STATE_KEY_EDITOR_SESSION_DATA, analyticsTrackerWrapper) - } - - viewModel = ViewModelProvider(this, viewModelFactory)[StoryComposerViewModel::class.java] - - site?.let { - val postInitialized = viewModel.start( - it, - editPostRepository, - LocalId(localPostId), - postEditorAnalyticsSession, - notificationType, - originalStorySaveResult - ) - - // Ensure we have a valid post - if (!postInitialized) { - showErrorAndFinish(R.string.post_not_found) - return@let - } - } - - storyEditorMedia.start(requireNotNull(site), this) - setupStoryEditorMediaObserver() - setupViewModelObservers() - } - - private fun setupViewModelObservers() { - viewModel.mediaFilesUris.observe(this, { uriList -> - val filteredList = uriList.filterNot { MediaUtils.isGif(it.toString()) } - if (filteredList.isNotEmpty()) { - addFramesToStoryFromMediaUriList(filteredList) - setDefaultSelectionAndUpdateBackgroundSurfaceUI(filteredList) - // generally speaking, adding media will happen at the beginning of loading the StoryComposer, so once - // it's done adding media the StoryComposer will be ready to render the newly loaded / created Story. - // Hence, it makes sense to start the editor session tracking at this point - note subsequent calls - // will have no effect, given PostEditorAnalyticsSession has a flag so it can only be started once. - viewModel.onStoryComposerStartAnalyticsSession() - } - - // finally if any of the files was a gif, warn the user - if (filteredList.size != uriList.size) { - FrameSaveErrorDialog.newInstance( - title = getString(R.string.dialog_edit_story_unsupported_format_title), - message = getString(R.string.dialog_edit_story_unsupported_format_message), - hideCancelButton = true, - listener = object : FrameSaveErrorDialogOk { - override fun OnOkClicked(dialog: DialogFragment) { - if (filteredList.isEmpty()) { - onStoryDiscarded() - setResult(Activity.RESULT_CANCELED) - finish() - } - } - } - ).show(supportFragmentManager, FRAGMENT_ANNOUNCEMENT_DIALOG) - } - }) - - viewModel.openPrepublishingBottomSheet.observeEvent(this, { - analyticsTrackerWrapper.track(PREPUBLISHING_BOTTOM_SHEET_OPENED) - openPrepublishingBottomSheet() - }) - - viewModel.submitButtonClicked.observeEvent(this, { - analyticsTrackerWrapper.track(Stat.STORY_POST_PUBLISH_TAPPED) - processStorySaving() - }) - - viewModel.trackEditorCreatedPost.observeEvent(this, { - site?.let { - analyticsUtilsWrapper.trackEditorCreatedPost( - intent.action, - intent, - it, - editPostRepository.getPost() - ) - } - }) - } - - private fun showErrorAndFinish(errorMessageId: Int) { - ToastUtils.showToast( - this, - errorMessageId, - ToastUtils.Duration.LONG - ) - finish() - } - - override fun onLoadFromIntent(intent: Intent) { - super.onLoadFromIntent(intent) - // now see if we need to handle information coming from the MediaPicker to populate - handleMediaPickerIntentData(intent) - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - viewModel.writeToBundle(outState) - } - - @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION", "NestedBlockDepth") - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - viewModel.onStoryComposerAnalyticsSessionStartTimeReset() - super.onActivityResult(requestCode, resultCode, data) - data?.let { - when (requestCode) { - RequestCodes.MULTI_SELECT_MEDIA_PICKER, RequestCodes.SINGLE_SELECT_MEDIA_PICKER -> { - handleMediaPickerIntentData(it) - } - RequestCodes.PHOTO_PICKER, RequestCodes.STORIES_PHOTO_PICKER -> { - when { - it.hasExtra(MediaPickerConstants.EXTRA_MEDIA_URIS) -> { - data.getStringArrayExtra(MediaPickerConstants.EXTRA_MEDIA_URIS)?.let { - val uriList: List = convertStringArrayIntoUrisList(it) - storyEditorMedia.addNewMediaItemsToEditorAsync(uriList, false) - } - } - it.hasExtra(MediaBrowserActivity.RESULT_IDS) -> { - handleMediaPickerIntentData(it) - } - else -> { - // handleMediaPickerIntentData(it)? - } - } - } - else -> { - // handleMediaPickerIntentData(it)? - } - } - } - } - - override fun onDestroy() { - storyEditorMedia.cancelAddMediaToEditorActions() - super.onDestroy() - } - - private fun getBackingPostIdFromIntent(): Int { - var localPostId = intent.getIntExtra(KEY_POST_LOCAL_ID, 0) - if (localPostId == 0) { - if (intent.hasExtra(KEY_STORY_SAVE_RESULT)) { - val storySaveResult = intent.getParcelableExtraCompat(KEY_STORY_SAVE_RESULT) - storySaveResult?.let { - localPostId = it.metadata?.getInt(KEY_POST_LOCAL_ID, 0) ?: 0 - } - } - } - return localPostId - } - - override fun showProvidedSnackbar(message: String, actionLabel: String?, callback: () -> Unit) { - // no op - // no provided snackbar here given we're not using snackbars from within the Story Creation experience - // in WPAndroid - } - - override fun setupRequestCodes(requestCodes: ExternalMediaPickerRequestCodesAndExtraKeys) { - requestCodes.PHOTO_PICKER = RequestCodes.PHOTO_PICKER - requestCodes.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED = - MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED - requestCodes.EXTRA_LAUNCH_WPSTORIES_MEDIA_PICKER_REQUESTED = - MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_MEDIA_PICKER_REQUESTED - // we're handling EXTRA_MEDIA_URIS at the app level (not at the Stories library level) - // hence we set the requestCode to UNUSED - requestCodes.EXTRA_MEDIA_URIS = UNUSED_KEY - } - - override fun showProvidedMediaPicker() { - mediaPickerLauncher.showStoriesPhotoPickerForResult( - this, - site - ) - } - - override fun providerHandlesOnActivityResult(): Boolean { - // lets the super class know we're handling media picking OnActivityResult - return true - } - - private fun handleMediaPickerIntentData(data: Intent) { - if (permissionsRequestForCameraInProgress) { - return - } - - when { - data.hasExtra(MediaPickerConstants.EXTRA_MEDIA_URIS) -> { - data.getStringArrayExtra(MediaPickerConstants.EXTRA_MEDIA_URIS)?.let { - val uriList: List = convertStringArrayIntoUrisList(it) - - if (uriList.isNotEmpty()) { - storyEditorMedia.addNewMediaItemsToEditorAsync(uriList, false) - } - } - } - data.hasExtra(MediaBrowserActivity.RESULT_IDS) -> { - val ids = ListUtils.fromLongArray( - data.getLongArrayExtra( - MediaBrowserActivity.RESULT_IDS - ) - ) - if (ids == null || ids.size == 0) { - return - } - storyEditorMedia.addExistingMediaToEditorAsync(WP_MEDIA_LIBRARY, ids) - } - data.hasExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED) -> { - // when coming from this entry point, we can start the analytics session - viewModel.onStoryComposerStartAnalyticsSession() - } - } - } - - private fun setupStoryEditorMediaObserver() { - storyEditorMedia.uiState.observe(this, - Observer { uiState: AddMediaToStoryPostUiState? -> - if (uiState != null) { - updateAddingMediaToStoryComposerProgressDialogState(uiState.progressDialogUiState) - if (uiState.editorOverlayVisibility) { - showLoading() - } else { - hideLoading() - } - } - } - ) - storyEditorMedia.snackBarMessage.observeEvent(this, - { messageHolder -> - findViewById(StoriesR.id.compose_loop_frame_layout)?.let { - WPSnackbar - .make( - it, - uiHelpers.getTextOfUiString(this, messageHolder.message), - Snackbar.LENGTH_SHORT - ) - .show() - } - } - ) - } - - // EditorMediaListener - override fun appendMediaFiles(mediaFiles: Map) { - viewModel.appendMediaFiles(mediaFiles) - } - - override fun getImmutablePost(): PostImmutableModel { - return Objects.requireNonNull(editPostRepository.getPost()!!) - } - - override fun syncPostObjectWithUiAndSaveIt(listener: OnPostUpdatedFromUIListener?) { - // TODO will implement when we support StoryPost editing - // updateAndSavePostAsync(listener) - // Ignore the result as we want to invoke the listener even when the PostModel was up-to-date - listener?.onPostUpdatedFromUI(null) - } - - override fun onMediaModelsCreatedFromOptimizedUris(oldUriToMediaFiles: Map) { - // no op - we're not doing any special handling while composing, only when saving in the UploadBridge - } - - override fun showVideoDurationLimitWarning(fileName: String) { - ToastUtils.showToast(this, R.string.error_media_video_duration_exceeds_limit, LONG) - } - - private fun updateAddingMediaToStoryComposerProgressDialogState(uiState: ProgressDialogUiState) { - addingMediaToEditorProgressDialog = progressDialogHelper - .updateProgressDialogState(this, addingMediaToEditorProgressDialog, uiState, uiHelpers) - } - - override fun getAuthHeaders(url: String): Map { - return authenticationUtils.getAuthHeaders(url) - } - - // region NotificationIntentLoader - override fun loadIntentForErrorNotification(): Intent { - val notificationIntent = Intent(applicationContext, StoryComposerActivity::class.java) - notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) - notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - notificationIntent.putExtra(WordPress.SITE, site) - // setup tracks NotificationType for Notification tracking. Note this doesn't use our interface. - val notificationType = NotificationType.STORY_SAVE_ERROR - notificationIntent.putExtra(ARG_NOTIFICATION_TYPE, notificationType) - return notificationIntent - } - - override fun loadPendingIntentForErrorNotificationDeletion(notificationId: Int): PendingIntent? { - return NotificationsProcessingService - .getPendingIntentForNotificationDismiss( - applicationContext, - notificationId, - NotificationType.STORY_SAVE_ERROR - ) - } - - override fun setupErrorNotificationBaseId(): Int { - return BASE_FRAME_MEDIA_ERROR_NOTIFICATION_ID - } - // endregion - - override fun loadMetadataForStory(index: StoryIndex): Bundle? { - val bundle = Bundle() - bundle.putSerializable(WordPress.SITE, site) - bundle.putInt(KEY_STORY_INDEX, index) - bundle.putInt(KEY_POST_LOCAL_ID, editPostRepository.id) - return bundle - } - - override fun onStoryDiscarded() { - val launchedFromGutenberg = intent.getBooleanExtra(KEY_LAUNCHED_FROM_GUTENBERG, false) - val storyDiscardedFromRetry = viewModel.onStoryDiscarded(!launchedFromGutenberg) - - if (launchedFromGutenberg || storyDiscardedFromRetry) { - setResult(Activity.RESULT_CANCELED) - } - finish() - } - - 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 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) { - story.frames[storyFrameIndex].id?.let { - frameIdsToRemove.add(it) - } - } - } - - private fun openPrepublishingBottomSheet() { - val fragment = supportFragmentManager.findFragmentByTag(PrepublishingBottomSheetFragment.TAG) - if (fragment == null) { - val prepublishingFragment = PrepublishingBottomSheetFragment.newInstance( - site = requireNotNull(site), - isPage = editPostRepository.isPage, - isStoryPost = true - ) - prepublishingFragment.show(supportFragmentManager, PrepublishingBottomSheetFragment.TAG) - } - } - - 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(siteLocalId, RemoteId(frameId.toLong()))) { - storiesPrefs.deleteSlideWithRemoteId(siteLocalId, RemoteId(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(siteLocalId, LocalId(frameId.toInt())) - } - } - } - - viewModel.onStorySaved() - // TODO add tracks - processStorySaving() - - val savedContentIntent = Intent() - val blockId = intent.extras?.getString(ARG_STORY_BLOCK_ID) - savedContentIntent.putExtra(ARG_STORY_BLOCK_ID, blockId) - - // check if story index has been passed through intent - var storyIndex = intent.getIntExtra(KEY_STORY_INDEX, DEFAULT_NONE_SELECTED) - if (storyIndex == 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 - // 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.buildJetpackStoryBlockStringFromStoryMediaFileData( - buildStoryMediaFileDataListFromStoryFrameIndexes(storyIndex) - ) - - savedContentIntent.putExtra(ARG_STORY_BLOCK_UPDATED_CONTENT, updatedStoryBlock) - setResult(Activity.RESULT_OK, savedContentIntent) - finish() - } else { - // assume this is a new Post, and proceed to PrePublish bottom sheet - viewModel.onStorySaveButtonPressed() - } - } - - private fun buildStoryMediaFileDataListFromStoryFrameIndexes( - storyIndex: StoryIndex - ): ArrayList { - 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 - // 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 = buildStoryMediaFileDataForTemporarySlide( - frame, - assignedTempId - ) - frame.id = storyMediaFileData.id - storyMediaFileDataList.add(storyMediaFileData) - } - // 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 { - if (it.startsWith(TEMPORARY_ID_PREFIX)) { - val storyMediaFileData = buildStoryMediaFileDataForTemporarySlide( - frame, - it - ) - storyMediaFileDataList.add(storyMediaFileData) - } else { - site?.let { site -> - val mediaModel = mediaStore.getSiteMediaWithId(site, it.toLong()) - val mediaFile = fluxCUtilsWrapper.mediaFileFromMediaModel(mediaModel) - mediaFile?.let { mediafile -> - mediaFile.alt = StoryFrameItem.getAltTextFromFrameAddedViews(frame) - mediaModel?.alt = mediaFile.alt - val storyMediaFileData = - saveStoryGutenbergBlockUseCase.buildMediaFileDataWithTemporaryId( - mediaFile = mediafile, - temporaryId = assignedTempId - ) - frame.id = storyMediaFileData.id - storyMediaFileDataList.add(storyMediaFileData) - } - } - } - } - } - } - } - return storyMediaFileDataList - } - - private fun buildStoryMediaFileDataForTemporarySlide(frame: StoryFrameItem, tempId: String): StoryMediaFileData { - return 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) - ) - } - - override fun onSubmitButtonClicked(publishPost: PublishPost) { - viewModel.onSubmitButtonClicked() - } - - 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) - } - } - } - - @Suppress("unused", "UNUSED_PARAMETER") - @Subscribe(threadMode = ThreadMode.MAIN) - fun onStoryLoadEnd(event: StoryLoadEnd) { - // once the Story has been loaded by the Composer, we should mark the composing session start as the - // UI is ready to receive user's input - viewModel.onStoryComposerStartAnalyticsSession() - } -} 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 deleted file mode 100644 index de85724d229e..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryComposerViewModel.kt +++ /dev/null @@ -1,197 +0,0 @@ -package org.wordpress.android.ui.stories - -import android.net.Uri -import android.os.Bundle -import android.webkit.URLUtil -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LifecycleRegistry -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModel -import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult -import org.wordpress.android.WordPress -import org.wordpress.android.fluxc.Dispatcher -import org.wordpress.android.fluxc.generated.PostActionBuilder -import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId -import org.wordpress.android.fluxc.model.PostImmutableModel -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.push.NotificationType -import org.wordpress.android.ui.notifications.SystemNotificationsTracker -import org.wordpress.android.ui.posts.EditPostRepository -import org.wordpress.android.ui.posts.PostEditorAnalyticsSession -import org.wordpress.android.ui.posts.PostEditorAnalyticsSession.Outcome.CANCEL -import org.wordpress.android.ui.posts.PostEditorAnalyticsSession.Outcome.PUBLISH -import org.wordpress.android.ui.posts.PostEditorAnalyticsSession.Outcome.SAVE -import org.wordpress.android.ui.posts.PostEditorAnalyticsSessionWrapper -import org.wordpress.android.ui.posts.SavePostToDbUseCase -import org.wordpress.android.ui.stories.StoryComposerActivity.Companion.STATE_KEY_ORIGINAL_STORY_SAVE_RESULT -import org.wordpress.android.ui.stories.usecase.SetUntitledStoryTitleIfTitleEmptyUseCase -import org.wordpress.android.util.AppLog -import org.wordpress.android.util.AppLog.T -import org.wordpress.android.util.helpers.MediaFile -import org.wordpress.android.viewmodel.Event -import org.wordpress.android.viewmodel.SingleLiveEvent -import javax.inject.Inject - -class StoryComposerViewModel @Inject constructor( - private val systemNotificationsTracker: SystemNotificationsTracker, - private val saveInitialPostUseCase: SaveInitialPostUseCase, - private val savePostToDbUseCase: SavePostToDbUseCase, - private val setUntitledStoryTitleIfTitleEmptyUseCase: SetUntitledStoryTitleIfTitleEmptyUseCase, - private val postEditorAnalyticsSessionWrapper: PostEditorAnalyticsSessionWrapper, - private val dispatcher: Dispatcher -) : ViewModel() { - private val lifecycleOwner = object : LifecycleOwner { - val lifecycleRegistry = LifecycleRegistry(this) - override val lifecycle: Lifecycle = lifecycleRegistry - } - - private lateinit var editPostRepository: EditPostRepository - private lateinit var site: SiteModel - private var postEditorAnalyticsSession: PostEditorAnalyticsSession? = null - private var originalIntentStorySaveResult: StorySaveResult? = null - - private val _mediaFilesUris = MutableLiveData>() - val mediaFilesUris: LiveData> = _mediaFilesUris - - private val _openPrepublishingBottomSheet = SingleLiveEvent>() - val openPrepublishingBottomSheet = _openPrepublishingBottomSheet - - private val _submitButtonClicked = SingleLiveEvent>() - val submitButtonClicked = _submitButtonClicked - - init { - lifecycleOwner.lifecycleRegistry.currentState = Lifecycle.State.CREATED - } - - private val _trackEditorCreatedPost = MutableLiveData>() - val trackEditorCreatedPost: LiveData> = _trackEditorCreatedPost - - @Suppress("LongParameterList") - fun start( - site: SiteModel, - editPostRepository: EditPostRepository, - postId: LocalId, - postEditorAnalyticsSession: PostEditorAnalyticsSession?, - notificationType: NotificationType?, - originalStorySaveResult: StorySaveResult? - ): Boolean { - this.editPostRepository = editPostRepository - this.site = site - this.originalIntentStorySaveResult = originalStorySaveResult - - notificationType?.let { - systemNotificationsTracker.trackTappedNotification(it) - } - - if (postId.value == 0) { - // Create a new post - saveInitialPostUseCase.saveInitialPost(editPostRepository, site) - // Bump post created analytics only once, first time the editor is opened - _trackEditorCreatedPost.postValue(Event(Unit)) - } else { - editPostRepository.loadPostByLocalPostId(postId.value) - } - - // Ensure we have a valid post - if (!editPostRepository.hasPost()) { - AppLog.e(T.EDITOR, "StoryComposerViewModel's EditPostRepository has no Post loaded: " + postId.value) - return false - } - - setupPostEditorAnalyticsSession(postEditorAnalyticsSession) - - lifecycleOwner.lifecycleRegistry.currentState = Lifecycle.State.STARTED - updateStoryPostWithChanges() - - return true - } - - private fun setupPostEditorAnalyticsSession(postEditorAnalyticsSession: PostEditorAnalyticsSession?) { - this.postEditorAnalyticsSession = postEditorAnalyticsSession ?: createPostEditorAnalyticsSessionTracker( - editPostRepository.getPost(), - site - ) - } - - private fun createPostEditorAnalyticsSessionTracker( - post: PostImmutableModel?, - site: SiteModel? - ): PostEditorAnalyticsSession { - return postEditorAnalyticsSessionWrapper.getNewPostEditorAnalyticsSession( - PostEditorAnalyticsSession.Editor.WP_STORIES_CREATOR, - post, site, true - ) - } - - fun onStoryComposerStartAnalyticsSession() { - this.postEditorAnalyticsSession?.start(null, null, null) - } - - fun onStoryComposerAnalyticsSessionStartTimeReset() { - this.postEditorAnalyticsSession?.resetStartTime() - } - - fun writeToBundle(outState: Bundle) { - outState.putSerializable(WordPress.SITE, site) - outState.putInt(StoryComposerActivity.STATE_KEY_POST_LOCAL_ID, editPostRepository.id) - outState.putSerializable(StoryComposerActivity.STATE_KEY_EDITOR_SESSION_DATA, postEditorAnalyticsSession) - outState.putParcelable(STATE_KEY_ORIGINAL_STORY_SAVE_RESULT, originalIntentStorySaveResult) - } - - fun onStorySaved() { - postEditorAnalyticsSession?.setOutcome(SAVE) - } - - // returns true if user is discarding a Story out of a save retry (error handling state) - // returns false otherwise - fun onStoryDiscarded(deleteDiscardedPost: Boolean): Boolean { - if (deleteDiscardedPost) { - // delete empty post from database - dispatcher.dispatch(PostActionBuilder.newRemovePostAction(editPostRepository.getEditablePost())) - } - postEditorAnalyticsSession?.setOutcome(CANCEL) - - originalIntentStorySaveResult?.let { - return (!it.isSuccess() || it.isRetry) - } ?: return false - } - - private fun updateStoryPostWithChanges() { - editPostRepository.postChanged.observe(lifecycleOwner, Observer { - savePostToDbUseCase.savePostToDb(editPostRepository, site) - }) - } - - fun appendMediaFiles(mediaFiles: Map) { - val uriList = ArrayList() - for ((key) in mediaFiles.entries) { - val url = if (URLUtil.isNetworkUrl(key)) { - key - } else { - "file://$key" - } - uriList.add(Uri.parse(url)) - } - - _mediaFilesUris.postValue(uriList) - } - - fun onStorySaveButtonPressed() { - _openPrepublishingBottomSheet.postValue(Event(Unit)) - } - - fun onSubmitButtonClicked() { - setUntitledStoryTitleIfTitleEmptyUseCase.setUntitledStoryTitleIfTitleEmpty(editPostRepository) - postEditorAnalyticsSession?.setOutcome(PUBLISH) - _submitButtonClicked.postValue(Event(Unit)) - } - - override fun onCleared() { - super.onCleared() - lifecycleOwner.lifecycleRegistry.currentState = Lifecycle.State.DESTROYED - postEditorAnalyticsSession?.end() - } -} 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 deleted file mode 100644 index 3b0e382e2c7f..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryRepositoryWrapper.kt +++ /dev/null @@ -1,24 +0,0 @@ -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 - -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) - - fun getStoryAtIndex(index: StoryIndex) = StoryRepository.getStoryAtIndex(index) - fun getImmutableStories() = StoryRepository.getImmutableStories() - fun getCurrentStorySaveProgress(storyIndex: StoryIndex, oneItemActualProgress: Float = 0.0F) = - StoryRepository.getCurrentStorySaveProgress(storyIndex, oneItemActualProgress) - - fun findStoryContainingStoryFrameItemsByIds(ids: ArrayList) = - StoryRepository.findStoryContainingStoryFrameItemsByIds(ids) -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryTitleHeaderView.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryTitleHeaderView.kt deleted file mode 100644 index 5fb411ef704a..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoryTitleHeaderView.kt +++ /dev/null @@ -1,57 +0,0 @@ -package org.wordpress.android.ui.stories - -import android.content.Context -import android.text.Editable -import android.text.TextWatcher -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.FrameLayout -import org.wordpress.android.R -import org.wordpress.android.databinding.PrepublishingStoryTitleListItemBinding -import org.wordpress.android.ui.posts.prepublishing.home.PrepublishingHomeItemUiState.StoryTitleUiState -import org.wordpress.android.ui.utils.UiHelpers -import org.wordpress.android.util.extensions.focusAndShowKeyboard -import org.wordpress.android.util.image.ImageManager -import org.wordpress.android.util.image.ImageType - -class StoryTitleHeaderView @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0 -) : FrameLayout(context, attrs, defStyleAttr) { - private val thumbnailCornerRadius = - context.resources.getDimension(R.dimen.prepublishing_site_blavatar_corner_radius) - .toInt() - - fun init(uiHelpers: UiHelpers, imageManager: ImageManager, uiState: StoryTitleUiState) { - with(PrepublishingStoryTitleListItemBinding.inflate(LayoutInflater.from(context), this, true)) { - imageManager.loadImageWithCorners( - storyThumbnail, - ImageType.IMAGE, - uiState.storyThumbnailUrl, - thumbnailCornerRadius - ) - - uiState.storyTitle?.let { title -> - storyTitle.setText(uiHelpers.getTextOfUiString(context, title)) - storyTitle.setSelection(title.text.length) - } - - storyTitle.focusAndShowKeyboard() - - storyTitleContent.setOnClickListener { - storyTitle.focusAndShowKeyboard() - } - - storyTitle.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} - override fun afterTextChanged(view: Editable?) { - view?.let { - uiState.onStoryTitleChanged.invoke(it.toString()) - } - } - }) - } - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroDialogFragment.kt deleted file mode 100644 index 9067133bfc45..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroDialogFragment.kt +++ /dev/null @@ -1,92 +0,0 @@ -package org.wordpress.android.ui.stories.intro - -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import androidx.lifecycle.ViewModelProvider -import org.wordpress.android.R -import org.wordpress.android.WordPress -import org.wordpress.android.databinding.StoriesIntroDialogFragmentBinding -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.ui.ActivityLauncher -import org.wordpress.android.ui.photopicker.MediaPickerLauncher -import org.wordpress.android.util.extensions.getSerializableCompat -import org.wordpress.android.util.extensions.setStatusBarAsSurfaceColor -import javax.inject.Inject - -class StoriesIntroDialogFragment : DialogFragment() { - @Inject - lateinit var viewModelFactory: ViewModelProvider.Factory - - @Inject - internal lateinit var mediaPickerLauncher: MediaPickerLauncher - - private lateinit var viewModel: StoriesIntroViewModel - - companion object { - const val TAG = "STORIES_INTRO_DIALOG_FRAGMENT" - - @JvmStatic - fun newInstance(site: SiteModel?): StoriesIntroDialogFragment { - val args = Bundle() - if (site != null) { - args.putSerializable(WordPress.SITE, site) - } - return StoriesIntroDialogFragment().apply { arguments = args } - } - } - - override fun getTheme(): Int { - return R.style.FeatureAnnouncementDialogFragment - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val dialog = super.onCreateDialog(savedInstanceState) - viewModel = ViewModelProvider(this, viewModelFactory) - .get(StoriesIntroViewModel::class.java) - dialog.setStatusBarAsSurfaceColor() - return dialog - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.stories_intro_dialog_fragment, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - val site = requireArguments().getSerializableCompat(WordPress.SITE) - with(StoriesIntroDialogFragmentBinding.bind(view)) { - createStoryIntroButton.setOnClickListener { viewModel.onCreateStoryButtonPressed() } - storiesIntroBackButton.setOnClickListener { viewModel.onBackButtonPressed() } - - storyImageFirst.setOnClickListener { viewModel.onStoryPreviewTapped1() } - storyImageSecond.setOnClickListener { viewModel.onStoryPreviewTapped2() } - } - viewModel.onCreateButtonClicked.observe(this) { - activity?.let { - mediaPickerLauncher.showStoriesPhotoPickerForResultAndTrack(it, site) - } - dismiss() - } - - viewModel.onDialogClosed.observe(this) { - dismiss() - } - - viewModel.onStoryOpenRequested.observe(this) { storyUrl -> - ActivityLauncher.openUrlExternal(context, storyUrl) - } - - viewModel.start() - } - - override fun onAttach(context: Context) { - super.onAttach(context) - (requireActivity().applicationContext as WordPress).component().inject(this) - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroViewModel.kt deleted file mode 100644 index 4b9f5ce45fd5..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroViewModel.kt +++ /dev/null @@ -1,63 +0,0 @@ -package org.wordpress.android.ui.stories.intro - -import androidx.lifecycle.LiveData -import kotlinx.coroutines.CoroutineDispatcher -import org.wordpress.android.analytics.AnalyticsTracker.Stat -import org.wordpress.android.modules.UI_THREAD -import org.wordpress.android.ui.prefs.AppPrefsWrapper -import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper -import org.wordpress.android.viewmodel.ScopedViewModel -import org.wordpress.android.viewmodel.SingleLiveEvent -import javax.inject.Inject -import javax.inject.Named - -class StoriesIntroViewModel @Inject constructor( - private val analyticsTrackerWrapper: AnalyticsTrackerWrapper, - private val appPrefsWrapper: AppPrefsWrapper, - @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher -) : ScopedViewModel(mainDispatcher) { - private val _onDialogClosed = SingleLiveEvent() - val onDialogClosed: LiveData = _onDialogClosed - - private val _onCreateButtonClicked = SingleLiveEvent() - val onCreateButtonClicked: LiveData = _onCreateButtonClicked - - private val _onStoryOpenRequested = SingleLiveEvent() - val onStoryOpenRequested: LiveData = _onStoryOpenRequested - - private var isStarted = false - - fun start() { - if (isStarted) return - isStarted = true - - analyticsTrackerWrapper.track(Stat.STORY_INTRO_SHOWN) - } - - fun onBackButtonPressed() { - analyticsTrackerWrapper.track(Stat.STORY_INTRO_DISMISSED) - _onDialogClosed.call() - } - - fun onCreateStoryButtonPressed() { - analyticsTrackerWrapper.track(Stat.STORY_INTRO_CREATE_STORY_BUTTON_TAPPED) - - appPrefsWrapper.shouldShowStoriesIntro = false - - _onCreateButtonClicked.call() - } - - fun onStoryPreviewTapped1() { - _onStoryOpenRequested.value = STORY_URL_1 + STORY_FULLSCREEN_URL_PARAMS - } - - fun onStoryPreviewTapped2() { - _onStoryOpenRequested.value = STORY_URL_2 + STORY_FULLSCREEN_URL_PARAMS - } - - companion object { - private const val STORY_URL_1 = "https://wpstories.wordpress.com/2020/12/02/story-demo-01/" - private const val STORY_URL_2 = "https://wpstories.wordpress.com/2020/12/02/story-demo-02/" - private const val STORY_FULLSCREEN_URL_PARAMS = "?wp-story-load-in-fullscreen=true&wp-story-play-on-load=true" - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMedia.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMedia.kt deleted file mode 100644 index 1a91710c5bc6..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryEditorMedia.kt +++ /dev/null @@ -1,116 +0,0 @@ -package org.wordpress.android.ui.stories.media - -import android.net.Uri -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import org.wordpress.android.R -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.modules.UI_THREAD -import org.wordpress.android.ui.pages.SnackbarMessageHolder -import org.wordpress.android.ui.posts.ProgressDialogUiState -import org.wordpress.android.ui.posts.ProgressDialogUiState.HiddenProgressDialog -import org.wordpress.android.ui.posts.ProgressDialogUiState.VisibleProgressDialog -import org.wordpress.android.ui.posts.editor.media.AddExistingMediaSource -import org.wordpress.android.ui.posts.editor.media.AddExistingMediaToPostUseCase -import org.wordpress.android.ui.posts.editor.media.AddLocalMediaToPostUseCase -import org.wordpress.android.ui.posts.editor.media.EditorMediaListener -import org.wordpress.android.ui.stories.media.StoryEditorMedia.AddMediaToStoryPostUiState.AddingMediaToStoryIdle -import org.wordpress.android.ui.stories.media.StoryEditorMedia.AddMediaToStoryPostUiState.AddingMultipleMediaToStory -import org.wordpress.android.ui.stories.media.StoryEditorMedia.AddMediaToStoryPostUiState.AddingSingleMediaToStory -import org.wordpress.android.ui.utils.UiString.UiStringRes -import org.wordpress.android.viewmodel.Event -import javax.inject.Inject -import javax.inject.Named -import kotlin.coroutines.CoroutineContext - -class StoryEditorMedia @Inject constructor( - private val addLocalMediaToPostUseCase: AddLocalMediaToPostUseCase, - private val addExistingMediaToPostUseCase: AddExistingMediaToPostUseCase, - @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher -) : CoroutineScope { - // region Fields - private var job: Job = Job() - - override val coroutineContext: CoroutineContext - get() = mainDispatcher + job - - private lateinit var site: SiteModel - private lateinit var editorMediaListener: EditorMediaListener - - private val _uiState: MutableLiveData = MutableLiveData() - val uiState: LiveData = _uiState - - private val _snackBarMessage = MutableLiveData>() - val snackBarMessage = _snackBarMessage as LiveData> - - fun start(site: SiteModel, editorMediaListener: EditorMediaListener) { - this.site = site - this.editorMediaListener = editorMediaListener - _uiState.value = AddingMediaToStoryIdle - } - - fun addNewMediaItemsToEditorAsync(uriList: List, freshlyTaken: Boolean) { - launch { - _uiState.value = if (uriList.size > 1) { - AddingMultipleMediaToStory - } else { - AddingSingleMediaToStory - } - val allMediaSucceed = addLocalMediaToPostUseCase.addNewMediaToEditorAsync( - uriList, - site, - freshlyTaken, - editorMediaListener, - false // don't start upload for StoryComposer, that'll be all started - // when finished composing - ) - if (!allMediaSucceed) { - _snackBarMessage.value = Event(SnackbarMessageHolder(UiStringRes(R.string.gallery_error))) - } - _uiState.value = AddingMediaToStoryIdle - } - } - // endregion - - fun addExistingMediaToEditorAsync(source: AddExistingMediaSource, mediaIdList: List) { - launch { - addExistingMediaToPostUseCase.addMediaExistingInRemoteToEditorAsync( - site, - source, - mediaIdList, - editorMediaListener - ) - } - } - - fun cancelAddMediaToEditorActions() { - job.cancel() - } - - sealed class AddMediaToStoryPostUiState( - val editorOverlayVisibility: Boolean, - val progressDialogUiState: ProgressDialogUiState - ) { - /** - * Adding multiple media items at once can take several seconds on slower devices, so we show a blocking - * progress dialog in this situation - otherwise the user could accidentally back out of the process - * before all items were added - */ - object AddingMultipleMediaToStory : AddMediaToStoryPostUiState( - editorOverlayVisibility = true, - progressDialogUiState = VisibleProgressDialog( - messageString = UiStringRes(R.string.add_media_progress), - cancelable = false, - indeterminate = true - ) - ) - - object AddingSingleMediaToStory : AddMediaToStoryPostUiState(true, HiddenProgressDialog) - - object AddingMediaToStoryIdle : AddMediaToStoryPostUiState(false, HiddenProgressDialog) - } -} 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 deleted file mode 100644 index 77c7c52fb953..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/media/StoryMediaSaveUploadBridge.kt +++ /dev/null @@ -1,275 +0,0 @@ -package org.wordpress.android.ui.stories.media - -import android.content.Context -import android.net.Uri -import androidx.lifecycle.DefaultLifecycleObserver -import androidx.lifecycle.LifecycleOwner -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 -import kotlinx.coroutines.launch -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode.MAIN -import org.wordpress.android.R -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 -import org.wordpress.android.modules.UI_THREAD -import org.wordpress.android.ui.posts.EditPostActivity.OnPostUpdatedFromUIListener -import org.wordpress.android.ui.posts.EditPostRepository -import org.wordpress.android.ui.posts.PostUtilsWrapper -import org.wordpress.android.ui.posts.SavePostToDbUseCase -import org.wordpress.android.ui.posts.editor.media.AddLocalMediaToPostUseCase -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.TempId -import org.wordpress.android.ui.uploads.UploadServiceFacade -import org.wordpress.android.util.EventBusWrapper -import org.wordpress.android.util.NetworkUtilsWrapper -import org.wordpress.android.util.ToastUtils -import org.wordpress.android.util.ToastUtils.Duration.LONG -import org.wordpress.android.util.extensions.getSerializableCompat -import org.wordpress.android.util.helpers.MediaFile -import javax.inject.Inject -import javax.inject.Named -import kotlin.coroutines.CoroutineContext - -/* - * StoryMediaSaveUploadBridge listens for StorySaveResult events triggered from the StorySaveService, and - * then transforms its result data into something the UploadService can use to upload the Story frame media - * first, then obtain the media Ids and collect them, and finally create a Post with the Story block - * with the obtained media Ids. - * This is different than uploading media to a regular Post because we don't need to replace the URLs for final Urls as - * we do in Aztec / Gutenberg. - */ -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, - private val eventBusWrapper: EventBusWrapper, - private val storyRepositoryWrapper: StoryRepositoryWrapper, - @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher -) : CoroutineScope, DefaultLifecycleObserver { - // region Fields - private var job: Job = Job() - private lateinit var appContext: Context - - override val coroutineContext: CoroutineContext - get() = mainDispatcher + job - - @Inject - lateinit var editPostRepository: EditPostRepository - - @Inject - lateinit var storiesTrackerHelper: StoriesTrackerHelper - - @Inject - lateinit var saveStoryGutenbergBlockUseCase: SaveStoryGutenbergBlockUseCase - - override fun onCreate(owner: LifecycleOwner) { - eventBusWrapper.register(this) - } - - override fun onDestroy(owner: LifecycleOwner) { - // note: not sure whether this is ever going to get called if we attach it to the lifecycle of the Application - // class, but leaving it here prepared for the case when this class is attached to some other LifeCycleOwner - // other than the Application. - cancelAddMediaToEditorActions() - eventBusWrapper.unregister(this) - } - - fun init(context: Context) { - appContext = context - } - - // 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 = storyRepositoryWrapper.getStoryAtIndex(saveResult.storyIndex).frames - addNewMediaItemsInStoryFramesToPostAsync(site, frames, saveResult.isEditMode) - } - - private fun addNewMediaItemsInStoryFramesToPostAsync( - site: SiteModel, - frames: List, - isEditMode: Boolean - ) { - val uriList = frames.map { Uri.fromFile(it.composedFrameFile) } - - // this is similar to addNewMediaItemsToEditorAsync in EditorMedia - launch { - val localEditorMediaListener = object : EditorMediaListener { - override fun appendMediaFiles(mediaFiles: Map) { - if (!isEditMode) { - saveStoryGutenbergBlockUseCase.assignAltOnEachMediaFile(frames, ArrayList(mediaFiles.values)) - 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 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 - // find the MediaModel for a given Uri from composedFrameFile - for (frame in 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 oldUri = Uri.fromFile(frame.composedFrameFile) - val mediaModel = oldUriToMediaFiles.get(oldUri) - mediaModel?.let { - val oldTemporaryId = frame.id ?: "" - frame.id = it.id.toString() - - // set alt text on MediaModel too - mediaModel.alt = StoryFrameItem.getAltTextFromFrameAddedViews(frame) - - // 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( - 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 - LocalId(it.id), - frame - ) - - // for editMode, we'll need to tell the Gutenberg Editor to replace their mediaFiles - // ids with the new MediaModel local ids are created so, broadcasting the event. - if (isEditMode) { - // finally send the event that this frameId has changed - eventBusWrapper.postSticky( - StoryFrameMediaModelCreatedEvent( - oldTemporaryId, - it.id, - oldUri.toString(), - frame - ) - ) - } - } - } - } - - override fun showVideoDurationLimitWarning(fileName: String) { - ToastUtils.showToast( - appContext, - R.string.error_media_video_duration_exceeds_limit, - LONG - ) - } - } - - addLocalMediaToPostUseCase.addNewMediaToEditorAsync( - uriList, - site, - freshlyTaken = false, // we don't care about this - editorMediaListener = localEditorMediaListener, - doUploadAfterAdding = true, - trackEvent = false // Already tracked event when media were first added to the story - ) - - // 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, - "StoryMediaSaveUploadBridge#addNewMediaItemsInStoryFramesToPostAsync" - ) - // 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. - } - } - } - } - // endregion - - private fun cancelAddMediaToEditorActions() { - job.cancel() - } - - @Subscribe(sticky = true, threadMode = MAIN) - fun onEventMainThread(event: StorySaveResult) { - // track event - storiesTrackerHelper.trackStorySaveResultEvent(event) - - event.metadata?.let { - val site = requireNotNull(it.getSerializableCompat(WordPress.SITE)) - 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) && !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 MySiteFragment for details. - eventBusWrapper.removeStickyEvent(event) - editPostRepository.loadPostByLocalPostId(it.getInt(StoryComposerActivity.KEY_POST_LOCAL_ID)) - // media upload tracking already in addLocalMediaToPostUseCase.addNewMediaToEditorAsync - addNewStoryFrameMediaItemsToPostAndUploadAsync(site, event) - } - } - } - - private fun isStorySavingComplete(event: StorySaveResult): Boolean { - return (event.isSuccess() && - event.frameSaveResult.size == storyRepositoryWrapper.getStoryAtIndex(event.storyIndex).frames.size) - } - - 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 deleted file mode 100644 index 2c673a922c9e..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/prefs/StoriesPrefs.kt +++ /dev/null @@ -1,264 +0,0 @@ -package org.wordpress.android.ui.stories.prefs - -import android.annotation.SuppressLint -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 -import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId -import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class StoriesPrefs @Inject constructor( - private val context: Context -) { - companion object { - 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 { - return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + - KEY_PREFIX_REMOTE_MEDIA_ID + mediaId.value.toString() - } - - private fun buildSlideKey(siteId: Long, mediaId: LocalId): String { - return KEY_PREFIX_STORIES_SLIDE_ID + siteId.toString() + "-" + - 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 - } - - private 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) - } - - private fun checkSlideIdExists(siteId: Long, tempId: TempId): Boolean { - val slideIdKey = buildSlideKey(siteId, tempId) - return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) - } - - private fun checkSlideIdExists(siteId: Long, localId: LocalId): Boolean { - val slideIdKey = buildSlideKey(siteId, localId) - return PreferenceManager.getDefaultSharedPreferences(context).contains(slideIdKey) - } - - private fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: RemoteId): Boolean { - return checkSlideOriginalBackgroundMediaExists(getSlideWithRemoteId(siteId, mediaId)) - } - - private fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: TempId): Boolean { - return checkSlideOriginalBackgroundMediaExists(getSlideWithTempId(siteId, mediaId)) - } - - private fun checkSlideOriginalBackgroundMediaExists(siteId: Long, mediaId: LocalId): Boolean { - return checkSlideOriginalBackgroundMediaExists(getSlideWithLocalId(siteId, mediaId)) - } - - 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 -> - if (source is FileBackgroundSource) { - source.file?.let { - return it.exists() - } ?: return false - } else if (source is UriBackgroundSource) { - source.contentUri?.let { - return isUriAccessible(it) - } ?: return false - } - } - } - return false - } - - @Suppress("ReturnCount", "PrintStackTrace", "ForbiddenComment") - 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 - return true - } - try { - context.contentResolver.openInputStream(uri)?.let { - it.close() - return true - } - } catch (e: java.lang.Exception) { - e.printStackTrace() - } - return false - } - - private fun saveSlide(slideIdKey: String, storySlideJson: String) { - val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() - editor.putString(slideIdKey, storySlideJson) - editor.apply() - } - - fun isValidSlide(siteId: Long, mediaId: RemoteId): Boolean { - return checkSlideIdExists(siteId, mediaId) && - 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) - } - - 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: LocalId): StoryFrameItem? { - val jsonSlide = getSlideJson(buildSlideKey(siteId, mediaId)) - jsonSlide?.let { - return StorySerializerUtils.deserializeStoryFrameItem(jsonSlide) - } ?: 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)) - } - - fun saveSlideWithRemoteId(siteId: Long, mediaId: RemoteId, storyFrameItem: StoryFrameItem) { - val slideIdKey = buildSlideKey(siteId, mediaId) - 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() - editor.remove(slideIdKey) - editor.apply() - } - - fun deleteSlideWithRemoteId(siteId: Long, mediaId: RemoteId) { - val slideIdKey = buildSlideKey(siteId, mediaId) - PreferenceManager.getDefaultSharedPreferences(context).edit().apply { - remove(slideIdKey) - apply() - } - } - - // 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 - ) { - // look for the slide saved with the local id key (mediaFile.id), and re-convert to mediaId. - getSlideWithLocalId( - localSiteId, - LocalId(localIdKey) - )?.let { - it.id = remoteIdKey.toString() // update the StoryFrameItem id to hold the same value as the remote mediaID - saveSlideWithRemoteId( - localSiteId, - RemoteId(remoteIdKey), // use the new mediaId as key - it - ) - // now delete the old entry - deleteSlideWithLocalId( - localSiteId, - LocalId(localIdKey) - ) - } - } - - // 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 - ): 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 deleted file mode 100644 index b65650469a58..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/LoadStoryFromStoriesPrefsUseCase.kt +++ /dev/null @@ -1,164 +0,0 @@ -package org.wordpress.android.ui.stories.usecase - -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.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.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 -import org.wordpress.android.util.StringUtils -import javax.inject.Inject - -@Reusable -class LoadStoryFromStoriesPrefsUseCase @Inject constructor( - private val storyRepositoryWrapper: StoryRepositoryWrapper, - private val storiesPrefs: StoriesPrefs, - private val mediaStore: MediaStore -) { - @Suppress("UNCHECKED_CAST") - fun getMediaIdsFromStoryBlockBridgeMediaFiles(mediaFiles: ArrayList): ArrayList { - val mediaIds = ArrayList() - for (mediaFile in mediaFiles) { - val rawIdField = (mediaFile as HashMap)["id"] - if (rawIdField is String && rawIdField.startsWith(TEMPORARY_ID_PREFIX)) { - mediaIds.add(rawIdField) - } else { - val mediaIdLong = rawIdField - .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 this is not a remote nor a local / temporary slide, 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 - } - - 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 storyIndex = StoryRepository.DEFAULT_NONE_SELECTED - storyRepositoryWrapper.loadStory(storyIndex) - storyIndex = storyRepositoryWrapper.getCurrentStoryIndex() - - // hold media that we'll need to retrieve from Site's media to use its remote url (flattened media) - val tmpMediaIdsLong = ArrayList() - - for (mediaId in mediaIds) { - // let's check if this is a temporary id - if (mediaId.startsWith(TEMPORARY_ID_PREFIX)) { - storiesPrefs.getSlideWithTempId( - site.getId().toLong(), - TempId(mediaId) - )?.let { - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(it) - } - } else { - storiesPrefs.getSlideWithRemoteId( - site.getId().toLong(), - RemoteId(mediaId.toLong()) - )?.let { - // verify the background media referenced here is still valid for editing, otherwise - // use the actual uploaded flattened media for safety - if (storiesPrefs.isValidSlide(site.getId().toLong(), RemoteId(mediaId.toLong()))) { - // just add the deserialized slide, given it's perfectly valid - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(it) - } else { - // add to the list of slides we need to retrieve a flattened media url for - tmpMediaIdsLong.add(mediaId.toLong()) - } - } ?: tmpMediaIdsLong.add(mediaId.toLong()) - } - } - - // if we collected media that we couldn't find locally, let's retrieve the remote urls for these all in one go - val result: ReCreateStoryResult - if (!tmpMediaIdsLong.isEmpty()) { - result = recreateStoryFrameItemsFromRemoteSiteFlattenedMediaUrls(storyIndex, site, tmpMediaIdsLong) - } else { - val noSlidesLoaded = storyRepositoryWrapper.getStoryAtIndex(storyIndex).frames.size == 0 - result = ReCreateStoryResult(storyIndex, allStorySlidesAreEditable = true, noSlidesLoaded) - } - return result - } - - private fun recreateStoryFrameItemsFromRemoteSiteFlattenedMediaUrls( - storyIndex: StoryIndex, - site: SiteModel, - mediaIds: ArrayList - ): ReCreateStoryResult { - // for this missing frame we'll create a new frame using the actual uploaded flattened media - val mediaModelList: List = mediaStore.getSiteMediaWithIds( - site, - mediaIds - ) - - for (mediaModel in mediaModelList) { - val storyFrameItem = StoryFrameItem.getNewStoryFrameItemFromUri( - Uri.parse(mediaModel.url), - mediaModel.isVideo - ) - storyFrameItem.id = mediaModel.mediaId.toString() - storyRepositoryWrapper.addStoryFrameItemToCurrentStory(storyFrameItem) - } - - val noSlidesLoaded = storyRepositoryWrapper.getStoryAtIndex(storyIndex).frames.size == 0 - return ReCreateStoryResult(storyIndex, allStorySlidesAreEditable = false, noSlidesLoaded) - } - - fun loadStoryFromMemoryOrRecreateFromPrefs(site: SiteModel, mediaFiles: ArrayList): ReCreateStoryResult { - val mediaIds = getMediaIdsFromStoryBlockBridgeMediaFiles( - mediaFiles - ) - val 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 match the order in which the media files were passed. - val 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, - val noSlidesLoaded: Boolean - ) -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/SetUntitledStoryTitleIfTitleEmptyUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/SetUntitledStoryTitleIfTitleEmptyUseCase.kt deleted file mode 100644 index 0538184f3997..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/SetUntitledStoryTitleIfTitleEmptyUseCase.kt +++ /dev/null @@ -1,21 +0,0 @@ -package org.wordpress.android.ui.stories.usecase - -import android.content.Context -import org.wordpress.android.R -import org.wordpress.android.ui.posts.EditPostRepository -import org.wordpress.android.ui.stories.StoryRepositoryWrapper -import javax.inject.Inject - -class SetUntitledStoryTitleIfTitleEmptyUseCase @Inject constructor( - private val storyRepositoryWrapper: StoryRepositoryWrapper, - private val updateStoryPostTitleUseCase: UpdateStoryPostTitleUseCase, - private val context: Context -) { - fun setUntitledStoryTitleIfTitleEmpty(editPostRepository: EditPostRepository) { - if (editPostRepository.title.isEmpty()) { - val untitledStoryTitle = context.resources.getString(R.string.untitled) - storyRepositoryWrapper.setCurrentStoryTitle(untitledStoryTitle) - updateStoryPostTitleUseCase.updateStoryTitle(untitledStoryTitle, editPostRepository) - } - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/UpdateStoryPostTitleUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/UpdateStoryPostTitleUseCase.kt deleted file mode 100644 index f1f45fe1cbf7..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/usecase/UpdateStoryPostTitleUseCase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.wordpress.android.ui.stories.usecase - -import dagger.Reusable -import org.wordpress.android.ui.posts.EditPostRepository -import javax.inject.Inject - -@Reusable -class UpdateStoryPostTitleUseCase @Inject constructor() { - fun updateStoryTitle(storyTitle: String, editPostRepository: EditPostRepository) { - editPostRepository.updateAsync({ postModel -> - postModel.setTitle(storyTitle) - true - }) - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadHandler.java b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadHandler.java index 2c46925798c5..278d0409c65e 100755 --- a/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadHandler.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/uploads/MediaUploadHandler.java @@ -22,7 +22,6 @@ import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.WPMediaUtils; import org.wordpress.android.util.analytics.AnalyticsUtils; -import org.wordpress.android.util.config.Mp4ComposerVideoOptimizationFeatureConfig; import java.util.ArrayList; import java.util.Collections; @@ -40,7 +39,6 @@ public class MediaUploadHandler implements UploadHandler, VideoOptim @Inject Dispatcher mDispatcher; @Inject SiteStore mSiteStore; - @Inject Mp4ComposerVideoOptimizationFeatureConfig mMp4ComposerVideoOptimizationFeatureConfig; MediaUploadHandler() { ((WordPress) WordPress.getContext().getApplicationContext()).component().inject(this); @@ -288,12 +286,7 @@ private void cancelUpload(MediaModel oneUpload, boolean delete) { private void prepareForUpload(@NonNull MediaModel media) { if (media.isVideo() && WPMediaUtils.isVideoOptimizationEnabled()) { addUniqueMediaToInProgressUploads(media); - - if (mMp4ComposerVideoOptimizationFeatureConfig.isEnabled()) { - new Mp4ComposerVideoOptimizer(media, this).start(); - } else { - new VideoOptimizer(media, this).start(); - } + new VideoOptimizer(media, this).start(); } else { dispatchUploadAction(media); } 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 86a4da36d608..8d72950dfa34 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,15 +9,12 @@ import org.wordpress.android.ui.media.services.MediaUploadReadyListener; 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.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); } @@ -29,10 +26,7 @@ public PostModel replaceMediaFileWithUrlInPost(@Nullable PostModel post, String boolean showAztecEditor = AppPrefs.isAztecEditorEnabled(); boolean showGutenbergEditor = AppPrefs.isGutenbergEditorEnabled(); - if (PostUtils.contentContainsWPStoryGutenbergBlocks(post.getContent())) { - mSaveStoryGutenbergBlockUseCase - .replaceLocalMediaIdsWithRemoteMediaIdsInPost(post, site, mediaFile); - } else if (showGutenbergEditor && PostUtils.contentContainsGutenbergBlocks(post.getContent())) { + if (showGutenbergEditor && PostUtils.contentContainsGutenbergBlocks(post.getContent())) { String siteUrl = site != null ? site.getUrl() : ""; post.setContent( PostUtils.replaceMediaFileWithUrlInGutenbergPost(post.getContent(), localMediaId, mediaFile, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/uploads/Mp4ComposerVideoOptimizer.java b/WordPress/src/main/java/org/wordpress/android/ui/uploads/Mp4ComposerVideoOptimizer.java deleted file mode 100644 index b5d7afc3d527..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/uploads/Mp4ComposerVideoOptimizer.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.wordpress.android.ui.uploads; - -import androidx.annotation.NonNull; - -import com.daasuu.mp4compose.composer.ComposerInterface; -import com.daasuu.mp4compose.composer.Listener; - -import org.wordpress.android.analytics.AnalyticsTracker; -import org.wordpress.android.fluxc.model.MediaModel; -import org.wordpress.android.ui.prefs.AppPrefs; -import org.wordpress.android.util.AppLog; -import org.wordpress.android.util.WPVideoUtils; -import org.wordpress.android.util.analytics.AnalyticsUtils; - -import java.util.Map; - -import static org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_VIDEO_CANT_OPTIMIZE; - -public class Mp4ComposerVideoOptimizer extends VideoOptimizerBase implements Listener { - public Mp4ComposerVideoOptimizer( - @NonNull MediaModel media, - @NonNull VideoOptimizationListener listener) { - super(media, listener); - } - - @Override - public void onStart() { - mStartTimeMS = System.currentTimeMillis(); - } - - @Override - public void onProgress(double progress) { - // this event fires quite often so we only call the listener when progress increases by 1% or more - // NOTE: progress can be -1 with Mp4Composer library - if (progress < 0) return; - - sendProgressIfNeeded((float) progress); - } - - @Override - public void onCompleted() { - trackVideoProcessingEvents(false, null); - selectMediaAndSendCompletionToListener(); - } - - @Override - public void onCanceled() { - AppLog.d(AppLog.T.MEDIA, "VideoOptimizer > stopped"); - } - - @Override - public void onFailed(@NonNull Exception exception) { - AppLog.e(AppLog.T.MEDIA, "VideoOptimizer > Can't optimize the video", exception); - trackVideoProcessingEvents(true, exception); - mListener.onVideoOptimizationCompleted(mMedia); - } - - @Override public void start() { - if (!arePathsValidated()) return; - - ComposerInterface composer = null; - - try { - composer = WPVideoUtils.getVideoOptimizationComposer( - mInputPath, - mOutputPath, - this, - AppPrefs.getVideoOptimizeWidth(), - AppPrefs.getVideoOptimizeQuality()); - } catch (Exception e) { - AppLog.w( - AppLog.T.MEDIA, - "VideoOptimizer > Exception while getting composer " + e.getMessage() - ); - composer = null; - } - - if (composer == null) { - AppLog.w(AppLog.T.MEDIA, "VideoOptimizer > null composer"); - Map properties = AnalyticsUtils.getMediaProperties(getContext(), true, - null, mInputPath); - properties.put("optimizer_lib", "mp4composer"); - AnalyticsTracker.track(MEDIA_VIDEO_CANT_OPTIMIZE, properties); - mListener.onVideoOptimizationCompleted(mMedia); - return; - } - - // setup done. We're ready to optimize! - composer.start(); - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/uploads/PostUploadHandler.java b/WordPress/src/main/java/org/wordpress/android/ui/uploads/PostUploadHandler.java index 9176a71fffcd..16b347394a4e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/uploads/PostUploadHandler.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/uploads/PostUploadHandler.java @@ -341,11 +341,9 @@ private void prepareUploadAnalytics(String postContent) { // loosely made knowing the other check ("contains blocks") is in place. // NOTE: added now first check if this post contains a WP Story and mark it created // like so. - PostUtils.contentContainsWPStoryGutenbergBlocks(mPost.getContent()) - ? SiteUtils.WP_STORIES_CREATOR_NAME - : (PostUtils.shouldShowGutenbergEditor( + PostUtils.shouldShowGutenbergEditor( mPost.isLocalDraft(), mPost.getContent(), selectedSite - ) ? SiteUtils.GB_EDITOR_NAME : SiteUtils.AZTEC_EDITOR_NAME)); + ) ? SiteUtils.GB_EDITOR_NAME : SiteUtils.AZTEC_EDITOR_NAME); } } if (hasGallery()) { @@ -690,8 +688,6 @@ public void onPostUploaded(OnPostUploaded event) { event.post, sCurrentUploadingPostAnalyticsProperties); sCurrentUploadingPostAnalyticsProperties.put(AnalyticsUtils.HAS_GUTENBERG_BLOCKS_KEY, PostUtils.contentContainsGutenbergBlocks(event.post.getContent())); - sCurrentUploadingPostAnalyticsProperties.put(AnalyticsUtils.HAS_WP_STORIES_BLOCKS_KEY, - PostUtils.contentContainsWPStoryGutenbergBlocks(event.post.getContent())); sCurrentUploadingPostAnalyticsProperties .put(AnalyticsUtils.PROMPT_ID, event.post.getAnsweredPromptId()); AnalyticsUtils.trackWithSiteDetails(Stat.EDITOR_PUBLISHED_POST, diff --git a/WordPress/src/main/java/org/wordpress/android/util/SiteUtils.java b/WordPress/src/main/java/org/wordpress/android/util/SiteUtils.java index f4f3a4549be8..c908f873d739 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/SiteUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/util/SiteUtils.java @@ -17,7 +17,6 @@ import org.wordpress.android.fluxc.store.SiteStore.DesignateMobileEditorPayload; import org.wordpress.android.fluxc.store.SiteStore.FetchSitesPayload; import org.wordpress.android.fluxc.store.SiteStore.SiteFilter; -import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalPhaseHelper; import org.wordpress.android.ui.plans.PlansConstants; import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.reader.utils.SiteAccessibilityInfo; @@ -32,9 +31,7 @@ public class SiteUtils { public static final String GB_EDITOR_NAME = "gutenberg"; public static final String AZTEC_EDITOR_NAME = "aztec"; - public static final String WP_STORIES_CREATOR_NAME = "wp_stories_creator"; public static final String WP_VIDEOPRESS_V5_JETPACK_VERSION = "8.5"; - public static final String WP_STORIES_JETPACK_VERSION = "9.1"; public static final String WP_CONTACT_INFO_JETPACK_VERSION = "8.5"; public static final String WP_FACEBOOK_EMBED_JETPACK_VERSION = "9.0"; public static final String WP_INSTAGRAM_EMBED_JETPACK_VERSION = "9.0"; @@ -320,11 +317,6 @@ public static boolean checkMinimalWordPressVersion(SiteModel site, String minVer return VersionUtils.checkMinimalVersion(site.getSoftwareVersion(), minVersion); } - public static boolean supportsStoriesFeature(SiteModel site, JetpackFeatureRemovalPhaseHelper helper) { - return site != null && (site.isWPCom() || checkMinimalJetpackVersion(site, WP_STORIES_JETPACK_VERSION)) - && helper.shouldShowStoryPost(); - } - public static boolean supportsContactInfoFeature(SiteModel site) { return site != null && (site.isWPCom() || checkMinimalJetpackVersion(site, WP_CONTACT_INFO_JETPACK_VERSION)); } diff --git a/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt b/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt index 9a44fe0ec0d3..5a4df6403e6e 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt @@ -4,7 +4,6 @@ import android.content.Context import androidx.annotation.DimenRes import dagger.Reusable import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalPhaseHelper import org.wordpress.android.ui.reader.utils.SiteAccessibilityInfo import javax.inject.Inject @@ -28,7 +27,4 @@ class SiteUtilsWrapper @Inject constructor(private val appContext: Context) { fun getSiteIconUrlOfResourceSize(site: SiteModel, @DimenRes sizeRes: Int): String { return SiteUtils.getSiteIconUrl(site, appContext.resources.getDimensionPixelSize(sizeRes)) } - fun supportsStoriesFeature(site: SiteModel?, helper: JetpackFeatureRemovalPhaseHelper): Boolean { - return SiteUtils.supportsStoriesFeature(site, helper) - } } diff --git a/WordPress/src/main/java/org/wordpress/android/util/WPVideoUtils.java b/WordPress/src/main/java/org/wordpress/android/util/WPVideoUtils.java index e2f28341984e..4c1294c5c068 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/WPVideoUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/util/WPVideoUtils.java @@ -2,17 +2,9 @@ import android.content.Context; import android.media.MediaCodecInfo; -import android.util.Size; import androidx.annotation.NonNull; -import com.daasuu.mp4compose.FillMode; -import com.daasuu.mp4compose.VideoFormatMimeType; -import com.daasuu.mp4compose.composer.ComposerInterface; -import com.daasuu.mp4compose.composer.ComposerProvider; -import com.daasuu.mp4compose.composer.ComposerUseCase.CompressVideo; -import com.daasuu.mp4compose.composer.Listener; -import com.daasuu.mp4compose.composer.Mp4ComposerBasic; import org.m4m.AudioFormat; import org.m4m.MediaComposer; @@ -115,57 +107,6 @@ public static MediaComposer getVideoOptimizationComposer(@NonNull Context ctx, @ return mediaComposer; } - // TODO: this should replace the equivalent function used for m4m lib once we fully introduce the Mp4Composer lib - public static ComposerInterface getVideoOptimizationComposer(@NonNull String inputFile, - @NonNull String outFile, - @NonNull Listener listener, - int width, int bitrate) { - // NOTE: the parameters here (namely the AVC format type, IFrameInterval, the audio bitrate - // and the CodecProfileLevel) have been selected based on what we had already as fixed parameters - // in the original implementation that was using the media for mobile lib. - // Two improvements could be: - // - Investigate if the parameters set is already optimal and can be improved - // - Expose them as parameters so that they can be eventually changed by some external logic - ComposerInterface composer = ComposerProvider.INSTANCE.getComposerForUseCase(new CompressVideo( - inputFile, - outFile, - VideoFormatMimeType.AVC, - bitrate * 1024, - 2, - 96 * 1024, - MediaCodecInfo.CodecProfileLevel.AACObjectLC, - true - )); - - Size srvVideoResolution = ((Mp4ComposerBasic) composer).getSrcVideoResolution(); - - if (srvVideoResolution == null) { - AppLog.w(AppLog.T.MEDIA, "Could not rescue source video resolution"); - return null; - } - - if (srvVideoResolution.getWidth() < width) { - AppLog.w(AppLog.T.MEDIA, "Input file width is lower than than " + width + ". Keeping the original file"); - return null; - } - if (srvVideoResolution.getHeight() == 0) { - AppLog.w(AppLog.T.MEDIA, "Input file height is unknown. Can't calculate the correct " - + "ratio for resizing. Keeping the original file"); - return null; - } - - // Calculate the height keeping the correct aspect ratio - float percentage = (float) width / srvVideoResolution.getWidth(); - float proportionateHeight = srvVideoResolution.getHeight() * percentage; - int height = (int) Math.rint(proportionateHeight); - - composer.size(new Size(width, height)) - .fillMode(FillMode.PRESERVE_ASPECT_FIT) - .listener(listener); - - return composer; - } - private static void configureVideoEncoderWithDefaults(MediaComposer mediaComposer, int width, int height, int bitrate) { VideoFormatAndroid videoFormat = new VideoFormatAndroid(VIDEO_MIME_TYPE, width, height); diff --git a/WordPress/src/main/java/org/wordpress/android/util/analytics/AnalyticsUtils.java b/WordPress/src/main/java/org/wordpress/android/util/analytics/AnalyticsUtils.java index 915207a14dac..d013c8f7d2a9 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/analytics/AnalyticsUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/util/analytics/AnalyticsUtils.java @@ -77,7 +77,6 @@ public class AnalyticsUtils { private static final String CAUSE_OF_ISSUE_KEY = "cause_of_issue"; public static final String HAS_GUTENBERG_BLOCKS_KEY = "has_gutenberg_blocks"; - public static final String HAS_WP_STORIES_BLOCKS_KEY = "has_wp_stories_blocks"; public static final String EDITOR_HAS_HW_ACCELERATION_DISABLED_KEY = "editor_has_hw_disabled"; public static final String EXTRA_CREATION_SOURCE_DETAIL = "creationSourceDetail"; public static final String PROMPT_ID = "prompt_id"; diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/main/WPMainActivityViewModel.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/main/WPMainActivityViewModel.kt index 7dc645b371aa..af5e5e430673 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/main/WPMainActivityViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/main/WPMainActivityViewModel.kt @@ -19,14 +19,12 @@ import org.wordpress.android.fluxc.store.SiteStore import org.wordpress.android.fluxc.store.bloggingprompts.BloggingPromptsStore import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.bloggingprompts.BloggingPromptsSettingsHelper -import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalPhaseHelper import org.wordpress.android.ui.main.MainActionListItem import org.wordpress.android.ui.main.MainActionListItem.ActionType import org.wordpress.android.ui.main.MainActionListItem.ActionType.ANSWER_BLOGGING_PROMPT import org.wordpress.android.ui.main.MainActionListItem.ActionType.CREATE_NEW_PAGE import org.wordpress.android.ui.main.MainActionListItem.ActionType.CREATE_NEW_PAGE_FROM_PAGES_CARD import org.wordpress.android.ui.main.MainActionListItem.ActionType.CREATE_NEW_POST -import org.wordpress.android.ui.main.MainActionListItem.ActionType.CREATE_NEW_STORY import org.wordpress.android.ui.main.MainActionListItem.ActionType.NO_ACTION import org.wordpress.android.ui.main.MainActionListItem.AnswerBloggingPromptAction import org.wordpress.android.ui.main.MainActionListItem.CreateAction @@ -41,7 +39,6 @@ import org.wordpress.android.ui.whatsnew.FeatureAnnouncementProvider import org.wordpress.android.util.BuildConfigWrapper import org.wordpress.android.util.FluxCUtils import org.wordpress.android.util.SiteUtils.hasFullAccessToContent -import org.wordpress.android.util.SiteUtilsWrapper import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import org.wordpress.android.util.mapSafe import org.wordpress.android.util.mapNullable @@ -69,8 +66,6 @@ class WPMainActivityViewModel @Inject constructor( private val bloggingPromptsSettingsHelper: BloggingPromptsSettingsHelper, private val bloggingPromptsStore: BloggingPromptsStore, @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher, - private val jetpackFeatureRemovalPhaseHelper: JetpackFeatureRemovalPhaseHelper, - private val siteUtilsWrapper: SiteUtilsWrapper, private val shouldAskPrivacyConsent: ShouldAskPrivacyConsent, ) : ScopedViewModel(mainDispatcher) { private var isStarted = false @@ -199,16 +194,6 @@ class WPMainActivityViewModel @Inject constructor( onClickAction = null ) ) - if (siteUtilsWrapper.supportsStoriesFeature(site, jetpackFeatureRemovalPhaseHelper)) { - actionsList.add( - CreateAction( - actionType = CREATE_NEW_STORY, - iconRes = R.drawable.ic_story_icon_24dp, - labelRes = R.string.my_site_bottom_sheet_add_story, - onClickAction = ::onCreateActionClicked - ) - ) - } actionsList.add( CreateAction( actionType = CREATE_NEW_POST, @@ -272,11 +257,7 @@ class WPMainActivityViewModel @Inject constructor( _showQuickStarInBottomSheet.postValue(quickStartRepository.activeTask.value == PUBLISH_POST) - if (siteUtilsWrapper.supportsStoriesFeature( - site, - jetpackFeatureRemovalPhaseHelper) || - hasFullAccessToContent(site) - ) { + if (hasFullAccessToContent(site)) { launch { // The user has at least two create options available for this site (pages and/or story posts), // so we should show a bottom sheet. @@ -340,30 +321,13 @@ class WPMainActivityViewModel @Inject constructor( _fabUiState.value = newState } - fun getCreateContentMessageId(site: SiteModel?): Int { - return if (siteUtilsWrapper.supportsStoriesFeature(site, jetpackFeatureRemovalPhaseHelper)) { - getCreateContentMessageIdStoriesFlagOn(hasFullAccessToContent(site)) - } else { - getCreateContentMessageIdStoriesFlagOff(hasFullAccessToContent(site)) - } - } - - // create_post_page_fab_tooltip_stories_feature_flag_on - private fun getCreateContentMessageIdStoriesFlagOn(hasFullAccessToContent: Boolean): Int { - return if (hasFullAccessToContent) { - R.string.create_post_page_fab_tooltip_stories_enabled - } else { - R.string.create_post_page_fab_tooltip_contributors_stories_enabled - } - } - - private fun getCreateContentMessageIdStoriesFlagOff(hasFullAccessToContent: Boolean): Int { - return if (hasFullAccessToContent) { + fun getCreateContentMessageId(site: SiteModel?): Int = + if (hasFullAccessToContent(site)) { R.string.create_post_page_fab_tooltip } else { R.string.create_post_page_fab_tooltip_contributors } - } + private fun updateFeatureAnnouncements() { launch { diff --git a/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_1.png b/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_1.png deleted file mode 100644 index 9a8f74d1815a..000000000000 Binary files a/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_1.png and /dev/null differ diff --git a/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_2.png b/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_2.png deleted file mode 100644 index a6c71d049118..000000000000 Binary files a/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_2.png and /dev/null differ diff --git a/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_1.png b/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_1.png deleted file mode 100644 index 12260bf4b1a7..000000000000 Binary files a/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_1.png and /dev/null differ diff --git a/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_2.png b/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_2.png deleted file mode 100644 index c76abd7dc35d..000000000000 Binary files a/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_2.png and /dev/null differ diff --git a/WordPress/src/main/res/drawable/ic_story_icon_24dp.xml b/WordPress/src/main/res/drawable/ic_story_icon_24dp.xml deleted file mode 100644 index 4d942d7a9879..000000000000 --- a/WordPress/src/main/res/drawable/ic_story_icon_24dp.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/WordPress/src/main/res/drawable/story_title_thumbnail_background.xml b/WordPress/src/main/res/drawable/story_title_thumbnail_background.xml deleted file mode 100644 index 360cb021b1b2..000000000000 --- a/WordPress/src/main/res/drawable/story_title_thumbnail_background.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/debug_cookie_item.xml b/WordPress/src/main/res/layout/debug_cookie_item.xml index 5c8554935d87..adb318163747 100644 --- a/WordPress/src/main/res/layout/debug_cookie_item.xml +++ b/WordPress/src/main/res/layout/debug_cookie_item.xml @@ -48,7 +48,7 @@ android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:padding="@dimen/margin_medium" - android:src="@drawable/ic_delete_black_24dp" + android:src="@drawable/ic_trash_grey_dark_24dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" diff --git a/WordPress/src/main/res/layout/photo_picker_fragment.xml b/WordPress/src/main/res/layout/photo_picker_fragment.xml index 27ad3bba67f1..c9aced51132c 100644 --- a/WordPress/src/main/res/layout/photo_picker_fragment.xml +++ b/WordPress/src/main/res/layout/photo_picker_fragment.xml @@ -6,18 +6,6 @@ android:layout_height="match_parent" android:orientation="vertical"> - - diff --git a/WordPress/src/main/res/layout/post_prepublishing_home_fragment.xml b/WordPress/src/main/res/layout/post_prepublishing_home_fragment.xml index 7e6438f6c794..ee69abe8761a 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_home_fragment.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_home_fragment.xml @@ -18,19 +18,6 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/story_title_header_view" /> - - - + app:layout_constraintTop_toTopOf="parent" /> diff --git a/WordPress/src/main/res/layout/prepublishing_story_title_list_item.xml b/WordPress/src/main/res/layout/prepublishing_story_title_list_item.xml deleted file mode 100644 index feb1cb71bd20..000000000000 --- a/WordPress/src/main/res/layout/prepublishing_story_title_list_item.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/quick_start_list_item.xml b/WordPress/src/main/res/layout/quick_start_list_item.xml index c2a84b89e45b..2302fc3b6896 100644 --- a/WordPress/src/main/res/layout/quick_start_list_item.xml +++ b/WordPress/src/main/res/layout/quick_start_list_item.xml @@ -52,9 +52,9 @@ android:layout_marginEnd="@dimen/margin_extra_large" android:layout_marginStart="@dimen/margin_large" android:contentDescription="@string/quick_start_list_task_complete" - android:src="@drawable/ic_checkmark" - android:tint="@color/quick_start_task_card_completed_checkmark" + android:src="@drawable/ic_checkmark_white_24dp" android:visibility="gone" + app:tint="@color/quick_start_task_card_completed_checkmark" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" diff --git a/WordPress/src/main/res/layout/stories_intro_dialog_fragment.xml b/WordPress/src/main/res/layout/stories_intro_dialog_fragment.xml deleted file mode 100644 index 0d0cedce5388..000000000000 --- a/WordPress/src/main/res/layout/stories_intro_dialog_fragment.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/values-v27/styles.xml b/WordPress/src/main/res/values-v27/styles.xml index 957f1123a827..6961aa8c41e9 100644 --- a/WordPress/src/main/res/values-v27/styles.xml +++ b/WordPress/src/main/res/values-v27/styles.xml @@ -4,12 +4,4 @@ @android:color/white true - - - diff --git a/WordPress/src/main/res/values/dimens.xml b/WordPress/src/main/res/values/dimens.xml index e3ac76c2201e..017bec1fcfa2 100644 --- a/WordPress/src/main/res/values/dimens.xml +++ b/WordPress/src/main/res/values/dimens.xml @@ -14,7 +14,6 @@ @dimen/fab_margin_default 16dp - 64dp 24dp 56dp @@ -624,10 +623,6 @@ 4dp 350dp 250dp - 72dp - 48dp - 6dp - 10dp -54dp diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 844d018c470f..f223a265d524 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -3466,9 +3466,6 @@ Create a page Create a post or story - Create a post, page or story - Create a post or story - Create Site %1$d of %2$d @@ -3641,84 +3638,10 @@ Blogging Can\'t decide? You can change the theme at any time. - - 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 - 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. - GIF files not supported - One or more slides have not been added to your Story because Stories don\'t support GIF files at the moment. Please choose a static image or video background instead. - Story being saved, please wait… - Capture - Flip camera - Flash - Stickers - Text - Sound - Flip - Flash - Saving - Saved - Retry - Saved to photos - SHARE - Share to Close - Saved - Retry - Slide - unselected - selected - errored - Change text alignment - Change text color - 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. - Delete - Discard story post? - Your story post will not be saved as a draft. - Discard - pref_camera_selection - pref_flash_mode_selection - Untitled - Saving "%1$s"… - several stories - 1 slide remaining - %1$d slides remaining - Uploading "%1$s"… - "%1$s" published - Unable to upload "%1$s" - Unable to upload "%1$s" - 1 slide requires action - %1$d slides require action - Manage - Unable to save 1 slide - Unable to save %1$d slides - Retry saving or delete the slides, then try publishing your story again. - Insufficient device storage - We need to save the story on your device before it can be published. Review your storage settings and remove files to free up space. - View Storage - Couldn\'t find Story slide - Operation in progress, try again - Error saving image - Video could not be saved This device doesn\'t support Camera2 API. An error occurred while playing your video - - Introducing Story Posts - A new way to create and publish engaging content on your site. - How to create a story post - Example story title - Now stories are for everyone - Combine photos, videos, and text to create engaging and tappable story posts that your visitors will love. - Story posts don\'t disappear - They\’re published as a new blog post on your site so your audience never misses out on a thing. - Create Story Post - %1$s (%2$s) @@ -4082,21 +4005,7 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> You can edit this block using the web version of the editor. You can rearrange blocks by tapping a block and then tapping the up and down arrows that appear on the bottom left side of the block to move it above or below other blocks. - You need to grant the app audio recording permission in order to record video - Casual - Classic - Strong - Playful - Modern - Bold - Delete - Next Done - Discard changes? - Any changes made will not be saved. - Discard - Text - Background Backup Download @@ -4142,7 +4051,6 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> Cloud with X icon icon - Upload Restore diff --git a/WordPress/src/main/res/values/styles.xml b/WordPress/src/main/res/values/styles.xml index e422dcdc1729..38af9181b6f5 100644 --- a/WordPress/src/main/res/values/styles.xml +++ b/WordPress/src/main/res/values/styles.xml @@ -215,12 +215,6 @@ @color/black - -