Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/in app review #81

Merged
merged 14 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 6 additions & 18 deletions app/src/main/java/org/openedx/app/AppActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@ import org.openedx.app.databinding.ActivityAppBinding
import org.openedx.auth.presentation.signin.SignInFragment
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.extension.requestApplyInsetsWhenAttached
import org.openedx.core.presentation.global.AppData
import org.openedx.core.presentation.global.AppDataHolder
import org.openedx.core.presentation.global.InsetHolder
import org.openedx.core.presentation.global.WindowSizeHolder
import org.openedx.core.ui.WindowSize
import org.openedx.core.ui.WindowType
import org.openedx.profile.presentation.ProfileRouter
import org.openedx.whatsnew.WhatsNewFileManager
import org.openedx.whatsnew.data.storage.WhatsNewPreferences
import org.openedx.whatsnew.WhatsNewManager
import org.openedx.whatsnew.presentation.whatsnew.WhatsNewFragment

class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder, AppDataHolder {
class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder {

override val topInset: Int
get() = _insetTop
Expand All @@ -40,13 +37,9 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder, AppDataH
override val windowSize: WindowSize
get() = _windowSize

override val appData: AppData
get() = AppData(BuildConfig.VERSION_NAME)

private lateinit var binding: ActivityAppBinding
private val viewModel by viewModel<AppViewModel>()
private val whatsNewFileManager by inject<WhatsNewFileManager>()
private val whatsNewPreferencesManager by inject<WhatsNewPreferences>()
private val whatsNewManager by inject<WhatsNewManager>()
private val corePreferencesManager by inject<CorePreferences>()
private val profileRouter by inject<ProfileRouter>()

Expand Down Expand Up @@ -121,11 +114,13 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder, AppDataH
.add(R.id.container, SignInFragment())
.commit()
}
shouldShowWhatsNew() -> {

whatsNewManager.shouldShowWhatsNew() -> {
supportFragmentManager.beginTransaction()
.add(R.id.container, WhatsNewFragment())
.commit()
}

corePreferencesManager.user != null -> {
supportFragmentManager.beginTransaction()
.add(R.id.container, MainFragment())
Expand Down Expand Up @@ -168,13 +163,6 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder, AppDataH
}
}

override fun shouldShowWhatsNew(): Boolean {
val dataVersion = whatsNewFileManager.getNewestData().version
return BuildConfig.VERSION_NAME == dataVersion
&& whatsNewPreferencesManager.lastWhatsNewVersion != dataVersion
&& org.openedx.core.BuildConfig.SHOW_WHATS_NEW
}

companion object {
const val TOP_INSET = "topInset"
const val BOTTOM_INSET = "bottomInset"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import org.openedx.app.BuildConfig
import org.openedx.core.data.storage.CorePreferences
import org.openedx.profile.data.model.Account
import org.openedx.core.data.model.User
import org.openedx.core.data.storage.InAppReviewPreferences
import org.openedx.core.domain.model.VideoSettings
import org.openedx.profile.data.storage.ProfilePreferences
import org.openedx.whatsnew.data.storage.WhatsNewPreferences

class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences, WhatsNewPreferences {
class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences, WhatsNewPreferences,
InAppReviewPreferences {

private val sharedPreferences = context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE)

Expand All @@ -21,6 +23,14 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
}
private fun getString(key: String): String = sharedPreferences.getString(key, "") ?: ""

private fun saveBoolean(key: String, value: Boolean) {
sharedPreferences.edit().apply {
putBoolean(key, value)
}.apply()
}

private fun getBoolean(key: String): Boolean = sharedPreferences.getBoolean(key, false)

override fun clear() {
sharedPreferences.edit().apply {
remove(ACCESS_TOKEN)
Expand Down Expand Up @@ -78,12 +88,32 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
}
get() = getString(LAST_WHATS_NEW_VERSION)

override var lastReviewVersion: InAppReviewPreferences.VersionName
set(value) {
val versionNameJson = Gson().toJson(value)
saveString(LAST_REVIEW_VERSION, versionNameJson)
}
get() {
val versionNameString = getString(LAST_REVIEW_VERSION)
return Gson().fromJson(versionNameString, InAppReviewPreferences.VersionName::class.java)
?: InAppReviewPreferences.VersionName.default
}


override var wasPositiveRated: Boolean
set(value) {
saveBoolean(APP_WAS_POSITIVE_RATED, value)
}
get() = getBoolean(APP_WAS_POSITIVE_RATED)

companion object {
private const val ACCESS_TOKEN = "access_token"
private const val REFRESH_TOKEN = "refresh_token"
private const val USER = "user"
private const val ACCOUNT = "account"
private const val VIDEO_SETTINGS = "video_settings"
private const val LAST_WHATS_NEW_VERSION = "last_whats_new_version"
private const val LAST_REVIEW_VERSION = "last_review_version"
private const val APP_WAS_POSITIVE_RATED = "app_was_positive_rated"
}
}
45 changes: 28 additions & 17 deletions app/src/main/java/org/openedx/app/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
package org.openedx.app.di

import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import androidx.room.RoomDatabase
import com.google.android.play.core.review.ReviewManagerFactory
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import kotlinx.coroutines.Dispatchers
import org.koin.android.ext.koin.androidApplication
import org.koin.core.qualifier.named
import org.koin.dsl.module
import org.openedx.app.AnalyticsManager
import org.openedx.app.AppAnalytics
import org.openedx.app.AppRouter
import org.openedx.app.BuildConfig
import org.openedx.app.data.storage.PreferencesManager
import org.openedx.app.room.AppDatabase
import org.openedx.app.room.DATABASE_NAME
import org.openedx.app.system.notifier.AppNotifier
import org.openedx.auth.presentation.AuthAnalytics
import org.openedx.auth.presentation.AuthRouter
import org.openedx.app.data.storage.PreferencesManager
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.data.storage.InAppReviewPreferences
import org.openedx.core.module.DownloadWorkerController
import org.openedx.core.module.TranscriptManager
import org.openedx.core.module.download.FileDownloader
import org.openedx.core.presentation.dialog.appreview.AppReviewManager
import org.openedx.core.presentation.global.AppData
import org.openedx.core.presentation.global.WhatsNewGlobalManager
import org.openedx.core.system.AppCookieManager
import org.openedx.core.system.ResourceManager
import org.openedx.core.system.connection.NetworkConnection
Expand All @@ -23,24 +41,13 @@ import org.openedx.discovery.presentation.DiscoveryRouter
import org.openedx.discussion.presentation.DiscussionAnalytics
import org.openedx.discussion.presentation.DiscussionRouter
import org.openedx.discussion.system.notifier.DiscussionNotifier
import org.openedx.app.AnalyticsManager
import org.openedx.app.AppAnalytics
import org.openedx.app.AppRouter
import org.openedx.app.room.AppDatabase
import org.openedx.app.room.DATABASE_NAME
import org.openedx.app.system.notifier.AppNotifier
import org.openedx.profile.data.storage.ProfilePreferences
import org.openedx.profile.presentation.ProfileAnalytics
import org.openedx.profile.presentation.ProfileRouter
import org.openedx.profile.system.notifier.ProfileNotifier
import kotlinx.coroutines.Dispatchers
import org.koin.android.ext.koin.androidApplication
import org.koin.core.qualifier.named
import org.koin.dsl.module
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.presentation.global.app_upgrade.AppUpgradeRouter
import org.openedx.core.system.notifier.AppUpgradeNotifier
import org.openedx.profile.data.storage.ProfilePreferences
import org.openedx.whatsnew.WhatsNewFileManager
import org.openedx.whatsnew.WhatsNewManager
import org.openedx.whatsnew.WhatsNewRouter
import org.openedx.whatsnew.data.storage.WhatsNewPreferences

Expand All @@ -50,10 +57,11 @@ val appModule = module {
single<CorePreferences> { get<PreferencesManager>() }
single<ProfilePreferences> { get<PreferencesManager>() }
single<WhatsNewPreferences> { get<PreferencesManager>() }
single<InAppReviewPreferences> { get<PreferencesManager>() }

single { ResourceManager(get()) }

single { AppCookieManager(get()) }
single { ReviewManagerFactory.create(get()) }

single<Gson> { GsonBuilder().create() }

Expand All @@ -73,7 +81,6 @@ val appModule = module {
single<WhatsNewRouter> { get<AppRouter>() }
single<AppUpgradeRouter> { get<AppRouter>() }


single { NetworkConnection(get()) }

single(named("IODispatcher")) {
Expand Down Expand Up @@ -122,8 +129,12 @@ val appModule = module {
DownloadWorkerController(get(), get(), get())
}

single { AppData(BuildConfig.VERSION_NAME) }
factory { (activity: AppCompatActivity) -> AppReviewManager(activity, get(), get()) }

single { TranscriptManager(get()) }
single { WhatsNewFileManager(get()) }
single { WhatsNewManager(get(), get(), get()) }
single<WhatsNewGlobalManager> { get<WhatsNewManager>() }

single { AnalyticsManager(get()) }
single<DashboardAnalytics> { get<AnalyticsManager>() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,13 @@ import org.openedx.core.ui.theme.appShapes
import org.openedx.core.ui.theme.appTypography
import org.openedx.core.ui.windowSizeValue
import org.openedx.core.AppUpdateState
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.openedx.core.presentation.global.AppDataHolder
import org.openedx.core.presentation.global.WhatsNewGlobalManager

class SignInFragment : Fragment() {

private val viewModel: SignInViewModel by viewModel()
private val router: AuthRouter by inject()
private val whatsNewGlobalManager by inject<WhatsNewGlobalManager>()

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -119,7 +118,7 @@ class SignInFragment : Fragment() {
)

LaunchedEffect(loginSuccess) {
val isNeedToShowWhatsNew = (requireActivity() as AppDataHolder).shouldShowWhatsNew()
val isNeedToShowWhatsNew = whatsNewGlobalManager.shouldShowWhatsNew()
if (loginSuccess) {
if (isNeedToShowWhatsNew) {
router.navigateToWhatsNew(parentFragmentManager)
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ ext {

window_version = '1.1.0'

in_app_review = '2.0.1'

extented_spans_version = "1.3.0"

//testing
Expand Down
3 changes: 3 additions & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ dependencies {
api "com.google.firebase:firebase-crashlytics-ktx"
api "com.google.firebase:firebase-analytics-ktx"

//Play In-App Review
api "com.google.android.play:review-ktx:$in_app_review"

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.openedx.core.data.storage

interface InAppReviewPreferences {
var lastReviewVersion: VersionName
var wasPositiveRated: Boolean

fun setVersion(version: String) {
lastReviewVersion = formatVersionName(version)
}

fun formatVersionName(version: String) = version
.split(".")
.let {
VersionName(
majorVersion = it[0].toInt(),
minorVersion = it[1].toInt()
)
}

data class VersionName(
var majorVersion: Int,
var minorVersion: Int
) {
companion object {
val default = VersionName(Int.MIN_VALUE, Int.MIN_VALUE)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.openedx.core.presentation.dialog.appreview

import androidx.appcompat.app.AppCompatActivity
import org.openedx.core.data.storage.InAppReviewPreferences
import org.openedx.core.presentation.global.AppData

class AppReviewManager(
private val activity: AppCompatActivity,
private val reviewPreferences: InAppReviewPreferences,
private val appData: AppData
) {
var isDialogShowed = false

fun tryToOpenRateDialog() {
val supportFragmentManager = activity.supportFragmentManager
if (!supportFragmentManager.isDestroyed) {
isDialogShowed = true
val currentVersionName = reviewPreferences.formatVersionName(appData.versionName)
// Check is app wasn't positive rated AND 2 minor OR 1 major app versions passed since the last review
if (
!reviewPreferences.wasPositiveRated
&& (currentVersionName.minorVersion - 2 >= reviewPreferences.lastReviewVersion.minorVersion
|| currentVersionName.majorVersion - 1 >= reviewPreferences.lastReviewVersion.majorVersion)
) {
val dialog = RateDialogFragment.newInstance()
dialog.show(
supportFragmentManager,
RateDialogFragment::class.simpleName
)
}
}
}
}
Loading