From 00c2fea8d151bc44f0e36d6db99cb116f56cd108 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 11:29:34 -0500 Subject: [PATCH 001/822] initial bottom sheet setup. --- .../android/modules/AppComponent.java | 3 + .../posts/PrepublishingBottomSheetFragment.kt | 55 +++++++++++++++++++ .../ui/posts/PrepublishingViewModel.kt | 10 ++++ .../post_prepublishing_bottom_sheet.xml | 6 ++ 4 files changed, 74 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt create mode 100644 WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml 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 d29752d0dedf..e454510c1bf9 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java @@ -93,6 +93,7 @@ import org.wordpress.android.ui.posts.PostSettingsTagsActivity; import org.wordpress.android.ui.posts.PostTimePickerDialogFragment; import org.wordpress.android.ui.posts.PostsListActivity; +import org.wordpress.android.ui.posts.PrepublishingBottomSheetFragment; import org.wordpress.android.ui.posts.PublishNotificationReceiver; import org.wordpress.android.ui.posts.SelectCategoriesActivity; import org.wordpress.android.ui.posts.adapters.AuthorSelectionAdapter; @@ -488,6 +489,8 @@ public interface AppComponent extends AndroidInjector { void inject(PageParentSearchFragment object); + void inject(PrepublishingBottomSheetFragment object); + // Allows us to inject the application without having to instantiate any modules, and provides the Application // in the app graph @Component.Builder diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt new file mode 100644 index 000000000000..fc2a464c6c70 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -0,0 +1,55 @@ +package org.wordpress.android.ui.posts + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import org.wordpress.android.R +import org.wordpress.android.WordPress +import org.wordpress.android.ui.utils.UiHelpers +import javax.inject.Inject + +class PrepublishingBottomSheetFragment : BottomSheetDialogFragment() { + @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject internal lateinit var uiHelpers: UiHelpers + + private lateinit var viewModel: PrepublishingViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + (requireNotNull(activity).application as WordPress).component().inject(this) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.post_prepublishing_bottom_sheet, container) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initViewModel() + } + + private fun initViewModel() { + viewModel = ViewModelProviders.of(this, viewModelFactory) + .get(PrepublishingViewModel::class.java) + } + + companion object { + const val TAG = "prepublishing_bottom_sheet_fragment_tag" + + fun newInstance( + ): PrepublishingBottomSheetFragment { + val fragment = PrepublishingBottomSheetFragment() + val bundle = Bundle() + fragment.arguments = bundle + return fragment + } + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt new file mode 100644 index 000000000000..33d1810db195 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt @@ -0,0 +1,10 @@ +package org.wordpress.android.ui.posts + +import androidx.lifecycle.ViewModel +import javax.inject.Inject + +class PrepublishingViewModel @Inject constructor( +) : ViewModel() { + fun start(){ + } +} diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml new file mode 100644 index 000000000000..3440167eea19 --- /dev/null +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -0,0 +1,6 @@ + + + + From e9e1acf4bf9c787a0d14f658c14e58b4e07d71ad Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 12:22:58 -0500 Subject: [PATCH 002/822] added first layout. --- .../post_prepublishing_bottom_sheet.xml | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml index 3440167eea19..06f4a5b59bd9 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -1,6 +1,25 @@ - + + + + From 059a5b347d91485e4336cba42f72023f67f93a32 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 12:35:37 -0500 Subject: [PATCH 003/822] added JvmStatic so that newInstance can be used from EditPostActivity --- .../android/ui/posts/PrepublishingBottomSheetFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index fc2a464c6c70..1421489b2c61 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -44,6 +44,7 @@ class PrepublishingBottomSheetFragment : BottomSheetDialogFragment() { companion object { const val TAG = "prepublishing_bottom_sheet_fragment_tag" + @JvmStatic fun newInstance( ): PrepublishingBottomSheetFragment { val fragment = PrepublishingBottomSheetFragment() From 90aedbb33ccdef02681bcc85c30ad3aea2aa74e9 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 15:51:24 -0500 Subject: [PATCH 004/822] added prepublishing viewmodel to module --- .../java/org/wordpress/android/modules/ViewModelModule.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 f2981c1a7386..f016d4265b46 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java @@ -8,6 +8,7 @@ import org.wordpress.android.ui.plans.PlansViewModel; import org.wordpress.android.ui.posts.EditPostPublishSettingsViewModel; import org.wordpress.android.ui.posts.PostListMainViewModel; +import org.wordpress.android.ui.posts.PrepublishingViewModel; import org.wordpress.android.ui.posts.editor.StorePostViewModel; import org.wordpress.android.ui.reader.ReaderCommentListViewModel; import org.wordpress.android.ui.reader.viewmodels.ReaderPostListViewModel; @@ -276,6 +277,11 @@ abstract class ViewModelModule { @ViewModelKey(PageParentSearchViewModel.class) abstract ViewModel pageParentSearchViewModel(PageParentSearchViewModel viewModel); + @Binds + @IntoMap + @ViewModelKey(PrepublishingViewModel.class) + abstract ViewModel prepublishingViewModel(PrepublishingViewModel viewModel); + @Binds abstract ViewModelProvider.Factory provideViewModelFactory(ViewModelFactory viewModelFactory); } From e701cf09760176f56ee3c9ee1365770d5c8aa518 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 15:51:59 -0500 Subject: [PATCH 005/822] added options fragment that will show main actions. --- .../posts/PrepublishingBottomSheetFragment.kt | 14 +++++++++++ .../ui/posts/PrepublishingOptionsFragments.kt | 25 +++++++++++++++++++ .../post_prepublishing_bottom_sheet.xml | 5 ++-- .../post_prepublishing_options_fragment.xml | 8 ++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt create mode 100644 WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index 1421489b2c61..3880ec547863 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.posts +import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -41,6 +42,19 @@ class PrepublishingBottomSheetFragment : BottomSheetDialogFragment() { .get(PrepublishingViewModel::class.java) } + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + removeContentFragmentBeforeDismissal() + } + + private fun removeContentFragmentBeforeDismissal() { + activity?.supportFragmentManager?.let { fragmentManager -> + fragmentManager.findFragmentById(R.id.prepublishing_content_fragment)?.also { fragment -> + fragmentManager.beginTransaction().remove(fragment).commit() + } + } + } + companion object { const val TAG = "prepublishing_bottom_sheet_fragment_tag" diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt new file mode 100644 index 000000000000..37396a10f766 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt @@ -0,0 +1,25 @@ +package org.wordpress.android.ui.posts + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import org.wordpress.android.R + +/** + * A simple [Fragment] subclass. + */ +class PrepublishingOptionsFragments : Fragment() { + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.post_prepublishing_options_fragment, container, false) + } + + companion object { + const val TAG ="prepublishing_options_fragment_tag" + } +} diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml index 06f4a5b59bd9..8bd12bfd142f 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -11,11 +11,12 @@ layout="@layout/bottom_sheet_handle_view" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintBottom_toTopOf="@id/content_fragment" + app:layout_constraintBottom_toTopOf="@id/prepublishing_content_fragment" app:layout_constraintTop_toTopOf="parent" /> + + + From b5b663bac97fcafed08fd5cb4487af298187d62b Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 15:52:20 -0500 Subject: [PATCH 006/822] added the ability to trigger the bottom sheet from the publish action --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index d607bd0b661d..f5177c9a7519 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 @@ -1245,7 +1245,7 @@ private boolean performSecondaryAction() { uploadPost(false); return true; case PUBLISH_NOW: - showPublishConfirmationDialogAndPublishPost(); + showPrepublishingNudgeBottomSheetBeforePostUpload(); return true; case NONE: throw new IllegalStateException("Switch in `secondaryAction` shouldn't go through the NONE case"); @@ -1370,7 +1370,7 @@ private void performPrimaryAction() { showUpdateConfirmationDialogAndUploadPost(); return; case PUBLISH_NOW: - showPublishConfirmationDialogAndPublishPost(); + showPrepublishingNudgeBottomSheetBeforePostUpload(); return; // In other cases, we'll upload the post without changing its status case SCHEDULE: @@ -1795,6 +1795,11 @@ private void saveResult(boolean saved, boolean uploadNotStarted) { setResult(RESULT_OK, i); } + private void showPrepublishingNudgeBottomSheetBeforePostUpload() { + PrepublishingBottomSheetFragment prepublishingFragment = PrepublishingBottomSheetFragment.newInstance(); + prepublishingFragment.show(getSupportFragmentManager(), PrepublishingBottomSheetFragment.TAG); + } + private void uploadPost(final boolean publishPost) { AccountModel account = mAccountStore.getAccount(); // prompt user to verify e-mail before publishing From d1155f38028fee8f8deeaf6ef358196d72240969 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 17:48:13 -0500 Subject: [PATCH 007/822] Ensures that the bottom sheet's width is restricted on wide screens --- .../android/ui/posts/PrepublishingBottomSheetFragment.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index 3880ec547863..24c7505ab571 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -10,10 +10,11 @@ import androidx.lifecycle.ViewModelProviders import com.google.android.material.bottomsheet.BottomSheetDialogFragment import org.wordpress.android.R import org.wordpress.android.WordPress +import org.wordpress.android.login.widgets.WPBottomSheetDialogFragment import org.wordpress.android.ui.utils.UiHelpers import javax.inject.Inject -class PrepublishingBottomSheetFragment : BottomSheetDialogFragment() { +class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment() { @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory @Inject internal lateinit var uiHelpers: UiHelpers From 28711d118c1591c8a8de90bdbd034b7d606ac9e5 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 18:44:30 -0500 Subject: [PATCH 008/822] fixed initial layout. --- .../post_prepublishing_bottom_sheet.xml | 24 ++++++++++--------- .../post_prepublishing_options_fragment.xml | 10 ++++---- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml index 8bd12bfd142f..142f4a4dd686 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -1,18 +1,9 @@ - - + app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> + + diff --git a/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml b/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml index 08a1210e57a1..dc861b4e7fd2 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml @@ -1,8 +1,6 @@ - - + From 0f567edfdcfb68e19cb2c12ed48fedf2b17f61cb Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 20:03:46 -0500 Subject: [PATCH 009/822] remove unused tag. --- .../android/ui/posts/PrepublishingOptionsFragments.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt index 37396a10f766..8abc5ccb1b4f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt @@ -18,8 +18,4 @@ class PrepublishingOptionsFragments : Fragment() { // Inflate the layout for this fragment return inflater.inflate(R.layout.post_prepublishing_options_fragment, container, false) } - - companion object { - const val TAG ="prepublishing_options_fragment_tag" - } } From bf4b0dca17929d78302f4abc6683450ac37fd971 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 20:04:12 -0500 Subject: [PATCH 010/822] add options recycler view --- .../post_prepublishing_options_fragment.xml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml b/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml index dc861b4e7fd2..b83616e81b4e 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml @@ -1,6 +1,19 @@ + android:layout_height="match_parent"> + + From 7aafc2685350905bb8caaefbb1dbeea434f2c23e Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 20:36:02 -0500 Subject: [PATCH 011/822] added initial skeleton for options fragment. --- .../android/modules/AppComponent.java | 3 ++ .../android/modules/ViewModelModule.java | 6 +++ .../ui/posts/PrepublishingActionListItem.kt | 18 ++++++++ .../ui/posts/PrepublishingOptionsFragment.kt | 45 +++++++++++++++++++ .../ui/posts/PrepublishingOptionsFragments.kt | 21 --------- .../ui/posts/PrepublishingOptionsViewModel.kt | 10 +++++ .../post_prepublishing_bottom_sheet.xml | 2 +- WordPress/src/main/res/values/strings.xml | 5 +++ 8 files changed, 88 insertions(+), 22 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragment.kt delete mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt 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 e454510c1bf9..a0b9627c823a 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java @@ -94,6 +94,7 @@ import org.wordpress.android.ui.posts.PostTimePickerDialogFragment; import org.wordpress.android.ui.posts.PostsListActivity; import org.wordpress.android.ui.posts.PrepublishingBottomSheetFragment; +import org.wordpress.android.ui.posts.PrepublishingOptionsFragment; import org.wordpress.android.ui.posts.PublishNotificationReceiver; import org.wordpress.android.ui.posts.SelectCategoriesActivity; import org.wordpress.android.ui.posts.adapters.AuthorSelectionAdapter; @@ -491,6 +492,8 @@ public interface AppComponent extends AndroidInjector { void inject(PrepublishingBottomSheetFragment object); + void inject(PrepublishingOptionsFragment object); + // Allows us to inject the application without having to instantiate any modules, and provides the Application // in the app graph @Component.Builder diff --git a/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java b/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java index f016d4265b46..eaad98724e34 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java @@ -8,6 +8,7 @@ import org.wordpress.android.ui.plans.PlansViewModel; import org.wordpress.android.ui.posts.EditPostPublishSettingsViewModel; import org.wordpress.android.ui.posts.PostListMainViewModel; +import org.wordpress.android.ui.posts.PrepublishingOptionsViewModel; import org.wordpress.android.ui.posts.PrepublishingViewModel; import org.wordpress.android.ui.posts.editor.StorePostViewModel; import org.wordpress.android.ui.reader.ReaderCommentListViewModel; @@ -282,6 +283,11 @@ abstract class ViewModelModule { @ViewModelKey(PrepublishingViewModel.class) abstract ViewModel prepublishingViewModel(PrepublishingViewModel viewModel); + @Binds + @IntoMap + @ViewModelKey(PrepublishingOptionsViewModel.class) + abstract ViewModel prepublishingOptionsViewModel(PrepublishingOptionsViewModel viewModel); + @Binds abstract ViewModelProvider.Factory provideViewModelFactory(ViewModelFactory viewModelFactory); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt new file mode 100644 index 000000000000..6f91222fe7e3 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt @@ -0,0 +1,18 @@ +package org.wordpress.android.ui.posts + +import androidx.annotation.StringRes +import org.wordpress.android.R +import org.wordpress.android.ui.utils.UiString + +data class PrepublishingActionListItem( + val label: UiString, + val content: UiString?, + val onActionClicked: (actionType: ActionType) -> Unit, + val actionType: ActionType +) + +enum class ActionType(@StringRes val textRes: Int) { + PUBLISH(R.string.prepublishing_nudges_publish_action), + VISIBILITY(R.string.prepublishing_nudges_visibility_action), + TAGS(R.string.prepublishing_nudges_tags_action) +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragment.kt new file mode 100644 index 000000000000..a24a704b25de --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragment.kt @@ -0,0 +1,45 @@ +package org.wordpress.android.ui.posts + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import org.wordpress.android.R +import org.wordpress.android.WordPress +import org.wordpress.android.ui.utils.UiHelpers +import javax.inject.Inject + +/** + * A simple [Fragment] subclass. + */ +class PrepublishingOptionsFragment : Fragment() { + @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject internal lateinit var uiHelpers: UiHelpers + private lateinit var viewModel: PrepublishingOptionsViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + (requireNotNull(activity).application as WordPress).component().inject(this) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.post_prepublishing_options_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initViewModel() + } + + private fun initViewModel() { + viewModel = ViewModelProviders.of(this, viewModelFactory) + .get(PrepublishingOptionsViewModel::class.java) + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt deleted file mode 100644 index 8abc5ccb1b4f..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragments.kt +++ /dev/null @@ -1,21 +0,0 @@ -package org.wordpress.android.ui.posts - -import android.os.Bundle -import androidx.fragment.app.Fragment -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import org.wordpress.android.R - -/** - * A simple [Fragment] subclass. - */ -class PrepublishingOptionsFragments : Fragment() { - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.post_prepublishing_options_fragment, container, false) - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt new file mode 100644 index 000000000000..69150f311ee5 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt @@ -0,0 +1,10 @@ +package org.wordpress.android.ui.posts + +import androidx.lifecycle.ViewModel +import javax.inject.Inject + +class PrepublishingOptionsViewModel @Inject constructor( +) : ViewModel() { + fun start() { + } +} diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml index 142f4a4dd686..ee9dcb689f07 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -7,7 +7,7 @@ done Failed to crop and save image, please try again. + + Publish + Visibility + Tags + %1$s. Current value is %2$s From b28091ce5944c7a6c71f00a8a21ad313462dd3ad Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 20:36:20 -0500 Subject: [PATCH 012/822] removed unused property --- .../android/ui/posts/PrepublishingBottomSheetFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index 24c7505ab571..3565fae34070 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -16,7 +16,6 @@ import javax.inject.Inject class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment() { @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory - @Inject internal lateinit var uiHelpers: UiHelpers private lateinit var viewModel: PrepublishingViewModel From 423afbecc7f16db27563ca57d0d3bcbfef447904 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 20:53:26 -0500 Subject: [PATCH 013/822] Prepublishing actions list management setup. --- .../android/modules/AppComponent.java | 4 +-- .../ui/posts/PrepublishingActionsAdapter.kt | 32 +++++++++++++++++++ .../posts/PrepublishingActionsDiffCallback.kt | 24 ++++++++++++++ ...ent.kt => PrepublishingActionsFragment.kt} | 8 +++-- .../PrepublishingActionsListItemViewHolder.kt | 14 ++++++++ ...> post_prepublishing_actions_fragment.xml} | 2 +- .../post_prepublishing_bottom_sheet.xml | 2 +- .../layout/prepublishing_action_list_item.xml | 6 ++++ 8 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt rename WordPress/src/main/java/org/wordpress/android/ui/posts/{PrepublishingOptionsFragment.kt => PrepublishingActionsFragment.kt} (77%) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt rename WordPress/src/main/res/layout/{post_prepublishing_options_fragment.xml => post_prepublishing_actions_fragment.xml} (94%) create mode 100644 WordPress/src/main/res/layout/prepublishing_action_list_item.xml 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 a0b9627c823a..228842a4c265 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java @@ -94,7 +94,7 @@ import org.wordpress.android.ui.posts.PostTimePickerDialogFragment; import org.wordpress.android.ui.posts.PostsListActivity; import org.wordpress.android.ui.posts.PrepublishingBottomSheetFragment; -import org.wordpress.android.ui.posts.PrepublishingOptionsFragment; +import org.wordpress.android.ui.posts.PrepublishingActionsFragment; import org.wordpress.android.ui.posts.PublishNotificationReceiver; import org.wordpress.android.ui.posts.SelectCategoriesActivity; import org.wordpress.android.ui.posts.adapters.AuthorSelectionAdapter; @@ -492,7 +492,7 @@ public interface AppComponent extends AndroidInjector { void inject(PrepublishingBottomSheetFragment object); - void inject(PrepublishingOptionsFragment object); + void inject(PrepublishingActionsFragment object); // Allows us to inject the application without having to instantiate any modules, and provides the Application // in the app graph diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt new file mode 100644 index 000000000000..02b810e10142 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt @@ -0,0 +1,32 @@ +package org.wordpress.android.ui.posts + +import android.content.Context +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView + +class PrepublishingActionsAdapter(context: Context) : RecyclerView.Adapter() { + private var actionItems: List = listOf() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PrepublishingActionsListItemViewHolder { + return PrepublishingActionsListItemViewHolder(parent) + } + + fun update(newActionItems: List) { + val diffResult = DiffUtil.calculateDiff( + PrepublishingActionsDiffCallback( + this.actionItems, + newActionItems + ) + ) + this.actionItems = newActionItems + diffResult.dispatchUpdatesTo(this) + } + + override fun getItemCount(): Int = actionItems.size + + override fun onBindViewHolder(holder: PrepublishingActionsListItemViewHolder, position: Int) { + val item = actionItems[position] + holder.bind(item) + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt new file mode 100644 index 000000000000..7652116090ca --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt @@ -0,0 +1,24 @@ +package org.wordpress.android.ui.posts + +import androidx.recyclerview.widget.DiffUtil.Callback + +class PrepublishingActionsDiffCallback( + private val oldList: List, + private val newList: List +) : Callback() { + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + val newItem = newList[newItemPosition] + val oldItem = oldList[oldItemPosition] + + return (oldItem.actionType == newItem.actionType) + } + + override fun getOldListSize(): Int = oldList.size + + override fun getNewListSize(): Int = newList.size + + override fun areContentsTheSame( + oldItemPosition: Int, + newItemPosition: Int + ): Boolean = oldList[oldItemPosition] == newList[newItemPosition] +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt similarity index 77% rename from WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragment.kt rename to WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt index a24a704b25de..5cff43793919 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt @@ -7,6 +7,8 @@ import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.android.synthetic.main.post_prepublishing_actions_fragment.* import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.ui.utils.UiHelpers @@ -15,7 +17,7 @@ import javax.inject.Inject /** * A simple [Fragment] subclass. */ -class PrepublishingOptionsFragment : Fragment() { +class PrepublishingActionsFragment : Fragment() { @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory @Inject internal lateinit var uiHelpers: UiHelpers private lateinit var viewModel: PrepublishingOptionsViewModel @@ -30,12 +32,14 @@ class PrepublishingOptionsFragment : Fragment() { savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment - return inflater.inflate(R.layout.post_prepublishing_options_fragment, container, false) + return inflater.inflate(R.layout.post_prepublishing_actions_fragment, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initViewModel() + actions_recycler_view.layoutManager = LinearLayoutManager(requireActivity()) + actions_recycler_view.adapter = PrepublishingActionsAdapter(requireActivity()) } private fun initViewModel() { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt new file mode 100644 index 000000000000..65743f664dbf --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt @@ -0,0 +1,14 @@ +package org.wordpress.android.ui.posts + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView.ViewHolder +import org.wordpress.android.R + +class PrepublishingActionsListItemViewHolder(internal val parent: ViewGroup) : ViewHolder( + LayoutInflater.from(parent.context).inflate( + R.layout.prepublishing_action_list_item, parent, false + ) +) { + fun bind(action: PrepublishingActionListItem) {} +} diff --git a/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml b/WordPress/src/main/res/layout/post_prepublishing_actions_fragment.xml similarity index 94% rename from WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml rename to WordPress/src/main/res/layout/post_prepublishing_actions_fragment.xml index b83616e81b4e..6be3e0a45c82 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_options_fragment.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_actions_fragment.xml @@ -5,7 +5,7 @@ android:layout_height="match_parent"> + + + From e40f1ddbd4cbd252ece39743303d650ab224dedb Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 21:04:58 -0500 Subject: [PATCH 014/822] setup list actions in the viewmodel. --- .../ui/posts/PrepublishingActionListItem.kt | 7 +++-- .../ui/posts/PrepublishingOptionsViewModel.kt | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt index 6f91222fe7e3..d9df74915b71 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt @@ -5,10 +5,9 @@ import org.wordpress.android.R import org.wordpress.android.ui.utils.UiString data class PrepublishingActionListItem( - val label: UiString, - val content: UiString?, - val onActionClicked: (actionType: ActionType) -> Unit, - val actionType: ActionType + val actionType: ActionType, + var actionResult: UiString? = null, + val onActionClicked: (actionType: ActionType) -> Unit ) enum class ActionType(@StringRes val textRes: Int) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt index 69150f311ee5..60ed77f95650 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt @@ -1,10 +1,37 @@ package org.wordpress.android.ui.posts +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import org.wordpress.android.ui.posts.ActionType.PUBLISH +import org.wordpress.android.ui.posts.ActionType.TAGS +import org.wordpress.android.ui.posts.ActionType.VISIBILITY +import org.wordpress.android.viewmodel.SingleLiveEvent import javax.inject.Inject class PrepublishingOptionsViewModel @Inject constructor( ) : ViewModel() { + private val _prepublishingActions = MutableLiveData>() + val prepublishingActions: LiveData> = _prepublishingActions + + private val _prepublishingAction = SingleLiveEvent() + val prepublishingAction: LiveData = _prepublishingAction + fun start() { + loadActions() + } + + private fun loadActions() { + val prepublishingActionsList = arrayListOf().apply { + add(PrepublishingActionListItem(actionType = PUBLISH, onActionClicked = ::onActionClicked)) + add(PrepublishingActionListItem(actionType = VISIBILITY, onActionClicked = ::onActionClicked)) + add(PrepublishingActionListItem(actionType = TAGS, onActionClicked = ::onActionClicked)) + } + + _prepublishingActions.postValue(prepublishingActionsList) + } + + private fun onActionClicked(actionType: ActionType) { + _prepublishingAction.postValue(actionType) } } From b5c4a242cffe726f0d4fe74b52d88aaf5160e329 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 21:10:08 -0500 Subject: [PATCH 015/822] add list actions observer & binded it to adapter. --- .../android/ui/posts/PrepublishingActionsFragment.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt index 5cff43793919..80c98ab4267d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt @@ -5,6 +5,7 @@ import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager @@ -19,7 +20,6 @@ import javax.inject.Inject */ class PrepublishingActionsFragment : Fragment() { @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory - @Inject internal lateinit var uiHelpers: UiHelpers private lateinit var viewModel: PrepublishingOptionsViewModel override fun onCreate(savedInstanceState: Bundle?) { @@ -37,13 +37,21 @@ class PrepublishingActionsFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - initViewModel() actions_recycler_view.layoutManager = LinearLayoutManager(requireActivity()) actions_recycler_view.adapter = PrepublishingActionsAdapter(requireActivity()) + + initViewModel() + setupViewModelObservers() } private fun initViewModel() { viewModel = ViewModelProviders.of(this, viewModelFactory) .get(PrepublishingOptionsViewModel::class.java) } + + private fun setupViewModelObservers() { + viewModel.prepublishingActions.observe(this, Observer { + (actions_recycler_view.adapter as? PrepublishingActionsAdapter)?.update(it) + }) + } } From 5b1662a29c8da4f4a76a43809d8087b924037a25 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 8 Apr 2020 22:12:24 -0500 Subject: [PATCH 016/822] created actions ui and bind it to adapter. --- .../android/modules/AppComponent.java | 3 ++ .../ui/posts/PrepublishingActionListItem.kt | 10 +++--- .../ui/posts/PrepublishingActionsAdapter.kt | 10 +++++- .../ui/posts/PrepublishingActionsFragment.kt | 10 +++--- .../PrepublishingActionsListItemViewHolder.kt | 10 ++++-- .../ui/posts/PrepublishingOptionsViewModel.kt | 4 +++ .../ui/posts/PrepublishingViewModel.kt | 4 +++ .../post_prepublishing_bottom_sheet.xml | 1 + .../layout/prepublishing_action_list_item.xml | 36 +++++++++++++++++-- 9 files changed, 71 insertions(+), 17 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java index 228842a4c265..7f377cf7d8ac 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java @@ -93,6 +93,7 @@ import org.wordpress.android.ui.posts.PostSettingsTagsActivity; import org.wordpress.android.ui.posts.PostTimePickerDialogFragment; import org.wordpress.android.ui.posts.PostsListActivity; +import org.wordpress.android.ui.posts.PrepublishingActionsAdapter; import org.wordpress.android.ui.posts.PrepublishingBottomSheetFragment; import org.wordpress.android.ui.posts.PrepublishingActionsFragment; import org.wordpress.android.ui.posts.PublishNotificationReceiver; @@ -494,6 +495,8 @@ public interface AppComponent extends AndroidInjector { void inject(PrepublishingActionsFragment object); + void inject(PrepublishingActionsAdapter object); + // Allows us to inject the application without having to instantiate any modules, and provides the Application // in the app graph @Component.Builder diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt index d9df74915b71..c8e85611750c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt @@ -1,8 +1,8 @@ package org.wordpress.android.ui.posts -import androidx.annotation.StringRes import org.wordpress.android.R import org.wordpress.android.ui.utils.UiString +import org.wordpress.android.ui.utils.UiString.UiStringRes data class PrepublishingActionListItem( val actionType: ActionType, @@ -10,8 +10,8 @@ data class PrepublishingActionListItem( val onActionClicked: (actionType: ActionType) -> Unit ) -enum class ActionType(@StringRes val textRes: Int) { - PUBLISH(R.string.prepublishing_nudges_publish_action), - VISIBILITY(R.string.prepublishing_nudges_visibility_action), - TAGS(R.string.prepublishing_nudges_tags_action) +enum class ActionType(val textRes: UiStringRes) { + PUBLISH(UiStringRes(R.string.prepublishing_nudges_publish_action)), + VISIBILITY(UiStringRes(R.string.prepublishing_nudges_visibility_action)), + TAGS(UiStringRes(R.string.prepublishing_nudges_tags_action)) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt index 02b810e10142..2136712852b0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt @@ -4,12 +4,20 @@ import android.content.Context import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView +import org.wordpress.android.WordPress +import org.wordpress.android.ui.utils.UiHelpers +import javax.inject.Inject class PrepublishingActionsAdapter(context: Context) : RecyclerView.Adapter() { private var actionItems: List = listOf() + @Inject lateinit var uiHelpers: UiHelpers + + init { + (context.applicationContext as WordPress).component().inject(this) + } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PrepublishingActionsListItemViewHolder { - return PrepublishingActionsListItemViewHolder(parent) + return PrepublishingActionsListItemViewHolder(parent, uiHelpers) } fun update(newActionItems: List) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt index 80c98ab4267d..4685e260f295 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt @@ -1,10 +1,10 @@ package org.wordpress.android.ui.posts import android.os.Bundle -import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders @@ -12,7 +12,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.post_prepublishing_actions_fragment.* import org.wordpress.android.R import org.wordpress.android.WordPress -import org.wordpress.android.ui.utils.UiHelpers import javax.inject.Inject /** @@ -41,17 +40,16 @@ class PrepublishingActionsFragment : Fragment() { actions_recycler_view.adapter = PrepublishingActionsAdapter(requireActivity()) initViewModel() - setupViewModelObservers() } private fun initViewModel() { viewModel = ViewModelProviders.of(this, viewModelFactory) .get(PrepublishingOptionsViewModel::class.java) - } - private fun setupViewModelObservers() { viewModel.prepublishingActions.observe(this, Observer { - (actions_recycler_view.adapter as? PrepublishingActionsAdapter)?.update(it) + (actions_recycler_view.adapter as PrepublishingActionsAdapter).update(it) }) + + viewModel.start() } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt index 65743f664dbf..c36581aff62d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt @@ -2,13 +2,19 @@ package org.wordpress.android.ui.posts import android.view.LayoutInflater import android.view.ViewGroup +import android.widget.TextView import androidx.recyclerview.widget.RecyclerView.ViewHolder import org.wordpress.android.R +import org.wordpress.android.ui.utils.UiHelpers -class PrepublishingActionsListItemViewHolder(internal val parent: ViewGroup) : ViewHolder( +class PrepublishingActionsListItemViewHolder(internal val parent: ViewGroup, val uiHelpers: UiHelpers) : ViewHolder( LayoutInflater.from(parent.context).inflate( R.layout.prepublishing_action_list_item, parent, false ) ) { - fun bind(action: PrepublishingActionListItem) {} + fun bind(action: PrepublishingActionListItem) { + val actionType: TextView = this.itemView.findViewById(R.id.action_type) + + actionType.text = uiHelpers.getTextOfUiString(itemView.context, action.actionType.textRes) + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt index 60ed77f95650..9385771d0387 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt @@ -11,6 +11,8 @@ import javax.inject.Inject class PrepublishingOptionsViewModel @Inject constructor( ) : ViewModel() { + private var isStarted = false + private val _prepublishingActions = MutableLiveData>() val prepublishingActions: LiveData> = _prepublishingActions @@ -18,6 +20,8 @@ class PrepublishingOptionsViewModel @Inject constructor( val prepublishingAction: LiveData = _prepublishingAction fun start() { + if (isStarted) return + isStarted = true loadActions() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt index 33d1810db195..7303bd114f93 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt @@ -5,6 +5,10 @@ import javax.inject.Inject class PrepublishingViewModel @Inject constructor( ) : ViewModel() { + private var isStarted = false + fun start(){ + if (isStarted) return + isStarted = true } } diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml index c98b770cf4d9..6320e7dd4f97 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -21,6 +21,7 @@ layout="@layout/bottom_sheet_handle_view" android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/margin_extra_large" app:layout_constraintBottom_toTopOf="@id/prepublishing_content_fragment" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml index 3440167eea19..07f2bd9619d4 100644 --- a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml +++ b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml @@ -1,6 +1,36 @@ - + + + + From 85c80da5fba2467a26559a0077c979e39a2d9007 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 12:43:59 -0500 Subject: [PATCH 017/822] ensure that the bottom sheet is fully expanded when opened. --- .../posts/PrepublishingBottomSheetFragment.kt | 17 +++++++++++++++-- .../layout/post_prepublishing_bottom_sheet.xml | 2 +- WordPress/src/main/res/values/dimens.xml | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index 3565fae34070..3306319d255a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -5,13 +5,14 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.FrameLayout import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders -import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.login.widgets.WPBottomSheetDialogFragment -import org.wordpress.android.ui.utils.UiHelpers import javax.inject.Inject class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment() { @@ -35,6 +36,18 @@ class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initViewModel() + dialog?.setOnShowListener { dialogInterface -> + val sheetDialog = dialogInterface as? BottomSheetDialog + + val bottomSheet = sheetDialog?.findViewById( + com.google.android.material.R.id.design_bottom_sheet + ) as? FrameLayout + + bottomSheet?.let { + val behavior = BottomSheetBehavior.from(it) + behavior.state = BottomSheetBehavior.STATE_EXPANDED + } + } } private fun initViewModel() { diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml index 6320e7dd4f97..19f6522c8815 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -12,7 +12,7 @@ android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHeight_min="300dp" + app:layout_constraintHeight_min="@dimen/prepublishing_bottom_sheet_min_height" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/bottom_sheet_handle" /> diff --git a/WordPress/src/main/res/values/dimens.xml b/WordPress/src/main/res/values/dimens.xml index a6988237b2fd..40024fcc6488 100644 --- a/WordPress/src/main/res/values/dimens.xml +++ b/WordPress/src/main/res/values/dimens.xml @@ -485,5 +485,6 @@ 0dp 1dp + 300dp From 22a557c41eec56fbfec5c9f5b7b8bb32e9896c7f Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 13:16:00 -0500 Subject: [PATCH 018/822] refactored ui state of prepublishing actions. --- .../posts/PrepublishingActionItemUiState.kt | 19 ++++++++++++++ .../ui/posts/PrepublishingActionListItem.kt | 17 ------------ .../ui/posts/PrepublishingActionsAdapter.kt | 14 +++++----- .../posts/PrepublishingActionsDiffCallback.kt | 6 ++--- .../ui/posts/PrepublishingActionsFragment.kt | 7 ++--- .../PrepublishingActionsListItemViewHolder.kt | 6 +++-- .../ui/posts/PrepublishingOptionsViewModel.kt | 26 ++++++++++--------- .../layout/prepublishing_action_list_item.xml | 11 +++----- 8 files changed, 53 insertions(+), 53 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionItemUiState.kt delete mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionItemUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionItemUiState.kt new file mode 100644 index 000000000000..d4db4aa2af47 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionItemUiState.kt @@ -0,0 +1,19 @@ +package org.wordpress.android.ui.posts + +import org.wordpress.android.R +import org.wordpress.android.ui.utils.UiString +import org.wordpress.android.ui.utils.UiString.UiStringRes + +sealed class PrepublishingActionItemUiState { + data class PrepublishingActionUiState( + val actionType: ActionType, + var actionResult: UiString? = null, + val onActionClicked: (actionType: ActionType) -> Unit + ) : PrepublishingActionItemUiState() + + enum class ActionType(val textRes: UiStringRes) { + PUBLISH(UiStringRes(R.string.prepublishing_nudges_publish_action)), + VISIBILITY(UiStringRes(R.string.prepublishing_nudges_visibility_action)), + TAGS(UiStringRes(R.string.prepublishing_nudges_tags_action)) + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt deleted file mode 100644 index c8e85611750c..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionListItem.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.wordpress.android.ui.posts - -import org.wordpress.android.R -import org.wordpress.android.ui.utils.UiString -import org.wordpress.android.ui.utils.UiString.UiStringRes - -data class PrepublishingActionListItem( - val actionType: ActionType, - var actionResult: UiString? = null, - val onActionClicked: (actionType: ActionType) -> Unit -) - -enum class ActionType(val textRes: UiStringRes) { - PUBLISH(UiStringRes(R.string.prepublishing_nudges_publish_action)), - VISIBILITY(UiStringRes(R.string.prepublishing_nudges_visibility_action)), - TAGS(UiStringRes(R.string.prepublishing_nudges_tags_action)) -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt index 2136712852b0..5cfc687e2665 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsAdapter.kt @@ -9,7 +9,7 @@ import org.wordpress.android.ui.utils.UiHelpers import javax.inject.Inject class PrepublishingActionsAdapter(context: Context) : RecyclerView.Adapter() { - private var actionItems: List = listOf() + private var items: List = listOf() @Inject lateinit var uiHelpers: UiHelpers init { @@ -20,21 +20,21 @@ class PrepublishingActionsAdapter(context: Context) : RecyclerView.Adapter) { + fun update(newItems: List) { val diffResult = DiffUtil.calculateDiff( PrepublishingActionsDiffCallback( - this.actionItems, - newActionItems + this.items, + newItems ) ) - this.actionItems = newActionItems + this.items = newItems diffResult.dispatchUpdatesTo(this) } - override fun getItemCount(): Int = actionItems.size + override fun getItemCount(): Int = items.size override fun onBindViewHolder(holder: PrepublishingActionsListItemViewHolder, position: Int) { - val item = actionItems[position] + val item = items[position] holder.bind(item) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt index 7652116090ca..3d07ccf7bd4e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsDiffCallback.kt @@ -3,14 +3,14 @@ package org.wordpress.android.ui.posts import androidx.recyclerview.widget.DiffUtil.Callback class PrepublishingActionsDiffCallback( - private val oldList: List, - private val newList: List + private val oldList: List, + private val newList: List ) : Callback() { override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { val newItem = newList[newItemPosition] val oldItem = oldList[oldItemPosition] - return (oldItem.actionType == newItem.actionType) + return (oldItem == newItem) } override fun getOldListSize(): Int = oldList.size diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt index 4685e260f295..5e6e98ebdc08 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt @@ -14,9 +14,6 @@ import org.wordpress.android.R import org.wordpress.android.WordPress import javax.inject.Inject -/** - * A simple [Fragment] subclass. - */ class PrepublishingActionsFragment : Fragment() { @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory private lateinit var viewModel: PrepublishingOptionsViewModel @@ -46,8 +43,8 @@ class PrepublishingActionsFragment : Fragment() { viewModel = ViewModelProviders.of(this, viewModelFactory) .get(PrepublishingOptionsViewModel::class.java) - viewModel.prepublishingActions.observe(this, Observer { - (actions_recycler_view.adapter as PrepublishingActionsAdapter).update(it) + viewModel.prepublishingActionsUiState.observe(this, Observer { uiState -> + (actions_recycler_view.adapter as PrepublishingActionsAdapter).update(uiState) }) viewModel.start() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt index c36581aff62d..7f532545e419 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt @@ -5,6 +5,7 @@ import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView.ViewHolder import org.wordpress.android.R +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.PrepublishingActionUiState import org.wordpress.android.ui.utils.UiHelpers class PrepublishingActionsListItemViewHolder(internal val parent: ViewGroup, val uiHelpers: UiHelpers) : ViewHolder( @@ -12,9 +13,10 @@ class PrepublishingActionsListItemViewHolder(internal val parent: ViewGroup, val R.layout.prepublishing_action_list_item, parent, false ) ) { - fun bind(action: PrepublishingActionListItem) { + fun bind(uiState: PrepublishingActionItemUiState) { + uiState as PrepublishingActionUiState val actionType: TextView = this.itemView.findViewById(R.id.action_type) - actionType.text = uiHelpers.getTextOfUiString(itemView.context, action.actionType.textRes) + actionType.text = uiHelpers.getTextOfUiString(itemView.context, uiState.actionType.textRes) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt index 9385771d0387..3dfa243f6e85 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt @@ -3,9 +3,11 @@ package org.wordpress.android.ui.posts import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import org.wordpress.android.ui.posts.ActionType.PUBLISH -import org.wordpress.android.ui.posts.ActionType.TAGS -import org.wordpress.android.ui.posts.ActionType.VISIBILITY +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType.PUBLISH +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType.TAGS +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType.VISIBILITY +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.PrepublishingActionUiState import org.wordpress.android.viewmodel.SingleLiveEvent import javax.inject.Inject @@ -13,8 +15,8 @@ class PrepublishingOptionsViewModel @Inject constructor( ) : ViewModel() { private var isStarted = false - private val _prepublishingActions = MutableLiveData>() - val prepublishingActions: LiveData> = _prepublishingActions + private val _prepublishingActionsUiState = MutableLiveData>() + val prepublishingActionsUiState: LiveData> = _prepublishingActionsUiState private val _prepublishingAction = SingleLiveEvent() val prepublishingAction: LiveData = _prepublishingAction @@ -22,17 +24,17 @@ class PrepublishingOptionsViewModel @Inject constructor( fun start() { if (isStarted) return isStarted = true - loadActions() + loadActionsUiState() } - private fun loadActions() { - val prepublishingActionsList = arrayListOf().apply { - add(PrepublishingActionListItem(actionType = PUBLISH, onActionClicked = ::onActionClicked)) - add(PrepublishingActionListItem(actionType = VISIBILITY, onActionClicked = ::onActionClicked)) - add(PrepublishingActionListItem(actionType = TAGS, onActionClicked = ::onActionClicked)) + private fun loadActionsUiState() { + val prepublishingActionsUiStateList = arrayListOf().apply { + add(PrepublishingActionUiState(actionType = PUBLISH, onActionClicked = ::onActionClicked)) + add(PrepublishingActionUiState(actionType = VISIBILITY, onActionClicked = ::onActionClicked)) + add(PrepublishingActionUiState(actionType = TAGS, onActionClicked = ::onActionClicked)) } - _prepublishingActions.postValue(prepublishingActionsList) + _prepublishingActionsUiState.postValue(prepublishingActionsUiStateList) } private fun onActionClicked(actionType: ActionType) { diff --git a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml index 07f2bd9619d4..b51ba2b24855 100644 --- a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml +++ b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml @@ -1,9 +1,9 @@ + android:layout_height="wrap_content"> + app:layout_constraintTop_toTopOf="parent" /> Date: Thu, 9 Apr 2020 13:38:22 -0500 Subject: [PATCH 019/822] added action result to ui and adapter --- .../PrepublishingActionsListItemViewHolder.kt | 4 ++++ .../ui/posts/PrepublishingOptionsViewModel.kt | 18 +++++++++++++++-- .../layout/prepublishing_action_list_item.xml | 20 +++++++++++++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt index 7f532545e419..78270a9a8550 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsListItemViewHolder.kt @@ -16,7 +16,11 @@ class PrepublishingActionsListItemViewHolder(internal val parent: ViewGroup, val fun bind(uiState: PrepublishingActionItemUiState) { uiState as PrepublishingActionUiState val actionType: TextView = this.itemView.findViewById(R.id.action_type) + val actionResult: TextView = this.itemView.findViewById(R.id.action_result) actionType.text = uiHelpers.getTextOfUiString(itemView.context, uiState.actionType.textRes) + uiState.actionResult?.let { resultText -> + actionResult.text = uiHelpers.getTextOfUiString(itemView.context, resultText) + } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt index 3dfa243f6e85..d6fad56d276f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt @@ -8,6 +8,7 @@ import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType. import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType.TAGS import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType.VISIBILITY import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.PrepublishingActionUiState +import org.wordpress.android.ui.utils.UiString.UiStringText import org.wordpress.android.viewmodel.SingleLiveEvent import javax.inject.Inject @@ -27,10 +28,23 @@ class PrepublishingOptionsViewModel @Inject constructor( loadActionsUiState() } + // TODO remove hardcoded Immediately & Public with live data from the EditPostRepository / user changes. private fun loadActionsUiState() { val prepublishingActionsUiStateList = arrayListOf().apply { - add(PrepublishingActionUiState(actionType = PUBLISH, onActionClicked = ::onActionClicked)) - add(PrepublishingActionUiState(actionType = VISIBILITY, onActionClicked = ::onActionClicked)) + add( + PrepublishingActionUiState( + actionType = PUBLISH, + actionResult = UiStringText("Immediately"), + onActionClicked = ::onActionClicked + ) + ) + add( + PrepublishingActionUiState( + actionType = VISIBILITY, + actionResult = UiStringText("Public"), + onActionClicked = ::onActionClicked + ) + ) add(PrepublishingActionUiState(actionType = TAGS, onActionClicked = ::onActionClicked)) } diff --git a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml index b51ba2b24855..406ba5de03fb 100644 --- a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml +++ b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml @@ -25,9 +25,25 @@ android:textAlignment="viewStart" android:textAppearance="?attr/textAppearanceSubtitle1" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintEnd_toStartOf="@id/action_result" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/top_divider" - app:layout_constraintVertical_chainStyle="packed" + app:layout_constraintVertical_chainStyle="spread" tools:text="Yeah" /> + + From 65493d7b95b93555c5e62401762810f954212631 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 14:08:44 -0500 Subject: [PATCH 020/822] renamed options viewmodel to actions --- .../java/org/wordpress/android/modules/ViewModelModule.java | 6 +++--- .../android/ui/posts/PrepublishingActionsFragment.kt | 4 ++-- ...OptionsViewModel.kt => PrepublishingActionsViewModel.kt} | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename WordPress/src/main/java/org/wordpress/android/ui/posts/{PrepublishingOptionsViewModel.kt => PrepublishingActionsViewModel.kt} (97%) 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 eaad98724e34..4004f247ffc0 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/ViewModelModule.java @@ -8,7 +8,7 @@ import org.wordpress.android.ui.plans.PlansViewModel; import org.wordpress.android.ui.posts.EditPostPublishSettingsViewModel; import org.wordpress.android.ui.posts.PostListMainViewModel; -import org.wordpress.android.ui.posts.PrepublishingOptionsViewModel; +import org.wordpress.android.ui.posts.PrepublishingActionsViewModel; import org.wordpress.android.ui.posts.PrepublishingViewModel; import org.wordpress.android.ui.posts.editor.StorePostViewModel; import org.wordpress.android.ui.reader.ReaderCommentListViewModel; @@ -285,8 +285,8 @@ abstract class ViewModelModule { @Binds @IntoMap - @ViewModelKey(PrepublishingOptionsViewModel.class) - abstract ViewModel prepublishingOptionsViewModel(PrepublishingOptionsViewModel viewModel); + @ViewModelKey(PrepublishingActionsViewModel.class) + abstract ViewModel prepublishingOptionsViewModel(PrepublishingActionsViewModel viewModel); @Binds abstract ViewModelProvider.Factory provideViewModelFactory(ViewModelFactory viewModelFactory); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt index 5e6e98ebdc08..700fcc83907e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt @@ -16,7 +16,7 @@ import javax.inject.Inject class PrepublishingActionsFragment : Fragment() { @Inject internal lateinit var viewModelFactory: ViewModelProvider.Factory - private lateinit var viewModel: PrepublishingOptionsViewModel + private lateinit var viewModel: PrepublishingActionsViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -41,7 +41,7 @@ class PrepublishingActionsFragment : Fragment() { private fun initViewModel() { viewModel = ViewModelProviders.of(this, viewModelFactory) - .get(PrepublishingOptionsViewModel::class.java) + .get(PrepublishingActionsViewModel::class.java) viewModel.prepublishingActionsUiState.observe(this, Observer { uiState -> (actions_recycler_view.adapter as PrepublishingActionsAdapter).update(uiState) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt similarity index 97% rename from WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt rename to WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt index d6fad56d276f..15c6ce6e14f8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingOptionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt @@ -12,7 +12,7 @@ import org.wordpress.android.ui.utils.UiString.UiStringText import org.wordpress.android.viewmodel.SingleLiveEvent import javax.inject.Inject -class PrepublishingOptionsViewModel @Inject constructor( +class PrepublishingActionsViewModel @Inject constructor( ) : ViewModel() { private var isStarted = false From f49daff021811e31e45ab6ddaf3b503f38dc6825 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 14:38:01 -0500 Subject: [PATCH 021/822] refactored viewmodel's action type --- .../android/ui/posts/PrepublishingActionsViewModel.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt index 15c6ce6e14f8..90dc6ffefd65 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt @@ -19,8 +19,8 @@ class PrepublishingActionsViewModel @Inject constructor( private val _prepublishingActionsUiState = MutableLiveData>() val prepublishingActionsUiState: LiveData> = _prepublishingActionsUiState - private val _prepublishingAction = SingleLiveEvent() - val prepublishingAction: LiveData = _prepublishingAction + private val _prepublishingActionType = SingleLiveEvent() + val prepublishingActionType: LiveData = _prepublishingActionType fun start() { if (isStarted) return @@ -52,6 +52,6 @@ class PrepublishingActionsViewModel @Inject constructor( } private fun onActionClicked(actionType: ActionType) { - _prepublishingAction.postValue(actionType) + _prepublishingActionType.postValue(actionType) } } From f99862a479b54d31d1d34fff1c6a514b91ecd8f6 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 14:38:22 -0500 Subject: [PATCH 022/822] actions viewmodel tests. --- .../PrepublishingActionsViewModelTest.kt | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt new file mode 100644 index 000000000000..117f64d3590a --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt @@ -0,0 +1,82 @@ +package org.wordpress.android.ui.posts + +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import org.assertj.core.api.Assertions.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.junit.MockitoJUnitRunner +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType.PUBLISH +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType.VISIBILITY +import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.PrepublishingActionUiState + +@RunWith(MockitoJUnitRunner::class) +class PrepublishingActionsViewModelTest { + @Rule + @JvmField val rule = InstantTaskExecutorRule() + + private lateinit var viewModel: PrepublishingActionsViewModel + + @Before + fun setUp() { + viewModel = PrepublishingActionsViewModel() + viewModel.start() + } + + @Test + fun `verify that actions are propagated to prepublishingActionsUiState once the viewModel is started`() { + // arrange + val expectedActionsAmount = 3 + + // act - viewModel is already started + + // assert + assertThat(viewModel.prepublishingActionsUiState.value?.size).isEqualTo(expectedActionsAmount) + } + + @Test + fun `verify that when publish action is clicked the right action type is propagated to prepublishingActionType`() { + // arrange + val expectedActionType = PUBLISH + + // act + val publishAction = getActionUiState(expectedActionType) + publishAction.onActionClicked.invoke(expectedActionType) + + // assert + assertThat(viewModel.prepublishingActionType.value).isEqualTo(expectedActionType) + } + + @Test + fun `verify that when visibility action is clicked the right action type is propagated to prepublishingActionType`() { + // arrange + val expectedActionType = VISIBILITY + + // act + val visibilityAction = getActionUiState(expectedActionType) + visibilityAction.onActionClicked.invoke(expectedActionType) + + // assert + assertThat(viewModel.prepublishingActionType.value).isEqualTo(expectedActionType) + } + + @Test + fun `verify that when tags action is clicked the right action type is propagated to prepublishingActionType`() { + // arrange + val expectedActionType = VISIBILITY + + // act + val tagsAction = getActionUiState(expectedActionType) + tagsAction.onActionClicked.invoke(expectedActionType) + + // assert + assertThat(viewModel.prepublishingActionType.value).isEqualTo(expectedActionType) + } + + private fun getActionUiState(actionType: ActionType): PrepublishingActionUiState { + val actions = viewModel.prepublishingActionsUiState.value?.filterIsInstance(PrepublishingActionUiState::class.java) + return actions?.find { it.actionType == actionType }!! + } +} From 0b48f7302e0d26bdf5a56abdb4b3db931d8ec91c Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 16:34:40 -0500 Subject: [PATCH 023/822] so that there isn't a crash when this fragment is being removed --- .../android/ui/posts/PrepublishingBottomSheetFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index 3306319d255a..a6e7839e54cb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -63,7 +63,7 @@ class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment() { private fun removeContentFragmentBeforeDismissal() { activity?.supportFragmentManager?.let { fragmentManager -> fragmentManager.findFragmentById(R.id.prepublishing_content_fragment)?.also { fragment -> - fragmentManager.beginTransaction().remove(fragment).commit() + fragmentManager.beginTransaction().remove(fragment).commitAllowingStateLoss() } } } From 8ee2cf7f6789aecd55729ca3c3a9235ea3ad8551 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 16:42:31 -0500 Subject: [PATCH 024/822] fixed ktlint errors. --- .../android/ui/posts/PrepublishingActionsFragment.kt | 3 ++- .../android/ui/posts/PrepublishingActionsViewModel.kt | 3 +-- .../android/ui/posts/PrepublishingBottomSheetFragment.kt | 3 +-- .../wordpress/android/ui/posts/PrepublishingViewModel.kt | 5 ++--- .../ui/posts/PrepublishingActionsViewModelTest.kt | 9 +++++---- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt index 700fcc83907e..d3b0868fe3c1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsFragment.kt @@ -24,7 +24,8 @@ class PrepublishingActionsFragment : Fragment() { } override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, + inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt index 90dc6ffefd65..c5970d7279e9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt @@ -12,8 +12,7 @@ import org.wordpress.android.ui.utils.UiString.UiStringText import org.wordpress.android.viewmodel.SingleLiveEvent import javax.inject.Inject -class PrepublishingActionsViewModel @Inject constructor( -) : ViewModel() { +class PrepublishingActionsViewModel @Inject constructor() : ViewModel() { private var isStarted = false private val _prepublishingActionsUiState = MutableLiveData>() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index a6e7839e54cb..f45dba8bd66a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -72,8 +72,7 @@ class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment() { const val TAG = "prepublishing_bottom_sheet_fragment_tag" @JvmStatic - fun newInstance( - ): PrepublishingBottomSheetFragment { + fun newInstance(): PrepublishingBottomSheetFragment { val fragment = PrepublishingBottomSheetFragment() val bundle = Bundle() fragment.arguments = bundle diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt index 7303bd114f93..db5ad77cd228 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt @@ -3,11 +3,10 @@ package org.wordpress.android.ui.posts import androidx.lifecycle.ViewModel import javax.inject.Inject -class PrepublishingViewModel @Inject constructor( -) : ViewModel() { +class PrepublishingViewModel @Inject constructor() : ViewModel() { private var isStarted = false - fun start(){ + fun start() { if (isStarted) return isStarted = true } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt index 117f64d3590a..fcfde870e5ae 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt @@ -37,7 +37,7 @@ class PrepublishingActionsViewModelTest { } @Test - fun `verify that when publish action is clicked the right action type is propagated to prepublishingActionType`() { + fun `verify that publish action type is propagated to prepublishingActionType`() { // arrange val expectedActionType = PUBLISH @@ -50,7 +50,7 @@ class PrepublishingActionsViewModelTest { } @Test - fun `verify that when visibility action is clicked the right action type is propagated to prepublishingActionType`() { + fun `verify that visibility action type is propagated to prepublishingActionType`() { // arrange val expectedActionType = VISIBILITY @@ -63,7 +63,7 @@ class PrepublishingActionsViewModelTest { } @Test - fun `verify that when tags action is clicked the right action type is propagated to prepublishingActionType`() { + fun `verify that tags action type is propagated to prepublishingActionType`() { // arrange val expectedActionType = VISIBILITY @@ -76,7 +76,8 @@ class PrepublishingActionsViewModelTest { } private fun getActionUiState(actionType: ActionType): PrepublishingActionUiState { - val actions = viewModel.prepublishingActionsUiState.value?.filterIsInstance(PrepublishingActionUiState::class.java) + val actions = viewModel.prepublishingActionsUiState.value + ?.filterIsInstance(PrepublishingActionUiState::class.java) return actions?.find { it.actionType == actionType }!! } } From 4fef3e28b8f9340af0f3544a0b5142958fd00a3f Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 9 Apr 2020 16:43:58 -0500 Subject: [PATCH 025/822] Revert "Merge branch 'feature/prepublishing_nudges' into issue-11602/create_bottom_sheet" This reverts commit b1c15e7e6f296e60bb85db6956440b56a83026ea. --- .configure | 4 +- .configure-files/gradle.properties.enc | Bin 2864 -> 2832 bytes WordPress/build.gradle | 1 + WordPress/metadata/PlayStoreStrings.po | 18 ++-- WordPress/metadata/release_notes.txt | 9 +- .../android/ui/posts/EditPostActivity.java | 10 +- .../reactnative/ReactNativeRequestHandler.kt | 32 +++++- .../posts/reactnative/ReactNativeUrlUtil.kt | 50 ++++++++++ .../android/ui/utils/AuthenticationUtils.kt | 8 +- WordPress/src/main/res/values/key_strings.xml | 18 ++-- WordPress/src/main/res/values/strings.xml | 12 +-- WordPress/src/main/res/xml/site_settings.xml | 4 +- .../ReactNativeRequestHandlerTest.kt | 91 ++++++++++++++++-- .../reactnative/ReactNativeUrlUtilTest.kt | 68 +++++++++++++ build.gradle | 2 +- .../android/editor/AztecEditorFragment.java | 7 +- .../editor/EditorFragmentAbstract.java | 2 +- .../editor/GutenbergEditorFragment.java | 2 +- 18 files changed, 272 insertions(+), 66 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt diff --git a/.configure b/.configure index 79c516aded91..df3e2a3eab64 100644 --- a/.configure +++ b/.configure @@ -1,7 +1,7 @@ { "project_name": "WordPress-Android", "branch": "master", - "pinned_hash": "c9fee80926844dde0c23d55128de6232539571e2", + "pinned_hash": "eb32678967bdbe1e100a6dbb4cf8adeb8935e335", "files_to_copy": [ { "file": "android/WPAndroid/gradle.properties", @@ -27,4 +27,4 @@ "file_dependencies": [ ] -} +} \ No newline at end of file diff --git a/.configure-files/gradle.properties.enc b/.configure-files/gradle.properties.enc index d63de9c1aa0878c25e1fa240e3d1d676693c3f79..9e124793952956d4e6f4af26363afd8d9fa31971 100644 GIT binary patch delta 1152 zcmV-`1b_Rm7LXROpay?olSCOd-U2;^L$!ZxZ(ZrekfYCR=K_l!1MOptJfZ@m(u_D` zFCvhFV>)+Axg4&m7Le}gZ2!r}rkBsr;|wM+3kBsAEk{%E&c*NePL=$7e5k5~+KaR_ zoy`y&$Jd&5iNvM#9bx0hNHcZUUcJF~wi3N+6B(uv6Zn!-P$hrAQ=#t6&VUDVt~E;s zP`^3?M>jb?u0v>wI|sZjKxf zO4&2}8ub~se#vZMJl1&nutM&Fzr>5OzE4YOnIld$th8m6p&2(_C8jD=7!c9rxagye z)vWM-$HT&RQJAb)umnV+}&v0xd zUYfDo!M(!8LeF&E9Cl+LORMD*e0}ITUO$>s1OJcLR?y)T3BVf4V{<=TI+qFN8&B zfIT_seyoPsPRiEZK5G!@OXonjG@cEy``D?!^_xRH`ajI-ddG)Y zKM+Sp%TEC4mPH&ntYgRMbWYLm_slVT;UB#R(xk~T%SacDYd?@;Q})E~{Z9BgqqcW_ z9o;(Se42l=f=Tj^H$mUh3a|+9SCU7M#{lnaa)4CQO-3M6OA$i8em(O6(6@fx!A1 zGk{a&PfHQroj>J(kbb&ib9OUyDEm72k}ZOHuDpMw(jD;Nit8;#c(Q@2vS&+~|MdVW z%bP~__jsIW8HN{Rdz7U-qM&~e(iBMkwuJS%TNvIU>2xcxD9Kd4s&T?Q_sDs`(Ge#(qTnUZGTgOmzHhBS6?WvpKW%PVX@K3|x9YmO3H)_(|Y zb<@mxs)s&_q(awrN0z$=EN|1V8=_RcAZUMT`5*+T-PO(Y<2{Psl9J=M0RUZE&yFcb z`oc9w7Y##>ywsI0{fa*PHDF3Ee^2^FBI^nB zD*00>{8tL~{t7}jmA6ehXVlki5AYFSr^gb|6>=LcFj^V&?%b?w$gc01g}r82w@PQBtiG?Uu`z_ z}?s`NUARKw)CnSGCWZjb8@1&f)r$_?P!lkuU z4iL?YqF^h(f(dXi!kZv;U0AuZ* z-Gy8F^F+98@xf7+>ZXWK1sOGK3ZJk*(|ReaJTQ(9LZbP>|I$1hY8|@``-^ccc-344b8t zD2UQm5I7a4qI+d$TY>dcIjnJ~PvyH*3(a4O%Df%dZx^ifeXFLv7V*6q16$F~4!*Fy zO=_NFm}iWU1}}g%`Xk46>Mh^b#$Z6_ zOjjZ56XnuNuWm|i4uQ~xY+3aB*KOL-UDd$7g}Zg{s*t6nOZojTRgoC%8_in?Y96E9 zddh!xaF}hT^JJlovCy!SYO2l&wMz5gek7Wsb1?_JO}9No-jLQu z9a_5YMtIuVurKZWoN}wFx;-jmttIaVFvF)D^fKhfBYSNc)&7&rVL2Jfh7w}KNS2hi znIJWE%$xH^V)gJx>vmuE_*G7_ij<@F9Y4X76j}jMuX?=69j1>Go?1Rk^30}rAH{!1 zJm8N^Ic$dFrTF1R1YL_P*BtBk96yI#NM2XbsEYChRNc260ieqpnvOdF@OzJ}B4o(x|$lR%apoOu6pQomCO diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 0edd8c76f147..a06d548e5489 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -307,6 +307,7 @@ dependencies { // Debug debugImplementation 'com.facebook.stetho:stetho:1.5.1' debugImplementation 'com.facebook.stetho:stetho-okhttp3:1.5.1' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2' implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" diff --git a/WordPress/metadata/PlayStoreStrings.po b/WordPress/metadata/PlayStoreStrings.po index 33df533e9de3..e25586e73a2a 100644 --- a/WordPress/metadata/PlayStoreStrings.po +++ b/WordPress/metadata/PlayStoreStrings.po @@ -11,16 +11,6 @@ msgstr "" "Project-Id-Version: Release Notes & Play Store Descriptions\n" #. translators: Release notes for this version to be displayed in the Play Store. Limit to 500 characters including spaces and commas! -msgctxt "release_note_146" -msgid "" -"14.6:\n" -"Block editor enhancements: Added Cover block. Enabled crop, zoom, and rotate for images in posts. Tweaked “Take a Video” icon to differentiate from “Take a Photo.” Removed dimming effect on unselected blocks. Added toolbar for alignment options in Heading, Paragraph, Image, and MediaText blocks.\n" -"\n" -"Fixes: Issue where “wordpress://” links in a browser didn’t open the app, issue where opening a page opened an empty editor.\n" -"\n" -"General improvements: Dark Theme support.\n" -msgstr "" - msgctxt "release_note_145" msgid "" "14.5:\n" @@ -30,6 +20,14 @@ msgid "" "Bug fix: fixed an issue causing failed post uploads to be retried indefinitely.\n" msgstr "" +msgctxt "release_note_144" +msgid "" +"14.4:\n" +"One small fix: this release takes care of an issue that caused images to upload with wonky URLs, which made them inaccessible on your website.\n" +"\n" +"Wash your hands and stay safe, everyone.\n" +msgstr "" + #. translators: Release notes for this version to be displayed in the Play Store. Limit to 500 characters including spaces and commas! msgctxt "sample_post_content" msgid "The best moment of any trip, for me, is when I first step foot off the plane. The whole of the trip is in front me, ripe with possibility." diff --git a/WordPress/metadata/release_notes.txt b/WordPress/metadata/release_notes.txt index f16b89d68cd9..3584e9159e6c 100644 --- a/WordPress/metadata/release_notes.txt +++ b/WordPress/metadata/release_notes.txt @@ -1,5 +1,4 @@ -Block editor enhancements: Added Cover block. Enabled crop, zoom, and rotate for images in posts. Tweaked “Take a Video” icon to differentiate from “Take a Photo.” Removed dimming effect on unselected blocks. Added toolbar for alignment options in Heading, Paragraph, Image, and MediaText blocks. - -Fixes: Issue where “wordpress://” links in a browser didn’t open the app, issue where opening a page opened an empty editor. - -General improvements: Dark Theme support. +Block editor: Added Latest Posts block, fixed crash caused by pasting HTML content with embedded images +Page Templates: Added a block-based templates for quicker page creation. +Site Creation: removed a few steps for faster setup — select the kind of site, enter the domain name, done. +Bug fix: fixed an issue causing failed post uploads to be retried indefinitely. 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 bc140e739e6f..d607bd0b661d 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 @@ -142,7 +142,6 @@ import org.wordpress.android.ui.uploads.UploadUtils; import org.wordpress.android.ui.uploads.UploadUtilsWrapper; import org.wordpress.android.ui.uploads.VideoOptimizer; -import org.wordpress.android.ui.utils.AuthenticationUtils; import org.wordpress.android.ui.utils.UiHelpers; import org.wordpress.android.util.ActivityUtils; import org.wordpress.android.util.AniUtils; @@ -2672,15 +2671,14 @@ public void onVideoPressInfoRequested(final String videoId) { } @Override - public Map onAuthHeaderRequested(String url) { - Map authHeaders = new HashMap<>(); - + public String onAuthHeaderRequested(String url) { + String authHeader = ""; String token = mAccountStore.getAccessToken(); if (mSite.isPrivate() && WPUrlUtils.safeToAddWordPressComAuthToken(url) && !TextUtils.isEmpty(token)) { - authHeaders.put(AuthenticationUtils.AUTHORIZATION_HEADER_NAME, "Bearer " + token); + authHeader = "Bearer " + token; } - return authHeaders; + return authHeader; } @Override diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt index 145c89f32554..0b4620b9fcdf 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt @@ -19,6 +19,7 @@ import javax.inject.Named class ReactNativeRequestHandler @Inject constructor( private val reactNativeStore: ReactNativeStore, + private val urlUtil: ReactNativeUrlUtil, @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher ) : CoroutineScope { override val coroutineContext = bgDispatcher + Job() @@ -30,8 +31,11 @@ class ReactNativeRequestHandler @Inject constructor( onError: Consumer ) { launch { - val response = reactNativeStore.executeRequest(mSite, pathWithParams) - handleResponse(response, onSuccess::accept, onError::accept) + if (mSite.isUsingWpComRestApi) { + performGetRequestForWPComSite(pathWithParams, mSite.siteId, onSuccess::accept, onError::accept) + } else { + performGetRequestForSelfHostedSite(pathWithParams, mSite.url, onSuccess::accept, onError::accept) + } } } @@ -45,6 +49,30 @@ class ReactNativeRequestHandler @Inject constructor( coroutineContext[Job]!!.cancel() } + private suspend fun performGetRequestForWPComSite( + pathWithParams: String, + wpComSiteId: Long, + onSuccess: (String) -> Unit, + onError: (Bundle) -> Unit + ) { + urlUtil.parseUrlAndParamsForWPCom(pathWithParams, wpComSiteId)?.let { (url, params) -> + val response = reactNativeStore.performWPComRequest(url, params) + handleResponse(response, onSuccess, onError) + } + } + + private suspend fun performGetRequestForSelfHostedSite( + pathWithParams: String, + siteUrl: String, + onSuccess: (String) -> Unit, + onError: (Bundle) -> Unit + ) { + urlUtil.parseUrlAndParamsForWPOrg(pathWithParams, siteUrl)?.let { (url, params) -> + val response = reactNativeStore.performWPAPIRequest(url, params) + handleResponse(response, onSuccess, onError) + } + } + private fun handleResponse( response: ReactNativeFetchResponse, onSuccess: (String) -> Unit, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt new file mode 100644 index 000000000000..aa920e654a4a --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt @@ -0,0 +1,50 @@ +package org.wordpress.android.ui.posts.reactnative + +import android.net.Uri +import javax.inject.Inject + +private const val WPCOM_ENDPOINT = "https://public-api.wordpress.com" + +class ReactNativeUrlUtil @Inject constructor() { + internal fun parseUrlAndParamsForWPCom( + pathWithParams: String, + wpComSiteId: Long + ): Pair>? = + parsePathAndParams(pathWithParams)?.let { (path, params) -> + val url = WPCOM_ENDPOINT + path.replace("wp/v2/", "wp/v2/sites/$wpComSiteId/") + Pair(url, params) + } + + internal fun parseUrlAndParamsForWPOrg( + pathWithParams: String, + siteUrl: String + ): Pair>? = + parsePathAndParams(pathWithParams)?.let { (path, params) -> + val url = "$siteUrl/wp-json$path" + val updatedParams = updateUrlForWPOrgRequest(params) + Pair(url, updatedParams) + } + + /* + * We cannot make authorized requests to self-hosted sites. A "context" of + * "edit" requires authorization, so changing the context to "view" since that does not need + * authorizations and still has the data we need. + */ + private fun updateUrlForWPOrgRequest(params: Map): Map = + params.mapValues { (key, value) -> + val hasEditContext = key == "context" && value == "edit" + if (hasEditContext) { + "view" + } else { + value + } + } + + private fun parsePathAndParams(pathWithParams: String): Pair> { + val uri = Uri.parse(pathWithParams) + val paramMap = uri.queryParameterNames.map { name -> + name to uri.getQueryParameter(name) + }.toMap() + return Pair(uri.path, paramMap) + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/utils/AuthenticationUtils.kt b/WordPress/src/main/java/org/wordpress/android/ui/utils/AuthenticationUtils.kt index 3d538504d25d..d9c2b95135d0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/utils/AuthenticationUtils.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/utils/AuthenticationUtils.kt @@ -20,7 +20,7 @@ class AuthenticationUtils headers["User-Agent"] = userAgent.userAgent if (WPUrlUtils.safeToAddWordPressComAuthToken(url)) { if (accessToken.exists()) { - headers[AUTHORIZATION_HEADER_NAME] = "Bearer " + accessToken.get() + headers["Authorization"] = "Bearer " + accessToken.get() } } else { // Check if we had HTTP Auth credentials for the root url @@ -28,13 +28,9 @@ class AuthenticationUtils if (httpAuthModel != null) { val creds = String.format("%s:%s", httpAuthModel.username, httpAuthModel.password) val auth = "Basic " + Base64.encodeToString(creds.toByteArray(), Base64.NO_WRAP) - headers[AUTHORIZATION_HEADER_NAME] = auth + headers["Authorization"] = auth } } return headers } - - companion object { - const val AUTHORIZATION_HEADER_NAME = "Authorization" - } } diff --git a/WordPress/src/main/res/values/key_strings.xml b/WordPress/src/main/res/values/key_strings.xml index cf3e2ace33ce..60d3d2f86c80 100644 --- a/WordPress/src/main/res/values/key_strings.xml +++ b/WordPress/src/main/res/values/key_strings.xml @@ -173,17 +173,17 @@ -1 - - @string/weekday_sunday - @string/weekday_monday - @string/weekday_tuesday - @string/weekday_wednesday - @string/weekday_thursday - @string/weekday_friday - @string/weekday_saturday + + Sunday + Monday + Tuesday + Wednesday + Thursday + Friday + Saturday - + 0 1 2 diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index eb5377cf8cab..3e59d06a4e75 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -679,14 +679,6 @@ Enable to resize and compress pictures Enable to resize and compress videos - Sunday - Monday - Tuesday - Wednesday - Thursday - Friday - Saturday - Require manual approval for everyone\'s comments. Automatically approve if the user has a previously approved comment Automatically approve everyone\'s comments. @@ -835,7 +827,7 @@ dark default @string/app_theme_entry_value_light - + @string/app_theme_light @string/app_theme_dark @@ -1494,7 +1486,7 @@ Version conflict You\'ve made unsaved changes to this post - @string/local_post_is_conflicted + @string/local_post_is_conflicted You\'ve made unsaved changes to this page diff --git a/WordPress/src/main/res/xml/site_settings.xml b/WordPress/src/main/res/xml/site_settings.xml index 3d89452cfa21..f73fda37e7ed 100644 --- a/WordPress/src/main/res/xml/site_settings.xml +++ b/WordPress/src/main/res/xml/site_settings.xml @@ -141,8 +141,8 @@ diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt index 306cbaa1d67b..c2ca681eeb54 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt @@ -29,20 +29,31 @@ import org.wordpress.android.util.NoDelayCoroutineDispatcher @RunWith(RobolectricTestRunner::class) class ReactNativeRequestHandlerTest { private val reactNativeStore = mock() + private val reactNativeUrlUtil = mock() private val site = mock() + private val pathWithParams = "/wp/v2/media?context=edit" + private val siteId: Long = 1111 + private val siteUrl = "a_site_url" + private val parsedPath = "/wp/v2/media" + private val paramsMap = mapOf("context" to "edit") + private lateinit var subject: ReactNativeRequestHandler @Before fun setUp() { subject = ReactNativeRequestHandler( reactNativeStore, + reactNativeUrlUtil, NoDelayCoroutineDispatcher() ) + + whenever(site.siteId).thenReturn(siteId) + whenever(site.url).thenReturn(siteUrl) } @Test - fun `successful request`() = test { + fun `WPcom get request that succeeds`() = test { whenever(site.isUsingWpComRestApi).thenReturn(true) var calledSuccess = false @@ -56,11 +67,14 @@ class ReactNativeRequestHandlerTest { fail("Error handler should not be called") } + whenever(reactNativeUrlUtil.parseUrlAndParamsForWPCom(pathWithParams, siteId)).thenReturn( + Pair(parsedPath, paramsMap) + ) + val successfulResponseJson = mock() whenever(successfulResponseJson.toString()).thenReturn(jsonAsString) - val fetchResponse = ReactNativeFetchResponse.Success(successfulResponseJson) - whenever(reactNativeStore.executeRequest(site, pathWithParams)).thenReturn(fetchResponse) + whenever(reactNativeStore.performWPComRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) @@ -68,7 +82,7 @@ class ReactNativeRequestHandlerTest { } @Test - fun `failed request`() = test { + fun `WPcom get request that fails`() = test { whenever(site.isUsingWpComRestApi).thenReturn(true) var calledError = false @@ -84,15 +98,80 @@ class ReactNativeRequestHandlerTest { fail("Success handler should not be called") } + whenever(reactNativeUrlUtil.parseUrlAndParamsForWPCom(pathWithParams, siteId)).thenReturn( + Pair(parsedPath, paramsMap) + ) + + val fetchResponse = getFetchResponseError(errorMessage, statusCode) + whenever(reactNativeStore.performWPComRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) + + subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) + + assertTrue(calledError) + } + + @Test + fun `WPorg get request that succeeds`() = test { + whenever(site.isUsingWpComRestApi).thenReturn(false) + + var calledSuccess = false + val jsonAsString = "json_as_string" + val successHandler = Consumer { + if (it != jsonAsString) { fail("expected json was not returned: $it") } + calledSuccess = true + } + + val errorHandler = Consumer { + fail("Error handler should not be called") + } + + whenever(reactNativeUrlUtil.parseUrlAndParamsForWPOrg(pathWithParams, siteUrl)).thenReturn( + Pair(parsedPath, paramsMap) + ) + + val successfulResponseJson = mock() + whenever(successfulResponseJson.toString()).thenReturn(jsonAsString) + val fetchResponse = ReactNativeFetchResponse.Success(successfulResponseJson) + whenever(reactNativeStore.performWPAPIRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) + + subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) + + assertTrue(calledSuccess) + } + + @Test + fun `WPorg get request that fails`() = test { + whenever(site.isUsingWpComRestApi).thenReturn(false) + + var calledError = false + val statusCode = 505 + val errorMessage = "error_message" + val errorHandler = Consumer { + assertEquals(statusCode, it.getInt("code")) + assertEquals(errorMessage, it.getString("message")) + calledError = true + } + + val successHandler = Consumer { + fail("Success handler should not be called") + } + + whenever(reactNativeUrlUtil.parseUrlAndParamsForWPOrg(pathWithParams, siteUrl)).thenReturn( + Pair(parsedPath, paramsMap) + ) + val fetchResponse = getFetchResponseError(errorMessage, statusCode) - whenever(reactNativeStore.executeRequest(site, pathWithParams)).thenReturn(fetchResponse) + whenever(reactNativeStore.performWPAPIRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) assertTrue(calledError) } - private fun getFetchResponseError(errorMessage: String, statusCode: Int): Error { + private fun getFetchResponseError( + errorMessage: String, + statusCode: Int + ): Error { val volleyNetworkResponse = NetworkResponse(statusCode, null, false, 0L, null) val volleyError = VolleyError(volleyNetworkResponse) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt new file mode 100644 index 000000000000..9fe2b1376f6b --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt @@ -0,0 +1,68 @@ +package org.wordpress.android.ui.posts.reactnative + +import android.os.Build +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.wordpress.android.TestApplication + +private const val INPUT_PATH = "/wp/v2/media/54" +private const val INPUT_QUERY_PARAMS = "?context=edit&_locale=user" +private val INPUT_QUERY_PARAMS_MAP = mapOf("context" to "edit", "_locale" to "user") + +@Config(application = TestApplication::class, sdk = [Build.VERSION_CODES.LOLLIPOP]) +@RunWith(RobolectricTestRunner::class) +class ReactNativeUrlUtilTest { + private lateinit var subject: ReactNativeUrlUtil + + @Before + fun setUp() { + subject = ReactNativeUrlUtil() + } + + @Test + fun `successfully generates url and query params for WPcom`() { + val siteId = 555L + + val expectedUrl = "https://public-api.wordpress.com/wp/v2/sites/$siteId/media/54" + val expected = Pair(expectedUrl, INPUT_QUERY_PARAMS_MAP) + + assertEquals(expected, subject.parseUrlAndParamsForWPCom(INPUT_PATH + INPUT_QUERY_PARAMS, siteId)) + } + + @Test + fun `successfully generates url missing query params for WPcom`() { + val siteId = 555L + + val expectedUrl = "https://public-api.wordpress.com/wp/v2/sites/$siteId/media/54" + val expected = Pair(expectedUrl, emptyMap()) + + assertEquals(expected, subject.parseUrlAndParamsForWPCom(INPUT_PATH, siteId)) + } + + @Test + fun `successfully generates url and query params for WPorg`() { + val siteUrl = "https://jurassic.ninja" + + val expectedUrl = "$siteUrl/wp-json/wp/v2/media/54" + + // changes context from edit to view + val expectedParams = INPUT_QUERY_PARAMS_MAP.plus("context" to "view") + + val expected = Pair(expectedUrl, expectedParams) + assertEquals(expected, subject.parseUrlAndParamsForWPOrg(INPUT_PATH + INPUT_QUERY_PARAMS, siteUrl)) + } + + @Test + fun `successfully generates url missing query params for WPorg`() { + val siteUrl = "https://jurassic.ninja" + + val expectedUrl = "$siteUrl/wp-json/wp/v2/media/54" + val expected = Pair(expectedUrl, emptyMap()) + + assertEquals(expected, subject.parseUrlAndParamsForWPOrg(INPUT_PATH, siteUrl)) + } +} diff --git a/build.gradle b/build.gradle index 17ff59a08374..e0e4b1b4e598 100644 --- a/build.gradle +++ b/build.gradle @@ -106,7 +106,7 @@ ext { targetSdkVersion = 28 daggerVersion = '2.22.1' - fluxCVersion = '1.6.10-beta-1' + fluxCVersion = '1.6.9' appCompatVersion = '1.0.2' constraintLayoutVersion = '1.1.3' diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java index 27f08c657bf6..33b3494e28a4 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java @@ -148,8 +148,6 @@ public AztecLoggingException(Throwable originalException) { private static final String TEMP_VIDEO_UPLOADING_CLASS = "data-temp-aztec-video"; private static final String GUTENBERG_BLOCK_START = " + + + diff --git a/WordPress/src/main/res/layout/fragment_prepublishing_tags.xml b/WordPress/src/main/res/layout/fragment_prepublishing_tags.xml new file mode 100644 index 000000000000..22e1c0291c1c --- /dev/null +++ b/WordPress/src/main/res/layout/fragment_prepublishing_tags.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml index a32c6f0b61f9..023e03b1cbb7 100644 --- a/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml +++ b/WordPress/src/main/res/layout/post_prepublishing_bottom_sheet.xml @@ -20,7 +20,7 @@ layout="@layout/bottom_sheet_handle_view" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/margin_extra_large" + android:layout_marginBottom="@dimen/margin_extra_small" app:layout_constraintBottom_toTopOf="@id/prepublishing_content_fragment" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml index b833cd0ab5cb..53b3263cf515 100644 --- a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml +++ b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml @@ -11,13 +11,13 @@ android:layout_width="0dp" android:layout_height="1dp" android:background="?android:attr/listDivider" - app:layout_constraintBottom_toTopOf="@id/action_type" + app:layout_constraintBottom_toTopOf="@id/toolbar_title" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> diff --git a/WordPress/src/main/res/layout/prepublishing_toolbar.xml b/WordPress/src/main/res/layout/prepublishing_toolbar.xml new file mode 100644 index 000000000000..27d37b2c1e8d --- /dev/null +++ b/WordPress/src/main/res/layout/prepublishing_toolbar.xml @@ -0,0 +1,52 @@ + + + + + + + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 1f2ef66bc182..4e88cfd9f2fc 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2736,6 +2736,7 @@ Publish Visibility Tags + Back From b236600e77284b8a910b2efee5f07d722f2943ea Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Mon, 13 Apr 2020 21:05:11 -0500 Subject: [PATCH 072/822] fixed the id type of action_type layout. --- .../src/main/res/layout/prepublishing_action_list_item.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml index 53b3263cf515..0a3097134da7 100644 --- a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml +++ b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml @@ -17,7 +17,7 @@ app:layout_constraintTop_toTopOf="parent" /> Date: Mon, 13 Apr 2020 21:10:55 -0500 Subject: [PATCH 073/822] invalidate adapter so tags are shown. --- .../main/java/org/wordpress/android/ui/posts/TagsFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/TagsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/TagsFragment.java index 6682dea5e629..527a3dc0fca9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/TagsFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/TagsFragment.java @@ -98,6 +98,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mTagsEditText.setText(mTags); mTagsEditText.setSelection(mTagsEditText.length()); } + filterListForCurrentText(); } @Override From 33a5ed3dd82b78716c73c69f1d9bb8bdabf6b464 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Mon, 13 Apr 2020 21:11:15 -0500 Subject: [PATCH 074/822] updated toolbar ui. --- .../src/main/res/drawable/ic_arrow_left_grey_24dp.xml | 8 ++++---- WordPress/src/main/res/drawable/ic_close_grey_24dp.xml | 8 ++++---- WordPress/src/main/res/layout/prepublishing_toolbar.xml | 2 -- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/WordPress/src/main/res/drawable/ic_arrow_left_grey_24dp.xml b/WordPress/src/main/res/drawable/ic_arrow_left_grey_24dp.xml index e668d3c67e87..dae847bd696a 100644 --- a/WordPress/src/main/res/drawable/ic_arrow_left_grey_24dp.xml +++ b/WordPress/src/main/res/drawable/ic_arrow_left_grey_24dp.xml @@ -1,9 +1,9 @@ + android:height="36dp" + android:width="36dp" + android:viewportHeight="36.0" + android:viewportWidth="36.0" > + android:height="36dp" + android:width="36dp" + android:viewportHeight="36.0" + android:viewportWidth="36.0" > diff --git a/WordPress/src/main/res/layout/prepublishing_toolbar.xml b/WordPress/src/main/res/layout/prepublishing_toolbar.xml index 27d37b2c1e8d..e9747d94dcf6 100644 --- a/WordPress/src/main/res/layout/prepublishing_toolbar.xml +++ b/WordPress/src/main/res/layout/prepublishing_toolbar.xml @@ -14,7 +14,6 @@ app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - android:layout_marginStart="@dimen/margin_extra_large" /> Date: Mon, 13 Apr 2020 21:14:22 -0500 Subject: [PATCH 075/822] fixed layout issues. --- .../src/main/res/layout/prepublishing_action_list_item.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml index 0a3097134da7..b833cd0ab5cb 100644 --- a/WordPress/src/main/res/layout/prepublishing_action_list_item.xml +++ b/WordPress/src/main/res/layout/prepublishing_action_list_item.xml @@ -11,7 +11,7 @@ android:layout_width="0dp" android:layout_height="1dp" android:background="?android:attr/listDivider" - app:layout_constraintBottom_toTopOf="@id/toolbar_title" + app:layout_constraintBottom_toTopOf="@id/action_type" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> @@ -44,7 +44,7 @@ android:textColor="?attr/wpColorOnSurfaceMedium" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@id/toolbar_title" + app:layout_constraintStart_toEndOf="@id/action_type" app:layout_constraintTop_toBottomOf="@id/top_divider" tools:text="Action result" /> From c1db2e21e1e76f5b702c9b1b395433cd5e987c44 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Mon, 13 Apr 2020 21:22:12 -0500 Subject: [PATCH 076/822] fixed R import. --- .../wordpress/android/ui/posts/PostSettingsTagsFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostSettingsTagsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostSettingsTagsFragment.kt index f636aea196f9..c75833772e3d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostSettingsTagsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostSettingsTagsFragment.kt @@ -2,12 +2,12 @@ package org.wordpress.android.ui.posts import android.content.Context import android.os.Bundle -import org.wordpress.android.R.layout +import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.fluxc.model.SiteModel class PostSettingsTagsFragment : TagsFragment() { - override fun getContentLayout() = layout.fragment_post_settings_tags + override fun getContentLayout() = R.layout.fragment_post_settings_tags override fun onAttach(context: Context) { super.onAttach(context) From c97cdfdc4b2c4dd707ca6a5407308003b1c79bfb Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Mon, 13 Apr 2020 22:19:11 -0500 Subject: [PATCH 077/822] formatted toolbar layout. --- .../main/res/layout/prepublishing_toolbar.xml | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/WordPress/src/main/res/layout/prepublishing_toolbar.xml b/WordPress/src/main/res/layout/prepublishing_toolbar.xml index e9747d94dcf6..8d0f1dfcb5ab 100644 --- a/WordPress/src/main/res/layout/prepublishing_toolbar.xml +++ b/WordPress/src/main/res/layout/prepublishing_toolbar.xml @@ -1,9 +1,10 @@ + android:layout_height="?actionBarSize"> + - + app:layout_constraintTop_toTopOf="parent" /> + + app:layout_constraintTop_toTopOf="parent" /> + + + From 05f2678805ba12812d33dcdf52b8c60014b45e20 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Tue, 14 Apr 2020 22:24:07 -0500 Subject: [PATCH 078/822] restructured viewmodels and their states. --- .../ui/posts/PrepublishingActionsViewModel.kt | 6 +-- .../posts/PrepublishingBottomSheetFragment.kt | 26 +++++----- .../ui/posts/PrepublishingViewModel.kt | 52 ++++++++++++------- .../PrepublishingActionsViewModelTest.kt | 6 +-- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt index d77be58a64c3..fc31e2841953 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModel.kt @@ -18,8 +18,8 @@ class PrepublishingActionsViewModel @Inject constructor() : ViewModel() { private val _prepublishingActionsUiState = MutableLiveData>() val prepublishingActionsUiState: LiveData> = _prepublishingActionsUiState - private val _prepublishingActionType = MutableLiveData>() - val prepublishingActionType: LiveData> = _prepublishingActionType + private val _onActionClicked = MutableLiveData>() + val onActionClicked: LiveData> = _onActionClicked fun start() { if (isStarted) return @@ -45,6 +45,6 @@ class PrepublishingActionsViewModel @Inject constructor() : ViewModel() { } private fun onActionClicked(actionType: ActionType) { - _prepublishingActionType.postValue(Event(actionType)) + _onActionClicked.postValue(Event(actionType)) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index c1131b2eb799..e654688c5d8c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -17,7 +17,7 @@ import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.login.widgets.WPBottomSheetDialogFragment -import org.wordpress.android.ui.posts.ActionState.TagsActionState +import org.wordpress.android.ui.posts.PrepublishingActionState.TagsActionState import org.wordpress.android.ui.posts.PrepublishingScreen.HOME import javax.inject.Inject @@ -68,32 +68,30 @@ class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment(), TagsSele prepublishingActionsViewModel = ViewModelProviders.of(this, viewModelFactory) .get(PrepublishingActionsViewModel::class.java) - prepublishingActionsViewModel.prepublishingActionType.observe(this, Observer { event -> + prepublishingActionsViewModel.onActionClicked.observe(this, Observer { event -> event.getContentIfNotHandled()?.let { actionType -> - prepublishingViewModel.updateCurrentActionTypeState(actionType) + prepublishingViewModel.onActionClicked(actionType) } }) - prepublishingViewModel.currentActionsState.observe(this, Observer { event -> - event.getContentIfNotHandled()?.let { actionState -> - navigateToScreen(actionState) + prepublishingViewModel.navigationState.observe(this, Observer { event -> + event.getContentIfNotHandled()?.let { uiState -> + navigateToScreen(uiState.prepublishingActionState) } }) - var actionsState = arguments?.getParcelable(KEY_TAGS_ACTION_STATE) - if (actionsState == null) { - actionsState = ActionsState(tagsActionState = TagsActionState(tags = null)) - } - prepublishingViewModel.start(actionsState) + val prepublishingActionState = arguments?.getParcelable(KEY_TAGS_ACTION_STATE) + + prepublishingViewModel.start(prepublishingActionState) } - private fun navigateToScreen(actionState: ActionsState) { - val result = when (actionState.currentScreen) { + private fun navigateToScreen(actionState: PrepublishingActionState) { + val result = when (actionState.prepublishingScreen) { HOME -> Pair(PrepublishingActionsFragment.newInstance(), PrepublishingActionsFragment.TAG) PrepublishingScreen.PUBLISH -> TODO() PrepublishingScreen.VISIBILITY -> TODO() PrepublishingScreen.TAGS -> Pair( - PrepublishingTagsFragment.newInstance(site, actionState.tagsActionState.tags), + PrepublishingTagsFragment.newInstance(site, (actionState as TagsActionState).tags), PrepublishingTagsFragment.TAG ) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt index 1df52c22b604..4e03702976b3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingViewModel.kt @@ -6,8 +6,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import kotlinx.android.parcel.Parcelize -import org.wordpress.android.ui.posts.ActionState.TagsActionState import org.wordpress.android.ui.posts.PrepublishingActionItemUiState.ActionType +import org.wordpress.android.ui.posts.PrepublishingActionState.InitialState +import org.wordpress.android.ui.posts.PrepublishingActionState.TagsActionState import org.wordpress.android.ui.posts.PrepublishingScreen.HOME import org.wordpress.android.ui.posts.PrepublishingScreen.TAGS import org.wordpress.android.viewmodel.Event @@ -22,39 +23,54 @@ enum class PrepublishingScreen { TAGS } -@Parcelize -data class ActionsState(val currentScreen: PrepublishingScreen = HOME, val tagsActionState: TagsActionState) : - Parcelable +sealed class PrepublishingActionState(val prepublishingScreen: PrepublishingScreen) : Parcelable { + @Parcelize + data class TagsActionState(val tags: String? = null) : PrepublishingActionState(TAGS) -sealed class ActionState : Parcelable { @Parcelize - data class TagsActionState(val tags: String?) : ActionState() + object InitialState : PrepublishingActionState(HOME) } +data class PrepublishingNavigationState(val prepublishingActionState: PrepublishingActionState) + class PrepublishingViewModel @Inject constructor() : ViewModel() { private var isStarted = false - private lateinit var actionsState: ActionsState - private val _currentActionsState = MutableLiveData>() - val currentActionsState: LiveData> = _currentActionsState + private var prepublishingActionState: PrepublishingActionState? = null + private val _navigationState = MutableLiveData>() + val navigationState: LiveData> = _navigationState - fun start(actionsState: ActionsState) { + fun start(prepublishingActionState: PrepublishingActionState?) { if (isStarted) return isStarted = true - this.actionsState = actionsState - updateState() + + this.prepublishingActionState = prepublishingActionState + + navigateToScreen() } - private fun updateState() { - _currentActionsState.postValue(Event(actionsState)) + private fun navigateToScreen() { + if (prepublishingActionState != null) { + updateNavigationState(prepublishingActionState as PrepublishingActionState) + } else { + updateNavigationState(InitialState) + } } - fun updateCurrentActionTypeState(actionType: ActionType) { - actionsState = actionsState.copy(currentScreen = TAGS) - updateState() + fun updateNavigationState(state: PrepublishingActionState) { + _navigationState.postValue(Event(PrepublishingNavigationState(state))) } + private + fun writeToBundle(outState: Bundle) { - outState.putParcelable(KEY_TAGS_ACTION_STATE, actionsState) + outState.putParcelable(KEY_TAGS_ACTION_STATE, prepublishingActionState) + } + + fun onActionClicked(actionType: ActionType) { + when (actionType) { + ActionType.TAGS -> updateNavigationState(TagsActionState()) + else -> TODO() + } } } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt index d05374f9c499..df4c43ac0992 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingActionsViewModelTest.kt @@ -46,7 +46,7 @@ class PrepublishingActionsViewModelTest { publishAction?.onActionClicked?.invoke(expectedActionType) // assert - assertThat(requireNotNull(viewModel.prepublishingActionType.value).peekContent()).isEqualTo(expectedActionType) + assertThat(requireNotNull(viewModel.onActionClicked.value).peekContent()).isEqualTo(expectedActionType) } @Test @@ -59,7 +59,7 @@ class PrepublishingActionsViewModelTest { visibilityAction?.onActionClicked?.invoke(expectedActionType) // assert - assertThat(requireNotNull(viewModel.prepublishingActionType.value).peekContent()).isEqualTo(expectedActionType) + assertThat(requireNotNull(viewModel.onActionClicked.value).peekContent()).isEqualTo(expectedActionType) } @Test @@ -72,7 +72,7 @@ class PrepublishingActionsViewModelTest { tagsAction?.onActionClicked?.invoke(expectedActionType) // assert - assertThat(requireNotNull(viewModel.prepublishingActionType.value).peekContent()).isEqualTo(expectedActionType) + assertThat(requireNotNull(viewModel.onActionClicked.value).peekContent()).isEqualTo(expectedActionType) } private fun getActionUiState(actionType: ActionType): PrepublishingActionUiState? { From 3d7bee3b518341e6898949ef0de43d15c33bc40f Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Tue, 14 Apr 2020 22:36:22 -0500 Subject: [PATCH 079/822] fixed theming structure. --- .../android/ui/posts/PrepublishingBottomSheetFragment.kt | 2 +- WordPress/src/main/res/values/styles.xml | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt index e654688c5d8c..696dcc9f82aa 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingBottomSheetFragment.kt @@ -31,7 +31,7 @@ class PrepublishingBottomSheetFragment : WPBottomSheetDialogFragment(), TagsSele override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setStyle(DialogFragment.STYLE_NORMAL, R.style.WordPress_BottomSheetDialogTheme) + setStyle(DialogFragment.STYLE_NORMAL, R.style.WordPress_PrepublishingNudges_BottomSheetDialogTheme) (requireNotNull(activity).application as WordPress).component().inject(this) site = arguments?.getSerializable(SITE) as SiteModel } diff --git a/WordPress/src/main/res/values/styles.xml b/WordPress/src/main/res/values/styles.xml index a81e3ca3dd47..2fd6520a6aa2 100644 --- a/WordPress/src/main/res/values/styles.xml +++ b/WordPress/src/main/res/values/styles.xml @@ -102,7 +102,6 @@ @android:color/transparent false true - adjustResize @style/WordPress.BottomSheetDialogTheme.BottomSheetStyle @@ -121,6 +120,10 @@ 0dp + + + From 005641ebf89a0ac489f6a84cc78e4c75a9058d91 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Mon, 1 Jun 2020 18:27:32 +0530 Subject: [PATCH 543/822] Transform tags to ui state --- .../interests/ReaderInterestsFragment.kt | 19 +++++++------ .../interests/ReaderInterestsViewModel.kt | 27 +++++++++++++++---- .../reader_interests_fragment_layout.xml | 2 +- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index 801c021a1758..7c423be60695 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -10,7 +10,7 @@ import com.google.android.material.chip.Chip import kotlinx.android.synthetic.main.reader_interests_fragment_layout.* import org.wordpress.android.R import org.wordpress.android.WordPress -import org.wordpress.android.models.ReaderTagList +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState import javax.inject.Inject class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layout) { @@ -34,19 +34,22 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo private fun startObserving() { viewModel.uiState.observe(viewLifecycleOwner, Observer { uiState -> - updateInterests(uiState.interests) + updateInterests(uiState.interestsUiState) }) viewModel.start() } - private fun updateInterests(interests: ReaderTagList) { - interests_chip_group.removeAllViews() - for (index in interests.indices) { + private fun updateInterests(interestsUiState: List) { + interestsUiState.forEachIndexed { index, interestTagUiState -> val chip = layoutInflater.inflate(R.layout.reader_interest_filter_chip, interests_chip_group, false) as Chip - chip.layoutDirection = View.LAYOUT_DIRECTION_LOCALE - chip.text = interests[index].tagTitle - chip.tag = interests[index].tagSlug + with(chip) { + layoutDirection = View.LAYOUT_DIRECTION_LOCALE + text = interestTagUiState.title + setOnCheckedChangeListener { _, _ -> // TODO: Pass index to VM + } + } + interests_chip_group.addView(chip) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 1361e218ef18..035118dc5626 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -9,10 +9,10 @@ import org.wordpress.android.models.ReaderTagType.DEFAULT import javax.inject.Inject class ReaderInterestsViewModel @Inject constructor() : ViewModel() { - private var initialized: Boolean = false + var initialized: Boolean = false - private val _uiState = MutableLiveData() - val uiState: LiveData = _uiState + private val _uiState = MutableLiveData() + val uiState: LiveData = _uiState fun start() { if (initialized) return @@ -23,17 +23,34 @@ class ReaderInterestsViewModel @Inject constructor() : ViewModel() { // TODO: get list from tags repository once available val tagList = getMockInterests() if (tagList.isNotEmpty()) { - _uiState.value = ReaderInterestsUiState(tagList) + updateUiState(UiState(transformToInterestsUiState(tagList), tagList)) if (!initialized) { initialized = true } } } - data class ReaderInterestsUiState( + private fun transformToInterestsUiState(interests: ReaderTagList) = + interests.mapIndexed { index, interestTag -> // TODO: use index to know checked status + InterestUiState( + interestTag.tagTitle + ) + } + + private fun updateUiState(uiState: UiState) { + _uiState.value = uiState + } + + data class UiState( + val interestsUiState: List, val interests: ReaderTagList ) + data class InterestUiState( + val title: String, + val isChecked: Boolean = false + ) + private fun getMockInterests() = ReaderTagList().apply { for (c in 'A'..'Z') diff --git a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml index ce5ae00a24d1..996a47cac212 100644 --- a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml +++ b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml @@ -4,7 +4,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:padding="@dimen/margin_extra_large"> + android:padding="@dimen/content_margin"> Date: Mon, 1 Jun 2020 20:21:00 +0530 Subject: [PATCH 544/822] Get tags from repository --- .../interests/ReaderInterestsViewModel.kt | 44 ++++++++----------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 035118dc5626..572f188a87d1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -3,12 +3,15 @@ package org.wordpress.android.ui.reader.discover.interests import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import org.wordpress.android.models.ReaderTag +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch import org.wordpress.android.models.ReaderTagList -import org.wordpress.android.models.ReaderTagType.DEFAULT +import org.wordpress.android.ui.reader.repository.ReaderTagRepository import javax.inject.Inject -class ReaderInterestsViewModel @Inject constructor() : ViewModel() { +class ReaderInterestsViewModel @Inject constructor( + private val readerTagRepository: ReaderTagRepository +) : ViewModel() { var initialized: Boolean = false private val _uiState = MutableLiveData() @@ -20,22 +23,23 @@ class ReaderInterestsViewModel @Inject constructor() : ViewModel() { } private fun loadInterests() { - // TODO: get list from tags repository once available - val tagList = getMockInterests() - if (tagList.isNotEmpty()) { - updateUiState(UiState(transformToInterestsUiState(tagList), tagList)) - if (!initialized) { - initialized = true + viewModelScope.launch { // TODO: Might want to use ScopedViewModel with mainDispatcher for consistency + val tagList = readerTagRepository.getInterests() + if (tagList.isNotEmpty()) { + updateUiState(UiState(transformToInterestsUiState(tagList), tagList)) + if (!initialized) { + initialized = true + } } } } private fun transformToInterestsUiState(interests: ReaderTagList) = - interests.mapIndexed { index, interestTag -> // TODO: use index to know checked status - InterestUiState( - interestTag.tagTitle - ) - } + interests.map { interest -> + InterestUiState( + interest.tagTitle + ) + } private fun updateUiState(uiState: UiState) { _uiState.value = uiState @@ -50,16 +54,4 @@ class ReaderInterestsViewModel @Inject constructor() : ViewModel() { val title: String, val isChecked: Boolean = false ) - - private fun getMockInterests() = - ReaderTagList().apply { - for (c in 'A'..'Z') - (add( - ReaderTag( - c.toString(), c.toString(), c.toString(), - "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", - DEFAULT - ) - )) - } } From 8048ad83980927628d7e77b810c1855a7aafa855 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Mon, 1 Jun 2020 20:24:56 +0530 Subject: [PATCH 545/822] Fix layout margins --- .../reader_interests_fragment_layout.xml | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml index 996a47cac212..174d144c9a7a 100644 --- a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml +++ b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml @@ -4,12 +4,28 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:padding="@dimen/content_margin"> + android:padding="@dimen/margin_medium"> + + + + From 6dc759d1511a134a949f4dec8c26790c4868096c Mon Sep 17 00:00:00 2001 From: ashiagr Date: Mon, 1 Jun 2020 20:33:01 +0530 Subject: [PATCH 546/822] Pass repo to VM in VMTest --- .../discover/interests/ReaderInterestsViewModelTest.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index d1e8392384b2..37b089e2e8e6 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -5,7 +5,9 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner +import org.wordpress.android.ui.reader.repository.ReaderTagRepository @RunWith(MockitoJUnitRunner::class) class ReaderInterestsViewModelTest { @@ -14,9 +16,11 @@ class ReaderInterestsViewModelTest { private lateinit var viewModel: ReaderInterestsViewModel + @Mock lateinit var readerTagRepository: ReaderTagRepository + @Before fun setUp() { - viewModel = ReaderInterestsViewModel() + viewModel = ReaderInterestsViewModel(readerTagRepository) } @Test From 1136bff5ef678ac5912315375733313a40c78fa0 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Mon, 1 Jun 2020 13:27:32 -0400 Subject: [PATCH 547/822] Temporarily disable Slack notifications for failing connected tests --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1b3bbeadbae7..f2e7e9fd3cfe 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -329,7 +329,7 @@ workflows: - Connected Tests: requires: - gutenberg-bundle-build - post-to-slack: true + post-to-slack: false # Always run connected tests on develop and release branches filters: branches: From baae2ea0a4b183e8735ea054a698afea6d81470b Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 1 Jun 2020 16:06:35 -0400 Subject: [PATCH 548/822] Add stub functions to support reader improvement dev --- .../reader/repository/ReaderPostRepository.kt | 37 +++++++++++- .../reader/repository/ReaderTagRepository.kt | 56 +++++++++++++------ 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt index 0b24e7033a64..3b47410052e0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt @@ -1,3 +1,38 @@ package org.wordpress.android.ui.reader.repository -class ReaderPostRepository +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext +import org.wordpress.android.modules.BG_THREAD +import org.wordpress.android.modules.DEFAULT_SCOPE +import java.util.concurrent.TimeUnit +import javax.inject.Inject +import javax.inject.Named + +class ReaderPostRepository @Inject constructor( + @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, + @Named(DEFAULT_SCOPE) private val defaultDispatcher: CoroutineDispatcher +) { + private val mutableDiscoveryFeed = MutableLiveData>() + val discoveryFeed: LiveData> = mutableDiscoveryFeed + + suspend fun getDiscoveryFeed(): LiveData> = + withContext(bgDispatcher) { + delay(TimeUnit.SECONDS.toMillis(5)) + getMockDiscoverFeed() + } + + private suspend fun getMockDiscoverFeed(): LiveData> { + return withContext(defaultDispatcher) { + mutableDiscoveryFeed.postValue(getListOfString()) + discoveryFeed + } + } + + private fun getListOfString() = ArrayList().apply { + for (c in 'A'..'Z') + (add(c.toString())) + }.toList() +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt index 8e0b80762789..7122ca86e250 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt @@ -2,6 +2,7 @@ package org.wordpress.android.ui.reader.repository import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -10,33 +11,28 @@ import kotlinx.coroutines.withContext import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.models.ReaderTagType +import org.wordpress.android.modules.BG_THREAD +import org.wordpress.android.modules.DEFAULT_SCOPE import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit.SECONDS import javax.inject.Inject +import javax.inject.Named /** * ReaderTagRepository is middleware that encapsulates data related business related data logic * Handle communicate with ReaderServices and Actions */ -class ReaderTagRepository @Inject constructor() { - private val mutableTopics = MutableLiveData>() - val topics: LiveData> = mutableTopics +class ReaderTagRepository @Inject constructor( + @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, + @Named(DEFAULT_SCOPE) private val defaultDispatcher: CoroutineDispatcher +) { + private val mutableRecommendedInterests = MutableLiveData() + val recommendedInterests: LiveData = mutableRecommendedInterests suspend fun getInterests(): ReaderTagList = - withContext(Dispatchers.IO) { - delay(SECONDS.toMillis(5)) - getMockInterests() - } - - // todo: remove method post implementation - private fun getMockInterests() = - ReaderTagList().apply { - for (c in 'A'..'Z') - (add(ReaderTag( - c.toString(), c.toString(), c.toString(), - "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", - ReaderTagType.DEFAULT - ))) + withContext(Dispatchers.IO) { + delay(SECONDS.toMillis(5)) + getMockInterests() } // todo: full implementation needed @@ -45,4 +41,30 @@ class ReaderTagRepository @Inject constructor() { delay(TimeUnit.SECONDS.toMillis(5)) } } + + suspend fun getRecommendedInterests(): LiveData = + withContext(bgDispatcher) { + delay(TimeUnit.SECONDS.toMillis(5)) + getMockRecommendedInterests() + } + + private suspend fun getMockRecommendedInterests(): LiveData { + return withContext(defaultDispatcher) { + mutableRecommendedInterests.postValue(getMockInterests()) + recommendedInterests + } + } + + // todo: remove method post implementation + private fun getMockInterests() = + ReaderTagList().apply { + for (c in 'A'..'Z') + (add( + ReaderTag( + c.toString(), c.toString(), c.toString(), + "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", + ReaderTagType.DEFAULT + ) + )) + } } From ee014fccbdd1cda0446862f0cd81be023ab9a4b1 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Tue, 2 Jun 2020 13:51:06 +0530 Subject: [PATCH 549/822] Add tests for show interests --- .../interests/ReaderInterestsViewModel.kt | 11 ++-- .../interests/ReaderInterestsViewModelTest.kt | 54 ++++++++++++++++++- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 572f188a87d1..74946dd6d726 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -2,16 +2,19 @@ package org.wordpress.android.ui.reader.discover.interests import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch import org.wordpress.android.models.ReaderTagList +import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.reader.repository.ReaderTagRepository +import org.wordpress.android.viewmodel.ScopedViewModel import javax.inject.Inject +import javax.inject.Named class ReaderInterestsViewModel @Inject constructor( + @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher, private val readerTagRepository: ReaderTagRepository -) : ViewModel() { +) : ScopedViewModel(mainDispatcher) { var initialized: Boolean = false private val _uiState = MutableLiveData() @@ -23,7 +26,7 @@ class ReaderInterestsViewModel @Inject constructor( } private fun loadInterests() { - viewModelScope.launch { // TODO: Might want to use ScopedViewModel with mainDispatcher for consistency + launch { val tagList = readerTagRepository.getInterests() if (tagList.isNotEmpty()) { updateUiState(UiState(transformToInterestsUiState(tagList), tagList)) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index 37b089e2e8e6..0270e8913f24 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -1,12 +1,21 @@ package org.wordpress.android.ui.reader.discover.interests import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import com.nhaarman.mockitokotlin2.whenever +import kotlinx.coroutines.InternalCoroutinesApi +import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner +import org.wordpress.android.TEST_DISPATCHER +import org.wordpress.android.models.ReaderTag +import org.wordpress.android.models.ReaderTagList +import org.wordpress.android.models.ReaderTagType +import org.wordpress.android.test +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState import org.wordpress.android.ui.reader.repository.ReaderTagRepository @RunWith(MockitoJUnitRunner::class) @@ -18,11 +27,52 @@ class ReaderInterestsViewModelTest { @Mock lateinit var readerTagRepository: ReaderTagRepository + @InternalCoroutinesApi @Before fun setUp() { - viewModel = ReaderInterestsViewModel(readerTagRepository) + viewModel = ReaderInterestsViewModel(TEST_DISPATCHER, readerTagRepository) } @Test - fun `sample test`() {} // TODO: + fun `interests ui correctly loaded if non empty interests received from repo on start`() = test { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + + // When + initViewModel() + + // Then + assertThat(requireNotNull(viewModel.uiState.value).interests).isEqualTo(mockInterests) + assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0]) + .isInstanceOf(InterestUiState::class.java) + assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0].title) + .isEqualTo(mockInterests[0].tagTitle) + } + + @Test + fun `interests ui not updated if no tags received from repo on start`() = test { + // Given + whenever(readerTagRepository.getInterests()).thenReturn(ReaderTagList()) + + // When + initViewModel() + + // Then + assertThat(viewModel.uiState.value).isNull() + } + + private fun initViewModel() = viewModel.start() + + private fun getMockInterests() = + ReaderTagList().apply { + for (c in 'A'..'Z') + (add( + ReaderTag( + c.toString(), c.toString(), c.toString(), + "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", + ReaderTagType.DEFAULT + ) + )) + } } From d2405e221ae8a3d3654ae14c7682d6ac3ffcd6db Mon Sep 17 00:00:00 2001 From: ashiagr Date: Tue, 2 Jun 2020 16:31:42 +0530 Subject: [PATCH 550/822] Propagate and store selected items in the VM --- .../interests/ReaderInterestsFragment.kt | 4 ++- .../interests/ReaderInterestsViewModel.kt | 29 ++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index 7c423be60695..3f7926a19659 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -46,7 +46,9 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo with(chip) { layoutDirection = View.LAYOUT_DIRECTION_LOCALE text = interestTagUiState.title - setOnCheckedChangeListener { _, _ -> // TODO: Pass index to VM + isChecked = interestTagUiState.isChecked + setOnCheckedChangeListener { _, _ -> + viewModel.onInterestAtIndexToggled(index) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 74946dd6d726..c262d65a7946 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch +import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.reader.repository.ReaderTagRepository @@ -20,8 +21,13 @@ class ReaderInterestsViewModel @Inject constructor( private val _uiState = MutableLiveData() val uiState: LiveData = _uiState + private val selectedInterests = ReaderTagList() + fun start() { - if (initialized) return + if (initialized) { + updateUiStateWithSelectedInterests() + return + } loadInterests() } @@ -37,6 +43,17 @@ class ReaderInterestsViewModel @Inject constructor( } } + fun onInterestAtIndexToggled(index: Int) { + uiState.value?.let { + val interestAtIndex = it.interests[index] + if (!selectedInterests.contains(interestAtIndex)) { + selectedInterests.add(interestAtIndex) + } else { + selectedInterests.remove(interestAtIndex) + } + } + } + private fun transformToInterestsUiState(interests: ReaderTagList) = interests.map { interest -> InterestUiState( @@ -44,10 +61,20 @@ class ReaderInterestsViewModel @Inject constructor( ) } + private fun updateUiStateWithSelectedInterests() { + val uiState = uiState.value as UiState + val updatedInterestsUiState = uiState.interestsUiState.mapIndexed { index, interestUiState -> + interestUiState.copy(isChecked = isInterestSelected(uiState.interests[index])) + } + updateUiState(uiState.copy(interestsUiState = updatedInterestsUiState)) + } + private fun updateUiState(uiState: UiState) { _uiState.value = uiState } + private fun isInterestSelected(interest: ReaderTag) = selectedInterests.contains(interest) + data class UiState( val interestsUiState: List, val interests: ReaderTagList From 29e7481efa18940db3122464b49cee5ba7bbe02a Mon Sep 17 00:00:00 2001 From: ashiagr Date: Tue, 2 Jun 2020 18:22:38 +0530 Subject: [PATCH 551/822] Swap ScopedViewModel with viewModelScope --- .../interests/ReaderInterestsViewModel.kt | 11 +-- .../android/MainCoroutineScopeRule.kt | 36 +++++++++ .../interests/ReaderInterestsViewModelTest.kt | 75 ++++++++++--------- 3 files changed, 81 insertions(+), 41 deletions(-) create mode 100644 WordPress/src/test/java/org/wordpress/android/MainCoroutineScopeRule.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 74946dd6d726..03b6f18bedf6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -2,19 +2,16 @@ package org.wordpress.android.ui.reader.discover.interests import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import kotlinx.coroutines.CoroutineDispatcher +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import org.wordpress.android.models.ReaderTagList -import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.reader.repository.ReaderTagRepository -import org.wordpress.android.viewmodel.ScopedViewModel import javax.inject.Inject -import javax.inject.Named class ReaderInterestsViewModel @Inject constructor( - @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher, private val readerTagRepository: ReaderTagRepository -) : ScopedViewModel(mainDispatcher) { +) : ViewModel() { var initialized: Boolean = false private val _uiState = MutableLiveData() @@ -26,7 +23,7 @@ class ReaderInterestsViewModel @Inject constructor( } private fun loadInterests() { - launch { + viewModelScope.launch { val tagList = readerTagRepository.getInterests() if (tagList.isNotEmpty()) { updateUiState(UiState(transformToInterestsUiState(tagList), tagList)) diff --git a/WordPress/src/test/java/org/wordpress/android/MainCoroutineScopeRule.kt b/WordPress/src/test/java/org/wordpress/android/MainCoroutineScopeRule.kt new file mode 100644 index 000000000000..487ca6806517 --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/MainCoroutineScopeRule.kt @@ -0,0 +1,36 @@ +package org.wordpress.android + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestCoroutineDispatcher +import kotlinx.coroutines.test.TestCoroutineScope +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.setMain +import org.junit.rules.TestWatcher +import org.junit.runner.Description + +/** + * MainCoroutineRule installs a TestCoroutineDispatcher for Disptachers.Main. + * + * You may call [DelayController] methods on [MainCoroutineScopeRule] and they will control the + * virtual-clock. + * + * By default, [MainCoroutineScopeRule] will be in a *resumed* state. + * + * @param dispatcher if provided, this [TestCoroutineDispatcher] will be used. + */ +@ExperimentalCoroutinesApi +class MainCoroutineScopeRule(val dispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()) : + TestWatcher(), + TestCoroutineScope by TestCoroutineScope(dispatcher) { + override fun starting(description: Description?) { + super.starting(description) + Dispatchers.setMain(dispatcher) + } + + override fun finished(description: Description?) { + super.finished(description) + cleanupTestCoroutines() + Dispatchers.resetMain() + } +} diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index 0270e8913f24..0e6f15e019db 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -2,7 +2,8 @@ package org.wordpress.android.ui.reader.discover.interests import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.nhaarman.mockitokotlin2.whenever -import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runBlockingTest import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Rule @@ -10,11 +11,10 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner -import org.wordpress.android.TEST_DISPATCHER +import org.wordpress.android.MainCoroutineScopeRule import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.models.ReaderTagType -import org.wordpress.android.test import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState import org.wordpress.android.ui.reader.repository.ReaderTagRepository @@ -23,56 +23,63 @@ class ReaderInterestsViewModelTest { @Rule @JvmField val rule = InstantTaskExecutorRule() + @ExperimentalCoroutinesApi + @Rule + @JvmField val coroutineScope = MainCoroutineScopeRule() + private lateinit var viewModel: ReaderInterestsViewModel @Mock lateinit var readerTagRepository: ReaderTagRepository - @InternalCoroutinesApi @Before fun setUp() { - viewModel = ReaderInterestsViewModel(TEST_DISPATCHER, readerTagRepository) + viewModel = ReaderInterestsViewModel(readerTagRepository) } + @ExperimentalCoroutinesApi @Test - fun `interests ui correctly loaded if non empty interests received from repo on start`() = test { - // Given - val mockInterests = getMockInterests() - whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + fun `interests ui correctly loaded if non empty interests received from repo on start`() = + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) - // When - initViewModel() + // When + initViewModel() - // Then - assertThat(requireNotNull(viewModel.uiState.value).interests).isEqualTo(mockInterests) - assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0]) - .isInstanceOf(InterestUiState::class.java) - assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0].title) - .isEqualTo(mockInterests[0].tagTitle) - } + // Then + assertThat(requireNotNull(viewModel.uiState.value).interests).isEqualTo(mockInterests) + assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0]) + .isInstanceOf(InterestUiState::class.java) + assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0].title) + .isEqualTo(mockInterests[0].tagTitle) + } + @ExperimentalCoroutinesApi @Test - fun `interests ui not updated if no tags received from repo on start`() = test { - // Given - whenever(readerTagRepository.getInterests()).thenReturn(ReaderTagList()) + fun `interests ui not updated if no tags received from repo on start`() = + coroutineScope.runBlockingTest { + // Given + whenever(readerTagRepository.getInterests()).thenReturn(ReaderTagList()) - // When - initViewModel() + // When + initViewModel() - // Then - assertThat(viewModel.uiState.value).isNull() - } + // Then + assertThat(viewModel.uiState.value).isNull() + } private fun initViewModel() = viewModel.start() private fun getMockInterests() = ReaderTagList().apply { - for (c in 'A'..'Z') - (add( - ReaderTag( - c.toString(), c.toString(), c.toString(), - "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", - ReaderTagType.DEFAULT - ) - )) + for (c in 'A'..'Z') + (add( + ReaderTag( + c.toString(), c.toString(), c.toString(), + "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", + ReaderTagType.DEFAULT + ) + )) } } From b25a2c8c883f1480b419ad3e0d29949be3a95ec6 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Tue, 2 Jun 2020 19:03:20 +0530 Subject: [PATCH 552/822] Add done button UI --- .../reader_interests_fragment_layout.xml | 37 ++++++++++++++++++- WordPress/src/main/res/values/strings.xml | 2 + 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml index 174d144c9a7a..2f48bee25158 100644 --- a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml +++ b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml @@ -3,8 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent" - android:padding="@dimen/margin_medium"> + android:layout_height="match_parent"> + + + + + + + + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 29e983a145e1..2bf6e164e9c5 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -1695,6 +1695,8 @@ Post saved Turn off site notifications Turn on site notifications + Select a few to continue + Remove the current filter From 71d760d5d76e977578da93b32a89b084ac2f3c52 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 2 Jun 2020 12:32:06 -0300 Subject: [PATCH 553/822] make isRestarting flag feed itself from checkToRestart validation, to make checks consistent and fix null extra bug --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 67f27bb9a582..2402e8eaa21d 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 @@ -445,7 +445,7 @@ protected void onCreate(Bundle savedInstanceState) { FragmentManager fragmentManager = getSupportFragmentManager(); Bundle extras = getIntent().getExtras(); String action = getIntent().getAction(); - boolean isRestarting = !RestartEditorOptions.NO_RESTART.name().equals(extras.getString(EXTRA_RESTART_EDITOR)); + boolean isRestarting = checkToRestart(getIntent()); if (savedInstanceState == null) { if (!getIntent().hasExtra(EXTRA_POST_LOCAL_ID) || Intent.ACTION_SEND.equals(action) From 81257a0d0217d96a0988e2b9f39b4f21cb433447 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 2 Jun 2020 12:18:35 -0400 Subject: [PATCH 554/822] Update wiremock dependency and include jackson-core group --- WordPress/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index d2af31bd9f91..48965fedaaa1 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -252,8 +252,7 @@ dependencies { exclude group: 'com.android.support', module: 'support-v4' exclude module: 'recyclerview-v7' } - androidTestImplementation('com.github.tomakehurst:wiremock:2.23.2') { - exclude group: 'com.fasterxml.jackson.core', module: 'jackson-core' + androidTestImplementation('com.github.tomakehurst:wiremock:2.26.3') { exclude group: 'org.apache.httpcomponents', module: 'httpclient' exclude group: 'org.apache.commons', module: 'commons-lang3' exclude group: 'asm', module: 'asm' From f250065b674bf6650a2b78b0427df3b4113f0772 Mon Sep 17 00:00:00 2001 From: Aditya Date: Tue, 2 Jun 2020 17:22:16 +0100 Subject: [PATCH 555/822] Remove gutenberg submodule update --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 3a073dc2ea6b..a02fbda36f4f 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 3a073dc2ea6bce5276de6ff69ec3e50ec285547a +Subproject commit a02fbda36f4fca543aec4a66a4a413216f0f0fa1 From e45c524beb77ccb0474ce62507ff3ede43a6dfd3 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 2 Jun 2020 13:55:39 -0400 Subject: [PATCH 556/822] Change model to ReaderPostList --- .../reader/repository/ReaderPostRepository.kt | 366 +++++++++++++++++- 1 file changed, 356 insertions(+), 10 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt index 3b47410052e0..be7b19114741 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt @@ -5,6 +5,8 @@ import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.delay import kotlinx.coroutines.withContext +import org.json.JSONObject +import org.wordpress.android.models.ReaderPostList import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.modules.DEFAULT_SCOPE import java.util.concurrent.TimeUnit @@ -15,24 +17,368 @@ class ReaderPostRepository @Inject constructor( @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, @Named(DEFAULT_SCOPE) private val defaultDispatcher: CoroutineDispatcher ) { - private val mutableDiscoveryFeed = MutableLiveData>() - val discoveryFeed: LiveData> = mutableDiscoveryFeed + companion object { + const val discoverJson = "{\n" + + " \"found\": 3978,\n" + + " \"posts\": [\n" + + " {\n" + + " \"ID\": 42190,\n" + + " \"site_ID\": 53424024,\n" + + " \"author\": {\n" + + " \"ID\": 118930156,\n" + + " \"login\": \"carolynannewells\",\n" + + " \"email\": false,\n" + + " \"name\": \"Carolyn Wells\",\n" + + " \"first_name\": \"Carolyn\",\n" + + " \"last_name\": \"Wells\",\n" + + " \"nice_name\": \"carolynannewells\",\n" + + " \"URL\": \"http:\\/\\/onceuponatime66.wordpress.com\",\n" + + " \"avatar_URL\": \"https:\\/\\/0.gravatar.com\\/avatar\\/c5e37740ae83e815e3c4e9ef94367509?s=96&d=identicon&r=G\",\n" + + " \"profile_URL\": \"https:\\/\\/en.gravatar.com\\/carolynannewells\",\n" + + " \"site_ID\": 126167003,\n" + + " \"has_avatar\": true\n" + + " },\n" + + " \"date\": \"2020-06-02T10:00:08-04:00\",\n" + + " \"modified\": \"2020-06-01T19:46:26-04:00\",\n" + + " \"title\": \"Tabitha Farrar on Eating Disorder Recovery\",\n" + + " \"URL\": \"https:\\/\\/discover.wordpress.com\\/2020\\/06\\/02\\/tabitha-farrar-on-eating-disorder-recovery\\/\",\n" + + " \"short_URL\": \"https:\\/\\/wp.me\\/p3Ca1O-aYu\",\n" + + " \"content\": \"

This is content ... Tabitha Farrar, one of the founders of World Eating Disorders Action Day, shares her experience of blogging about recovery — and supporting others in their own journeys.<\\/p>\\n\",\n" + + " \"excerpt\": \"

Tabitha Farrar, one of the founders of World Eating Disorders Action Day, shares her experience of blogging about recovery — and supporting others in their own journeys.<\\/p>\\n\",\n" + + " \"slug\": \"tabitha-farrar-on-eating-disorder-recovery\",\n" + + " \"guid\": \"https:\\/\\/discover.wordpress.com\\/?p=42190\",\n" + + " \"status\": \"publish\",\n" + + " \"sticky\": false,\n" + + " \"password\": \"\",\n" + + " \"parent\": false,\n" + + " \"type\": \"post\",\n" + + " \"discussion\": {\n" + + " \"comments_open\": true,\n" + + " \"comment_status\": \"open\",\n" + + " \"pings_open\": false,\n" + + " \"ping_status\": \"closed\",\n" + + " \"comment_count\": 0\n" + + " },\n" + + " \"likes_enabled\": true,\n" + + " \"sharing_enabled\": true,\n" + + " \"like_count\": 30,\n" + + " \"i_like\": false,\n" + + " \"is_reblogged\": false,\n" + + " \"is_following\": false,\n" + + " \"global_ID\": \"e12043ca2dc1d8d291e8a2837c6253d6\",\n" + + " \"featured_image\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"post_thumbnail\": {\n" + + " \"ID\": 42195,\n" + + " \"URL\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"guid\": \"http:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"mime_type\": \"image\\/png\",\n" + + " \"width\": 1934,\n" + + " \"height\": 1726\n" + + " },\n" + + " \"format\": \"standard\",\n" + + " \"geo\": false,\n" + + " \"menu_order\": 0,\n" + + " \"page_template\": \"\",\n" + + " \"publicize_URLs\": [],\n" + + " \"terms\": {\n" + + " \"category\": {\n" + + " \"Education\": {\n" + + " \"ID\": 1342,\n" + + " \"name\": \"Education\",\n" + + " \"slug\": \"education\",\n" + + " \"description\": \"Resources across disciplines and perspectives on teaching, learning, and the educational system from educators, teachers, and parents.\",\n" + + " \"post_count\": 162,\n" + + " \"parent\": 0,\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/categories\\/slug:education\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/categories\\/slug:education\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"Writing\": {\n" + + " \"ID\": 349,\n" + + " \"name\": \"Writing\",\n" + + " \"slug\": \"writing\",\n" + + " \"description\": \"Writing, advice, and commentary on the act and process of writing, blogging, and publishing.\",\n" + + " \"post_count\": 527,\n" + + " \"parent\": 0,\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/categories\\/slug:writing\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/categories\\/slug:writing\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"post_tag\": {\n" + + " \"#ShareYourStory\": {\n" + + " \"ID\": 83876228,\n" + + " \"name\": \"#ShareYourStory\",\n" + + " \"slug\": \"shareyourstory\",\n" + + " \"description\": \"\",\n" + + " \"post_count\": 1,\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/tags\\/slug:shareyourstory\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/tags\\/slug:shareyourstory\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"World Eating Disorders Action Day\": {\n" + + " \"ID\": 501041846,\n" + + " \"name\": \"World Eating Disorders Action Day\",\n" + + " \"slug\": \"world-eating-disorders-action-day\",\n" + + " \"description\": \"\",\n" + + " \"post_count\": 1,\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"post_format\": {},\n" + + " \"mentions\": {}\n" + + " },\n" + + " \"tags\": {\n" + + " \"World Eating Disorders Action Day\": {\n" + + " \"ID\": 501041846,\n" + + " \"name\": \"World Eating Disorders Action Day\",\n" + + " \"slug\": \"world-eating-disorders-action-day\",\n" + + " \"description\": \"\",\n" + + " \"post_count\": 1,\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " }\n" + + " },\n" + + " \"display_name\": \"world-eating-disorders-action-day\"\n" + + " }\n" + + " },\n" + + " \"categories\": {\n" + + " \"Writing\": {\n" + + " \"ID\": 349,\n" + + " \"name\": \"Writing\",\n" + + " \"slug\": \"writing\",\n" + + " \"description\": \"Writing, advice, and commentary on the act and process of writing, blogging, and publishing.\",\n" + + " \"post_count\": 527,\n" + + " \"parent\": 0,\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/categories\\/slug:writing\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/categories\\/slug:writing\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"attachments\": {\n" + + " \"42195\": {\n" + + " \"ID\": 42195,\n" + + " \"URL\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"guid\": \"http:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"date\": \"2020-06-01T12:40:25-04:00\",\n" + + " \"post_ID\": 42190,\n" + + " \"author_ID\": 118930156,\n" + + " \"file\": \"screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"mime_type\": \"image\\/png\",\n" + + " \"extension\": \"png\",\n" + + " \"title\": \"Screen Shot 2020-06-01 at 9.29.38 AM\",\n" + + " \"caption\": \"Neural Rewiring for Eating Disorder Recovery book cover, tabithafarrar.com\",\n" + + " \"description\": \"\",\n" + + " \"alt\": \"\",\n" + + " \"thumbnails\": {\n" + + " \"thumbnail\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=150\",\n" + + " \"medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=315\",\n" + + " \"large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1147\",\n" + + " \"newspack-article-block-landscape-large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200&h=900&crop=1\",\n" + + " \"newspack-article-block-portrait-large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=900&h=1200&crop=1\",\n" + + " \"newspack-article-block-square-large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200&h=1200&crop=1\",\n" + + " \"newspack-article-block-landscape-medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=800&h=600&crop=1\",\n" + + " \"newspack-article-block-portrait-medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=600&h=800&crop=1\",\n" + + " \"newspack-article-block-square-medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=800&h=800&crop=1\",\n" + + " \"newspack-article-block-landscape-small\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=400&h=300&crop=1\",\n" + + " \"newspack-article-block-portrait-small\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=300&h=400&crop=1\",\n" + + " \"newspack-article-block-square-small\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=400&h=400&crop=1\",\n" + + " \"newspack-article-block-landscape-tiny\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=200&h=150&crop=1\",\n" + + " \"newspack-article-block-portrait-tiny\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=150&h=200&crop=1\",\n" + + " \"newspack-article-block-square-tiny\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=200&h=200&crop=1\",\n" + + " \"newspack-article-block-uncropped\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200\"\n" + + " },\n" + + " \"height\": 1726,\n" + + " \"width\": 1934,\n" + + " \"exif\": {\n" + + " \"aperture\": \"0\",\n" + + " \"credit\": \"\",\n" + + " \"camera\": \"\",\n" + + " \"caption\": \"\",\n" + + " \"created_timestamp\": \"0\",\n" + + " \"copyright\": \"\",\n" + + " \"focal_length\": \"0\",\n" + + " \"iso\": \"0\",\n" + + " \"shutter_speed\": \"0\",\n" + + " \"title\": \"\",\n" + + " \"orientation\": \"0\",\n" + + " \"keywords\": []\n" + + " },\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/media\\/42195\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/media\\/42195\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\",\n" + + " \"parent\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/posts\\/42190\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"attachment_count\": 1,\n" + + " \"metadata\": [\n" + + " {\n" + + " \"id\": \"143898\",\n" + + " \"key\": \"geo_public\",\n" + + " \"value\": \"0\"\n" + + " },\n" + + " {\n" + + " \"id\": \"143903\",\n" + + " \"key\": \"_thumbnail_id\",\n" + + " \"value\": \"42195\"\n" + + " },\n" + + " {\n" + + " \"id\": \"143991\",\n" + + " \"key\": \"_wpas_done_22794201\",\n" + + " \"value\": \"1\"\n" + + " },\n" + + " {\n" + + " \"id\": \"143931\",\n" + + " \"key\": \"_wpas_mess\",\n" + + " \"value\": \"On World Eating Disorders Action Day we are sharing the story of Tabitha Farrar and her recovery blog. #ShareYourStory\"\n" + + " }\n" + + " ],\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/read\\/sites\\/53424024\\/posts\\/42190\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/posts\\/42190\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\",\n" + + " \"replies\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/posts\\/42190\\/replies\\/\",\n" + + " \"likes\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/posts\\/42190\\/likes\\/\"\n" + + " },\n" + + " \"data\": {\n" + + " \"site\": {\n" + + " \"ID\": 53424024,\n" + + " \"name\": \"Discover\",\n" + + " \"description\": \"A daily selection of the best content published on WordPress, collected for you by humans who love to read.\",\n" + + " \"URL\": \"https:\\/\\/discover.wordpress.com\",\n" + + " \"jetpack\": false,\n" + + " \"subscribers_count\": 47606255,\n" + + " \"locale\": false,\n" + + " \"icon\": {\n" + + " \"img\": \"https:\\/\\/secure.gravatar.com\\/blavatar\\/c9e4e04719c81ca4936a63ea2dce6ace\",\n" + + " \"ico\": \"https:\\/\\/secure.gravatar.com\\/blavatar\\/c9e4e04719c81ca4936a63ea2dce6ace\"\n" + + " },\n" + + " \"logo\": {\n" + + " \"id\": 0,\n" + + " \"sizes\": [],\n" + + " \"url\": \"\"\n" + + " },\n" + + " \"visible\": null,\n" + + " \"is_private\": false,\n" + + " \"is_coming_soon\": false,\n" + + " \"is_following\": false,\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/help\",\n" + + " \"posts\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/posts\\/\",\n" + + " \"comments\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/comments\\/\",\n" + + " \"xmlrpc\": \"https:\\/\\/discover.wordpress.com\\/xmlrpc.php\"\n" + + " }\n" + + " },\n" + + " \"launch_status\": false,\n" + + " \"site_migration\": null,\n" + + " \"is_fse_active\": false,\n" + + " \"is_fse_eligible\": false,\n" + + " \"is_core_site_editor_enabled\": false\n" + + " },\n" + + " \"likes\": {\n" + + " \"found\": 1,\n" + + " \"i_like\": false,\n" + + " \"site_ID\": 53424024,\n" + + " \"post_ID\": 42190,\n" + + " \"likes\": [\n" + + " {\n" + + " \"ID\": 187315272,\n" + + " \"login\": \"erprashantdeep90\",\n" + + " \"email\": false,\n" + + " \"name\": \"The Incredible Mishra\",\n" + + " \"first_name\": \"The Incredible\",\n" + + " \"last_name\": \"Mishra\",\n" + + " \"nice_name\": \"erprashantdeep90\",\n" + + " \"URL\": \"http:\\/\\/theincrediblemishrawritupsart.wordpress.com\",\n" + + " \"avatar_URL\": \"https:\\/\\/2.gravatar.com\\/avatar\\/2c587712f1bc9bd1eb425e9fa13c76e2?s=96&d=identicon&r=G\",\n" + + " \"profile_URL\": \"https:\\/\\/en.gravatar.com\\/erprashantdeep90\",\n" + + " \"ip_address\": false,\n" + + " \"site_ID\": 178308566,\n" + + " \"site_visible\": true,\n" + + " \"default_avatar\": true\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " },\n" + + " \"capabilities\": {\n" + + " \"publish_post\": false,\n" + + " \"delete_post\": false,\n" + + " \"edit_post\": false\n" + + " },\n" + + " \"other_URLs\": {},\n" + + " \"feed_ID\": 41325786,\n" + + " \"feed_URL\": \"http:\\/\\/discover.wordpress.com\",\n" + + " \"pseudo_ID\": \"e12043ca2dc1d8d291e8a2837c6253d6\",\n" + + " \"is_external\": false,\n" + + " \"site_name\": \"Discover\",\n" + + " \"site_URL\": \"https:\\/\\/discover.wordpress.com\",\n" + + " \"site_is_private\": false,\n" + + " \"featured_media\": {\n" + + " \"uri\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/gettyimages-521952628.jpg\",\n" + + " \"width\": 6260,\n" + + " \"height\": 2832,\n" + + " \"type\": \"image\"\n" + + " },\n" + + " \"use_excerpt\": false,\n" + + " \"is_following_conversation\": false\n" + + " }\n" + + " ],\n" + + " \"meta\": {\n" + + " \"links\": {\n" + + " \"counts\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/post-counts\\/post\"\n" + + " },\n" + + " \"next_page\": \"value=2020-06-02T10%3A00%3A08-04%3A00&id=42190\",\n" + + " \"wpcom\": true\n" + + " }\n" + + "}" + } + + private val mutableDiscoveryFeed = MutableLiveData() + val discoveryFeed: LiveData = mutableDiscoveryFeed - suspend fun getDiscoveryFeed(): LiveData> = + suspend fun getDiscoveryFeed(): LiveData = withContext(bgDispatcher) { delay(TimeUnit.SECONDS.toMillis(5)) getMockDiscoverFeed() } - private suspend fun getMockDiscoverFeed(): LiveData> { + private suspend fun getMockDiscoverFeed(): LiveData { return withContext(defaultDispatcher) { - mutableDiscoveryFeed.postValue(getListOfString()) + mutableDiscoveryFeed.postValue(ReaderPostList.fromJson(JSONObject(discoverJson))) discoveryFeed } } - - private fun getListOfString() = ArrayList().apply { - for (c in 'A'..'Z') - (add(c.toString())) - }.toList() } From c1ea149dc67a57706c39cc28ef60182a1cfb9bb5 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 2 Jun 2020 16:19:58 -0400 Subject: [PATCH 557/822] Show keyboard on entry --- .../sitecreation/domains/SiteCreationDomainsViewModel.kt | 9 ++++++--- .../ui/sitecreation/misc/SearchInputWithHeader.kt | 9 +++++++++ .../sitecreation/misc/SiteCreationSearchInputUiState.kt | 3 ++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/domains/SiteCreationDomainsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/domains/SiteCreationDomainsViewModel.kt index 33e833f66fcd..4d6a955a85e8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/domains/SiteCreationDomainsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/domains/SiteCreationDomainsViewModel.kt @@ -193,7 +193,8 @@ class SiteCreationDomainsViewModel @Inject constructor( searchInputUiState = createSearchInputUiState( showProgress = state is Loading, showClearButton = isNonEmptyUserQuery, - showDivider = state.data.isNotEmpty() + showDivider = state.data.isNotEmpty(), + showKeyboard = true ), contentState = createDomainsUiContentState(query, state), createSiteButtonContainerVisibility = selectedDomain != null @@ -298,13 +299,15 @@ class SiteCreationDomainsViewModel @Inject constructor( private fun createSearchInputUiState( showProgress: Boolean, showClearButton: Boolean, - showDivider: Boolean + showDivider: Boolean, + showKeyboard: Boolean ): SiteCreationSearchInputUiState { return SiteCreationSearchInputUiState( hint = UiStringRes(R.string.new_site_creation_search_domain_input_hint), showProgress = showProgress, showClearButton = showClearButton, - showDivider = showDivider + showDivider = showDivider, + showKeyboard = showKeyboard ) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SearchInputWithHeader.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SearchInputWithHeader.kt index 0bf7d36ea5e5..c7c97468a2ec 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SearchInputWithHeader.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SearchInputWithHeader.kt @@ -9,6 +9,7 @@ import android.widget.EditText import android.widget.TextView import org.wordpress.android.R import org.wordpress.android.ui.utils.UiHelpers +import org.wordpress.android.util.ActivityUtils class SearchInputWithHeader(private val uiHelpers: UiHelpers, rootView: View, onClear: () -> Unit) { private val headerLayout = rootView.findViewById(R.id.header_layout) @@ -61,5 +62,13 @@ class SearchInputWithHeader(private val uiHelpers: UiHelpers, rootView: View, on uiHelpers.updateVisibility(progressBar, uiState.showProgress) uiHelpers.updateVisibility(clearAllLayout, uiState.showClearButton) uiHelpers.updateVisibility(divider, uiState.showDivider) + showKeyboard(uiState.showKeyboard) + } + + private fun showKeyboard(shouldShow: Boolean) { + if (shouldShow) { + searchInput.requestFocus() + ActivityUtils.showKeyboard(searchInput) + } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationSearchInputUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationSearchInputUiState.kt index 91f649ea7d3e..17497cd633f5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationSearchInputUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationSearchInputUiState.kt @@ -6,5 +6,6 @@ data class SiteCreationSearchInputUiState( val hint: UiString, val showProgress: Boolean, val showClearButton: Boolean, - val showDivider: Boolean + val showDivider: Boolean, + val showKeyboard: Boolean ) From 76f0c7a1394ea37e80d5f59b3c155ca81aaa22f6 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Tue, 2 Jun 2020 18:31:05 -0500 Subject: [PATCH 558/822] made click action nullable. --- .../ui/posts/PrepublishingHomeItemUiState.kt | 2 +- .../ui/posts/PrepublishingHomeViewHolder.kt | 2 +- .../ui/posts/PrepublishingHomeViewModel.kt | 32 ++++++++++++------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt index e18dcd2af18e..e121ce6db60c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt @@ -11,7 +11,7 @@ sealed class PrepublishingHomeItemUiState { val actionType: ActionType, var actionResult: UiString? = null, val actionEnabled: Boolean, - val onActionClicked: (actionType: ActionType) -> Unit + val onActionClicked: ((actionType: ActionType) -> Unit)? ) : PrepublishingHomeItemUiState() data class HeaderUiState(val siteName: UiStringText, val siteIconUrl: String) : diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt index c2e1c9196c92..086391c5c062 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt @@ -39,7 +39,7 @@ sealed class PrepublishingHomeViewHolder( if (uiState.actionEnabled) { actionLayout.setOnClickListener { - uiState.onActionClicked.invoke(uiState.actionType) + uiState.onActionClicked?.invoke(uiState.actionType) } } else { actionType.setTextColor(ContextCompat.getColor(itemView.context, R.color.gray_20)) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt index 23638e4af3b8..a1ffe68ca7ed 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt @@ -52,19 +52,27 @@ class PrepublishingHomeViewModel @Inject constructor( val prepublishingHomeUiStateList = mutableListOf().apply { add(HeaderUiState(UiStringText(site.name), StringUtils.notNullStr(site.iconUrl))) - add(HomeUiState( - actionType = VISIBILITY, - actionResult = getPostVisibilityUseCase.getVisibility(editPostRepository).textRes, - actionEnabled = true, - onActionClicked = ::onActionClicked - )) + add( + HomeUiState( + actionType = VISIBILITY, + actionResult = getPostVisibilityUseCase.getVisibility(editPostRepository).textRes, + actionEnabled = true, + onActionClicked = ::onActionClicked + ) + ) - add(HomeUiState( - actionType = PUBLISH, - actionResult = publishDateLabelUseCase.getLabel(editPostRepository), - actionEnabled = editPostRepository.status != PostStatus.PRIVATE, - onActionClicked = ::onActionClicked - )) + add( + HomeUiState( + actionType = PUBLISH, + actionResult = publishDateLabelUseCase.getLabel(editPostRepository), + actionEnabled = editPostRepository.status != PostStatus.PRIVATE, + onActionClicked = if (editPostRepository.status != PostStatus.PRIVATE) { + ::onActionClicked + } else { + null + } + ) + ) if (!editPostRepository.isPage) { add(HomeUiState( From ccb2f80f2d355fa386d996c7d32bd6fe06247730 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Tue, 2 Jun 2020 21:20:12 -0500 Subject: [PATCH 559/822] added private and non private UI for publish date. --- .../ui/posts/PrepublishingHomeItemUiState.kt | 3 ++ .../ui/posts/PrepublishingHomeViewHolder.kt | 6 ++-- .../ui/posts/PrepublishingHomeViewModel.kt | 33 ++++++++++++------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt index e121ce6db60c..2b72565fd8a4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.posts +import androidx.annotation.ColorRes import org.wordpress.android.R import org.wordpress.android.ui.utils.UiString import org.wordpress.android.ui.utils.UiString.UiStringRes @@ -9,7 +10,9 @@ typealias PublishPost = Boolean sealed class PrepublishingHomeItemUiState { data class HomeUiState( val actionType: ActionType, + @ColorRes val actionTypeColor : Int = R.color.black, var actionResult: UiString? = null, + @ColorRes val actionResultColor : Int = R.color.gray_40, val actionEnabled: Boolean, val onActionClicked: ((actionType: ActionType) -> Unit)? ) : PrepublishingHomeItemUiState() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt index 086391c5c062..3434aab8ae5a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt @@ -41,10 +41,10 @@ sealed class PrepublishingHomeViewHolder( actionLayout.setOnClickListener { uiState.onActionClicked?.invoke(uiState.actionType) } - } else { - actionType.setTextColor(ContextCompat.getColor(itemView.context, R.color.gray_20)) - actionResult.setTextColor(ContextCompat.getColor(itemView.context, R.color.gray_20)) } + + actionType.setTextColor(ContextCompat.getColor(itemView.context, uiState.actionTypeColor)) + actionResult.setTextColor(ContextCompat.getColor(itemView.context, uiState.actionResultColor)) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt index a1ffe68ca7ed..00ae686493f4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt @@ -61,18 +61,27 @@ class PrepublishingHomeViewModel @Inject constructor( ) ) - add( - HomeUiState( - actionType = PUBLISH, - actionResult = publishDateLabelUseCase.getLabel(editPostRepository), - actionEnabled = editPostRepository.status != PostStatus.PRIVATE, - onActionClicked = if (editPostRepository.status != PostStatus.PRIVATE) { - ::onActionClicked - } else { - null - } - ) - ) + if (editPostRepository.status != PostStatus.PRIVATE) { + add( + HomeUiState( + actionType = PUBLISH, + actionResult = publishDateLabelUseCase.getLabel(editPostRepository), + actionEnabled = true, + onActionClicked = ::onActionClicked + ) + ) + } else { + add( + HomeUiState( + actionType = PUBLISH, + actionResult = publishDateLabelUseCase.getLabel(editPostRepository), + actionTypeColor = R.color.gray_20, + actionResultColor = R.color.gray_20, + actionEnabled = false, + onActionClicked = null + ) + ) + } if (!editPostRepository.isPage) { add(HomeUiState( From f4a0aa4258c16f3a11fe9ea7aa086c2b21aa7be7 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Wed, 3 Jun 2020 11:17:21 +0530 Subject: [PATCH 560/822] Allow editing an image in Media&Text block Hide Edit from bottom bar if video is selected --- .../ui/photopicker/PhotoPickerAdapter.java | 5 +++++ .../ui/photopicker/PhotoPickerFragment.java | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java index 7e0b5c269148..a290ff07a0cb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java @@ -52,6 +52,8 @@ interface PhotoPickerAdapterListener { void onSelectedCountChanged(int count); void onAdapterLoaded(boolean isEmpty); + + void onItemSelected(boolean isVideo); } private class PhotoPickerItem { @@ -239,6 +241,9 @@ private void setItemSelected(int position, boolean isSelected, boolean updateAft if (isSelected) { mSelectedPositions.add(position); + if (mListener != null) { + mListener.onItemSelected(item.mIsVideo); + } } else { int selectedIndex = mSelectedPositions.indexOf(position); if (selectedIndex > -1) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java index 155587a25117..9e33de81c52f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java @@ -13,6 +13,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.PopupMenu; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -53,6 +54,7 @@ public class PhotoPickerFragment extends Fragment { private static final String KEY_LAST_TAPPED_ICON = "last_tapped_icon"; private static final String KEY_SELECTED_POSITIONS = "selected_positions"; + private static final String KEY_SELECTED_ITEM_IS_VIDEO = "selected_item_is_video"; static final int NUM_COLUMNS = 3; public static final String ARG_BROWSER_TYPE = "browser_type"; @@ -100,6 +102,7 @@ public interface PhotoPickerListener { private MediaBrowserType mBrowserType; private SiteModel mSite; private ArrayList mSelectedPositions; + private boolean mIsSelectedItemVideo; public static PhotoPickerFragment newInstance(@NonNull PhotoPickerListener listener, @NonNull MediaBrowserType browserType, @@ -129,6 +132,9 @@ public void onCreate(@Nullable Bundle savedInstanceState) { if (savedInstanceState.containsKey(KEY_SELECTED_POSITIONS)) { mSelectedPositions = savedInstanceState.getIntegerArrayList(KEY_SELECTED_POSITIONS); } + if (savedInstanceState.containsKey(KEY_SELECTED_ITEM_IS_VIDEO)) { + mIsSelectedItemVideo = savedInstanceState.getBoolean(KEY_SELECTED_ITEM_IS_VIDEO); + } } } @@ -239,7 +245,7 @@ private boolean canShowMediaSourceBottomBar() { } private boolean canShowInsertEditBottomBar() { - return mBrowserType.isGutenbergPicker() && !mBrowserType.isVideoPicker(); + return mBrowserType.isGutenbergPicker(); } @Override @@ -251,6 +257,7 @@ public void onSaveInstanceState(@NonNull Bundle outState) { if (hasAdapter() && getAdapter().getNumSelected() > 0) { ArrayList selectedItems = getAdapter().getSelectedPositions(); outState.putIntegerArrayList(KEY_SELECTED_POSITIONS, selectedItems); + outState.putBoolean(KEY_SELECTED_ITEM_IS_VIDEO, mIsSelectedItemVideo); } } @@ -404,6 +411,12 @@ public void onSelectedCountChanged(int count) { if (activity == null) { return; } + + if (canShowInsertEditBottomBar()) { + TextView editView = mInsertEditBottomBar.findViewById(R.id.text_edit); + editView.setVisibility(mIsSelectedItemVideo ? View.GONE : View.VISIBLE); + } + if (mActionMode == null) { ((AppCompatActivity) activity).startSupportActionMode(new ActionModeCallback()); } @@ -424,6 +437,10 @@ public void onAdapterLoaded(boolean isEmpty) { mRestoreState = null; } } + + @Override public void onItemSelected(boolean isVideo) { + mIsSelectedItemVideo = isVideo; + } }; private boolean hasAdapter() { From 07edd5039f744453e09a1c474ef38c49d6dea91c Mon Sep 17 00:00:00 2001 From: ashiagr Date: Wed, 3 Jun 2020 12:34:44 +0530 Subject: [PATCH 561/822] Add tracking event for Plan details --- .../java/org/wordpress/android/ui/plans/PlansViewModel.kt | 6 +++++- .../org/wordpress/android/analytics/AnalyticsTracker.java | 1 + .../wordpress/android/analytics/AnalyticsTrackerNosara.java | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/plans/PlansViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/plans/PlansViewModel.kt index 9a18d62bcd16..42fdbcba8f19 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/plans/PlansViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/plans/PlansViewModel.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode +import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.action.PlanOffersAction.FETCH_PLAN_OFFERS import org.wordpress.android.fluxc.generated.PlanOffersActionBuilder @@ -17,6 +18,7 @@ import org.wordpress.android.modules.UI_SCOPE import org.wordpress.android.ui.plans.PlansViewModel.PlansListStatus.DONE import org.wordpress.android.util.AppLog import org.wordpress.android.util.AppLog.T +import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import org.wordpress.android.viewmodel.SingleLiveEvent import javax.inject.Inject import javax.inject.Named @@ -25,7 +27,8 @@ class PlansViewModel @Inject constructor( private val dispatcher: Dispatcher, @Suppress("unused") private var plansStore: PlanOffersStore, - @param:Named(UI_SCOPE) private val uiScope: CoroutineScope + @param:Named(UI_SCOPE) private val uiScope: CoroutineScope, + private val analyticsTrackerWrapper: AnalyticsTrackerWrapper ) : ViewModel() { enum class PlansListStatus { DONE, @@ -77,6 +80,7 @@ class PlansViewModel @Inject constructor( } fun onItemClicked(item: PlanOffersModel) { + analyticsTrackerWrapper.track(Stat.OPENED_PLANS_COMPARISON) _showDialog.value = item } diff --git a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java index 6f0cd306cca7..ea7828538eeb 100644 --- a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java +++ b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java @@ -287,6 +287,7 @@ public enum Stat { OPENED_PERSON, OPENED_PLUGIN_DIRECTORY, OPENED_PLANS, + OPENED_PLANS_COMPARISON, OPENED_SHARING_MANAGEMENT, OPENED_SHARING_BUTTON_MANAGEMENT, ACTIVITY_LOG_LIST_OPENED, diff --git a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java index b3832da4acc0..177fe222174e 100644 --- a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java +++ b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java @@ -1746,6 +1746,8 @@ public static String getEventNameForStat(AnalyticsTracker.Stat stat) { case FEATURE_ANNOUNCEMENT_FIND_OUT_MORE_TAPPED: case FEATURE_ANNOUNCEMENT_CLOSE_DIALOG_BUTTON_TAPPED: return "feature_announcement_button_tapped"; + case OPENED_PLANS_COMPARISON: + return "plans_compare"; } return null; } From 81bb2c8285457849da524afad46ec773befc7cac Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Wed, 3 Jun 2020 07:49:27 -0400 Subject: [PATCH 562/822] Fix ktlint --- .../reader/repository/ReaderPostRepository.kt | 203 ++++++++++++------ 1 file changed, 136 insertions(+), 67 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt index be7b19114741..5c6b7dd45eda 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt @@ -33,7 +33,8 @@ class ReaderPostRepository @Inject constructor( " \"last_name\": \"Wells\",\n" + " \"nice_name\": \"carolynannewells\",\n" + " \"URL\": \"http:\\/\\/onceuponatime66.wordpress.com\",\n" + - " \"avatar_URL\": \"https:\\/\\/0.gravatar.com\\/avatar\\/c5e37740ae83e815e3c4e9ef94367509?s=96&d=identicon&r=G\",\n" + + " \"avatar_URL\": \"https:\\/\\/0.gravatar.com\\/avatar\\/" + + "c5e37740ae83e815e3c4e9ef94367509?s=96&d=identicon&r=G\",\n" + " \"profile_URL\": \"https:\\/\\/en.gravatar.com\\/carolynannewells\",\n" + " \"site_ID\": 126167003,\n" + " \"has_avatar\": true\n" + @@ -41,10 +42,15 @@ class ReaderPostRepository @Inject constructor( " \"date\": \"2020-06-02T10:00:08-04:00\",\n" + " \"modified\": \"2020-06-01T19:46:26-04:00\",\n" + " \"title\": \"Tabitha Farrar on Eating Disorder Recovery\",\n" + - " \"URL\": \"https:\\/\\/discover.wordpress.com\\/2020\\/06\\/02\\/tabitha-farrar-on-eating-disorder-recovery\\/\",\n" + + " \"URL\": \"https:\\/\\/discover.wordpress.com\\/2020\\/06\\/02\\/" + + "tabitha-farrar-on-eating-disorder-recovery\\/\",\n" + " \"short_URL\": \"https:\\/\\/wp.me\\/p3Ca1O-aYu\",\n" + - " \"content\": \"

This is content ... Tabitha Farrar, one of the founders of World Eating Disorders Action Day, shares her experience of blogging about recovery — and supporting others in their own journeys.<\\/p>\\n\",\n" + - " \"excerpt\": \"

Tabitha Farrar, one of the founders of World Eating Disorders Action Day, shares her experience of blogging about recovery — and supporting others in their own journeys.<\\/p>\\n\",\n" + + " \"content\": \"

This is content ... Tabitha Farrar, one of the founders " + + "of World Eating Disorders Action Day, shares her experience of blogging about " + + "recovery — and supporting others in their own journeys.<\\/p>\\n\",\n" + + " \"excerpt\": \"

Tabitha Farrar, one of the founders of World Eating " + + "Disorders Action Day, shares her experience of blogging about recovery — " + + "and supporting others in their own journeys.<\\/p>\\n\",\n" + " \"slug\": \"tabitha-farrar-on-eating-disorder-recovery\",\n" + " \"guid\": \"https:\\/\\/discover.wordpress.com\\/?p=42190\",\n" + " \"status\": \"publish\",\n" + @@ -66,11 +72,14 @@ class ReaderPostRepository @Inject constructor( " \"is_reblogged\": false,\n" + " \"is_following\": false,\n" + " \"global_ID\": \"e12043ca2dc1d8d291e8a2837c6253d6\",\n" + - " \"featured_image\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"featured_image\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + " \"post_thumbnail\": {\n" + " \"ID\": 42195,\n" + - " \"URL\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + - " \"guid\": \"http:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"URL\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"guid\": \"http:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + " \"mime_type\": \"image\\/png\",\n" + " \"width\": 1934,\n" + " \"height\": 1726\n" + @@ -86,14 +95,18 @@ class ReaderPostRepository @Inject constructor( " \"ID\": 1342,\n" + " \"name\": \"Education\",\n" + " \"slug\": \"education\",\n" + - " \"description\": \"Resources across disciplines and perspectives on teaching, learning, and the educational system from educators, teachers, and parents.\",\n" + + " \"description\": \"Resources across disciplines and perspectives on " + + "teaching, learning, and the educational system from educators, teachers, and parents.\",\n" + " \"post_count\": 162,\n" + " \"parent\": 0,\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/categories\\/slug:education\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/categories\\/slug:education\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/categories\\/slug:education\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/categories\\/slug:education\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\"\n" + " }\n" + " }\n" + " },\n" + @@ -101,14 +114,18 @@ class ReaderPostRepository @Inject constructor( " \"ID\": 349,\n" + " \"name\": \"Writing\",\n" + " \"slug\": \"writing\",\n" + - " \"description\": \"Writing, advice, and commentary on the act and process of writing, blogging, and publishing.\",\n" + + " \"description\": \"Writing, advice, and commentary on the act and " + + "process of writing, blogging, and publishing.\",\n" + " \"post_count\": 527,\n" + " \"parent\": 0,\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/categories\\/slug:writing\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/categories\\/slug:writing\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/categories\\/slug:writing\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/categories\\/slug:writing\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\"\n" + " }\n" + " }\n" + " }\n" + @@ -122,9 +139,12 @@ class ReaderPostRepository @Inject constructor( " \"post_count\": 1,\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/tags\\/slug:shareyourstory\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/tags\\/slug:shareyourstory\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/tags\\/slug:shareyourstory\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/tags\\/slug:shareyourstory\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\"\n" + " }\n" + " }\n" + " },\n" + @@ -136,9 +156,12 @@ class ReaderPostRepository @Inject constructor( " \"post_count\": 1,\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\"\n" + " }\n" + " }\n" + " }\n" + @@ -155,9 +178,12 @@ class ReaderPostRepository @Inject constructor( " \"post_count\": 1,\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/tags\\/slug:world-eating-disorders-action-day\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\"\n" + " }\n" + " },\n" + " \"display_name\": \"world-eating-disorders-action-day\"\n" + @@ -168,14 +194,18 @@ class ReaderPostRepository @Inject constructor( " \"ID\": 349,\n" + " \"name\": \"Writing\",\n" + " \"slug\": \"writing\",\n" + - " \"description\": \"Writing, advice, and commentary on the act and process of writing, blogging, and publishing.\",\n" + + " \"description\": \"Writing, advice, and commentary on the act and " + + "process of writing, blogging, and publishing.\",\n" + " \"post_count\": 527,\n" + " \"parent\": 0,\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/categories\\/slug:writing\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/categories\\/slug:writing\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/categories\\/slug:writing\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/categories\\/slug:writing\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\"\n" + " }\n" + " }\n" + " }\n" + @@ -183,8 +213,10 @@ class ReaderPostRepository @Inject constructor( " \"attachments\": {\n" + " \"42195\": {\n" + " \"ID\": 42195,\n" + - " \"URL\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + - " \"guid\": \"http:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"URL\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + + " \"guid\": \"http:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png\",\n" + " \"date\": \"2020-06-01T12:40:25-04:00\",\n" + " \"post_ID\": 42190,\n" + " \"author_ID\": 118930156,\n" + @@ -192,26 +224,43 @@ class ReaderPostRepository @Inject constructor( " \"mime_type\": \"image\\/png\",\n" + " \"extension\": \"png\",\n" + " \"title\": \"Screen Shot 2020-06-01 at 9.29.38 AM\",\n" + - " \"caption\": \"Neural Rewiring for Eating Disorder Recovery book cover, tabithafarrar.com\",\n" + + " \"caption\": \"Neural Rewiring for Eating Disorder Recovery book cover," + + " tabithafarrar.com\",\n" + " \"description\": \"\",\n" + " \"alt\": \"\",\n" + " \"thumbnails\": {\n" + - " \"thumbnail\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=150\",\n" + - " \"medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=315\",\n" + - " \"large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1147\",\n" + - " \"newspack-article-block-landscape-large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200&h=900&crop=1\",\n" + - " \"newspack-article-block-portrait-large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=900&h=1200&crop=1\",\n" + - " \"newspack-article-block-square-large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200&h=1200&crop=1\",\n" + - " \"newspack-article-block-landscape-medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=800&h=600&crop=1\",\n" + - " \"newspack-article-block-portrait-medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=600&h=800&crop=1\",\n" + - " \"newspack-article-block-square-medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=800&h=800&crop=1\",\n" + - " \"newspack-article-block-landscape-small\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=400&h=300&crop=1\",\n" + - " \"newspack-article-block-portrait-small\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=300&h=400&crop=1\",\n" + - " \"newspack-article-block-square-small\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=400&h=400&crop=1\",\n" + - " \"newspack-article-block-landscape-tiny\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=200&h=150&crop=1\",\n" + - " \"newspack-article-block-portrait-tiny\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=150&h=200&crop=1\",\n" + - " \"newspack-article-block-square-tiny\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=200&h=200&crop=1\",\n" + - " \"newspack-article-block-uncropped\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200\"\n" + + " \"thumbnail\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png?w=150\",\n" + + " \"medium\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png?w=315\",\n" + + " \"large\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "screen-shot-2020-06-01-at-9.29.38-am.png?w=1147\",\n" + + " \"newspack-article-block-landscape-large\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200&h=900&crop=1\",\n" + + " \"newspack-article-block-portrait-large\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=900&h=1200&crop=1\",\n" + + " \"newspack-article-block-square-large\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200&h=1200&crop=1\",\n" + + " \"newspack-article-block-landscape-medium\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=800&h=600&crop=1\",\n" + + " \"newspack-article-block-portrait-medium\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=600&h=800&crop=1\",\n" + + " \"newspack-article-block-square-medium\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=800&h=800&crop=1\",\n" + + " \"newspack-article-block-landscape-small\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=400&h=300&crop=1\",\n" + + " \"newspack-article-block-portrait-small\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=300&h=400&crop=1\",\n" + + " \"newspack-article-block-square-small\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=400&h=400&crop=1\",\n" + + " \"newspack-article-block-landscape-tiny\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=200&h=150&crop=1\",\n" + + " \"newspack-article-block-portrait-tiny\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=150&h=200&crop=1\",\n" + + " \"newspack-article-block-square-tiny\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=200&h=200&crop=1\",\n" + + " \"newspack-article-block-uncropped\": \"https:\\/\\/discover.files." + + "wordpress.com\\/2020\\/06\\/screen-shot-2020-06-01-at-9.29.38-am.png?w=1200\"\n" + " },\n" + " \"height\": 1726,\n" + " \"width\": 1934,\n" + @@ -231,10 +280,14 @@ class ReaderPostRepository @Inject constructor( " },\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/media\\/42195\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/media\\/42195\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\",\n" + - " \"parent\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/posts\\/42190\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/media\\/42195\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/media\\/42195\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\",\n" + + " \"parent\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/posts\\/42190\"\n" + " }\n" + " }\n" + " }\n" + @@ -259,29 +312,38 @@ class ReaderPostRepository @Inject constructor( " {\n" + " \"id\": \"143931\",\n" + " \"key\": \"_wpas_mess\",\n" + - " \"value\": \"On World Eating Disorders Action Day we are sharing the story of Tabitha Farrar and her recovery blog. #ShareYourStory\"\n" + + " \"value\": \"On World Eating Disorders Action Day we are sharing the " + + "story of Tabitha Farrar and her recovery blog. #ShareYourStory\"\n" + " }\n" + " ],\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/read\\/sites\\/53424024\\/posts\\/42190\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/posts\\/42190\\/help\",\n" + - " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\",\n" + - " \"replies\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/posts\\/42190\\/replies\\/\",\n" + - " \"likes\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/posts\\/42190\\/likes\\/\"\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/read\\/" + + "sites\\/53424024\\/posts\\/42190\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/posts\\/42190\\/help\",\n" + + " \"site\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\",\n" + + " \"replies\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/posts\\/42190\\/replies\\/\",\n" + + " \"likes\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/posts\\/42190\\/likes\\/\"\n" + " },\n" + " \"data\": {\n" + " \"site\": {\n" + " \"ID\": 53424024,\n" + " \"name\": \"Discover\",\n" + - " \"description\": \"A daily selection of the best content published on WordPress, collected for you by humans who love to read.\",\n" + + " \"description\": \"A daily selection of the best content published on" + + " WordPress, collected for you by humans who love to read.\",\n" + " \"URL\": \"https:\\/\\/discover.wordpress.com\",\n" + " \"jetpack\": false,\n" + " \"subscribers_count\": 47606255,\n" + " \"locale\": false,\n" + " \"icon\": {\n" + - " \"img\": \"https:\\/\\/secure.gravatar.com\\/blavatar\\/c9e4e04719c81ca4936a63ea2dce6ace\",\n" + - " \"ico\": \"https:\\/\\/secure.gravatar.com\\/blavatar\\/c9e4e04719c81ca4936a63ea2dce6ace\"\n" + + " \"img\": \"https:\\/\\/secure.gravatar.com\\/blavatar\\/" + + "c9e4e04719c81ca4936a63ea2dce6ace\",\n" + + " \"ico\": \"https:\\/\\/secure.gravatar.com\\/blavatar\\/" + + "c9e4e04719c81ca4936a63ea2dce6ace\"\n" + " },\n" + " \"logo\": {\n" + " \"id\": 0,\n" + @@ -294,10 +356,14 @@ class ReaderPostRepository @Inject constructor( " \"is_following\": false,\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\",\n" + - " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/help\",\n" + - " \"posts\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/posts\\/\",\n" + - " \"comments\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/sites\\/53424024\\/comments\\/\",\n" + + " \"self\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\",\n" + + " \"help\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/help\",\n" + + " \"posts\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/posts\\/\",\n" + + " \"comments\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.1\\/" + + "sites\\/53424024\\/comments\\/\",\n" + " \"xmlrpc\": \"https:\\/\\/discover.wordpress.com\\/xmlrpc.php\"\n" + " }\n" + " },\n" + @@ -322,7 +388,8 @@ class ReaderPostRepository @Inject constructor( " \"last_name\": \"Mishra\",\n" + " \"nice_name\": \"erprashantdeep90\",\n" + " \"URL\": \"http:\\/\\/theincrediblemishrawritupsart.wordpress.com\",\n" + - " \"avatar_URL\": \"https:\\/\\/2.gravatar.com\\/avatar\\/2c587712f1bc9bd1eb425e9fa13c76e2?s=96&d=identicon&r=G\",\n" + + " \"avatar_URL\": \"https:\\/\\/2.gravatar.com\\/avatar\\/" + + "2c587712f1bc9bd1eb425e9fa13c76e2?s=96&d=identicon&r=G\",\n" + " \"profile_URL\": \"https:\\/\\/en.gravatar.com\\/erprashantdeep90\",\n" + " \"ip_address\": false,\n" + " \"site_ID\": 178308566,\n" + @@ -347,7 +414,8 @@ class ReaderPostRepository @Inject constructor( " \"site_URL\": \"https:\\/\\/discover.wordpress.com\",\n" + " \"site_is_private\": false,\n" + " \"featured_media\": {\n" + - " \"uri\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/gettyimages-521952628.jpg\",\n" + + " \"uri\": \"https:\\/\\/discover.files.wordpress.com\\/2020\\/06\\/" + + "gettyimages-521952628.jpg\",\n" + " \"width\": 6260,\n" + " \"height\": 2832,\n" + " \"type\": \"image\"\n" + @@ -358,7 +426,8 @@ class ReaderPostRepository @Inject constructor( " ],\n" + " \"meta\": {\n" + " \"links\": {\n" + - " \"counts\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/sites\\/53424024\\/post-counts\\/post\"\n" + + " \"counts\": \"https:\\/\\/public-api.wordpress.com\\/rest\\/v1.2\\/" + + "sites\\/53424024\\/post-counts\\/post\"\n" + " },\n" + " \"next_page\": \"value=2020-06-02T10%3A00%3A08-04%3A00&id=42190\",\n" + " \"wpcom\": true\n" + From 3f6822793e299ea52d60659500c4479bced810fe Mon Sep 17 00:00:00 2001 From: ashiagr Date: Wed, 3 Jun 2020 19:21:24 +0530 Subject: [PATCH 563/822] Manage done button state + click action --- .../interests/ReaderInterestsFragment.kt | 28 ++++++- .../interests/ReaderInterestsViewModel.kt | 83 +++++++++++++++---- WordPress/src/main/res/values/strings.xml | 1 + 3 files changed, 92 insertions(+), 20 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index 3f7926a19659..d9a88dca8ca3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -1,6 +1,7 @@ package org.wordpress.android.ui.reader.discover.interests import android.os.Bundle +import android.util.Log import android.view.View import androidx.fragment.app.Fragment import androidx.lifecycle.Observer @@ -10,6 +11,7 @@ import com.google.android.material.chip.Chip import kotlinx.android.synthetic.main.reader_interests_fragment_layout.* import org.wordpress.android.R import org.wordpress.android.WordPress +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState import javax.inject.Inject @@ -24,9 +26,16 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + initDoneButton() initViewModel() } + private fun initDoneButton() { + done_button.setOnClickListener { + viewModel.onDoneButtonClick() + } + } + private fun initViewModel() { viewModel = ViewModelProviders.of(this, viewModelFactory).get(ReaderInterestsViewModel::class.java) startObserving() @@ -35,20 +44,35 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo private fun startObserving() { viewModel.uiState.observe(viewLifecycleOwner, Observer { uiState -> updateInterests(uiState.interestsUiState) + updateDoneButton(uiState.doneButtonUiState) + }) + + viewModel.navigateToDiscover.observe(viewLifecycleOwner, Observer { event -> + event?.getContentIfNotHandled()?.let { + Log.d("ReaderInterestsFragment", "Go to discover") + } }) viewModel.start() } + private fun updateDoneButton(doneButtonUiState: DoneButtonUiState) { + with(done_button) { + isEnabled = doneButtonUiState.enabled + text = getString(doneButtonUiState.titleRes) + } + } + private fun updateInterests(interestsUiState: List) { + interests_chip_group.removeAllViews() interestsUiState.forEachIndexed { index, interestTagUiState -> val chip = layoutInflater.inflate(R.layout.reader_interest_filter_chip, interests_chip_group, false) as Chip with(chip) { layoutDirection = View.LAYOUT_DIRECTION_LOCALE text = interestTagUiState.title isChecked = interestTagUiState.isChecked - setOnCheckedChangeListener { _, _ -> - viewModel.onInterestAtIndexToggled(index) + setOnCheckedChangeListener { _, isChecked -> + viewModel.onInterestAtIndexToggled(index, isChecked) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index e2cb52afe1c1..0dc9d5330afb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -1,13 +1,16 @@ package org.wordpress.android.ui.reader.discover.interests +import androidx.annotation.StringRes import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch +import org.wordpress.android.R import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.ui.reader.repository.ReaderTagRepository +import org.wordpress.android.viewmodel.Event import javax.inject.Inject class ReaderInterestsViewModel @Inject constructor( @@ -18,11 +21,15 @@ class ReaderInterestsViewModel @Inject constructor( private val _uiState = MutableLiveData() val uiState: LiveData = _uiState + private val _navigateToDiscover = MutableLiveData>() + val navigateToDiscover: LiveData> = _navigateToDiscover + private val selectedInterests = ReaderTagList() fun start() { if (initialized) { - updateUiStateWithSelectedInterests() + val uiState = uiState.value as UiState + updateUiState(uiState.copy(interestsUiState = getInterestsUiStateWithSelectedStates())) return } loadInterests() @@ -32,7 +39,7 @@ class ReaderInterestsViewModel @Inject constructor( viewModelScope.launch { val tagList = readerTagRepository.getInterests() if (tagList.isNotEmpty()) { - updateUiState(UiState(transformToInterestsUiState(tagList), tagList)) + updateUiState(UiState(transformToInterestsUiState(tagList), tagList, getDoneButtonUiState())) if (!initialized) { initialized = true } @@ -40,45 +47,85 @@ class ReaderInterestsViewModel @Inject constructor( } } - fun onInterestAtIndexToggled(index: Int) { + fun onInterestAtIndexToggled(index: Int, isChecked: Boolean) { uiState.value?.let { - val interestAtIndex = it.interests[index] - if (!selectedInterests.contains(interestAtIndex)) { - selectedInterests.add(interestAtIndex) - } else { - selectedInterests.remove(interestAtIndex) + val enableDoneButton = selectedInterests.isEmpty() && isChecked + val disableDoneButton = selectedInterests.size == 1 && !isChecked + + updateSelectedInterests(it.interests[index]) + + if (enableDoneButton || disableDoneButton) { + val uiState = uiState.value as UiState + updateUiState( + uiState.copy( + interestsUiState = getInterestsUiStateWithSelectedStates(), + doneButtonUiState = getDoneButtonUiState() + ) + ) } } } + fun onDoneButtonClick() { + viewModelScope.launch { + readerTagRepository.saveInterests(selectedInterests) + _navigateToDiscover.value = Event(Unit) + } + } + + private fun updateSelectedInterests(interestAtIndex: ReaderTag?) { + if (!selectedInterests.contains(interestAtIndex)) { + selectedInterests.add(interestAtIndex) + } else { + selectedInterests.remove(interestAtIndex) + } + } + private fun transformToInterestsUiState(interests: ReaderTagList) = interests.map { interest -> - InterestUiState( - interest.tagTitle - ) + InterestUiState(interest.tagTitle) } - private fun updateUiStateWithSelectedInterests() { + private fun getInterestsUiStateWithSelectedStates(): List { val uiState = uiState.value as UiState - val updatedInterestsUiState = uiState.interestsUiState.mapIndexed { index, interestUiState -> - interestUiState.copy(isChecked = isInterestSelected(uiState.interests[index])) + + return uiState.interestsUiState.mapIndexed { index, interestUiState -> + val interestAtIndex = uiState.interests[index] + val isInterestAtIndexSelected = selectedInterests.contains(interestAtIndex) + + interestUiState.copy(isChecked = isInterestAtIndexSelected) } - updateUiState(uiState.copy(interestsUiState = updatedInterestsUiState)) + } + + private fun getDoneButtonUiState(): DoneButtonUiState { + val doneButtonEnabled = selectedInterests.isNotEmpty() + return DoneButtonUiState( + titleRes = if (doneButtonEnabled) { + R.string.reader_btn_done + } else { + R.string.reader_btn_select_few_interests + }, + enabled = doneButtonEnabled + ) } private fun updateUiState(uiState: UiState) { _uiState.value = uiState } - private fun isInterestSelected(interest: ReaderTag) = selectedInterests.contains(interest) - data class UiState( val interestsUiState: List, - val interests: ReaderTagList + val interests: ReaderTagList, + val doneButtonUiState: DoneButtonUiState ) data class InterestUiState( val title: String, val isChecked: Boolean = false ) + + data class DoneButtonUiState( + @StringRes val titleRes: Int, + val enabled: Boolean = false + ) } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 2bf6e164e9c5..8b238b7dab8d 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -1696,6 +1696,7 @@ Turn off site notifications Turn on site notifications Select a few to continue + Done From 65d0fb1d1b6dc810e1222e3ef2dc0efe3f8540c3 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Wed, 3 Jun 2020 19:21:34 +0530 Subject: [PATCH 564/822] Add done button tests --- .../interests/ReaderInterestsViewModelTest.kt | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index 0e6f15e019db..680ca381f71e 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -12,6 +12,7 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner import org.wordpress.android.MainCoroutineScopeRule +import org.wordpress.android.R import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.models.ReaderTagType @@ -69,6 +70,57 @@ class ReaderInterestsViewModelTest { assertThat(viewModel.uiState.value).isNull() } + @ExperimentalCoroutinesApi + @Test + fun `done button enabled if at least one interest selected`() = + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + + // When + initViewModel() + viewModel.onInterestAtIndexToggled(index = 0, isChecked = true) + + // Then + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.enabled).isEqualTo(true) + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.titleRes) + .isEqualTo(R.string.reader_btn_done) + } + + @ExperimentalCoroutinesApi + @Test + fun `done button disabled if no interest selected`() = + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + + // When + initViewModel() + + // Then + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.enabled).isEqualTo(false) + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.titleRes) + .isEqualTo(R.string.reader_btn_select_few_interests) + } + + @ExperimentalCoroutinesApi + @Test + fun `navigate to discover on done button click`() = + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + + // When + initViewModel() + viewModel.onDoneButtonClick() + + // Then + assertThat(requireNotNull(viewModel.navigateToDiscover.value).peekContent()).isNotNull + } + private fun initViewModel() = viewModel.start() private fun getMockInterests() = From d72f019c0a48eea5ed4ea4117f369fd5c99d1383 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 3 Jun 2020 15:52:49 +0200 Subject: [PATCH 565/822] Fix dagger issues in develop --- .../ui/reader/repository/ReaderPostRepository.kt | 6 +++--- .../ui/reader/repository/ReaderTagRepository.kt | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt index 5c6b7dd45eda..382e8b9eb610 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderPostRepository.kt @@ -8,14 +8,14 @@ import kotlinx.coroutines.withContext import org.json.JSONObject import org.wordpress.android.models.ReaderPostList import org.wordpress.android.modules.BG_THREAD -import org.wordpress.android.modules.DEFAULT_SCOPE +import org.wordpress.android.modules.IO_THREAD import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Named class ReaderPostRepository @Inject constructor( @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, - @Named(DEFAULT_SCOPE) private val defaultDispatcher: CoroutineDispatcher + @Named(IO_THREAD) private val ioDispatcher: CoroutineDispatcher ) { companion object { const val discoverJson = "{\n" + @@ -445,7 +445,7 @@ class ReaderPostRepository @Inject constructor( } private suspend fun getMockDiscoverFeed(): LiveData { - return withContext(defaultDispatcher) { + return withContext(ioDispatcher) { mutableDiscoveryFeed.postValue(ReaderPostList.fromJson(JSONObject(discoverJson))) discoveryFeed } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt index 7122ca86e250..6e93c3a7fe09 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderTagRepository.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -12,7 +11,7 @@ import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.models.ReaderTagType import org.wordpress.android.modules.BG_THREAD -import org.wordpress.android.modules.DEFAULT_SCOPE +import org.wordpress.android.modules.IO_THREAD import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit.SECONDS import javax.inject.Inject @@ -24,20 +23,20 @@ import javax.inject.Named */ class ReaderTagRepository @Inject constructor( @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, - @Named(DEFAULT_SCOPE) private val defaultDispatcher: CoroutineDispatcher + @Named(IO_THREAD) private val ioDispatcher: CoroutineDispatcher ) { private val mutableRecommendedInterests = MutableLiveData() val recommendedInterests: LiveData = mutableRecommendedInterests suspend fun getInterests(): ReaderTagList = - withContext(Dispatchers.IO) { + withContext(ioDispatcher) { delay(SECONDS.toMillis(5)) getMockInterests() } // todo: full implementation needed suspend fun saveInterests(tags: List) { - CoroutineScope(Dispatchers.IO).launch { + CoroutineScope(ioDispatcher).launch { delay(TimeUnit.SECONDS.toMillis(5)) } } @@ -49,7 +48,7 @@ class ReaderTagRepository @Inject constructor( } private suspend fun getMockRecommendedInterests(): LiveData { - return withContext(defaultDispatcher) { + return withContext(ioDispatcher) { mutableRecommendedInterests.postValue(getMockInterests()) recommendedInterests } From 598503259ad9bda4a01f63eaab5e202525248077 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 3 Jun 2020 16:42:38 -0500 Subject: [PATCH 566/822] revert publishPost and used is newPost. --- .../home/usecases/PublishPostImmediatelyUseCase.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCase.kt index 6560bb7f77f0..b343bc68f3b8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCase.kt @@ -10,7 +10,7 @@ import javax.inject.Inject class PublishPostImmediatelyUseCase @Inject constructor(private val dateTimeUtilsWrapper: DateTimeUtilsWrapper) { fun updatePostToPublishImmediately( editPostRepository: EditPostRepository, - publishPost: Boolean + isNewPost: Boolean ) { editPostRepository.updateAsync({ postModel: PostModel -> if (postModel.status == SCHEDULED.toString()) { @@ -18,10 +18,10 @@ class PublishPostImmediatelyUseCase @Inject constructor(private val dateTimeUtil } // when the post is a Draft, Publish Now is shown as the Primary Action but if it's already Published then // Update Now is shown. - if (publishPost) { - postModel.setStatus(PostStatus.PUBLISHED.toString()) - } else { + if (isNewPost) { postModel.setStatus(PostStatus.DRAFT.toString()) + } else { + postModel.setStatus(PostStatus.PUBLISHED.toString()) } true }) From 5a1f25d69cc947887922038967d5f939ebe32288 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 3 Jun 2020 16:50:24 -0500 Subject: [PATCH 567/822] did tests improvements. --- .../usecases/PublishPostImmediatelyUseCaseTest.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCaseTest.kt index a7392a8e65dd..b1fdf66cd8f5 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/PublishPostImmediatelyUseCaseTest.kt @@ -54,14 +54,26 @@ class PublishPostImmediatelyUseCaseTest : BaseUnitTest() { } @Test - fun `EditPostRepository's PostModel should be set with the currentDate`() { + fun `EditPostRepository's PostModel should be set with the currentDate if PostStatus is SCHEDULED`() { // arrange val currentDate = "2020-05-05T20:33:20+0200" whenever(dateTimeUtilsWrapper.currentTimeInIso8601()).thenReturn(currentDate) + editPostRepository.set { PostModel().apply { setStatus(PostStatus.SCHEDULED.toString()) } } // act useCase.updatePostToPublishImmediately(editPostRepository, false) assertThat(editPostRepository.dateCreated).isEqualTo(currentDate) } + + @Test + fun `EditPostRepository's PostModel should not be set with the currentDate if PostStatus is not SCHEDULED`() { + // arrange + editPostRepository.set { PostModel().apply { setStatus(PostStatus.DRAFT.toString()) } } + + // act + useCase.updatePostToPublishImmediately(editPostRepository, false) + + assertThat(editPostRepository.dateCreated).isEmpty() + } } From ad26c2a6cfbc47d775f36873d288ff6851bd2b10 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 3 Jun 2020 18:42:40 -0500 Subject: [PATCH 568/822] added the ability to restore the bottom sheet state --- .../android/ui/posts/PostListMainViewModel.kt | 15 ++++++++++++++- .../android/ui/posts/PostsListActivity.kt | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt index 6ce6ac4d167e..7e9ed4855e0a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt @@ -91,6 +91,7 @@ class PostListMainViewModel @Inject constructor( private lateinit var site: SiteModel private lateinit var editPostRepository: EditPostRepository + var currentBottomSheetPostId: LocalId? = null private val _viewState = MutableLiveData() val viewState: LiveData = _viewState @@ -206,7 +207,12 @@ class PostListMainViewModel @Inject constructor( lifecycleRegistry.markState(Lifecycle.State.CREATED) } - fun start(site: SiteModel, initPreviewState: PostListRemotePreviewState, editPostRepository: EditPostRepository) { + fun start( + site: SiteModel, + initPreviewState: PostListRemotePreviewState, + currentBottomSheetPostId: LocalId, + editPostRepository: EditPostRepository + ) { this.site = site this.editPostRepository = editPostRepository @@ -258,6 +264,12 @@ class PostListMainViewModel @Inject constructor( ) _previewState.value = _previewState.value ?: initPreviewState + currentBottomSheetPostId.let { postId -> + if (postId.value != 0) { + editPostRepository.loadPostByLocalPostId(postId.value) + } + } + lifecycleRegistry.markState(Lifecycle.State.STARTED) uploadStarter.queueUploadFromSite(site) @@ -420,6 +432,7 @@ class PostListMainViewModel @Inject constructor( } private fun showPrepublishingBottomSheet(post: PostModel) { + currentBottomSheetPostId = LocalId(post.id) editPostRepository.loadPostByLocalPostId(post.id) _openPrepublishingBottomSheet.postValue(Event(Unit)) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostsListActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostsListActivity.kt index e5900dd6d955..9446391fd1b4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostsListActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostsListActivity.kt @@ -34,6 +34,7 @@ import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.QuickStartStore import org.wordpress.android.fluxc.store.QuickStartStore.QuickStartTask @@ -69,6 +70,7 @@ import javax.inject.Inject const val EXTRA_TARGET_POST_LOCAL_ID = "targetPostLocalId" const val STATE_KEY_PREVIEW_STATE = "stateKeyPreviewState" +const val STATE_KEY_BOTTOMSHEET_POST_ID = "stateKeyBottomSheetPostId" class PostsListActivity : LocaleAwareActivity(), EditPostActivityHook, @@ -162,9 +164,15 @@ class PostsListActivity : LocaleAwareActivity(), PostListRemotePreviewState.fromInt(savedInstanceState.getInt(STATE_KEY_PREVIEW_STATE, 0)) } + val currentBottomSheetPostId = if (savedInstanceState == null) { + LocalId(0) + } else { + LocalId(savedInstanceState.getInt(STATE_KEY_BOTTOMSHEET_POST_ID, 0)) + } + setupActionBar() setupContent() - initViewModel(initPreviewState) + initViewModel(initPreviewState, currentBottomSheetPostId) loadIntentData(intent) quickStartEvent = savedInstanceState?.getParcelable(QuickStartEvent.KEY) @@ -237,9 +245,9 @@ class PostsListActivity : LocaleAwareActivity(), pager.adapter = postsPagerAdapter } - private fun initViewModel(initPreviewState: PostListRemotePreviewState) { + private fun initViewModel(initPreviewState: PostListRemotePreviewState, currentBottomSheetPostId: LocalId) { viewModel = ViewModelProviders.of(this, viewModelFactory).get(PostListMainViewModel::class.java) - viewModel.start(site, initPreviewState, editPostRepository) + viewModel.start(site, initPreviewState, currentBottomSheetPostId, editPostRepository) viewModel.viewState.observe(this, Observer { state -> state?.let { @@ -503,6 +511,9 @@ class PostsListActivity : LocaleAwareActivity(), viewModel.previewState.value?.let { outState.putInt(STATE_KEY_PREVIEW_STATE, it.value) } + viewModel.currentBottomSheetPostId?.let { + outState.putInt(STATE_KEY_BOTTOMSHEET_POST_ID, it.value) + } } // BasicDialogFragment Callbacks From de37ba5a590510c2fbdf09cc4c0d70aca1be4871 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 3 Jun 2020 19:27:55 -0500 Subject: [PATCH 569/822] fixed tests. --- .../ui/posts/PostListMainViewModelTest.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt index d05a353907e7..6efc07a6c447 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt @@ -12,6 +12,7 @@ import org.junit.Before import org.junit.Test import org.mockito.Mock import org.wordpress.android.BaseUnitTest +import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.ui.posts.PostListViewLayoutType.COMPACT import org.wordpress.android.ui.posts.PostListViewLayoutType.STANDARD @@ -20,6 +21,7 @@ import org.wordpress.android.ui.uploads.UploadStarter class PostListMainViewModelTest : BaseUnitTest() { lateinit var site: SiteModel + private val currentBottomSheetPostId = LocalId(0) @Mock lateinit var uploadStarter: UploadStarter private lateinit var viewModel: PostListMainViewModel @@ -52,7 +54,7 @@ class PostListMainViewModelTest : BaseUnitTest() { @Test fun `when started, it uploads all local drafts`() { - viewModel.start(site, PostListRemotePreviewState.NONE, mock()) + viewModel.start(site, PostListRemotePreviewState.NONE, currentBottomSheetPostId, mock()) verify(uploadStarter, times(1)).queueUploadFromSite(eq(site)) } @@ -60,7 +62,7 @@ class PostListMainViewModelTest : BaseUnitTest() { @Test fun `search is available for wpcom and jetpack sites`() { site.origin = SiteModel.ORIGIN_WPCOM_REST - viewModel.start(site, PostListRemotePreviewState.NONE, mock()) + viewModel.start(site, PostListRemotePreviewState.NONE, currentBottomSheetPostId, mock()) var isSearchAvailable = false viewModel.isSearchAvailable.observeForever { @@ -73,7 +75,7 @@ class PostListMainViewModelTest : BaseUnitTest() { @Test fun `search is not available for xmlrpc sites`() { site.origin = SiteModel.ORIGIN_XMLRPC - viewModel.start(site, PostListRemotePreviewState.NONE, mock()) + viewModel.start(site, PostListRemotePreviewState.NONE, currentBottomSheetPostId, mock()) var isSearchAvailable = true viewModel.isSearchAvailable.observeForever { @@ -86,7 +88,7 @@ class PostListMainViewModelTest : BaseUnitTest() { @Test fun `calling onSearch() updates search query`() { val testSearch = "keyword" - viewModel.start(site, PostListRemotePreviewState.NONE, mock()) + viewModel.start(site, PostListRemotePreviewState.NONE, currentBottomSheetPostId, mock()) var searchQuery: String? = null viewModel.searchQuery.observeForever { @@ -100,7 +102,7 @@ class PostListMainViewModelTest : BaseUnitTest() { @Test fun `expanding and collapsing search triggers isSearchExpanded`() { - viewModel.start(site, PostListRemotePreviewState.NONE, mock()) + viewModel.start(site, PostListRemotePreviewState.NONE, currentBottomSheetPostId, mock()) var isSearchExpanded = false viewModel.isSearchExpanded.observeForever { @@ -118,7 +120,7 @@ class PostListMainViewModelTest : BaseUnitTest() { fun `expanding search after configuration change preserves search query`() { val testSearch = "keyword" - viewModel.start(site, PostListRemotePreviewState.NONE, mock()) + viewModel.start(site, PostListRemotePreviewState.NONE, currentBottomSheetPostId, mock()) var searchQuery: String? = null viewModel.searchQuery.observeForever { @@ -141,7 +143,7 @@ class PostListMainViewModelTest : BaseUnitTest() { @Test fun `search is using compact view mode independently from normal post list`() { - viewModel.start(site, PostListRemotePreviewState.NONE, mock()) + viewModel.start(site, PostListRemotePreviewState.NONE, currentBottomSheetPostId, mock()) assertThat(viewModel.viewLayoutType.value).isEqualTo(STANDARD) // default value var viewLayoutType: PostListViewLayoutType? = null From 0bdfd4ea633164661e03d4a9076b79f6a935783a Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 3 Jun 2020 19:41:28 -0500 Subject: [PATCH 570/822] added tests for currentBottomSheetPostId logic --- .../ui/posts/PostListMainViewModelTest.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt index 6efc07a6c447..f11066385340 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.posts +import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.doReturn import com.nhaarman.mockitokotlin2.eq import com.nhaarman.mockitokotlin2.mock @@ -159,4 +160,30 @@ class PostListMainViewModelTest : BaseUnitTest() { assertThat(viewLayoutType).isEqualTo(STANDARD) } + + @Test + fun `if currentBottomSheetPostId isn't 0 then set the post in editPostRepository from the postStore`(){ + // arrange + val editPostRepository:EditPostRepository = mock() + val bottomSheetPostId = LocalId(2) + + // act + viewModel.start(site, PostListRemotePreviewState.NONE, bottomSheetPostId, editPostRepository) + + // assert + verify(editPostRepository, times(1)).loadPostByLocalPostId(any()) + } + + @Test + fun `if currentBottomSheetPostId is 0 then don't set the post in editPostRepository from the postStore`(){ + // arrange + val editPostRepository:EditPostRepository = mock() + val bottomSheetPostId = LocalId(0) + + // act + viewModel.start(site, PostListRemotePreviewState.NONE, bottomSheetPostId, editPostRepository) + + // assert + verify(editPostRepository, times(0)).loadPostByLocalPostId(any()) + } } From 6b46c65bff0ab73be898a38027567c463d709d0d Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 3 Jun 2020 19:52:25 -0500 Subject: [PATCH 571/822] fixed lint errors. --- .../android/ui/posts/PostListMainViewModelTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt index f11066385340..8367d5367c51 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelTest.kt @@ -162,9 +162,9 @@ class PostListMainViewModelTest : BaseUnitTest() { } @Test - fun `if currentBottomSheetPostId isn't 0 then set the post in editPostRepository from the postStore`(){ + fun `if currentBottomSheetPostId isn't 0 then set the post in editPostRepository from the postStore`() { // arrange - val editPostRepository:EditPostRepository = mock() + val editPostRepository: EditPostRepository = mock() val bottomSheetPostId = LocalId(2) // act @@ -175,9 +175,9 @@ class PostListMainViewModelTest : BaseUnitTest() { } @Test - fun `if currentBottomSheetPostId is 0 then don't set the post in editPostRepository from the postStore`(){ + fun `if currentBottomSheetPostId is 0 then don't set the post in editPostRepository from the postStore`() { // arrange - val editPostRepository:EditPostRepository = mock() + val editPostRepository: EditPostRepository = mock() val bottomSheetPostId = LocalId(0) // act From 262a906ec551307c17cb30235768df1abd7b21fd Mon Sep 17 00:00:00 2001 From: Klymentiy haykov Date: Wed, 3 Jun 2020 20:44:55 -0700 Subject: [PATCH 572/822] Add downsample strategy to thumbnails. --- .../main/java/org/wordpress/android/util/image/ImageManager.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt b/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt index bfb0f0a0c102..03165934d9ae 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt @@ -23,6 +23,7 @@ import androidx.fragment.app.FragmentActivity import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.load.resource.bitmap.CenterCrop +import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.request.target.AppWidgetTarget import com.bumptech.glide.request.target.BaseTarget @@ -448,6 +449,7 @@ class ImageManager @Inject constructor(private val placeholderManager: ImagePlac val thumbnailRequest = GlideApp .with(context) .load(thumbnailUrl) + .downsample(DownsampleStrategy.AT_MOST) .attachRequestListener(listener) return this.thumbnail(thumbnailRequest) } From db4e193ff067b50ef6ad0e22b5434da5e6ee7e00 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Thu, 4 Jun 2020 12:30:36 +0530 Subject: [PATCH 573/822] Add done button states --- .../interests/ReaderInterestsViewModel.kt | 29 +++--- .../interests/ReaderInterestsViewModelTest.kt | 91 +++++++++++-------- 2 files changed, 71 insertions(+), 49 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 0dc9d5330afb..46cda1dbcad3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -9,6 +9,8 @@ import kotlinx.coroutines.launch import org.wordpress.android.R import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonDisabledUiState +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonEnabledUiState import org.wordpress.android.ui.reader.repository.ReaderTagRepository import org.wordpress.android.viewmodel.Event import javax.inject.Inject @@ -97,16 +99,10 @@ class ReaderInterestsViewModel @Inject constructor( } } - private fun getDoneButtonUiState(): DoneButtonUiState { - val doneButtonEnabled = selectedInterests.isNotEmpty() - return DoneButtonUiState( - titleRes = if (doneButtonEnabled) { - R.string.reader_btn_done - } else { - R.string.reader_btn_select_few_interests - }, - enabled = doneButtonEnabled - ) + private fun getDoneButtonUiState() = if (selectedInterests.isNotEmpty()) { + DoneButtonEnabledUiState + } else { + DoneButtonDisabledUiState } private fun updateUiState(uiState: UiState) { @@ -124,8 +120,17 @@ class ReaderInterestsViewModel @Inject constructor( val isChecked: Boolean = false ) - data class DoneButtonUiState( + sealed class DoneButtonUiState( @StringRes val titleRes: Int, val enabled: Boolean = false - ) + ) { + object DoneButtonEnabledUiState : DoneButtonUiState( + titleRes = R.string.reader_btn_done, + enabled = true + ) + object DoneButtonDisabledUiState : DoneButtonUiState( + titleRes = R.string.reader_btn_select_few_interests, + enabled = false + ) + } } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index 680ca381f71e..bd4943eaea20 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -16,6 +16,8 @@ import org.wordpress.android.R import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.models.ReaderTagType +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonDisabledUiState +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonEnabledUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState import org.wordpress.android.ui.reader.repository.ReaderTagRepository @@ -73,53 +75,68 @@ class ReaderInterestsViewModelTest { @ExperimentalCoroutinesApi @Test fun `done button enabled if at least one interest selected`() = - coroutineScope.runBlockingTest { - // Given - val mockInterests = getMockInterests() - whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) - - // When - initViewModel() - viewModel.onInterestAtIndexToggled(index = 0, isChecked = true) - - // Then - assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.enabled).isEqualTo(true) - assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.titleRes) + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + + // When + initViewModel() + viewModel.onInterestAtIndexToggled(index = 0, isChecked = true) + + // Then + assertThat(requireNotNull(viewModel.uiState.value).interestsUiState.filter { it.isChecked }.size) + .isGreaterThanOrEqualTo(1) + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) + .isInstanceOf(DoneButtonEnabledUiState::class.java) + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.titleRes) .isEqualTo(R.string.reader_btn_done) - } + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.enabled) + .isEqualTo(true) + } @ExperimentalCoroutinesApi @Test - fun `done button disabled if no interest selected`() = - coroutineScope.runBlockingTest { - // Given - val mockInterests = getMockInterests() - whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + fun `done button disabled if the only selected interest is deselected`() = + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) - // When - initViewModel() + // When + initViewModel() + // Select an interest + viewModel.onInterestAtIndexToggled(index = 0, isChecked = true) + // Then + assertThat(requireNotNull(viewModel.uiState.value).interestsUiState.filter { it.isChecked }.size) + .isGreaterThanOrEqualTo(1) + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) + .isInstanceOf(DoneButtonEnabledUiState::class.java) - // Then - assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.enabled).isEqualTo(false) - assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.titleRes) - .isEqualTo(R.string.reader_btn_select_few_interests) - } + // Deselect the only selected interest + viewModel.onInterestAtIndexToggled(index = 0, isChecked = false) + // Then + assertThat(requireNotNull(viewModel.uiState.value).interestsUiState.filter { it.isChecked }.size) + .isEqualTo(0) + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) + .isInstanceOf(DoneButtonDisabledUiState::class.java) + } @ExperimentalCoroutinesApi @Test fun `navigate to discover on done button click`() = - coroutineScope.runBlockingTest { - // Given - val mockInterests = getMockInterests() - whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) - - // When - initViewModel() - viewModel.onDoneButtonClick() - - // Then - assertThat(requireNotNull(viewModel.navigateToDiscover.value).peekContent()).isNotNull - } + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + + // When + initViewModel() + viewModel.onDoneButtonClick() + + // Then + assertThat(requireNotNull(viewModel.navigateToDiscover.value).peekContent()).isNotNull + } private fun initViewModel() = viewModel.start() From b2328ab53155e27c6151cf20bd652c51361d34d4 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Thu, 4 Jun 2020 15:37:04 +0530 Subject: [PATCH 574/822] Add done button hidden state --- .../interests/ReaderInterestsFragment.kt | 3 ++ .../interests/ReaderInterestsViewModel.kt | 19 ++++++++--- .../reader_interests_fragment_layout.xml | 7 ++-- .../interests/ReaderInterestsViewModelTest.kt | 34 ++++++++++++++++++- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index d9a88dca8ca3..adf28316ae53 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -13,11 +13,13 @@ import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState +import org.wordpress.android.ui.utils.UiHelpers import javax.inject.Inject class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layout) { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory private lateinit var viewModel: ReaderInterestsViewModel + @Inject lateinit var uiHelpers: UiHelpers override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -61,6 +63,7 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo isEnabled = doneButtonUiState.enabled text = getString(doneButtonUiState.titleRes) } + uiHelpers.updateVisibility(done_button, doneButtonUiState.visible) } private fun updateInterests(interestsUiState: List) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 46cda1dbcad3..8eb1bf63c79f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -11,6 +11,7 @@ import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagList import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonDisabledUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonEnabledUiState +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonHiddenUiState import org.wordpress.android.ui.reader.repository.ReaderTagRepository import org.wordpress.android.viewmodel.Event import javax.inject.Inject @@ -20,7 +21,9 @@ class ReaderInterestsViewModel @Inject constructor( ) : ViewModel() { var initialized: Boolean = false - private val _uiState = MutableLiveData() + private val _uiState: MutableLiveData = MutableLiveData( + UiState(listOf(), ReaderTagList(), DoneButtonHiddenUiState) + ) val uiState: LiveData = _uiState private val _navigateToDiscover = MutableLiveData>() @@ -121,16 +124,22 @@ class ReaderInterestsViewModel @Inject constructor( ) sealed class DoneButtonUiState( - @StringRes val titleRes: Int, - val enabled: Boolean = false + @StringRes val titleRes: Int = R.string.reader_btn_done, + val enabled: Boolean = false, + val visible: Boolean = true ) { object DoneButtonEnabledUiState : DoneButtonUiState( - titleRes = R.string.reader_btn_done, + titleRes = R.string.reader_btn_done, enabled = true ) + object DoneButtonDisabledUiState : DoneButtonUiState( - titleRes = R.string.reader_btn_select_few_interests, + titleRes = R.string.reader_btn_select_few_interests, enabled = false ) + + object DoneButtonHiddenUiState : DoneButtonUiState( + visible = false + ) } } diff --git a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml index 2f48bee25158..a9dc710dab9c 100644 --- a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml +++ b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml @@ -40,7 +40,8 @@ android:id="@+id/bottom_bar" android:layout_width="0dp" android:layout_height="wrap_content" - app:contentPadding="@dimen/margin_medium" + app:contentPaddingLeft="@dimen/margin_medium" + app:contentPaddingRight="@dimen/margin_medium" app:cardCornerRadius="0dp" app:cardElevation="@dimen/appbar_elevation" app:layout_constraintStart_toStartOf="parent" @@ -54,8 +55,8 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/content_margin" android:layout_marginEnd="@dimen/content_margin" - android:layout_marginTop="@dimen/margin_medium" - android:layout_marginBottom="@dimen/margin_small_medium" + android:layout_marginTop="@dimen/margin_extra_large" + android:layout_marginBottom="@dimen/margin_extra_large" android:enabled="false" android:textAllCaps="false" android:text="@string/reader_btn_select_few_interests" /> diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index bd4943eaea20..0a5d2d035d69 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -18,7 +18,9 @@ import org.wordpress.android.models.ReaderTagList import org.wordpress.android.models.ReaderTagType import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonDisabledUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonEnabledUiState +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState.DoneButtonHiddenUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState +import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.UiState import org.wordpress.android.ui.reader.repository.ReaderTagRepository @RunWith(MockitoJUnitRunner::class) @@ -69,7 +71,37 @@ class ReaderInterestsViewModelTest { initViewModel() // Then - assertThat(viewModel.uiState.value).isNull() + assertThat(viewModel.uiState.value).isEqualTo( + UiState( + listOf(), + ReaderTagList(), + DoneButtonHiddenUiState + ) + ) + } + + @ExperimentalCoroutinesApi + @Test + fun `done button hidden on start switches to disabled state when tags received from repo`() = + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + + // Pause dispatcher so we can verify done button initial state + coroutineScope.pauseDispatcher() + + // Trigger data load + initViewModel() + + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) + .isInstanceOf(DoneButtonHiddenUiState::class.java) + + // Resume pending coroutines execution + coroutineScope.resumeDispatcher() + + assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) + .isInstanceOf(DoneButtonDisabledUiState::class.java) } @ExperimentalCoroutinesApi From e19444923b2de2501fa23daf281e4adb528f7c32 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Thu, 4 Jun 2020 15:38:30 +0530 Subject: [PATCH 575/822] Reformat code --- .../interests/ReaderInterestsFragment.kt | 9 +++-- .../interests/ReaderInterestsViewModel.kt | 8 ++++- .../interests/ReaderInterestsViewModelTest.kt | 36 +++++++++---------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index adf28316ae53..ae61a0217e5e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -39,7 +39,8 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo } private fun initViewModel() { - viewModel = ViewModelProviders.of(this, viewModelFactory).get(ReaderInterestsViewModel::class.java) + viewModel = ViewModelProviders.of(this, viewModelFactory) + .get(ReaderInterestsViewModel::class.java) startObserving() } @@ -69,7 +70,11 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo private fun updateInterests(interestsUiState: List) { interests_chip_group.removeAllViews() interestsUiState.forEachIndexed { index, interestTagUiState -> - val chip = layoutInflater.inflate(R.layout.reader_interest_filter_chip, interests_chip_group, false) as Chip + val chip = layoutInflater.inflate( + R.layout.reader_interest_filter_chip, + interests_chip_group, + false + ) as Chip with(chip) { layoutDirection = View.LAYOUT_DIRECTION_LOCALE text = interestTagUiState.title diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt index 8eb1bf63c79f..2e11511446f3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModel.kt @@ -44,7 +44,13 @@ class ReaderInterestsViewModel @Inject constructor( viewModelScope.launch { val tagList = readerTagRepository.getInterests() if (tagList.isNotEmpty()) { - updateUiState(UiState(transformToInterestsUiState(tagList), tagList, getDoneButtonUiState())) + updateUiState( + UiState( + transformToInterestsUiState(tagList), + tagList, + getDoneButtonUiState() + ) + ) if (!initialized) { initialized = true } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index 0a5d2d035d69..71bc403d0257 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -55,9 +55,9 @@ class ReaderInterestsViewModelTest { // Then assertThat(requireNotNull(viewModel.uiState.value).interests).isEqualTo(mockInterests) assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0]) - .isInstanceOf(InterestUiState::class.java) + .isInstanceOf(InterestUiState::class.java) assertThat(requireNotNull(viewModel.uiState.value).interestsUiState[0].title) - .isEqualTo(mockInterests[0].tagTitle) + .isEqualTo(mockInterests[0].tagTitle) } @ExperimentalCoroutinesApi @@ -118,13 +118,13 @@ class ReaderInterestsViewModelTest { // Then assertThat(requireNotNull(viewModel.uiState.value).interestsUiState.filter { it.isChecked }.size) - .isGreaterThanOrEqualTo(1) + .isGreaterThanOrEqualTo(1) assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) - .isInstanceOf(DoneButtonEnabledUiState::class.java) + .isInstanceOf(DoneButtonEnabledUiState::class.java) assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.titleRes) - .isEqualTo(R.string.reader_btn_done) + .isEqualTo(R.string.reader_btn_done) assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState.enabled) - .isEqualTo(true) + .isEqualTo(true) } @ExperimentalCoroutinesApi @@ -141,17 +141,17 @@ class ReaderInterestsViewModelTest { viewModel.onInterestAtIndexToggled(index = 0, isChecked = true) // Then assertThat(requireNotNull(viewModel.uiState.value).interestsUiState.filter { it.isChecked }.size) - .isGreaterThanOrEqualTo(1) + .isGreaterThanOrEqualTo(1) assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) - .isInstanceOf(DoneButtonEnabledUiState::class.java) + .isInstanceOf(DoneButtonEnabledUiState::class.java) // Deselect the only selected interest viewModel.onInterestAtIndexToggled(index = 0, isChecked = false) // Then assertThat(requireNotNull(viewModel.uiState.value).interestsUiState.filter { it.isChecked }.size) - .isEqualTo(0) + .isEqualTo(0) assertThat(requireNotNull(viewModel.uiState.value).doneButtonUiState) - .isInstanceOf(DoneButtonDisabledUiState::class.java) + .isInstanceOf(DoneButtonDisabledUiState::class.java) } @ExperimentalCoroutinesApi @@ -174,13 +174,13 @@ class ReaderInterestsViewModelTest { private fun getMockInterests() = ReaderTagList().apply { - for (c in 'A'..'Z') - (add( - ReaderTag( - c.toString(), c.toString(), c.toString(), - "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", - ReaderTagType.DEFAULT - ) - )) + for (c in 'A'..'Z') + (add( + ReaderTag( + c.toString(), c.toString(), c.toString(), + "https://public-api.wordpress.com/rest/v1.2/read/tags/$c/posts", + ReaderTagType.DEFAULT + ) + )) } } From ccc4a7da41ddb5294a021aed1f31d4e3bd17445c Mon Sep 17 00:00:00 2001 From: ashiagr Date: Thu, 4 Jun 2020 15:39:19 +0530 Subject: [PATCH 576/822] Navigate to discover --- .../discover/interests/ReaderInterestsFragment.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index ae61a0217e5e..84179d3b8fcd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -1,7 +1,6 @@ package org.wordpress.android.ui.reader.discover.interests import android.os.Bundle -import android.util.Log import android.view.View import androidx.fragment.app.Fragment import androidx.lifecycle.Observer @@ -11,6 +10,7 @@ import com.google.android.material.chip.Chip import kotlinx.android.synthetic.main.reader_interests_fragment_layout.* import org.wordpress.android.R import org.wordpress.android.WordPress +import org.wordpress.android.ui.reader.discover.ReaderDiscoverFragment import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState import org.wordpress.android.ui.utils.UiHelpers @@ -52,7 +52,7 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo viewModel.navigateToDiscover.observe(viewLifecycleOwner, Observer { event -> event?.getContentIfNotHandled()?.let { - Log.d("ReaderInterestsFragment", "Go to discover") + navigateToDiscover() } }) @@ -87,4 +87,13 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo interests_chip_group.addView(chip) } } + + private fun navigateToDiscover() { + val fragmentTransaction = parentFragmentManager.beginTransaction() + fragmentTransaction.setCustomAnimations( + R.anim.activity_slide_in_from_right, R.anim.activity_slide_out_to_left, + R.anim.activity_slide_in_from_left, R.anim.activity_slide_out_to_right + ) + fragmentTransaction.replace(R.id.fragment_container, ReaderDiscoverFragment(), tag).commit() + } } From e0cac192fe7ef081f8ce3e52e2df6226cc64ada3 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Thu, 4 Jun 2020 16:15:00 +0530 Subject: [PATCH 577/822] Minor optimization --- .../interests/ReaderInterestsFragment.kt | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index 84179d3b8fcd..b9e65a9e0ebd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -68,23 +68,29 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo } private fun updateInterests(interestsUiState: List) { - interests_chip_group.removeAllViews() interestsUiState.forEachIndexed { index, interestTagUiState -> - val chip = layoutInflater.inflate( - R.layout.reader_interest_filter_chip, - interests_chip_group, - false - ) as Chip + var chip = interests_chip_group.findViewWithTag(interestTagUiState.title) + if (chip == null) { + chip = layoutInflater.inflate( + R.layout.reader_interest_filter_chip, + interests_chip_group, + false + ) as Chip + with(chip) { + layoutDirection = View.LAYOUT_DIRECTION_LOCALE + tag = interestTagUiState.title + setOnCheckedChangeListener { compoundButton, isChecked -> + if (compoundButton.isPressed) { + viewModel.onInterestAtIndexToggled(index, isChecked) + } + } + interests_chip_group.addView(chip) + } + } with(chip) { - layoutDirection = View.LAYOUT_DIRECTION_LOCALE text = interestTagUiState.title isChecked = interestTagUiState.isChecked - setOnCheckedChangeListener { _, isChecked -> - viewModel.onInterestAtIndexToggled(index, isChecked) - } } - - interests_chip_group.addView(chip) } } From c3f6d9b3603d3464276f828757f5472fefc805cf Mon Sep 17 00:00:00 2001 From: ashiagr Date: Thu, 4 Jun 2020 18:23:19 +0530 Subject: [PATCH 578/822] Use fragment transition --- .../reader/discover/interests/ReaderInterestsFragment.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt index b9e65a9e0ebd..069f3cbb47c8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsFragment.kt @@ -10,7 +10,7 @@ import com.google.android.material.chip.Chip import kotlinx.android.synthetic.main.reader_interests_fragment_layout.* import org.wordpress.android.R import org.wordpress.android.WordPress -import org.wordpress.android.ui.reader.discover.ReaderDiscoverFragment +import org.wordpress.android.ui.reader.ReaderFragment import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.DoneButtonUiState import org.wordpress.android.ui.reader.discover.interests.ReaderInterestsViewModel.InterestUiState import org.wordpress.android.ui.utils.UiHelpers @@ -97,9 +97,9 @@ class ReaderInterestsFragment : Fragment(R.layout.reader_interests_fragment_layo private fun navigateToDiscover() { val fragmentTransaction = parentFragmentManager.beginTransaction() fragmentTransaction.setCustomAnimations( - R.anim.activity_slide_in_from_right, R.anim.activity_slide_out_to_left, - R.anim.activity_slide_in_from_left, R.anim.activity_slide_out_to_right + R.anim.fragment_close_enter, R.anim.fragment_close_exit, + R.anim.fragment_close_enter, R.anim.fragment_close_exit ) - fragmentTransaction.replace(R.id.fragment_container, ReaderDiscoverFragment(), tag).commit() + fragmentTransaction.replace(R.id.fragment_container, ReaderFragment(), tag).commit() } } From 95040605cd76cc7fc97bd5b94f7bde179b90f80b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 4 Jun 2020 11:53:34 -0300 Subject: [PATCH 579/822] added comment to clarify functioning of getSelectedSite() and use of hasFullAccessToContent --- .../java/org/wordpress/android/ui/main/WPMainActivity.java | 4 ++++ 1 file changed, 4 insertions(+) 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 9d10f5d07f9f..2e2ec3dd046e 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 @@ -1426,6 +1426,10 @@ private void hideQuickStartSnackBar() { } } + // The first time this is called in onCreate -> initViewModel we still haven't initialized mSelectedSite, + // which hasFullAccessToContent depends on, and as such the state will be initialized with the most restrictive + // rights case (that is, will assume hasFullAccessToContent is false). This is OK and will be frequently checked + // to normalize the UI state whenever mSelectedSite changes. private boolean hasFullAccessToContent() { return SiteUtils.hasFullAccessToContent(getSelectedSite()); } From ba23592d9ed0528818ec928b47121fdcdf14cd0d Mon Sep 17 00:00:00 2001 From: ashiagr Date: Thu, 4 Jun 2020 20:45:58 +0530 Subject: [PATCH 580/822] Add test for saving interests --- .../interests/ReaderInterestsViewModelTest.kt | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt index 71bc403d0257..1ed8a66b49a7 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/interests/ReaderInterestsViewModelTest.kt @@ -1,6 +1,9 @@ package org.wordpress.android.ui.reader.discover.interests import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import com.nhaarman.mockitokotlin2.eq +import com.nhaarman.mockitokotlin2.times +import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runBlockingTest @@ -156,7 +159,7 @@ class ReaderInterestsViewModelTest { @ExperimentalCoroutinesApi @Test - fun `navigate to discover on done button click`() = + fun `navigation to discover triggered on done button click`() = coroutineScope.runBlockingTest { // Given val mockInterests = getMockInterests() @@ -170,6 +173,24 @@ class ReaderInterestsViewModelTest { assertThat(requireNotNull(viewModel.navigateToDiscover.value).peekContent()).isNotNull } + @ExperimentalCoroutinesApi + @Test + fun `selected interests saved on done button click`() = + coroutineScope.runBlockingTest { + // Given + val mockInterests = getMockInterests() + whenever(readerTagRepository.getInterests()).thenReturn(mockInterests) + val selectInterestAtIndex = 2 + + // When + initViewModel() + viewModel.onInterestAtIndexToggled(index = selectInterestAtIndex, isChecked = true) + viewModel.onDoneButtonClick() + + // Then + verify(readerTagRepository, times(1)).saveInterests(eq(listOf(mockInterests[selectInterestAtIndex]))) + } + private fun initViewModel() = viewModel.start() private fun getMockInterests() = From bb35bd4cf4f99ed55a7c4ae0138310765024b1bd Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Jun 2020 12:18:45 -0400 Subject: [PATCH 581/822] Revert "Temporarily disable Slack notifications for failing connected tests" This reverts commit 1136bff5ef678ac5912315375733313a40c78fa0. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f2e7e9fd3cfe..1b3bbeadbae7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -329,7 +329,7 @@ workflows: - Connected Tests: requires: - gutenberg-bundle-build - post-to-slack: false + post-to-slack: true # Always run connected tests on develop and release branches filters: branches: From a50beff89f85b0fd133f2fc4a0ff2978dbbbda65 Mon Sep 17 00:00:00 2001 From: Ajith R N Date: Thu, 4 Jun 2020 22:21:38 +0530 Subject: [PATCH 582/822] Update README.md added notes about avoiding update plugins while building app on Android Studio. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b85532c265e3..62554d1dc82d 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ it on [Google Play](https://play.google.com/store/apps/details?id=org.wordpress. Notes: * To use WordPress.com features (login to WordPress.com, access Reader and Stats, etc) you need a WordPress.com OAuth2 ID and secret. Please read the [OAuth2 Authentication](#oauth2-authentication) section. +* While building the app in Android Studio ignore all the update plugin prompts (updating plugins may resulted in plugin conflicts and interrupt the build process). ## OAuth2 Authentication ## From f3d00ce0053d06ae36d884113660ecbf200eb4d0 Mon Sep 17 00:00:00 2001 From: Ajith R N Date: Thu, 4 Jun 2020 23:19:26 +0530 Subject: [PATCH 583/822] Update README.md updated the note to specifically mention what plugin updates to avoid while using android studio. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62554d1dc82d..3220dc749185 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ it on [Google Play](https://play.google.com/store/apps/details?id=org.wordpress. Notes: * To use WordPress.com features (login to WordPress.com, access Reader and Stats, etc) you need a WordPress.com OAuth2 ID and secret. Please read the [OAuth2 Authentication](#oauth2-authentication) section. -* While building the app in Android Studio ignore all the update plugin prompts (updating plugins may resulted in plugin conflicts and interrupt the build process). +* While loading/building the app in Android Studio ignore the prompt to update the gradle plugin version as that will probably introduce build errors. On the other hand, feel free to update if you are planning to work on ensuring the compatibility of the newer version. ## OAuth2 Authentication ## From 37353d5f655e3270903305852e25643168973719 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Jun 2020 15:55:37 -0400 Subject: [PATCH 584/822] Improve EventBus crash logging by removing top level exception --- .../android/util/CrashLoggingUtils.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt b/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt index e54dda44d3c0..aa1db8394ce0 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt @@ -7,6 +7,10 @@ import io.sentry.core.Sentry import org.wordpress.android.BuildConfig import org.wordpress.android.R +private const val EVENT_BUS_MODULE = "org.greenrobot.eventbus" +private const val EVENT_BUS_EXCEPTION = "EventBusException" +private const val EVENT_BUS_INVOKING_SUBSCRIBER_FAILED_ERROR = "Invoking subscriber failed" + class CrashLoggingUtils { companion object { @JvmStatic fun shouldEnableCrashLogging(context: Context): Boolean { @@ -24,6 +28,21 @@ class CrashLoggingUtils { options.dsn = BuildConfig.SENTRY_DSN options.cacheDirPath = context.cacheDir.absolutePath options.isEnableSessionTracking = true // Release Health tracking + options.setBeforeSend { event, _ -> + if (event.exceptions.size > 1) { + event.exceptions.lastOrNull()?.let { lastException -> + // Remove the "Invoking subscriber failed" exception so that the main error will show up + // in Sentry. This error only means that an exception occurred during an EventBus event and + // it's not particularly useful for debugging. + if (lastException.module == EVENT_BUS_MODULE + && lastException.type == EVENT_BUS_EXCEPTION + && lastException.value == EVENT_BUS_INVOKING_SUBSCRIBER_FAILED_ERROR) { + event.exceptions.remove(lastException) + } + } + } + event + } } Sentry.setTag("version", BuildConfig.VERSION_NAME) } From 94017da34e54d067f7cde64ccea7a11da4633660 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Jun 2020 16:26:19 -0400 Subject: [PATCH 585/822] Fix possible NPE for plugin removed snackbar --- .../android/ui/plugins/PluginDetailActivity.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/plugins/PluginDetailActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/plugins/PluginDetailActivity.java index 4bb164dee36a..669e470d009d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/plugins/PluginDetailActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/plugins/PluginDetailActivity.java @@ -813,9 +813,9 @@ private void showSuccessfulInstallSnackbar() { .show(); } - private void showSuccessfulPluginRemovedSnackbar() { + private void showSuccessfulPluginRemovedSnackbar(String pluginDisplayName) { WPSnackbar.make(mContainer, - getString(R.string.plugin_removed_successfully, mPlugin.getDisplayName()), + getString(R.string.plugin_removed_successfully, pluginDisplayName), Snackbar.LENGTH_LONG) .show(); } @@ -1130,13 +1130,14 @@ public void onSitePluginDeleted(OnSitePluginDeleted event) { return; } + String pluginDisplayName = mPlugin.getDisplayName(); mIsRemovingPlugin = false; cancelRemovePluginProgressDialog(); if (event.isError()) { AppLog.e(T.PLUGINS, "An error occurred while removing the plugin with type: " + event.error.type + " and message: " + event.error.message); String toastMessage = getString(R.string.plugin_updated_failed_detailed, - mPlugin.getDisplayName(), event.error.message); + pluginDisplayName, event.error.message); ToastUtils.showToast(this, toastMessage, Duration.LONG); return; } @@ -1151,7 +1152,7 @@ public void onSitePluginDeleted(OnSitePluginDeleted event) { refreshViews(); invalidateOptionsMenu(); } - showSuccessfulPluginRemovedSnackbar(); + showSuccessfulPluginRemovedSnackbar(pluginDisplayName); } // This check should only handle events for already installed plugins - onSitePluginConfigured, From 563197ac666941a47b4d72c2f84ec18f3a22c52f Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Thu, 4 Jun 2020 16:29:30 -0400 Subject: [PATCH 586/822] Fix ktlint issue in CrashLoggingUtils --- .../java/org/wordpress/android/util/CrashLoggingUtils.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt b/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt index aa1db8394ce0..fedac0acf144 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/CrashLoggingUtils.kt @@ -34,9 +34,9 @@ class CrashLoggingUtils { // Remove the "Invoking subscriber failed" exception so that the main error will show up // in Sentry. This error only means that an exception occurred during an EventBus event and // it's not particularly useful for debugging. - if (lastException.module == EVENT_BUS_MODULE - && lastException.type == EVENT_BUS_EXCEPTION - && lastException.value == EVENT_BUS_INVOKING_SUBSCRIBER_FAILED_ERROR) { + if (lastException.module == EVENT_BUS_MODULE && + lastException.type == EVENT_BUS_EXCEPTION && + lastException.value == EVENT_BUS_INVOKING_SUBSCRIBER_FAILED_ERROR) { event.exceptions.remove(lastException) } } From 14646e11ab192a6f48fc93875dd339f61e32ab87 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 19:34:27 -0500 Subject: [PATCH 587/822] implemented a proper viewholder approach for the home action state ui --- .../android/ui/posts/PrepublishingHomeItemUiState.kt | 4 ++-- .../android/ui/posts/PrepublishingHomeViewHolder.kt | 7 +++---- .../android/ui/posts/PrepublishingHomeViewModel.kt | 12 ++++++------ WordPress/src/main/res/values/colors.xml | 2 ++ .../ui/posts/PrepublishingHomeViewModelTest.kt | 6 +++--- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt index 2b72565fd8a4..ec435991585f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt @@ -12,8 +12,8 @@ sealed class PrepublishingHomeItemUiState { val actionType: ActionType, @ColorRes val actionTypeColor : Int = R.color.black, var actionResult: UiString? = null, - @ColorRes val actionResultColor : Int = R.color.gray_40, - val actionEnabled: Boolean, + @ColorRes val actionResultColor : Int = R.color.prepublishing_publish_date_result_enabled, + val actionClickable: Boolean, val onActionClicked: ((actionType: ActionType) -> Unit)? ) : PrepublishingHomeItemUiState() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt index 3434aab8ae5a..e96d5ec9dbf9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewHolder.kt @@ -37,10 +37,9 @@ sealed class PrepublishingHomeViewHolder( actionResult.text = uiHelpers.getTextOfUiString(itemView.context, resultText) } - if (uiState.actionEnabled) { - actionLayout.setOnClickListener { - uiState.onActionClicked?.invoke(uiState.actionType) - } + actionLayout.isEnabled = uiState.actionClickable + actionLayout.setOnClickListener { + uiState.onActionClicked?.invoke(uiState.actionType) } actionType.setTextColor(ContextCompat.getColor(itemView.context, uiState.actionTypeColor)) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt index 00ae686493f4..ba66c7144509 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt @@ -56,7 +56,7 @@ class PrepublishingHomeViewModel @Inject constructor( HomeUiState( actionType = VISIBILITY, actionResult = getPostVisibilityUseCase.getVisibility(editPostRepository).textRes, - actionEnabled = true, + actionClickable = true, onActionClicked = ::onActionClicked ) ) @@ -66,7 +66,7 @@ class PrepublishingHomeViewModel @Inject constructor( HomeUiState( actionType = PUBLISH, actionResult = publishDateLabelUseCase.getLabel(editPostRepository), - actionEnabled = true, + actionClickable = true, onActionClicked = ::onActionClicked ) ) @@ -75,9 +75,9 @@ class PrepublishingHomeViewModel @Inject constructor( HomeUiState( actionType = PUBLISH, actionResult = publishDateLabelUseCase.getLabel(editPostRepository), - actionTypeColor = R.color.gray_20, - actionResultColor = R.color.gray_20, - actionEnabled = false, + actionTypeColor = R.color.prepublishing_publish_date_disabled, + actionResultColor = R.color.prepublishing_publish_date_disabled, + actionClickable = false, onActionClicked = null ) ) @@ -88,7 +88,7 @@ class PrepublishingHomeViewModel @Inject constructor( actionType = TAGS, actionResult = getPostTagsUseCase.getTags(editPostRepository)?.let { UiStringText(it) } ?: run { UiStringRes(R.string.prepublishing_nudges_home_tags_not_set) }, - actionEnabled = true, + actionClickable = true, onActionClicked = ::onActionClicked ) ) diff --git a/WordPress/src/main/res/values/colors.xml b/WordPress/src/main/res/values/colors.xml index 2a567975ccc6..2822fd5f1f29 100644 --- a/WordPress/src/main/res/values/colors.xml +++ b/WordPress/src/main/res/values/colors.xml @@ -41,6 +41,8 @@ @color/gray_20 + #CBCBCB + #85878D @color/pink_50 diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt index c099e69557ce..208c86a5a59f 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt @@ -292,7 +292,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { val uiState = getHomeUiState(PUBLISH) - assertThat(uiState?.actionEnabled).isFalse() + assertThat(uiState?.actionClickable).isFalse() } @Test @@ -303,7 +303,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { val uiState = getHomeUiState(TAGS) - assertThat(uiState?.actionEnabled).isTrue() + assertThat(uiState?.actionClickable).isTrue() } @Test @@ -314,7 +314,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { val uiState = getHomeUiState(VISIBILITY) - assertThat(uiState?.actionEnabled).isTrue() + assertThat(uiState?.actionClickable).isTrue() } private fun getHeaderUiState() = viewModel.uiState.value?.filterIsInstance(HeaderUiState::class.java)?.first() From 3815aaa377a83dc837c4dc2877739d25a7658922 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 20:53:04 -0500 Subject: [PATCH 588/822] created use case for updating post status and refactored code to support --- .../ui/posts/PrepublishingHomeViewModel.kt | 9 ++- .../usecases/GetPublishDateLabelUseCase.kt | 29 ------- .../PrepublishingVisibilityViewModel.kt | 6 +- .../usecases/UpdatePostStatusUseCase.kt | 28 ++----- .../usecases/UpdateVisibilityUseCase.kt | 33 ++++++++ .../posts/PrepublishingHomeViewModelTest.kt | 11 +-- .../GetPublishDateLabelUseCaseTest.kt | 77 ------------------- .../PrepublishingVisibilityViewModelTest.kt | 6 +- .../usecases/UpdatePostStatusUseCaseTest.kt | 32 ++------ 9 files changed, 63 insertions(+), 168 deletions(-) delete mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCase.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdateVisibilityUseCase.kt delete mode 100644 WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCaseTest.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt index ba66c7144509..d0f147af7cd0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModel.kt @@ -14,7 +14,6 @@ import org.wordpress.android.ui.posts.PrepublishingHomeItemUiState.ActionType.VI import org.wordpress.android.ui.posts.PrepublishingHomeItemUiState.HeaderUiState import org.wordpress.android.ui.posts.PrepublishingHomeItemUiState.HomeUiState import org.wordpress.android.ui.posts.prepublishing.home.usecases.GetButtonUiStateUseCase -import org.wordpress.android.ui.posts.prepublishing.home.usecases.GetPublishDateLabelUseCase import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.GetPostVisibilityUseCase import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.ui.utils.UiString.UiStringText @@ -26,7 +25,7 @@ import javax.inject.Inject class PrepublishingHomeViewModel @Inject constructor( private val getPostTagsUseCase: GetPostTagsUseCase, private val getPostVisibilityUseCase: GetPostVisibilityUseCase, - private val publishDateLabelUseCase: GetPublishDateLabelUseCase, + private val postSettingsUtils: PostSettingsUtils, private val getButtonUiStateUseCase: GetButtonUiStateUseCase, private val analyticsTrackerWrapper: AnalyticsTrackerWrapper ) : ViewModel() { @@ -65,7 +64,8 @@ class PrepublishingHomeViewModel @Inject constructor( add( HomeUiState( actionType = PUBLISH, - actionResult = publishDateLabelUseCase.getLabel(editPostRepository), + actionResult = editPostRepository.getEditablePost() + ?.let { UiStringText(postSettingsUtils.getPublishDateLabel(it)) }, actionClickable = true, onActionClicked = ::onActionClicked ) @@ -74,7 +74,8 @@ class PrepublishingHomeViewModel @Inject constructor( add( HomeUiState( actionType = PUBLISH, - actionResult = publishDateLabelUseCase.getLabel(editPostRepository), + actionResult = editPostRepository.getEditablePost() + ?.let { UiStringText(postSettingsUtils.getPublishDateLabel(it)) }, actionTypeColor = R.color.prepublishing_publish_date_disabled, actionResultColor = R.color.prepublishing_publish_date_disabled, actionClickable = false, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCase.kt deleted file mode 100644 index 8628093c3abc..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCase.kt +++ /dev/null @@ -1,29 +0,0 @@ -package org.wordpress.android.ui.posts.prepublishing.home.usecases - -import org.wordpress.android.R -import org.wordpress.android.fluxc.model.post.PostStatus.PRIVATE -import org.wordpress.android.ui.posts.EditPostRepository -import org.wordpress.android.ui.posts.PostSettingsUtils -import org.wordpress.android.ui.utils.UiString -import org.wordpress.android.ui.utils.UiString.UiStringRes -import org.wordpress.android.ui.utils.UiString.UiStringText -import javax.inject.Inject - -class GetPublishDateLabelUseCase @Inject constructor(private val postSettingsUtils: PostSettingsUtils) { - fun getLabel(editPostRepository: EditPostRepository): UiString { - if (editPostRepository.status == PRIVATE) { - return UiStringRes(R.string.immediately) - } else { - editPostRepository.getPost()?.let { postImmutableModel -> - val label = postSettingsUtils.getPublishDateLabel(postImmutableModel) - return if (label.isNotEmpty()) { - UiStringText(label) - } else { - UiStringRes(R.string.immediately) - } - } ?: run { - throw NullPointerException("Post can't be null") - } - } - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModel.kt index 9c0c0a5fffd8..f5a029fbad6c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModel.kt @@ -15,7 +15,7 @@ import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisi import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.VisibilityUiState import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.GetPostVisibilityUseCase import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.UpdatePostPasswordUseCase -import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.UpdatePostStatusUseCase +import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.UpdateVisibilityUseCase import org.wordpress.android.ui.posts.trackPrepublishingNudges import org.wordpress.android.ui.utils.UiString import org.wordpress.android.ui.utils.UiString.UiStringRes @@ -26,7 +26,7 @@ import javax.inject.Inject class PrepublishingVisibilityViewModel @Inject constructor( private val getPostVisibilityUseCase: GetPostVisibilityUseCase, private val updatePostPasswordUseCase: UpdatePostPasswordUseCase, - private val updatePostStatusUseCase: UpdatePostStatusUseCase, + private val updatePostStatusUseCase: UpdateVisibilityUseCase, private val analyticsTrackerWrapper: AnalyticsTrackerWrapper ) : ViewModel() { private var isStarted = false @@ -112,7 +112,7 @@ class PrepublishingVisibilityViewModel @Inject constructor( private fun updatePostStatus(visibility: Visibility) { analyticsTrackerWrapper.trackPrepublishingNudges(Stat.EDITOR_POST_VISIBILITY_CHANGED) - updatePostStatusUseCase.updatePostStatus(visibility, editPostRepository, ::updateUiState) + updatePostStatusUseCase.updatePostVisibility(visibility, editPostRepository, ::updateUiState) } fun onPostPasswordChanged(password: String) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt index 7e4862465c4e..21e7aa9aa765 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt @@ -4,40 +4,24 @@ import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.fluxc.model.post.PostStatus import org.wordpress.android.ui.posts.EditPostRepository import org.wordpress.android.ui.posts.EditPostRepository.UpdatePostResult -import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility -import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.DRAFT -import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PASSWORD_PROTECTED -import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PENDING_REVIEW -import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PRIVATE -import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PUBLISH import org.wordpress.android.util.DateTimeUtilsWrapper -import java.lang.IllegalStateException import javax.inject.Inject class UpdatePostStatusUseCase @Inject constructor(private val dateTimeUtilsWrapper: DateTimeUtilsWrapper) { fun updatePostStatus( - visibility: Visibility, + postStatus: PostStatus, editPostRepository: EditPostRepository, onPostStatusUpdated: () -> Unit ) { - val postStatus = when (visibility) { - PUBLISH -> PostStatus.PUBLISHED - DRAFT -> PostStatus.DRAFT - PENDING_REVIEW -> PostStatus.PENDING - PRIVATE -> PostStatus.PRIVATE - PASSWORD_PROTECTED -> { - throw IllegalStateException("$visibility shouldn't be persisted. It does not map to a PostStatus.") + editPostRepository.updateAsync({ postModel: PostModel -> + // we set the date to immediately if it's scheduled. + if (postStatus == PostStatus.PRIVATE) { + if (postModel.status == PostStatus.SCHEDULED.toString()) + postModel.setDateCreated(dateTimeUtilsWrapper.currentTimeInIso8601()) } - } - editPostRepository.updateAsync({ postModel: PostModel -> postModel.setStatus(postStatus.toString()) - // since PRIVATE posts always have to be immediate we set the current date when updating to be sure. - if (visibility == PRIVATE) { - postModel.setDateCreated(dateTimeUtilsWrapper.currentTimeInIso8601()) - } - true }, { _, result -> if (result == UpdatePostResult.Updated) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdateVisibilityUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdateVisibilityUseCase.kt new file mode 100644 index 000000000000..c2cfc68ecd61 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdateVisibilityUseCase.kt @@ -0,0 +1,33 @@ +package org.wordpress.android.ui.posts.prepublishing.visibility.usecases + +import org.wordpress.android.fluxc.model.post.PostStatus +import org.wordpress.android.ui.posts.EditPostRepository +import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility +import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.DRAFT +import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PASSWORD_PROTECTED +import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PENDING_REVIEW +import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PRIVATE +import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PUBLISH +import javax.inject.Inject + +class UpdateVisibilityUseCase @Inject constructor(private val updatePostStatusUseCase: UpdatePostStatusUseCase) { + fun updatePostVisibility( + visibility: Visibility, + editPostRepository: EditPostRepository, + onPostStatusUpdated: () -> Unit + ) { + val postStatus = when (visibility) { + PUBLISH -> PostStatus.PUBLISHED + DRAFT -> PostStatus.DRAFT + PENDING_REVIEW -> PostStatus.PENDING + PRIVATE -> PostStatus.PRIVATE + PASSWORD_PROTECTED -> { + throw IllegalStateException("$visibility shouldn't be persisted. It does not map to a PostStatus.") + } + } + + updatePostStatusUseCase.updatePostStatus(postStatus, editPostRepository) { + onPostStatusUpdated.invoke() + } + } +} diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt index 208c86a5a59f..30ea2fe84568 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt @@ -10,6 +10,7 @@ import org.junit.Test import org.mockito.Mock import org.wordpress.android.BaseUnitTest import org.wordpress.android.R +import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.model.post.PostStatus.PRIVATE import org.wordpress.android.ui.posts.PrepublishingHomeItemUiState.ActionType @@ -21,7 +22,6 @@ import org.wordpress.android.ui.posts.PrepublishingHomeItemUiState.HomeUiState import org.wordpress.android.ui.posts.PrepublishingHomeItemUiState.SubmitButtonUiState import org.wordpress.android.ui.posts.PrepublishingHomeItemUiState.SubmitButtonUiState.PublishButtonUiState import org.wordpress.android.ui.posts.prepublishing.home.usecases.GetButtonUiStateUseCase -import org.wordpress.android.ui.posts.prepublishing.home.usecases.GetPublishDateLabelUseCase import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.DRAFT import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.GetPostVisibilityUseCase import org.wordpress.android.ui.utils.UiString.UiStringRes @@ -30,7 +30,7 @@ import org.wordpress.android.viewmodel.Event class PrepublishingHomeViewModelTest : BaseUnitTest() { private lateinit var viewModel: PrepublishingHomeViewModel - @Mock lateinit var getPublishDateLabelUseCase: GetPublishDateLabelUseCase + @Mock lateinit var postSettingsUtils: PostSettingsUtils @Mock lateinit var editPostRepository: EditPostRepository @Mock lateinit var getPostTagsUseCase: GetPostTagsUseCase @Mock lateinit var getPostVisibilityUseCase: GetPostVisibilityUseCase @@ -42,7 +42,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { viewModel = PrepublishingHomeViewModel( getPostTagsUseCase, getPostVisibilityUseCase, - getPublishDateLabelUseCase, + postSettingsUtils, getButtonUiStateUseCase, mock() ) @@ -55,7 +55,8 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { ).doAnswer { PublishButtonUiState(it.arguments[2] as (PublishPost) -> Unit) } - whenever(getPublishDateLabelUseCase.getLabel(any())).thenReturn(UiStringText("")) + whenever(editPostRepository.getEditablePost()).thenReturn(PostModel()) + whenever(postSettingsUtils.getPublishDateLabel(any())).thenReturn(("")) whenever(getPostVisibilityUseCase.getVisibility(any())).thenReturn(DRAFT) whenever(site.name).thenReturn("") } @@ -187,7 +188,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { fun `verify that publish action result is propagated from postSettingsUtils`() { // arrange val expectedLabel = "test data" - whenever(getPublishDateLabelUseCase.getLabel(any())).thenReturn(UiStringText(expectedLabel)) + whenever(postSettingsUtils.getPublishDateLabel(any())).thenReturn(expectedLabel) // act viewModel.start(editPostRepository, site) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCaseTest.kt deleted file mode 100644 index 4ce42e196b17..000000000000 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/home/usecases/GetPublishDateLabelUseCaseTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package org.wordpress.android.ui.posts.prepublishing.home.usecases - -import com.nhaarman.mockitokotlin2.any -import com.nhaarman.mockitokotlin2.whenever -import org.assertj.core.api.Assertions.assertThat -import org.junit.Before -import org.junit.Test -import org.mockito.Mock -import org.wordpress.android.BaseUnitTest -import org.wordpress.android.R -import org.wordpress.android.fluxc.model.PostModel -import org.wordpress.android.fluxc.model.post.PostStatus.PRIVATE -import org.wordpress.android.ui.posts.EditPostRepository -import org.wordpress.android.ui.posts.PostSettingsUtils -import org.wordpress.android.ui.utils.UiString.UiStringRes -import org.wordpress.android.ui.utils.UiString.UiStringText - -class GetPublishDateLabelUseCaseTest : BaseUnitTest() { - private lateinit var useCase: GetPublishDateLabelUseCase - - @Mock lateinit var editPostRepository: EditPostRepository - @Mock lateinit var postSettingsUtils: PostSettingsUtils - - @Before - fun setup() { - useCase = GetPublishDateLabelUseCase(postSettingsUtils) - } - - @Test - fun `verify that when PostStatus is PRIVATE then publish date label is Immediately`() { - // arrange - whenever(editPostRepository.status).thenReturn(PRIVATE) - - // act - val label = useCase.getLabel(editPostRepository) - - // assert - assertThat((label as UiStringRes).stringRes).isEqualTo(R.string.immediately) - } - - @Test - fun `verify that when PostModel is not null a label is returned based on that PostModel`() { - // arrange - val expectedLabel = "label" - whenever(editPostRepository.getPost()).thenReturn(PostModel()) - whenever(postSettingsUtils.getPublishDateLabel(any())).thenReturn(expectedLabel) - - // act - val label = useCase.getLabel(editPostRepository) - - // assert - assertThat((label as UiStringText).text).isEqualTo(expectedLabel) - } - - @Test - fun `verify that when label from PostSettingsUtils is empty the publish date label is Immediately`() { - // arrange - val emptyLabel = "" - whenever(editPostRepository.getPost()).thenReturn(PostModel()) - whenever(postSettingsUtils.getPublishDateLabel(any())).thenReturn(emptyLabel) - - // act - val label = useCase.getLabel(editPostRepository) - - // assert - assertThat((label as UiStringRes).stringRes).isEqualTo(R.string.immediately) - } - - @Test(expected = NullPointerException::class) - fun `verify that when PostModel is null then an Exception is thrown`() { - // arrange - whenever(editPostRepository.getPost()).thenReturn(null) - - // act - useCase.getLabel(editPostRepository) - } -} diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModelTest.kt index f24762bdeef2..1a4f9849b9e5 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/PrepublishingVisibilityViewModelTest.kt @@ -23,7 +23,7 @@ import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisi import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PUBLISH import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.GetPostVisibilityUseCase import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.UpdatePostPasswordUseCase -import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.UpdatePostStatusUseCase +import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.UpdateVisibilityUseCase import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.viewmodel.Event @@ -32,7 +32,7 @@ class PrepublishingVisibilityViewModelTest : BaseUnitTest() { @Mock lateinit var getPostVisibilityUseCase: GetPostVisibilityUseCase @Mock lateinit var updatePostPasswordUseCase: UpdatePostPasswordUseCase - @Mock lateinit var updatePostStatusUseCase: UpdatePostStatusUseCase + @Mock lateinit var updatePostStatusUseCase: UpdateVisibilityUseCase private lateinit var editPostRepository: EditPostRepository @InternalCoroutinesApi @@ -184,7 +184,7 @@ class PrepublishingVisibilityViewModelTest : BaseUnitTest() { invokeVisibilityOnItemTapped(PRIVATE) // assert - verify(updatePostStatusUseCase).updatePostStatus(any(), any(), any()) + verify(updatePostStatusUseCase).updatePostVisibility(any(), any(), any()) } @Test diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt index 400fd9cd6e55..69282629e28a 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt @@ -1,12 +1,10 @@ package org.wordpress.android.ui.posts.prepublishing.visibility.usecases import com.nhaarman.mockitokotlin2.mock -import com.nhaarman.mockitokotlin2.verify import kotlinx.coroutines.InternalCoroutinesApi import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Test -import org.mockito.Mock import org.wordpress.android.BaseUnitTest import org.wordpress.android.TEST_DISPATCHER import org.wordpress.android.fluxc.model.PostModel @@ -17,19 +15,15 @@ import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisi import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PENDING_REVIEW import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PRIVATE import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PUBLISH -import org.wordpress.android.util.DateTimeUtilsWrapper -import java.lang.IllegalStateException class UpdatePostStatusUseCaseTest : BaseUnitTest() { private lateinit var editPostRepository: EditPostRepository - private lateinit var updatePostStatusUseCase: UpdatePostStatusUseCase - - @Mock lateinit var dateTimeUtilsWrapper: DateTimeUtilsWrapper + private lateinit var updatePostStatusUseCase: UpdateVisibilityUseCase @InternalCoroutinesApi @Before fun setup() { - updatePostStatusUseCase = UpdatePostStatusUseCase(dateTimeUtilsWrapper) + updatePostStatusUseCase = UpdateVisibilityUseCase(UpdatePostStatusUseCase(mock())) editPostRepository = EditPostRepository(mock(), mock(), mock(), TEST_DISPATCHER, TEST_DISPATCHER) editPostRepository.set { PostModel() } } @@ -40,7 +34,7 @@ class UpdatePostStatusUseCaseTest : BaseUnitTest() { val expectedPostStatus = PostStatus.PUBLISHED // act - updatePostStatusUseCase.updatePostStatus(PUBLISH, editPostRepository) {} + updatePostStatusUseCase.updatePostVisibility(PUBLISH, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) @@ -52,7 +46,7 @@ class UpdatePostStatusUseCaseTest : BaseUnitTest() { val expectedPostStatus = PostStatus.DRAFT // act - updatePostStatusUseCase.updatePostStatus(DRAFT, editPostRepository) {} + updatePostStatusUseCase.updatePostVisibility(DRAFT, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) @@ -64,7 +58,7 @@ class UpdatePostStatusUseCaseTest : BaseUnitTest() { val expectedPostStatus = PostStatus.PENDING // act - updatePostStatusUseCase.updatePostStatus(PENDING_REVIEW, editPostRepository) {} + updatePostStatusUseCase.updatePostVisibility(PENDING_REVIEW, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) @@ -76,27 +70,15 @@ class UpdatePostStatusUseCaseTest : BaseUnitTest() { val expectedPostStatus = PostStatus.PRIVATE // act - updatePostStatusUseCase.updatePostStatus(PRIVATE, editPostRepository) {} + updatePostStatusUseCase.updatePostVisibility(PRIVATE, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) } - @Test - fun `verify that when updatePostStatus is called with PRIVATE Visibility dateTimeUtilsWrapper is used`() { - // arrange - val expectedPostStatus = PostStatus.PRIVATE - - // act - updatePostStatusUseCase.updatePostStatus(PRIVATE, editPostRepository) {} - - // assert - verify(dateTimeUtilsWrapper).currentTimeInIso8601() - } - @Test(expected = IllegalStateException::class) fun `verify that when updatePostStatus is called with PASSWORD_PROTECTED Visibility an exception is thrown`() { // act - updatePostStatusUseCase.updatePostStatus(PASSWORD_PROTECTED, editPostRepository) {} + updatePostStatusUseCase.updatePostVisibility(PASSWORD_PROTECTED, editPostRepository) {} } } From 75362650ba151035961c9d5950df33a5bc7de4d7 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 21:25:04 -0500 Subject: [PATCH 589/822] added use case to save PostStatus to EditPostActivity --- .../ui/posts/EditPostSettingsFragment.java | 22 +++++++++---------- .../usecases/UpdatePostStatusUseCase.kt | 7 +++--- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java index 671595dc1b49..ee6652efcfba 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java @@ -64,12 +64,13 @@ import org.wordpress.android.ui.ActivityLauncher; import org.wordpress.android.ui.RequestCodes; import org.wordpress.android.ui.media.MediaBrowserType; -import org.wordpress.android.ui.posts.PublishSettingsViewModel.PublishUiModel; import org.wordpress.android.ui.posts.EditPostRepository.UpdatePostResult; import org.wordpress.android.ui.posts.FeaturedImageHelper.FeaturedImageData; import org.wordpress.android.ui.posts.FeaturedImageHelper.FeaturedImageState; import org.wordpress.android.ui.posts.FeaturedImageHelper.TrackableEvent; import org.wordpress.android.ui.posts.PostSettingsListDialogFragment.DialogType; +import org.wordpress.android.ui.posts.PublishSettingsViewModel.PublishUiModel; +import org.wordpress.android.ui.posts.prepublishing.visibility.usecases.UpdatePostStatusUseCase; import org.wordpress.android.ui.prefs.SiteSettingsInterface; import org.wordpress.android.ui.prefs.SiteSettingsInterface.SiteSettingsListener; import org.wordpress.android.ui.utils.UiHelpers; @@ -152,6 +153,7 @@ public class EditPostSettingsFragment extends Fragment { @Inject UiHelpers mUiHelpers; @Inject PostSettingsUtils mPostSettingsUtils; @Inject AnalyticsTrackerWrapper mAnalyticsTrackerWrapper; + @Inject UpdatePostStatusUseCase mUpdatePostStatusUseCase; @Inject ViewModelProvider.Factory mViewModelFactory; private EditPostPublishSettingsViewModel mPublishedViewModel; @@ -765,19 +767,15 @@ private void updateCategories(List categoryList) { } } - public void updatePostStatus(PostStatus postStatus) { + void updatePostStatus(PostStatus postStatus) { EditPostRepository editPostRepository = getEditPostRepository(); if (editPostRepository != null) { - editPostRepository.updateAsync(postModel -> { - postModel.setStatus(postStatus.toString()); - return true; - }, (postModel, result) -> { - if (result == UpdatePostResult.Updated.INSTANCE) { - updatePostStatusRelatedViews(postModel); - updateSaveButton(); - } - return null; - }); + mUpdatePostStatusUseCase.updatePostStatus(postStatus, editPostRepository, + postImmutableModel -> { + updatePostStatusRelatedViews(postImmutableModel); + updateSaveButton(); + return null; + }); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt index 21e7aa9aa765..3aef559cc05d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCase.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.posts.prepublishing.visibility.usecases +import org.wordpress.android.fluxc.model.PostImmutableModel import org.wordpress.android.fluxc.model.PostModel import org.wordpress.android.fluxc.model.post.PostStatus import org.wordpress.android.ui.posts.EditPostRepository @@ -11,7 +12,7 @@ class UpdatePostStatusUseCase @Inject constructor(private val dateTimeUtilsWrapp fun updatePostStatus( postStatus: PostStatus, editPostRepository: EditPostRepository, - onPostStatusUpdated: () -> Unit + onPostStatusUpdated: (PostImmutableModel) -> Unit ) { editPostRepository.updateAsync({ postModel: PostModel -> // we set the date to immediately if it's scheduled. @@ -23,9 +24,9 @@ class UpdatePostStatusUseCase @Inject constructor(private val dateTimeUtilsWrapp postModel.setStatus(postStatus.toString()) true - }, { _, result -> + }, { postModel, result -> if (result == UpdatePostResult.Updated) { - onPostStatusUpdated.invoke() + onPostStatusUpdated.invoke(postModel) } }) } From 24f87d1084fa7f96de93d3ed8791504ef85c85ee Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 21:27:19 -0500 Subject: [PATCH 590/822] Renamed test case to fit it's new purpose. --- ...Test.kt => UpdateVisibilityUseCaseTest.kt} | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) rename WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/{UpdatePostStatusUseCaseTest.kt => UpdateVisibilityUseCaseTest.kt} (70%) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdateVisibilityUseCaseTest.kt similarity index 70% rename from WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt rename to WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdateVisibilityUseCaseTest.kt index 69282629e28a..6c89269c36ba 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdateVisibilityUseCaseTest.kt @@ -16,69 +16,69 @@ import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisi import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PRIVATE import org.wordpress.android.ui.posts.prepublishing.visibility.PrepublishingVisibilityItemUiState.Visibility.PUBLISH -class UpdatePostStatusUseCaseTest : BaseUnitTest() { +class UpdateVisibilityUseCaseTest : BaseUnitTest() { private lateinit var editPostRepository: EditPostRepository - private lateinit var updatePostStatusUseCase: UpdateVisibilityUseCase + private lateinit var updateVisibilityUseCase: UpdateVisibilityUseCase @InternalCoroutinesApi @Before fun setup() { - updatePostStatusUseCase = UpdateVisibilityUseCase(UpdatePostStatusUseCase(mock())) + updateVisibilityUseCase = UpdateVisibilityUseCase(UpdatePostStatusUseCase(mock())) editPostRepository = EditPostRepository(mock(), mock(), mock(), TEST_DISPATCHER, TEST_DISPATCHER) editPostRepository.set { PostModel() } } @Test - fun `verify that when updatePostStatus is called with PUBLISH Visibility the PostStatus is PUBLISHED`() { + fun `verify that when updatePostVisibility is called with PUBLISH Visibility the PostStatus is PUBLISHED`() { // arrange val expectedPostStatus = PostStatus.PUBLISHED // act - updatePostStatusUseCase.updatePostVisibility(PUBLISH, editPostRepository) {} + updateVisibilityUseCase.updatePostVisibility(PUBLISH, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) } @Test - fun `verify that when updatePostStatus is called with DRAFT Visibility the PostStatus is DRAFT`() { + fun `verify that when updatePostVisibility is called with DRAFT Visibility the PostStatus is DRAFT`() { // arrange val expectedPostStatus = PostStatus.DRAFT // act - updatePostStatusUseCase.updatePostVisibility(DRAFT, editPostRepository) {} + updateVisibilityUseCase.updatePostVisibility(DRAFT, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) } @Test - fun `verify that when updatePostStatus is called with PENDING_REVIEW Visibility the PostStatus is PENDING`() { + fun `verify that when updatePostVisibility is called with PENDING_REVIEW Visibility the PostStatus is PENDING`() { // arrange val expectedPostStatus = PostStatus.PENDING // act - updatePostStatusUseCase.updatePostVisibility(PENDING_REVIEW, editPostRepository) {} + updateVisibilityUseCase.updatePostVisibility(PENDING_REVIEW, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) } @Test - fun `verify that when updatePostStatus is called with PRIVATE Visibility the PostStatus is PRIVATE`() { + fun `verify that when updatePostVisibility is called with PRIVATE Visibility the PostStatus is PRIVATE`() { // arrange val expectedPostStatus = PostStatus.PRIVATE // act - updatePostStatusUseCase.updatePostVisibility(PRIVATE, editPostRepository) {} + updateVisibilityUseCase.updatePostVisibility(PRIVATE, editPostRepository) {} // assert assertThat(editPostRepository.getPost()?.status).isEqualTo(expectedPostStatus.toString()) } @Test(expected = IllegalStateException::class) - fun `verify that when updatePostStatus is called with PASSWORD_PROTECTED Visibility an exception is thrown`() { + fun `verify that when updatePostVisibility is called with PASSWORD_PROTECTED Visibility an exception is thrown`() { // act - updatePostStatusUseCase.updatePostVisibility(PASSWORD_PROTECTED, editPostRepository) {} + updateVisibilityUseCase.updatePostVisibility(PASSWORD_PROTECTED, editPostRepository) {} } } From 937f9e6fcfaff8d1ea9c652ce6b53a22052a0d37 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 21:46:20 -0500 Subject: [PATCH 591/822] added tests for use case --- .../usecases/UpdatePostStatusUseCaseTest.kt | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt new file mode 100644 index 000000000000..6212125275a1 --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/prepublishing/visibility/usecases/UpdatePostStatusUseCaseTest.kt @@ -0,0 +1,78 @@ +package org.wordpress.android.ui.posts.prepublishing.visibility.usecases + +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import kotlinx.coroutines.InternalCoroutinesApi +import org.assertj.core.api.Assertions.assertThat +import org.wordpress.android.BaseUnitTest + +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.wordpress.android.TEST_DISPATCHER +import org.wordpress.android.fluxc.model.PostModel +import org.wordpress.android.fluxc.model.post.PostStatus +import org.wordpress.android.fluxc.model.post.PostStatus.PRIVATE +import org.wordpress.android.ui.posts.EditPostRepository +import org.wordpress.android.util.DateTimeUtilsWrapper + +class UpdatePostStatusUseCaseTest : BaseUnitTest() { + private lateinit var editPostRepository: EditPostRepository + private lateinit var updatePostStatusUseCase: UpdatePostStatusUseCase + @Mock lateinit var dateTimeUtilsWrapper: DateTimeUtilsWrapper + + @InternalCoroutinesApi + @Before + fun setup() { + updatePostStatusUseCase = UpdatePostStatusUseCase(dateTimeUtilsWrapper) + editPostRepository = EditPostRepository(mock(), mock(), mock(), TEST_DISPATCHER, TEST_DISPATCHER) + } + + @Test + fun `if the new PostStatus is PRIVATE & the old PostStatus is SCHEDULED then the date created should be now`() { + // arrange + val currentDate = "2020-06-06T20:28:20+0200" + whenever(dateTimeUtilsWrapper.currentTimeInIso8601()).thenReturn(currentDate) + editPostRepository.set { PostModel().apply { setStatus(PostStatus.SCHEDULED.toString()) } } + + // act + updatePostStatusUseCase.updatePostStatus(PRIVATE, editPostRepository) {} + + // assert + assertThat(editPostRepository.dateCreated).isEqualTo(currentDate) + } + + @Test + fun `if the new PostStatus is PRIVATE & the old PostStatus is not SCHEDULED then the date should be the same`() { + // arrange + val currentDate = "2020-06-06T20:28:20+0200" + editPostRepository.set { + PostModel().apply { + setDateCreated(currentDate) + setStatus(PostStatus.DRAFT.toString()) + } + } + + // act + updatePostStatusUseCase.updatePostStatus(PRIVATE, editPostRepository) {} + + // assert + assertThat(editPostRepository.dateCreated).isEqualTo(currentDate) + } + + @Test + fun `if the new PostStatus is PRIVATE & the old PostStatus is DRAFT then the postModel should be updated`() { + // arrange + editPostRepository.set { + PostModel().apply { + setStatus(PostStatus.DRAFT.toString()) + } + } + + // act + updatePostStatusUseCase.updatePostStatus(PRIVATE, editPostRepository) {} + + // assert + assertThat(editPostRepository.status).isEqualTo(PRIVATE) + } +} From 9f6cd9f16c14fcb6014fdfc39e879f0a2d1b73ab Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 21:50:51 -0500 Subject: [PATCH 592/822] fixed tests naming. --- .../android/ui/posts/PrepublishingHomeViewModelTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt index 30ea2fe84568..dae28c115029 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PrepublishingHomeViewModelTest.kt @@ -286,7 +286,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { } @Test - fun `verify that PUBLISH action is disabled if PostStatus is PRIVATE`() { + fun `verify that PUBLISH action is unclickable if PostStatus is PRIVATE`() { whenever(editPostRepository.status).thenReturn(PRIVATE) viewModel.start(editPostRepository, site) @@ -297,7 +297,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { } @Test - fun `verify that TAGS action is enabled if PostStatus is PRIVATE`() { + fun `verify that TAGS action is clickable if PostStatus is PRIVATE`() { whenever(editPostRepository.status).thenReturn(PRIVATE) viewModel.start(editPostRepository, site) @@ -308,7 +308,7 @@ class PrepublishingHomeViewModelTest : BaseUnitTest() { } @Test - fun `verify that VISIBILITY action is disabled if PostStatus is PRIVATE`() { + fun `verify that VISIBILITY action is clickable if PostStatus is PRIVATE`() { whenever(editPostRepository.status).thenReturn(PRIVATE) viewModel.start(editPostRepository, site) From 5ce7ea1f50c356fa75ffe11e050a98dc954be22a Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 22:07:06 -0500 Subject: [PATCH 593/822] fixed lint issues. --- .../android/ui/posts/PrepublishingHomeItemUiState.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt index ec435991585f..4e62dfb08ee5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PrepublishingHomeItemUiState.kt @@ -7,12 +7,13 @@ import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.ui.utils.UiString.UiStringText typealias PublishPost = Boolean + sealed class PrepublishingHomeItemUiState { data class HomeUiState( val actionType: ActionType, - @ColorRes val actionTypeColor : Int = R.color.black, + @ColorRes val actionTypeColor: Int = R.color.black, var actionResult: UiString? = null, - @ColorRes val actionResultColor : Int = R.color.prepublishing_publish_date_result_enabled, + @ColorRes val actionResultColor: Int = R.color.prepublishing_publish_date_result_enabled, val actionClickable: Boolean, val onActionClicked: ((actionType: ActionType) -> Unit)? ) : PrepublishingHomeItemUiState() From faf7dad2f45805c77d7a2f4a741f22f8ded67922 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 4 Jun 2020 23:55:16 -0500 Subject: [PATCH 594/822] added post settings implementation. --- .../ui/posts/EditPostSettingsFragment.java | 21 ++++++++++++++----- .../layout/edit_post_settings_fragment.xml | 1 + 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java index ee6652efcfba..b225f493f543 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostSettingsFragment.java @@ -93,6 +93,7 @@ import java.util.Calendar; import java.util.Iterator; import java.util.List; +import java.util.Objects; import javax.inject.Inject; @@ -119,6 +120,7 @@ public class EditPostSettingsFragment extends Fragment { private LinearLayout mExcerptContainer; private LinearLayout mFormatContainer; private LinearLayout mTagsContainer; + private LinearLayout mPublishDateContainer; private TextView mExcerptTextView; private TextView mSlugTextView; private TextView mLocationTextView; @@ -128,6 +130,7 @@ public class EditPostSettingsFragment extends Fragment { private TextView mPostFormatTextView; private TextView mPasswordTextView; private TextView mPublishDateTextView; + private TextView mPublishDateTitleTextView; private TextView mCategoriesTagsHeaderTextView; private TextView mFeaturedImageHeaderTextView; private TextView mMoreOptionsHeaderTextView; @@ -269,10 +272,12 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c mPostFormatTextView = rootView.findViewById(R.id.post_format); mPasswordTextView = rootView.findViewById(R.id.post_password); mPublishDateTextView = rootView.findViewById(R.id.publish_date); + mPublishDateTitleTextView = rootView.findViewById(R.id.publish_date_title); mCategoriesTagsHeaderTextView = rootView.findViewById(R.id.post_settings_categories_and_tags_header); mMoreOptionsHeaderTextView = rootView.findViewById(R.id.post_settings_more_options_header); mFeaturedImageHeaderTextView = rootView.findViewById(R.id.post_settings_featured_image_header); mPublishHeaderTextView = rootView.findViewById(R.id.post_settings_publish); + mPublishDateContainer = rootView.findViewById(R.id.publish_date_container); mFeaturedImageView = rootView.findViewById(R.id.post_featured_image); mLocalFeaturedImageView = rootView.findViewById(R.id.post_featured_image_local); @@ -368,8 +373,7 @@ public void onClick(View view) { } }); - final LinearLayout publishDateContainer = rootView.findViewById(R.id.publish_date_container); - publishDateContainer.setOnClickListener(new View.OnClickListener() { + mPublishDateContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FragmentActivity activity = getActivity(); @@ -390,7 +394,8 @@ public void onClick(View view) { mPublishedViewModel.getOnUiModel().observe(this, new Observer() { @Override public void onChanged(PublishUiModel uiModel) { - updatePublishDateTextView(uiModel.getPublishDateLabel()); + updatePublishDateTextView(uiModel.getPublishDateLabel(), + Objects.requireNonNull(getEditPostRepository().getPost())); } }); mPublishedViewModel.getOnPostStatusChanged().observe(this, new Observer() { @@ -854,12 +859,18 @@ private void updatePublishDateTextView(PostImmutableModel postModel) { } if (postModel != null) { String labelToUse = mPostSettingsUtils.getPublishDateLabel(postModel); - mPublishDateTextView.setText(labelToUse); + updatePublishDateTextView(labelToUse, postModel); } } - private void updatePublishDateTextView(String label) { + private void updatePublishDateTextView(String label, PostImmutableModel postImmutableModel) { mPublishDateTextView.setText(label); + + boolean isPrivatePost = postImmutableModel.getStatus().equals(PostStatus.PRIVATE.toString()); + + mPublishDateTextView.setEnabled(!isPrivatePost); + mPublishDateTitleTextView.setEnabled(!isPrivatePost); + mPublishDateContainer.setEnabled(!isPrivatePost); } private void updateCategoriesTextView(PostImmutableModel post) { diff --git a/WordPress/src/main/res/layout/edit_post_settings_fragment.xml b/WordPress/src/main/res/layout/edit_post_settings_fragment.xml index c0a14615fe4d..733710a8769a 100644 --- a/WordPress/src/main/res/layout/edit_post_settings_fragment.xml +++ b/WordPress/src/main/res/layout/edit_post_settings_fragment.xml @@ -38,6 +38,7 @@ style="@style/PostSettingsContainer"> From f98f231e7c9c3f367a46807917811dbddf385c81 Mon Sep 17 00:00:00 2001 From: ashiagr Date: Fri, 5 Jun 2020 11:47:13 +0530 Subject: [PATCH 595/822] Iterate over selected items to know if one of them is "video" --- .../ui/photopicker/PhotoPickerAdapter.java | 15 ++++++++++----- .../ui/photopicker/PhotoPickerFragment.java | 13 ++----------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java index a290ff07a0cb..a562dc67e4c3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerAdapter.java @@ -52,8 +52,6 @@ interface PhotoPickerAdapterListener { void onSelectedCountChanged(int count); void onAdapterLoaded(boolean isEmpty); - - void onItemSelected(boolean isVideo); } private class PhotoPickerItem { @@ -241,9 +239,6 @@ private void setItemSelected(int position, boolean isSelected, boolean updateAft if (isSelected) { mSelectedPositions.add(position); - if (mListener != null) { - mListener.onItemSelected(item.mIsVideo); - } } else { int selectedIndex = mSelectedPositions.indexOf(position); if (selectedIndex > -1) { @@ -291,6 +286,16 @@ private ThumbnailViewHolder getViewHolderAtPosition(int position) { return (ThumbnailViewHolder) mRecycler.findViewHolderForAdapterPosition(position); } + boolean isVideoFileSelected() { + for (Integer position : mSelectedPositions) { + PhotoPickerItem item = getItemAtPosition(position); + if (item != null && item.mIsVideo) { + return true; + } + } + return false; + } + @NonNull ArrayList getSelectedURIs() { ArrayList uriList = new ArrayList<>(); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java index 9e33de81c52f..f9c379762c2d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.java @@ -54,7 +54,6 @@ public class PhotoPickerFragment extends Fragment { private static final String KEY_LAST_TAPPED_ICON = "last_tapped_icon"; private static final String KEY_SELECTED_POSITIONS = "selected_positions"; - private static final String KEY_SELECTED_ITEM_IS_VIDEO = "selected_item_is_video"; static final int NUM_COLUMNS = 3; public static final String ARG_BROWSER_TYPE = "browser_type"; @@ -102,7 +101,6 @@ public interface PhotoPickerListener { private MediaBrowserType mBrowserType; private SiteModel mSite; private ArrayList mSelectedPositions; - private boolean mIsSelectedItemVideo; public static PhotoPickerFragment newInstance(@NonNull PhotoPickerListener listener, @NonNull MediaBrowserType browserType, @@ -132,9 +130,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) { if (savedInstanceState.containsKey(KEY_SELECTED_POSITIONS)) { mSelectedPositions = savedInstanceState.getIntegerArrayList(KEY_SELECTED_POSITIONS); } - if (savedInstanceState.containsKey(KEY_SELECTED_ITEM_IS_VIDEO)) { - mIsSelectedItemVideo = savedInstanceState.getBoolean(KEY_SELECTED_ITEM_IS_VIDEO); - } } } @@ -257,7 +252,6 @@ public void onSaveInstanceState(@NonNull Bundle outState) { if (hasAdapter() && getAdapter().getNumSelected() > 0) { ArrayList selectedItems = getAdapter().getSelectedPositions(); outState.putIntegerArrayList(KEY_SELECTED_POSITIONS, selectedItems); - outState.putBoolean(KEY_SELECTED_ITEM_IS_VIDEO, mIsSelectedItemVideo); } } @@ -414,7 +408,8 @@ public void onSelectedCountChanged(int count) { if (canShowInsertEditBottomBar()) { TextView editView = mInsertEditBottomBar.findViewById(R.id.text_edit); - editView.setVisibility(mIsSelectedItemVideo ? View.GONE : View.VISIBLE); + boolean isVideoFileSelected = getAdapter().isVideoFileSelected(); + editView.setVisibility(isVideoFileSelected ? View.GONE : View.VISIBLE); } if (mActionMode == null) { @@ -437,10 +432,6 @@ public void onAdapterLoaded(boolean isEmpty) { mRestoreState = null; } } - - @Override public void onItemSelected(boolean isVideo) { - mIsSelectedItemVideo = isVideo; - } }; private boolean hasAdapter() { From 5d04f02bdbd9d4b30b6f19ab693659b88a257bad Mon Sep 17 00:00:00 2001 From: ashiagr Date: Fri, 5 Jun 2020 14:39:26 +0530 Subject: [PATCH 596/822] Add title, subtitle --- .../reader_interests_fragment_layout.xml | 93 ++++++++++++++----- .../src/main/res/values/reader_styles.xml | 21 +++++ WordPress/src/main/res/values/strings.xml | 3 + 3 files changed, 96 insertions(+), 21 deletions(-) diff --git a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml index a9dc710dab9c..062ba62dd2cd 100644 --- a/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml +++ b/WordPress/src/main/res/layout/reader_interests_fragment_layout.xml @@ -2,31 +2,82 @@ + android:layout_height="match_parent" + android:contentDescription="@string/reader_choose_interests_content_description"> - - - - - + app:layout_constraintBottom_toTopOf="@id/bottom_bar"> + + + + + + + + + + + + + + + + ?attr/wpColorText + + + + - - - - + + + +