Skip to content

Commit

Permalink
Merge pull request #10267 from wordpress-mobile/issue/9639-refactoring
Browse files Browse the repository at this point in the history
Move photon url logic from VH to VM
  • Loading branch information
mzorz authored Jul 22, 2019
2 parents 6f11da4 + 404ee70 commit 8b3f6a2
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import org.wordpress.android.ui.utils.UiHelpers
import org.wordpress.android.ui.utils.UiString
import org.wordpress.android.util.DisplayUtils
import org.wordpress.android.util.NetworkUtils
import org.wordpress.android.util.SiteUtils
import org.wordpress.android.util.ToastUtils
import org.wordpress.android.util.WPSwipeToRefreshHelper.buildSwipeToRefreshHelper
import org.wordpress.android.util.helpers.SwipeToRefreshHelper
Expand Down Expand Up @@ -63,23 +62,11 @@ class PostListFragment : Fragment() {
private lateinit var postListType: PostListType

private lateinit var nonNullActivity: FragmentActivity
private lateinit var site: SiteModel

private val postViewHolderConfig: PostViewHolderConfig by lazy {
val displayWidth = DisplayUtils.getDisplayPixelWidth(context)
val contentSpacing = nonNullActivity.resources.getDimensionPixelSize(R.dimen.content_margin)
PostViewHolderConfig(
photonWidth = displayWidth - contentSpacing * 2,
photonHeight = nonNullActivity.resources.getDimensionPixelSize(R.dimen.reader_featured_image_height),
isPhotonCapable = SiteUtils.isPhotonCapable(site),
imageManager = imageManager
)
}

private val postListAdapter: PostListAdapter by lazy {
PostListAdapter(
context = nonNullActivity,
postViewHolderConfig = postViewHolderConfig,
imageManager = imageManager,
uiHelpers = uiHelpers
)
}
Expand All @@ -89,18 +76,12 @@ class PostListFragment : Fragment() {
nonNullActivity = checkNotNull(activity)
(nonNullActivity.application as WordPress).component().inject(this)

val site: SiteModel? = if (savedInstanceState == null) {
val nonNullIntent = checkNotNull(nonNullActivity.intent)
nonNullIntent.getSerializableExtra(WordPress.SITE) as SiteModel?
} else {
savedInstanceState.getSerializable(WordPress.SITE) as SiteModel?
}
val nonNullIntent = checkNotNull(nonNullActivity.intent)
val site: SiteModel? = nonNullIntent.getSerializableExtra(WordPress.SITE) as SiteModel?

if (site == null) {
ToastUtils.showToast(nonNullActivity, R.string.blog_not_found, ToastUtils.Duration.SHORT)
nonNullActivity.finish()
} else {
this.site = site
}
}

Expand Down Expand Up @@ -136,7 +117,13 @@ class PostListFragment : Fragment() {
val postListViewModelConnector = mainViewModel.getPostListViewModelConnector(authorFilter, postListType)

viewModel = ViewModelProviders.of(this, viewModelFactory).get<PostListViewModel>(PostListViewModel::class.java)
viewModel.start(postListViewModelConnector)

val displayWidth = DisplayUtils.getDisplayPixelWidth(context)
val contentSpacing = nonNullActivity.resources.getDimensionPixelSize(R.dimen.content_margin)
viewModel.start(
postListViewModelConnector, photonWidth = displayWidth - contentSpacing * 2,
photonHeight = nonNullActivity.resources.getDimensionPixelSize(R.dimen.reader_featured_image_height)
)

initObservers()
}
Expand Down Expand Up @@ -173,11 +160,6 @@ class PostListFragment : Fragment() {
})
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putSerializable(WordPress.SITE, site)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.post_list_fragment, container, false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import androidx.annotation.LayoutRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import org.wordpress.android.R
import org.wordpress.android.ui.reader.utils.ReaderUtils
import org.wordpress.android.ui.utils.UiHelpers
import org.wordpress.android.ui.utils.UiString
import org.wordpress.android.util.image.ImageManager
import org.wordpress.android.util.image.ImageType
import org.wordpress.android.viewmodel.posts.PostListItemAction
import org.wordpress.android.viewmodel.posts.PostListItemAction.MoreItem
Expand All @@ -33,7 +33,7 @@ import org.wordpress.android.widgets.WPTextView
sealed class PostListItemViewHolder(
@LayoutRes layout: Int,
parent: ViewGroup,
private val config: PostViewHolderConfig,
private val imageManager: ImageManager,
private val uiHelpers: UiHelpers
) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(layout, parent, false)) {
private val featuredImageView: ImageView = itemView.findViewById(R.id.image_featured)
Expand All @@ -52,9 +52,9 @@ sealed class PostListItemViewHolder(

class Standard(
parent: ViewGroup,
config: PostViewHolderConfig,
imageManager: ImageManager,
private val uiHelpers: UiHelpers
) : PostListItemViewHolder(R.layout.post_list_item, parent, config, uiHelpers) {
) : PostListItemViewHolder(R.layout.post_list_item, parent, imageManager, uiHelpers) {
private val excerptTextView: WPTextView = itemView.findViewById(R.id.excerpt)
private val actionButtons: List<PostListButton> = listOf(
itemView.findViewById(R.id.btn_primary),
Expand Down Expand Up @@ -95,9 +95,9 @@ sealed class PostListItemViewHolder(

class Compact(
parent: ViewGroup,
config: PostViewHolderConfig,
imageManager: ImageManager,
private val uiHelpers: UiHelpers
) : PostListItemViewHolder(R.layout.post_list_item_compact, parent, config, uiHelpers) {
) : PostListItemViewHolder(R.layout.post_list_item_compact, parent, imageManager, uiHelpers) {
private val moreButton: ImageButton = itemView.findViewById(R.id.more_button)

override fun onBind(item: PostListItemUiState) {
Expand Down Expand Up @@ -170,15 +170,12 @@ sealed class PostListItemViewHolder(
// Suppress blinking as the media upload progresses
return
}
if (imageUrl == null) {
if (imageUrl.isNullOrBlank()) {
featuredImageView.visibility = View.GONE
config.imageManager.cancelRequestAndClearImageView(featuredImageView)
imageManager.cancelRequestAndClearImageView(featuredImageView)
} else {
val photonUrl = ReaderUtils.getResizedImageUrl(
imageUrl, config.photonWidth, config.photonHeight, !config.isPhotonCapable
)
featuredImageView.visibility = View.VISIBLE
config.imageManager.load(featuredImageView, ImageType.PHOTO, photonUrl, ScaleType.CENTER_CROP)
imageManager.load(featuredImageView, ImageType.PHOTO, imageUrl, ScaleType.CENTER_CROP)
}
loadedFeaturedImgUrl = imageUrl
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import org.wordpress.android.ui.posts.PostListItemViewHolder
import org.wordpress.android.ui.posts.PostListViewLayoutType
import org.wordpress.android.ui.posts.PostListViewLayoutType.COMPACT
import org.wordpress.android.ui.posts.PostListViewLayoutType.STANDARD
import org.wordpress.android.ui.posts.PostViewHolderConfig
import org.wordpress.android.ui.utils.UiHelpers
import org.wordpress.android.util.image.ImageManager
import org.wordpress.android.viewmodel.posts.PostListItemProgressBar
import org.wordpress.android.viewmodel.posts.PostListItemType
import org.wordpress.android.viewmodel.posts.PostListItemType.EndListIndicatorItem
Expand All @@ -30,7 +30,7 @@ private const val VIEW_TYPE_LOADING_COMPACT = 4

class PostListAdapter(
context: Context,
private val postViewHolderConfig: PostViewHolderConfig,
private val imageManager: ImageManager,
private val uiHelpers: UiHelpers
) : PagedListAdapter<PostListItemType, ViewHolder>(PostListDiffItemCallback) {
private val layoutInflater: LayoutInflater = LayoutInflater.from(context)
Expand Down Expand Up @@ -69,10 +69,10 @@ class PostListAdapter(
LoadingViewHolder(view)
}
VIEW_TYPE_POST -> {
PostListItemViewHolder.Standard(parent, postViewHolderConfig, uiHelpers)
PostListItemViewHolder.Standard(parent, imageManager, uiHelpers)
}
VIEW_TYPE_POST_COMPACT -> {
PostListItemViewHolder.Compact(parent, postViewHolderConfig, uiHelpers)
PostListItemViewHolder.Compact(parent, imageManager, uiHelpers)
}
else -> {
// Fail fast if a new view type is added so the we can handle it
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.wordpress.android.ui.reader.utils

import dagger.Reusable
import javax.inject.Inject

/**
* Injectable wrapper around ReaderUtils.
*
* ReaderUtils interface is consisted of static methods, which make the client code difficult to test/mock. Main purpose of
* this wrapper is to make testing easier.
*
*/
@Reusable
class ReaderUtilsWrapper @Inject constructor() {
fun getResizedImageUrl(imageUrl: String?, width: Int, height: Int, isPrivate: Boolean): String? =
ReaderUtils.getResizedImageUrl(imageUrl, width, height, isPrivate)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import org.wordpress.android.ui.posts.AuthorFilterSelection.ME
import org.wordpress.android.ui.posts.PostListType.SEARCH
import org.wordpress.android.ui.posts.PostUtils
import org.wordpress.android.ui.posts.trackPostListAction
import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper
import org.wordpress.android.ui.uploads.UploadStarter
import org.wordpress.android.util.AppLog
import org.wordpress.android.util.NetworkUtilsWrapper
Expand All @@ -47,6 +48,7 @@ import org.wordpress.android.viewmodel.posts.PostListItemIdentifier.LocalPostId
import org.wordpress.android.viewmodel.posts.PostListItemType.PostListItemUiState
import javax.inject.Inject
import javax.inject.Named
import kotlin.properties.Delegates

typealias PagedPostList = PagedList<PostListItemType>

Expand All @@ -63,6 +65,7 @@ class PostListViewModel @Inject constructor(
private val listItemUiStateHelper: PostListItemUiStateHelper,
private val networkUtilsWrapper: NetworkUtilsWrapper,
private val uploadStarter: UploadStarter,
private val readerUtilsWrapper: ReaderUtilsWrapper,
@Named(UI_THREAD) private val uiDispatcher: CoroutineDispatcher,
@Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher,
connectionStatus: LiveData<ConnectionStatus>
Expand All @@ -73,6 +76,9 @@ class PostListViewModel @Inject constructor(
private var isStarted: Boolean = false
private lateinit var connector: PostListViewModelConnector

private var photonWidth by Delegates.notNull<Int>()
private var photonHeight by Delegates.notNull<Int>()

private var scrollToLocalPostId: LocalPostId? = null

private val _scrollToPosition = SingleLiveEvent<Int>()
Expand Down Expand Up @@ -113,10 +119,16 @@ class PostListViewModel @Inject constructor(
private val lifecycleRegistry = LifecycleRegistry(this)
override fun getLifecycle(): Lifecycle = lifecycleRegistry

fun start(postListViewModelConnector: PostListViewModelConnector) {
fun start(
postListViewModelConnector: PostListViewModelConnector,
photonWidth: Int,
photonHeight: Int
) {
if (isStarted) {
return
}
this.photonHeight = photonHeight
this.photonWidth = photonWidth
connector = postListViewModelConnector

if (connector.postListType != SEARCH) {
Expand Down Expand Up @@ -337,7 +349,8 @@ class PostListViewModel @Inject constructor(
unhandledConflicts = connector.doesPostHaveUnhandledConflict(post),
capabilitiesToPublish = connector.site.hasCapabilityPublishPosts,
statsSupported = isStatsSupported,
featuredImageUrl = connector.getFeaturedImageUrl(post.featuredImageId),
featuredImageUrl =
convertToPhotonUrlIfPossible(connector.getFeaturedImageUrl(post.featuredImageId)),
formattedDate = PostUtils.getFormattedDate(post),
performingCriticalAction = connector.postActionHandler.isPerformingCriticalAction(LocalId(post.id)),
onAction = { postModel, buttonType, statEvent ->
Expand All @@ -354,4 +367,12 @@ class PostListViewModel @Inject constructor(
fetchFirstPage()
}
}

private fun convertToPhotonUrlIfPossible(featuredImageUrl: String?): String? =
readerUtilsWrapper.getResizedImageUrl(
featuredImageUrl,
photonWidth,
photonHeight,
!SiteUtils.isPhotonCapable(connector.site)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.wordpress.android.ui.posts.PostListType.DRAFTS
import org.wordpress.android.ui.posts.PostListType.SEARCH
import org.wordpress.android.ui.uploads.UploadStarter

private const val DEFAULT_PHOTON_DIMENSIONS = -9
class PostListViewModelTest : BaseUnitTest() {
@Mock private lateinit var site: SiteModel
@Mock private lateinit var uploadStarter: UploadStarter
Expand All @@ -34,33 +35,16 @@ class PostListViewModelTest : BaseUnitTest() {
val listStore = mock<ListStore>()
val postList = mock<PagedListWrapper<PostListItemType>>()

whenever(
postList.listError
).thenReturn(mock())

whenever(
postList.isFetchingFirstPage
).thenReturn(mock())

whenever(
postList.isEmpty
).thenReturn(mock())

whenever(
postList.data
).thenReturn(mock())

whenever(
postList.isLoadingMore
).thenReturn(mock())

whenever(
listStore.getList<PostListDescriptorForXmlRpcSite, PostListItemIdentifier, PostListItemType>(
whenever(postList.listError).thenReturn(mock())
whenever(postList.isFetchingFirstPage).thenReturn(mock())
whenever(postList.isEmpty).thenReturn(mock())
whenever(postList.data).thenReturn(mock())
whenever(postList.isLoadingMore).thenReturn(mock())
whenever(listStore.getList<PostListDescriptorForXmlRpcSite, PostListItemIdentifier, PostListItemType>(
any(),
any(),
any()
)
).thenReturn(postList)
)).thenReturn(postList)

viewModel = PostListViewModel(
dispatcher = mock(),
Expand All @@ -70,6 +54,7 @@ class PostListViewModelTest : BaseUnitTest() {
listItemUiStateHelper = mock(),
networkUtilsWrapper = mock(),
uploadStarter = uploadStarter,
readerUtilsWrapper = mock(),
connectionStatus = mock(),
uiDispatcher = TEST_DISPATCHER,
bgDispatcher = TEST_DISPATCHER
Expand All @@ -78,7 +63,11 @@ class PostListViewModelTest : BaseUnitTest() {

@Test
fun `when swiping to refresh, it uploads all local drafts`() {
viewModel.start(createPostListViewModelConnector(site = site, postListType = DRAFTS))
viewModel.start(
createPostListViewModelConnector(site = site, postListType = DRAFTS),
DEFAULT_PHOTON_DIMENSIONS,
DEFAULT_PHOTON_DIMENSIONS
)

// When
viewModel.swipeToRefresh()
Expand All @@ -89,7 +78,11 @@ class PostListViewModelTest : BaseUnitTest() {

@Test
fun `empty search query should show search prompt`() {
viewModel.start(createPostListViewModelConnector(site = site, postListType = SEARCH))
viewModel.start(
createPostListViewModelConnector(site = site, postListType = SEARCH),
DEFAULT_PHOTON_DIMENSIONS,
DEFAULT_PHOTON_DIMENSIONS
)

val emptyViewStateResults = mutableListOf<PostListEmptyUiState>()

Expand Down

0 comments on commit 8b3f6a2

Please sign in to comment.