Skip to content

Commit

Permalink
Merge pull request ContriHUB#1 from darkBlueLemon/InAppReview
Browse files Browse the repository at this point in the history
In app review
  • Loading branch information
darkBlueLemon authored Aug 7, 2024
2 parents 7558432 + fdef76a commit 52e78c6
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 76 deletions.
4 changes: 4 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,8 @@ dependencies {
// Firebase Analytics
implementation (platform(libs.firebase.bom))
implementation (libs.google.firebase.analytics)

// In App Review
implementation (libs.review)
implementation (libs.review.ktx)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.minimalisttodolist.pleasebethelastrecyclerview

import android.graphics.Color
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
Expand All @@ -10,21 +9,21 @@ import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.lifecycleScope
import androidx.room.Room
import com.google.android.play.core.review.ReviewManagerFactory
import com.google.firebase.Firebase
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.analytics
import com.google.firebase.analytics.logEvent
import com.minimalisttodolist.pleasebethelastrecyclerview.data.database.MIGRATION_1_2
import com.minimalisttodolist.pleasebethelastrecyclerview.data.preferences.AppPreferences
import com.minimalisttodolist.pleasebethelastrecyclerview.data.database.TaskDatabase
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.ReviewStateType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.ThemeType
import com.minimalisttodolist.pleasebethelastrecyclerview.ui.navigation.NavGraph
import com.minimalisttodolist.pleasebethelastrecyclerview.viewmodel.AppViewModel
Expand Down Expand Up @@ -69,7 +68,6 @@ class MainActivity : ComponentActivity() {
TaskViewModelFactory(db.dao, notificationHelper, dataStoreViewModel)
}

@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand Down Expand Up @@ -114,7 +112,6 @@ class MainActivity : ComponentActivity() {
)
}

@RequiresApi(Build.VERSION_CODES.O)
@Composable
private fun SetupTheme() {
val theme by dataStoreViewModel.theme.collectAsState()
Expand All @@ -137,12 +134,23 @@ class MainActivity : ComponentActivity() {
NavGraph(
taskViewModel = taskViewModel,
dataStoreViewModel = dataStoreViewModel,
appViewModel = appViewModel
appViewModel = appViewModel,
maybeShowReview = { maybeShowReview() }
)
}
}

@RequiresApi(Build.VERSION_CODES.O)
private fun maybeShowReview() {
val manager = ReviewManagerFactory.create(applicationContext)
manager.requestReviewFlow().addOnCompleteListener {
if(it.isSuccessful) {
manager.launchReviewFlow(this, it.result)
dataStoreViewModel.updateReviewState(ReviewStateType.SHOWN)
taskViewModel.logReviewStatus(ReviewStateType.SHOWN)
}
}
}

override fun onResume() {
super.onResume()
taskViewModel.reloadTasks()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.minimalisttodolist.pleasebethelastrecyclerview.data.model

enum class ReviewStateType {
NOT_YET,
SHOWN,
READY
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.FirstDayOfT
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.FontFamilyType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.FontWeightType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.RecurrenceType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.ReviewStateType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.SortType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.ThemeType
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -47,6 +48,7 @@ class AppPreferences private constructor(context: Context) {
val TUTORIAL_VISIBILITY = booleanPreferencesKey("tutorial_visibility")
val DUE_DATE_FILTER = stringPreferencesKey("due_date_filter")
val FIRST_DAY_OF_THE_WEEK = stringPreferencesKey("first_day_of_the_week")
val REVIEW_STATE = stringPreferencesKey("review_state")
}

val theme: Flow<ThemeType> = dataStore.data.map { preferences ->
Expand Down Expand Up @@ -93,6 +95,10 @@ class AppPreferences private constructor(context: Context) {
FirstDayOfTheWeekType.fromDisplayName(preferences[PreferencesKeys.FIRST_DAY_OF_THE_WEEK] ?: FirstDayOfTheWeekType.MONDAY.displayName)
}

val reviewState: Flow<ReviewStateType> = dataStore.data.map { preferences ->
ReviewStateType.valueOf(preferences[PreferencesKeys.REVIEW_STATE] ?: ReviewStateType.NOT_YET.name)
}

suspend fun saveTheme(theme: ThemeType) {
dataStore.edit { preferences -> preferences[PreferencesKeys.THEME] = theme.displayName }
}
Expand Down Expand Up @@ -143,4 +149,8 @@ class AppPreferences private constructor(context: Context) {
suspend fun saveFirstDayOfTheWeekType(firstDayOfTheWeekType: FirstDayOfTheWeekType) {
dataStore.edit { preferences -> preferences[PreferencesKeys.FIRST_DAY_OF_THE_WEEK] = firstDayOfTheWeekType.displayName }
}

suspend fun updateReviewState(reviewState: ReviewStateType) {
dataStore.edit { preferences -> preferences[PreferencesKeys.REVIEW_STATE] = reviewState.name }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.minimalisttodolist.pleasebethelastrecyclerview.ui.navigation

import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.material.ripple.LocalRippleTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
Expand All @@ -16,13 +14,13 @@ import com.minimalisttodolist.pleasebethelastrecyclerview.viewmodel.AppViewModel
import com.minimalisttodolist.pleasebethelastrecyclerview.viewmodel.TaskViewModel
import com.minimalisttodolist.pleasebethelastrecyclerview.ui.theme.NoRippleTheme

@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun NavGraph(
startDestination: String = "task_list",
taskViewModel: TaskViewModel,
dataStoreViewModel: DataStoreViewModel,
appViewModel: AppViewModel
appViewModel: AppViewModel,
maybeShowReview: () -> Unit
) {
val navController = rememberNavController()
val taskState by taskViewModel.state.collectAsState()
Expand All @@ -41,6 +39,7 @@ fun NavGraph(
onAppEvent = appViewModel::onEvent,
taskViewModel = taskViewModel,
dataStoreViewModel = dataStoreViewModel,
maybeShowReview = maybeShowReview
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.minimalisttodolist.pleasebethelastrecyclerview.ui.screens

import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandVertically
Expand Down Expand Up @@ -53,6 +51,7 @@ import com.minimalisttodolist.pleasebethelastrecyclerview.util.AnalyticsEvents
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.DueDateFilterType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.PriorityColor
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.RecurrenceType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.ReviewStateType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.Task
import com.minimalisttodolist.pleasebethelastrecyclerview.ui.components.CompleteIcon
import com.minimalisttodolist.pleasebethelastrecyclerview.ui.components.emptyStateMessages
Expand All @@ -76,7 +75,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@OptIn(ExperimentalFoundationApi::class)
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun TaskScreen(
taskState: TaskState,
Expand All @@ -85,6 +83,7 @@ fun TaskScreen(
onAppEvent: (AppEvent) -> Unit,
taskViewModel: TaskViewModel,
dataStoreViewModel: DataStoreViewModel,
maybeShowReview: () -> Unit
) {
val darkTheme = LocalDarkTheme.current

Expand Down Expand Up @@ -187,7 +186,11 @@ fun TaskScreen(
},
) { padding ->

TaskList(onEvent, onClearFilters = { onEvent(TaskEvent.ClearFilters) }, taskState, taskViewModel, padding, dataStoreViewModel)
TaskList(onEvent, onClearFilters = { onEvent(TaskEvent.ClearFilters) }, taskState, taskViewModel, padding, dataStoreViewModel, checkAndShowReview = {
if (dataStoreViewModel.reviewStateType.value == ReviewStateType.READY) {
maybeShowReview()
}
})

if (taskState.isAddTaskDialogVisible) {
AddTaskDialog(taskState, onEvent, taskViewModel, dataStoreViewModel, onAppEvent, isEdit = taskState.editingTaskId != null)
Expand Down Expand Up @@ -290,9 +293,8 @@ fun TaskScreen(
}
}

@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun TaskList(onEvent: (TaskEvent) -> Unit, onClearFilters: () -> Unit, taskState: TaskState, viewModel: TaskViewModel, padding: PaddingValues, dataStoreViewModel: DataStoreViewModel) {
fun TaskList(onEvent: (TaskEvent) -> Unit, onClearFilters: () -> Unit, taskState: TaskState, viewModel: TaskViewModel, padding: PaddingValues, dataStoreViewModel: DataStoreViewModel, checkAndShowReview: () -> Unit) {
val dueDateFilterType by dataStoreViewModel.dueDateFilter.collectAsState()
val recurrenceType by dataStoreViewModel.recurrenceFilter.collectAsState()
val filterText = buildString {
Expand Down Expand Up @@ -361,6 +363,7 @@ fun TaskList(onEvent: (TaskEvent) -> Unit, onClearFilters: () -> Unit, taskState
visible = false
}
}
checkAndShowReview()
},
viewModel = viewModel
)
Expand All @@ -369,7 +372,6 @@ fun TaskList(onEvent: (TaskEvent) -> Unit, onClearFilters: () -> Unit, taskState
}
}

@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun TaskItem(task: Task, onEdit: (Task) -> Unit, onDelete: (Task) -> Unit, viewModel: TaskViewModel) {
val darkTheme = LocalDarkTheme.current
Expand Down Expand Up @@ -426,10 +428,8 @@ fun TaskItem(task: Task, onEdit: (Task) -> Unit, onDelete: (Task) -> Unit, viewM
}
}

@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun DueDate_Recurrence_Note(
modifier: Modifier = Modifier,
task: Task,
viewModel: TaskViewModel
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ object AnalyticsEvents {
const val COMPLETE_TASK_CLICKED = "complete_task_clicked"
const val REPEAT_FILTER_CLICKED = "repeat_filter_change"
const val DUE_FILTER_CHANGE = "due_filter_change"
const val MAYBE_REVIEW_SHOWN = "maybe_review_shown"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.minimalisttodolist.pleasebethelastrecyclerview.viewmodel

import androidx.compose.ui.text.font.FontWeight
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
Expand All @@ -10,6 +9,7 @@ import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.FirstDayOfT
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.FontFamilyType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.FontWeightType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.RecurrenceType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.ReviewStateType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.SortType
import com.minimalisttodolist.pleasebethelastrecyclerview.data.preferences.AppPreferences
import com.minimalisttodolist.pleasebethelastrecyclerview.data.model.ThemeType
Expand Down Expand Up @@ -59,6 +59,10 @@ class DataStoreViewModel(private val appPreferences: AppPreferences) : ViewModel
.map { it }
.stateIn(viewModelScope, SharingStarted.Eagerly, FirstDayOfTheWeekType.MONDAY)

val reviewStateType: StateFlow<ReviewStateType> = appPreferences.reviewState
.map { it }
.stateIn(viewModelScope, SharingStarted.Eagerly, ReviewStateType.NOT_YET)

fun saveTheme(themeType: ThemeType) {
viewModelScope.launch { appPreferences.saveTheme(themeType) }
}
Expand Down Expand Up @@ -99,28 +103,8 @@ class DataStoreViewModel(private val appPreferences: AppPreferences) : ViewModel
viewModelScope.launch { appPreferences.saveFirstDayOfTheWeekType(firstDayOfTheWeekType) }
}

private fun fontWeightFromDisplayName(displayName: String): FontWeight {
return when (displayName) {
"Light" -> FontWeight.Light
"Thin" -> FontWeight.Thin
"Normal" -> FontWeight.Normal
"Medium" -> FontWeight.Medium
"Bold" -> FontWeight.Bold
"Black" -> FontWeight.Black
else -> FontWeight.Normal
}
}

private fun FontWeight.toDisplayString(): String {
return when (this) {
FontWeight.Light -> "Light"
FontWeight.Thin -> "Thin"
FontWeight.Normal -> "Normal"
FontWeight.Medium -> "Medium"
FontWeight.Bold -> "Bold"
FontWeight.Black -> "Black"
else -> "Normal"
}
fun updateReviewState(reviewState: ReviewStateType) {
viewModelScope.launch { appPreferences.updateReviewState(reviewState) }
}
}

Expand Down
Loading

0 comments on commit 52e78c6

Please sign in to comment.