From c56776842a7ac6a12f861fc7cb804db76ff38e50 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Mon, 18 Mar 2024 22:48:02 -0700 Subject: [PATCH] ConversationListScreen: Implements pull-to-refresh --- .../ConversationListScreen.kt | 58 ++++++++++++++----- .../ConversationListViewModel.kt | 8 +-- .../main/res/xml/network_security_config.xml | 2 +- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListScreen.kt b/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListScreen.kt index 43f8d42..6125423 100644 --- a/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListScreen.kt +++ b/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListScreen.kt @@ -9,11 +9,16 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.* import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Info import androidx.compose.material.icons.rounded.Settings +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState 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.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle @@ -25,10 +30,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.hilt.navigation.compose.hiltViewModel +import kotlinx.coroutines.launch import net.buzzert.kordophone.backend.model.Conversation import java.time.LocalDate import java.time.LocalDateTime -import java.time.LocalTime import java.time.ZoneId import java.time.format.DateTimeFormatter import java.util.Date @@ -54,17 +59,31 @@ fun ConversationListScreen( conversations = conversations, onConversationSelected = onConversationSelected, onSettingsInvoked = onSettingsInvoked, + onRefresh = suspend { viewModel.refresh() } ) } @Composable +@OptIn(ExperimentalMaterialApi::class) fun ConversationListView( conversations: List, onConversationSelected: (conversationID: String) -> Unit, onSettingsInvoked: () -> Unit, + onRefresh: suspend () -> Unit, ) { val listState = rememberLazyListState() + val refreshScope = rememberCoroutineScope() + var refreshing by remember { mutableStateOf(false) } + + fun refresh() = refreshScope.launch { + refreshing = true + onRefresh() + refreshing = false + } + + val refreshState = rememberPullRefreshState(refreshing = refreshing, onRefresh = ::refresh) + Scaffold( topBar = { TopAppBar(title = { Text("Conversations") }, actions = { @@ -74,17 +93,30 @@ fun ConversationListView( }) } ) { - LazyColumn(state = listState, modifier = Modifier.padding(it)) { - items(conversations) { conversation -> - ConversationListItem( - name = conversation.formattedDisplayName(), - id = conversation.guid, - isUnread = conversation.unreadCount > 0, - lastMessagePreview = conversation.lastMessagePreview ?: "", - date = conversation.date, - onClick = { onConversationSelected(conversation.guid) } - ) + Box(Modifier.pullRefresh(refreshState)) { + LazyColumn( + state = listState, + modifier = Modifier + .padding(it) + .fillMaxSize() + ) { + items(conversations) { conversation -> + ConversationListItem( + name = conversation.formattedDisplayName(), + id = conversation.guid, + isUnread = conversation.unreadCount > 0, + lastMessagePreview = conversation.lastMessagePreview ?: "", + date = conversation.date, + onClick = { onConversationSelected(conversation.guid) } + ) + } } + + PullRefreshIndicator( + refreshing = refreshing, + state = refreshState, + modifier = Modifier.align(Alignment.TopCenter), + ) } } } diff --git a/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListViewModel.kt b/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListViewModel.kt index c632302..fec359b 100644 --- a/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListViewModel.kt +++ b/app/src/main/java/net/buzzert/kordophonedroid/ui/conversationlist/ConversationListViewModel.kt @@ -1,25 +1,21 @@ package net.buzzert.kordophonedroid.ui.conversationlist import android.util.Log -import androidx.compose.runtime.collectAsState import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import net.buzzert.kordophone.backend.model.Conversation import net.buzzert.kordophone.backend.server.Authentication import net.buzzert.kordophone.backend.server.ChatRepository -import net.buzzert.kordophone.backend.server.REPO_LOG import net.buzzert.kordophone.backend.server.RetrofitAPIClient import net.buzzert.kordophonedroid.ui.shared.ServerConfigRepository import java.net.URL import javax.inject.Inject -import kotlin.coroutines.CoroutineContext const val CL_VM_LOG: String = "ConversationListViewModel" @@ -69,4 +65,8 @@ class ConversationListViewModel @Inject constructor( chatRepository.beginWatchingForUpdates(this) } } + + suspend fun refresh() { + chatRepository.synchronize() + } } \ No newline at end of file diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml index 2b824f3..a9f67c3 100644 --- a/app/src/main/res/xml/network_security_config.xml +++ b/app/src/main/res/xml/network_security_config.xml @@ -1,7 +1,7 @@ - 192.168.1.111 + 192.168.1.123 tesseract.localdomain buzzert.kordophone.nor