diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index a8cc5d4f9ad6..6041b3d14229 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -5,6 +5,7 @@
* Added ability to toggle to compact view type for blog posts list
* Fixed several bugs on the blog posts screen
* Fixed bug that prevented audio playing in the reader
+* New Insights Management for selecting the most relevant stats
12.3
-----
diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml
index 6f4cb1c22155..eca0e09b391e 100644
--- a/WordPress/src/main/AndroidManifest.xml
+++ b/WordPress/src/main/AndroidManifest.xml
@@ -288,9 +288,13 @@
android:theme="@style/Calypso.NoActionBar" />
+
oldItem == newItem
}
} else {
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/NavigationTarget.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/NavigationTarget.kt
index 56447eee483c..cf771c95271e 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/NavigationTarget.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/NavigationTarget.kt
@@ -34,4 +34,5 @@ sealed class NavigationTarget {
object ViewDayAverageStats : NavigationTarget()
object ViewRecentWeeksStats : NavigationTarget()
object ViewAnnualStats : NavigationTarget()
+ object ViewInsightsManagement : NavigationTarget()
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt
index 1eca4cc4bb3a..f900dbd64916 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt
@@ -36,6 +36,7 @@ import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSect
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.MONTHS
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.WEEKS
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.YEARS
+import org.wordpress.android.ui.stats.refresh.utils.StatsNavigator
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.util.WPSwipeToRefreshHelper
import org.wordpress.android.util.helpers.SwipeToRefreshHelper
@@ -49,15 +50,12 @@ class StatsFragment : DaggerFragment() {
@Inject lateinit var statsSiteProvider: StatsSiteProvider
private lateinit var viewModel: StatsViewModel
private lateinit var swipeToRefreshHelper: SwipeToRefreshHelper
+ @Inject lateinit var navigator: StatsNavigator
private var restorePreviousSearch = false
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setHasOptionsMenu(true)
- }
-
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ setHasOptionsMenu(true)
return inflater.inflate(R.layout.stats_fragment, container, false)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt
index ab25cedfe4dc..56279380fab8 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt
@@ -203,7 +203,7 @@ class StatsModule {
mainDispatcher,
statsSiteProvider,
useCases,
- { statsStore.getInsights() },
+ { statsStore.getAddedInsights(statsSiteProvider.siteModel) },
uiModelMapper::mapInsights
)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewAllFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewAllFragment.kt
index dbcd5eebd2bc..afaf84208604 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewAllFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewAllFragment.kt
@@ -83,7 +83,7 @@ class StatsViewAllFragment : DaggerFragment() {
super.onSaveInstanceState(outState)
}
- private fun initializeViews(savedInstanceState: Bundle?) {
+ private fun initializeViews(savedInstanceState: Bundle?) {
val layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
savedInstanceState?.getParcelable(listStateKey)?.let {
@@ -97,10 +97,10 @@ class StatsViewAllFragment : DaggerFragment() {
viewModel.onPullToRefresh()
}
- select_next_date.setOnClickListener {
+ nextDateButton.setOnClickListener {
viewModel.onNextDateSelected()
}
- select_previous_date.setOnClickListener {
+ previousDateButton.setOnClickListener {
viewModel.onPreviousDateSelected()
}
}
@@ -173,8 +173,8 @@ class StatsViewAllFragment : DaggerFragment() {
if (it != null) {
recyclerView.visibility = if (it is StatsBlock.Success) View.VISIBLE else View.GONE
loadingContainer.visibility = if (it is StatsBlock.Loading) View.VISIBLE else View.GONE
- actionable_error_view.visibility = if (it is StatsBlock.Error) View.VISIBLE else View.GONE
- actionable_empty_view.visibility = if (it is StatsBlock.EmptyBlock) View.VISIBLE else View.GONE
+ statsErrorView.visibility = if (it is StatsBlock.Error) View.VISIBLE else View.GONE
+ statsEmptyView.visibility = if (it is StatsBlock.EmptyBlock) View.VISIBLE else View.GONE
when (it) {
is StatsBlock.Success -> {
loadData(recyclerView, prepareLayout(it.data, it.type))
@@ -183,7 +183,7 @@ class StatsViewAllFragment : DaggerFragment() {
loadData(loadingRecyclerView, prepareLayout(it.data, it.type))
}
is StatsBlock.Error -> {
- actionable_error_view.button.setOnClickListener {
+ statsErrorView.button.setOnClickListener {
viewModel.onRetryClick()
}
}
@@ -201,14 +201,14 @@ class StatsViewAllFragment : DaggerFragment() {
if (date_selection_toolbar.visibility != dateSelectorVisibility) {
date_selection_toolbar.visibility = dateSelectorVisibility
}
- selected_date.text = dateSelectorUiModel?.date ?: ""
+ selectedDateTextView.text = dateSelectorUiModel?.date ?: ""
val enablePreviousButton = dateSelectorUiModel?.enableSelectPrevious == true
- if (select_previous_date.isEnabled != enablePreviousButton) {
- select_previous_date.isEnabled = enablePreviousButton
+ if (previousDateButton.isEnabled != enablePreviousButton) {
+ previousDateButton.isEnabled = enablePreviousButton
}
val enableNextButton = dateSelectorUiModel?.enableSelectNext == true
- if (select_next_date.isEnabled != enableNextButton) {
- select_next_date.isEnabled = enableNextButton
+ if (nextDateButton.isEnabled != enableNextButton) {
+ nextDateButton.isEnabled = enableNextButton
}
})
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewModel.kt
index efdeac1efbe1..f639f2ab3149 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsViewModel.kt
@@ -109,6 +109,7 @@ class StatsViewModel
listUseCases[statsSection]?.onListSelected()
_toolbarHasShadow.value = statsSection == INSIGHTS
+
when (statsSection) {
INSIGHTS -> analyticsTracker.track(STATS_INSIGHTS_ACCESSED)
DAYS -> analyticsTracker.track(STATS_PERIOD_DAYS_ACCESSED)
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/BaseListUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/BaseListUseCase.kt
index e94599a24b24..2b519389caef 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/BaseListUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/BaseListUseCase.kt
@@ -7,14 +7,13 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.wordpress.android.R
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
import org.wordpress.android.ui.pages.SnackbarMessageHolder
import org.wordpress.android.ui.stats.refresh.NavigationTarget
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.UiModel
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.UseCaseModel
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
-import org.wordpress.android.util.DistinctMutableLiveData
import org.wordpress.android.util.PackageUtils
import org.wordpress.android.util.combineMap
import org.wordpress.android.util.distinct
@@ -28,15 +27,19 @@ class BaseListUseCase(
private val mainDispatcher: CoroutineDispatcher,
private val statsSiteProvider: StatsSiteProvider,
private val useCases: List>,
- private val getStatsTypes: suspend () -> List,
- private val mapUiModel: (useCaseModels: List, showError: (Int) -> Unit) -> UiModel
+ private val getStatsTypes: suspend () -> List,
+ private val mapUiModel: (
+ useCaseModels: List,
+ MutableLiveData>,
+ showError: (Int) -> Unit
+ ) -> UiModel
) {
private val blockListData = combineMap(
useCases.associateBy { it.type }.mapValues { entry -> entry.value.liveData }
)
- private val statsTypes = DistinctMutableLiveData>(listOf())
- val data: MediatorLiveData = mergeNotNull(statsTypes, blockListData) { insights, map ->
- insights.mapNotNull {
+ private val statsTypes = MutableLiveData>()
+ val data: MediatorLiveData = mergeNotNull(statsTypes, blockListData) { types, map ->
+ types.mapNotNull {
if (map.containsKey(it)) {
map[it]
} else {
@@ -44,13 +47,14 @@ class BaseListUseCase(
}
}
}.map { useCaseModels ->
- mapUiModel(useCaseModels) { message ->
+ mapUiModel(useCaseModels, mutableNavigationTarget) { message ->
mutableSnackbarMessage.postValue(message)
}
}.distinct()
+ private val mutableNavigationTarget = MutableLiveData>()
val navigationTarget: LiveData> = mergeNotNull(
- useCases.map { it.navigationTarget },
+ useCases.map { it.navigationTarget } + mutableNavigationTarget,
distinct = false
)
@@ -70,16 +74,26 @@ class BaseListUseCase(
loadData(true, forced)
}
+ suspend fun refreshTypes(): List {
+ val items = getStatsTypes()
+ withContext(mainDispatcher) {
+ statsTypes.value = items
+ }
+ return items
+ }
+
private suspend fun loadData(refresh: Boolean, forced: Boolean) {
if (statsSiteProvider.hasLoadedSite()) {
withContext(bgDispatcher) {
if (PackageUtils.isDebugBuild() && useCases.distinctBy { it.type }.size < useCases.size) {
throw RuntimeException("Duplicate stats type in a use case")
}
- useCases.forEach { block -> launch { block.fetch(refresh, forced) } }
- val items = getStatsTypes()
- withContext(mainDispatcher) {
- statsTypes.value = items
+ val visibleTypes = refreshTypes()
+ visibleTypes.forEach { type ->
+ useCases.find { it.type == type }
+ ?.let { block -> launch(bgDispatcher) {
+ block.fetch(refresh, forced) }
+ }
}
}
} else {
@@ -89,7 +103,6 @@ class BaseListUseCase(
fun onCleared() {
mutableSnackbarMessage.value = null
- statsTypes.clear()
blockListData.value = null
useCases.forEach { it.clear() }
data.value = null
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlock.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlock.kt
index 0a71e078f20f..eef7998ba99f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlock.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlock.kt
@@ -1,37 +1,43 @@
package org.wordpress.android.ui.stats.refresh.lists
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.CONTROL
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.EMPTY
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.ERROR
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.LOADING
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.SUCCESS
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
-sealed class StatsBlock(val type: Type, open val statsTypes: StatsTypes, open val data: List) {
+sealed class StatsBlock(val type: Type, open val data: List) {
enum class Type {
SUCCESS,
ERROR,
EMPTY,
- LOADING
+ LOADING,
+ CONTROL
}
data class Success(
- override val statsTypes: StatsTypes,
+ val statsType: StatsType,
override val data: List
- ) : StatsBlock(SUCCESS, statsTypes, data)
+ ) : StatsBlock(SUCCESS, data)
data class Error(
- override val statsTypes: StatsTypes,
+ val statsType: StatsType,
override val data: List = listOf()
- ) : StatsBlock(ERROR, statsTypes, data)
+ ) : StatsBlock(ERROR, data)
data class EmptyBlock(
- override val statsTypes: StatsTypes,
+ val statsType: StatsType,
override val data: List
- ) : StatsBlock(EMPTY, statsTypes, data)
+ ) : StatsBlock(EMPTY, data)
data class Loading(
- override val statsTypes: StatsTypes,
+ val statsType: StatsType,
override val data: List
- ) : StatsBlock(LOADING, statsTypes, data)
+ ) : StatsBlock(LOADING, data)
+
+ data class Control(
+ override val data: List
+ ) : StatsBlock(CONTROL, data)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockAdapter.kt
index 260064dedce9..8b6d67c4dcf8 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockAdapter.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockAdapter.kt
@@ -3,6 +3,11 @@ package org.wordpress.android.ui.stats.refresh.lists
import android.support.v7.util.DiffUtil
import android.support.v7.widget.RecyclerView.Adapter
import android.view.ViewGroup
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.EmptyBlock
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Loading
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Success
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Error
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.CONTROL
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.EMPTY
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.ERROR
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.LOADING
@@ -10,11 +15,13 @@ import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.SUCCESS
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Type.values
import org.wordpress.android.ui.stats.refresh.lists.viewholders.BaseStatsViewHolder
import org.wordpress.android.ui.stats.refresh.lists.viewholders.BlockListViewHolder
+import org.wordpress.android.ui.stats.refresh.lists.viewholders.ControlViewHolder
import org.wordpress.android.ui.stats.refresh.lists.viewholders.LoadingViewHolder
import org.wordpress.android.util.image.ImageManager
class StatsBlockAdapter(val imageManager: ImageManager) : Adapter() {
private var items: List = listOf()
+
fun update(newItems: List) {
val diffResult = DiffUtil.calculateDiff(
StatsBlockDiffCallback(
@@ -23,7 +30,6 @@ class StatsBlockAdapter(val imageManager: ImageManager) : Adapter BlockListViewHolder(parent, imageManager)
LOADING -> LoadingViewHolder(parent, imageManager)
+ CONTROL -> ControlViewHolder(parent, imageManager)
}
}
@@ -43,8 +50,16 @@ class StatsBlockAdapter(val imageManager: ImageManager) : Adapter) {
val item = items[position]
when (holder) {
- is BlockListViewHolder -> holder.bind(item.statsTypes, item.data)
- is LoadingViewHolder -> holder.bind(item.statsTypes, item.data)
+ is ControlViewHolder -> holder.bind(item.data)
+ is BlockListViewHolder,
+ is LoadingViewHolder -> {
+ when (item) {
+ is Success -> holder.bind(item.statsType, item.data)
+ is Loading -> holder.bind(item.statsType, item.data)
+ is EmptyBlock -> holder.bind(item.statsType, item.data)
+ is Error -> holder.bind(item.statsType, item.data)
+ }
+ }
}
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockDiffCallback.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockDiffCallback.kt
index 16c949f8c8fc..525467e9587f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockDiffCallback.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsBlockDiffCallback.kt
@@ -1,7 +1,11 @@
package org.wordpress.android.ui.stats.refresh.lists
import android.support.v7.util.DiffUtil.Callback
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Control
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.EmptyBlock
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Loading
import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Success
+import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Error
class StatsBlockDiffCallback(
private val oldList: List,
@@ -11,7 +15,13 @@ class StatsBlockDiffCallback(
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val newItem = newList[newItemPosition]
val oldItem = oldList[oldItemPosition]
- return oldItem.statsTypes == newItem.statsTypes
+ return oldItem.type == newItem.type && when (oldItem) {
+ is Success -> oldItem.statsType == (newItem as Success).statsType
+ is EmptyBlock -> oldItem.statsType == (newItem as EmptyBlock).statsType
+ is Error -> oldItem.statsType == (newItem as Error).statsType
+ is Loading -> oldItem.statsType == (newItem as Loading).statsType
+ is Control -> true
+ }
}
override fun getOldListSize(): Int = oldList.size
@@ -30,7 +40,7 @@ class StatsBlockDiffCallback(
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
val newItem = newList[newItemPosition]
val oldItem = oldList[oldItemPosition]
- if (oldItem is Success && newItem is Success) {
+ if (oldItem.type == newItem.type) {
return Payload
}
return null
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListFragment.kt
index b1b47733df4c..e0b1a70ad91b 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListFragment.kt
@@ -15,10 +15,10 @@ import android.view.View
import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import kotlinx.android.synthetic.main.stats_date_selector.*
+import kotlinx.android.synthetic.main.stats_empty_view.*
import kotlinx.android.synthetic.main.stats_error_view.*
import kotlinx.android.synthetic.main.stats_list_fragment.*
import org.wordpress.android.R
-import org.wordpress.android.ui.stats.refresh.StatsListItemDecoration
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.UiModel
import org.wordpress.android.ui.stats.refresh.lists.detail.DetailListViewModel
@@ -88,6 +88,10 @@ class StatsListFragment : DaggerFragment() {
)
)
+ statsEmptyView.button.setOnClickListener {
+ viewModel.onEmptyInsightsButtonClicked()
+ }
+
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (!recyclerView.canScrollVertically(1) && dy != 0) {
@@ -96,13 +100,17 @@ class StatsListFragment : DaggerFragment() {
}
})
- select_next_date.setOnClickListener {
+ nextDateButton.setOnClickListener {
viewModel.onNextDateSelected()
}
- select_previous_date.setOnClickListener {
+ previousDateButton.setOnClickListener {
viewModel.onPreviousDateSelected()
}
+
+ statsErrorView.button.setOnClickListener {
+ viewModel.onRetryClick()
+ }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -145,10 +153,13 @@ class StatsListFragment : DaggerFragment() {
}
is UiModel.Error -> {
recyclerView.visibility = View.GONE
- actionable_error_view.visibility = View.VISIBLE
- actionable_error_view.button.setOnClickListener {
- viewModel.onRetryClick()
- }
+ statsErrorView.visibility = View.VISIBLE
+ statsEmptyView.visibility = View.GONE
+ }
+ is UiModel.Empty -> {
+ recyclerView.visibility = View.GONE
+ statsEmptyView.visibility = View.VISIBLE
+ statsErrorView.visibility = View.GONE
}
}
}
@@ -159,14 +170,14 @@ class StatsListFragment : DaggerFragment() {
if (date_selection_toolbar.visibility != dateSelectorVisibility) {
date_selection_toolbar.visibility = dateSelectorVisibility
}
- selected_date.text = dateSelectorUiModel?.date ?: ""
+ selectedDateTextView.text = dateSelectorUiModel?.date ?: ""
val enablePreviousButton = dateSelectorUiModel?.enableSelectPrevious == true
- if (select_previous_date.isEnabled != enablePreviousButton) {
- select_previous_date.isEnabled = enablePreviousButton
+ if (previousDateButton.isEnabled != enablePreviousButton) {
+ previousDateButton.isEnabled = enablePreviousButton
}
val enableNextButton = dateSelectorUiModel?.enableSelectNext == true
- if (select_next_date.isEnabled != enableNextButton) {
- select_next_date.isEnabled = enableNextButton
+ if (nextDateButton.isEnabled != enableNextButton) {
+ nextDateButton.isEnabled = enableNextButton
}
})
@@ -185,11 +196,19 @@ class StatsListFragment : DaggerFragment() {
viewModel.listSelected.observe(this, Observer {
viewModel.onListSelected()
})
+
+ viewModel.typeMoved?.observe(this, Observer { event ->
+ event?.getContentIfNotHandled()?.let {
+ viewModel.onTypeMoved()
+ }
+ })
}
private fun updateInsights(statsState: List) {
recyclerView.visibility = View.VISIBLE
- actionable_error_view.visibility = View.GONE
+ statsErrorView.visibility = View.GONE
+ statsEmptyView.visibility = View.GONE
+
val adapter: StatsBlockAdapter
if (recyclerView.adapter == null) {
adapter = StatsBlockAdapter(imageManager)
@@ -197,6 +216,7 @@ class StatsListFragment : DaggerFragment() {
} else {
adapter = recyclerView.adapter as StatsBlockAdapter
}
+
val layoutManager = recyclerView?.layoutManager
val recyclerViewState = layoutManager?.onSaveInstanceState()
adapter.update(statsState)
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsListItemDecoration.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListItemDecoration.kt
similarity index 95%
rename from WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsListItemDecoration.kt
rename to WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListItemDecoration.kt
index ad26320b52ee..10fdf97ff384 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsListItemDecoration.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListItemDecoration.kt
@@ -1,4 +1,4 @@
-package org.wordpress.android.ui.stats.refresh
+package org.wordpress.android.ui.stats.refresh.lists
import android.graphics.Rect
import android.support.v7.widget.RecyclerView
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListViewModel.kt
index 3ddb76930526..c60bcb98e07c 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/StatsListViewModel.kt
@@ -1,6 +1,7 @@
package org.wordpress.android.ui.stats.refresh.lists
import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.MutableLiveData
import android.support.annotation.StringRes
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
@@ -14,6 +15,7 @@ import org.wordpress.android.ui.stats.refresh.DAY_STATS_USE_CASE
import org.wordpress.android.ui.stats.refresh.INSIGHTS_USE_CASE
import org.wordpress.android.ui.stats.refresh.MONTH_STATS_USE_CASE
import org.wordpress.android.ui.stats.refresh.NavigationTarget
+import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewInsightsManagement
import org.wordpress.android.ui.stats.refresh.StatsViewModel.DateSelectorUiModel
import org.wordpress.android.ui.stats.refresh.WEEK_STATS_USE_CASE
import org.wordpress.android.ui.stats.refresh.YEAR_STATS_USE_CASE
@@ -22,9 +24,11 @@ import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSect
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.MONTHS
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.WEEKS
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.YEARS
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsDateSelector
import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
import org.wordpress.android.util.mapNullable
+import org.wordpress.android.util.mergeNotNull
import org.wordpress.android.util.throttle
import org.wordpress.android.viewmodel.Event
import org.wordpress.android.viewmodel.ScopedViewModel
@@ -37,7 +41,8 @@ abstract class StatsListViewModel(
defaultDispatcher: CoroutineDispatcher,
private val statsUseCase: BaseListUseCase,
private val analyticsTracker: AnalyticsTrackerWrapper,
- private val dateSelector: StatsDateSelector
+ private val dateSelector: StatsDateSelector,
+ popupMenuHandler: ItemPopupMenuHandler? = null
) : ScopedViewModel(defaultDispatcher) {
private var trackJob: Job? = null
private var isInitialized = false
@@ -54,7 +59,10 @@ abstract class StatsListViewModel(
val selectedDate = dateSelector.selectedDate
- val navigationTarget: LiveData> = statsUseCase.navigationTarget
+ private val mutableNavigationTarget = MutableLiveData>()
+ val navigationTarget: LiveData> = mergeNotNull(
+ statsUseCase.navigationTarget, mutableNavigationTarget
+ )
val listSelected = statsUseCase.listSelected
@@ -66,6 +74,8 @@ abstract class StatsListViewModel(
it ?: DateSelectorUiModel(false)
}
+ val typeMoved = popupMenuHandler?.typeMoved
+
override fun onCleared() {
statsUseCase.onCleared()
super.onCleared()
@@ -108,6 +118,10 @@ abstract class StatsListViewModel(
dateSelector.updateDateSelector()
}
+ fun onEmptyInsightsButtonClicked() {
+ mutableNavigationTarget.value = Event(ViewInsightsManagement)
+ }
+
fun start() {
if (!isInitialized) {
isInitialized = true
@@ -122,6 +136,13 @@ abstract class StatsListViewModel(
sealed class UiModel {
data class Success(val data: List) : UiModel()
class Error(val message: Int = R.string.stats_loading_error) : UiModel()
+ object Empty : UiModel()
+ }
+
+ fun onTypeMoved() {
+ launch {
+ statsUseCase.refreshTypes()
+ }
}
}
@@ -130,8 +151,15 @@ class InsightsListViewModel
@Named(UI_THREAD) mainDispatcher: CoroutineDispatcher,
@Named(INSIGHTS_USE_CASE) private val insightsUseCase: BaseListUseCase,
analyticsTracker: AnalyticsTrackerWrapper,
- dateSelectorFactory: StatsDateSelector.Factory
-) : StatsListViewModel(mainDispatcher, insightsUseCase, analyticsTracker, dateSelectorFactory.build(INSIGHTS))
+ dateSelectorFactory: StatsDateSelector.Factory,
+ popupMenuHandler: ItemPopupMenuHandler
+) : StatsListViewModel(
+ mainDispatcher,
+ insightsUseCase,
+ analyticsTracker,
+ dateSelectorFactory.build(INSIGHTS),
+ popupMenuHandler
+)
class YearsListViewModel @Inject constructor(
@Named(UI_THREAD) mainDispatcher: CoroutineDispatcher,
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/UiModelMapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/UiModelMapper.kt
index 15ad6c2ef7ba..ae02f7a13836 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/UiModelMapper.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/UiModelMapper.kt
@@ -1,69 +1,97 @@
package org.wordpress.android.ui.stats.refresh.lists
+import android.arch.lifecycle.MutableLiveData
import org.wordpress.android.R.string
-import org.wordpress.android.fluxc.store.StatsStore.PostDetailTypes
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes
-import org.wordpress.android.ui.stats.refresh.lists.StatsBlock.Error
+import org.wordpress.android.fluxc.store.StatsStore.PostDetailType
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType
+import org.wordpress.android.ui.stats.refresh.NavigationTarget
+import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewInsightsManagement
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.UiModel
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.UseCaseModel
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.UseCaseModel.UseCaseState.EMPTY
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.UseCaseModel.UseCaseState.ERROR
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.UseCaseModel.UseCaseState.LOADING
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.UseCaseModel.UseCaseState.SUCCESS
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.LinkButton
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.NavigationAction
import org.wordpress.android.util.NetworkUtilsWrapper
+import org.wordpress.android.viewmodel.Event
import javax.inject.Inject
class UiModelMapper
@Inject constructor(private val networkUtilsWrapper: NetworkUtilsWrapper) {
- fun mapInsights(useCaseModels: List, showError: (Int) -> Unit): UiModel {
- val allFailing = useCaseModels.isNotEmpty() && useCaseModels.fold(true) { acc, useCaseModel ->
- acc && useCaseModel.state == ERROR
- }
- val allFailingWithoutData = useCaseModels.isNotEmpty() && useCaseModels.fold(true) { acc, useCaseModel ->
- acc && useCaseModel.state == ERROR && useCaseModel.data == null
- }
- return if (!allFailing && !allFailingWithoutData) {
- UiModel.Success(useCaseModels.map { useCaseModel ->
- when (useCaseModel.state) {
- SUCCESS -> StatsBlock.Success(useCaseModel.type, useCaseModel.data ?: listOf())
- ERROR -> Error(
- useCaseModel.type,
- useCaseModel.stateData ?: useCaseModel.data ?: listOf()
- )
- LOADING -> StatsBlock.Loading(
- useCaseModel.type,
- useCaseModel.stateData ?: useCaseModel.data ?: listOf()
- )
- EMPTY -> StatsBlock.EmptyBlock(
+ fun mapInsights(
+ useCaseModels: List,
+ navigationTarget: MutableLiveData>,
+ showError: (Int) -> Unit
+ ): UiModel {
+ if (useCaseModels.isNotEmpty()) {
+ val allFailing = useCaseModels.fold(true) { acc, useCaseModel ->
+ acc && useCaseModel.state == ERROR
+ }
+ val allFailingWithoutData = useCaseModels.isNotEmpty() && useCaseModels.fold(true) { acc, useCaseModel ->
+ acc && useCaseModel.state == ERROR && useCaseModel.data == null
+ }
+ return if (!allFailing && !allFailingWithoutData) {
+ val data = useCaseModels.map { useCaseModel ->
+ when (useCaseModel.state) {
+ SUCCESS -> StatsBlock.Success(useCaseModel.type, useCaseModel.data ?: listOf())
+ ERROR -> StatsBlock.Error(
+ useCaseModel.type,
+ useCaseModel.stateData ?: useCaseModel.data ?: listOf()
+ )
+ LOADING -> StatsBlock.Loading(
+ useCaseModel.type,
+ useCaseModel.stateData ?: useCaseModel.data ?: listOf()
+ )
+ EMPTY -> StatsBlock.EmptyBlock(
+ useCaseModel.type,
+ useCaseModel.stateData ?: useCaseModel.data ?: listOf()
+ )
+ }
+ }.toMutableList()
+
+ data += StatsBlock.Control(listOf(LinkButton(string.edit,
+ NavigationAction.create {
+ navigationTarget.value = Event(ViewInsightsManagement)
+ }
+ )))
+ UiModel.Success(data)
+ } else if (!allFailingWithoutData) {
+ showError(getErrorMessage())
+ UiModel.Success(useCaseModels.map { useCaseModel ->
+ StatsBlock.Error(
useCaseModel.type,
- useCaseModel.stateData ?: useCaseModel.data ?: listOf()
+ useCaseModel.data ?: useCaseModel.stateData ?: listOf()
)
- }
- })
- } else if (!allFailingWithoutData) {
- showError(getErrorMessage())
- UiModel.Success(useCaseModels.map { useCaseModel ->
- Error(
- useCaseModel.type,
- useCaseModel.data ?: useCaseModel.stateData ?: listOf()
- )
- })
+ })
+ } else {
+ UiModel.Error(getErrorMessage())
+ }
} else {
- UiModel.Error(getErrorMessage())
+ return UiModel.Empty
}
}
- fun mapTimeStats(useCaseModels: List, showError: (Int) -> Unit): UiModel {
- return mapStatsWithOverview(TimeStatsTypes.OVERVIEW, useCaseModels, showError)
+ fun mapTimeStats(
+ useCaseModels: List,
+ navigationTarget: MutableLiveData>,
+ showError: (Int) -> Unit
+ ): UiModel {
+ return mapStatsWithOverview(TimeStatsType.OVERVIEW, useCaseModels, showError)
}
- fun mapDetailStats(useCaseModels: List, showError: (Int) -> Unit): UiModel {
- return mapStatsWithOverview(PostDetailTypes.POST_OVERVIEW, useCaseModels, showError)
+ fun mapDetailStats(
+ useCaseModels: List,
+ navigationTarget: MutableLiveData>,
+ showError: (Int) -> Unit
+ ): UiModel {
+ return mapStatsWithOverview(PostDetailType.POST_OVERVIEW, useCaseModels, showError)
}
private fun mapStatsWithOverview(
- overViewType: StatsTypes,
+ overViewType: StatsType,
useCaseModels: List,
showError: (Int) -> Unit
): UiModel {
@@ -73,33 +101,37 @@ class UiModelMapper
}
val overviewHasData = useCaseModels.any { it.type == overViewType && it.data != null }
return if (!allFailing) {
- UiModel.Success(useCaseModels.mapNotNull { useCaseModel ->
- if ((useCaseModel.type == overViewType) && useCaseModel.data != null) {
- StatsBlock.Success(useCaseModel.type, useCaseModel.data)
- } else {
- when (useCaseModel.state) {
- SUCCESS -> StatsBlock.Success(useCaseModel.type, useCaseModel.data ?: listOf())
- ERROR -> useCaseModel.stateData?.let {
- Error(
- useCaseModel.type,
- useCaseModel.stateData
- )
- }
- LOADING -> useCaseModel.stateData?.let {
- StatsBlock.Loading(
- useCaseModel.type,
- useCaseModel.stateData
- )
- }
- EMPTY -> useCaseModel.stateData?.let {
- StatsBlock.EmptyBlock(
- useCaseModel.type,
- useCaseModel.stateData
- )
+ if (useCaseModels.isNotEmpty()) {
+ UiModel.Success(useCaseModels.mapNotNull { useCaseModel ->
+ if ((useCaseModel.type == overViewType) && useCaseModel.data != null) {
+ StatsBlock.Success(useCaseModel.type, useCaseModel.data)
+ } else {
+ when (useCaseModel.state) {
+ SUCCESS -> StatsBlock.Success(useCaseModel.type, useCaseModel.data ?: listOf())
+ ERROR -> useCaseModel.stateData?.let {
+ StatsBlock.Error(
+ useCaseModel.type,
+ useCaseModel.stateData
+ )
+ }
+ LOADING -> useCaseModel.stateData?.let {
+ StatsBlock.Loading(
+ useCaseModel.type,
+ useCaseModel.stateData
+ )
+ }
+ EMPTY -> useCaseModel.stateData?.let {
+ StatsBlock.EmptyBlock(
+ useCaseModel.type,
+ useCaseModel.stateData
+ )
+ }
}
}
- }
- })
+ })
+ } else {
+ UiModel.Empty
+ }
} else if (overviewHasData) {
showError(getErrorMessage())
UiModel.Success(useCaseModels.mapNotNull { useCaseModel ->
@@ -107,7 +139,7 @@ class UiModelMapper
StatsBlock.Success(useCaseModel.type, useCaseModel.data)
} else {
useCaseModel.stateData?.let {
- Error(
+ StatsBlock.Error(
useCaseModel.type,
useCaseModel.stateData
)
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostAverageViewsPerDayUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostAverageViewsPerDayUseCase.kt
index fceb81db30bf..b06797ac879a 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostAverageViewsPerDayUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostAverageViewsPerDayUseCase.kt
@@ -3,7 +3,7 @@ package org.wordpress.android.ui.stats.refresh.lists.detail
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.PostDetailStatsModel
-import org.wordpress.android.fluxc.store.StatsStore.PostDetailTypes
+import org.wordpress.android.fluxc.store.StatsStore.PostDetailType
import org.wordpress.android.fluxc.store.stats.PostDetailStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewDayAverageStats
@@ -33,7 +33,7 @@ class PostAverageViewsPerDayUseCase(
private val postDetailMapper: PostDetailMapper,
private val useCaseMode: UseCaseMode
) : BaseStatsUseCase(
- PostDetailTypes.AVERAGE_VIEWS_PER_DAY,
+ PostDetailType.AVERAGE_VIEWS_PER_DAY,
mainDispatcher,
ExpandedYearUiState()
) {
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt
index 778327ca4bd2..bc9c05f87727 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt
@@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.PostDetailStatsModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity.DAYS
-import org.wordpress.android.fluxc.store.StatsStore.PostDetailTypes
+import org.wordpress.android.fluxc.store.StatsStore.PostDetailType
import org.wordpress.android.fluxc.store.stats.PostDetailStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.DETAIL
@@ -30,7 +30,7 @@ class PostDayViewsUseCase
private val statsPostProvider: StatsPostProvider,
private val postDetailStore: PostDetailStore
) : BaseStatsUseCase(
- PostDetailTypes.POST_OVERVIEW,
+ PostDetailType.POST_OVERVIEW,
mainDispatcher,
UiState()
) {
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostHeaderUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostHeaderUseCase.kt
index 797fc6726f68..c8a0fd72b94f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostHeaderUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostHeaderUseCase.kt
@@ -2,7 +2,7 @@ package org.wordpress.android.ui.stats.refresh.lists.detail
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R.string
-import org.wordpress.android.fluxc.store.StatsStore.PostDetailTypes
+import org.wordpress.android.fluxc.store.StatsStore.PostDetailType
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatelessUseCase
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
@@ -16,7 +16,7 @@ class PostHeaderUseCase
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
private val statsPostProvider: StatsPostProvider
) : StatelessUseCase(
- PostDetailTypes.POST_HEADER,
+ PostDetailType.POST_HEADER,
mainDispatcher
) {
override suspend fun loadCachedData(): String? {
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostMonthsAndYearsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostMonthsAndYearsUseCase.kt
index be4afc2f9a0d..f0aacf04b05d 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostMonthsAndYearsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostMonthsAndYearsUseCase.kt
@@ -3,7 +3,7 @@ package org.wordpress.android.ui.stats.refresh.lists.detail
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.PostDetailStatsModel
-import org.wordpress.android.fluxc.store.StatsStore.PostDetailTypes
+import org.wordpress.android.fluxc.store.StatsStore.PostDetailType
import org.wordpress.android.fluxc.store.stats.PostDetailStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewMonthsAndYearsStats
@@ -33,7 +33,7 @@ class PostMonthsAndYearsUseCase(
private val postDetailMapper: PostDetailMapper,
private val useCaseMode: UseCaseMode
) : BaseStatsUseCase(
- PostDetailTypes.MONTHS_AND_YEARS,
+ PostDetailType.MONTHS_AND_YEARS,
mainDispatcher,
ExpandedYearUiState()
) {
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostRecentWeeksUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostRecentWeeksUseCase.kt
index 19910f03b75b..5f9c197edb02 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostRecentWeeksUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostRecentWeeksUseCase.kt
@@ -3,7 +3,7 @@ package org.wordpress.android.ui.stats.refresh.lists.detail
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.PostDetailStatsModel
-import org.wordpress.android.fluxc.store.StatsStore.PostDetailTypes
+import org.wordpress.android.fluxc.store.StatsStore.PostDetailType
import org.wordpress.android.fluxc.store.stats.PostDetailStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewRecentWeeksStats
@@ -33,7 +33,7 @@ class PostRecentWeeksUseCase(
private val postDetailMapper: PostDetailMapper,
private val useCaseMode: UseCaseMode
) : BaseStatsUseCase(
- PostDetailTypes.CLICKS_BY_WEEKS,
+ PostDetailType.CLICKS_BY_WEEKS,
mainDispatcher,
ExpandedWeekUiState()
) {
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/StatsDetailFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/StatsDetailFragment.kt
index 0a39df843538..99eda6c04921 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/StatsDetailFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/StatsDetailFragment.kt
@@ -89,14 +89,14 @@ class StatsDetailFragment : DaggerFragment() {
if (date_selection_toolbar.visibility != dateSelectorVisibility) {
date_selection_toolbar.visibility = dateSelectorVisibility
}
- selected_date.text = dateSelectorUiModel?.date ?: ""
+ selectedDateTextView.text = dateSelectorUiModel?.date ?: ""
val enablePreviousButton = dateSelectorUiModel?.enableSelectPrevious == true
- if (select_previous_date.isEnabled != enablePreviousButton) {
- select_previous_date.isEnabled = enablePreviousButton
+ if (previousDateButton.isEnabled != enablePreviousButton) {
+ previousDateButton.isEnabled = enablePreviousButton
}
val enableNextButton = dateSelectorUiModel?.enableSelectNext == true
- if (select_next_date.isEnabled != enableNextButton) {
- select_next_date.isEnabled = enableNextButton
+ if (nextDateButton.isEnabled != enableNextButton) {
+ nextDateButton.isEnabled = enableNextButton
}
})
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt
index cbdb02a92bdf..2089ff34dea6 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt
@@ -6,7 +6,7 @@ import android.arch.lifecycle.MutableLiveData
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import org.wordpress.android.R
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
import org.wordpress.android.ui.stats.refresh.NavigationTarget
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.State.Data
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.State.Empty
@@ -27,7 +27,7 @@ import org.wordpress.android.viewmodel.Event
* Do not override this class directly. Use StatefulUseCase or StatelessUseCase instead.
*/
abstract class BaseStatsUseCase(
- val type: StatsTypes,
+ val type: StatsType,
private val mainDispatcher: CoroutineDispatcher,
private val defaultUiState: UI_STATE
) {
@@ -200,7 +200,7 @@ abstract class BaseStatsUseCase(
}
data class UseCaseModel(
- val type: StatsTypes,
+ val type: StatsType,
val data: List? = null,
val stateData: List? = null,
val state: UseCaseState = SUCCESS
@@ -216,7 +216,7 @@ abstract class BaseStatsUseCase(
* @param defaultUiState default value the UI state should have when the screen first loads
*/
abstract class StatefulUseCase(
- type: StatsTypes,
+ type: StatsType,
mainDispatcher: CoroutineDispatcher,
private val defaultUiState: UI_STATE
) : BaseStatsUseCase(type, mainDispatcher, defaultUiState) {
@@ -238,7 +238,7 @@ abstract class BaseStatsUseCase(
* These blocks don't have only one UI state and it doesn't change.
*/
abstract class StatelessUseCase(
- type: StatsTypes,
+ type: StatsType,
mainDispatcher: CoroutineDispatcher
) : BaseStatsUseCase(type, mainDispatcher, NotUsedUiState) {
/**
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListAdapter.kt
index b709a1fa71c6..3c1dbb5addcf 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListAdapter.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListAdapter.kt
@@ -16,12 +16,13 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Expan
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Header
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Information
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Link
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.LinkButton
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.ListItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.ListItemWithIcon
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.LoadingItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.MapItem
-import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.ReferredItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.QuickScanItem
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.ReferredItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.TabsItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Text
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
@@ -35,12 +36,13 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.HEADER
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.INFO
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LINK
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LINK_BUTTON
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LIST_ITEM
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LIST_ITEM_WITH_ICON
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LOADING_ITEM
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.MAP
-import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.REFERRED_ITEM
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.QUICK_SCAN_ITEM
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.REFERRED_ITEM
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.TABS
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.TEXT
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.TITLE
@@ -57,13 +59,14 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.Expanda
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.FourColumnsViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.HeaderViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.InformationViewHolder
+import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.LinkButtonViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.LinkViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.ListItemViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.ListItemWithIconViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.LoadingItemViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.MapViewHolder
-import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.ReferredItemViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.QuickScanItemViewHolder
+import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.ReferredItemViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.TabsViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.TextViewHolder
import org.wordpress.android.ui.stats.refresh.lists.sections.viewholders.TitleViewHolder
@@ -121,6 +124,7 @@ class BlockListAdapter(val imageManager: ImageManager) : Adapter ActivityViewHolder(parent)
REFERRED_ITEM -> ReferredItemViewHolder(parent)
QUICK_SCAN_ITEM -> QuickScanItemViewHolder(parent)
+ LINK_BUTTON -> LinkButtonViewHolder(parent)
}
}
@@ -155,6 +159,7 @@ class BlockListAdapter(val imageManager: ImageManager) : Adapter holder.bind(item as LoadingItem)
is ReferredItemViewHolder -> holder.bind(item as ReferredItem)
is QuickScanItemViewHolder -> holder.bind(item as QuickScanItem)
+ is LinkButtonViewHolder -> holder.bind(item as LinkButton)
}
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListItem.kt
index 9d06dbcaf409..626760889bb8 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListItem.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BlockListItem.kt
@@ -2,6 +2,7 @@ package org.wordpress.android.ui.stats.refresh.lists.sections
import android.support.annotation.DrawableRes
import android.support.annotation.StringRes
+import android.view.View
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.ListItemWithIcon.IconStyle.NORMAL
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.ACTIVITY_ITEM
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.BAR_CHART
@@ -13,6 +14,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.HEADER
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.INFO
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LINK
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LINK_BUTTON
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LIST_ITEM
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LIST_ITEM_WITH_ICON
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Type.LOADING_ITEM
@@ -51,10 +53,15 @@ sealed class BlockListItem(val type: Type) {
LOADING_ITEM,
ACTIVITY_ITEM,
REFERRED_ITEM,
- QUICK_SCAN_ITEM
+ QUICK_SCAN_ITEM,
+ LINK_BUTTON
}
- data class Title(@StringRes val textResource: Int? = null, val text: String? = null) : BlockListItem(TITLE)
+ data class Title(
+ @StringRes val textResource: Int? = null,
+ val text: String? = null,
+ val menuAction: ((View) -> Unit)? = null
+ ) : BlockListItem(TITLE)
data class ReferredItem(@StringRes val label: Int, val itemTitle: String) : BlockListItem(REFERRED_ITEM)
@@ -134,8 +141,12 @@ sealed class BlockListItem(val type: Type) {
@DrawableRes val icon: Int? = null,
@StringRes val text: Int,
val navigateAction: NavigationAction
- ) :
- BlockListItem(LINK)
+ ) : BlockListItem(LINK)
+
+ data class LinkButton(
+ @StringRes val text: Int,
+ val navigateAction: NavigationAction
+ ) : BlockListItem(LINK_BUTTON)
data class BarChartItem(
val entries: List,
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatefulUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatefulUseCase.kt
index 60c8b17ce4df..d79c978b6911 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatefulUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatefulUseCase.kt
@@ -4,14 +4,14 @@ import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatefulUseCase
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import java.util.Date
abstract class GranularStatefulUseCase(
- type: StatsTypes,
+ type: StatsType,
mainDispatcher: CoroutineDispatcher,
val statsSiteProvider: StatsSiteProvider,
val selectedDateProvider: SelectedDateProvider,
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatelessUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatelessUseCase.kt
index d8a4dfd126d2..d63c796520a4 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatelessUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/GranularStatelessUseCase.kt
@@ -4,14 +4,14 @@ import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatelessUseCase
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import java.util.Date
abstract class GranularStatelessUseCase(
- type: StatsTypes,
+ type: StatsType,
mainDispatcher: CoroutineDispatcher,
val selectedDateProvider: SelectedDateProvider,
val statsSiteProvider: StatsSiteProvider,
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/AuthorsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/AuthorsUseCase.kt
index 9421c52d70f7..f9755680c84f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/AuthorsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/AuthorsUseCase.kt
@@ -8,7 +8,7 @@ import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.time.AuthorsModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.AUTHORS
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.AUTHORS
import org.wordpress.android.fluxc.store.stats.time.AuthorsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.StatsConstants
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ClicksUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ClicksUseCase.kt
index 7ecca14b38c0..3d59e419c1d2 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ClicksUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ClicksUseCase.kt
@@ -8,7 +8,7 @@ import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.time.ClicksModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.CLICKS
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.CLICKS
import org.wordpress.android.fluxc.store.stats.time.ClicksStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewClicks
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/CountryViewsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/CountryViewsUseCase.kt
index 51b442505465..f299ff9e9fc2 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/CountryViewsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/CountryViewsUseCase.kt
@@ -8,7 +8,7 @@ import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.time.CountryViewsModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.COUNTRIES
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.COUNTRIES
import org.wordpress.android.fluxc.store.stats.time.CountryViewsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewCountries
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt
index 8c3f83876f43..eb92514d4fca 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt
@@ -6,7 +6,7 @@ import org.wordpress.android.analytics.AnalyticsTracker
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.time.VisitsAndViewsModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.OVERVIEW
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.OVERVIEW
import org.wordpress.android.fluxc.store.stats.time.VisitsAndViewsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatefulUseCase
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/PostsAndPagesUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/PostsAndPagesUseCase.kt
index aae4b9af1823..182d7a4df514 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/PostsAndPagesUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/PostsAndPagesUseCase.kt
@@ -11,7 +11,7 @@ import org.wordpress.android.fluxc.model.stats.time.PostAndPageViewsModel.ViewsT
import org.wordpress.android.fluxc.model.stats.time.PostAndPageViewsModel.ViewsType.PAGE
import org.wordpress.android.fluxc.model.stats.time.PostAndPageViewsModel.ViewsType.POST
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.POSTS_AND_PAGES
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.POSTS_AND_PAGES
import org.wordpress.android.fluxc.store.stats.time.PostAndPageViewsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.StatsConstants.ITEM_TYPE_HOME_PAGE
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt
index 0c761ff1a1a4..870f5224c848 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt
@@ -8,7 +8,7 @@ import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.time.ReferrersModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.REFERRERS
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.REFERRERS
import org.wordpress.android.fluxc.store.stats.time.ReferrersStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewReferrers
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/SearchTermsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/SearchTermsUseCase.kt
index 3ca0f40534db..558efbe85bdb 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/SearchTermsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/SearchTermsUseCase.kt
@@ -8,7 +8,7 @@ import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.time.SearchTermsModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.SEARCH_TERMS
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.SEARCH_TERMS
import org.wordpress.android.fluxc.store.stats.time.SearchTermsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewSearchTerms
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/VideoPlaysUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/VideoPlaysUseCase.kt
index f546e695f8f9..5f1c3a8e4d86 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/VideoPlaysUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/VideoPlaysUseCase.kt
@@ -8,7 +8,7 @@ import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.time.VideoPlaysModel
import org.wordpress.android.fluxc.network.utils.StatsGranularity
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.VIDEOS
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.VIDEOS
import org.wordpress.android.fluxc.store.stats.time.VideoPlaysStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewUrl
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/InsightsMenuAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/InsightsMenuAdapter.kt
new file mode 100644
index 000000000000..b2a4735614d0
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/InsightsMenuAdapter.kt
@@ -0,0 +1,73 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.ImageView
+import android.widget.TextView
+
+import org.wordpress.android.R
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter.InsightsMenuItem.DOWN
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter.InsightsMenuItem.REMOVE
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter.InsightsMenuItem.UP
+
+class InsightsMenuAdapter(context: Context, isUpVisible: Boolean, isDownVisible: Boolean) : BaseAdapter() {
+ private val mInflater: LayoutInflater = LayoutInflater.from(context)
+ private val items = listOfNotNull(if (isUpVisible) UP else null, if (isDownVisible) DOWN else null, REMOVE)
+
+ override fun getCount(): Int {
+ return items.size
+ }
+
+ override fun getItem(position: Int): Any {
+ return items[position]
+ }
+
+ override fun getItemId(position: Int): Long {
+ return items[position].id
+ }
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var view = convertView
+ val holder: MenuHolder
+ if (view == null) {
+ view = mInflater.inflate(R.layout.stats_insights_popup_menu_item, parent, false)
+ holder = MenuHolder(view!!)
+ view.tag = holder
+ } else {
+ holder = view.tag as MenuHolder
+ }
+
+ val textRes: Int
+ val iconRes: Int
+ when (items[position]) {
+ UP -> {
+ textRes = R.string.stats_menu_move_up
+ iconRes = R.drawable.ic_arrow_up_grey_dark_24dp
+ }
+ DOWN -> {
+ textRes = R.string.stats_menu_move_down
+ iconRes = R.drawable.ic_arrow_down_grey_dark_24dp
+ }
+ REMOVE -> {
+ textRes = R.string.stats_menu_remove
+ iconRes = R.drawable.ic_trash_grey_dark_24dp
+ }
+ }
+
+ holder.text.setText(textRes)
+ holder.icon.setImageResource(iconRes)
+ return view
+ }
+
+ internal inner class MenuHolder(view: View) {
+ val text: TextView = view.findViewById(R.id.text)
+ val icon: ImageView = view.findViewById(R.id.image)
+ }
+
+ enum class InsightsMenuItem(val id: Long) {
+ UP(0), DOWN(1), REMOVE(2)
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/AddedInsightViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/AddedInsightViewHolder.kt
new file mode 100644
index 000000000000..fecb7c741dbf
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/AddedInsightViewHolder.kt
@@ -0,0 +1,52 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.support.v4.view.MotionEventCompat
+import android.support.v7.widget.RecyclerView.ViewHolder
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageButton
+import android.widget.TextView
+import org.wordpress.android.R
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel
+
+class AddedInsightViewHolder(
+ val parent: ViewGroup,
+ private val onDragStarted: (viewHolder: ViewHolder) -> Unit,
+ private val onButtonClicked: (InsightModel) -> Unit
+) : InsightsManagementViewHolder(parent) {
+ private val title: TextView = itemView.findViewById(R.id.itemTitle)
+ private val managementButton: ImageButton = itemView.findViewById(R.id.insightsManagementItemButton)
+ private val dragAndDropButton: View = itemView.findViewById(R.id.dragAndDropItemButton)
+ private val divider: View = itemView.findViewById(R.id.divider)
+
+ override fun bind(insight: InsightModel, isLast: Boolean) {
+ title.setText(insight.name)
+
+ managementButton.setImageResource(R.drawable.ic_remove_circle)
+ managementButton.setOnClickListener {
+ managementButton.setOnClickListener(null)
+ onButtonClicked(insight)
+ }
+
+ dragAndDropButton.setOnTouchListener { _, event ->
+ if (MotionEventCompat.isFromSource(event, MotionEvent.ACTION_DOWN)) {
+ onDragStarted(this)
+ itemView.elevation = 10f
+ }
+ return@setOnTouchListener true
+ }
+
+ dragAndDropButton.visibility = View.VISIBLE
+
+ updateDividerVisibility(isLast)
+ }
+
+ fun updateDividerVisibility(isLast: Boolean) {
+ divider.visibility = if (isLast) View.GONE else View.VISIBLE
+ }
+
+ fun onDragFinished() {
+ itemView.elevation = 0f
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementActivity.kt
new file mode 100644
index 000000000000..823d47df9ba3
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementActivity.kt
@@ -0,0 +1,28 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import android.view.MenuItem
+import org.wordpress.android.R
+
+class InsightsManagementActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.insights_management_activity)
+
+ supportActionBar?.let {
+ it.setHomeButtonEnabled(true)
+ it.setDisplayHomeAsUpEnabled(true)
+ it.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp)
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ if (item.itemId == android.R.id.home) {
+ onBackPressed()
+ return true
+ }
+ return super.onOptionsItemSelected(item)
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementAdapter.kt
new file mode 100644
index 000000000000..f0861ae66c36
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementAdapter.kt
@@ -0,0 +1,89 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.support.v7.util.DiffUtil
+import android.support.v7.util.DiffUtil.Callback
+import android.support.v7.widget.RecyclerView.Adapter
+import android.support.v7.widget.RecyclerView.ViewHolder
+import android.view.ViewGroup
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel.Status.ADDED
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel.Status.REMOVED
+import java.util.Collections
+
+class InsightsManagementAdapter(
+ private val onItemButtonClicked: (InsightModel) -> Unit,
+ private val onDragStarted: (viewHolder: ViewHolder) -> Unit,
+ private val onDragFinished: (List) -> Unit
+) : Adapter(), ItemTouchHelperAdapter {
+ private var items = ArrayList()
+
+ override fun onCreateViewHolder(parent: ViewGroup, itemType: Int): InsightsManagementViewHolder {
+ val type = InsightModel.Status.values()[itemType]
+ return when (type) {
+ ADDED -> AddedInsightViewHolder(parent, onDragStarted, onItemButtonClicked)
+ REMOVED -> RemovedInsightViewHolder(parent, onItemButtonClicked)
+ }
+ }
+
+ override fun onBindViewHolder(holder: InsightsManagementViewHolder, position: Int) {
+ holder.bind(items[position], position == items.size - 1)
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return items[position].type.ordinal
+ }
+
+ override fun onItemMoved(originalViewHolder: ViewHolder, newViewHolder: ViewHolder) {
+ val fromPosition = originalViewHolder.adapterPosition
+ val toPosition = newViewHolder.adapterPosition
+ if (fromPosition < toPosition) {
+ for (i in fromPosition until toPosition) {
+ Collections.swap(items, i, i + 1)
+ }
+ } else {
+ for (i in fromPosition downTo toPosition + 1) {
+ Collections.swap(items, i, i - 1)
+ }
+ }
+ notifyItemMoved(fromPosition, toPosition)
+
+ (originalViewHolder as? AddedInsightViewHolder)?.updateDividerVisibility(toPosition == items.size - 1)
+ (newViewHolder as? AddedInsightViewHolder)?.updateDividerVisibility(fromPosition == items.size - 1)
+ }
+
+ override fun onDragFinished(viewHolder: ViewHolder) {
+ onDragFinished.invoke(items)
+
+ (viewHolder as? AddedInsightViewHolder)?.onDragFinished()
+ }
+
+ override fun getItemCount(): Int = items.size
+
+ fun update(newItems: List) {
+ val diffResult = DiffUtil.calculateDiff(InsightModelDiffCallback(items, newItems))
+ items = ArrayList(newItems)
+ diffResult.dispatchUpdatesTo(this)
+ }
+}
+
+interface ItemTouchHelperAdapter {
+ fun onItemMoved(originalViewHolder: ViewHolder, newViewHolder: ViewHolder)
+ fun onDragFinished(viewHolder: ViewHolder)
+}
+
+class InsightModelDiffCallback(
+ private val oldList: List,
+ private val newList: List
+) : Callback() {
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ return oldList[oldItemPosition].insightType == newList[newItemPosition].insightType
+ }
+
+ override fun getOldListSize(): Int = oldList.size
+
+ override fun getNewListSize(): Int = newList.size
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ return oldList[oldItemPosition] == newList[newItemPosition]
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementFragment.kt
new file mode 100644
index 000000000000..bd8c990ba34b
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementFragment.kt
@@ -0,0 +1,144 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.arch.lifecycle.Observer
+import android.arch.lifecycle.ViewModelProvider
+import android.arch.lifecycle.ViewModelProviders
+import android.os.Bundle
+import android.support.v4.app.FragmentActivity
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.helper.ItemTouchHelper
+import android.view.LayoutInflater
+import android.view.Menu
+import android.view.MenuInflater
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import dagger.android.support.DaggerFragment
+import kotlinx.android.synthetic.main.insights_management_fragment.*
+import javax.inject.Inject
+import android.animation.LayoutTransition
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import org.wordpress.android.R
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel
+
+class InsightsManagementFragment : DaggerFragment() {
+ @Inject lateinit var viewModelFactory: ViewModelProvider.Factory
+ private lateinit var viewModel: InsightsManagementViewModel
+ private lateinit var addedInsightsTouchHelper: ItemTouchHelper
+
+ private var menu: Menu? = null
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ setHasOptionsMenu(true)
+ return inflater.inflate(R.layout.insights_management_fragment, container, false)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
+ super.onCreateOptionsMenu(menu, inflater)
+
+ inflater?.inflate(R.menu.menu_insights_management, menu)
+ this.menu = menu
+
+ initializeViews()
+ initializeViewModels(requireActivity())
+
+ enableAnimations()
+ }
+
+ private fun enableAnimations() {
+ viewModel.launch {
+ delay(500)
+ val transition = LayoutTransition()
+ transition.disableTransitionType(LayoutTransition.DISAPPEARING)
+ transition.disableTransitionType(LayoutTransition.APPEARING)
+ transition.enableTransitionType(LayoutTransition.CHANGING)
+ insightsManagementContainer.layoutTransition = transition
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ if (item.itemId == R.id.save_insights) {
+ viewModel.onSaveInsights()
+ }
+ return true
+ }
+
+ private fun initializeViews() {
+ removedInsights.layoutManager = LinearLayoutManager(requireActivity(), LinearLayoutManager.VERTICAL, false)
+ addedInsights.layoutManager = LinearLayoutManager(requireActivity(), LinearLayoutManager.VERTICAL, false)
+ }
+
+ private fun initializeViewModels(activity: FragmentActivity) {
+ viewModel = ViewModelProviders.of(activity, viewModelFactory).get(InsightsManagementViewModel::class.java)
+ viewModel.start()
+
+ setupObservers()
+ }
+
+ private fun setupObservers() {
+ viewModel.removedInsights.observe(this, Observer {
+ it?.let { items ->
+ updateRemovedInsights(items)
+
+ if (items.isEmpty()) {
+ addInsightsHeader.visibility = View.GONE
+ } else {
+ addInsightsHeader.visibility = View.VISIBLE
+ }
+ }
+ })
+
+ viewModel.addedInsights.observe(this, Observer {
+ it?.let { items ->
+ updateAddedInsights(items)
+
+ if (items.isEmpty()) {
+ addedInsightsInfo.visibility = View.GONE
+ } else {
+ addedInsightsInfo.visibility = View.VISIBLE
+ }
+ }
+ })
+
+ viewModel.closeInsightsManagement.observe(this, Observer {
+ requireActivity().finish()
+ })
+
+ viewModel.isMenuVisible.observe(this, Observer { isMenuVisible ->
+ isMenuVisible?.let {
+ menu?.findItem(R.id.save_insights)?.isVisible = isMenuVisible
+ }
+ })
+ }
+
+ private fun updateRemovedInsights(insights: List) {
+ var adapter = removedInsights.adapter as? InsightsManagementAdapter
+ if (adapter == null) {
+ adapter = InsightsManagementAdapter(
+ { item -> viewModel.onItemButtonClicked(item) },
+ { viewHolder -> addedInsightsTouchHelper.startDrag(viewHolder) },
+ { list -> viewModel.onAddedInsightsReordered(list) }
+ )
+ removedInsights.adapter = adapter
+ }
+ adapter.update(insights)
+ }
+
+ private fun updateAddedInsights(insights: List) {
+ var adapter = addedInsights.adapter as? InsightsManagementAdapter
+ if (adapter == null) {
+ adapter = InsightsManagementAdapter(
+ { item -> viewModel.onItemButtonClicked(item) },
+ { viewHolder -> addedInsightsTouchHelper.startDrag(viewHolder) },
+ { list -> viewModel.onAddedInsightsReordered(list) }
+ )
+ addedInsights.adapter = adapter
+
+ val callback = ItemTouchHelperCallback(adapter)
+ addedInsightsTouchHelper = ItemTouchHelper(callback)
+ addedInsightsTouchHelper.attachToRecyclerView(addedInsights)
+ }
+ adapter.update(insights)
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementViewHolder.kt
new file mode 100644
index 000000000000..e0223078ef83
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementViewHolder.kt
@@ -0,0 +1,13 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.support.v7.widget.RecyclerView.ViewHolder
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import org.wordpress.android.R
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel
+
+abstract class InsightsManagementViewHolder(
+ parent: ViewGroup
+) : ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.insights_management_list_item, parent, false)) {
+ abstract fun bind(insight: InsightModel, isLast: Boolean)
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementViewModel.kt
new file mode 100644
index 000000000000..6feb1c9d30c2
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementViewModel.kt
@@ -0,0 +1,123 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.MutableLiveData
+import androidx.annotation.StringRes
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import org.wordpress.android.R
+import org.wordpress.android.fluxc.store.StatsStore
+import org.wordpress.android.fluxc.store.StatsStore.InsightType
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.ALL_TIME_STATS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.ANNUAL_SITE_STATS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.COMMENTS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.FOLLOWERS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.FOLLOWER_TOTALS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.LATEST_POST_SUMMARY
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.MOST_POPULAR_DAY_AND_HOUR
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.POSTING_ACTIVITY
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.PUBLICIZE
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.TAGS_AND_CATEGORIES
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.TODAY_STATS
+import org.wordpress.android.modules.UI_THREAD
+import org.wordpress.android.ui.stats.refresh.INSIGHTS_USE_CASE
+import org.wordpress.android.ui.stats.refresh.lists.BaseListUseCase
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel.Status.ADDED
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel.Status.REMOVED
+import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
+import org.wordpress.android.viewmodel.ScopedViewModel
+import org.wordpress.android.viewmodel.SingleLiveEvent
+import javax.inject.Inject
+import javax.inject.Named
+
+class InsightsManagementViewModel @Inject constructor(
+ @Named(UI_THREAD) mainDispatcher: CoroutineDispatcher,
+ @Named(INSIGHTS_USE_CASE) val insightsUseCase: BaseListUseCase,
+ private val siteProvider: StatsSiteProvider,
+ private val statsStore: StatsStore
+) : ScopedViewModel(mainDispatcher) {
+ private val _removedInsights = MutableLiveData>()
+ val removedInsights: LiveData> = _removedInsights
+
+ private val _addedInsights = MutableLiveData>()
+ val addedInsights: LiveData> = _addedInsights
+
+ private val _closeInsightsManagement = SingleLiveEvent()
+ val closeInsightsManagement: LiveData = _closeInsightsManagement
+
+ private val _isMenuVisible = MutableLiveData()
+ val isMenuVisible: LiveData = _isMenuVisible
+
+ private lateinit var insights: List
+ private var isInitialized = false
+
+ fun start() {
+ if (!isInitialized) {
+ isInitialized = true
+ _isMenuVisible.value = false
+ loadInsights()
+ }
+ }
+
+ private fun loadInsights() {
+ launch {
+ val addedInsights = statsStore.getAddedInsights(siteProvider.siteModel)
+ insights = addedInsights.map { InsightModel(it, ADDED) } +
+ statsStore.getRemovedInsights(addedInsights).map { InsightModel(it, REMOVED) }
+ displayInsights()
+ }
+ }
+
+ private fun displayInsights() {
+ _addedInsights.value = insights.filter { it.type == ADDED }
+ _removedInsights.value = insights.filter { it.type == REMOVED }
+ }
+
+ fun onSaveInsights() {
+ // This has to be GlobalScope because otherwise the coroutine gets killed with the ViewModel
+ GlobalScope.launch {
+ val addedTypes = insights.filter { it.type == ADDED }.map { it.insightType }
+ statsStore.updateTypes(siteProvider.siteModel, addedTypes)
+
+ insightsUseCase.loadData()
+ }
+ _closeInsightsManagement.call()
+ }
+
+ fun onAddedInsightsReordered(addedInsights: List) {
+ insights = addedInsights + insights.filter { it.type == REMOVED }
+ _isMenuVisible.value = true
+ }
+
+ fun onItemButtonClicked(insight: InsightModel) {
+ if (insight.type == ADDED) {
+ insight.type = REMOVED
+ } else {
+ insight.type = ADDED
+ }
+ displayInsights()
+ _isMenuVisible.value = true
+ }
+
+ data class InsightModel(val insightType: InsightType, var type: Status) {
+ @StringRes val name: Int = when (insightType) {
+ LATEST_POST_SUMMARY -> R.string.stats_insights_latest_post_summary
+ MOST_POPULAR_DAY_AND_HOUR -> R.string.stats_insights_popular
+ ALL_TIME_STATS -> R.string.stats_insights_all_time_stats
+ TAGS_AND_CATEGORIES -> R.string.stats_insights_tags_and_categories
+ COMMENTS -> R.string.stats_comments
+ FOLLOWERS -> R.string.stats_view_followers
+ TODAY_STATS -> R.string.stats_insights_today
+ POSTING_ACTIVITY -> R.string.stats_insights_posting_activity
+ PUBLICIZE -> R.string.stats_view_publicize
+ ANNUAL_SITE_STATS -> R.string.stats_insights_this_year_site_stats
+ FOLLOWER_TOTALS -> R.string.stats_view_follower_totals
+ }
+
+ enum class Status {
+ ADDED,
+ REMOVED
+ }
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/ItemTouchHelperCallback.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/ItemTouchHelperCallback.kt
new file mode 100644
index 000000000000..51b9d2944926
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/ItemTouchHelperCallback.kt
@@ -0,0 +1,34 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.RecyclerView.ViewHolder
+import android.support.v7.widget.helper.ItemTouchHelper
+
+class ItemTouchHelperCallback(private val adapter: ItemTouchHelperAdapter) : ItemTouchHelper.Callback() {
+ override fun isLongPressDragEnabled(): Boolean {
+ return false
+ }
+
+ override fun isItemViewSwipeEnabled(): Boolean {
+ return false
+ }
+
+ override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: ViewHolder): Int {
+ val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
+ return makeMovementFlags(dragFlags, 0)
+ }
+
+ override fun onMove(recyclerView: RecyclerView, viewHolder: ViewHolder, target: ViewHolder): Boolean {
+ adapter.onItemMoved(viewHolder, target)
+ return true
+ }
+
+ override fun onSwiped(viewHolder: ViewHolder, direction: Int) {
+ }
+
+ override fun clearView(recyclerView: RecyclerView, viewHolder: ViewHolder) {
+ super.clearView(recyclerView, viewHolder)
+
+ adapter.onDragFinished(viewHolder)
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/RemovedInsightViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/RemovedInsightViewHolder.kt
new file mode 100644
index 000000000000..d231c6ef0504
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/RemovedInsightViewHolder.kt
@@ -0,0 +1,31 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.insights.management
+
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageButton
+import android.widget.TextView
+import org.wordpress.android.R
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightModel
+
+class RemovedInsightViewHolder(
+ val parent: ViewGroup,
+ private val onButtonClicked: (InsightModel) -> Unit
+) : InsightsManagementViewHolder(parent) {
+ private val title: TextView = itemView.findViewById(R.id.itemTitle)
+ private val managementButton: ImageButton = itemView.findViewById(R.id.insightsManagementItemButton)
+ private val dragAndDropButton: View = itemView.findViewById(R.id.dragAndDropItemButton)
+ private val divider: View = itemView.findViewById(R.id.divider)
+
+ override fun bind(insight: InsightModel, isLast: Boolean) {
+ title.setText(insight.name)
+
+ managementButton.setImageResource(R.drawable.ic_add_circle)
+ managementButton.setOnClickListener {
+ managementButton.setOnClickListener(null)
+ onButtonClicked(insight)
+ }
+
+ dragAndDropButton.visibility = View.GONE
+ divider.visibility = if (isLast) View.GONE else View.VISIBLE
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCase.kt
index 9a1c8c57fc10..52a588c2c2e8 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCase.kt
@@ -1,10 +1,11 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.InsightsAllTimeModel
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.ALL_TIME_STATS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.ALL_TIME_STATS
import org.wordpress.android.fluxc.store.stats.insights.AllTimeInsightsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatelessUseCase
@@ -13,6 +14,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Empty
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.QuickScanItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.QuickScanItem.Column
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsDateFormatter
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.ui.stats.refresh.utils.toFormattedString
@@ -24,10 +26,15 @@ class AllTimeStatsUseCase
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
private val allTimeStore: AllTimeInsightsStore,
private val statsSiteProvider: StatsSiteProvider,
- private val statsDateFormatter: StatsDateFormatter
+ private val statsDateFormatter: StatsDateFormatter,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : StatelessUseCase(ALL_TIME_STATS, mainDispatcher) {
override fun buildLoadingItem(): List = listOf(Title(R.string.stats_insights_all_time_stats))
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
+
override suspend fun loadCachedData(): InsightsAllTimeModel? {
return allTimeStore.getAllTimeInsights(statsSiteProvider.siteModel)
}
@@ -51,7 +58,7 @@ class AllTimeStatsUseCase
override fun buildUiModel(domainModel: InsightsAllTimeModel): List {
val items = mutableListOf()
- items.add(Title(R.string.stats_insights_all_time_stats))
+ items.add(buildTitle())
val hasPosts = domainModel.posts > 0
val hasViews = domainModel.views > 0
@@ -84,4 +91,10 @@ class AllTimeStatsUseCase
}
return items
}
+
+ private fun buildTitle() = Title(string.stats_insights_all_time_stats, menuAction = this::onMenuClick)
+
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AnnualSiteStatsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AnnualSiteStatsUseCase.kt
index 80bff5129b8f..cc59286c9cc6 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AnnualSiteStatsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AnnualSiteStatsUseCase.kt
@@ -1,9 +1,11 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
+import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.YearsInsightsModel
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.ANNUAL_SITE_STATS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.ANNUAL_SITE_STATS
import org.wordpress.android.fluxc.store.stats.insights.MostPopularInsightsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget
@@ -17,6 +19,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Navig
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
import org.wordpress.android.ui.stats.refresh.lists.sections.granular.SelectedDateProvider
import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightUseCaseFactory
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.util.LocaleManagerWrapper
import java.util.Calendar
@@ -33,6 +36,7 @@ class AnnualSiteStatsUseCase(
private val selectedDateProvider: SelectedDateProvider,
private val annualStatsMapper: AnnualStatsMapper,
private val localeManagerWrapper: LocaleManagerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler,
private val useCaseMode: UseCaseMode
) : StatelessUseCase(ANNUAL_SITE_STATS, mainDispatcher) {
override suspend fun loadCachedData(): YearsInsightsModel? {
@@ -67,7 +71,7 @@ class AnnualSiteStatsUseCase(
when (useCaseMode) {
BLOCK -> {
- items.add(Title(R.string.stats_insights_this_year_site_stats))
+ items.add(buildTitle())
items.addAll(annualStatsMapper.mapYearInBlock(domainModel.years.last()))
if (domainModel.years.size > VISIBLE_ITEMS) {
items.add(
@@ -102,6 +106,12 @@ class AnnualSiteStatsUseCase(
return calendar.time
}
+ private fun buildTitle() = Title(string.stats_insights_this_year_site_stats, menuAction = this::onMenuClick)
+
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
+
class AnnualSiteStatsUseCaseFactory
@Inject constructor(
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
@@ -109,7 +119,8 @@ class AnnualSiteStatsUseCase(
private val statsSiteProvider: StatsSiteProvider,
private val annualStatsMapper: AnnualStatsMapper,
private val localeManagerWrapper: LocaleManagerWrapper,
- private val selectedDateProvider: SelectedDateProvider
+ private val selectedDateProvider: SelectedDateProvider,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : InsightUseCaseFactory {
override fun build(useCaseMode: UseCaseMode) =
AnnualSiteStatsUseCase(
@@ -119,6 +130,7 @@ class AnnualSiteStatsUseCase(
selectedDateProvider,
annualStatsMapper,
localeManagerWrapper,
+ popupMenuHandler,
useCaseMode
)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/CommentsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/CommentsUseCase.kt
index 112d651ab01b..3e25b249eef4 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/CommentsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/CommentsUseCase.kt
@@ -1,12 +1,13 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.R.string
import org.wordpress.android.analytics.AnalyticsTracker
import org.wordpress.android.fluxc.model.stats.CommentsModel
import org.wordpress.android.fluxc.model.stats.LimitMode
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.COMMENTS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.COMMENTS
import org.wordpress.android.fluxc.store.stats.insights.CommentsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewCommentsStats
@@ -24,6 +25,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Navig
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.TabsItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightUseCaseFactory
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.ui.stats.refresh.utils.toFormattedString
import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
@@ -40,6 +42,7 @@ class CommentsUseCase
private val commentsStore: CommentsStore,
private val statsSiteProvider: StatsSiteProvider,
private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler,
private val useCaseMode: UseCaseMode
) : StatefulUseCase(COMMENTS, mainDispatcher, 0) {
override suspend fun fetchRemoteData(forced: Boolean): State {
@@ -52,7 +55,8 @@ class CommentsUseCase
error != null -> State.Error(error.message ?: error.type.name)
model != null && (model.authors.isNotEmpty() || model.posts.isNotEmpty()) -> State.Data(
model,
- cached = response.cached)
+ cached = response.cached
+ )
else -> State.Empty()
}
}
@@ -64,11 +68,15 @@ class CommentsUseCase
override fun buildLoadingItem(): List = listOf(Title(R.string.stats_view_comments))
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
+
override fun buildStatefulUiModel(model: CommentsModel, uiState: Int): List {
val items = mutableListOf()
if (useCaseMode == BLOCK) {
- items.add(Title(string.stats_view_comments))
+ items.add(buildTitle())
}
if (model.authors.isNotEmpty() || model.posts.isNotEmpty()) {
@@ -99,6 +107,8 @@ class CommentsUseCase
return items
}
+ private fun buildTitle() = Title(string.stats_view_comments, menuAction = this::onMenuClick)
+
private fun buildAuthorsTab(authors: List): List {
val mutableItems = mutableListOf()
if (authors.isNotEmpty()) {
@@ -140,12 +150,17 @@ class CommentsUseCase
navigateTo(ViewCommentsStats(selectedTab))
}
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
+
class CommentsUseCaseFactory
@Inject constructor(
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
private val commentsStore: CommentsStore,
private val statsSiteProvider: StatsSiteProvider,
- private val analyticsTracker: AnalyticsTrackerWrapper
+ private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : InsightUseCaseFactory {
override fun build(useCaseMode: UseCaseMode) =
CommentsUseCase(
@@ -153,6 +168,7 @@ class CommentsUseCase
commentsStore,
statsSiteProvider,
analyticsTracker,
+ popupMenuHandler,
useCaseMode
)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowerTotalsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowerTotalsUseCase.kt
index f5252f8c164a..de4acfaf7906 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowerTotalsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowerTotalsUseCase.kt
@@ -6,7 +6,7 @@ import kotlinx.coroutines.async
import org.wordpress.android.R
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.PagedMode
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.FOLLOWER_TOTALS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.FOLLOWER_TOTALS
import org.wordpress.android.fluxc.store.stats.insights.FollowersStore
import org.wordpress.android.fluxc.store.stats.insights.PublicizeStore
import org.wordpress.android.modules.BG_THREAD
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCase.kt
index 0181bfb81e0d..42939b0cf06d 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCase.kt
@@ -1,5 +1,6 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
@@ -12,7 +13,7 @@ import org.wordpress.android.fluxc.model.stats.FollowersModel
import org.wordpress.android.fluxc.model.stats.FollowersModel.FollowerModel
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.PagedMode
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.FOLLOWERS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.FOLLOWERS
import org.wordpress.android.fluxc.store.stats.insights.FollowersStore
import org.wordpress.android.modules.BG_THREAD
import org.wordpress.android.modules.UI_THREAD
@@ -34,6 +35,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.TabsI
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightUseCaseFactory
import org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.FollowersUseCase.FollowersUiState
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
import org.wordpress.android.viewmodel.ResourceProvider
@@ -51,6 +53,7 @@ class FollowersUseCase(
private val statsUtilsWrapper: StatsUtilsWrapper,
private val resourceProvider: ResourceProvider,
private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler,
private val useCaseMode: UseCaseMode
) : StatefulUseCase, FollowersUiState>(
FOLLOWERS,
@@ -118,6 +121,10 @@ class FollowersUseCase(
override fun buildLoadingItem(): List = listOf(Title(R.string.stats_view_followers))
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
+
override fun buildStatefulUiModel(
domainModel: Pair,
uiState: FollowersUiState
@@ -127,7 +134,7 @@ class FollowersUseCase(
val items = mutableListOf()
if (useCaseMode == BLOCK) {
- items.add(Title(string.stats_view_followers))
+ items.add(buildTitle())
}
if (domainModel.first.followers.isNotEmpty() || domainModel.second.followers.isNotEmpty()) {
@@ -168,6 +175,8 @@ class FollowersUseCase(
return items
}
+ private fun buildTitle() = Title(string.stats_view_followers, menuAction = this::onMenuClick)
+
private fun loadMore() {
GlobalScope.launch(bgDispatcher) {
val state = fetchData(true, PagedMode(itemsToLoad, true))
@@ -214,6 +223,10 @@ class FollowersUseCase(
data class FollowersUiState(val selectedTab: Int = 0, val isLoading: Boolean = false)
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
+
class FollowersUseCaseFactory
@Inject constructor(
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
@@ -222,6 +235,7 @@ class FollowersUseCase(
private val statsSiteProvider: StatsSiteProvider,
private val statsUtilsWrapper: StatsUtilsWrapper,
private val resourceProvider: ResourceProvider,
+ private val popupMenuHandler: ItemPopupMenuHandler,
private val analyticsTracker: AnalyticsTrackerWrapper
) : InsightUseCaseFactory {
override fun build(useCaseMode: UseCaseMode) =
@@ -233,6 +247,7 @@ class FollowersUseCase(
statsUtilsWrapper,
resourceProvider,
analyticsTracker,
+ popupMenuHandler,
useCaseMode
)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt
index ff9d64669c32..5db6e2e19473 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt
@@ -1,5 +1,6 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.R.string
@@ -8,7 +9,7 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_LATEST_POST_S
import org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_LATEST_POST_SUMMARY_SHARE_POST_TAPPED
import org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_LATEST_POST_SUMMARY_VIEW_POST_DETAILS_TAPPED
import org.wordpress.android.fluxc.model.stats.InsightsLatestPostModel
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.LATEST_POST_SUMMARY
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.LATEST_POST_SUMMARY
import org.wordpress.android.fluxc.store.stats.insights.LatestPostInsightsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.AddNewPost
@@ -22,6 +23,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.ListI
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.NavigationAction
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.ValueItem
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.MILLION
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.ui.stats.refresh.utils.toFormattedString
@@ -35,7 +37,8 @@ class LatestPostSummaryUseCase
private val latestPostStore: LatestPostInsightsStore,
private val statsSiteProvider: StatsSiteProvider,
private val latestPostSummaryMapper: LatestPostSummaryMapper,
- private val analyticsTracker: AnalyticsTrackerWrapper
+ private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : StatelessUseCase(LATEST_POST_SUMMARY, mainDispatcher) {
override suspend fun loadCachedData(): InsightsLatestPostModel? {
return latestPostStore.getLatestPostInsights(statsSiteProvider.siteModel)
@@ -67,7 +70,7 @@ class LatestPostSummaryUseCase
private fun buildNullableUiModel(domainModel: InsightsLatestPostModel?): MutableList {
val items = mutableListOf()
- items.add(Title(string.stats_insights_latest_post_summary))
+ items.add(buildTitle())
items.add(latestPostSummaryMapper.buildMessageItem(domainModel, this::onLinkClicked))
if (domainModel != null && domainModel.hasData()) {
items.add(
@@ -100,6 +103,8 @@ class LatestPostSummaryUseCase
return items
}
+ private fun buildTitle() = Title(string.stats_insights_latest_post_summary, menuAction = this::onMenuClick)
+
private fun InsightsLatestPostModel.hasData() =
this.postViewsCount > 0 || this.postCommentCount > 0 || this.postLikeCount > 0
@@ -154,6 +159,10 @@ class LatestPostSummaryUseCase
navigateTo(ViewPost(params.postId, params.postUrl))
}
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
+
data class LinkClickParams(val postId: Long, val postUrl: String)
data class SharePostParams(val postUrl: String, val postTitle: String)
data class ViewMoreParams(val postId: Long, val postTitle: String, val postUrl: String)
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt
index 4a68269d37b4..cf4341de95c0 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt
@@ -1,17 +1,21 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
+import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.InsightsMostPopularModel
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.MOST_POPULAR_DAY_AND_HOUR
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.MOST_POPULAR_DAY_AND_HOUR
import org.wordpress.android.fluxc.store.stats.insights.MostPopularInsightsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatelessUseCase
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.QuickScanItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.QuickScanItem.Column
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Empty
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
import org.wordpress.android.ui.stats.refresh.utils.DateUtils
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.viewmodel.ResourceProvider
import javax.inject.Inject
@@ -24,7 +28,8 @@ class MostPopularInsightsUseCase
private val mostPopularStore: MostPopularInsightsStore,
private val statsSiteProvider: StatsSiteProvider,
private val dateUtils: DateUtils,
- private val resourceProvider: ResourceProvider
+ private val resourceProvider: ResourceProvider,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : StatelessUseCase(MOST_POPULAR_DAY_AND_HOUR, mainDispatcher) {
override suspend fun loadCachedData(): InsightsMostPopularModel? {
return mostPopularStore.getMostPopularInsights(statsSiteProvider.siteModel)
@@ -44,9 +49,13 @@ class MostPopularInsightsUseCase
override fun buildLoadingItem(): List = listOf(Title(R.string.stats_insights_popular))
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
+
override fun buildUiModel(domainModel: InsightsMostPopularModel): List {
val items = mutableListOf()
- items.add(Title(R.string.stats_insights_popular))
+ items.add(buildTitle())
items.add(
QuickScanItem(
Column(
@@ -69,4 +78,10 @@ class MostPopularInsightsUseCase
)
return items
}
+
+ private fun buildTitle() = Title(string.stats_insights_popular, menuAction = this::onMenuClick)
+
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PostingActivityUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PostingActivityUseCase.kt
index e74598851d3b..725602c45969 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PostingActivityUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PostingActivityUseCase.kt
@@ -1,15 +1,18 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.fluxc.model.stats.insights.PostingActivityModel
import org.wordpress.android.fluxc.model.stats.insights.PostingActivityModel.Day
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.POSTING_ACTIVITY
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.POSTING_ACTIVITY
import org.wordpress.android.fluxc.store.stats.insights.PostingActivityStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatelessUseCase
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Empty
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import java.util.Calendar
import javax.inject.Inject
@@ -20,9 +23,14 @@ class PostingActivityUseCase
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
private val store: PostingActivityStore,
private val statsSiteProvider: StatsSiteProvider,
- private val postingActivityMapper: PostingActivityMapper
+ private val postingActivityMapper: PostingActivityMapper,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : StatelessUseCase(POSTING_ACTIVITY, mainDispatcher) {
- override fun buildLoadingItem(): List = listOf(Title(R.string.stats_insights_all_time_stats))
+ override fun buildLoadingItem(): List = listOf(Title(R.string.stats_insights_posting_activity))
+
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
override suspend fun loadCachedData(): PostingActivityModel? {
return store.getPostingActivity(statsSiteProvider.siteModel, getStartDate(), getEndDate())
@@ -44,12 +52,14 @@ class PostingActivityUseCase
override fun buildUiModel(domainModel: PostingActivityModel): List {
val items = mutableListOf()
- items.add(Title(R.string.stats_insights_posting_activity))
+ items.add(buildTitle())
val activityItem = postingActivityMapper.buildActivityItem(domainModel.months, domainModel.max)
items.add(activityItem)
return items
}
+ private fun buildTitle() = Title(R.string.stats_insights_posting_activity, menuAction = this::onMenuClick)
+
private fun getEndDate(): Day {
val endDate = Calendar.getInstance()
return Day(
@@ -68,4 +78,8 @@ class PostingActivityUseCase
startDate.getActualMinimum(Calendar.DAY_OF_MONTH)
)
}
+
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PublicizeUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PublicizeUseCase.kt
index 6c7296a35b44..8e0aec9de598 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PublicizeUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/PublicizeUseCase.kt
@@ -1,12 +1,13 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.R.string
import org.wordpress.android.analytics.AnalyticsTracker
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.PublicizeModel
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.PUBLICIZE
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.PUBLICIZE
import org.wordpress.android.fluxc.store.stats.insights.PublicizeStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewPublicizeStats
@@ -20,6 +21,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Link
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.NavigationAction
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightUseCaseFactory
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.ServiceMapper
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
@@ -36,6 +38,7 @@ class PublicizeUseCase
private val statsSiteProvider: StatsSiteProvider,
private val mapper: ServiceMapper,
private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler,
private val useCaseMode: UseCaseMode
) : StatelessUseCase(PUBLICIZE, mainDispatcher) {
private val itemsToLoad = if (useCaseMode == VIEW_ALL) VIEW_ALL_ITEM_COUNT else BLOCK_ITEM_COUNT
@@ -67,11 +70,15 @@ class PublicizeUseCase
override fun buildLoadingItem(): List = listOf(Title(R.string.stats_view_publicize))
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
+
override fun buildUiModel(domainModel: PublicizeModel): List {
val items = mutableListOf()
if (useCaseMode == BLOCK) {
- items.add(Title(string.stats_view_publicize))
+ items.add(buildTitle())
}
if (domainModel.services.isEmpty()) {
@@ -91,18 +98,25 @@ class PublicizeUseCase
return items
}
+ private fun buildTitle() = Title(R.string.stats_view_publicize, menuAction = this::onMenuClick)
+
private fun onLinkClick() {
analyticsTracker.track(AnalyticsTracker.Stat.STATS_PUBLICIZE_VIEW_MORE_TAPPED)
return navigateTo(ViewPublicizeStats)
}
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
+
class PublicizeUseCaseFactory
@Inject constructor(
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
private val publicizeStore: PublicizeStore,
private val statsSiteProvider: StatsSiteProvider,
private val mapper: ServiceMapper,
- private val analyticsTracker: AnalyticsTrackerWrapper
+ private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : InsightUseCaseFactory {
override fun build(useCaseMode: UseCaseMode) =
PublicizeUseCase(
@@ -111,6 +125,7 @@ class PublicizeUseCase
statsSiteProvider,
mapper,
analyticsTracker,
+ popupMenuHandler,
useCaseMode
)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TagsAndCategoriesUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TagsAndCategoriesUseCase.kt
index 17e447ceccde..4a74edb4f22a 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TagsAndCategoriesUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TagsAndCategoriesUseCase.kt
@@ -1,5 +1,6 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
import org.wordpress.android.R.drawable
@@ -8,7 +9,7 @@ import org.wordpress.android.analytics.AnalyticsTracker
import org.wordpress.android.fluxc.model.stats.LimitMode
import org.wordpress.android.fluxc.model.stats.TagsModel
import org.wordpress.android.fluxc.model.stats.TagsModel.TagModel
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.TAGS_AND_CATEGORIES
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.TAGS_AND_CATEGORIES
import org.wordpress.android.fluxc.store.stats.insights.TagsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewTag
@@ -28,6 +29,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Navig
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightUseCaseFactory
import org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.TagsAndCategoriesUseCase.TagsAndCategoriesUiState
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.ui.stats.refresh.utils.toFormattedString
import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
@@ -45,6 +47,7 @@ class TagsAndCategoriesUseCase
private val statsSiteProvider: StatsSiteProvider,
private val resourceProvider: ResourceProvider,
private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler,
private val useCaseMode: UseCaseMode
) : StatefulUseCase(
TAGS_AND_CATEGORIES,
@@ -71,11 +74,15 @@ class TagsAndCategoriesUseCase
override fun buildLoadingItem(): List = listOf(Title(R.string.stats_insights_tags_and_categories))
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
+
override fun buildStatefulUiModel(domainModel: TagsModel, uiState: TagsAndCategoriesUiState): List {
val items = mutableListOf()
if (useCaseMode == BLOCK) {
- items.add(Title(R.string.stats_insights_tags_and_categories))
+ items.add(buildTitle())
}
if (domainModel.tags.isEmpty()) {
@@ -122,6 +129,8 @@ class TagsAndCategoriesUseCase
return items
}
+ private fun buildTitle() = Title(string.stats_insights_tags_and_categories, menuAction = this::onMenuClick)
+
private fun areTagsEqual(tagA: TagModel, tagB: TagModel?): Boolean {
return tagA.items == tagB?.items && tagA.views == tagB.views
}
@@ -175,6 +184,10 @@ class TagsAndCategoriesUseCase
navigateTo(ViewTag(link))
}
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
+
data class TagsAndCategoriesUiState(val expandedTag: TagModel? = null)
class TagsAndCategoriesUseCaseFactory
@@ -183,7 +196,8 @@ class TagsAndCategoriesUseCase
private val tagsStore: TagsStore,
private val statsSiteProvider: StatsSiteProvider,
private val resourceProvider: ResourceProvider,
- private val analyticsTracker: AnalyticsTrackerWrapper
+ private val analyticsTracker: AnalyticsTrackerWrapper,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : InsightUseCaseFactory {
override fun build(useCaseMode: UseCaseMode) =
TagsAndCategoriesUseCase(
@@ -192,6 +206,7 @@ class TagsAndCategoriesUseCase
statsSiteProvider,
resourceProvider,
analyticsTracker,
+ popupMenuHandler,
useCaseMode
)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCase.kt
index 7b16ed794661..b1711e7f34fe 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCase.kt
@@ -1,9 +1,11 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
+import android.view.View
import kotlinx.coroutines.CoroutineDispatcher
import org.wordpress.android.R
+import org.wordpress.android.R.string
import org.wordpress.android.fluxc.model.stats.VisitsModel
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.TODAY_STATS
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.TODAY_STATS
import org.wordpress.android.fluxc.store.stats.insights.TodayInsightsStore
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.stats.refresh.lists.sections.BaseStatsUseCase.StatelessUseCase
@@ -12,6 +14,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Empty
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.QuickScanItem
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.QuickScanItem.Column
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
+import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
import org.wordpress.android.ui.stats.refresh.utils.toFormattedString
import javax.inject.Inject
@@ -21,7 +24,8 @@ class TodayStatsUseCase
@Inject constructor(
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
private val todayStore: TodayInsightsStore,
- private val statsSiteProvider: StatsSiteProvider
+ private val statsSiteProvider: StatsSiteProvider,
+ private val popupMenuHandler: ItemPopupMenuHandler
) : StatelessUseCase(TODAY_STATS, mainDispatcher) {
override suspend fun loadCachedData(): VisitsModel? {
return todayStore.getTodayInsights(statsSiteProvider.siteModel)
@@ -44,9 +48,13 @@ class TodayStatsUseCase
override fun buildLoadingItem(): List = listOf(Title(R.string.stats_insights_today_stats))
+ override fun buildEmptyItem(): List {
+ return listOf(buildTitle(), Empty())
+ }
+
override fun buildUiModel(domainModel: VisitsModel): List {
val items = mutableListOf()
- items.add(Title(R.string.stats_insights_today_stats))
+ items.add(buildTitle())
val hasViews = domainModel.views > 0
val hasVisitors = domainModel.visitors > 0
@@ -70,4 +78,10 @@ class TodayStatsUseCase
}
return items
}
+
+ private fun onMenuClick(view: View) {
+ popupMenuHandler.onMenuClick(view, type)
+ }
+
+ private fun buildTitle() = Title(string.stats_insights_today_stats, menuAction = this::onMenuClick)
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/viewholders/LinkButtonViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/viewholders/LinkButtonViewHolder.kt
new file mode 100644
index 000000000000..7b99ec6c6ae2
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/viewholders/LinkButtonViewHolder.kt
@@ -0,0 +1,19 @@
+package org.wordpress.android.ui.stats.refresh.lists.sections.viewholders
+
+import android.view.ViewGroup
+import android.widget.TextView
+import org.wordpress.android.R
+import org.wordpress.android.R.id
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.LinkButton
+
+class LinkButtonViewHolder(val parent: ViewGroup) : BlockListItemViewHolder(
+ parent,
+ R.layout.stats_block_link_button_item
+) {
+ private val text = itemView.findViewById(id.text)
+
+ fun bind(item: LinkButton) {
+ text.setText(item.text)
+ text.setOnClickListener { item.navigateAction.click() }
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/viewholders/TitleViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/viewholders/TitleViewHolder.kt
index 04f708903444..ad1d2b783138 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/viewholders/TitleViewHolder.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/viewholders/TitleViewHolder.kt
@@ -1,7 +1,10 @@
package org.wordpress.android.ui.stats.refresh.lists.sections.viewholders
+import android.view.View
import android.view.ViewGroup
+import android.widget.ImageButton
import android.widget.TextView
+import org.wordpress.android.R
import org.wordpress.android.R.id
import org.wordpress.android.R.layout
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem.Title
@@ -11,7 +14,15 @@ class TitleViewHolder(parent: ViewGroup) : BlockListItemViewHolder(
layout.stats_block_title_item
) {
private val text = itemView.findViewById(id.text)
+ private val menu = itemView.findViewById(R.id.menu)
fun bind(item: Title) {
text.setTextOrHide(item.textResource, item.text)
+ if (item.menuAction != null) {
+ menu.visibility = View.VISIBLE
+ menu.setOnClickListener { item.menuAction.invoke(menu) }
+ } else {
+ menu.visibility = View.GONE
+ menu.setOnClickListener(null)
+ }
}
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BaseStatsViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BaseStatsViewHolder.kt
index 37ed84b8acfb..04aad05bb4d9 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BaseStatsViewHolder.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BaseStatsViewHolder.kt
@@ -6,9 +6,9 @@ import android.support.v7.widget.RecyclerView.ViewHolder
import android.support.v7.widget.StaggeredGridLayoutManager
import android.view.LayoutInflater
import android.view.ViewGroup
-import org.wordpress.android.fluxc.store.StatsStore.InsightsTypes.LATEST_POST_SUMMARY
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
-import org.wordpress.android.fluxc.store.StatsStore.TimeStatsTypes.OVERVIEW
+import org.wordpress.android.fluxc.store.StatsStore.InsightType.LATEST_POST_SUMMARY
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
+import org.wordpress.android.fluxc.store.StatsStore.TimeStatsType.OVERVIEW
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
abstract class BaseStatsViewHolder(
@@ -16,8 +16,8 @@ abstract class BaseStatsViewHolder(
@LayoutRes layout: Int
) : ViewHolder(LayoutInflater.from(parent.context).inflate(layout, parent, false)) {
@CallSuper
- open fun bind(statsTypes: StatsTypes, items: List) {
- if (statsTypes == OVERVIEW || statsTypes == LATEST_POST_SUMMARY) {
+ open fun bind(statsType: StatsType?, items: List) {
+ if (statsType == OVERVIEW || statsType == LATEST_POST_SUMMARY) {
val layoutParams = itemView.layoutParams as? StaggeredGridLayoutManager.LayoutParams
layoutParams?.isFullSpan = true
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BlockListViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BlockListViewHolder.kt
index e657dd780d90..f3fbf508cc4a 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BlockListViewHolder.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/BlockListViewHolder.kt
@@ -4,18 +4,18 @@ import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.ViewGroup
import org.wordpress.android.R
-import org.wordpress.android.fluxc.store.StatsStore.StatsTypes
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListAdapter
import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
import org.wordpress.android.util.image.ImageManager
-class BlockListViewHolder(parent: ViewGroup, val imageManager: ImageManager) : BaseStatsViewHolder(
+open class BlockListViewHolder(parent: ViewGroup, val imageManager: ImageManager) : BaseStatsViewHolder(
parent,
R.layout.stats_list_block
) {
private val list: RecyclerView = itemView.findViewById(R.id.stats_block_list)
- override fun bind(statsTypes: StatsTypes, items: List) {
- super.bind(statsTypes, items)
+ override fun bind(statsType: StatsType?, items: List) {
+ super.bind(statsType, items)
list.isNestedScrollingEnabled = false
if (list.adapter == null) {
list.layoutManager = LinearLayoutManager(list.context, LinearLayoutManager.VERTICAL, false)
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/ControlViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/ControlViewHolder.kt
new file mode 100644
index 000000000000..afd9155f6afd
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/ControlViewHolder.kt
@@ -0,0 +1,15 @@
+package org.wordpress.android.ui.stats.refresh.lists.viewholders
+
+import android.view.ViewGroup
+import org.wordpress.android.ui.stats.refresh.lists.sections.BlockListItem
+import org.wordpress.android.util.image.ImageManager
+
+class ControlViewHolder(val parent: ViewGroup, imageManager: ImageManager) : BlockListViewHolder(
+ parent,
+ imageManager
+) {
+ fun bind(items: List) {
+ super.bind(null, items)
+ itemView.background = null
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/LoadingViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/LoadingViewHolder.kt
index 4dd36bcaffcd..49a9f72bb01f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/LoadingViewHolder.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/viewholders/LoadingViewHolder.kt
@@ -14,8 +14,8 @@ class LoadingViewHolder(parent: ViewGroup, val imageManager: ImageManager) : Bas
R.layout.stats_loading_view
) {
private val list: RecyclerView = itemView.findViewById(R.id.stats_block_list)
- override fun bind(statsTypes: StatsStore.StatsTypes, items: List) {
- super.bind(statsTypes, items)
+ override fun bind(statsType: StatsStore.StatsType?, items: List) {
+ super.bind(statsType, items)
list.isNestedScrollingEnabled = false
if (list.adapter == null) {
list.layoutManager = LinearLayoutManager(list.context, LinearLayoutManager.VERTICAL, false)
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/utils/ItemPopupMenuHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/utils/ItemPopupMenuHandler.kt
new file mode 100644
index 000000000000..06d6d21295a1
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/utils/ItemPopupMenuHandler.kt
@@ -0,0 +1,81 @@
+package org.wordpress.android.ui.stats.refresh.utils
+
+import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.MutableLiveData
+import android.view.View
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import org.wordpress.android.R
+import org.wordpress.android.fluxc.store.StatsStore
+import org.wordpress.android.fluxc.store.StatsStore.InsightType
+import org.wordpress.android.fluxc.store.StatsStore.StatsType
+import org.wordpress.android.modules.BG_THREAD
+import org.wordpress.android.modules.UI_THREAD
+import org.wordpress.android.viewmodel.Event
+import javax.inject.Inject
+import javax.inject.Named
+import javax.inject.Singleton
+import android.support.v7.widget.ListPopupWindow
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter.InsightsMenuItem
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter.InsightsMenuItem.DOWN
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter.InsightsMenuItem.REMOVE
+import org.wordpress.android.ui.stats.refresh.lists.sections.insights.InsightsMenuAdapter.InsightsMenuItem.UP
+
+@Singleton
+class ItemPopupMenuHandler
+@Inject constructor(
+ @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher,
+ @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
+ private val statsStore: StatsStore,
+ private val statsSiteProvider: StatsSiteProvider
+) {
+ private val mutableTypeMoved = MutableLiveData>()
+ val typeMoved: LiveData> = mutableTypeMoved
+
+ fun onMenuClick(view: View, statsType: StatsType) {
+ GlobalScope.launch(bgDispatcher) {
+ val type = statsType as InsightType
+ val insights = statsStore.getAddedInsights(statsSiteProvider.siteModel)
+
+ val indexOfBlock = insights.indexOfFirst { it == type }
+ val showUpAction = indexOfBlock > 0
+ val showDownAction = indexOfBlock < insights.size - 1
+
+ withContext(mainDispatcher) {
+ val popup = ListPopupWindow(view.context)
+ val adapter = InsightsMenuAdapter(view.context, showUpAction, showDownAction)
+ popup.setAdapter(adapter)
+ popup.width = view.context.resources.getDimensionPixelSize(R.dimen.stats_insights_menu_item_width)
+ popup.anchorView = view
+ popup.isModal = true
+ popup.setOnItemClickListener { _, _, _, id ->
+ when (InsightsMenuItem.values()[id.toInt()]) {
+ UP -> {
+ GlobalScope.launch(bgDispatcher) {
+ statsStore.moveTypeUp(statsSiteProvider.siteModel, type)
+ mutableTypeMoved.postValue(Event(type))
+ }
+ }
+ DOWN -> {
+ GlobalScope.launch(bgDispatcher) {
+ statsStore.moveTypeDown(statsSiteProvider.siteModel, type)
+ mutableTypeMoved.postValue(Event(type))
+ }
+ }
+ REMOVE -> {
+ GlobalScope.launch(bgDispatcher) {
+ statsStore.removeType(statsSiteProvider.siteModel, type)
+ mutableTypeMoved.postValue(Event(type))
+ }
+ }
+ }
+ popup.dismiss()
+ }
+ popup.show()
+ }
+ }
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/utils/StatsNavigator.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/utils/StatsNavigator.kt
index 240181534bfb..1e8d80b4f23f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/utils/StatsNavigator.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/utils/StatsNavigator.kt
@@ -30,6 +30,7 @@ import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewClicks
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewCommentsStats
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewCountries
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewFollowersStats
+import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewInsightsManagement
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewMonthsAndYearsStats
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewPost
import org.wordpress.android.ui.stats.refresh.NavigationTarget.ViewPostDetailStats
@@ -130,6 +131,9 @@ class StatsNavigator
is ViewUrl -> {
WPWebViewActivity.openURL(activity, target.url)
}
+ is ViewInsightsManagement -> {
+ ActivityLauncher.viewInsightsManagement(activity)
+ }
}
}
}
diff --git a/WordPress/src/main/java/org/wordpress/android/util/LiveDataUtils.kt b/WordPress/src/main/java/org/wordpress/android/util/LiveDataUtils.kt
index 061e7f74ea4f..76156edf7ee1 100644
--- a/WordPress/src/main/java/org/wordpress/android/util/LiveDataUtils.kt
+++ b/WordPress/src/main/java/org/wordpress/android/util/LiveDataUtils.kt
@@ -203,8 +203,8 @@ fun LiveData.throttle(
): ThrottleLiveData {
val mediatorLiveData: ThrottleLiveData = ThrottleLiveData(coroutineScope = coroutineScope, offset = offset)
mediatorLiveData.addSource(this) {
- if (it != mediatorLiveData.value || !distinct) {
- mediatorLiveData.value = it
+ if ((it != mediatorLiveData.value || !distinct) && it != null) {
+ mediatorLiveData.postValue(it)
}
}
return mediatorLiveData
diff --git a/WordPress/src/main/res/drawable/ic_add_circle.xml b/WordPress/src/main/res/drawable/ic_add_circle.xml
new file mode 100644
index 000000000000..b6826feeb3e3
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_add_circle.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_arrow_down_grey_dark_24dp.xml b/WordPress/src/main/res/drawable/ic_arrow_down_grey_dark_24dp.xml
new file mode 100644
index 000000000000..11365e9c23b0
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_arrow_down_grey_dark_24dp.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_arrow_up_grey_dark_24dp.xml b/WordPress/src/main/res/drawable/ic_arrow_up_grey_dark_24dp.xml
new file mode 100644
index 000000000000..c1cdf781c6a7
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_arrow_up_grey_dark_24dp.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_ellipsis_vertical_grey_darken_48dp.xml b/WordPress/src/main/res/drawable/ic_ellipsis_vertical_grey_darken_48dp.xml
new file mode 100644
index 000000000000..047b3c616cc3
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_ellipsis_vertical_grey_darken_48dp.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_material_drag_handle_24dp.xml b/WordPress/src/main/res/drawable/ic_material_drag_handle_24dp.xml
new file mode 100644
index 000000000000..6d333d8042a9
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_material_drag_handle_24dp.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_minus_small_24dp.xml b/WordPress/src/main/res/drawable/ic_minus_small_24dp.xml
new file mode 100644
index 000000000000..0da31deb6983
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_minus_small_24dp.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_plus_small_24dp.xml b/WordPress/src/main/res/drawable/ic_plus_small_24dp.xml
new file mode 100644
index 000000000000..9c2634168399
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_plus_small_24dp.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_remove_circle.xml b/WordPress/src/main/res/drawable/ic_remove_circle.xml
new file mode 100644
index 000000000000..581a0cb7cac2
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_remove_circle.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/WordPress/src/main/res/drawable/ic_trash_grey_dark_24dp.xml b/WordPress/src/main/res/drawable/ic_trash_grey_dark_24dp.xml
new file mode 100644
index 000000000000..a7d5e8e7e921
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_trash_grey_dark_24dp.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout-w528dp/insights_management_fragment.xml b/WordPress/src/main/res/layout-w528dp/insights_management_fragment.xml
new file mode 100644
index 000000000000..fe773fc50a10
--- /dev/null
+++ b/WordPress/src/main/res/layout-w528dp/insights_management_fragment.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout/insights_management_activity.xml b/WordPress/src/main/res/layout/insights_management_activity.xml
new file mode 100644
index 000000000000..e44533e02dca
--- /dev/null
+++ b/WordPress/src/main/res/layout/insights_management_activity.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout/insights_management_fragment.xml b/WordPress/src/main/res/layout/insights_management_fragment.xml
new file mode 100644
index 000000000000..e75aa05bf766
--- /dev/null
+++ b/WordPress/src/main/res/layout/insights_management_fragment.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout/insights_management_list_item.xml b/WordPress/src/main/res/layout/insights_management_list_item.xml
new file mode 100644
index 000000000000..9b7da91766e9
--- /dev/null
+++ b/WordPress/src/main/res/layout/insights_management_list_item.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout/stats_block_four_columns_item.xml b/WordPress/src/main/res/layout/stats_block_four_columns_item.xml
index 10fa560668f3..804e1cae3fbb 100644
--- a/WordPress/src/main/res/layout/stats_block_four_columns_item.xml
+++ b/WordPress/src/main/res/layout/stats_block_four_columns_item.xml
@@ -4,7 +4,8 @@
android:id="@+id/column_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:baselineAligned="false">
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout/stats_block_title_item.xml b/WordPress/src/main/res/layout/stats_block_title_item.xml
index 072e9b7a9aec..39f5d1193f28 100644
--- a/WordPress/src/main/res/layout/stats_block_title_item.xml
+++ b/WordPress/src/main/res/layout/stats_block_title_item.xml
@@ -1,15 +1,28 @@
+
+
+
+
diff --git a/WordPress/src/main/res/layout/stats_date_selector.xml b/WordPress/src/main/res/layout/stats_date_selector.xml
index fe8daf5bdbb5..1a62d9bca772 100644
--- a/WordPress/src/main/res/layout/stats_date_selector.xml
+++ b/WordPress/src/main/res/layout/stats_date_selector.xml
@@ -7,7 +7,7 @@
android:background="@android:color/white">
diff --git a/WordPress/src/main/res/layout/stats_error_view.xml b/WordPress/src/main/res/layout/stats_error_view.xml
index c789a623c1d0..a87dc3fd881b 100644
--- a/WordPress/src/main/res/layout/stats_error_view.xml
+++ b/WordPress/src/main/res/layout/stats_error_view.xml
@@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/actionable_error_view"
+ android:id="@+id/statsErrorView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
diff --git a/WordPress/src/main/res/layout/stats_insights_popup_menu_item.xml b/WordPress/src/main/res/layout/stats_insights_popup_menu_item.xml
new file mode 100644
index 000000000000..1b589cd3d7e5
--- /dev/null
+++ b/WordPress/src/main/res/layout/stats_insights_popup_menu_item.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout/stats_list_fragment.xml b/WordPress/src/main/res/layout/stats_list_fragment.xml
index a6c6c4e3db2c..2981a45bd21b 100644
--- a/WordPress/src/main/res/layout/stats_list_fragment.xml
+++ b/WordPress/src/main/res/layout/stats_list_fragment.xml
@@ -17,10 +17,7 @@
android:layout_weight="1"/>
+ layout="@layout/stats_empty_view" />
@@ -39,6 +37,7 @@
android:id="@+id/recyclerView"
style="@style/StatsList"
android:clipToPadding="false"
+ android:descendantFocusability="beforeDescendants"
android:scrollbars="vertical"/>
diff --git a/WordPress/src/main/res/menu/menu_insights_management.xml b/WordPress/src/main/res/menu/menu_insights_management.xml
new file mode 100644
index 000000000000..a58b0dce68e9
--- /dev/null
+++ b/WordPress/src/main/res/menu/menu_insights_management.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/WordPress/src/main/res/values-ar/strings.xml b/WordPress/src/main/res/values-ar/strings.xml
index 13486536db00..da74846a626e 100644
--- a/WordPress/src/main/res/values-ar/strings.xml
+++ b/WordPress/src/main/res/values-ar/strings.xml
@@ -221,7 +221,7 @@ Language: ar
إجمالي %1$s من المتابعين: %2$s
البريد الإلكتروني
ووردبريس.كوم
- إدارة الرؤى
+ إدارة الرؤى
تخصيص الرؤى الخاصة بك والحصول على معلومات حول أداء موقعك
لم تتم إضافة رى حتى الآن
لا توجد بيانات حتى الآن
diff --git a/WordPress/src/main/res/values-de/strings.xml b/WordPress/src/main/res/values-de/strings.xml
index c8b5e3dfbf6e..5789dbb5a947 100644
--- a/WordPress/src/main/res/values-de/strings.xml
+++ b/WordPress/src/main/res/values-de/strings.xml
@@ -221,7 +221,7 @@ Language: de
%1$s-Follower insgesamt: %2$s
E-Mail
WordPress.com
- Einsichten verwalten
+ Einsichten verwalten
Passe deine Einsichten an und erhalte Details zur Leistung deiner Website
Noch keine Einsichten hinzugefügt
Noch keine Daten
diff --git a/WordPress/src/main/res/values-en-rAU/strings.xml b/WordPress/src/main/res/values-en-rAU/strings.xml
index f5a57dd2fb96..399e4dfb0e2b 100644
--- a/WordPress/src/main/res/values-en-rAU/strings.xml
+++ b/WordPress/src/main/res/values-en-rAU/strings.xml
@@ -221,7 +221,7 @@ Language: en_AU
Total %1$s Followers: %2$s
Email
WordPress.com
- Manage insights
+ Manage insights
Customise your insights and get the low-down on your site’s performance
No insights added yet
No data yet
diff --git a/WordPress/src/main/res/values-en-rCA/strings.xml b/WordPress/src/main/res/values-en-rCA/strings.xml
index 6c331e2fb284..21e5611f41c5 100644
--- a/WordPress/src/main/res/values-en-rCA/strings.xml
+++ b/WordPress/src/main/res/values-en-rCA/strings.xml
@@ -221,7 +221,7 @@ Language: en_CA
Total %1$s Followers: %2$s
Email
WordPress.com
- Manage insights
+ Manage insights
Customize your insights and get the low-down on your site’s performance
No insights added yet
No data yet
diff --git a/WordPress/src/main/res/values-en-rGB/strings.xml b/WordPress/src/main/res/values-en-rGB/strings.xml
index 4643b487ec04..c658bea430be 100644
--- a/WordPress/src/main/res/values-en-rGB/strings.xml
+++ b/WordPress/src/main/res/values-en-rGB/strings.xml
@@ -200,7 +200,7 @@ Language: en_GB
Total %1$s Followers: %2$s
E-mail
WordPress.com
- Manage insights
+ Manage insights
Customise your insights and get the low-down on your site’s performance
No insights added yet
No data yet
diff --git a/WordPress/src/main/res/values-es-rCL/strings.xml b/WordPress/src/main/res/values-es-rCL/strings.xml
index 86995f084ec9..78cc4773cc74 100644
--- a/WordPress/src/main/res/values-es-rCL/strings.xml
+++ b/WordPress/src/main/res/values-es-rCL/strings.xml
@@ -60,7 +60,7 @@ Language: es_CL
Total %1$s Seguidores: %2$s
Email
WordPress.com
- Administrar estadísticas
+ Administrar estadísticas
Aún no se ha añadido estadisticas
Aún no hay datos
Menú Depuración
diff --git a/WordPress/src/main/res/values-es/strings.xml b/WordPress/src/main/res/values-es/strings.xml
index 68d214d25f8b..f67d4d51007e 100644
--- a/WordPress/src/main/res/values-es/strings.xml
+++ b/WordPress/src/main/res/values-es/strings.xml
@@ -221,7 +221,7 @@ Language: es
Total %1$s seguidores: %2$s
Correo electrónico
WordPress.com
- Gestionar impresiones
+ Gestionar impresiones
Personaliza tus informes y profundiza en el rendimiento de tu sitio
Aún no se han añadido impresiones
Aún no hay datos
diff --git a/WordPress/src/main/res/values-fr/strings.xml b/WordPress/src/main/res/values-fr/strings.xml
index a7dffe5047b0..3ca0b44abb5c 100644
--- a/WordPress/src/main/res/values-fr/strings.xml
+++ b/WordPress/src/main/res/values-fr/strings.xml
@@ -221,7 +221,7 @@ Language: fr
Total des abonnés %1$s : %2$s
E-mail
WordPress.com
- Gérer les tendances
+ Gérer les tendances
Personnalisez vos tendances et obtenez les dernières informations sur les performances de votre site
Aucune tendance n’a encore été ajoutée
Aucune donnée pour le moment.
diff --git a/WordPress/src/main/res/values-he/strings.xml b/WordPress/src/main/res/values-he/strings.xml
index a79491f40567..1c2d0ba02e29 100644
--- a/WordPress/src/main/res/values-he/strings.xml
+++ b/WordPress/src/main/res/values-he/strings.xml
@@ -217,7 +217,7 @@ Language: he_IL
סך הכול %1$s עוקבים: %2$s
אימייל
WordPress.com
- ניהול תובנות
+ ניהול תובנות
עדיין לא נוספו תובנות
עדיין אין נתונים
תפריט איתור באגים
diff --git a/WordPress/src/main/res/values-id/strings.xml b/WordPress/src/main/res/values-id/strings.xml
index 3b1217c8c344..756f2c2af89e 100644
--- a/WordPress/src/main/res/values-id/strings.xml
+++ b/WordPress/src/main/res/values-id/strings.xml
@@ -217,7 +217,7 @@ Language: id
Total %1$s Pengikut: %2$s
Email
WordPress.com
- Kelola informasi
+ Kelola informasi
Belum ada informasi yang ditambahkan
Belum ada data
Menu Debug
diff --git a/WordPress/src/main/res/values-it/strings.xml b/WordPress/src/main/res/values-it/strings.xml
index b9e9320bb6cc..174b093af19b 100644
--- a/WordPress/src/main/res/values-it/strings.xml
+++ b/WordPress/src/main/res/values-it/strings.xml
@@ -201,7 +201,7 @@ Language: it
Totale follower da %1$s: %2$s
Email
WordPress.com
- Gestisci insight
+ Gestisci insight
Nessun insight aggiunto
Nessun dato
Menu di debug
diff --git a/WordPress/src/main/res/values-ja/strings.xml b/WordPress/src/main/res/values-ja/strings.xml
index 4b2f8ce72fee..377a85ade72a 100644
--- a/WordPress/src/main/res/values-ja/strings.xml
+++ b/WordPress/src/main/res/values-ja/strings.xml
@@ -220,7 +220,7 @@ Language: ja_JP
Total %1$s Followers:%2$s
メール
WordPress.com
- インサイトを管理
+ インサイトを管理
インサイトをカスタマイズして、サイトのパフォーマンスを把握しましょう
インサイトは追加されていません
データはまだありません
diff --git a/WordPress/src/main/res/values-ko/strings.xml b/WordPress/src/main/res/values-ko/strings.xml
index 5d60c9bbd20f..72350b7655ca 100644
--- a/WordPress/src/main/res/values-ko/strings.xml
+++ b/WordPress/src/main/res/values-ko/strings.xml
@@ -213,7 +213,7 @@ Language: ko_KR
총 %1$s 팔로워 수: %2$s
이메일
워드프레스닷컴
- 인사이트 관리
+ 인사이트 관리
아직 추가된 인사이트가 없음
아직 데이터 없음
디버그 메뉴
diff --git a/WordPress/src/main/res/values-nb/strings.xml b/WordPress/src/main/res/values-nb/strings.xml
index 333d8bf97378..1506d56ecc66 100644
--- a/WordPress/src/main/res/values-nb/strings.xml
+++ b/WordPress/src/main/res/values-nb/strings.xml
@@ -200,7 +200,7 @@ Language: nb_NO
Totalt %1$s følgere: %2$s
E-post
WordPress.com
- Behandle innsikter
+ Behandle innsikter
Tilpass dine innsikter og få den viktigste informasjonen om ytelsen til nettstedet ditt
Ingen innsikter lagt til ennå
Ingen data ennå
diff --git a/WordPress/src/main/res/values-pl/strings.xml b/WordPress/src/main/res/values-pl/strings.xml
index 0d48e3aadb5c..d50390b0498e 100644
--- a/WordPress/src/main/res/values-pl/strings.xml
+++ b/WordPress/src/main/res/values-pl/strings.xml
@@ -216,7 +216,7 @@ Language: pl
Całkowita liczba obserwujących %1$s: %2$s
Email
WordPress.com
- Zarządzaj trendami
+ Zarządzaj trendami
Spersonalizuj kartę Trendy i uzyskaj pełną informację o wynikach swojej witryny
Brak trendów, jak dotąd
Brak danych, jak dotąd
diff --git a/WordPress/src/main/res/values-pt-rBR/strings.xml b/WordPress/src/main/res/values-pt-rBR/strings.xml
index f4023f79d60e..0ec5cf7c35b0 100644
--- a/WordPress/src/main/res/values-pt-rBR/strings.xml
+++ b/WordPress/src/main/res/values-pt-rBR/strings.xml
@@ -221,7 +221,7 @@ Language: pt_BR
Total de seguidores por %1$s: %2$s
E-mail
WordPress.com
- Gerenciar informações
+ Gerenciar informações
Personalize as informações de seu site para saber mais sobre seu desempenho
Nenhuma informação adicionada ainda
Nenhum dado ainda
diff --git a/WordPress/src/main/res/values-ro/strings.xml b/WordPress/src/main/res/values-ro/strings.xml
index 7027b1d4292e..26c999fa0951 100644
--- a/WordPress/src/main/res/values-ro/strings.xml
+++ b/WordPress/src/main/res/values-ro/strings.xml
@@ -221,7 +221,7 @@ Language: ro
Total urmăritori %1$s: %2$s
Prin email
WordPress.com
- Administrează perspectivele
+ Administrează perspectivele
Personalizează-ți perspectivele și primești informații relevante despre performanța sitului
Nu ai adăugat perspective până acum
Încă nu există date
diff --git a/WordPress/src/main/res/values-ru/strings.xml b/WordPress/src/main/res/values-ru/strings.xml
index d13beaa8fd30..7c466832d444 100644
--- a/WordPress/src/main/res/values-ru/strings.xml
+++ b/WordPress/src/main/res/values-ru/strings.xml
@@ -221,7 +221,7 @@ Language: ru
Всего %1$s Подписчики: %2$s
Email
WordPress.com
- Настроить статистику
+ Настроить статистику
Настройте вашу статистику и узнайте важное то, чем живет ваш сайт.
Еще нет статистики
Пока нет данных
diff --git a/WordPress/src/main/res/values-sq/strings.xml b/WordPress/src/main/res/values-sq/strings.xml
index 958a556815bb..9eece35f8917 100644
--- a/WordPress/src/main/res/values-sq/strings.xml
+++ b/WordPress/src/main/res/values-sq/strings.xml
@@ -221,7 +221,7 @@ Language: sq_AL
%1$s Ndjekës Gjithsej: %2$s
Email
WordPress.com
- Administroni tendenca
+ Administroni tendenca
Përshtatni tendencat tuaj dhe merrni faktet mbi funksionimin e sajtit tuaj
S’janë shtuar ende tendenca
Ende pa të dhëna
diff --git a/WordPress/src/main/res/values-sv/strings.xml b/WordPress/src/main/res/values-sv/strings.xml
index e94dd389dfab..f81f06828df8 100644
--- a/WordPress/src/main/res/values-sv/strings.xml
+++ b/WordPress/src/main/res/values-sv/strings.xml
@@ -221,7 +221,7 @@ Language: sv_SE
Totalt antal följare för ”%1$s”: %2$s
E-post
WordPress.com
- Hantera insikter
+ Hantera insikter
Anpassa dina insikter och se detaljerna om hur din webbplats presterar
Inga insikter har lagts till än
Inga data insamlade än
diff --git a/WordPress/src/main/res/values-tr/strings.xml b/WordPress/src/main/res/values-tr/strings.xml
index 9c45aa284dcc..f6e18461e4a8 100644
--- a/WordPress/src/main/res/values-tr/strings.xml
+++ b/WordPress/src/main/res/values-tr/strings.xml
@@ -221,7 +221,7 @@ Language: tr
Toplam %1$s takipçisi: %2$s
E-posta
WordPress.com
- İçgörüleri yönet
+ İçgörüleri yönet
Analizlerinizi özelleştirin ve sitenizin performansındaki düşüş hakkında bilgi edinin
Henüz içgörü eklenmedi
Henüz veri yok
diff --git a/WordPress/src/main/res/values-w528dp/stats_styles.xml b/WordPress/src/main/res/values-w528dp/stats_styles.xml
index 711082a1ae55..0de4a22b9943 100644
--- a/WordPress/src/main/res/values-w528dp/stats_styles.xml
+++ b/WordPress/src/main/res/values-w528dp/stats_styles.xml
@@ -6,4 +6,10 @@
- 1
- center_horizontal
+
+
diff --git a/WordPress/src/main/res/values-w720dp/stats_styles.xml b/WordPress/src/main/res/values-w720dp/stats_styles.xml
index efb9b785aef1..78df3fc4485e 100644
--- a/WordPress/src/main/res/values-w720dp/stats_styles.xml
+++ b/WordPress/src/main/res/values-w720dp/stats_styles.xml
@@ -6,4 +6,10 @@
- 1
- center_horizontal
+
+
diff --git a/WordPress/src/main/res/values-zh-rCN/strings.xml b/WordPress/src/main/res/values-zh-rCN/strings.xml
index 4462c0a26fc4..579771faa06a 100644
--- a/WordPress/src/main/res/values-zh-rCN/strings.xml
+++ b/WordPress/src/main/res/values-zh-rCN/strings.xml
@@ -169,7 +169,7 @@ Language: zh_CN
共 %1$s 位粉丝:%2$s
电子邮件
WordPress.com
- 管理见解
+ 管理见解
尚未添加任何见解
尚无数据
正在更改密码…
diff --git a/WordPress/src/main/res/values-zh-rHK/strings.xml b/WordPress/src/main/res/values-zh-rHK/strings.xml
index 3ebbe7c59089..4854a78ecfc3 100644
--- a/WordPress/src/main/res/values-zh-rHK/strings.xml
+++ b/WordPress/src/main/res/values-zh-rHK/strings.xml
@@ -175,7 +175,7 @@ Language: zh_TW
%1$s 關注者總數:%2$s
電子郵件
WordPress.com
- 管理洞察報告
+ 管理洞察報告
尚未新增任何洞察報告
尚無資料
除錯選單
diff --git a/WordPress/src/main/res/values-zh-rTW/strings.xml b/WordPress/src/main/res/values-zh-rTW/strings.xml
index 3ebbe7c59089..4854a78ecfc3 100644
--- a/WordPress/src/main/res/values-zh-rTW/strings.xml
+++ b/WordPress/src/main/res/values-zh-rTW/strings.xml
@@ -175,7 +175,7 @@ Language: zh_TW
%1$s 關注者總數:%2$s
電子郵件
WordPress.com
- 管理洞察報告
+ 管理洞察報告
尚未新增任何洞察報告
尚無資料
除錯選單
diff --git a/WordPress/src/main/res/values/dimens.xml b/WordPress/src/main/res/values/dimens.xml
index 4bb808794f24..062f427a7b0f 100644
--- a/WordPress/src/main/res/values/dimens.xml
+++ b/WordPress/src/main/res/values/dimens.xml
@@ -236,7 +236,7 @@
7dp
15dp
- 48sp
+ 48dp
256sp
16dp
24dp
@@ -410,6 +410,9 @@
8dp
56dp
1dp
+ 24dp
+ 231dp
+ 52dp
24dp
diff --git a/WordPress/src/main/res/values/stats_styles.xml b/WordPress/src/main/res/values/stats_styles.xml
index 021dbb27e5a9..76e0c8ba8acb 100644
--- a/WordPress/src/main/res/values/stats_styles.xml
+++ b/WordPress/src/main/res/values/stats_styles.xml
@@ -200,6 +200,11 @@
- 1
+
+