database setup and insert/delete working

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>
This commit is contained in:
parneet-guraya 2024-12-15 22:42:58 +05:30
parent 0153cbe0ed
commit f908f71a7e
No known key found for this signature in database
GPG key ID: 63B807C4B2A9064B
10 changed files with 223 additions and 1 deletions

View file

@ -0,0 +1,26 @@
package fr.free.nrw.commons.bookmarks.category
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import fr.free.nrw.commons.bookmarks.models.BookmarksCategoryModal
import kotlinx.coroutines.flow.Flow
@Dao
interface BookmarkCategoriesDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(bookmarksCategoryModal: BookmarksCategoryModal)
@Delete
suspend fun delete(bookmarksCategoryModal: BookmarksCategoryModal)
@Query("SELECT EXISTS (SELECT 1 FROM bookmarks_categories WHERE categoryName = :categoryName)")
suspend fun doesExist(categoryName: String): Boolean
@Query("SELECT * FROM bookmarks_categories")
fun getAllCategories(): Flow<List<BookmarksCategoryModal>>
}

View file

@ -0,0 +1,26 @@
package fr.free.nrw.commons.bookmarks.category
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import fr.free.nrw.commons.R
class BookmarkCategoriesFragment : DaggerFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bookmark_categories, container, false)
}
companion object {
@JvmStatic
fun newInstance(param1: String, param2: String) =
BookmarkCategoriesFragment()
}
}

View file

@ -0,0 +1,9 @@
package fr.free.nrw.commons.bookmarks.category
class BookmarkCategoriesViewModel(
) {
}

View file

@ -0,0 +1,9 @@
package fr.free.nrw.commons.bookmarks.models
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "bookmarks_categories")
data class BookmarksCategoryModal(
@PrimaryKey val categoryName: String
)

View file

@ -7,8 +7,12 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.activity.viewModels
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import fr.free.nrw.commons.Media import fr.free.nrw.commons.Media
import fr.free.nrw.commons.R import fr.free.nrw.commons.R
import fr.free.nrw.commons.Utils import fr.free.nrw.commons.Utils
@ -19,6 +23,8 @@ import fr.free.nrw.commons.explore.categories.parent.ParentCategoriesFragment
import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment
import fr.free.nrw.commons.media.MediaDetailPagerFragment import fr.free.nrw.commons.media.MediaDetailPagerFragment
import fr.free.nrw.commons.theme.BaseActivity import fr.free.nrw.commons.theme.BaseActivity
import kotlinx.coroutines.launch
import javax.inject.Inject
/** /**
@ -38,6 +44,11 @@ class CategoryDetailsActivity : BaseActivity(),
private lateinit var binding: ActivityCategoryDetailsBinding private lateinit var binding: ActivityCategoryDetailsBinding
@Inject
lateinit var categoryViewModelFactory: CategoryDetailsViewModel.ViewModelFactory
private val viewModel: CategoryDetailsViewModel by viewModels<CategoryDetailsViewModel> { categoryViewModelFactory }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -53,6 +64,15 @@ class CategoryDetailsActivity : BaseActivity(),
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
setTabs() setTabs()
setPageTitle() setPageTitle()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED){
viewModel.bookmarkState.collect {
invalidateOptionsMenu()
}
}
}
} }
/** /**
@ -73,6 +93,8 @@ class CategoryDetailsActivity : BaseActivity(),
categoriesMediaFragment.arguments = arguments categoriesMediaFragment.arguments = arguments
subCategoryListFragment.arguments = arguments subCategoryListFragment.arguments = arguments
parentCategoriesFragment.arguments = arguments parentCategoriesFragment.arguments = arguments
viewModel.onCheckIfBookmarked(categoryName!!)
} }
fragmentList.add(categoriesMediaFragment) fragmentList.add(categoriesMediaFragment)
titleList.add("MEDIA") titleList.add("MEDIA")
@ -181,6 +203,15 @@ class CategoryDetailsActivity : BaseActivity(),
Utils.handleWebUrl(this, Uri.parse(title.canonicalUri)) Utils.handleWebUrl(this, Uri.parse(title.canonicalUri))
true true
} }
R.id.menu_bookmark_current_category -> {
//TODO: most likely won't be null
categoryName?.let {
viewModel.onBookmarkClick(categoryName = it)
}
true
}
android.R.id.home -> { android.R.id.home -> {
onBackPressed() onBackPressed()
true true
@ -189,6 +220,20 @@ class CategoryDetailsActivity : BaseActivity(),
} }
} }
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
menu?.run {
val bookmarkMenuItem = findItem(R.id.menu_bookmark_current_category)
val icon = if(viewModel.bookmarkState.value){
R.drawable.menu_ic_round_star_filled_24px
} else {
R.drawable.menu_ic_round_star_border_24px
}
bookmarkMenuItem.setIcon(icon)
}
return super.onPrepareOptionsMenu(menu)
}
/** /**
* This method is called on backPressed of anyFragment in the activity. * This method is called on backPressed of anyFragment in the activity.
* If condition is called when mediaDetailFragment is opened. * If condition is called when mediaDetailFragment is opened.

View file

@ -0,0 +1,77 @@
package fr.free.nrw.commons.category
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import fr.free.nrw.commons.bookmarks.category.BookmarkCategoriesDao
import fr.free.nrw.commons.bookmarks.models.BookmarksCategoryModal
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
class CategoryDetailsViewModel(
private val bookmarkCategoriesDao: BookmarkCategoriesDao
) : ViewModel() {
private val _bookmarkState = MutableStateFlow(false)
val bookmarkState = _bookmarkState.asStateFlow()
fun onCheckIfBookmarked(categoryName: String) {
viewModelScope.launch {
val isBookmarked = bookmarkCategoriesDao.doesExist(categoryName)
_bookmarkState.update {
isBookmarked
}
}
}
fun onBookmarkClick(categoryName: String) {
if (_bookmarkState.value) {
deleteBookmark(categoryName)
_bookmarkState.update {
false
}
} else {
addBookmark(categoryName)
_bookmarkState.update {
true
}
}
}
private fun addBookmark(categoryName: String) {
viewModelScope.launch {
// TODO [Parry] view only knows about `name` see if we can have more data
val categoryItem = BookmarksCategoryModal(
categoryName = categoryName
)
bookmarkCategoriesDao.insert(categoryItem)
}
}
private fun deleteBookmark(categoryName: String) {
viewModelScope.launch {
bookmarkCategoriesDao.delete(
BookmarksCategoryModal(
categoryName = categoryName
)
)
}
}
class ViewModelFactory @Inject constructor(
private val bookmarkCategoriesDao: BookmarkCategoriesDao
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T =
if (modelClass.isAssignableFrom(CategoryDetailsViewModel::class.java)) {
CategoryDetailsViewModel(bookmarkCategoriesDao) as T
} else {
throw IllegalArgumentException("Unknown class name")
}
}
}

View file

@ -3,6 +3,8 @@ package fr.free.nrw.commons.db
import androidx.room.Database import androidx.room.Database
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters import androidx.room.TypeConverters
import fr.free.nrw.commons.bookmarks.category.BookmarkCategoriesDao
import fr.free.nrw.commons.bookmarks.models.BookmarksCategoryModal
import fr.free.nrw.commons.contributions.Contribution import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.contributions.ContributionDao import fr.free.nrw.commons.contributions.ContributionDao
import fr.free.nrw.commons.customselector.database.NotForUploadStatus import fr.free.nrw.commons.customselector.database.NotForUploadStatus
@ -21,7 +23,7 @@ import fr.free.nrw.commons.upload.depicts.DepictsDao
* *
*/ */
@Database( @Database(
entities = [Contribution::class, Depicts::class, UploadedStatus::class, NotForUploadStatus::class, ReviewEntity::class, Place::class], entities = [Contribution::class, Depicts::class, UploadedStatus::class, NotForUploadStatus::class, ReviewEntity::class, Place::class, BookmarksCategoryModal::class],
version = 18, version = 18,
exportSchema = false, exportSchema = false,
) )
@ -38,4 +40,6 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun NotForUploadStatusDao(): NotForUploadStatusDao abstract fun NotForUploadStatusDao(): NotForUploadStatusDao
abstract fun ReviewDao(): ReviewDao abstract fun ReviewDao(): ReviewDao
abstract fun bookmarkCategoriesDao(): BookmarkCategoriesDao
} }

View file

@ -15,6 +15,7 @@ import dagger.Provides
import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.BuildConfig
import fr.free.nrw.commons.R import fr.free.nrw.commons.R
import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.bookmarks.category.BookmarkCategoriesDao
import fr.free.nrw.commons.contributions.ContributionDao import fr.free.nrw.commons.contributions.ContributionDao
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao
import fr.free.nrw.commons.customselector.database.UploadedStatusDao import fr.free.nrw.commons.customselector.database.UploadedStatusDao
@ -221,6 +222,10 @@ open class CommonsApplicationModule(private val applicationContext: Context) {
fun providesReviewDao(appDatabase: AppDatabase): ReviewDao = fun providesReviewDao(appDatabase: AppDatabase): ReviewDao =
appDatabase.ReviewDao() appDatabase.ReviewDao()
@Provides
fun providesBookmarkCategoriesDao (appDatabase: AppDatabase): BookmarkCategoriesDao =
appDatabase.bookmarkCategoriesDao()
@Provides @Provides
fun providesContentResolver(context: Context): ContentResolver = fun providesContentResolver(context: Context): ContentResolver =
context.contentResolver context.contentResolver

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".bookmarks.category.BookmarkCategoriesFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>

View file

@ -2,6 +2,13 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_bookmark_current_category"
android:icon="@drawable/menu_icon_bookmark_selector"
android:title="@string/menu_bookmark"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/menu_browser_current_category" android:id="@+id/menu_browser_current_category"
android:title="@string/menu_view_category_page" android:title="@string/menu_view_category_page"