diff --git a/app/src/main/res/navigation/main_navigation.xml b/app/src/main/res/navigation/main_navigation.xml
index f17e2a2..69ae5ab 100644
--- a/app/src/main/res/navigation/main_navigation.xml
+++ b/app/src/main/res/navigation/main_navigation.xml
@@ -1,6 +1,10 @@
+
+
diff --git a/core/src/main/java/dev/carlos/core/domain/network/NetworkErrors.kt b/core/src/main/java/dev/carlos/core/domain/network/NetworkErrors.kt
index 83e931f..39c676e 100644
--- a/core/src/main/java/dev/carlos/core/domain/network/NetworkErrors.kt
+++ b/core/src/main/java/dev/carlos/core/domain/network/NetworkErrors.kt
@@ -1,7 +1,10 @@
package dev.carlos.core.domain.network
-enum class RequestError {
- NO_NETWORK,
- BAD_RESPONSE,
- UNKNOWN_PROBLEM
+import androidx.annotation.StringRes
+import dev.carlos.core.R
+
+enum class RequestError(@StringRes val message: Int) {
+ NO_NETWORK(R.string.network_error_no_network),
+ BAD_RESPONSE(R.string.network_error_bad_response),
+ UNKNOWN_PROBLEM(R.string.network_error_unknown)
}
diff --git a/core/src/main/java/dev/carlos/core/extensions/DataExtensions.kt b/core/src/main/java/dev/carlos/core/extensions/DataExtensions.kt
index 1176e23..c9b501b 100644
--- a/core/src/main/java/dev/carlos/core/extensions/DataExtensions.kt
+++ b/core/src/main/java/dev/carlos/core/extensions/DataExtensions.kt
@@ -5,7 +5,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
fun LiveData.observeNonNull(owner: LifecycleOwner, func: (T) -> Unit) {
- observe(owner, Observer {
+ observe(owner, {
it?.let {
func(it)
}
diff --git a/core/src/main/java/dev/carlos/core/extensions/StringsExtensions.kt b/core/src/main/java/dev/carlos/core/extensions/StringsExtensions.kt
new file mode 100644
index 0000000..e61c927
--- /dev/null
+++ b/core/src/main/java/dev/carlos/core/extensions/StringsExtensions.kt
@@ -0,0 +1,5 @@
+package dev.carlos.core.extensions
+
+import java.util.*
+
+fun String.capitalize() = replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
diff --git a/core/src/main/res/drawable/bg_card.xml b/core/src/main/res/drawable/bg_card.xml
new file mode 100644
index 0000000..f686445
--- /dev/null
+++ b/core/src/main/res/drawable/bg_card.xml
@@ -0,0 +1,9 @@
+
+
+ -
+
+
+
+
+
+
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index 09837df..9c8f149 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -7,4 +7,7 @@
#FF018786
#FF000000
#FFFFFFFF
-
\ No newline at end of file
+ #EEEEEE
+ #00000000
+ #FFFFFF
+
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 75f77d2..696b69b 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
- core
-
\ No newline at end of file
+ Respuesta inesperada
+ Sin conexión
+ Error desconocido
+
diff --git a/shortform/src/main/java/dev/carlos/shortform/feature/ShortformFragment.kt b/shortform/src/main/java/dev/carlos/shortform/feature/ShortformFragment.kt
index b787a69..3f8cc3e 100644
--- a/shortform/src/main/java/dev/carlos/shortform/feature/ShortformFragment.kt
+++ b/shortform/src/main/java/dev/carlos/shortform/feature/ShortformFragment.kt
@@ -1,4 +1,90 @@
package dev.carlos.shortform.feature
-class ShortformFragment {
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import dev.carlos.core.domain.network.RequestError
+import dev.carlos.core.domain.network.RequestState
+import dev.carlos.core.extensions.gone
+import dev.carlos.core.extensions.observeNonNull
+import dev.carlos.core.extensions.visible
+import dev.carlos.shortform.R
+import dev.carlos.shortform.data.models.ShortformModel
+import dev.carlos.shortform.databinding.FragmentShortformDefinitionBinding
+import dev.carlos.shortform.viewmodels.ShortformViewmodel
+import dev.carlos.shortform.widgets.LongformAdapter
+import org.koin.androidx.viewmodel.ext.android.viewModel
+
+class ShortformFragment : Fragment() {
+ private val viewModel: ShortformViewmodel by viewModel()
+ private val listAdapter by lazy { LongformAdapter() }
+ private lateinit var binding: FragmentShortformDefinitionBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View = inflater.inflate(R.layout.fragment_shortform_definition, container, false)
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setBinding(view)
+ setRecycler()
+ setObservers()
+ }
+
+ private fun setBinding(view: View) {
+ binding = FragmentShortformDefinitionBinding.bind(view)
+ }
+
+ private fun setObservers() {
+ viewModel.acronymDefinition.observeNonNull(this) {
+ handleResult(it)
+ }
+ }
+
+ private fun handleResult(state: RequestState) {
+ when (state) {
+ is RequestState.Success<*> -> handleSuccess(state.data as ShortformModel)
+ is RequestState.Empty -> handleEmpty()
+ is RequestState.Error -> handleError(state.type)
+ is RequestState.Loading -> handleLoading()
+ }
+ }
+
+ private fun handleLoading() {
+ binding.shortformDefinitionLoading.visible()
+ binding.shortformDefinitionError.gone()
+ }
+
+ private fun handleSuccess(shortform: ShortformModel) {
+ binding.shortformDefinitionError.gone()
+ binding.shortformDefinitionLoading.gone()
+ listAdapter.addAll(shortform.results)
+ }
+
+ private fun handleEmpty() {
+ binding.shortformDefinitionErrorLabel.text = getString(R.string.shortform_definition_no_definition)
+ binding.shortformDefinitionError.visible()
+ binding.shortformDefinitionLoading.gone()
+ }
+
+ private fun handleError(error: RequestError) {
+ binding.shortformDefinitionErrorLabel.text = getString(error.message)
+ binding.shortformDefinitionError.visible()
+ binding.shortformDefinitionLoading.gone()
+ }
+
+ private fun setRecycler() {
+ binding.shortformDefinitionRecycler.apply {
+ layoutManager = LinearLayoutManager(context)
+ adapter = listAdapter.apply {
+ onItemClick = {
+ Toast.makeText(context, it.value, Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/shortform/src/main/java/dev/carlos/shortform/widgets/LongformAdapter.kt b/shortform/src/main/java/dev/carlos/shortform/widgets/LongformAdapter.kt
new file mode 100644
index 0000000..6543abe
--- /dev/null
+++ b/shortform/src/main/java/dev/carlos/shortform/widgets/LongformAdapter.kt
@@ -0,0 +1,60 @@
+package dev.carlos.shortform.widgets
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import dev.carlos.core.extensions.autoNotify
+import dev.carlos.core.extensions.capitalize
+import dev.carlos.shortform.R
+import dev.carlos.shortform.data.models.ShortformModel
+import dev.carlos.shortform.databinding.ItemLongformCardBinding
+import kotlin.properties.Delegates
+
+class LongformAdapter : RecyclerView.Adapter() {
+
+ private var items by Delegates.observable(emptyList()) { _, oldList, newList ->
+ autoNotify(oldList, newList) { old, new -> old.value == new.value }
+ notifyDataSetChanged()
+ }
+
+ var onItemClick: (ShortformModel.LongformModel) -> Unit = { }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
+ LongformViewHolder(
+ LayoutInflater
+ .from(parent.context)
+ .inflate(R.layout.item_longform_card, parent, false),
+ onItemClick
+ )
+
+ fun getItem(position: Int) = items[position]
+
+ fun addAll(list: List) {
+ items = list
+ }
+
+ override fun getItemCount() = items.size
+
+ override fun onBindViewHolder(viewholder: RecyclerView.ViewHolder, position: Int) =
+ when (viewholder) {
+ is LongformViewHolder -> viewholder.bind(items[position])
+ else -> throw NoWhenBranchMatchedException("Undefined viewholder")
+ }
+}
+
+class LongformViewHolder(
+ private val view: View,
+ private val onItemClick: (ShortformModel.LongformModel) -> Unit
+) : RecyclerView.ViewHolder(view) {
+
+ private val binding = ItemLongformCardBinding.bind(view)
+
+ fun bind(longform: ShortformModel.LongformModel) = with(view) {
+ binding.itemLongformName.text = longform.value.capitalize()
+ binding.itemLongformSince.text = view.resources.getString(R.string.item_longform_since, longform.since)
+ binding.itemLongformContainer.setOnClickListener {
+ onItemClick(longform)
+ }
+ }
+}
\ No newline at end of file
diff --git a/shortform/src/main/res/layout/fragment_shortform_definition.xml b/shortform/src/main/res/layout/fragment_shortform_definition.xml
new file mode 100644
index 0000000..0958fae
--- /dev/null
+++ b/shortform/src/main/res/layout/fragment_shortform_definition.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shortform/src/main/res/layout/item_longform_card.xml b/shortform/src/main/res/layout/item_longform_card.xml
new file mode 100644
index 0000000..e580f44
--- /dev/null
+++ b/shortform/src/main/res/layout/item_longform_card.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
diff --git a/shortform/src/main/res/navigation/shortform_navigation.xml b/shortform/src/main/res/navigation/shortform_navigation.xml
new file mode 100644
index 0000000..2ed5d1b
--- /dev/null
+++ b/shortform/src/main/res/navigation/shortform_navigation.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/shortform/src/main/res/values/strings.xml b/shortform/src/main/res/values/strings.xml
index 5423e6c..be206d9 100644
--- a/shortform/src/main/res/values/strings.xml
+++ b/shortform/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
- acronyms
+ Desde %1$d
+ Buscar acrónimo
+ No existe una definición
\ No newline at end of file