Skip to content

Commit

Permalink
Merge pull request #57 from pauliancu97/feature/FavoritesAnimesPage
Browse files Browse the repository at this point in the history
Feature/favorites animes page added
  • Loading branch information
justdvnsh authored Oct 10, 2021
2 parents fa6ce4a + e4011a2 commit df0b2cf
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class FavoritesFragment: Fragment() {
if (mediator != null)
mediator!!.detach()
pagerAdapter.removeAllFragments()
pagerAdapter.addFragments(tabNames)
pagerAdapter.addFragments()
binding.viewPager2.offscreenPageLimit = pagerAdapter.itemCount

val tabs = mutableListOf<String>().apply {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package divyansh.tech.animeclassroom.favorites.screens.animes

import divyansh.tech.animeclassroom.common.AnimeClickCallback
import divyansh.tech.animeclassroom.common.CommonViewModel
import divyansh.tech.animeclassroom.favorites.FavoritesFragmentDirections

class FavoriteAnimeCallbacks(private val viewModel: CommonViewModel) : AnimeClickCallback {
override fun onAnimeClicked(animeUrl: String) {
viewModel.changeNavigation(
FavoritesFragmentDirections.actionFavoritesFragmentToAnimeDetailFragment(
animeUrl = animeUrl
)
)
}

override fun onEpisodeClicked(episodeUrl: String) {}

override fun onGenreClicked(genreUrl: String) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package divyansh.tech.animeclassroom.favorites.screens.animes

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import divyansh.tech.animeclassroom.EventObserver
import divyansh.tech.animeclassroom.ResultWrapper
import divyansh.tech.animeclassroom.databinding.FragmentFavoriteAnimeBinding
import divyansh.tech.animeclassroom.favorites.screens.animes.epoxy.EpoxyFavoriteAnimeController

@AndroidEntryPoint
class FavoriteAnimeFragment : Fragment() {

companion object {
fun getInstance() = FavoriteAnimeFragment()
}

private lateinit var _favoriteAnimeFragmentBinding: FragmentFavoriteAnimeBinding
private val binding: FragmentFavoriteAnimeBinding
get() = _favoriteAnimeFragmentBinding

private val viewModel by viewModels<FavoriteAnimeViewModel>()

private val favoriteAnimeController: EpoxyFavoriteAnimeController by lazy {
EpoxyFavoriteAnimeController(FavoriteAnimeCallbacks(viewModel))
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_favoriteAnimeFragmentBinding = FragmentFavoriteAnimeBinding.inflate(inflater, container, false)
return binding.root
}

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

private fun setupObservers() {
viewModel.favoriteAnimeListState.observe(viewLifecycleOwner) { result ->
when (result) {
is ResultWrapper.Success -> {
result.data?.let {
binding.noAnimeText.visibility = if (it.isEmpty()) View.VISIBLE else View.GONE
favoriteAnimeController.setData(it)
}
}
is ResultWrapper.Error -> Log.i("FAVORITES", result.message.toString())
is ResultWrapper.Loading -> {}
}

}
viewModel.navigation.observe(
viewLifecycleOwner,
EventObserver {
findNavController().navigate(it)
}
)
}

private fun setupRecyclerView() {
with(binding.favoriteAnimeList) {
layoutManager = GridLayoutManager(requireContext(), 3)
adapter = favoriteAnimeController.adapter
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package divyansh.tech.animeclassroom.favorites.screens.animes

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import divyansh.tech.animeclassroom.ResultWrapper
import divyansh.tech.animeclassroom.common.CommonViewModel
import divyansh.tech.animeclassroom.di.DispatcherModule
import divyansh.tech.animeclassroom.favorites.FavoriteAnimeLocalRepo
import divyansh.tech.animeclassroom.models.home.OfflineAnimeModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class FavoriteAnimeViewModel @Inject constructor(
favoriteAnimeLocalRepo: FavoriteAnimeLocalRepo,
@DispatcherModule.IODispatcher coroutineDispatcher: CoroutineDispatcher
): CommonViewModel() {

private val _favoriteAnimeListState: MutableLiveData<ResultWrapper<List<OfflineAnimeModel>>> =
MutableLiveData()
val favoriteAnimeListState: LiveData<ResultWrapper<List<OfflineAnimeModel>>> = _favoriteAnimeListState

init {
viewModelScope.launch(coroutineDispatcher) {
_favoriteAnimeListState.postValue(ResultWrapper.Loading())
_favoriteAnimeListState.postValue(
ResultWrapper.Success(favoriteAnimeLocalRepo.getAllAnime())
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package divyansh.tech.animeclassroom.favorites.screens.animes.epoxy

import com.airbnb.epoxy.TypedEpoxyController
import divyansh.tech.animeclassroom.common.AnimeClickCallback
import divyansh.tech.animeclassroom.models.home.OfflineAnimeModel

class EpoxyFavoriteAnimeController(
private val animeClickCallback: AnimeClickCallback
) : TypedEpoxyController<List<OfflineAnimeModel>>() {

override fun buildModels(data: List<OfflineAnimeModel>?) {
data?.let { offlineAnimeModels ->
offlineAnimeModels.forEach {
epoxyFavoriteAnime {
id(it.animeUrl)
anime(it)
animeCallback(animeClickCallback)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package divyansh.tech.animeclassroom.favorites.screens.animes.epoxy

import androidx.databinding.ViewDataBinding
import com.airbnb.epoxy.DataBindingEpoxyModel
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import divyansh.tech.animeclassroom.BR
import divyansh.tech.animeclassroom.R
import divyansh.tech.animeclassroom.common.AnimeClickCallback
import divyansh.tech.animeclassroom.models.home.OfflineAnimeModel

@EpoxyModelClass(layout = R.layout.recycler_item_favorite_anime)
abstract class EpoxyFavoriteAnimeModel : DataBindingEpoxyModel() {

@EpoxyAttribute
lateinit var anime: OfflineAnimeModel

@EpoxyAttribute
lateinit var animeCallback: AnimeClickCallback

override fun setDataBindingVariables(binding: ViewDataBinding) {
binding.setVariable(BR.anime, anime)
binding.setVariable(BR.animeCallback, animeCallback)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import divyansh.tech.animeclassroom.favorites.screens.DynamicTabFragment
import divyansh.tech.animeclassroom.favorites.screens.animes.FavoriteAnimeFragment


class ViewPagerAdapter(private val list: MutableList<Fragment> = mutableListOf(),
Expand All @@ -22,13 +23,10 @@ class ViewPagerAdapter(private val list: MutableList<Fragment> = mutableListOf()
return list[position]
}

fun addFragments(ls:List<String>){
fun addFragments(){
pageIds.clear()
ls.forEach {
category ->
list.add(DynamicTabFragment.getInstance(category))
}

list.add(FavoriteAnimeFragment.getInstance())
list.add(DynamicTabFragment.getInstance("Mangas"))
pageIds.addAll(list.map { it.hashCode().toLong() })
notifyDataSetChanged()
}
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/res/layout/fragment_favorite_anime.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/favoriteAnimeList"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/noAnimeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/empty_favorites_anime_list"
android:textColor="@color/recycler_anime_title"
android:textSize="14sp"
android:ellipsize="end"
android:minLines="2"
android:maxLines="2"
android:fontFamily="sans-serif"
android:visibility="gone"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
55 changes: 55 additions & 0 deletions app/src/main/res/layout/recycler_item_favorite_anime.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="anime"
type="divyansh.tech.animeclassroom.models.home.OfflineAnimeModel" />
<variable
name = "animeCallback"
type = "divyansh.tech.animeclassroom.common.AnimeClickCallback"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
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="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:foreground="?selectableItemBackgroundBorderless"
android:layout_marginBottom="20dp"
android:onClick="@{() -> animeCallback.onAnimeClicked(anime.animeUrl)}">
<androidx.cardview.widget.CardView
android:id="@+id/animeImageCardView"
android:layout_width="105dp"
android:layout_height="180dp"
app:cardCornerRadius="4dp"
app:cardElevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
imageUrl="@{anime.imageUrl}"
android:scaleType="centerCrop"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/animeTitle"
android:layout_width="0dp"
android:fontFamily="sans-serif"
android:layout_height="wrap_content"
android:ellipsize="end"
android:minLines="2"
android:maxLines="2"
android:layout_marginTop="4dp"
android:text="@{anime.name}"
android:textColor="@color/recycler_anime_title"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
android:gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/animeImageCardView"
tools:text="One Piece" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
6 changes: 5 additions & 1 deletion app/src/main/res/navigation/home_navigation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@
<fragment
android:id="@+id/favoritesFragment"
android:name="divyansh.tech.animeclassroom.favorites.FavoritesFragment"
android:label="FavoritesFragment" />
android:label="FavoritesFragment" >
<action
android:id="@+id/action_favoritesFragment_to_animeDetailFragment"
app:destination="@id/animeDetailFragment" />
</fragment>

<action
android:id="@+id/action_global_playerActivity"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@
<item>Night Mode</item>
<item>System</item>
</string-array>

<string name="empty_favorites_anime_list">Empty Favorite Animes List</string>
</resources>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
buildscript {
ext {
gradle_version="4.1.2"
kotlin_version="1.4.31"
kotlin_version="1.5.31"
core_ktx="1.3.2"
appcompat="1.2.0"
material="1.3.0"
Expand Down
2 changes: 2 additions & 0 deletions data/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ dependencies {

implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import divyansh.tech.animeclassroom.models.home.OfflineAnimeModel
@Dao
interface AnimeDao {
@Query("SELECT * FROM animes")
fun getAllAnimes(): List<OfflineAnimeModel>
suspend fun getAllAnimes(): List<OfflineAnimeModel>

@Insert
fun insertAnime(anime: OfflineAnimeModel)
suspend fun insertAnime(anime: OfflineAnimeModel)

@Delete
fun deleteAnime(anime: OfflineAnimeModel)
suspend fun deleteAnime(anime: OfflineAnimeModel)
}
3 changes: 3 additions & 0 deletions domain/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,7 @@ dependencies {

implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ class FavoriteAnimeLocalRepo @Inject constructor(
dao.insertAnime(model)
}

suspend fun getAllAnime() {
suspend fun getAllAnime(): List<OfflineAnimeModel> {
val list = dao.getAllAnimes()
Log.i("ROOM REPO -> ", list.toString())
return list
}
}

0 comments on commit df0b2cf

Please sign in to comment.