From f908f71a7e7af7b6046b911f716553ef71ad52cb Mon Sep 17 00:00:00 2001 From: parneet-guraya Date: Sun, 15 Dec 2024 22:42:58 +0530 Subject: [PATCH] database setup and insert/delete working Signed-off-by: parneet-guraya --- .../category/BookmarkCategoriesDao.kt | 26 +++++++ .../category/BookmarkCategoriesFragment.kt | 26 +++++++ .../category/BookmarkCategoriesViewModel.kt | 9 +++ .../models/BookmarksCategoryModal.kt | 9 +++ .../category/CategoryDetailsActivity.kt | 45 +++++++++++ .../category/CategoryDetailsViewModel.kt | 77 +++++++++++++++++++ .../fr/free/nrw/commons/db/AppDatabase.kt | 6 +- .../commons/di/CommonsApplicationModule.kt | 5 ++ .../layout/fragment_bookmark_categories.xml | 14 ++++ .../res/menu/fragment_category_detail.xml | 7 ++ 10 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesDao.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesFragment.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesViewModel.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/bookmarks/models/BookmarksCategoryModal.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsViewModel.kt create mode 100644 app/src/main/res/layout/fragment_bookmark_categories.xml diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesDao.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesDao.kt new file mode 100644 index 000000000..870c0556f --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesDao.kt @@ -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> + +} diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesFragment.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesFragment.kt new file mode 100644 index 000000000..7e5c04db9 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesFragment.kt @@ -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() + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesViewModel.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesViewModel.kt new file mode 100644 index 000000000..5967813b3 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/category/BookmarkCategoriesViewModel.kt @@ -0,0 +1,9 @@ +package fr.free.nrw.commons.bookmarks.category + +class BookmarkCategoriesViewModel( + +) { + + + +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/models/BookmarksCategoryModal.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/models/BookmarksCategoryModal.kt new file mode 100644 index 000000000..295803720 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/models/BookmarksCategoryModal.kt @@ -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 +) \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt index ba1fcfdae..13934d774 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt @@ -7,8 +7,12 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.View +import androidx.activity.viewModels import androidx.fragment.app.Fragment 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.R 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.media.MediaDetailPagerFragment 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 + @Inject + lateinit var categoryViewModelFactory: CategoryDetailsViewModel.ViewModelFactory + + private val viewModel: CategoryDetailsViewModel by viewModels { categoryViewModelFactory } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -53,6 +64,15 @@ class CategoryDetailsActivity : BaseActivity(), supportActionBar?.setDisplayHomeAsUpEnabled(true) setTabs() setPageTitle() + + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED){ + viewModel.bookmarkState.collect { + invalidateOptionsMenu() + } + } + } + } /** @@ -73,6 +93,8 @@ class CategoryDetailsActivity : BaseActivity(), categoriesMediaFragment.arguments = arguments subCategoryListFragment.arguments = arguments parentCategoriesFragment.arguments = arguments + + viewModel.onCheckIfBookmarked(categoryName!!) } fragmentList.add(categoriesMediaFragment) titleList.add("MEDIA") @@ -181,6 +203,15 @@ class CategoryDetailsActivity : BaseActivity(), Utils.handleWebUrl(this, Uri.parse(title.canonicalUri)) 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 -> { onBackPressed() 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. * If condition is called when mediaDetailFragment is opened. diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsViewModel.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsViewModel.kt new file mode 100644 index 000000000..fd3220b0e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsViewModel.kt @@ -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 create(modelClass: Class): T = + if (modelClass.isAssignableFrom(CategoryDetailsViewModel::class.java)) { + CategoryDetailsViewModel(bookmarkCategoriesDao) as T + } else { + throw IllegalArgumentException("Unknown class name") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt index 71947fa1a..6222f2462 100644 --- a/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt +++ b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt @@ -3,6 +3,8 @@ package fr.free.nrw.commons.db import androidx.room.Database import androidx.room.RoomDatabase 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.ContributionDao import fr.free.nrw.commons.customselector.database.NotForUploadStatus @@ -21,7 +23,7 @@ import fr.free.nrw.commons.upload.depicts.DepictsDao * */ @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, exportSchema = false, ) @@ -38,4 +40,6 @@ abstract class AppDatabase : RoomDatabase() { abstract fun NotForUploadStatusDao(): NotForUploadStatusDao abstract fun ReviewDao(): ReviewDao + + abstract fun bookmarkCategoriesDao(): BookmarkCategoriesDao } diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.kt b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.kt index b195674a9..58d9039d5 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.kt +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.kt @@ -15,6 +15,7 @@ import dagger.Provides import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.R 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.customselector.database.NotForUploadStatusDao import fr.free.nrw.commons.customselector.database.UploadedStatusDao @@ -221,6 +222,10 @@ open class CommonsApplicationModule(private val applicationContext: Context) { fun providesReviewDao(appDatabase: AppDatabase): ReviewDao = appDatabase.ReviewDao() + @Provides + fun providesBookmarkCategoriesDao (appDatabase: AppDatabase): BookmarkCategoriesDao = + appDatabase.bookmarkCategoriesDao() + @Provides fun providesContentResolver(context: Context): ContentResolver = context.contentResolver diff --git a/app/src/main/res/layout/fragment_bookmark_categories.xml b/app/src/main/res/layout/fragment_bookmark_categories.xml new file mode 100644 index 000000000..5838e8b03 --- /dev/null +++ b/app/src/main/res/layout/fragment_bookmark_categories.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/fragment_category_detail.xml b/app/src/main/res/menu/fragment_category_detail.xml index 386e678fd..b3663ee97 100644 --- a/app/src/main/res/menu/fragment_category_detail.xml +++ b/app/src/main/res/menu/fragment_category_detail.xml @@ -2,6 +2,13 @@ + + +