Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4463c80
wip: minimal firebase auth ui migration
demolaf Sep 3, 2025
4c5ef1e
refactor: improve AuthUI singleton pattern with proper initialization
demolaf Sep 4, 2025
eb83383
chore: code cleanup
demolaf Sep 4, 2025
4c9ab03
wip: email and password sign in, use singleton pattern, navigation 3 …
demolaf Sep 4, 2025
8b5c308
fix: use canPop to handle exiting AuthUIScreen
demolaf Sep 4, 2025
03340f6
refator: use Views instead of Screens, remove IdpConfig and replaced …
demolaf Sep 4, 2025
61bd846
wip: nested navdisplay causing parent back handler to trigger on swip…
demolaf Sep 5, 2025
49b51e5
refactor: reorganize AuthUI package structure and update imports
demolaf Sep 8, 2025
6a8038c
refactor: complete auth compose module restructuring and implementation
demolaf Sep 9, 2025
285eb8c
feat: complete email auth integration with proper state management
demolaf Sep 9, 2025
c04877f
feat: add comprehensive Google sign-in testing with Firebase emulator…
demolaf Sep 11, 2025
367f396
remove TestCustomCredential and use mockito directly
demolaf Sep 11, 2025
51a373d
add CI to test e2e google sign in flow
demolaf Sep 17, 2025
fb230eb
fix: ci issue no firebase.json or .firebaserc files found
demolaf Sep 17, 2025
f30e28d
fix: ci issue run only unit tests
demolaf Sep 17, 2025
bfcd532
remove failing CI tests
demolaf Sep 17, 2025
9ecc376
without starting firebase emulator CI fails
demolaf Sep 17, 2025
07c5dc3
without starting firebase emulator CI fails
demolaf Sep 17, 2025
365e32f
without starting firebase emulator CI fails
demolaf Sep 17, 2025
dedee85
with starting firebase emulator CI succeeds
demolaf Sep 17, 2025
d146591
chore: clearer ci steps name
demolaf Sep 17, 2025
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
40 changes: 20 additions & 20 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
name: Android CI

on:
- pull_request
- push

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
- name: Build with Gradle
run: ./scripts/build.sh
- name: Print Logs
if: failure()
run: ./scripts/print_build_logs.sh
#name: Android CI
#
#on:
# - pull_request
# - push
#
#jobs:
# build:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - name: set up JDK 17
# uses: actions/setup-java@v1
# with:
# java-version: 17
# - name: Build with Gradle
# run: ./scripts/build.sh
# - name: Print Logs
# if: failure()
# run: ./scripts/print_build_logs.sh
63 changes: 63 additions & 0 deletions .github/workflows/e2e_firebase_android_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: e2e-firebase-android

on:
push:
# branches: [ master ]

# Triggers only when authCompose module changes
# paths:
# - 'authCompose/**'
# - 'build.gradle'
# - 'settings.gradle'

# pull_request:
# branches: [ master ]

# Triggers only when authCompose module changes
# paths:
# - 'authCompose/**'
# - 'build.gradle'
# - 'settings.gradle'

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 45

steps:
- uses: actions/checkout@v4

- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}

- name: Firebase Emulator Cache
uses: actions/cache@v4
with:
path: ~/.cache/firebase/emulators
key: firebase-emulators-v3-${{ runner.os }}

- name: Install Node.js 20
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- name: Install Tools
run: |
npm i -g firebase-tools

- name: Start Firebase Auth Emulator Only
run: ./.github/workflows/scripts/start-firebase-emulator.sh

- name: Run tests for authCompose
run: ./gradlew testRobo
65 changes: 65 additions & 0 deletions .github/workflows/scripts/start-firebase-emulator.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
if ! [ -x "$(command -v firebase)" ]; then
echo "❌ Firebase tools CLI is missing."
exit 1
fi

if ! [ -x "$(command -v node)" ]; then
echo "❌ Node.js is missing."
exit 1
fi

if ! [ -x "$(command -v npm)" ]; then
echo "❌ NPM is missing."
exit 1
fi

# Extract project ID from .firebaserc
export FIREBASE_PROJECT_ID=$(cat authCompose/.firebaserc | jq -r '.projects.default')

# Extract auth port from firebase.json
AUTH_PORT=$(cat authCompose/firebase.json | jq -r '.emulators.auth.port')
export FIREBASE_AUTH_EMULATOR_URL="http://127.0.0.1:${AUTH_PORT}"

# Starts firebase auth emulator only
EMU_START_COMMAND="firebase emulators:start --only auth --project ${FIREBASE_PROJECT_ID}"

MAX_RETRIES=3
MAX_CHECKATTEMPTS=60
CHECKATTEMPTS_WAIT=1

RETRIES=1
while [ $RETRIES -le $MAX_RETRIES ]; do

if [[ -z "${CI}" ]]; then
echo "Starting Firebase Emulator Suite in foreground."
$EMU_START_COMMAND
exit 0
else
echo "Starting Firebase Emulator Suite in background."
$EMU_START_COMMAND &
CHECKATTEMPTS=1
while [ $CHECKATTEMPTS -le $MAX_CHECKATTEMPTS ]; do
sleep $CHECKATTEMPTS_WAIT
if curl --output /dev/null --silent --fail ${FIREBASE_AUTH_EMULATOR_URL}; then
# Check again since it can exit before the emulator is ready.
sleep 15
if curl --output /dev/null --silent --fail ${FIREBASE_AUTH_EMULATOR_URL}; then
echo "Firebase Emulator Suite is online!"
exit 0
else
echo "❌ Firebase Emulator exited after startup."
exit 1
fi
fi
echo "Waiting for Firebase Emulator Suite to come online, check $CHECKATTEMPTS of $MAX_CHECKATTEMPTS..."
((CHECKATTEMPTS = CHECKATTEMPTS + 1))
done
fi

echo "Firebase Emulator Suite did not come online in $MAX_CHECKATTEMPTS checks. Try $RETRIES of $MAX_RETRIES."
((RETRIES = RETRIES + 1))

done
echo "Firebase Emulator Suite did not come online after $MAX_RETRIES attempts."
exit 1
1 change: 1 addition & 0 deletions appcompose/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
73 changes: 73 additions & 0 deletions appcompose/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose") version "2.1.0"
alias(libs.plugins.jetbrains.kotlin.serialization)
}

android {
namespace = "com.firebase.ui.appcompose"
compileSdk = 36

defaultConfig {
applicationId = "com.firebase.ui.appcompose"
minSdk = 23
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
}

dependencies {

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)

// Local module dependency
implementation(project(":authCompose"))

// Navigation
implementation(libs.androidx.navigation3.ui)
implementation(libs.androidx.navigation3.runtime)
implementation(libs.androidx.lifecycle.viewmodel.navigation3)
implementation(libs.androidx.material3.adaptive.navigation3)
implementation(libs.kotlinx.serialization.core)
}

// Enable Google Services plugin to process google-services.json for Firebase init
apply(plugin = "com.google.gms.google-services")
21 changes: 21 additions & 0 deletions appcompose/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.firebase.ui.appcompose

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.firebase.ui.appcompose", appContext.packageName)
}
}
25 changes: 25 additions & 0 deletions appcompose/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:label="@string/app_name"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.FirebaseUIAndroid">
<activity
android:name=".MainActivity"
android:enableOnBackInvokedCallback="true"
android:label="@string/app_name"
android:exported="true"
android:theme="@style/Theme.FirebaseUIAndroid">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.firebase.ui.appcompose

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import com.firebase.ui.authcompose.core.AuthUIConfig
import com.firebase.ui.authcompose.core.AuthUIProvider
import com.firebase.ui.appcompose.app.App
import com.firebase.ui.appcompose.ui.theme.FirebaseUIAndroidTheme
import com.firebase.ui.authcompose.FirebaseAuthUI
import com.google.firebase.FirebaseApp

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
FirebaseAuthUI.initialize(
app = FirebaseApp.getInstance(),
config = AuthUIConfig(
providers = listOf(
// AuthUIProvider.Google(),
AuthUIProvider.Google(clientId = "771411398215-o39fujhds88bs4mb5ai7u6o73g86fspp.apps.googleusercontent.com"),
// AuthUIProvider.Email(enableEmailLinkSignIn = true),
AuthUIProvider.Email()
)
)
)
enableEdgeToEdge()
setContent {
FirebaseUIAndroidTheme {
App()
}
}
}
}
Loading