Skip to content

Commit

Permalink
[FEAT] List arcs on arcs screen
Browse files Browse the repository at this point in the history
  • Loading branch information
peterkrauz committed Oct 23, 2020
1 parent 4710667 commit 6539a99
Show file tree
Hide file tree
Showing 17 changed files with 212 additions and 10 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/com/peterkrauz/grimoire/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import kotlinx.android.synthetic.main.activity_main.*
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

private val mainViewModel: MainViewModel by viewModels()
private val mainViewModel by viewModels<MainViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_Grimoire)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.peterkrauz.grimoire.common.extension

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes

fun ViewGroup.inflate(@LayoutRes layoutId: Int): View {
return LayoutInflater.from(context).inflate(layoutId, this, false)
}
2 changes: 1 addition & 1 deletion common/src/main/res/drawable/ic_add.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM19,11h-4v4h-2v-4L9,11L9,9h4L13,5h2v4h4v2z"/>
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>
2 changes: 2 additions & 0 deletions common/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Gruhm Waar</string>
<!-- Empty state messages -->
<string name="arcs_empty_state_msg">It seems you haven\'t\ncreated any Arc.\n\n\nClick the button below\nto add one!</string>
<string name="characters_empty_state_msg">It seems you haven\'t\ncreated any Character.\n\n\nClick the button below\nto add one!</string>
Expand All @@ -9,4 +10,5 @@
<!-- Generic messages -->
<string name="create">Create</string>
<string name="generic_error_msg">An error has occurred. Please retry</string>
<string name="read_more">Read more</string>
</resources>
3 changes: 3 additions & 0 deletions data/src/main/java/com/peterkrauz/grimoire/data/dao/ArcDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ interface ArcDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(arc: ArcEntity): Long

@Query("SELECT * FROM arc")
suspend fun findAll(): List<ArcEntity>

@Query("SELECT * FROM arc WHERE id = :arcId")
suspend fun findById(arcId: Long): ArcEntity
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ class ArcRepositoryImpl @Inject constructor(private val dao: ArcDao) : ArcReposi
val arcId = dao.insert(entity)
return ArcMapper.fromEntity(dao.findById(arcId))
}

override suspend fun findAll(): List<Arc> {
val entities = dao.findAll()
return entities.map(ArcMapper::fromEntity)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.peterkrauz.grimoire.domain.entity

class Arc(
data class Arc(
val id: Long,
val title: String,
val description: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ package com.peterkrauz.grimoire.domain.entity

interface ArcRepository {

suspend fun findAll(): List<Arc>
suspend fun createArc(form: CreateArcForm): Arc
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.peterkrauz.grimoire.presentation.home

import android.view.View
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.peterkrauz.grimoire.domain.entity.Arc
import kotlinx.android.synthetic.main.item_arc.view.*

class ArcViewHolder(view: View) : ViewHolder(view) {
fun bind(arc: Arc) {
itemView.run {
textViewArcName.text = arc.title
textViewArcDescription.text = arc.description
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.peterkrauz.grimoire.presentation.home

import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.peterkrauz.grimoire.common.extension.inflate
import com.peterkrauz.grimoire.domain.entity.Arc

class ArcsAdapter : ListAdapter<Arc, ArcViewHolder>(ArcDiffCallback) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArcViewHolder {
return ArcViewHolder(parent.inflate(R.layout.item_arc))
}

override fun onBindViewHolder(holder: ArcViewHolder, position: Int) {
holder.bind(getItem(position))
}

private object ArcDiffCallback : DiffUtil.ItemCallback<Arc>() {
override fun areItemsTheSame(old: Arc, new: Arc): Boolean {
return old.id == new.id
}

override fun areContentsTheSame(old: Arc, new: Arc): Boolean {
return old == new
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,66 @@ package com.peterkrauz.grimoire.presentation.home

import android.os.Bundle
import android.view.View
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.observe
import androidx.recyclerview.widget.LinearLayoutManager
import com.peterkrauz.grimoire.common.extension.safeNavigate
import com.peterkrauz.grimoire.common.extension.snackBar
import com.peterkrauz.grimoire.common.snackbar.SnackBarType
import com.peterkrauz.grimoire.domain.entity.Arc
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.fragment_arcs.*

@AndroidEntryPoint
class ArcsFragment : Fragment(R.layout.fragment_arcs) {

private val viewModel: ArcsViewModel by viewModels()
private val viewModel by viewModels<ArcsViewModel>()

private val arcsAdapter by lazy(::ArcsAdapter)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupButtons()
setupRecyclerView()
observeViewModel()
}

override fun onResume() {
super.onResume()
viewModel.fetchArcs()
}

private fun setupButtons() {
floatingActionButton.setOnClickListener {
safeNavigate(R.id.arcsFragment, R.id.createArcAction)
}
}

private fun setupRecyclerView() {
recyclerViewArcs.apply {
setHasFixedSize(true)
adapter = arcsAdapter
layoutManager = LinearLayoutManager(requireContext())
}
}

private fun observeViewModel() {
viewModel.arcsLiveData.observe(viewLifecycleOwner, ::setArcs)
viewModel.stateLiveData.observe(viewLifecycleOwner, ::setState)
viewModel.errorLiveEvent.observe(viewLifecycleOwner) { setError() }
}

private fun setArcs(arcs: List<Arc>) {
arcsAdapter.submitList(arcs)
recyclerViewArcs.isVisible = arcs.isNotEmpty()
linearLayoutEmptyState.isVisible = arcs.isEmpty()
}

private fun setState(state: ArcsState) {
progressBarState.isVisible = state == ArcsState.LOADING
}

private fun setError() = snackBar(R.string.generic_error_msg, SnackBarType.ERROR)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.peterkrauz.grimoire.presentation.home

enum class ArcsState {
IDLE
IDLE, LOADING
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ package com.peterkrauz.grimoire.presentation.home

import androidx.hilt.Assisted
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.SavedStateHandle
import com.peterkrauz.grimoire.common.base.BaseViewModel
import com.peterkrauz.grimoire.common.presentation.SingleLiveEvent
import com.peterkrauz.grimoire.domain.entity.Arc
import com.peterkrauz.grimoire.domain.entity.ArcRepository
import kotlin.coroutines.CoroutineContext

class ArcsViewModel @ViewModelInject constructor(
@Assisted private val savedStateHandle: SavedStateHandle
@Assisted private val savedStateHandle: SavedStateHandle,
private val arcRepository: ArcRepository
) : BaseViewModel<ArcsState>() {

override var state = ArcsState.IDLE
Expand All @@ -16,6 +22,19 @@ class ArcsViewModel @ViewModelInject constructor(
_stateLiveData.postValue(value)
}

val errorLiveEvent = SingleLiveEvent<Unit>()

private val _arcsLiveData = MutableLiveData<List<Arc>>()
val arcsLiveData: LiveData<List<Arc>>
get() = _arcsLiveData

fun fetchArcs() {
perform(ArcsState.LOADING, ArcsState.IDLE) {
_arcsLiveData.postValue(arcRepository.findAll())
}
}

override fun handleCoroutineError(ctx: CoroutineContext, error: Throwable) {
errorLiveEvent.call()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import kotlinx.android.synthetic.main.fragment_create_arc.*
@AndroidEntryPoint
class CreateArcFragment : Fragment(R.layout.fragment_create_arc) {

private val viewModel: CreateArcViewModel by viewModels()
private val mainViewModel: MainViewModel by viewModels(::requireActivity)
private val viewModel by viewModels<CreateArcViewModel>()
private val mainViewModel by viewModels<MainViewModel>(::requireActivity)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Expand Down
20 changes: 20 additions & 0 deletions presentation/home/src/main/res/layout/fragment_arcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@

</LinearLayout>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewArcs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:padding="24dp"
android:clipToPadding="false"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>

<ProgressBar
android:id="@+id/progressBarState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="wrap_content"
Expand Down
13 changes: 11 additions & 2 deletions presentation/home/src/main/res/layout/fragment_create_arc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/arc_title"
android:imeOptions="actionNext"
android:nextFocusDown="@id/editTextDescription"
app:placeholderText="@string/arc_title_placeholder">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editTextTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:imeOptions="actionNext"
android:nextFocusDown="@id/editTextDescription">

</com.google.android.material.textfield.TextInputEditText>
Expand All @@ -60,13 +64,18 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/arc_description"
android:imeOptions="actionNext"
android:nextFocusDown="@id/buttonCreate"
android:layout_marginTop="16dp"
app:placeholderText="@string/arc_description_placeholder">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editTextDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:maxLines="1"
android:imeOptions="actionNext"
android:nextFocusDown="@id/buttonCreate">

</com.google.android.material.textfield.TextInputEditText>

Expand All @@ -92,6 +101,6 @@
android:enabled="false"
app:layout_anchor="@id/linearLayoutInputs"
app:layout_anchorGravity="bottom|end"
app:icon="@drawable/ic_confirm"/>
app:icon="@drawable/ic_add"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
53 changes: 53 additions & 0 deletions presentation/home/src/main/res/layout/item_arc.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView 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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardUseCompatPadding="true">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp">

<TextView
android:id="@+id/textViewArcName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fontFamily="@font/kumbh_sans_bold"
android:textSize="21sp"
android:maxLines="1"
android:layout_marginTop="4dp"
tools:text="There and back again"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<TextView
android:id="@+id/textViewArcDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fontFamily="@font/kumbh_sans_regular"
android:textSize="16sp"
android:maxLines="3"
android:ellipsize="middle"
tools:text="Once upon a time..."
app:layout_constraintTop_toBottomOf="@id/textViewArcName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<Button
style="@style/Widget.MaterialComponents.Button.TextButton"
android:id="@+id/buttonReadMore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/read_more"
app:layout_constraintTop_toBottomOf="@id/textViewArcDescription"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

</com.google.android.material.card.MaterialCardView>

0 comments on commit 6539a99

Please sign in to comment.