mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-17 23:47:02 +05:30
app: remove existing post loading
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
parent
ada6a6f3ff
commit
d0d08f8a3c
3 changed files with 5 additions and 50 deletions
|
@ -24,6 +24,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import androidx.navigation.compose.navigate
|
import androidx.navigation.compose.navigate
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import dev.msfjarvis.lobsters.model.LobstersPost
|
||||||
import dev.msfjarvis.lobsters.util.IconResource
|
import dev.msfjarvis.lobsters.util.IconResource
|
||||||
import dev.msfjarvis.lobsters.ui.viewmodel.LobstersViewModel
|
import dev.msfjarvis.lobsters.ui.viewmodel.LobstersViewModel
|
||||||
import dev.msfjarvis.lobsters.ui.navigation.Destination
|
import dev.msfjarvis.lobsters.ui.navigation.Destination
|
||||||
|
@ -54,7 +55,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
fun LobstersApp() {
|
fun LobstersApp() {
|
||||||
val viewModel: LobstersViewModel = viewModel()
|
val viewModel: LobstersViewModel = viewModel()
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val hottestPosts by viewModel.posts.collectAsState()
|
val hottestPosts = emptyList<LobstersPost>()
|
||||||
val savedPosts by viewModel.savedPosts.collectAsState()
|
val savedPosts by viewModel.savedPosts.collectAsState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
@ -68,7 +69,6 @@ fun LobstersApp() {
|
||||||
HottestPosts(
|
HottestPosts(
|
||||||
posts = hottestPosts,
|
posts = hottestPosts,
|
||||||
listState = hottestPostsListState,
|
listState = hottestPostsListState,
|
||||||
overscrollAction = viewModel::getMorePosts,
|
|
||||||
saveAction = viewModel::savePost,
|
saveAction = viewModel::savePost,
|
||||||
modifier = Modifier.padding(bottom = innerPadding.bottom),
|
modifier = Modifier.padding(bottom = innerPadding.bottom),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package dev.msfjarvis.lobsters.ui.posts
|
package dev.msfjarvis.lobsters.ui.posts
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumnForIndexed
|
import androidx.compose.foundation.lazy.LazyColumnFor
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
@ -14,7 +14,6 @@ fun HottestPosts(
|
||||||
posts: List<LobstersPost>,
|
posts: List<LobstersPost>,
|
||||||
listState: LazyListState,
|
listState: LazyListState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
overscrollAction: () -> Unit,
|
|
||||||
saveAction: (LobstersPost) -> Unit,
|
saveAction: (LobstersPost) -> Unit,
|
||||||
) {
|
) {
|
||||||
val urlLauncher = UrlLauncherAmbient.current
|
val urlLauncher = UrlLauncherAmbient.current
|
||||||
|
@ -22,14 +21,11 @@ fun HottestPosts(
|
||||||
if (posts.isEmpty()) {
|
if (posts.isEmpty()) {
|
||||||
EmptyList(saved = false)
|
EmptyList(saved = false)
|
||||||
} else {
|
} else {
|
||||||
LazyColumnForIndexed(
|
LazyColumnFor(
|
||||||
items = posts,
|
items = posts,
|
||||||
state = listState,
|
state = listState,
|
||||||
modifier = Modifier.padding(horizontal = 8.dp).then(modifier)
|
modifier = Modifier.padding(horizontal = 8.dp).then(modifier)
|
||||||
) { index, item ->
|
) { item ->
|
||||||
if (posts.lastIndex == index) {
|
|
||||||
overscrollAction.invoke()
|
|
||||||
}
|
|
||||||
LobstersItem(
|
LobstersItem(
|
||||||
post = item,
|
post = item,
|
||||||
onClick = { urlLauncher.launch(item.url.ifEmpty { item.commentsUrl }) },
|
onClick = { urlLauncher.launch(item.url.ifEmpty { item.commentsUrl }) },
|
||||||
|
|
|
@ -3,44 +3,21 @@ package dev.msfjarvis.lobsters.ui.viewmodel
|
||||||
import androidx.hilt.lifecycle.ViewModelInject
|
import androidx.hilt.lifecycle.ViewModelInject
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dev.msfjarvis.lobsters.data.api.LobstersApi
|
|
||||||
import dev.msfjarvis.lobsters.data.source.PostsDatabase
|
import dev.msfjarvis.lobsters.data.source.PostsDatabase
|
||||||
import dev.msfjarvis.lobsters.model.LobstersPost
|
import dev.msfjarvis.lobsters.model.LobstersPost
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.net.SocketTimeoutException
|
|
||||||
import java.net.UnknownHostException
|
|
||||||
|
|
||||||
class LobstersViewModel @ViewModelInject constructor(
|
class LobstersViewModel @ViewModelInject constructor(
|
||||||
private val lobstersApi: LobstersApi,
|
|
||||||
database: PostsDatabase,
|
database: PostsDatabase,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private var apiPage = 1
|
|
||||||
private val _posts = MutableStateFlow<List<LobstersPost>>(emptyList())
|
|
||||||
private val _savedPosts = MutableStateFlow<List<LobstersPost>>(emptyList())
|
private val _savedPosts = MutableStateFlow<List<LobstersPost>>(emptyList())
|
||||||
private val postsDao = database.postsDao()
|
|
||||||
private val savedPostsDao = database.savedPostsDao()
|
private val savedPostsDao = database.savedPostsDao()
|
||||||
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
|
|
||||||
when (throwable) {
|
|
||||||
// Swallow known network errors that can be recovered from.
|
|
||||||
is UnknownHostException, is SocketTimeoutException -> {
|
|
||||||
if (_posts.value.isEmpty()) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
postsDao.loadPosts().collectLatest { _posts.value = it }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> throw throwable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val posts: StateFlow<List<LobstersPost>> get() = _posts
|
|
||||||
val savedPosts: StateFlow<List<LobstersPost>> get() = _savedPosts
|
val savedPosts: StateFlow<List<LobstersPost>> get() = _savedPosts
|
||||||
|
|
||||||
init {
|
init {
|
||||||
getMorePostsInternal(true)
|
|
||||||
getSavedPosts()
|
getSavedPosts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,24 +27,6 @@ class LobstersViewModel @ViewModelInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMorePosts() {
|
|
||||||
getMorePostsInternal(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMorePostsInternal(firstLoad: Boolean) {
|
|
||||||
viewModelScope.launch(coroutineExceptionHandler) {
|
|
||||||
val newPosts = lobstersApi.getHottestPosts(apiPage)
|
|
||||||
if (firstLoad) {
|
|
||||||
_posts.value = newPosts
|
|
||||||
postsDao.deleteAllPosts()
|
|
||||||
} else {
|
|
||||||
_posts.value += newPosts
|
|
||||||
}
|
|
||||||
apiPage += 1
|
|
||||||
postsDao.insertPosts(*_posts.value.toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun savePost(post: LobstersPost) {
|
fun savePost(post: LobstersPost) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
savedPostsDao.insertPosts(post)
|
savedPostsDao.insertPosts(post)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue