diff --git a/README.md b/README.md index 7c8ac80..8ed68cf 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,18 @@ An Android client for Open-Feeedback https://github.com/HugoGresse/open-feedback The Composable `OpenFeedback` is the entry point to vote on a session. It'll make calls between the Firebase which host your OpenFeedback instance and your mobile application. It is -mandatory to pass the `OpenFeedbackState` to give the Firebase configuration and your open-feedback -configuration which is common for all sessions of your event. +mandatory to pass the `OpenFeedbackFirebaseConfig` to give the Firebase instance which is common +for all sessions of your event. + +Note that it is mandatory to keep this instance unique in your application because it creates the +`FirebaseApp` instance which is the active connection between your mobile application and the +OpenFeedback Firebase host. Consider to save this configuration in your custom `Application` class +or in singleton in your dependency injection. ```kotlin // In your Application class -val firebaseConfig = FirebaseConfig( +val openfeedbackFirebaseConfig = OpenFeedbackFirebaseConfig( + context = applicationContext, projectId = "", applicationId = "", apiKey = "", @@ -23,7 +29,7 @@ val firebaseConfig = FirebaseConfig( // In your Compose screen OpenFeedback( - config = MyApp.firebaseConfig, + config = (application as MyApp).openfeedbackFirebaseConfig, projectId = "", sessionId = "", language = "" @@ -32,7 +38,12 @@ OpenFeedback( That's all! -If you want to see an example, please check the [sample-app](sample-app/src/main/java/io/openfeedback/android/sample/MainActivity.kt). +See the [sample-app](sample-app/src/main/java/io/openfeedback/android/sample/MainActivity.kt) app +module if you want to see this implementation in action. + +If you are interested to create your own UI, you can use the component `OpenFeedbackLayout`. This +`Composable` takes OpenFeedback Model UI in input and you can use `OpenFeedbackViewModel` in the +viewmodel artifact to get the data from the Firebase host. ## Installation @@ -43,11 +54,14 @@ repositories { mavenCentral() } +val openfeedbackVersion = "0.0.6" dependencies { // Material 2 - implementation("io.openfeedback:feedback-android-sdk-m2:0.0.6") + implementation("io.openfeedback:feedback-android-sdk-m2:$openfeedbackVersion") // Material 3 - implementation("io.openfeedback:feedback-android-sdk-m3:0.0.6") + implementation("io.openfeedback:feedback-android-sdk-m3:$openfeedbackVersion") + // ViewModel + implementation("io.openfeedback:feedback-android-sdk-viewmodel:$openfeedbackVersion") } ``` diff --git a/openfeedback-m2/src/main/java/io/openfeedback/android/m2/OpenFeedbackLayout.kt b/openfeedback-m2/src/main/java/io/openfeedback/android/m2/OpenFeedbackLayout.kt index 99ace12..1355cb9 100644 --- a/openfeedback-m2/src/main/java/io/openfeedback/android/m2/OpenFeedbackLayout.kt +++ b/openfeedback-m2/src/main/java/io/openfeedback/android/m2/OpenFeedbackLayout.kt @@ -11,7 +11,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import io.openfeedback.android.FirebaseConfig +import io.openfeedback.android.viewmodels.OpenFeedbackFirebaseConfig import io.openfeedback.android.viewmodels.OpenFeedbackUiState import io.openfeedback.android.viewmodels.OpenFeedbackViewModel import io.openfeedback.android.viewmodels.models.UISessionFeedback @@ -19,18 +19,16 @@ import io.openfeedback.android.viewmodels.models.UIVoteItem @Composable fun OpenFeedback( - config: FirebaseConfig, + config: OpenFeedbackFirebaseConfig, projectId: String, sessionId: String, language: String, modifier: Modifier = Modifier, loading: @Composable () -> Unit = { Loading(modifier = modifier) } ) { - val context = LocalContext.current val viewModel: OpenFeedbackViewModel = viewModel( factory = OpenFeedbackViewModel.Factory.create( - context = context, - firebaseConfig = config, + firebaseApp = config.firebaseApp, projectId = projectId, sessionId = sessionId, language = language diff --git a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/OpenFeedbackLayout.kt b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/OpenFeedbackLayout.kt index 7c0ecd2..d75b8ba 100644 --- a/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/OpenFeedbackLayout.kt +++ b/openfeedback-m3/src/main/kotlin/io/openfeedback/android/m3/OpenFeedbackLayout.kt @@ -15,11 +15,10 @@ import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import io.openfeedback.android.FirebaseConfig +import io.openfeedback.android.viewmodels.OpenFeedbackFirebaseConfig import io.openfeedback.android.viewmodels.OpenFeedbackUiState import io.openfeedback.android.viewmodels.OpenFeedbackViewModel import io.openfeedback.android.viewmodels.models.UIDot @@ -29,7 +28,7 @@ import io.openfeedback.android.viewmodels.models.UIVoteItem @OptIn(ExperimentalMaterial3Api::class) @Composable fun OpenFeedback( - config: FirebaseConfig, + config: OpenFeedbackFirebaseConfig, projectId: String, sessionId: String, language: String, @@ -37,11 +36,9 @@ fun OpenFeedback( loading: @Composable () -> Unit = { Loading(modifier = modifier) } ) { val configuration = LocalConfiguration.current - val context = LocalContext.current val viewModel: OpenFeedbackViewModel = viewModel( factory = OpenFeedbackViewModel.Factory.create( - context = context, - firebaseConfig = config, + firebaseApp = config.firebaseApp, projectId = projectId, sessionId = sessionId, language = language diff --git a/openfeedback/src/main/java/io/openfeedback/android/sources/FirebaseFactory.kt b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/FirebaseFactory.kt similarity index 79% rename from openfeedback/src/main/java/io/openfeedback/android/sources/FirebaseFactory.kt rename to openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/FirebaseFactory.kt index 41f5c70..dd75797 100644 --- a/openfeedback/src/main/java/io/openfeedback/android/sources/FirebaseFactory.kt +++ b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/FirebaseFactory.kt @@ -1,14 +1,13 @@ -package io.openfeedback.android.sources +package io.openfeedback.android.viewmodels import android.content.Context import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseOptions -import io.openfeedback.android.FirebaseConfig -object FirebaseFactory { +internal object FirebaseFactory { fun create( context: Context, - config: FirebaseConfig, + config: OpenFeedbackFirebaseConfig, appName: String = "openfeedback" ): FirebaseApp { val options = FirebaseOptions.Builder() diff --git a/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackFirebaseConfig.kt b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackFirebaseConfig.kt new file mode 100644 index 0000000..a194ad6 --- /dev/null +++ b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackFirebaseConfig.kt @@ -0,0 +1,16 @@ +package io.openfeedback.android.viewmodels + +import android.content.Context +import androidx.compose.runtime.Immutable + +@Immutable +data class OpenFeedbackFirebaseConfig( + val context: Context, + val projectId: String, + val applicationId: String, + val apiKey: String, + val databaseUrl: String, + val appName: String = "openfeedback" +) { + val firebaseApp = FirebaseFactory.create(context, this, appName) +} diff --git a/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt index fa3d99f..300996c 100644 --- a/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt +++ b/openfeedback-viewmodel/src/main/java/io/openfeedback/android/viewmodels/OpenFeedbackViewModel.kt @@ -1,15 +1,12 @@ package io.openfeedback.android.viewmodels -import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.google.firebase.FirebaseApp -import io.openfeedback.android.FirebaseConfig import io.openfeedback.android.OpenFeedbackRepository import io.openfeedback.android.caches.OptimisticVoteCaching import io.openfeedback.android.model.VoteStatus -import io.openfeedback.android.sources.FirebaseFactory import io.openfeedback.android.sources.OpenFeedbackAuth import io.openfeedback.android.sources.OpenFeedbackFirestore import io.openfeedback.android.viewmodels.mappers.convertToUiSessionFeedback @@ -27,14 +24,14 @@ sealed class OpenFeedbackUiState { } class OpenFeedbackViewModel( - private val firebase: FirebaseApp, + private val firebaseApp: FirebaseApp, private val projectId: String, private val sessionId: String, private val language: String ) : ViewModel() { private val repository = OpenFeedbackRepository( - auth = OpenFeedbackAuth.Factory.create(firebase), - firestore = OpenFeedbackFirestore.Factory.create(firebase), + auth = OpenFeedbackAuth.Factory.create(firebaseApp), + firestore = OpenFeedbackFirestore.Factory.create(firebaseApp), optimisticVoteCaching = OptimisticVoteCaching() ) @@ -75,14 +72,13 @@ class OpenFeedbackViewModel( object Factory { fun create( - context: Context, - firebaseConfig: FirebaseConfig, + firebaseApp: FirebaseApp, projectId: String, sessionId: String, language: String ) = object : ViewModelProvider.Factory { override fun create(modelClass: Class): T = OpenFeedbackViewModel( - firebase = FirebaseFactory.create(context, firebaseConfig), + firebaseApp = firebaseApp, projectId = projectId, sessionId = sessionId, language = language diff --git a/openfeedback/src/main/java/io/openfeedback/android/FirebaseConfig.kt b/openfeedback/src/main/java/io/openfeedback/android/FirebaseConfig.kt deleted file mode 100644 index e9412af..0000000 --- a/openfeedback/src/main/java/io/openfeedback/android/FirebaseConfig.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.openfeedback.android - -class FirebaseConfig( - val projectId: String, - val applicationId: String, - val apiKey: String, - val databaseUrl: String -) \ No newline at end of file diff --git a/sample-app/src/main/AndroidManifest.xml b/sample-app/src/main/AndroidManifest.xml index c325d1e..3edf783 100644 --- a/sample-app/src/main/AndroidManifest.xml +++ b/sample-app/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ + android:exported="true" + android:theme="@style/AppTheme.NoActionBar"> @@ -20,4 +21,4 @@ - \ No newline at end of file + diff --git a/sample-app/src/main/java/io/openfeedback/android/sample/MainActivity.kt b/sample-app/src/main/java/io/openfeedback/android/sample/MainActivity.kt index 1412b47..b3a1e74 100644 --- a/sample-app/src/main/java/io/openfeedback/android/sample/MainActivity.kt +++ b/sample-app/src/main/java/io/openfeedback/android/sample/MainActivity.kt @@ -21,7 +21,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import io.openfeedback.android.FirebaseConfig +import io.openfeedback.android.viewmodels.OpenFeedbackFirebaseConfig import io.openfeedback.android.m2.OpenFeedback import io.openfeedback.android.sample.theme.DesignSystem import io.openfeedback.android.sample.theme.OpenFeedbackTheme @@ -31,12 +31,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val projectId = "mMHR63ARZQpPidFQISyc" - val firebaseConfig = FirebaseConfig( - projectId = "openfeedback-b7ab9", - applicationId = "1:765209934800:android:a6bb09f3deabc2277297d5", - apiKey = "AIzaSyC_cfbh8xKwF8UPxCeasGcsHyK4s5yZFeA", - databaseUrl = "https://openfeedback-b7ab9.firebaseio.com" - ) + val openFeedbackFirebaseConfig = (application as MainApplication).openFeedbackFirebaseConfig setContent { var designSystem by rememberSaveable { mutableStateOf(DesignSystem.M2) } val isDark = isSystemInDarkTheme() @@ -55,7 +50,7 @@ class MainActivity : AppCompatActivity() { when (designSystem) { DesignSystem.M2 -> Scaffold { OpenFeedback( - config = firebaseConfig, + config = openFeedbackFirebaseConfig, projectId = projectId, sessionId = "173222", language = "en", @@ -66,7 +61,7 @@ class MainActivity : AppCompatActivity() { } DesignSystem.M3 -> androidx.compose.material3.Scaffold { io.openfeedback.android.m3.OpenFeedback( - config = firebaseConfig, + config = openFeedbackFirebaseConfig, projectId = projectId, sessionId = "173222", language = "en", diff --git a/sample-app/src/main/java/io/openfeedback/android/sample/MainApplication.kt b/sample-app/src/main/java/io/openfeedback/android/sample/MainApplication.kt new file mode 100644 index 0000000..bc4e0ee --- /dev/null +++ b/sample-app/src/main/java/io/openfeedback/android/sample/MainApplication.kt @@ -0,0 +1,19 @@ +package io.openfeedback.android.sample + +import android.app.Application +import io.openfeedback.android.viewmodels.OpenFeedbackFirebaseConfig + +class MainApplication: Application() { + lateinit var openFeedbackFirebaseConfig: OpenFeedbackFirebaseConfig + + override fun onCreate() { + super.onCreate() + openFeedbackFirebaseConfig = OpenFeedbackFirebaseConfig( + context = this, + projectId = "openfeedback-b7ab9", + applicationId = "1:765209934800:android:a6bb09f3deabc2277297d5", + apiKey = "AIzaSyC_cfbh8xKwF8UPxCeasGcsHyK4s5yZFeA", + databaseUrl = "https://openfeedback-b7ab9.firebaseio.com" + ) + } +}