Skip to content

feat: add basic wrapping to support compose #2201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: feat/migrate-to-kotlin
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 44 additions & 35 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,45 +1,53 @@
// NOTE: this project uses Gradle Kotlin DSL. More common build.gradle instructions can be found in
// the main README.
plugins {
id("com.android.application")
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
id("org.jetbrains.compose")
id("com.google.gms.google-services")
id("kotlin-kapt") // ← kapt drives annotation processors
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
id("kotlin-kapt") // ← kapt drives annotation processors
id("kotlin-kapt")

}

android {
namespace = "com.firebase.uidemo"
compileSdk = Config.SdkVersions.compile

namespace = "com.firebase.uidemo"

defaultConfig {
minSdk = Config.SdkVersions.min
targetSdk = Config.SdkVersions.target

versionName = Config.version
versionCode = 1

minSdk = Config.SdkVersions.min
targetSdk = Config.SdkVersions.target
versionName = Config.version
versionCode = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get rid of all the extra whitespaces (across all files) - I don't think it's common to use this formatting in Kotlin (at least I've never seen before)

Suggested change
minSdk = Config.SdkVersions.min
targetSdk = Config.SdkVersions.target
versionName = Config.version
versionCode = 1
minSdk = Config.SdkVersions.min
targetSdk = Config.SdkVersions.target
versionName = Config.version
versionCode = 1

multiDexEnabled = true
resourcePrefix("fui_")
vectorDrawables.useSupportLibrary = true
}

defaultConfig {
multiDexEnabled = true
}

buildTypes {
named("release").configure {
release {
// For the purposes of the sample, allow testing of a proguarded release build
// using the debug key
signingConfig = signingConfigs["debug"]

postprocessing {
isRemoveUnusedCode = true
isRemoveUnusedCode = true
isRemoveUnusedResources = true
isObfuscate = true
isOptimizeCode = true
isObfuscate = true
isOptimizeCode = true
}
}
}

lint {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

buildFeatures {
viewBinding = true
compose = true
}

lint {
// Common lint options across all modules

disable += mutableSetOf(
Expand All @@ -59,16 +67,7 @@ android {
abortOnError = true

baseline = file("$rootDir/library/quality/lint-baseline.xml")
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

buildFeatures {
viewBinding = true
}
}
}

dependencies {
Expand All @@ -80,23 +79,33 @@ dependencies {
implementation(project(":database"))
implementation(project(":storage"))

implementation(Config.Libs.Misc.glide)
kapt(Config.Libs.Misc.glideCompiler)

implementation(Config.Libs.Provider.facebook)
// Needed to override Facebook
implementation(Config.Libs.Androidx.cardView)
implementation(Config.Libs.Androidx.cardView)
implementation(Config.Libs.Androidx.customTabs)

implementation(Config.Libs.Misc.glide)
annotationProcessor(Config.Libs.Misc.glideCompiler)

// Used for FirestorePagingActivity
implementation(Config.Libs.Androidx.paging)

// The following dependencies are not required to use the Firebase UI library.
// They are used to make some aspects of the demo app implementation simpler for
// demonstrative purposes, and you may find them useful in your own apps; YMMV.

implementation(Config.Libs.Misc.permissions)
implementation(Config.Libs.Androidx.constraint)
debugImplementation(Config.Libs.Misc.leakCanary)

val composeBom = platform("androidx.compose:compose-bom:2025.02.00")
implementation(composeBom)
androidTestImplementation(composeBom)

implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.10.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5")
debugImplementation("androidx.compose.ui:ui-tooling")
releaseImplementation("androidx.compose.ui:ui-tooling-preview")
}

apply(plugin = "com.google.gms.google-services")
kapt { correctErrorTypes = true } // optional but avoids some kapt warnings
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
<activity
android:name=".auth.AnonymousUpgradeActivity"
android:label="@string/title_anonymous_upgrade" />
<activity
android:name=".auth.compose.AuthComposeActivity"
android:label="@string/auth_compose_title"
android:exported="false" />

<!-- Firestore demo -->
<activity
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/firebase/uidemo/ChooserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.firebase.ui.auth.util.ExtraConstants;
import com.firebase.uidemo.auth.AnonymousUpgradeActivity;
import com.firebase.uidemo.auth.AuthUiActivity;
import com.firebase.uidemo.auth.compose.AuthComposeActivity;
import com.firebase.uidemo.database.firestore.FirestoreChatActivity;
import com.firebase.uidemo.database.firestore.FirestorePagingActivity;
import com.firebase.uidemo.database.realtime.FirebaseDbPagingActivity;
Expand Down Expand Up @@ -65,6 +66,7 @@ private static class ActivityChooserAdapter
extends RecyclerView.Adapter<ActivityStarterHolder> {
private static final Class[] CLASSES = new Class[]{
AuthUiActivity.class,
AuthComposeActivity.class,
AnonymousUpgradeActivity.class,
FirestoreChatActivity.class,
FirestorePagingActivity.class,
Expand All @@ -75,6 +77,7 @@ private static class ActivityChooserAdapter

private static final int[] DESCRIPTION_NAMES = new int[]{
R.string.title_auth_activity,
R.string.auth_compose_title,
R.string.title_anonymous_upgrade,
R.string.title_firestore_activity,
R.string.title_firestore_paging_activity,
Expand All @@ -84,6 +87,7 @@ private static class ActivityChooserAdapter
};

private static final int[] DESCRIPTION_IDS = new int[]{
R.string.desc_auth,
R.string.desc_auth,
R.string.desc_anonymous_upgrade,
R.string.desc_firestore,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
import com.firebase.uidemo.R;
import com.firebase.uidemo.databinding.SignedInLayoutBinding;
import com.firebase.uidemo.storage.GlideApp;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.auth.EmailAuthProvider;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.firebase.uidemo.auth.compose

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import com.firebase.ui.auth.AuthUI
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
import com.firebase.uidemo.R
import com.firebase.uidemo.auth.SignedInActivity
import com.firebase.uidemo.ui.theme.FirebaseUIDemoTheme

class AuthComposeActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FirebaseUIDemoTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
AuthScreen { result ->
handleSignInResponse(result)
}
}
}
}
}

private fun handleSignInResponse(result: FirebaseAuthUIAuthenticationResult) {
when (result.resultCode) {
RESULT_OK -> {
// Successfully signed in
val response = result.idpResponse
startActivity(SignedInActivity.createIntent(this, response))
finish()
}
else -> {
// Sign in failed
val response = result.idpResponse
if (response == null) {
// User pressed back button
return
}
// Handle other error cases
}
}
}

companion object {
fun createIntent(context: Context): Intent {
return Intent(context, AuthComposeActivity::class.java)
}
}
}
41 changes: 41 additions & 0 deletions app/src/main/java/com/firebase/uidemo/auth/compose/AuthScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.firebase.uidemo.auth.compose

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.firebase.ui.auth.AuthUI
import com.firebase.ui.auth.AuthUI.IdpConfig
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
import com.firebase.ui.auth.compose.FirebaseAuthUI
import com.firebase.uidemo.R
import com.google.firebase.auth.EmailAuthProvider
import com.google.firebase.auth.GoogleAuthProvider

@Composable
fun AuthScreen(
onSignInResult: (FirebaseAuthUIAuthenticationResult) -> Unit
) {
val providers = listOf(
IdpConfig.GoogleBuilder().build(),
IdpConfig.EmailBuilder().build()
)

Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
FirebaseAuthUI(
providers = providers,
onSignInResult = onSignInResult,
theme = R.style.AppTheme,
logo = R.drawable.firebase_auth_120dp,
tosUrl = "https://www.google.com/policies/terms/",
privacyPolicyUrl = "https://www.google.com/policies/privacy/",
enableCredentials = true,
enableAnonymousUpgrade = false
)
}
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/firebase/uidemo/ui/theme/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.firebase.uidemo.ui.theme

import androidx.compose.ui.graphics.Color

val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)

val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
58 changes: 58 additions & 0 deletions app/src/main/java/com/firebase/uidemo/ui/theme/Theme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.firebase.uidemo.ui.theme

import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat

private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)

private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
)

@Composable
fun FirebaseUIDemoTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.primary.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}

MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
31 changes: 31 additions & 0 deletions app/src/main/java/com/firebase/uidemo/ui/theme/Type.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.firebase.uidemo.ui.theme

import androidx.compose.material3.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

val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
),
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
)
)
Loading