From f9cf6a38db41337d9fa1f6e622b6e441c190b669 Mon Sep 17 00:00:00 2001 From: Christian Olivera Date: Sat, 9 Nov 2024 20:27:50 -0300 Subject: [PATCH 1/2] new - remote config incoming --- .../com/example/jetnews/ui/MainActivity.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt index bd6d2ac0bd..ae837c6d3a 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt @@ -17,12 +17,16 @@ package com.example.jetnews.ui import android.os.Bundle +import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import com.example.jetnews.JetnewsApplication +import com.google.firebase.ktx.Firebase +import com.google.firebase.remoteconfig.ktx.remoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfigSettings class MainActivity : ComponentActivity() { @@ -36,5 +40,31 @@ class MainActivity : ComponentActivity() { val widthSizeClass = calculateWindowSizeClass(this).widthSizeClass JetnewsApp(appContainer, widthSizeClass) } + + // Inicializa Firebase Remote Config + val remoteConfig = Firebase.remoteConfig + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 3600 // Intervalo de fetch mínimo en segundos + } + remoteConfig.setConfigSettingsAsync(configSettings) + remoteConfig.setDefaultsAsync(mapOf( + "property_1" to "default_value_1", + "property_2" to "default_value_2" + )) + + // Realiza el fetch de los valores remotos + remoteConfig.fetchAndActivate().addOnCompleteListener { task -> + if (task.isSuccessful) { + val updated = task.result + Log.d("RemoteConfig", "Config params updated: $updated") + // Usa los valores de remoteConfig + val property1 = remoteConfig.getString("property_1") + val property2 = remoteConfig.getString("property_2") + // Actualiza la UI o lógica de negocio con estos valores + } else { + Log.w("RemoteConfig", "Fetch failed") + } + } + } } From 2cf2d95e981c25af9df05c7904171f54189c9cd1 Mon Sep 17 00:00:00 2001 From: Christian Olivera Date: Sun, 10 Nov 2024 22:19:12 -0300 Subject: [PATCH 2/2] new - show_search_icon y toast_text desde remote config para ocultar la busqueda y cambiar el mensaje del toast. --- .../com/example/jetnews/ui/MainActivity.kt | 26 ---- .../example/jetnews/ui/home/HomeScreens.kt | 131 +++++++++++------- JetNews/app/src/main/res/values/strings.xml | 1 + 3 files changed, 83 insertions(+), 75 deletions(-) diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt index ae837c6d3a..0a9d5c7897 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt @@ -40,31 +40,5 @@ class MainActivity : ComponentActivity() { val widthSizeClass = calculateWindowSizeClass(this).widthSizeClass JetnewsApp(appContainer, widthSizeClass) } - - // Inicializa Firebase Remote Config - val remoteConfig = Firebase.remoteConfig - val configSettings = remoteConfigSettings { - minimumFetchIntervalInSeconds = 3600 // Intervalo de fetch mínimo en segundos - } - remoteConfig.setConfigSettingsAsync(configSettings) - remoteConfig.setDefaultsAsync(mapOf( - "property_1" to "default_value_1", - "property_2" to "default_value_2" - )) - - // Realiza el fetch de los valores remotos - remoteConfig.fetchAndActivate().addOnCompleteListener { task -> - if (task.isSuccessful) { - val updated = task.result - Log.d("RemoteConfig", "Config params updated: $updated") - // Usa los valores de remoteConfig - val property1 = remoteConfig.getString("property_1") - val property2 = remoteConfig.getString("property_2") - // Actualiza la UI o lógica de negocio con estos valores - } else { - Log.w("RemoteConfig", "Fetch failed") - } - } - } } diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreens.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreens.kt index 07881aada0..cd2a8db94d 100644 --- a/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreens.kt +++ b/JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeScreens.kt @@ -18,6 +18,8 @@ package com.example.jetnews.ui.home import android.content.Context import android.content.res.Configuration.UI_MODE_NIGHT_YES +import android.util.Log +import android.view.View import android.widget.Toast import androidx.compose.animation.Crossfade import androidx.compose.foundation.BorderStroke @@ -73,8 +75,10 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.key +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier @@ -112,10 +116,14 @@ import com.example.jetnews.ui.utils.ShareButton import com.example.jetnews.ui.utils.TextSettingsButton import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.rememberSwipeRefreshState +import com.google.firebase.ktx.Firebase +import com.google.firebase.remoteconfig.ktx.remoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfigSettings import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.isActive import kotlinx.coroutines.runBlocking - +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch /** * The home screen displaying the feed along with an article details. */ @@ -154,9 +162,9 @@ fun HomeFeedWithArticleDetailsScreen( onToggleFavorite = onToggleFavorite, contentPadding = contentPadding, modifier = - Modifier - .width(334.dp) - .notifyInput(onInteractWithList), + Modifier + .width(334.dp) + .notifyInput(onInteractWithList), state = homeListLazyListState, searchInput = hasPostsUiState.searchInput, onSearchInputChanged = onSearchInputChanged, @@ -180,12 +188,12 @@ fun HomeFeedWithArticleDetailsScreen( state = detailLazyListState, contentPadding = contentPadding, modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxSize() - .notifyInput { - onInteractWithDetail(detailPost.id) - }, + Modifier + .padding(horizontal = 16.dp) + .fillMaxSize() + .notifyInput { + onInteractWithDetail(detailPost.id) + }, ) { postContentItems(detailPost) } @@ -197,10 +205,10 @@ fun HomeFeedWithArticleDetailsScreen( onToggleFavorite = { onToggleFavorite(detailPost.id) }, onSharePost = { sharePost(detailPost, context) }, modifier = - Modifier - .windowInsetsPadding(WindowInsets.safeDrawing) - .fillMaxWidth() - .wrapContentWidth(Alignment.End), + Modifier + .windowInsetsPadding(WindowInsets.safeDrawing) + .fillMaxWidth() + .wrapContentWidth(Alignment.End), ) } } @@ -326,7 +334,9 @@ private fun HomeScreenWithList( // if there are no posts, and no error, let the user refresh manually TextButton( onClick = onRefreshPosts, - modifier.padding(innerPadding).fillMaxSize(), + modifier + .padding(innerPadding) + .fillMaxSize(), ) { Text( stringResource(id = R.string.home_tap_to_load_content), @@ -475,9 +485,9 @@ private fun PostList( private fun FullScreenLoading() { Box( modifier = - Modifier - .fillMaxSize() - .wrapContentSize(Alignment.Center), + Modifier + .fillMaxSize() + .wrapContentSize(Alignment.Center), ) { CircularProgressIndicator() } @@ -551,10 +561,10 @@ private fun PostListPopularSection( ) Row( modifier = - Modifier - .horizontalScroll(rememberScrollState()) - .height(IntrinsicSize.Max) - .padding(horizontal = 16.dp), + Modifier + .horizontalScroll(rememberScrollState()) + .height(IntrinsicSize.Max) + .padding(horizontal = 16.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { for (post in posts) { @@ -618,14 +628,14 @@ private fun HomeSearch( placeholder = { Text(stringResource(R.string.home_search)) }, leadingIcon = { Icon(Icons.Filled.Search, null) }, modifier = - modifier - .fillMaxWidth() - .interceptKey(Key.Enter) { - // submit a search query when Enter is pressed - submitSearch(onSearchInputChanged, context) - keyboardController?.hide() - focusManager.clearFocus(force = true) - }, + modifier + .fillMaxWidth() + .interceptKey(Key.Enter) { + // submit a search query when Enter is pressed + submitSearch(onSearchInputChanged, context) + keyboardController?.hide() + focusManager.clearFocus(force = true) + }, singleLine = true, // keyboardOptions change the newline key to a search key on the soft keyboard keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), @@ -694,15 +704,37 @@ private fun HomeTopAppBar( ) { val context = LocalContext.current val title = stringResource(id = R.string.app_name) + var toastText = stringResource(id = R.string.toast_text_default) + + // Estado que controla la visibilidad del ícono de búsqueda + var showSearchIcon by remember { mutableStateOf(false) } + + // Inicializa Firebase Remote Config + val remoteConfig = Firebase.remoteConfig + + LaunchedEffect(Unit) { + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 1 + } + remoteConfig.setConfigSettingsAsync(configSettings) + remoteConfig.setDefaultsAsync(mapOf("show_search_icon" to true, "toast_text" to "")) + + while (true) { + // Obtiene el valor de Remote Config y actualiza el estado + remoteConfig.fetchAndActivate().addOnCompleteListener { task -> + if (task.isSuccessful) { + showSearchIcon = remoteConfig.getBoolean("show_search_icon") + toastText = remoteConfig.getString("toast_text") + } + } + // Espera 5 segundos antes de la próxima verificación + delay(5000L) + } + } + CenterAlignedTopAppBar( title = { - Image( - painter = painterResource(R.drawable.ic_jetnews_wordmark), - contentDescription = title, - contentScale = ContentScale.Inside, - colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary), - modifier = Modifier.fillMaxWidth(), - ) + Text(title) }, navigationIcon = { IconButton(onClick = openDrawer) { @@ -713,18 +745,19 @@ private fun HomeTopAppBar( } }, actions = { - IconButton(onClick = { -// Toast.makeText( -// context, -// "Search is not yet implemented in this configuration", -// Toast.LENGTH_LONG -// ).show() - throw RuntimeException("Test Crash") // Force a crash - }) { - Icon( - imageVector = Icons.Filled.Search, - contentDescription = stringResource(R.string.cd_search), - ) + if (showSearchIcon) { + IconButton(onClick = { + Toast.makeText( + context, + toastText, + Toast.LENGTH_LONG + ).show() + }) { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = stringResource(R.string.cd_search), + ) + } } }, scrollBehavior = scrollBehavior, diff --git a/JetNews/app/src/main/res/values/strings.xml b/JetNews/app/src/main/res/values/strings.xml index 5b438b2367..b05c7160c2 100644 --- a/JetNews/app/src/main/res/values/strings.xml +++ b/JetNews/app/src/main/res/values/strings.xml @@ -14,6 +14,7 @@ --> Jetnews + "" Can\'t update latest news Retry Add to favorites