mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-17 23:47:02 +05:30
src: remove cache and simplify db logic
Signed-off-by: Aditya Wasan <adityawasan55@gmail.com>
This commit is contained in:
parent
3bcdcbdac7
commit
f9fcb089a1
7 changed files with 60 additions and 23 deletions
|
@ -14,9 +14,17 @@ class LobstersPagingSource @Inject constructor(
|
||||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
|
||||||
return try {
|
return try {
|
||||||
val page = params.key ?: 1
|
val page = params.key ?: 1
|
||||||
val savedPosts = lobstersRepository.getCachedPosts()
|
|
||||||
val posts = lobstersApi.getHottestPosts(page).map { post ->
|
val posts = lobstersApi.getHottestPosts(page).map { post ->
|
||||||
post.copy(is_saved = savedPosts.contains(post.short_id))
|
// We can replace these two lines below with a getOrInsertPost repository method.
|
||||||
|
val dbPost = lobstersRepository.getPost(post.short_id)
|
||||||
|
return@map if (dbPost == null) {
|
||||||
|
// If db does not contain the post, add it and return the original post
|
||||||
|
lobstersRepository.addPostToDB(post)
|
||||||
|
post
|
||||||
|
} else {
|
||||||
|
// Otherwise return the db post
|
||||||
|
dbPost
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadResult.Page(
|
LoadResult.Page(
|
||||||
|
|
|
@ -8,32 +8,33 @@ import javax.inject.Inject
|
||||||
|
|
||||||
class LobstersRepository @Inject constructor(private val lobstersDatabase: LobstersDatabase) {
|
class LobstersRepository @Inject constructor(private val lobstersDatabase: LobstersDatabase) {
|
||||||
|
|
||||||
private var savedPostCache: MutableSet<String>? = null
|
|
||||||
|
|
||||||
fun isPostSaved(postId: String): Boolean {
|
fun isPostSaved(postId: String): Boolean {
|
||||||
savedPostCache ?: return false
|
// returns the post if it exists and its is_saved property is true
|
||||||
return requireNotNull(savedPostCache).contains(postId)
|
val post = lobstersDatabase.postQueries.isPostSaved(postId).executeAsOneOrNull()
|
||||||
|
return post != null
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getPost(postId: String): LobstersPost? = withContext(Dispatchers.IO) {
|
||||||
|
return@withContext lobstersDatabase.postQueries.selectPost(postId).executeAsOneOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSavedPosts(): List<LobstersPost> = withContext(Dispatchers.IO) {
|
||||||
|
return@withContext lobstersDatabase.postQueries.selectSavedPosts().executeAsList()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun addPostToDB(post: LobstersPost) = withContext(Dispatchers.IO) {
|
||||||
|
lobstersDatabase.postQueries.insertOrReplacePost(post)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun savePost(post: LobstersPost) = withContext(Dispatchers.IO) {
|
suspend fun savePost(post: LobstersPost) = withContext(Dispatchers.IO) {
|
||||||
val isElementAdded = getCachedPosts().add(post.short_id)
|
if (!isPostSaved(post.short_id)) {
|
||||||
if (isElementAdded) {
|
|
||||||
lobstersDatabase.postQueries.savePost(post.short_id)
|
lobstersDatabase.postQueries.savePost(post.short_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun removeSavedPost(post: LobstersPost) = withContext(Dispatchers.IO) {
|
suspend fun removeSavedPost(post: LobstersPost) = withContext(Dispatchers.IO) {
|
||||||
val isElementRemoved = getCachedPosts().remove(post.short_id)
|
if (isPostSaved(post.short_id)) {
|
||||||
if (isElementRemoved) {
|
|
||||||
lobstersDatabase.postQueries.removeSavedPost(post.short_id)
|
lobstersDatabase.postQueries.removeSavedPost(post.short_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCachedPosts(): MutableSet<String> = withContext(Dispatchers.IO) {
|
|
||||||
if (savedPostCache != null) return@withContext requireNotNull(savedPostCache)
|
|
||||||
|
|
||||||
val dbPosts = lobstersDatabase.postQueries.selectSavedPosts().executeAsList()
|
|
||||||
savedPostCache = dbPosts.filter { it.is_saved ?: false }.map { it.short_id }.toMutableSet()
|
|
||||||
return@withContext requireNotNull(savedPostCache)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,17 +12,20 @@ import dev.msfjarvis.lobsters.data.local.LobstersPost
|
||||||
import dev.msfjarvis.lobsters.database.LobstersDatabase
|
import dev.msfjarvis.lobsters.database.LobstersDatabase
|
||||||
import dev.msfjarvis.lobsters.model.SubmitterAdapter
|
import dev.msfjarvis.lobsters.model.SubmitterAdapter
|
||||||
import dev.msfjarvis.lobsters.model.TagsAdapter
|
import dev.msfjarvis.lobsters.model.TagsAdapter
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
object DatabaseModule {
|
object DatabaseModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@Singleton
|
||||||
fun providesSqlDriver(@ApplicationContext context: Context): SqlDriver {
|
fun providesSqlDriver(@ApplicationContext context: Context): SqlDriver {
|
||||||
return AndroidSqliteDriver(LobstersDatabase.Schema, context)
|
return AndroidSqliteDriver(LobstersDatabase.Schema, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@Singleton
|
||||||
fun providesLobstersDatabase(sqlDriver: SqlDriver): LobstersDatabase {
|
fun providesLobstersDatabase(sqlDriver: SqlDriver): LobstersDatabase {
|
||||||
return LobstersDatabase(sqlDriver, LobstersPost.Adapter(SubmitterAdapter(), TagsAdapter()))
|
return LobstersDatabase(sqlDriver, LobstersPost.Adapter(SubmitterAdapter(), TagsAdapter()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ fun LobstersApp() {
|
||||||
val savedPosts by viewModel.savedPosts.collectAsState()
|
val savedPosts by viewModel.savedPosts.collectAsState()
|
||||||
val hottestPostsListState = rememberLazyListState()
|
val hottestPostsListState = rememberLazyListState()
|
||||||
|
|
||||||
|
viewModel.getSavedPosts()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
LobstersBottomNav(
|
LobstersBottomNav(
|
||||||
|
|
|
@ -14,6 +14,10 @@ import androidx.compose.material.Surface
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.material.ripple.rememberRipple
|
import androidx.compose.material.ripple.rememberRipple
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
@ -65,6 +69,8 @@ fun LobstersItem(
|
||||||
onLongClick: () -> Unit,
|
onLongClick: () -> Unit,
|
||||||
onSaveButtonClick: () -> Unit,
|
onSaveButtonClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
var isSaved by remember { mutableStateOf(post.is_saved ?: false) }
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
@ -121,11 +127,14 @@ fun LobstersItem(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
IconResource(
|
IconResource(
|
||||||
resourceId = if (post.is_saved == true) R.drawable.ic_favorite_24px else R.drawable.ic_favorite_border_24px,
|
resourceId = if (isSaved) R.drawable.ic_favorite_24px else R.drawable.ic_favorite_border_24px,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = onSaveButtonClick,
|
onClick = {
|
||||||
|
onSaveButtonClick()
|
||||||
|
isSaved = isSaved.not()
|
||||||
|
},
|
||||||
indication = rememberRipple(),
|
indication = rememberRipple(),
|
||||||
)
|
)
|
||||||
.constrainAs(saveButton) {
|
.constrainAs(saveButton) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ class LobstersViewModel @Inject constructor(
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val _savedPosts = MutableStateFlow<List<LobstersPost>>(emptyList())
|
private val _savedPosts = MutableStateFlow<List<LobstersPost>>(emptyList())
|
||||||
val savedPosts = _savedPosts.asStateFlow()
|
val savedPosts = _savedPosts.asStateFlow()
|
||||||
val posts = Pager(PagingConfig(25)) {
|
val posts = Pager(PagingConfig(5)) {
|
||||||
pagingSource
|
pagingSource
|
||||||
}.flow
|
}.flow
|
||||||
|
|
||||||
|
@ -31,17 +31,25 @@ class LobstersViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSavedPosts() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
lobstersRepository.getSavedPosts().forEach {
|
||||||
|
_savedPosts.value = _savedPosts.value + it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun savePost(post: LobstersPost) {
|
private fun savePost(post: LobstersPost) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
lobstersRepository.savePost(post)
|
lobstersRepository.savePost(post)
|
||||||
_savedPosts.value = _savedPosts.value + post
|
_savedPosts.value = _savedPosts.value + post.copy(is_saved = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSavedPost(post: LobstersPost) {
|
private fun removeSavedPost(post: LobstersPost) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
lobstersRepository.removeSavedPost(post)
|
lobstersRepository.removeSavedPost(post)
|
||||||
_savedPosts.value = _savedPosts.value - post
|
_savedPosts.value = _savedPosts.value - post.copy(is_saved = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,12 @@ deleteAllPosts:
|
||||||
DELETE
|
DELETE
|
||||||
FROM LobstersPost;
|
FROM LobstersPost;
|
||||||
|
|
||||||
|
isPostSaved:
|
||||||
|
SELECT *
|
||||||
|
FROM LobstersPost
|
||||||
|
WHERE short_id = ?
|
||||||
|
AND is_saved = 1;
|
||||||
|
|
||||||
selectCount:
|
selectCount:
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM LobstersPost;
|
FROM LobstersPost;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue