Skip to content

Commit

Permalink
Merge pull request #9 from GerardPaligot/refactor/project-id
Browse files Browse the repository at this point in the history
refactor: can change openfeedback project id at runtime.
  • Loading branch information
martinbonnin authored Apr 6, 2023
2 parents 6c3d2d5 + 60de68a commit fa6bf89
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,41 @@ import io.openfeedback.android.viewmodels.OpenFeedbackViewModel
import io.openfeedback.android.viewmodels.models.UISessionFeedback
import io.openfeedback.android.viewmodels.models.UIVoteItem

@Deprecated(
message = "Use OpenFeedback component with projectId parameter."
)
@Composable
fun OpenFeedback(
openFeedbackState: OpenFeedbackConfig,
sessionId: String,
language: String,
modifier: Modifier = Modifier,
loading: @Composable () -> Unit = { Loading(modifier = modifier) }
) = OpenFeedback(
config = openFeedbackState,
projectId = openFeedbackState.openFeedbackProjectId,
sessionId = sessionId,
language = language,
modifier = modifier,
loading = loading
)

@Composable
fun OpenFeedback(
config: OpenFeedbackConfig,
projectId: String,
sessionId: String,
language: String,
modifier: Modifier = Modifier,
loading: @Composable () -> Unit = { Loading(modifier = modifier) }
) {
val viewModel: OpenFeedbackViewModel = viewModel(
factory = OpenFeedbackViewModel.Factory.create(openFeedbackState, sessionId, language)
factory = OpenFeedbackViewModel.Factory.create(
openFeedbackConfig = config,
projectId = projectId,
sessionId = sessionId,
language = language
)
)
val uiState = viewModel.uiState.collectAsState()
when (uiState.value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,41 @@ import io.openfeedback.android.viewmodels.OpenFeedbackViewModel
import io.openfeedback.android.viewmodels.models.UISessionFeedback
import io.openfeedback.android.viewmodels.models.UIVoteItem

@Deprecated(
message = "Use OpenFeedback component with projectId parameter."
)
@Composable
fun OpenFeedback(
openFeedbackState: OpenFeedbackConfig,
sessionId: String,
language: String,
modifier: Modifier = Modifier,
loading: @Composable () -> Unit = { Loading(modifier = modifier) }
) = OpenFeedback(
config = openFeedbackState,
projectId = openFeedbackState.openFeedbackProjectId,
sessionId = sessionId,
language = language,
modifier = modifier,
loading = loading
)

@Composable
fun OpenFeedback(
config: OpenFeedbackConfig,
projectId: String,
sessionId: String,
language: String,
modifier: Modifier = Modifier,
loading: @Composable () -> Unit = { Loading(modifier = modifier) }
) {
val viewModel: OpenFeedbackViewModel = viewModel(
factory = OpenFeedbackViewModel.Factory.create(openFeedbackState, sessionId, language)
factory = OpenFeedbackViewModel.Factory.create(
openFeedbackConfig = config,
projectId = projectId,
sessionId = sessionId,
language = language
)
)
val uiState = viewModel.uiState.collectAsState()
when (uiState.value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import io.openfeedback.android.OpenFeedbackConfig
import io.openfeedback.android.viewmodels.models.UISessionFeedback
import kotlinx.coroutines.flow.combine

/**
* A bunch of extensions to get UI models from a openFeedback object
*/
@Deprecated(
message = "Use getUISessionFeedback(projectId: String, sessionId: String, language: String) instead of this one.",
replaceWith = ReplaceWith("getUISessionFeedback(openFeedbackProjectId, sessionId, language)")
)
internal suspend fun OpenFeedbackConfig.getUISessionFeedback(
sessionId: String,
language: String
Expand All @@ -21,6 +22,24 @@ internal suspend fun OpenFeedbackConfig.getUISessionFeedback(
)
}

/**
* A bunch of extensions to get UI models from a openFeedback object
*/
internal suspend fun OpenFeedbackConfig.getUISessionFeedback(
projectId: String,
sessionId: String,
language: String
) = combine(
getProject(projectId),
getUserVotes(projectId, sessionId),
getTotalVotes(projectId, sessionId)
) { project, userVotes, totalVotes ->
return@combine UISessionFeedbackWithColors(
OpenFeedbackModelHelper.toUISessionFeedback(project, userVotes, totalVotes, language),
project.chipColors
)
}

internal data class UISessionFeedbackWithColors(
val session: UISessionFeedback,
val colors: List<String>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ sealed class OpenFeedbackUiState {

class OpenFeedbackViewModel(
private val openFeedbackConfig: OpenFeedbackConfig,
private val projectId: String,
private val sessionId: String,
private val language: String
) : ViewModel() {
Expand All @@ -26,7 +27,7 @@ class OpenFeedbackViewModel(

init {
viewModelScope.launch {
openFeedbackConfig.getUISessionFeedback(sessionId, language).collect {
openFeedbackConfig.getUISessionFeedback(projectId, sessionId, language).collect {
val oldSession =
if (uiState.value is OpenFeedbackUiState.Success) (uiState.value as OpenFeedbackUiState.Success).session
else null
Expand All @@ -43,17 +44,42 @@ class OpenFeedbackViewModel(

fun vote(voteItem: UIVoteItem) = viewModelScope.launch {
openFeedbackConfig.setVote(
projectId = projectId,
talkId = sessionId,
voteItemId = voteItem.id,
status = if (!voteItem.votedByUser) VoteStatus.Active else VoteStatus.Deleted
)
}

object Factory {
@Deprecated(
message = "Use create(openFeedbackConfig: OpenFeedbackConfig, projectId: String, sessionId: String, language: String) instead of this one.",
replaceWith = ReplaceWith("create(config, openFeedbackProjectId, sessionId, language)")
)
fun create(openFeedbackConfig: OpenFeedbackConfig, sessionId: String, language: String) =
object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T =
OpenFeedbackViewModel(openFeedbackConfig, sessionId, language) as T
OpenFeedbackViewModel(
openFeedbackConfig = openFeedbackConfig,
projectId = openFeedbackConfig.openFeedbackProjectId,
sessionId = sessionId,
language = language
) as T
}

fun create(
openFeedbackConfig: OpenFeedbackConfig,
projectId: String,
sessionId: String,
language: String
) = object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T =
OpenFeedbackViewModel(
openFeedbackConfig = openFeedbackConfig,
projectId = projectId,
sessionId = sessionId,
language = language
) as T
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ import java.util.Date
class OpenFeedbackConfig(
context: Context,
firebaseConfig: FirebaseConfig,
val openFeedbackProjectId: String,
appName: String = "openfeedback"
) {

val firestore: FirebaseFirestore
val auth: FirebaseAuth
var openFeedbackProjectId: String = ""

class OptimisticVotes(
var lastValue: Map<String, Long>?,
Expand All @@ -50,6 +49,18 @@ class OpenFeedbackConfig(
val databaseUrl: String
)

@Deprecated(
message = "Openfeedback project id should be passed in parameter in functions"
)
constructor(
context: Context,
firebaseConfig: FirebaseConfig,
openFeedbackProjectId: String,
appName: String = "openfeedback"
) : this(context, firebaseConfig, appName) {
this.openFeedbackProjectId = openFeedbackProjectId
}

init {
val options = FirebaseOptions.Builder()
.setProjectId(firebaseConfig.projectId)
Expand Down Expand Up @@ -83,19 +94,31 @@ class OpenFeedbackConfig(
auth.currentUser
}

suspend fun getProject(): Flow<Project> = flow {
@Deprecated(
message = "Use getProject(projectId: String) instead of this one.",
replaceWith = ReplaceWith("getProject(openFeedbackProjectId)")
)
suspend fun getProject(): Flow<Project> = getProject(openFeedbackProjectId)

suspend fun getProject(projectId: String): Flow<Project> = flow {
firestore.collection("projects")
.document(openFeedbackProjectId)
.document(projectId)
.toFlow()
.collect { documentSnapshot ->
documentSnapshot.toObject(Project::class.java)?.let { emit(it) }
}
}

fun getUserVotes(sessionId: String) = flow {
@Deprecated(
message = "Use getUserVotes(projectId: String, sessionId: String) instead of this one.",
replaceWith = ReplaceWith("getUserVotes(openFeedbackProjectId, sessionId)")
)
fun getUserVotes(sessionId: String) = getUserVotes(openFeedbackProjectId, sessionId)

fun getUserVotes(projectId: String, sessionId: String) = flow {
val user = getFirebaseUser()
if (user != null) {
firestore.collection("projects/$openFeedbackProjectId/userVotes")
firestore.collection("projects/$projectId/userVotes")
.whereEqualTo("userId", user.uid)
.toFlow()
.collect { querySnapshot ->
Expand All @@ -107,13 +130,20 @@ class OpenFeedbackConfig(
}
}

fun getTotalVotes(sessionId: String): Flow<Map<String, Long>> {
@Deprecated(
message = "Use getTotalVotes(projectId: String, sessionId: String) instead of this one.",
replaceWith = ReplaceWith("getTotalVotes(openFeedbackProjectId, sessionId)")
)
fun getTotalVotes(sessionId: String): Flow<Map<String, Long>> =
getTotalVotes(openFeedbackProjectId, sessionId)

fun getTotalVotes(projectId: String, sessionId: String): Flow<Map<String, Long>> {
val optimisticVotes = optimisticVotes.getOrPut(sessionId) {
OptimisticVotes(null, BroadcastChannel(Channel.CONFLATED))
}

val channel = Channel<Map<String, Long>>(Channel.CONFLATED)
val registration = firestore.collection("projects/$openFeedbackProjectId/sessionVotes")
val registration = firestore.collection("projects/$projectId/sessionVotes")
.document(sessionId)
.addSnapshotListener { documentSnapshot, firebaseFirestoreException ->
val totalVotes = documentSnapshot!!.data as? Map<String, Long>
Expand All @@ -139,10 +169,17 @@ class OpenFeedbackConfig(
return flowOf(flow1, flow2).flattenMerge()
}

@Deprecated(
message = "Use setVote(projectId: String, talkId: String, voteItemId: String, status: VoteStatus) instead of this one.",
replaceWith = ReplaceWith("setVote(openFeedbackProjectId, talkId, voteItemId, status)")
)
suspend fun setVote(talkId: String, voteItemId: String, status: VoteStatus) =
setVote(openFeedbackProjectId, talkId, voteItemId, status)

suspend fun setVote(projectId: String, talkId: String, voteItemId: String, status: VoteStatus) =
withFirebaseUser { firebaseUser ->
val collectionReference =
firestore.collection("projects/$openFeedbackProjectId/userVotes")
firestore.collection("projects/$projectId/userVotes")

val optimisticVotes = optimisticVotes.getOrPut(talkId) {
OptimisticVotes(null, BroadcastChannel(Channel.CONFLATED))
Expand Down Expand Up @@ -178,7 +215,7 @@ class OpenFeedbackConfig(
mapOf(
"id" to documentReference.id,
"createdAt" to Date(),
"projectId" to openFeedbackProjectId,
"projectId" to projectId,
"status" to status.value,
"talkId" to talkId,
"updatedAt" to Date(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class MainActivity : AppCompatActivity() {
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val projectId = "mMHR63ARZQpPidFQISyc"
val config = OpenFeedbackConfig(
context = this,
openFeedbackProjectId = "mMHR63ARZQpPidFQISyc",
firebaseConfig = OpenFeedbackConfig.FirebaseConfig(
projectId = "openfeedback-b7ab9",
applicationId = "1:765209934800:android:a6bb09f3deabc2277297d5",
Expand All @@ -60,7 +60,8 @@ class MainActivity : AppCompatActivity() {
when (designSystem) {
DesignSystem.M2 -> Scaffold {
OpenFeedback(
openFeedbackState = config,
config = config,
projectId = projectId,
sessionId = "173222",
language = "en",
modifier = Modifier
Expand All @@ -70,7 +71,8 @@ class MainActivity : AppCompatActivity() {
}
DesignSystem.M3 -> androidx.compose.material3.Scaffold {
io.openfeedback.android.m3.OpenFeedback(
openFeedbackState = config,
config = config,
projectId = projectId,
sessionId = "173222",
language = "en",
modifier = Modifier
Expand Down

0 comments on commit fa6bf89

Please sign in to comment.