mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 23:27:04 +05:30
android: integrate database
This commit is contained in:
parent
de93f32b96
commit
86e659a180
6 changed files with 75 additions and 3 deletions
|
@ -15,6 +15,7 @@ import androidx.compose.runtime.SideEffect
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
|
@ -35,6 +36,7 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
|||
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
|
||||
import dev.msfjarvis.claw.common.theme.LobstersTheme
|
||||
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private const val ScrollDelta = 50
|
||||
|
||||
|
@ -47,6 +49,7 @@ fun LobstersApp(
|
|||
val systemUiController = rememberSystemUiController()
|
||||
val scaffoldState = rememberScaffoldState()
|
||||
val listState = rememberLazyListState()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var isFabVisible by remember { mutableStateOf(true) }
|
||||
val nestedScrollConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
|
@ -97,6 +100,8 @@ fun LobstersApp(
|
|||
items = items,
|
||||
launchUrl = urlLauncher::launch,
|
||||
listState = listState,
|
||||
isSaved = viewModel::isPostSaved,
|
||||
toggleSave = { coroutineScope.launch { viewModel.toggleSave(it) } },
|
||||
modifier = Modifier.padding(top = 16.dp).nestedScroll(nestedScrollConnection),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,11 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
|
@ -11,26 +16,34 @@ import androidx.paging.compose.items
|
|||
import dev.msfjarvis.claw.android.ext.toDbModel
|
||||
import dev.msfjarvis.claw.api.model.LobstersPost
|
||||
import dev.msfjarvis.claw.common.posts.LobstersCard
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun NetworkPosts(
|
||||
items: LazyPagingItems<LobstersPost>,
|
||||
listState: LazyListState,
|
||||
launchUrl: (String) -> Unit,
|
||||
isSaved: suspend (SavedPost) -> Boolean,
|
||||
toggleSave: (SavedPost) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
modifier = Modifier.then(modifier),
|
||||
) {
|
||||
items(items) { item ->
|
||||
if (item != null) {
|
||||
val dbModel = item.toDbModel()
|
||||
var saved by remember(dbModel) { mutableStateOf(false) }
|
||||
coroutineScope.launch { saved = isSaved(dbModel) }
|
||||
LobstersCard(
|
||||
post = item.toDbModel(),
|
||||
isSaved = false,
|
||||
post = dbModel,
|
||||
isSaved = saved,
|
||||
viewPost = { launchUrl(item.url.ifEmpty { item.commentsUrl }) },
|
||||
viewComments = { launchUrl(item.commentsUrl) },
|
||||
toggleSave = {},
|
||||
toggleSave = { toggleSave(dbModel) },
|
||||
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,15 +6,24 @@ import androidx.paging.PagingConfig
|
|||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dev.msfjarvis.claw.android.paging.LobstersPagingSource
|
||||
import dev.msfjarvis.claw.api.LobstersApi
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.last
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@HiltViewModel
|
||||
class ClawViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
api: LobstersApi,
|
||||
private val repository: SavedPostsRepository,
|
||||
) : ViewModel() {
|
||||
var lastPagingSource: LobstersPagingSource? = null
|
||||
private val savedPosts = flow { repository.savedPosts.collect { emit(it) } }
|
||||
private val pager =
|
||||
Pager(PagingConfig(20)) {
|
||||
LobstersPagingSource(api::getHottestPosts).also { lastPagingSource = it }
|
||||
|
@ -23,6 +32,20 @@ constructor(
|
|||
val pagerFlow
|
||||
get() = pager.flow
|
||||
|
||||
suspend fun isPostSaved(post: SavedPost): Boolean {
|
||||
return savedPosts.mapLatest { posts -> post in posts }.last()
|
||||
}
|
||||
|
||||
suspend fun toggleSave(post: SavedPost) {
|
||||
val saved = isPostSaved(post)
|
||||
println("saved=$saved")
|
||||
if (saved) {
|
||||
repository.removePost(post)
|
||||
} else {
|
||||
repository.savePost(post)
|
||||
}
|
||||
}
|
||||
|
||||
fun reloadPosts() {
|
||||
lastPagingSource?.invalidate()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package dev.msfjarvis.claw.android.viewmodel
|
||||
|
||||
import com.squareup.sqldelight.runtime.coroutines.asFlow
|
||||
import com.squareup.sqldelight.runtime.coroutines.mapToList
|
||||
import dev.msfjarvis.claw.database.LobstersDatabase
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class SavedPostsRepository
|
||||
@Inject
|
||||
constructor(
|
||||
database: LobstersDatabase,
|
||||
) {
|
||||
private val savedPostQueries = database.savedPostQueries
|
||||
val savedPosts = savedPostQueries.selectAllPosts().asFlow().mapToList()
|
||||
|
||||
suspend fun savePost(post: SavedPost) {
|
||||
println("Saving post: ${post.shortId}")
|
||||
withContext(Dispatchers.IO) { savedPostQueries.insertOrReplacePost(post) }
|
||||
}
|
||||
|
||||
suspend fun removePost(post: SavedPost) {
|
||||
println("Removing post: ${post.shortId}")
|
||||
withContext(Dispatchers.IO) { savedPostQueries.deletePost(post.shortId) }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue