From 95334d2c8b93fafd8353f2fed134c5ccb669faa0 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Sun, 27 Sep 2020 16:23:41 +0530 Subject: [PATCH 1/3] data: ignore overwriting when inserting posts Signed-off-by: Harsh Shandilya --- .../main/java/dev/msfjarvis/lobsters/data/source/PostsDao.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/src/main/java/dev/msfjarvis/lobsters/data/source/PostsDao.kt b/data/src/main/java/dev/msfjarvis/lobsters/data/source/PostsDao.kt index 6de53a3e..dcee27ce 100644 --- a/data/src/main/java/dev/msfjarvis/lobsters/data/source/PostsDao.kt +++ b/data/src/main/java/dev/msfjarvis/lobsters/data/source/PostsDao.kt @@ -3,6 +3,7 @@ package dev.msfjarvis.lobsters.data.source import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert +import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Transaction import dev.msfjarvis.lobsters.data.model.LobstersEntity @@ -19,7 +20,7 @@ abstract class PostsDao { insertPosts(posts.map { LobstersEntity(it) }) } - @Insert + @Insert(onConflict = OnConflictStrategy.IGNORE) protected abstract suspend fun insertPosts(posts: List) @Transaction From 4fdb5a60d52225f4b1e212d4107108aefbd0b45c Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Sun, 27 Sep 2020 16:24:36 +0530 Subject: [PATCH 2/3] app: wire in local persistence in LobstersViewModel Signed-off-by: Harsh Shandilya --- .../lobsters/data/LobstersViewModel.kt | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/dev/msfjarvis/lobsters/data/LobstersViewModel.kt b/app/src/main/java/dev/msfjarvis/lobsters/data/LobstersViewModel.kt index cd32193f..e96c1129 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/data/LobstersViewModel.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/data/LobstersViewModel.kt @@ -4,27 +4,44 @@ import androidx.hilt.lifecycle.ViewModelInject import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dev.msfjarvis.lobsters.api.LobstersApi +import dev.msfjarvis.lobsters.data.source.PostsDatabase import dev.msfjarvis.lobsters.model.LobstersPost +import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch - +import java.net.UnknownHostException class LobstersViewModel @ViewModelInject constructor( private val lobstersApi: LobstersApi, + database: PostsDatabase, ) : ViewModel() { private var apiPage = 1 private val _posts = MutableStateFlow>(emptyList()) + private val dao = database.postsDao() + private val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable -> + when (throwable) { + // Swallow UHE since that happens when there is no internet and we'll just rely on our cache + is UnknownHostException -> {} + else -> throw throwable + } + } val posts: StateFlow> get() = _posts init { + viewModelScope.launch { + dao.loadPosts().collectLatest { _posts.value = it } + } getMorePosts() } fun getMorePosts() { - viewModelScope.launch { - _posts.value += lobstersApi.getHottestPosts(apiPage) + viewModelScope.launch(coroutineExceptionHandler) { + val newPosts = lobstersApi.getHottestPosts(apiPage) + _posts.value += newPosts apiPage += 1 + dao.insertPosts(*_posts.value.toTypedArray()) } } } From 62c2cb3fb758b828890a4bf5a7ab750028256860 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Sun, 27 Sep 2020 16:44:39 +0530 Subject: [PATCH 3/3] app: add no posts state Signed-off-by: Harsh Shandilya --- .../dev/msfjarvis/lobsters/MainActivity.kt | 33 ++++++++++++++----- .../res/drawable/ic_sync_problem_24px.xml | 9 +++++ app/src/main/res/values/strings.xml | 3 +- 3 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 app/src/main/res/drawable/ic_sync_problem_24px.xml diff --git a/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt b/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt index 03c66b3f..289eeec3 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt @@ -4,6 +4,9 @@ import android.os.Bundle import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.Text +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumnForIndexed import androidx.compose.material.Scaffold import androidx.compose.material.TopAppBar @@ -11,10 +14,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Providers import androidx.compose.runtime.ambientOf import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier import androidx.compose.ui.platform.setContent import androidx.compose.ui.res.stringResource import dagger.hilt.android.AndroidEntryPoint import dev.msfjarvis.lobsters.api.LobstersApi +import dev.msfjarvis.lobsters.compose.utils.IconResource import dev.msfjarvis.lobsters.data.LobstersViewModel import dev.msfjarvis.lobsters.ui.LobstersItem import dev.msfjarvis.lobsters.ui.LobstersTheme @@ -52,15 +58,26 @@ fun LobstersApp( Scaffold( topBar = { TopAppBar({ Text(text = stringResource(R.string.app_name)) }) }, bodyContent = { - LazyColumnForIndexed(state.value) { index, item -> - if (lastIndex == index) { - viewModel.getMorePosts() + if (state.value.isEmpty()) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + IconResource(R.drawable.ic_sync_problem_24px) + Text(stringResource(R.string.nothing_to_see_here)) + } + } else { + LazyColumnForIndexed(state.value) { index, item -> + if (lastIndex == index) { + viewModel.getMorePosts() + } + LobstersItem( + item, + linkOpenAction = { post -> urlLauncher.launch(post.url) }, + commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) }, + ) } - LobstersItem( - item, - linkOpenAction = { post -> urlLauncher.launch(post.url) }, - commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) }, - ) } } ) diff --git a/app/src/main/res/drawable/ic_sync_problem_24px.xml b/app/src/main/res/drawable/ic_sync_problem_24px.xml new file mode 100644 index 00000000..fe10eb1f --- /dev/null +++ b/app/src/main/res/drawable/ic_sync_problem_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b0ce64c6..eb4d1126 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ lobste.rs - \ No newline at end of file + Nothing to see here… +