Skip to content

Commit 0bb8125

Browse files
committed
feat: add basic wrapping to support compose
1 parent ca245bc commit 0bb8125

File tree

16 files changed

+425
-111
lines changed

16 files changed

+425
-111
lines changed

app/build.gradle.kts

+44-35
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,53 @@
11
// NOTE: this project uses Gradle Kotlin DSL. More common build.gradle instructions can be found in
22
// the main README.
33
plugins {
4-
id("com.android.application")
4+
id("com.android.application")
5+
id("org.jetbrains.kotlin.android")
6+
id("org.jetbrains.kotlin.plugin.compose")
7+
id("org.jetbrains.compose")
8+
id("com.google.gms.google-services")
9+
id("kotlin-kapt") // ← kapt drives annotation processors
510
}
611

712
android {
13+
namespace = "com.firebase.uidemo"
814
compileSdk = Config.SdkVersions.compile
915

10-
namespace = "com.firebase.uidemo"
11-
1216
defaultConfig {
13-
minSdk = Config.SdkVersions.min
14-
targetSdk = Config.SdkVersions.target
15-
16-
versionName = Config.version
17-
versionCode = 1
18-
17+
minSdk = Config.SdkVersions.min
18+
targetSdk = Config.SdkVersions.target
19+
versionName = Config.version
20+
versionCode = 1
21+
multiDexEnabled = true
1922
resourcePrefix("fui_")
2023
vectorDrawables.useSupportLibrary = true
2124
}
2225

23-
defaultConfig {
24-
multiDexEnabled = true
25-
}
26-
2726
buildTypes {
28-
named("release").configure {
27+
release {
2928
// For the purposes of the sample, allow testing of a proguarded release build
3029
// using the debug key
3130
signingConfig = signingConfigs["debug"]
32-
3331
postprocessing {
34-
isRemoveUnusedCode = true
32+
isRemoveUnusedCode = true
3533
isRemoveUnusedResources = true
36-
isObfuscate = true
37-
isOptimizeCode = true
34+
isObfuscate = true
35+
isOptimizeCode = true
3836
}
3937
}
4038
}
4139

42-
lint {
40+
compileOptions {
41+
sourceCompatibility = JavaVersion.VERSION_17
42+
targetCompatibility = JavaVersion.VERSION_17
43+
}
44+
45+
buildFeatures {
46+
viewBinding = true
47+
compose = true
48+
}
49+
50+
lint {
4351
// Common lint options across all modules
4452

4553
disable += mutableSetOf(
@@ -59,16 +67,7 @@ android {
5967
abortOnError = true
6068

6169
baseline = file("$rootDir/library/quality/lint-baseline.xml")
62-
}
63-
64-
compileOptions {
65-
sourceCompatibility = JavaVersion.VERSION_17
66-
targetCompatibility = JavaVersion.VERSION_17
67-
}
68-
69-
buildFeatures {
70-
viewBinding = true
71-
}
70+
}
7271
}
7372

7473
dependencies {
@@ -80,23 +79,33 @@ dependencies {
8079
implementation(project(":database"))
8180
implementation(project(":storage"))
8281

82+
implementation(Config.Libs.Misc.glide)
83+
kapt(Config.Libs.Misc.glideCompiler)
84+
8385
implementation(Config.Libs.Provider.facebook)
8486
// Needed to override Facebook
85-
implementation(Config.Libs.Androidx.cardView)
87+
implementation(Config.Libs.Androidx.cardView)
8688
implementation(Config.Libs.Androidx.customTabs)
87-
88-
implementation(Config.Libs.Misc.glide)
89-
annotationProcessor(Config.Libs.Misc.glideCompiler)
90-
9189
// Used for FirestorePagingActivity
9290
implementation(Config.Libs.Androidx.paging)
9391

9492
// The following dependencies are not required to use the Firebase UI library.
9593
// They are used to make some aspects of the demo app implementation simpler for
9694
// demonstrative purposes, and you may find them useful in your own apps; YMMV.
95+
9796
implementation(Config.Libs.Misc.permissions)
9897
implementation(Config.Libs.Androidx.constraint)
9998
debugImplementation(Config.Libs.Misc.leakCanary)
99+
100+
val composeBom = platform("androidx.compose:compose-bom:2025.02.00")
101+
implementation(composeBom)
102+
androidTestImplementation(composeBom)
103+
104+
implementation("androidx.compose.material3:material3")
105+
implementation("androidx.activity:activity-compose:1.10.0")
106+
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5")
107+
debugImplementation("androidx.compose.ui:ui-tooling")
108+
releaseImplementation("androidx.compose.ui:ui-tooling-preview")
100109
}
101110

102-
apply(plugin = "com.google.gms.google-services")
111+
kapt { correctErrorTypes = true } // optional but avoids some kapt warnings

app/src/main/AndroidManifest.xml

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
<activity
4343
android:name=".auth.AnonymousUpgradeActivity"
4444
android:label="@string/title_anonymous_upgrade" />
45+
<activity
46+
android:name=".auth.compose.AuthComposeActivity"
47+
android:label="@string/auth_compose_title"
48+
android:exported="false" />
4549

4650
<!-- Firestore demo -->
4751
<activity

app/src/main/java/com/firebase/uidemo/ChooserActivity.java

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.firebase.ui.auth.util.ExtraConstants;
2626
import com.firebase.uidemo.auth.AnonymousUpgradeActivity;
2727
import com.firebase.uidemo.auth.AuthUiActivity;
28+
import com.firebase.uidemo.auth.compose.AuthComposeActivity;
2829
import com.firebase.uidemo.database.firestore.FirestoreChatActivity;
2930
import com.firebase.uidemo.database.firestore.FirestorePagingActivity;
3031
import com.firebase.uidemo.database.realtime.FirebaseDbPagingActivity;
@@ -65,6 +66,7 @@ private static class ActivityChooserAdapter
6566
extends RecyclerView.Adapter<ActivityStarterHolder> {
6667
private static final Class[] CLASSES = new Class[]{
6768
AuthUiActivity.class,
69+
AuthComposeActivity.class,
6870
AnonymousUpgradeActivity.class,
6971
FirestoreChatActivity.class,
7072
FirestorePagingActivity.class,
@@ -75,6 +77,7 @@ private static class ActivityChooserAdapter
7577

7678
private static final int[] DESCRIPTION_NAMES = new int[]{
7779
R.string.title_auth_activity,
80+
R.string.auth_compose_title,
7881
R.string.title_anonymous_upgrade,
7982
R.string.title_firestore_activity,
8083
R.string.title_firestore_paging_activity,
@@ -84,6 +87,7 @@ private static class ActivityChooserAdapter
8487
};
8588

8689
private static final int[] DESCRIPTION_IDS = new int[]{
90+
R.string.desc_auth,
8791
R.string.desc_auth,
8892
R.string.desc_anonymous_upgrade,
8993
R.string.desc_firestore,

app/src/main/java/com/firebase/uidemo/auth/SignedInActivity.java

-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import com.firebase.uidemo.R;
3030
import com.firebase.uidemo.databinding.SignedInLayoutBinding;
3131
import com.firebase.uidemo.storage.GlideApp;
32-
import com.google.android.gms.tasks.OnCompleteListener;
33-
import com.google.android.gms.tasks.Task;
3432
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
3533
import com.google.android.material.snackbar.Snackbar;
3634
import com.google.firebase.auth.EmailAuthProvider;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.firebase.uidemo.auth.compose
2+
3+
import android.content.Context
4+
import android.content.Intent
5+
import android.os.Bundle
6+
import androidx.activity.ComponentActivity
7+
import androidx.activity.compose.setContent
8+
import androidx.compose.foundation.layout.fillMaxSize
9+
import androidx.compose.material3.MaterialTheme
10+
import androidx.compose.material3.Surface
11+
import androidx.compose.ui.Modifier
12+
import com.firebase.ui.auth.AuthUI
13+
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
14+
import com.firebase.uidemo.R
15+
import com.firebase.uidemo.auth.SignedInActivity
16+
import com.firebase.uidemo.ui.theme.FirebaseUIDemoTheme
17+
18+
class AuthComposeActivity : ComponentActivity() {
19+
override fun onCreate(savedInstanceState: Bundle?) {
20+
super.onCreate(savedInstanceState)
21+
setContent {
22+
FirebaseUIDemoTheme {
23+
Surface(
24+
modifier = Modifier.fillMaxSize(),
25+
color = MaterialTheme.colorScheme.background
26+
) {
27+
AuthScreen { result ->
28+
handleSignInResponse(result)
29+
}
30+
}
31+
}
32+
}
33+
}
34+
35+
private fun handleSignInResponse(result: FirebaseAuthUIAuthenticationResult) {
36+
when (result.resultCode) {
37+
RESULT_OK -> {
38+
// Successfully signed in
39+
val response = result.idpResponse
40+
startActivity(SignedInActivity.createIntent(this, response))
41+
finish()
42+
}
43+
else -> {
44+
// Sign in failed
45+
val response = result.idpResponse
46+
if (response == null) {
47+
// User pressed back button
48+
return
49+
}
50+
// Handle other error cases
51+
}
52+
}
53+
}
54+
55+
companion object {
56+
fun createIntent(context: Context): Intent {
57+
return Intent(context, AuthComposeActivity::class.java)
58+
}
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.firebase.uidemo.auth.compose
2+
3+
import androidx.compose.foundation.layout.Box
4+
import androidx.compose.foundation.layout.fillMaxSize
5+
import androidx.compose.material3.CircularProgressIndicator
6+
import androidx.compose.runtime.Composable
7+
import androidx.compose.ui.Alignment
8+
import androidx.compose.ui.Modifier
9+
import com.firebase.ui.auth.AuthUI
10+
import com.firebase.ui.auth.AuthUI.IdpConfig
11+
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
12+
import com.firebase.ui.auth.compose.FirebaseAuthUI
13+
import com.firebase.uidemo.R
14+
import com.google.firebase.auth.EmailAuthProvider
15+
import com.google.firebase.auth.GoogleAuthProvider
16+
17+
@Composable
18+
fun AuthScreen(
19+
onSignInResult: (FirebaseAuthUIAuthenticationResult) -> Unit
20+
) {
21+
val providers = listOf(
22+
IdpConfig.GoogleBuilder().build(),
23+
IdpConfig.EmailBuilder().build()
24+
)
25+
26+
Box(
27+
modifier = Modifier.fillMaxSize(),
28+
contentAlignment = Alignment.Center
29+
) {
30+
FirebaseAuthUI(
31+
providers = providers,
32+
onSignInResult = onSignInResult,
33+
theme = R.style.AppTheme,
34+
logo = R.drawable.firebase_auth_120dp,
35+
tosUrl = "https://www.google.com/policies/terms/",
36+
privacyPolicyUrl = "https://www.google.com/policies/privacy/",
37+
enableCredentials = true,
38+
enableAnonymousUpgrade = false
39+
)
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.firebase.uidemo.ui.theme
2+
3+
import androidx.compose.ui.graphics.Color
4+
5+
val Purple80 = Color(0xFFD0BCFF)
6+
val PurpleGrey80 = Color(0xFFCCC2DC)
7+
val Pink80 = Color(0xFFEFB8C8)
8+
9+
val Purple40 = Color(0xFF6650a4)
10+
val PurpleGrey40 = Color(0xFF625b71)
11+
val Pink40 = Color(0xFF7D5260)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.firebase.uidemo.ui.theme
2+
3+
import android.app.Activity
4+
import android.os.Build
5+
import androidx.compose.foundation.isSystemInDarkTheme
6+
import androidx.compose.material3.MaterialTheme
7+
import androidx.compose.material3.darkColorScheme
8+
import androidx.compose.material3.dynamicDarkColorScheme
9+
import androidx.compose.material3.dynamicLightColorScheme
10+
import androidx.compose.material3.lightColorScheme
11+
import androidx.compose.runtime.Composable
12+
import androidx.compose.runtime.SideEffect
13+
import androidx.compose.ui.graphics.toArgb
14+
import androidx.compose.ui.platform.LocalContext
15+
import androidx.compose.ui.platform.LocalView
16+
import androidx.core.view.WindowCompat
17+
18+
private val DarkColorScheme = darkColorScheme(
19+
primary = Purple80,
20+
secondary = PurpleGrey80,
21+
tertiary = Pink80
22+
)
23+
24+
private val LightColorScheme = lightColorScheme(
25+
primary = Purple40,
26+
secondary = PurpleGrey40,
27+
tertiary = Pink40
28+
)
29+
30+
@Composable
31+
fun FirebaseUIDemoTheme(
32+
darkTheme: Boolean = isSystemInDarkTheme(),
33+
dynamicColor: Boolean = true,
34+
content: @Composable () -> Unit
35+
) {
36+
val colorScheme = when {
37+
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
38+
val context = LocalContext.current
39+
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
40+
}
41+
darkTheme -> DarkColorScheme
42+
else -> LightColorScheme
43+
}
44+
val view = LocalView.current
45+
if (!view.isInEditMode) {
46+
SideEffect {
47+
val window = (view.context as Activity).window
48+
window.statusBarColor = colorScheme.primary.toArgb()
49+
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
50+
}
51+
}
52+
53+
MaterialTheme(
54+
colorScheme = colorScheme,
55+
typography = Typography,
56+
content = content
57+
)
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.firebase.uidemo.ui.theme
2+
3+
import androidx.compose.material3.Typography
4+
import androidx.compose.ui.text.TextStyle
5+
import androidx.compose.ui.text.font.FontFamily
6+
import androidx.compose.ui.text.font.FontWeight
7+
import androidx.compose.ui.unit.sp
8+
9+
val Typography = Typography(
10+
bodyLarge = TextStyle(
11+
fontFamily = FontFamily.Default,
12+
fontWeight = FontWeight.Normal,
13+
fontSize = 16.sp,
14+
lineHeight = 24.sp,
15+
letterSpacing = 0.5.sp
16+
),
17+
titleLarge = TextStyle(
18+
fontFamily = FontFamily.Default,
19+
fontWeight = FontWeight.Normal,
20+
fontSize = 22.sp,
21+
lineHeight = 28.sp,
22+
letterSpacing = 0.sp
23+
),
24+
labelSmall = TextStyle(
25+
fontFamily = FontFamily.Default,
26+
fontWeight = FontWeight.Medium,
27+
fontSize = 11.sp,
28+
lineHeight = 16.sp,
29+
letterSpacing = 0.5.sp
30+
)
31+
)

0 commit comments

Comments
 (0)