From 52fc21b0ad09e538243cc44f1ed6c9877512593e Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Fri, 9 Dec 2022 16:30:53 -0800 Subject: [PATCH] add pull to refresh mechanism on android home screen --- .../app/omnivore/omnivore/ui/home/HomeView.kt | 68 +++++++++++++------ .../omnivore/ui/home/HomeViewModel.kt | 15 ++++ 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 1663665b0..e3ee5d1f7 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -7,6 +7,10 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState @@ -14,6 +18,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import app.omnivore.omnivore.Routes import app.omnivore.omnivore.models.LinkedItem @@ -50,6 +55,7 @@ fun HomeView( } } +@OptIn(ExperimentalMaterialApi::class) @Composable fun HomeViewContent( homeViewModel: HomeViewModel, @@ -58,35 +64,53 @@ fun HomeViewContent( ) { val context = LocalContext.current val listState = rememberLazyListState() + + val pullRefreshState = rememberPullRefreshState( + refreshing = homeViewModel.isRefreshing, + onRefresh = { homeViewModel.refresh() } + ) + val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf()) - LazyColumn( - state = listState, - verticalArrangement = Arrangement.Top, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = modifier - .background(MaterialTheme.colorScheme.background) + Box( + modifier = Modifier .fillMaxSize() - .padding(horizontal = 6.dp) + .pullRefresh(pullRefreshState) ) { - items(linkedItems) { item -> - LinkedItemCard( - item = item, - onClickHandler = { - if (item.isPDF()) { - val intent = Intent(context, PDFReaderActivity::class.java) - intent.putExtra("LINKED_ITEM_SLUG", item.slug) - context.startActivity(intent) - } else { - navController.navigate("WebReader/${item.slug}") + LazyColumn( + state = listState, + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = modifier + .background(MaterialTheme.colorScheme.background) + .fillMaxSize() + .padding(horizontal = 6.dp) + ) { + items(linkedItems) { item -> + LinkedItemCard( + item = item, + onClickHandler = { + if (item.isPDF()) { + val intent = Intent(context, PDFReaderActivity::class.java) + intent.putExtra("LINKED_ITEM_SLUG", item.slug) + context.startActivity(intent) + } else { + navController.navigate("WebReader/${item.slug}") + } } - } - ) + ) + } } - } - InfiniteListHandler(listState = listState) { - homeViewModel.load() + InfiniteListHandler(listState = listState) { + homeViewModel.load() + } + + PullRefreshIndicator( + refreshing = homeViewModel.isRefreshing, + state = pullRefreshState, + modifier = Modifier.align(Alignment.TopCenter) + ) } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt index 6fc76e977..80aeb4b28 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt @@ -1,5 +1,8 @@ package app.omnivore.omnivore.ui.home +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -7,6 +10,8 @@ import app.omnivore.omnivore.models.LinkedItem import app.omnivore.omnivore.networking.Networker import app.omnivore.omnivore.networking.search import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import javax.inject.Inject @@ -26,6 +31,7 @@ class HomeViewModel @Inject constructor( // Live Data val searchTextLiveData = MutableLiveData("") val itemsLiveData = MutableLiveData>(listOf()) + var isRefreshing by mutableStateOf(false) fun updateSearchText(text: String) { searchTextLiveData.value = text @@ -37,6 +43,11 @@ class HomeViewModel @Inject constructor( } } + fun refresh() { + isRefreshing = true + load(true) + } + fun load(clearPreviousSearch: Boolean = false) { if (clearPreviousSearch) { cursor = null @@ -69,6 +80,10 @@ class HomeViewModel @Inject constructor( items = items.plus(searchResult.items) itemsLiveData.value = items } + + CoroutineScope(Dispatchers.Main).launch { + isRefreshing = false + } } }