From cbbc15d9fb141b79d03013d688225b1f37fb4c31 Mon Sep 17 00:00:00 2001 From: Ivan Agosto Date: Fri, 7 Feb 2025 18:25:23 -0600 Subject: [PATCH] Save progress --- .../agosto/p2play/activities/MainActivity.kt | 4 +- .../java/org/libre/agosto/p2play/ui/Routes.kt | 10 +++-- .../p2play/ui/bars/MainNavigationBar.kt | 2 +- .../agosto/p2play/ui/bars/MainTopAppBar.kt | 12 ++++- .../p2play/ui/views/SubscriptionsView.kt | 29 +++++------- .../viewModels/SubscriptionsViewModel.kt | 44 +++++++++++++++++++ 6 files changed, 75 insertions(+), 26 deletions(-) create mode 100644 app/src/main/java/org/libre/agosto/p2play/viewModels/SubscriptionsViewModel.kt diff --git a/app/src/main/java/org/libre/agosto/p2play/activities/MainActivity.kt b/app/src/main/java/org/libre/agosto/p2play/activities/MainActivity.kt index 16c1f69..b8420e0 100644 --- a/app/src/main/java/org/libre/agosto/p2play/activities/MainActivity.kt +++ b/app/src/main/java/org/libre/agosto/p2play/activities/MainActivity.kt @@ -22,6 +22,7 @@ import org.libre.agosto.p2play.ui.bars.SearchTopBar import org.libre.agosto.p2play.ui.views.SearchView import org.libre.agosto.p2play.ui.views.SubscriptionsView import org.libre.agosto.p2play.ui.views.VideosView +import org.libre.agosto.p2play.viewModels.SubscriptionsViewModel class MainActivity : ComponentActivity() { @@ -30,6 +31,7 @@ class MainActivity : ComponentActivity() { enableEdgeToEdge() setContent { val videoViewModel: VideosViewModel = viewModel() + val subscriptionsViewModel: SubscriptionsViewModel = viewModel() val navController = rememberNavController() val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route P2playTheme { @@ -46,7 +48,7 @@ class MainActivity : ComponentActivity() { ) { innerPadding -> NavHost(navController, startDestination = Routes.Videos.route, modifier = Modifier.padding(innerPadding)) { composable(Routes.Videos.route) { VideosView(videoViewModel) } - composable(Routes.Subscriptions.route) { SubscriptionsView() } + composable(Routes.Subscriptions.route) { SubscriptionsView(subscriptionsViewModel) } composable(Routes.Search.route) { SearchView() } } } diff --git a/app/src/main/java/org/libre/agosto/p2play/ui/Routes.kt b/app/src/main/java/org/libre/agosto/p2play/ui/Routes.kt index a251f46..ee7daef 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ui/Routes.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ui/Routes.kt @@ -1,7 +1,9 @@ package org.libre.agosto.p2play.ui -sealed class Routes (val route: String) { - data object Videos: Routes("videos") - data object Subscriptions: Routes("subscriptions") - data object Search: Routes("search") +import org.libre.agosto.p2play.R + +sealed class Routes (val route: String, val title: Int?) { + data object Videos: Routes("videos", R.string.app_name) + data object Subscriptions: Routes("subscriptions", R.string.title_subscriptions) + data object Search: Routes("search", null) } \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainNavigationBar.kt b/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainNavigationBar.kt index 6c8c454..9aee6de 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainNavigationBar.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainNavigationBar.kt @@ -22,7 +22,7 @@ import org.libre.agosto.p2play.ui.Routes fun MainNavigationBar (navController: NavController) { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentDestination = navBackStackEntry?.destination - currentDestination?.route + NavigationBar { NavigationBarItem( icon = { Icon(Icons.Filled.Home, "home") }, diff --git a/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainTopAppBar.kt b/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainTopAppBar.kt index 0af5c27..9d316d6 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainTopAppBar.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ui/bars/MainTopAppBar.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.navigation.NavController import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.compose.currentBackStackEntryAsState import org.libre.agosto.p2play.AboutActivity import org.libre.agosto.p2play.LoginActivity import org.libre.agosto.p2play.ManagerSingleton @@ -33,8 +34,17 @@ import org.libre.agosto.p2play.SettingsActivity2 fun MainTopAppBar(navController: NavController, modifier: Modifier = Modifier) { var isMenuOpen by remember { mutableStateOf(false) } val context = LocalContext.current + + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry?.destination + + val title = when (currentDestination?.route) { + Routes.Subscriptions.route -> stringResource(Routes.Subscriptions.title!!) + else -> stringResource(R.string.app_name) + } + TopAppBar( - { Text(stringResource(R.string.nav_menu_videos)) }, + { Text(title) }, modifier, actions = { IconButton({ diff --git a/app/src/main/java/org/libre/agosto/p2play/ui/views/SubscriptionsView.kt b/app/src/main/java/org/libre/agosto/p2play/ui/views/SubscriptionsView.kt index 290921d..656d237 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ui/views/SubscriptionsView.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ui/views/SubscriptionsView.kt @@ -7,6 +7,7 @@ import androidx.compose.material.icons.filled.Star import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -25,27 +26,18 @@ import org.libre.agosto.p2play.ui.components.molecules.ChipSelector import org.libre.agosto.p2play.ui.components.molecules.ChipValues import org.libre.agosto.p2play.helpers.TaskManager import org.libre.agosto.p2play.models.VideoModel +import org.libre.agosto.p2play.viewModels.SubscriptionsViewModel import java.util.ArrayList @SuppressLint("MutableCollectionMutableState") @Composable -fun SubscriptionsView (modifier: Modifier = Modifier) { - val videos by rememberSaveable { mutableStateOf(mutableListOf()) } - var isLoading by rememberSaveable { mutableStateOf(true) } +fun SubscriptionsView (subscriptionsViewModel: SubscriptionsViewModel, modifier: Modifier = Modifier) { + val videos by subscriptionsViewModel.videos.observeAsState(initial = listOf()) + val isLoading: Boolean by subscriptionsViewModel.isLoading.observeAsState(initial = false) - LaunchedEffect(isLoading) { - if (isLoading) { - val task = TaskManager>() - task.runTask( - { - val client = Videos() - client.getTrendingVideos(videos.size) - }, - { - videos.addAll(it) - isLoading = false - } - ) + LaunchedEffect(Unit) { + if (videos.isEmpty()) { + subscriptionsViewModel.loadVideos() } } @@ -55,13 +47,12 @@ fun SubscriptionsView (modifier: Modifier = Modifier) { isLoading = isLoading, onRefresh = { if (!isLoading) { - videos.clear() - isLoading = true + subscriptionsViewModel.refresh() } }, onLoadMore = { if (!isLoading) { - isLoading = true + subscriptionsViewModel.loadVideos() } } ) diff --git a/app/src/main/java/org/libre/agosto/p2play/viewModels/SubscriptionsViewModel.kt b/app/src/main/java/org/libre/agosto/p2play/viewModels/SubscriptionsViewModel.kt new file mode 100644 index 0000000..3452f8b --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/viewModels/SubscriptionsViewModel.kt @@ -0,0 +1,44 @@ +package org.libre.agosto.p2play.viewModels + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.libre.agosto.p2play.ManagerSingleton +import org.libre.agosto.p2play.ajax.Videos +import org.libre.agosto.p2play.models.VideoModel + +class SubscriptionsViewModel(savedStateHandle: SavedStateHandle) : ViewModel() { + val client = Videos() + + private val _videos = MutableLiveData>() + val videos: LiveData> = _videos + + private val _isLoading = MutableLiveData() + val isLoading: LiveData = _isLoading + + fun loadVideos() { + _isLoading.value = true + viewModelScope.launch { + val result = withContext(Dispatchers.IO) { + client.videoSubscriptions(ManagerSingleton.token.token, videos.value?.size ?: 0) + } + val data = if (videos.value !== null) + ArrayList(videos.value!!) + else + ArrayList() + data.addAll(result) + _videos.postValue(data) + _isLoading.value = false + } + } + + fun refresh() { + _videos.value = arrayListOf() + loadVideos() + } +} \ No newline at end of file