Skip to content

Commit

Permalink
Added ability to add movies to watchlist and mark them as watched fro…
Browse files Browse the repository at this point in the history
…m Movie Info screen. Also added feature to redirect to profile screen when the user clicks on the ProfileIcon or Username
  • Loading branch information
Mys7erio committed Apr 14, 2024
1 parent f8e3983 commit c392866
Show file tree
Hide file tree
Showing 21 changed files with 237 additions and 46 deletions.
15 changes: 1 addition & 14 deletions .idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ dependencies {
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

implementation("com.google.firebase:firebase-auth:22.3.1")
implementation("com.android.volley:volley:1.2.1")
implementation("androidx.activity:activity:1.8.2")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("com.android.volley:volley:1.2.1")
implementation("com.google.firebase:firebase-auth:22.3.1")
implementation("com.google.firebase:firebase-firestore-ktx:24.11.1")
}
13 changes: 12 additions & 1 deletion app/src/main/java/com/example/moviemate/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class HomeFragment : Fragment() {

tvHomeGreeting = view.findViewById(R.id.tvHomeGreeting)
ivHomeProfileImage = view.findViewById(R.id.ivHomeProfileImage)
tvHomeGreeting.setOnClickListener { navigateToProfile() }
ivHomeProfileImage.setOnClickListener { navigateToProfile() }

// auth = (activity as? MainActivity)?.auth ?: FirebaseAuth.getInstance()
// Fancy version feat. Typecasting, null safety OP. and elvis OP.
Expand Down Expand Up @@ -100,4 +102,13 @@ class HomeFragment : Fragment() {
}
}
}
}


private fun navigateToProfile() {
fragmentManager
.beginTransaction()
.replace(R.id.frame_container, ProfileFragment())
.addToBackStack(null)
.commit()
}
}
2 changes: 1 addition & 1 deletion app/src/main/java/com/example/moviemate/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import android.view.MenuItem
import androidx.fragment.app.Fragment
import com.google.firebase.auth.FirebaseAuth
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.firebase.firestore.FirebaseFirestore


class MainActivity : AppCompatActivity() {

private var apiKey: String = ""
lateinit var auth: FirebaseAuth
private lateinit var bottomNavigationBar: BottomNavigationView
Expand Down
114 changes: 111 additions & 3 deletions app/src/main/java/com/example/moviemate/MovieInfoFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,25 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.appcompat.widget.AppCompatRatingBar
import android.widget.TextView
import com.android.volley.RequestQueue
import com.android.volley.toolbox.Volley
import com.example.moviemate.api.getDocRefToUserCol
import com.example.moviemate.api.getMovieDetails
import com.example.moviemate.api.isMovieInUserCol
import com.example.moviemate.api.setImage
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import com.google.android.material.progressindicator.CircularProgressIndicator
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch


private const val imageBaseAPI = "https://image.tmdb.org/t/p"
Expand All @@ -27,12 +35,29 @@ private const val posterSize = "w300"
private const val backdropSize = "w780"

class MovieInfoFragment : Fragment() {
private var movieID: Int = 0
private val apiKey = BuildConfig.API_KEY
private lateinit var auth: FirebaseAuth
private lateinit var db: FirebaseFirestore

private lateinit var requestQueue: RequestQueue
private lateinit var movieInfoRootLayout: LinearLayout
private lateinit var loadingSpinner: CircularProgressIndicator

private var movieID = 0
private var posterUrl = ""
private var backdropUrl = ""
private var movieInWatchlist = false
private var movieInNotifList = false
private var movieAlreadyWatched = false

private lateinit var btnWatchlist: ImageButton
private lateinit var btnDoneWatching: ImageButton
private lateinit var btnNotify: ImageButton

private lateinit var tvNotifyLbl: TextView
private lateinit var tvWatchlistLbl: TextView
private lateinit var tvDoneWatchingLbl: TextView

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -42,22 +67,43 @@ class MovieInfoFragment : Fragment() {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_movie_info, container, false)

auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
movieID = arguments?.getString("MovieID")!!.toInt()
requestQueue = Volley.newRequestQueue(requireContext())
loadingSpinner = view.findViewById(R.id.cpiMovieDetail)
movieInfoRootLayout = view.findViewById(R.id.movieInfoRootLayout)

tvNotifyLbl = view.findViewById(R.id.tvMovieInfoNotify)
tvWatchlistLbl = view.findViewById(R.id.tvMovieInfoWatchlist)
tvDoneWatchingLbl = view.findViewById(R.id.tvMovieInfoDoneWatching)

btnWatchlist = view.findViewById(R.id.btnWatchlist)
btnDoneWatching = view.findViewById(R.id.btnMarkWatched)
btnNotify = view.findViewById(R.id.btnNotify)

// Run functions to check which collections the movies are in
CoroutineScope(Dispatchers.Main).launch {
movieInWatchlist = isMovieInUserCol(auth, db, "watchlist", movieID)
movieAlreadyWatched = isMovieInUserCol(auth, db, "doneWatching", movieID)
modifyBtnStates()
}

getMovieDetails(requestQueue, apiKey, movieID) { movieDetails ->

btnDoneWatching.setOnClickListener { handleBtnDoneWatchingClicked() }
btnWatchlist.setOnClickListener { handleBtnWatchlistClicked() }
btnNotify.setOnClickListener { handleBtnNotifyClicked() }

val tvMovieTitle: TextView = view.findViewById(R.id.tvMovieDetailMovieTitle)
val ivMoviePoster: ImageView = view.findViewById(R.id.ivMovieDetailMoviePoster)
val ivMovieBackdrop: ImageView = view.findViewById(R.id.ivMovieDetailMovieBackdrop)
val tvMovieOverview: TextView = view.findViewById(R.id.tvMovieDetailMovieOverview)
val rbMovieRating: AppCompatRatingBar = view.findViewById(R.id.rbMovieInfoMovieRating)
val chipGroup: ChipGroup = view.findViewById(R.id.cgMovieDetailsGenres)

val posterUrl = "$imageBaseAPI/$posterSize/${movieDetails.posterPath}"
val backdropUrl = "$imageBaseAPI/$backdropSize/${movieDetails.backdropPath}"
posterUrl = "$imageBaseAPI/$posterSize${movieDetails.posterPath}"
backdropUrl = "$imageBaseAPI/$backdropSize${movieDetails.backdropPath}"

// Set poster and backdrop
setImage(requestQueue, posterUrl) { posterBitmap ->
Expand Down Expand Up @@ -86,4 +132,66 @@ class MovieInfoFragment : Fragment() {

return view
}


private fun modifyBtnStates() {
// Set icon and text for Watchlist
tvWatchlistLbl.text = if (movieInWatchlist) "Remove from Watchlist" else "Save to Watchlist"
btnWatchlist.setImageResource(
if (movieInWatchlist) R.drawable.ic_bookmark_filled
else R.drawable.ic_bookmark_outlined
)

// Set icon and text for Done Watching
tvDoneWatchingLbl.text = if (movieAlreadyWatched) "Mark as Unwatched" else "Mark as Watched"
btnDoneWatching.setImageResource(
if (movieAlreadyWatched) R.drawable.ic_check_circle_filled
else R.drawable.ic_check_circle_outline
) // @formatter:on


// Set icon and text for Notifications
tvNotifyLbl.text = if (movieInNotifList) "Cancel Notifications" else "Notify"
btnNotify.setImageResource(
if (movieInNotifList) R.drawable.ic_notification_circle_filled
else R.drawable.ic_notification_circle_outlined
)
}

private fun handleBtnWatchlistClicked() {
val docRef = getDocRefToUserCol(auth, db, "watchlist", movieID)
val movieData = hashMapOf(
"poster_path" to posterUrl,
"backdrop_path" to backdropUrl
)

// Add movie to watchlist if it's not there, otherwise delete it
if (movieInWatchlist) docRef.delete()
else docRef.set(movieData)

// Update visual state of the button
movieInWatchlist = !movieInWatchlist
modifyBtnStates()
}

private fun handleBtnDoneWatchingClicked() {
val docRef = getDocRefToUserCol(auth, db, "doneWatching", movieID)
val movieData = hashMapOf(
"poster_path" to posterUrl,
"backdrop_path" to backdropUrl
)

// Add movie to watchlist if it's not there, otherwise delete it
if (movieAlreadyWatched) docRef.delete()
else docRef.set(movieData)

// Update visual state of the button
movieAlreadyWatched = !movieAlreadyWatched
modifyBtnStates()
}

private fun handleBtnNotifyClicked() {
movieInNotifList = !movieInNotifList
modifyBtnStates()
}
}
40 changes: 40 additions & 0 deletions app/src/main/java/com/example/moviemate/api/FirebaseHelper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.example.moviemate.api

import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.coroutines.tasks.await


// Check if movie is in user collection
suspend fun isMovieInUserCol(
auth: FirebaseAuth,
db: FirebaseFirestore,
collectionName: String,
movieID: Int
): Boolean {
val userEmail = auth.currentUser!!.email.toString()
val docRef = db.collection("users")
.document(userEmail)
.collection(collectionName)
.document(movieID.toString())

val docSnapshot = docRef.get().await()
return docSnapshot.exists()
}


// Get reference to document in user collection
fun getDocRefToUserCol(
auth: FirebaseAuth,
db: FirebaseFirestore,
collectionName: String,
movieID: Int,
): DocumentReference {
val userEmail = auth.currentUser!!.email.toString()

return db.collection("users")
.document(userEmail)
.collection(collectionName)
.document(movieID.toString())
}
Binary file removed app/src/main/res/drawable/dune_background.jpg
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
<vector android:height="32dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_check_circle_filled.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="32dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="32dp">

<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>

</vector>
File renamed without changes.
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_notification_circle_filled.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="32dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="32dp">

<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,18.5c-0.83,0 -1.5,-0.67 -1.5,-1.5h3c0,0.83 -0.67,1.5 -1.5,1.5zM17,16L7,16v-1l1,-1v-2.61C8,9.27 9.03,7.47 11,7v-0.5c0,-0.57 0.43,-1 1,-1s1,0.43 1,1L13,7c1.97,0.47 3,2.28 3,4.39L16,14l1,1v1z"/>

</vector>
File renamed without changes.
2 changes: 1 addition & 1 deletion app/src/main/res/layout/fragment_home.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
android:layout_width="48sp"
android:layout_height="48sp"
android:importantForAccessibility="no"
android:src="@drawable/ic_user_circle" />
android:src="@drawable/ic_user_circle_filled" />

</androidx.cardview.widget.CardView>

Expand Down
Loading

0 comments on commit c392866

Please sign in to comment.