diff --git a/build.gradle b/build.gradle index a302e22708..86337508f2 100644 --- a/build.gradle +++ b/build.gradle @@ -60,7 +60,11 @@ configurations { } dependencies { - ktlint "com.github.shyiko:ktlint:0.31.0" + ktlint ("com.pinterest:ktlint:0.48.2") { + attributes { + attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL)) + } + } } task("ktlint", type: JavaExec, group: "verification") { @@ -75,7 +79,7 @@ task("ktlint", type: JavaExec, group: "verification") { description = "Check Kotlin code style." classpath = configurations.ktlint - main = "com.github.shyiko.ktlint.Main" + mainClass.set("com.pinterest.ktlint.Main") args = [ "--format", "--android", diff --git a/config/app/build.gradle b/config/app/build.gradle index 17f01745ba..b53a787ced 100644 --- a/config/app/build.gradle +++ b/config/app/build.gradle @@ -12,23 +12,42 @@ android { defaultConfig { applicationId "com.google.samples.quickstart.config" - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 33 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } } buildTypes { release { - minifyEnabled true + minifyEnabled = true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } buildFeatures { viewBinding = true + compose = true + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + composeOptions { + kotlinCompilerExtensionVersion '1.3.2' + } + packagingOptions { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } } } @@ -37,6 +56,7 @@ dependencies { implementation project(":internal:chooserx") implementation 'com.google.android.material:material:1.7.0' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' // Import the Firebase BoM (see: https://firebase.google.com/docs/android/learn-more#bom) implementation platform('com.google.firebase:firebase-bom:31.1.0') @@ -50,9 +70,21 @@ dependencies { // For an optimal experience using Remote Config, add the Firebase SDK // for Google Analytics. This is recommended, but not required. implementation 'com.google.firebase:firebase-analytics' + implementation 'androidx.compose.material:material:1.3.1' + + debugImplementation "androidx.fragment:fragment-testing:1.5.4" + // Jetpack Compose + implementation "androidx.compose.ui:ui:$compose_version" + implementation "androidx.compose.material:material:$compose_version" + implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + implementation 'androidx.activity:activity-compose:1.5.1' + implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1' + androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' - androidTestImplementation 'androidx.test:rules:1.5.0' - androidTestImplementation 'androidx.test:runner:1.5.1' - androidTestImplementation 'androidx.test.ext:junit:1.1.4' + androidTestImplementation 'androidx.test:rules:1.4.0' + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" + debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" } diff --git a/config/app/src/main/AndroidManifest.xml b/config/app/src/main/AndroidManifest.xml index 6065a87b1b..ed2b8ff18a 100644 --- a/config/app/src/main/AndroidManifest.xml +++ b/config/app/src/main/AndroidManifest.xml @@ -5,20 +5,23 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:theme="@style/AppTheme" > - + android:theme="@style/AppTheme"> + + - - + android:exported="true" + android:label="@string/app_name"> @@ -27,4 +30,4 @@ - + \ No newline at end of file diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/EntryChoiceActivity.kt b/config/app/src/main/java/com/google/samples/quickstart/config/EntryChoiceActivity.kt index e6ffe34e8d..47c0d5c45a 100644 --- a/config/app/src/main/java/com/google/samples/quickstart/config/EntryChoiceActivity.kt +++ b/config/app/src/main/java/com/google/samples/quickstart/config/EntryChoiceActivity.kt @@ -8,18 +8,30 @@ class EntryChoiceActivity : BaseEntryChoiceActivity() { override fun getChoices(): List { return listOf( - Choice( - "Java", - "Run the Firebase Remote Config quickstart written in Java.", - Intent( - this, - com.google.samples.quickstart.config.java.MainActivity::class.java)), - Choice( - "Kotlin", - "Run the Firebase Remote Config quickstart written in Kotlin.", - Intent( - this, - com.google.samples.quickstart.config.kotlin.MainActivity::class.java)) + Choice( + "Java", + "Run the Firebase Remote Config quickstart written in Java.", + Intent( + this, + com.google.samples.quickstart.config.java.MainActivity::class.java + ) + ), + Choice( + "Kotlin", + "Run the Firebase Remote Config quickstart written in Kotlin.", + Intent( + this, + com.google.samples.quickstart.config.kotlin.MainActivity::class.java + ) + ), + Choice( + "Compose", + "Run the Firebase Remote Config quickstart written in Compose.", + Intent( + this, + com.google.samples.quickstart.config.kotlin.MainComposeActivity::class.java + ) + ) ) } } diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/java/MainActivity.java b/config/app/src/main/java/com/google/samples/quickstart/config/java/MainActivity.java index e4c537568e..9143ad64e7 100644 --- a/config/app/src/main/java/com/google/samples/quickstart/config/java/MainActivity.java +++ b/config/app/src/main/java/com/google/samples/quickstart/config/java/MainActivity.java @@ -65,27 +65,21 @@ public void onClick(View v) { }); // Get Remote Config instance. - // [START get_remote_config_instance] mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance(); - // [END get_remote_config_instance] // Create a Remote Config Setting to enable developer mode, which you can use to increase // the number of fetches available per hour during development. Also use Remote Config // Setting to set the minimum fetch interval. - // [START enable_dev_mode] FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder() .setMinimumFetchIntervalInSeconds(3600) .build(); mFirebaseRemoteConfig.setConfigSettingsAsync(configSettings); - // [END enable_dev_mode] // Set default Remote Config parameter values. An app uses the in-app default values, and // when you need to adjust those defaults, you set an updated value for only the values you // want to change in the Firebase console. See Best Practices in the README for more // information. - // [START set_default_values] mFirebaseRemoteConfig.setDefaultsAsync(R.xml.remote_config_defaults); - // [END set_default_values] fetchWelcome(); } @@ -96,7 +90,6 @@ public void onClick(View v) { private void fetchWelcome() { mWelcomeTextView.setText(mFirebaseRemoteConfig.getString(LOADING_PHRASE_CONFIG_KEY)); - // [START fetch_config_with_callback] mFirebaseRemoteConfig.fetchAndActivate() .addOnCompleteListener(this, new OnCompleteListener() { @Override @@ -114,18 +107,14 @@ public void onComplete(@NonNull Task task) { displayWelcomeMessage(); } }); - // [END fetch_config_with_callback] } /** * Display a welcome message in all caps if welcome_message_caps is set to true. Otherwise, * display a welcome message as fetched from welcome_message. */ - // [START display_welcome_message] private void displayWelcomeMessage() { - // [START get_config_values] String welcomeMessage = mFirebaseRemoteConfig.getString(WELCOME_MESSAGE_KEY); - // [END get_config_values] if (mFirebaseRemoteConfig.getBoolean(WELCOME_MESSAGE_CAPS_KEY)) { mWelcomeTextView.setAllCaps(true); } else { @@ -133,5 +122,4 @@ private void displayWelcomeMessage() { } mWelcomeTextView.setText(welcomeMessage); } - // [END display_welcome_message] } diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/MainActivity.kt b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/MainActivity.kt index 90a38e3941..9b191c78ea 100644 --- a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/MainActivity.kt +++ b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/MainActivity.kt @@ -1,99 +1,38 @@ package com.google.samples.quickstart.config.kotlin import android.os.Bundle -import android.util.Log -import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import com.google.firebase.ktx.Firebase -import com.google.firebase.remoteconfig.FirebaseRemoteConfig -import com.google.firebase.remoteconfig.ktx.get -import com.google.firebase.remoteconfig.ktx.remoteConfig -import com.google.firebase.remoteconfig.ktx.remoteConfigSettings +import androidx.lifecycle.lifecycleScope import com.google.samples.quickstart.config.R import com.google.samples.quickstart.config.databinding.ActivityMainBinding +import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { - - private lateinit var remoteConfig: FirebaseRemoteConfig private lateinit var binding: ActivityMainBinding + private val viewModel: RemoteConfigViewModel by viewModels { RemoteConfigViewModel.Factory } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) - binding.fetchButton.setOnClickListener { fetchWelcome() } - - // Get Remote Config instance. - // [START get_remote_config_instance] - remoteConfig = Firebase.remoteConfig - // [END get_remote_config_instance] + binding.fetchButton.setOnClickListener { viewModel.fetchRemoteConfig() } - // Create a Remote Config Setting to enable developer mode, which you can use to increase - // the number of fetches available per hour during development. Also use Remote Config - // Setting to set the minimum fetch interval. - // [START enable_dev_mode] - val configSettings = remoteConfigSettings { - minimumFetchIntervalInSeconds = 3600 - } - remoteConfig.setConfigSettingsAsync(configSettings) - // [END enable_dev_mode] + viewModel.enableDeveloperMode() - // Set default Remote Config parameter values. An app uses the in-app default values, and - // when you need to adjust those defaults, you set an updated value for only the values you - // want to change in the Firebase console. See Best Practices in the README for more - // information. - // [START set_default_values] - remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults) - // [END set_default_values] + viewModel.setDefaultValues(R.xml.remote_config_defaults) - fetchWelcome() - } - - /** - * Fetch a welcome message from the Remote Config service, and then activate it. - */ - private fun fetchWelcome() { - binding.welcomeTextView.text = remoteConfig[LOADING_PHRASE_CONFIG_KEY].asString() - - // [START fetch_config_with_callback] - remoteConfig.fetchAndActivate() - .addOnCompleteListener(this) { task -> - if (task.isSuccessful) { - val updated = task.result - Log.d(TAG, "Config params updated: $updated") - Toast.makeText(this, "Fetch and activate succeeded", - Toast.LENGTH_SHORT).show() - } else { - Toast.makeText(this, "Fetch failed", - Toast.LENGTH_SHORT).show() - } - displayWelcomeMessage() - } - // [END fetch_config_with_callback] - } - - /** - * Display a welcome message in all caps if welcome_message_caps is set to true. Otherwise, - * display a welcome message as fetched from welcome_message. - */ - // [START display_welcome_message] - private fun displayWelcomeMessage() { - // [START get_config_values] - val welcomeMessage = remoteConfig[WELCOME_MESSAGE_KEY].asString() - // [END get_config_values] - binding.welcomeTextView.isAllCaps = remoteConfig[WELCOME_MESSAGE_CAPS_KEY].asBoolean() - binding.welcomeTextView.text = welcomeMessage - } - - companion object { - - private const val TAG = "MainActivity" + lifecycleScope.launch { + viewModel.welcomeMessage.collect { welcomeMessage -> + binding.welcomeTextView.text = welcomeMessage + } + } - // Remote Config keys - private const val LOADING_PHRASE_CONFIG_KEY = "loading_phrase" - private const val WELCOME_MESSAGE_KEY = "welcome_message" - private const val WELCOME_MESSAGE_CAPS_KEY = "welcome_message_caps" + lifecycleScope.launch { + viewModel.allCaps.collect { isWelcomeAllCaps -> + binding.welcomeTextView.isAllCaps = isWelcomeAllCaps + } + } } - // [END display_welcome_message] } diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/MainComposeActivity.kt b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/MainComposeActivity.kt new file mode 100644 index 0000000000..30d9764d57 --- /dev/null +++ b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/MainComposeActivity.kt @@ -0,0 +1,151 @@ +package com.google.samples.quickstart.config.kotlin + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.Spacer + +import androidx.compose.material.Scaffold +import androidx.compose.material.TopAppBar +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.material.rememberScaffoldState + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.viewmodel.compose.viewModel +import com.google.samples.quickstart.config.R +import com.google.samples.quickstart.config.kotlin.ui.theme.ConfigTheme +import kotlinx.coroutines.launch + +class MainComposeActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + ConfigTheme { + // A surface container using the 'background' color from the theme + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colors.background + ) { + MainAppView() + } + } + } + } +} + +@Composable +fun MainAppView( + modifier: Modifier = Modifier, + lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, + remoteConfigViewModel: RemoteConfigViewModel = viewModel(factory = RemoteConfigViewModel.Factory) +) { + DisposableEffect(lifecycleOwner) { + val observer = LifecycleEventObserver { _, event -> + // Configure Firebase Remote Config when the screen is created + if (event == Lifecycle.Event.ON_CREATE) { + remoteConfigViewModel.enableDeveloperMode() + remoteConfigViewModel.setDefaultValues(R.xml.remote_config_defaults) + } + } + + lifecycleOwner.lifecycle.addObserver(observer) + + onDispose { + lifecycleOwner.lifecycle.removeObserver(observer) + } + } + + val scaffoldState = rememberScaffoldState() // this contains the `SnackbarHostState` + val coroutineScope = rememberCoroutineScope() + + Scaffold( + scaffoldState = scaffoldState, + topBar = { + TopAppBar( + backgroundColor = colorResource(R.color.colorPrimary) + ) { + Text( + text = stringResource(R.string.app_name), + style = androidx.compose.material.MaterialTheme.typography.h6, + textAlign = TextAlign.Center, + modifier = Modifier.padding(8.dp), + color = Color.White + ) + } + }, content = { + Column(modifier = Modifier.padding(it).fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + Spacer(modifier = Modifier.height(24.dp)) + + Image(painter = painterResource(R.drawable.firebase_lockup_400), contentDescription = "") + + // Text displayed + val remoteConfigDisplayText by remoteConfigViewModel.welcomeMessage.collectAsState() + + val allCaps by remoteConfigViewModel.allCaps.collectAsState() + + Text( + text = if (allCaps) { + remoteConfigDisplayText.uppercase() + } else { + remoteConfigDisplayText + }, + fontSize = 16.sp + ) + Spacer(modifier = Modifier.height(160.dp)) + + // Button to fetch remote welcome + Button( + colors = ButtonDefaults.buttonColors(backgroundColor = colorResource(R.color.colorAccent)), + onClick = { + // Fetch config and update the display text + remoteConfigViewModel.fetchRemoteConfig() + // Display Scaffold + coroutineScope.launch { // using the `coroutineScope` to `launch` showing the snackbar + // taking the `snackbarHostState` from the attached `scaffoldState` + val snackbarResult = scaffoldState.snackbarHostState.showSnackbar( + message = "Fetching remote message..." + ) + } + } + ) { + Text( + text = stringResource(R.string.fetch_remote_welcome_message), + fontSize = 20.sp, + color = Color.White + ) + } + } + }) + + + +} + diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/RemoteConfigViewModel.kt b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/RemoteConfigViewModel.kt new file mode 100644 index 0000000000..9f54bc7910 --- /dev/null +++ b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/RemoteConfigViewModel.kt @@ -0,0 +1,96 @@ +package com.google.samples.quickstart.config.kotlin + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.CreationExtras +import com.google.firebase.ktx.Firebase +import com.google.firebase.remoteconfig.FirebaseRemoteConfig +import com.google.firebase.remoteconfig.ktx.get +import com.google.firebase.remoteconfig.ktx.remoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfigSettings +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import kotlinx.coroutines.tasks.await + +class RemoteConfigViewModel( + private val remoteConfig: FirebaseRemoteConfig +) : ViewModel() { + private val _welcomeMessage = MutableStateFlow("Welcome...") + val welcomeMessage: StateFlow = _welcomeMessage + + private val _allCaps = MutableStateFlow(false) + val allCaps: StateFlow = _allCaps + + fun enableDeveloperMode() { + viewModelScope.launch { + // Create a Remote Config Setting to enable developer mode, which you can use to increase + // the number of fetches available per hour during development. Also use Remote Config + // Setting to set the minimum fetch interval. + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 3600 + } + remoteConfig.setConfigSettingsAsync(configSettings).await() + } + } + + fun setDefaultValues(defaultValuesXml: Int) { + viewModelScope.launch { + // Set default Remote Config parameter values. An app uses the in-app default values, and + // when you need to adjust those defaults, you set an updated value for only the values you + // want to change in the Firebase console. See Best Practices in the README for more + // information. + remoteConfig.setDefaultsAsync(defaultValuesXml).await() + + // Update the UI with the default parameter values + updateUI() + } + } + + fun fetchRemoteConfig() { + _welcomeMessage.value = remoteConfig[LOADING_PHRASE_CONFIG_KEY].asString() + + viewModelScope.launch { + try { + val updated = remoteConfig.fetchAndActivate().await() + Log.d(TAG, "Config params updated: $updated") + + // Update the UI with the fetched parameter values + updateUI() + } catch (e: Exception) { + Log.e(TAG, "There was an error fetching and activating your config") + _welcomeMessage.value = e.message ?: "Unknown Error" + } + } + } + + private fun updateUI() { + _welcomeMessage.value = remoteConfig[WELCOME_MESSAGE_KEY].asString() + _allCaps.value = remoteConfig[WELCOME_MESSAGE_CAPS_KEY].asBoolean() + } + + companion object { + const val TAG = "RemoteConfigViewModel" + + // Remote Config keys + private const val LOADING_PHRASE_CONFIG_KEY = "loading_phrase" + private const val WELCOME_MESSAGE_KEY = "welcome_message" + private const val WELCOME_MESSAGE_CAPS_KEY = "welcome_message_caps" + + // Used to inject this ViewModel's dependencies + // See also: https://developer.android.com/topic/libraries/architecture/viewmodel/viewmodel-factories + val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun create( + modelClass: Class, + extras: CreationExtras + ): T { + // Get Remote Config instance. + val remoteConfig = Firebase.remoteConfig + return RemoteConfigViewModel(remoteConfig) as T + } + } + } +} diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Color.kt b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Color.kt new file mode 100644 index 0000000000..ae14d722f3 --- /dev/null +++ b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.google.samples.quickstart.config.kotlin.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val FirebaseBlue = Color(0xFF0288D1) // copied from colors.xml +val FirebaseBannerBlue = Color(0xFF039BE5) // copied from colors.xml +val FirebaseOrange = Color(0xFFFFA000) // copied from colors.xml diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Shape.kt b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Shape.kt new file mode 100644 index 0000000000..1c1509ac47 --- /dev/null +++ b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Shape.kt @@ -0,0 +1,11 @@ +package com.google.samples.quickstart.config.kotlin.ui.theme + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Shapes +import androidx.compose.ui.unit.dp + +val Shapes = Shapes( + small = RoundedCornerShape(16.dp), + medium = RoundedCornerShape(4.dp), + large = RoundedCornerShape(0.dp) +) \ No newline at end of file diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Theme.kt b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Theme.kt new file mode 100644 index 0000000000..c3157d1e61 --- /dev/null +++ b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Theme.kt @@ -0,0 +1,47 @@ +package com.google.samples.quickstart.config.kotlin.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material.MaterialTheme +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors +import androidx.compose.runtime.Composable + +private val DarkColorPalette = darkColors( + primary = Purple80, + primaryVariant = PurpleGrey80, + secondary = Pink80 +) + +private val LightColorPalette = lightColors( + primary = Purple80, + primaryVariant = PurpleGrey80, + secondary = Pink80 + + /* Other default colors to override + background = Color.White, + surface = Color.White, + onPrimary = Color.White, + onSecondary = Color.Black, + onBackground = Color.Black, + onSurface = Color.Black, + */ +) + +@Composable +fun ConfigTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable () -> Unit +) { + val colors = if (darkTheme) { + DarkColorPalette + } else { + LightColorPalette + } + + MaterialTheme( + colors = colors, + typography = Typography, + shapes = Shapes, + content = content + ) +} \ No newline at end of file diff --git a/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Type.kt b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Type.kt new file mode 100644 index 0000000000..7d8bc30dd7 --- /dev/null +++ b/config/app/src/main/java/com/google/samples/quickstart/config/kotlin/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.google.samples.quickstart.config.kotlin.ui.theme + +import androidx.compose.material.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + body1 = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) diff --git a/config/app/src/main/res/values/strings.xml b/config/app/src/main/res/values/strings.xml index f03807996a..3f18f23cec 100644 --- a/config/app/src/main/res/values/strings.xml +++ b/config/app/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ Firebase Remote Config - fetch remote welcome + Fetch remote welcome diff --git a/config/build.gradle b/config/build.gradle index f9bdde250d..4f8407c741 100644 --- a/config/build.gradle +++ b/config/build.gradle @@ -1,6 +1,9 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext { + compose_version = '1.3.0' + } repositories { mavenLocal() google() diff --git a/config/gradle.properties b/config/gradle.properties index aac7c9b461..29b531a1d1 100644 --- a/config/gradle.properties +++ b/config/gradle.properties @@ -10,7 +10,7 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx1536m - +android.useAndroidX=true # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects