diff --git a/app/lint.xml b/app/lint.xml
index 7b2c2b0..55028d1 100644
--- a/app/lint.xml
+++ b/app/lint.xml
@@ -20,6 +20,8 @@
+
+
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 4c00cb7..76c8835 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -29,3 +29,5 @@
-dontwarn android.test.**
-dontwarn kotlin.jvm.internal.Reflection
-dontwarn com.google.errorprone.annotations.*
+-dontwarn com.squareup.okhttp.**
+
diff --git a/app/src/androidTest/kotlin/app/AndroidTestApplication.kt b/app/src/androidTest/kotlin/app/AndroidTestApplication.kt
index 5b23c9b..9cf6d01 100644
--- a/app/src/androidTest/kotlin/app/AndroidTestApplication.kt
+++ b/app/src/androidTest/kotlin/app/AndroidTestApplication.kt
@@ -16,10 +16,11 @@ internal open class AndroidTestApplication : MainApplication() {
* @see app.gaming.TopGamingAllTimePostsActivity
*/
override fun buildTopGamingAllTimePostsFeatureComponent(
- contentView: RecyclerView, errorView: View, progressView: View, activity: Activity) =
+ contentView: RecyclerView, errorView: View, progressView: View, guideView: View,
+ activity: Activity) =
DaggerTopGamingAllTimePostsFeatureInstrumentationComponent.builder()
.topGamingAllTimePostsFeatureInstrumentationModule(
TopGamingAllTimePostsFeatureInstrumentationModule(
- contentView, errorView, progressView, activity))
+ contentView, errorView, progressView, guideView, activity))
.build()
}
diff --git a/app/src/androidTest/kotlin/app/gaming/TopGamingActivityInstrumentation.kt b/app/src/androidTest/kotlin/app/gaming/TopGamingActivityInstrumentation.kt
index 0ead4b6..d38cdcd 100644
--- a/app/src/androidTest/kotlin/app/gaming/TopGamingActivityInstrumentation.kt
+++ b/app/src/androidTest/kotlin/app/gaming/TopGamingActivityInstrumentation.kt
@@ -95,7 +95,7 @@ internal class TopGamingActivityInstrumentation {
@Test
fun onLoadItemsAreShown() {
SUBJECT = ReplaySubject.create()
- SUBJECT.onNext(Post("0", "Bananas title", "r/bananas", 879, "bananaLink"))
+ SUBJECT.onNext(Post("0", "Bananas title", "r/bananas", 879, "bananaLink", "tb"))
SUBJECT.onCompleted()
launchActivity()
onView(withId(R.id.progress)).check { view, _ ->
@@ -123,7 +123,7 @@ internal class TopGamingActivityInstrumentation {
@Test
fun onItemClickIntentIsFired() {
SUBJECT = ReplaySubject.create()
- SUBJECT.onNext(Post("0", "Bananas title", "r/bananas", 879, "http://www.banan.as"))
+ SUBJECT.onNext(Post("0", "Bananas title", "r/bananas", 879, "http://www.banan.as", "tb"))
SUBJECT.onCompleted()
launchActivity()
Intents.init()
diff --git a/app/src/androidTest/kotlin/app/gaming/TopGamingPostsFeatureInstrumentationModule.kt b/app/src/androidTest/kotlin/app/gaming/TopGamingPostsFeatureInstrumentationModule.kt
index 621e2fa..2b7a46c 100644
--- a/app/src/androidTest/kotlin/app/gaming/TopGamingPostsFeatureInstrumentationModule.kt
+++ b/app/src/androidTest/kotlin/app/gaming/TopGamingPostsFeatureInstrumentationModule.kt
@@ -27,6 +27,7 @@ internal class TopGamingAllTimePostsFeatureInstrumentationModule(
private val contentView: RecyclerView,
private val errorView: View,
private val progressView: View,
+ private val guideView: View,
private val activity: Activity) {
@Provides
@Singleton
@@ -84,7 +85,7 @@ internal class TopGamingAllTimePostsFeatureInstrumentationModule(
@Provides
@Singleton
fun topGamingAllTimePostsView() = TopGamingAllTimePostsView(
- contentView, errorView, progressView)
+ contentView, errorView, progressView, guideView)
@Provides
@Singleton
diff --git a/app/src/main/kotlin/app/MainApplication.kt b/app/src/main/kotlin/app/MainApplication.kt
index a6fc9dd..0fc5b7c 100644
--- a/app/src/main/kotlin/app/MainApplication.kt
+++ b/app/src/main/kotlin/app/MainApplication.kt
@@ -24,10 +24,11 @@ internal open class MainApplication : Application() {
* @see app.gaming.TopGamingAllTimePostsActivity
*/
internal open fun buildTopGamingAllTimePostsFeatureComponent(
- contentView: RecyclerView, errorView: View, progressView: View, activity: Activity) =
+ contentView: RecyclerView, errorView: View, progressView: View, guideView: View,
+ activity: Activity) =
DaggerTopGamingAllTimePostsFeatureComponent.builder()
.topGamingAllTimePostsFeatureModule(
TopGamingAllTimePostsFeatureModule(
- contentView, errorView, progressView, activity))
+ contentView, errorView, progressView, guideView, activity))
.build()
}
diff --git a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsActivity.kt b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsActivity.kt
index 4afbac2..7c75cf7 100644
--- a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsActivity.kt
+++ b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsActivity.kt
@@ -107,7 +107,7 @@ class TopGamingAllTimePostsActivity : AppCompatActivity() {
private fun inject() {
(application as MainApplication).buildTopGamingAllTimePostsFeatureComponent(
// https://kotlinlang.org/docs/tutorials/android-plugin.html#using-kotlin-android-extensions
- content, error, progress, this).inject(this)
+ content, error, progress, scroll_guide, this).inject(this)
}
/**
diff --git a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureModule.kt b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureModule.kt
index 071e453..a8a3cab 100644
--- a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureModule.kt
+++ b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureModule.kt
@@ -39,6 +39,7 @@ internal class TopGamingAllTimePostsFeatureModule(
private val contentView: RecyclerView,
private val errorView: View,
private val progressView: View,
+ private val guideView: View,
private val activity: Activity) {
@Provides
@Singleton
@@ -93,7 +94,7 @@ internal class TopGamingAllTimePostsFeatureModule(
@Provides
@Singleton
fun topGamingAllTimePostsView() = TopGamingAllTimePostsView(
- contentView, errorView, progressView)
+ contentView, errorView, progressView, guideView)
@Provides
@Singleton
diff --git a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureView.kt b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureView.kt
index cf58457..2158e7e 100644
--- a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureView.kt
+++ b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsFeatureView.kt
@@ -10,12 +10,13 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Filter
import android.widget.Filterable
-import android.widget.FrameLayout
+import android.widget.ImageView
import android.widget.TextView
+import com.squareup.picasso.Callback
+import com.squareup.picasso.Picasso
import domain.entity.Post
import org.jorge.ms.app.R
import util.android.HtmlCompat
-import util.android.ext.getDimension
/**
* Configuration for the recycler view holding the post list.
@@ -82,7 +83,7 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder
= ViewHolder(LayoutInflater.from(parent.context).inflate(
- R.layout.item_post, parent, false), recyclerView, { callback.onItemClicked(it) })
+ R.layout.item_post, parent, false), { callback.onItemClicked(it) })
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.render(shownItems[position])
@@ -95,7 +96,7 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
return
}
// This is used to take the latest valid value in the given payload list
- val combinator: (Bundle, String) -> Unit = { bundle, key ->
+ val folder: (Bundle, String) -> Unit = { bundle, key ->
@Suppress("UNCHECKED_CAST")
bundle.putString(key, (payloads as List).fold(Bundle(), { old, new ->
val oldTitle = old.getString(key)
@@ -104,8 +105,8 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
}).getString(key))
}
val combinedBundle = Bundle().also { bundle ->
- arrayOf(KEY_TITLE, KEY_SUBREDDIT, KEY_SCORE).forEach {
- combinator(bundle, it)
+ arrayOf(KEY_TITLE, KEY_SUBREDDIT, KEY_SCORE, KEY_THUMBNAIL).forEach {
+ folder(bundle, it)
}
}
// Now combinedBundle contains the latest version of each of the fields that can be updated
@@ -183,9 +184,10 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
}
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int) =
- shownItems[oldItemPosition].let { (_, oldTitle, oldSubreddit, oldScore) ->
+ shownItems[oldItemPosition].let {
+ (_, oldTitle, oldSubreddit, oldScore, oldThumbnail) ->
filteredItems[newItemPosition].let {
- (_, newTitle, newSubreddit, newScore) ->
+ (_, newTitle, newSubreddit, newScore, newThumbnail) ->
Bundle().apply {
putString(KEY_TITLE, newTitle.takeIf {
!it.contentEquals(oldTitle)
@@ -196,6 +198,9 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
putString(KEY_SCORE, "${newScore.takeIf {
it != oldScore
}}")
+ putString(KEY_THUMBNAIL, newThumbnail.takeIf {
+ it != oldThumbnail
+ })
}
}
}
@@ -209,7 +214,6 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
@Suppress("UNCHECKED_CAST")
shownItems = results?.values as List? ?: items
- (recyclerView.layoutParams as FrameLayout.LayoutParams).bottomMargin = 0
diff.dispatchUpdatesTo(this@Adapter)
}
@@ -222,23 +226,25 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
/**
* Very simple viewholder that sets text and click event handling.
* @param itemView The view to dump the held data.
+ * @param onItemClicked What to run when a click happens.
*/
internal class ViewHolder internal constructor(
itemView: View,
- private val recyclerView: RecyclerView,
private val onItemClicked: (Post) -> Unit): RecyclerView.ViewHolder(itemView) {
private val titleView: TextView = itemView.findViewById(R.id.text_title) as TextView
private val scoreView: TextView = itemView.findViewById(R.id.text_score) as TextView
private val subredditView: TextView = itemView.findViewById(R.id.text_subreddit) as TextView
+ private val thumbnailView: ImageView = itemView.findViewById(R.id.thumbnail) as ImageView
/**
* Draw an item.
* @title The item to draw.
*/
internal fun render(item: Post) {
- titleView.text = HtmlCompat.fromHtml(item.title)
- subredditView.text = item.subreddit
- scoreView.text = item.score.toString()
+ setTitle(item.title)
+ setSubreddit(item.subreddit)
+ setScore(item.score)
+ setThumbnail(item.thumbnailLink)
itemView.setOnClickListener { onItemClicked(item) }
}
@@ -248,10 +254,12 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
* @param item The item these updates correspond to.
*/
internal fun renderPartial(bundle: Bundle, item: Post) {
- bundle.getString(KEY_TITLE).takeIf { it != null }.let { titleView.text =
- HtmlCompat.fromHtml(it!!) }
- bundle.getString(KEY_SUBREDDIT).takeIf { it != null }.let { subredditView.text = it }
- bundle.getString(KEY_SCORE).takeIf { it != null }.let { scoreView.text = it }
+ bundle.getString(KEY_TITLE).takeIf { it != null }.let { setTitle(it!!) }
+ bundle.getString(KEY_SUBREDDIT).takeIf { it != null }.let { setSubreddit(it!!) }
+ bundle.getString(KEY_SCORE).takeIf { it != null }.let {
+ setScore(Integer.valueOf(it!!))
+ }
+ setThumbnail(bundle.getString(KEY_THUMBNAIL))
itemView.setOnClickListener { onItemClicked(item) }
}
@@ -259,8 +267,56 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
* Adds a margin under the recycler view for the progress and error views to show.
*/
internal fun addBottomMargin() {
- (recyclerView.layoutParams as FrameLayout.LayoutParams).bottomMargin =
- itemView.context.getDimension(R.dimen.footer_padding).toInt()
+ }
+
+ /**
+ * Updates the layout according to the changes required by a new title.
+ * @param title The new title.
+ */
+ private fun setTitle(title: String) {
+ val formattedTitle = HtmlCompat.fromHtml(title)
+ titleView.text = formattedTitle
+ thumbnailView.contentDescription = formattedTitle.toString()
+ }
+
+ /**
+ * Updates the layout according to the changes required by a new subreddit.
+ * @param name The new subreddit name.
+ */
+ private fun setSubreddit(name: String) {
+ subredditView.text = name
+ }
+
+ /**
+ * Updates the layout according to the changes required by a new score.
+ * @param score The new score.
+ */
+ private fun setScore(score: Int) {
+ scoreView.text = score.toString()
+ }
+
+ /**
+ * Updates the layout according to the changes required by a new thumbnail link.
+ * @param thumbnailLink The new thumbnail link, or null
if none is applicable.
+ */
+ private fun setThumbnail(thumbnailLink: String?) {
+ if (thumbnailLink != null) {
+ Picasso.with(thumbnailView.context)
+ .load(thumbnailLink)
+ .into(thumbnailView, object : Callback {
+ override fun onError() {
+ thumbnailView.visibility = View.GONE
+ thumbnailView.setImageDrawable(null)
+ }
+
+ override fun onSuccess() {
+ thumbnailView.visibility = View.VISIBLE
+ }
+ })
+ } else {
+ thumbnailView.visibility = View.GONE
+ thumbnailView.setImageDrawable(null)
+ }
}
}
@@ -268,6 +324,7 @@ internal class Adapter(private val callback: TopGamingAllTimePostsActivity.Behav
private val KEY_TITLE = "KEY_TITLE"
private val KEY_SUBREDDIT = "KEY_SUBREDDIT"
private val KEY_SCORE = "KEY_SCORE"
+ private val KEY_THUMBNAIL = "KEY_THUMBNAIL"
}
}
diff --git a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsView.kt b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsView.kt
index f984de2..a3be93e 100644
--- a/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsView.kt
+++ b/app/src/main/kotlin/app/gaming/TopGamingAllTimePostsView.kt
@@ -2,8 +2,11 @@ package app.gaming
import android.support.v7.widget.RecyclerView
import android.view.View
+import android.widget.FrameLayout
import app.LoadableContentView
import domain.entity.Post
+import org.jorge.ms.app.R
+import util.android.ext.getDimension
/**
* Wraps UI behavior for top all time gaming posts scenario.
@@ -11,9 +14,12 @@ import domain.entity.Post
internal class TopGamingAllTimePostsView(
internal val contentView: RecyclerView,
internal val errorView: View,
- private val progressView: View) : LoadableContentView {
+ private val progressView: View,
+ private val guideView: View) : LoadableContentView {
override fun showLoadingLayout() {
+ pushInfoArea()
progressView.visibility = View.VISIBLE
+ guideView.visibility = View.INVISIBLE
}
override fun hideLoadingLayout() {
@@ -22,13 +28,21 @@ internal class TopGamingAllTimePostsView(
override fun updateContent(actionResult: List) {
(contentView.adapter as Adapter).addItems(actionResult)
+ guideView.visibility = View.VISIBLE
}
override fun showErrorLayout() {
+ pushInfoArea()
errorView.visibility = View.VISIBLE
+ guideView.visibility = View.INVISIBLE
}
override fun hideErrorLayout() {
errorView.visibility = View.GONE
}
+
+ private fun pushInfoArea() {
+ (contentView.layoutParams as FrameLayout.LayoutParams).bottomMargin =
+ contentView.context.getDimension(R.dimen.footer_padding).toInt()
+ }
}
diff --git a/app/src/main/res/layout-v21/item_post.xml b/app/src/main/res/layout-v21/item_post.xml
index 9c2c8a5..81ee944 100644
--- a/app/src/main/res/layout-v21/item_post.xml
+++ b/app/src/main/res/layout-v21/item_post.xml
@@ -3,6 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:padding="@dimen/appbar_horizontal_padding"
android:theme="@style/AppTheme.Card">
@@ -10,13 +11,20 @@
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/section_separator"
android:textIsSelectable="false"
android:clickable="false"
style="@style/AppTheme.TextTitle" />
+
diff --git a/app/src/main/res/layout/include_top_posts_view.xml b/app/src/main/res/layout/include_top_posts_view.xml
index 2c2c36f..e495345 100644
--- a/app/src/main/res/layout/include_top_posts_view.xml
+++ b/app/src/main/res/layout/include_top_posts_view.xml
@@ -36,4 +36,14 @@
android:textStyle="bold"
android:text="@string/top_posts_error_action" />
+
diff --git a/app/src/main/res/layout/item_post.xml b/app/src/main/res/layout/item_post.xml
index 50bf495..50fcd1f 100644
--- a/app/src/main/res/layout/item_post.xml
+++ b/app/src/main/res/layout/item_post.xml
@@ -1,6 +1,7 @@
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 55180e9..dfe7a4b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,5 +3,6 @@
reddit
Error loading
Retry
+ Scroll down to see more!
Search r/gaming]]>
diff --git a/app/src/test/kotlin/app/gaming/TopGamingAllTimePostsViewSpek.kt b/app/src/test/kotlin/app/gaming/TopGamingAllTimePostsViewSpek.kt
deleted file mode 100644
index 8c7f2fd..0000000
--- a/app/src/test/kotlin/app/gaming/TopGamingAllTimePostsViewSpek.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package app.gaming
-
-import android.support.v7.widget.RecyclerView
-import android.view.View
-import com.nhaarman.mockito_kotlin.doAnswer
-import com.nhaarman.mockito_kotlin.doReturn
-import com.nhaarman.mockito_kotlin.eq
-import com.nhaarman.mockito_kotlin.mock
-import com.nhaarman.mockito_kotlin.reset
-import com.nhaarman.mockito_kotlin.verify
-import com.nhaarman.mockito_kotlin.verifyNoMoreInteractions
-import com.nhaarman.mockito_kotlin.whenever
-import domain.entity.Post
-import org.jetbrains.spek.api.SubjectSpek
-import org.jetbrains.spek.api.dsl.it
-import org.junit.platform.runner.JUnitPlatform
-import org.junit.runner.RunWith
-
-/**
- * Tests for the all-time top in r/gaming view
- * @see TopGamingAllTimePostsView
- */
-@RunWith(JUnitPlatform::class)
-internal class TopGamingAllTimePostsViewSpek : SubjectSpek({
- subject { TopGamingAllTimePostsView(MOCK_RECYCLER_VIEW, MOCK_ERROR_VIEW, MOCK_PROGRESS_VIEW) }
-
- afterEachTest { reset(MOCK_RECYCLER_VIEW, MOCK_ERROR_VIEW, MOCK_PROGRESS_VIEW) }
-
- it ("should make the progress view visible") {
- subject.showLoadingLayout()
- verify(MOCK_PROGRESS_VIEW).visibility = eq(View.VISIBLE)
- verifyNoMoreInteractions(MOCK_RECYCLER_VIEW, MOCK_ERROR_VIEW, MOCK_PROGRESS_VIEW)
- }
-
- it ("should make the progress view go away") {
- subject.hideLoadingLayout()
- verify(MOCK_PROGRESS_VIEW).visibility = eq(View.GONE)
- verifyNoMoreInteractions(MOCK_RECYCLER_VIEW, MOCK_ERROR_VIEW, MOCK_PROGRESS_VIEW)
- }
-
- it ("should update the content") {
- val mockList = mock>()
- val mockAdapter = mock {
- onGeneric { addItems(eq(mockList)) } doAnswer { }
- }
- whenever (MOCK_RECYCLER_VIEW.adapter) doReturn mockAdapter
- subject.updateContent(mockList)
- verify(MOCK_RECYCLER_VIEW).adapter
- verify(mockAdapter).addItems(eq(mockList))
- verifyNoMoreInteractions(MOCK_RECYCLER_VIEW, MOCK_ERROR_VIEW, MOCK_PROGRESS_VIEW)
- }
-
- it ("should make the error view visible") {
- subject.showErrorLayout()
- verify(MOCK_ERROR_VIEW).visibility = eq(View.VISIBLE)
- verifyNoMoreInteractions(MOCK_RECYCLER_VIEW, MOCK_ERROR_VIEW, MOCK_PROGRESS_VIEW)
- }
-
- it ("should make the error view go away") {
- subject.hideErrorLayout()
- verify(MOCK_ERROR_VIEW).visibility = eq(View.GONE)
- verifyNoMoreInteractions(MOCK_RECYCLER_VIEW, MOCK_ERROR_VIEW, MOCK_PROGRESS_VIEW)
- }
-}) {
- companion object {
- private val MOCK_RECYCLER_VIEW = mock()
- private val MOCK_ERROR_VIEW = mock()
- private val MOCK_PROGRESS_VIEW = mock()
- }
-}
diff --git a/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
deleted file mode 100644
index 1f0955d..0000000
--- a/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
+++ /dev/null
@@ -1 +0,0 @@
-mock-maker-inline
diff --git a/buildsystem/dependencies.gradle b/buildsystem/dependencies.gradle
index de32761..b84c4d8 100644
--- a/buildsystem/dependencies.gradle
+++ b/buildsystem/dependencies.gradle
@@ -1,12 +1,13 @@
final def daggerVersion = "2.10"
-final def firebaseVersion = "10.2.4"
final def espressoVersion = "2.2.2"
+final def firebaseVersion = "10.2.4"
final def jsr250Version = "1.0"
final def junitPlatformRunnerVersion = "1.0.0-M3"
final def jUnitVersion = "4.12"
final def kotlinVersion = rootProject.ext.kotlinVersion
final def mockitoKotlinVersion = "1.4.0"
final def mockitoAndroidVersion = "2.7.22"
+final def picassoVersion = "2.5.2"
final def retrofitVersion = "2.1.0"
final def rxAndroidVersion = "1.2.1"
final def rxJavaVersion = "1.2.6"
@@ -65,7 +66,8 @@ ext {
"com.android.support:appcompat-v7:$supportVersion",
"com.android.support:design:$supportVersion",
"com.google.firebase:firebase-crash:$firebaseVersion",
- "com.google.dagger:dagger-android:$daggerVersion"
+ "com.google.dagger:dagger-android:$daggerVersion",
+ "com.squareup.picasso:picasso:$picassoVersion"
]
providedUtilAndroidDependencies = [
"com.android.support:support-annotations:$supportVersion"
diff --git a/data/src/main/kotlin/data/common/DataPost.kt b/data/src/main/kotlin/data/common/DataPost.kt
index 7bc76e2..d1b2245 100644
--- a/data/src/main/kotlin/data/common/DataPost.kt
+++ b/data/src/main/kotlin/data/common/DataPost.kt
@@ -11,7 +11,8 @@ internal data class DataPost(
@Json(name = "title") val title: String,
@Json(name = "subreddit_name_prefixed") val subreddit: String,
@Json(name = "score") val score: Int,
- @Json(name = "permalink") val permalink: String) {
+ @Json(name = "permalink") val permalink: String,
+ @Json(name= "thumbnail") val thumbnailLink: String) {
override fun hashCode() = id.hashCode()
override fun equals(other: Any?) = other is DataPost && id == other.id
diff --git a/data/src/main/kotlin/data/top/TopRequestEntityMapper.kt b/data/src/main/kotlin/data/top/TopRequestEntityMapper.kt
index 9a06f36..efe5e2b 100644
--- a/data/src/main/kotlin/data/top/TopRequestEntityMapper.kt
+++ b/data/src/main/kotlin/data/top/TopRequestEntityMapper.kt
@@ -17,5 +17,6 @@ internal class TopRequestEntityMapper {
dataPost.title,
dataPost.subreddit,
dataPost.score,
- "${BuildConfig.API_URL}${dataPost.permalink.drop(1)}")
+ "${BuildConfig.API_URL}${dataPost.permalink.drop(1)}",
+ dataPost.thumbnailLink)
}
diff --git a/data/src/test/kotlin/data/top/TopRequestEntityMapperSpek.kt b/data/src/test/kotlin/data/top/TopRequestEntityMapperSpek.kt
index cc07fe7..d7400ad 100644
--- a/data/src/test/kotlin/data/top/TopRequestEntityMapperSpek.kt
+++ b/data/src/test/kotlin/data/top/TopRequestEntityMapperSpek.kt
@@ -18,22 +18,22 @@ internal class TopRequestEntityMapperSpek : SubjectSpek(
subject { TopRequestEntityMapper() } // <- Specify the test subject (the singleton instance, in this case)
it ("should transform a happy case") {
- val source = DataPost("r54553", "random title", "random subreddit", 23, "some permalink")
+ val source = DataPost("r54553", "random title", "random subreddit", 23, "some permalink", "https://media.giphy.com/media/3o6ZtdtckQKDQWAet2/giphy.gif")
assertEquivalent(source, subject.transform(source))
}
it ("should transform an all empty/0s case") {
- val source = DataPost("", "", "", 0, "")
+ val source = DataPost("", "", "", 0, "", "")
assertEquivalent(source, subject.transform(source))
}
it ("should transform a mixed case") {
- val source = DataPost("aa", "", "another subreddit", 0, "another permalink")
+ val source = DataPost("aa", "", "another subreddit", 0, "another permalink", "self")
assertEquivalent(source, subject.transform(source))
}
it ("should transform when score is negative") {
- val source = DataPost("87", "a title", "yet another subreddit", -7, "one more permalink")
+ val source = DataPost("87", "a title", "yet another subreddit", -7, "one more permalink", "feafea")
assertEquivalent(source, subject.transform(source))
}
}) {
@@ -44,6 +44,7 @@ internal class TopRequestEntityMapperSpek : SubjectSpek(
assertEquals(dataPost.subreddit, post.subreddit)
assertEquals(dataPost.score, post.score)
assertEquals("${BuildConfig.API_URL}${dataPost.permalink.drop(1)}", post.detailLink)
+ assertEquals(dataPost.thumbnailLink, post.thumbnailLink)
}
}
}
diff --git a/domain/src/main/kotlin/domain/entity/Post.kt b/domain/src/main/kotlin/domain/entity/Post.kt
index 86370eb..e354fca 100644
--- a/domain/src/main/kotlin/domain/entity/Post.kt
+++ b/domain/src/main/kotlin/domain/entity/Post.kt
@@ -9,7 +9,8 @@ data class Post(
val title: String,
val subreddit: String,
val score: Int,
- val detailLink: String) {
+ val detailLink: String,
+ val thumbnailLink: String) {
override fun hashCode() = id.hashCode()
override fun equals(other: Any?) = other is Post && id == other.id
diff --git a/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsFetchUseCaseSpek.kt b/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsFetchUseCaseSpek.kt
index 7bf641d..cc24074 100644
--- a/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsFetchUseCaseSpek.kt
+++ b/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsFetchUseCaseSpek.kt
@@ -38,9 +38,9 @@ internal class TopGamingAllTimePostsFetchUseCaseSpek : SubjectSpek()
// Cannot mock Post as it is a data class
- val values = arrayOf(Post("", "title", "sr", -8, "permalink"),
- Post("rafe", "titfle", "eeesr", 9, ""),
- Post("123", "titlea", "sr", 0, "pfaefaermalink"))
+ val values = arrayOf(Post("", "title", "sr", -8, "permalink", "a"),
+ Post("rafe", "titfle", "eeesr", 9, "", "a"),
+ Post("123", "titlea", "sr", 0, "pfaefaermalink", "a"))
whenever(MOCK_FACADE.fetchTop(any(), any(), any())) doReturn Observable.from(values)
subject.execute(testSubscriber)
testSubscriber.awaitTerminalEvent()
diff --git a/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsGetUseCaseSpek.kt b/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsGetUseCaseSpek.kt
index 7545fd8..4d9688f 100644
--- a/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsGetUseCaseSpek.kt
+++ b/domain/src/test/kotlin/domain/interactor/TopGamingAllTimePostsGetUseCaseSpek.kt
@@ -38,9 +38,9 @@ internal class TopGamingAllTimePostsGetUseCaseSpek : SubjectSpek()
// Cannot mock Post as it is a data class
- val values = arrayOf(Post("", "title", "sr", -8, "permalink"),
- Post("fafe", "titfle", "eeesr", 9, ""),
- Post("id-1 23132", "titlea", "sr", 0, "pfaefaermalink"))
+ val values = arrayOf(Post("", "title", "sr", -8, "permalink", "a"),
+ Post("fafe", "titfle", "eeesr", 9, "", "a"),
+ Post("id-1 23132", "titlea", "sr", 0, "pfaefaermalink", "a"))
whenever(MOCK_FACADE.getTop(any(), any(), any())) doReturn Observable.from(values)
subject.execute(testSubscriber)
testSubscriber.awaitTerminalEvent()