Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ dependencies {
// Moshi
implementation 'com.squareup.moshi:moshi:1.9.2'

implementation 'com.github.bumptech.glide:glide:4.11.0'

// MaterialColors
implementation 'com.theah64.materialcolors:materialcolors:1.0.0'
Expand Down
10 changes: 3 additions & 7 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
android:usesCleartextTraffic="true"
tools:ignore="GoogleAppIndexingWarning"
tools:targetApi="m">

<activity android:name=".ui.activities.favorites.FavoritesActivity"></activity>
<!-- Splash -->
<activity
android:name=".ui.activities.splash.SplashActivity"
Expand All @@ -26,15 +26,11 @@

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- Main -->
</activity> <!-- Main -->
<activity
android:name=".ui.activities.feed.FeedActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar" />

<!-- Movie -->
android:theme="@style/AppTheme.NoActionBar" /> <!-- Movie -->
<activity
android:name=".ui.activities.movie.MovieActivity"
android:theme="@style/AppTheme.NoActionBar" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import androidx.room.TypeConverters
import com.theapache64.topcorn.data.local.daos.MoviesDao
import com.theapache64.topcorn.data.remote.Movie

@Database(entities = [Movie::class], version = 1)
@Database(entities = [Movie::class, FavoriteMovie::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun movieDao(): MoviesDao
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.theapache64.topcorn.data.local

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.squareup.moshi.Json

@Entity(tableName = "favorites")
data class FavoriteMovie(
@Json(name = "actors")
val actors: List<String>?,
@Json(name = "desc")
val desc: String?,
@Json(name = "directors")
val directors: List<String>?,
@Json(name = "genre")
val genre: List<String>?,
@Json(name = "image_url")
val imageUrl: String?,
@Json(name = "thumb_url")
val thumbUrl: String?,
@Json(name = "imdb_url")
val imdbUrl: String?,
@Json(name = "name")
val name: String?,
@Json(name = "rating")
val rating: Float?,
@Json(name = "year")
val year: Int?
) {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
var id: Long = 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.theapache64.topcorn.data.local.daos

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.theapache64.topcorn.data.local.FavoriteMovie
import com.theapache64.topcorn.data.remote.Movie
import kotlinx.coroutines.flow.Flow

Expand All @@ -16,4 +18,13 @@ interface MoviesDao {

@Insert
fun addAll(data: List<Movie>)

@Query("SELECT * FROM favorites")
suspend fun getAllFavoriteMovies(): List<FavoriteMovie>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(favoriteMovie: FavoriteMovie)

@Query("DELETE FROM favorites WHERE imageUrl = :url")
suspend fun deleteByUrl(url: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.theapache64.topcorn.data.repositories.movies

import android.content.SharedPreferences
import androidx.core.content.edit
import com.theapache64.topcorn.data.local.FavoriteMovie
import com.theapache64.topcorn.data.local.daos.MoviesDao
import com.theapache64.topcorn.data.remote.ApiInterface
import com.theapache64.topcorn.data.remote.Movie
Expand All @@ -10,6 +11,8 @@ import com.theapache64.topcorn.utils.test.OpenForTesting
import com.theapache64.twinkill.network.utils.Resource
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import javax.inject.Inject
Expand Down Expand Up @@ -61,6 +64,20 @@ class MoviesRepo @Inject constructor(
}.asFlow().flowOn(Dispatchers.IO)
}

suspend fun getAllFavoriteMovies() = moviesDao.getAllFavoriteMovies()

suspend fun insertToFavoritesAsync(favoriteMovie: FavoriteMovie) = coroutineScope {
async {
moviesDao.insert(favoriteMovie)
}
}

suspend fun deleteByUrlAsync(url: String) = coroutineScope {
async {
moviesDao.deleteByUrl(url)
}
}

@ExperimentalTime
private fun isExpired(lastSynced: Long): Boolean {
val currentTime = System.currentTimeMillis()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.theapache64.topcorn.di.modules


import com.theapache64.topcorn.ui.activities.favorites.FavoritesActivity
import com.theapache64.topcorn.ui.activities.feed.FeedActivity
import com.theapache64.topcorn.ui.activities.movie.MovieActivity
import com.theapache64.topcorn.ui.activities.splash.SplashActivity
Expand All @@ -22,4 +23,7 @@ abstract class ActivitiesBuilderModule {
@ContributesAndroidInjector
abstract fun getMovieActivity(): MovieActivity

@ContributesAndroidInjector
abstract fun getFavoritesActivity(): FavoritesActivity

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.theapache64.topcorn.di.modules

import androidx.lifecycle.ViewModel
import com.theapache64.topcorn.ui.activities.favorites.FavoritesViewModel
import com.theapache64.topcorn.ui.activities.feed.FeedViewModel
import com.theapache64.topcorn.ui.activities.movie.MovieViewModel
import com.theapache64.topcorn.ui.activities.splash.SplashViewModel
Expand Down Expand Up @@ -33,4 +34,9 @@ abstract class ViewModelModule {
@ViewModelKey(MovieViewModel::class)
abstract fun bindMovieViewModel(viewModel: MovieViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(FavoritesViewModel::class)
abstract fun bindFavoritesViewModel(viewModel: FavoritesViewModel): ViewModel

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.theapache64.topcorn.ui.activities.favorites

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import android.view.View.GONE
import android.view.View.VISIBLE
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.theapache64.topcorn.R
import com.theapache64.topcorn.ui.activities.movie.MovieActivity
import com.theapache64.topcorn.ui.adapters.FavoritesAdapter
import dagger.android.AndroidInjection
import kotlinx.android.synthetic.main.activity_favorites.*
import javax.inject.Inject

class FavoritesActivity : AppCompatActivity() {

@Inject
lateinit var factory: ViewModelProvider.Factory
private lateinit var viewModel: FavoritesViewModel

override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_favorites)

supportActionBar?.apply {
setDisplayHomeAsUpEnabled(true)
setDisplayShowHomeEnabled(true)
setTitle(R.string.favorites)
}

viewModel = ViewModelProvider(this, factory).get(FavoritesViewModel::class.java)

viewModel.favoritesMovies.observe(this, Observer {
favorites_recycler.adapter = FavoritesAdapter(it) { movie ->
startActivity(MovieActivity.getStartIntent(this, movie))
}
})

viewModel.isListEmpty.observe(this, Observer { empty ->
empty_text.visibility = if (empty) VISIBLE else GONE
})
}

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

override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) onBackPressed()
return super.onOptionsItemSelected(item)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.theapache64.topcorn.ui.activities.favorites

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.theapache64.topcorn.data.local.FavoriteMovie
import com.theapache64.topcorn.data.repositories.movies.MoviesRepo
import kotlinx.coroutines.launch
import javax.inject.Inject

class FavoritesViewModel @Inject constructor(
private val moviesRepo: MoviesRepo
) : ViewModel() {

val favoritesMovies = MutableLiveData<List<FavoriteMovie>>()
val isListEmpty = MutableLiveData<Boolean>()

fun getFavorites() {
viewModelScope.launch {
val favorites = moviesRepo.getAllFavoriteMovies()
favoritesMovies.postValue(favorites)
isListEmpty.value = favorites.isNullOrEmpty()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.theapache64.topcorn.R
import com.theapache64.topcorn.data.remote.Movie
import com.theapache64.topcorn.databinding.ActivityFeedBinding
import com.theapache64.topcorn.ui.activities.favorites.FavoritesActivity
import com.theapache64.topcorn.ui.activities.movie.MovieActivity
import com.theapache64.topcorn.ui.adapters.FeedAdapter
import com.theapache64.twinkill.logger.info
Expand Down Expand Up @@ -94,13 +95,8 @@ class FeedActivity : BaseAppCompatActivity() {
AppCompatDelegate.setDefaultNightMode(darkModeFlag)
})

// Watching for github home
viewModel.openGithub.observe(this, Observer {
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse(GITHUB_URL)
)
startActivity(intent)
viewModel.openFavorites.observe(this, Observer {
startActivity(Intent(this, FavoritesActivity::class.java))
})

// Watching for toast
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class FeedViewModel @Inject constructor(
private val _toast = MutableLiveData<Int>()
val toast: LiveData<Int> = _toast

val openGithub = SingleLiveEvent<Boolean>()
val openFavorites = SingleLiveEvent<Boolean>()

private val sortedOrder = MutableLiveData<Int>()

Expand Down Expand Up @@ -115,7 +115,7 @@ class FeedViewModel @Inject constructor(
}

fun onHeartClicked() {
openGithub.value = true
openFavorites.value = true
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.theapache64.topcorn.databinding.ActivityMovieBinding
import com.theapache64.twinkill.ui.activities.base.BaseAppCompatActivity
import com.theapache64.twinkill.utils.extensions.bindContentView
import dagger.android.AndroidInjection
import kotlinx.android.synthetic.main.activity_movie.*
import javax.inject.Inject

class MovieActivity : BaseAppCompatActivity() {
Expand Down Expand Up @@ -44,6 +45,10 @@ class MovieActivity : BaseAppCompatActivity() {
val movie = intent.getSerializableExtra(KEY_MOVIE) as Movie
viewModel.init(movie)

viewModel.isFavorite.observe(this, Observer {
ib_favorite_toggle.setImageResource(if (it) R.drawable.ic_star_24 else R.drawable.ic_star_border_24)
})

viewModel.closeActivity.observe(this, Observer {
finish()
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
package com.theapache64.topcorn.ui.activities.movie

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.theapache64.topcorn.data.local.FavoriteMovie
import com.theapache64.topcorn.data.remote.Movie
import com.theapache64.topcorn.data.repositories.movies.MoviesRepo
import com.theapache64.twinkill.utils.livedata.SingleLiveEvent
import kotlinx.coroutines.launch
import javax.inject.Inject

class MovieViewModel @Inject constructor() : ViewModel() {
class MovieViewModel @Inject constructor(
private val moviesRepo: MoviesRepo
) : ViewModel() {

val isFavorite = MutableLiveData<Boolean>()

fun init(movie: Movie) {
this.movie = movie
viewModelScope.launch {
val favorites = moviesRepo.getAllFavoriteMovies()
isFavorite.postValue(favorites.any { it.imageUrl == movie.imageUrl })
}
}

val openImdb = SingleLiveEvent<Boolean>()
Expand All @@ -19,6 +32,31 @@ class MovieViewModel @Inject constructor() : ViewModel() {
closeActivity.value = true
}

fun onFavoriteButtonClicked() {
viewModelScope.launch {
when (isFavorite.value) {
false -> {
moviesRepo.insertToFavoritesAsync(
FavoriteMovie(
movie?.actors,
movie?.desc,
movie?.directors,
movie?.genre,
movie?.imageUrl,
movie?.thumbUrl,
movie?.imdbUrl,
movie?.name,
movie?.rating,
movie?.year
)
)
}
true -> moviesRepo.deleteByUrlAsync(movie?.imageUrl ?: "")
}
}
isFavorite.value = isFavorite.value != true
}

fun onGoToImdbClicked() {
openImdb.value = true
}
Expand Down
Loading