Add Try Button to Theme and Instant flavor
This commit is contained in:
parent
4ff04bea5c
commit
6528708b51
28 changed files with 253 additions and 27 deletions
|
@ -76,6 +76,11 @@ android {
|
||||||
applicationId 'dev.lucasnlm.antimine'
|
applicationId 'dev.lucasnlm.antimine'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
googleInstant {
|
||||||
|
dimension 'version'
|
||||||
|
applicationId 'dev.lucasnlm.antimine'
|
||||||
|
}
|
||||||
|
|
||||||
foss {
|
foss {
|
||||||
dimension 'version'
|
dimension 'version'
|
||||||
// There's a typo on F-Droid release :(
|
// There's a typo on F-Droid release :(
|
||||||
|
@ -96,6 +101,7 @@ dependencies {
|
||||||
implementation project(':common')
|
implementation project(':common')
|
||||||
|
|
||||||
googleImplementation project(':proprietary')
|
googleImplementation project(':proprietary')
|
||||||
|
googleInstantImplementation project(':proprietary')
|
||||||
fossImplementation project(':foss')
|
fossImplementation project(':foss')
|
||||||
|
|
||||||
// AndroidX
|
// AndroidX
|
||||||
|
@ -115,7 +121,7 @@ dependencies {
|
||||||
implementation 'androidx.room:room-ktx:2.2.5'
|
implementation 'androidx.room:room-ktx:2.2.5'
|
||||||
|
|
||||||
// Constraint
|
// Constraint
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
|
|
||||||
// Google
|
// Google
|
||||||
implementation 'com.google.android.material:material:1.2.0'
|
implementation 'com.google.android.material:material:1.2.0'
|
||||||
|
@ -142,7 +148,7 @@ dependencies {
|
||||||
testImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
|
testImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
|
||||||
testImplementation 'androidx.fragment:fragment-testing:1.2.5'
|
testImplementation 'androidx.fragment:fragment-testing:1.2.5'
|
||||||
testImplementation 'org.robolectric:robolectric:4.3.1'
|
testImplementation 'org.robolectric:robolectric:4.3.1'
|
||||||
testImplementation 'androidx.test.ext:junit:1.1.1'
|
testImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
testImplementation 'io.mockk:mockk:1.10.0'
|
testImplementation 'io.mockk:mockk:1.10.0'
|
||||||
|
|
||||||
// Core library
|
// Core library
|
||||||
|
|
|
@ -574,7 +574,9 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
||||||
private fun restartIfNeed(): Boolean {
|
private fun restartIfNeed(): Boolean {
|
||||||
return (areaSizeMultiplier != preferencesRepository.areaSizeMultiplier()).also {
|
return (areaSizeMultiplier != preferencesRepository.areaSizeMultiplier()).also {
|
||||||
if (it) {
|
if (it) {
|
||||||
recreate()
|
finish()
|
||||||
|
startActivity(intent)
|
||||||
|
overridePendingTransition(0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,7 +637,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
||||||
|
|
||||||
private fun showSupportAppDialog() {
|
private fun showSupportAppDialog() {
|
||||||
if (supportFragmentManager.findFragmentByTag(SupportAppDialogFragment.TAG) == null) {
|
if (supportFragmentManager.findFragmentByTag(SupportAppDialogFragment.TAG) == null) {
|
||||||
SupportAppDialogFragment.newInstance(false)
|
SupportAppDialogFragment.newRequestSupportDialog()
|
||||||
.show(supportFragmentManager, SupportAppDialogFragment.TAG)
|
.show(supportFragmentManager, SupportAppDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import dev.lucasnlm.antimine.core.analytics.models.Analytics
|
||||||
import dev.lucasnlm.antimine.core.di.CommonModule
|
import dev.lucasnlm.antimine.core.di.CommonModule
|
||||||
import dev.lucasnlm.antimine.di.AppModule
|
import dev.lucasnlm.antimine.di.AppModule
|
||||||
import dev.lucasnlm.antimine.di.ViewModelModule
|
import dev.lucasnlm.antimine.di.ViewModelModule
|
||||||
|
import dev.lucasnlm.external.IAdsManager
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
import org.koin.core.context.startKoin
|
import org.koin.core.context.startKoin
|
||||||
|
@ -14,6 +15,8 @@ import org.koin.core.context.startKoin
|
||||||
open class MainApplication : MultiDexApplication() {
|
open class MainApplication : MultiDexApplication() {
|
||||||
private val analyticsManager: IAnalyticsManager by inject()
|
private val analyticsManager: IAnalyticsManager by inject()
|
||||||
|
|
||||||
|
private val adsManager: IAdsManager by inject()
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
startKoin {
|
startKoin {
|
||||||
|
@ -25,5 +28,7 @@ open class MainApplication : MultiDexApplication() {
|
||||||
setup(applicationContext, mapOf())
|
setup(applicationContext, mapOf())
|
||||||
sentEvent(Analytics.Open)
|
sentEvent(Analytics.Open)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adsManager.start(applicationContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,9 @@ open class ThematicActivity(@LayoutRes contentLayoutId: Int) : AppCompatActivity
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
if (usingTheme.id != currentTheme().id) {
|
if (usingTheme.id != currentTheme().id) {
|
||||||
recreate()
|
finish()
|
||||||
|
startActivity(intent)
|
||||||
|
overridePendingTransition(0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ class AboutActivity : ThematicActivity(R.layout.activity_empty) {
|
||||||
|
|
||||||
private fun showSupportAppDialog() {
|
private fun showSupportAppDialog() {
|
||||||
if (supportFragmentManager.findFragmentByTag(SupportAppDialogFragment.TAG) == null) {
|
if (supportFragmentManager.findFragmentByTag(SupportAppDialogFragment.TAG) == null) {
|
||||||
SupportAppDialogFragment.newInstance(false)
|
SupportAppDialogFragment.newRequestSupportDialog()
|
||||||
.show(supportFragmentManager, SupportAppDialogFragment.TAG)
|
.show(supportFragmentManager, SupportAppDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,10 @@ import dev.lucasnlm.antimine.core.analytics.DebugAnalyticsManager
|
||||||
import dev.lucasnlm.antimine.core.analytics.IAnalyticsManager
|
import dev.lucasnlm.antimine.core.analytics.IAnalyticsManager
|
||||||
import dev.lucasnlm.antimine.core.analytics.ProdAnalyticsManager
|
import dev.lucasnlm.antimine.core.analytics.ProdAnalyticsManager
|
||||||
import dev.lucasnlm.antimine.share.ShareManager
|
import dev.lucasnlm.antimine.share.ShareManager
|
||||||
|
import dev.lucasnlm.external.AdsManager
|
||||||
import dev.lucasnlm.external.BillingManager
|
import dev.lucasnlm.external.BillingManager
|
||||||
import dev.lucasnlm.external.ExternalAnalyticsWrapper
|
import dev.lucasnlm.external.ExternalAnalyticsWrapper
|
||||||
|
import dev.lucasnlm.external.IAdsManager
|
||||||
import dev.lucasnlm.external.IBillingManager
|
import dev.lucasnlm.external.IBillingManager
|
||||||
import dev.lucasnlm.external.IInstantAppManager
|
import dev.lucasnlm.external.IInstantAppManager
|
||||||
import dev.lucasnlm.external.IPlayGamesManager
|
import dev.lucasnlm.external.IPlayGamesManager
|
||||||
|
@ -23,6 +25,8 @@ val AppModule = module {
|
||||||
|
|
||||||
single { BillingManager(get()) } bind IBillingManager::class
|
single { BillingManager(get()) } bind IBillingManager::class
|
||||||
|
|
||||||
|
single { AdsManager() } bind IAdsManager::class
|
||||||
|
|
||||||
single { PlayGamesManager(get()) } bind IPlayGamesManager::class
|
single { PlayGamesManager(get()) } bind IPlayGamesManager::class
|
||||||
|
|
||||||
single { ReviewWrapper() } bind IReviewWrapper::class
|
single { ReviewWrapper() } bind IReviewWrapper::class
|
||||||
|
|
|
@ -8,16 +8,21 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import dev.lucasnlm.antimine.R
|
import dev.lucasnlm.antimine.R
|
||||||
import dev.lucasnlm.antimine.core.analytics.IAnalyticsManager
|
import dev.lucasnlm.antimine.core.analytics.IAnalyticsManager
|
||||||
import dev.lucasnlm.antimine.core.analytics.models.Analytics
|
import dev.lucasnlm.antimine.core.analytics.models.Analytics
|
||||||
|
import dev.lucasnlm.antimine.core.themes.repository.IThemeRepository
|
||||||
|
import dev.lucasnlm.external.IAdsManager
|
||||||
import dev.lucasnlm.external.IBillingManager
|
import dev.lucasnlm.external.IBillingManager
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
|
||||||
class SupportAppDialogFragment : AppCompatDialogFragment() {
|
class SupportAppDialogFragment : AppCompatDialogFragment() {
|
||||||
private val billingManager: IBillingManager by inject()
|
private val billingManager: IBillingManager by inject()
|
||||||
|
private val themeRepository: IThemeRepository by inject()
|
||||||
private val analyticsManager: IAnalyticsManager by inject()
|
private val analyticsManager: IAnalyticsManager by inject()
|
||||||
|
private val adsManager: IAdsManager by inject()
|
||||||
private val iapHandler: IapHandler by inject()
|
private val iapHandler: IapHandler by inject()
|
||||||
|
|
||||||
private var unlockMessage: Boolean = false
|
private var showUnlockMessage: Boolean = false
|
||||||
|
private var targetThemeId: Long = -1L
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -25,16 +30,31 @@ class SupportAppDialogFragment : AppCompatDialogFragment() {
|
||||||
billingManager.start(iapHandler)
|
billingManager.start(iapHandler)
|
||||||
analyticsManager.sentEvent(Analytics.ShowIapDialog)
|
analyticsManager.sentEvent(Analytics.ShowIapDialog)
|
||||||
|
|
||||||
unlockMessage = (arguments?.getBoolean(UNLOCK_LABEL) ?: savedInstanceState?.getBoolean(UNLOCK_LABEL)) ?: false
|
showUnlockMessage = (arguments?.getBoolean(UNLOCK_LABEL) ?: savedInstanceState?.getBoolean(UNLOCK_LABEL)) ?: false
|
||||||
|
targetThemeId = (arguments?.getLong(TARGET_THEME_ID, -1L)) ?: -1L
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
return AlertDialog.Builder(requireContext()).apply {
|
return AlertDialog.Builder(requireContext()).apply {
|
||||||
setView(R.layout.dialog_payments)
|
setView(R.layout.dialog_payments)
|
||||||
setNeutralButton(R.string.rating_button_no) { _, _ ->
|
|
||||||
analyticsManager.sentEvent(Analytics.DenyIapDialog)
|
if (showUnlockMessage) {
|
||||||
|
setNeutralButton(R.string.try_it) { _, _ ->
|
||||||
|
analyticsManager.sentEvent(Analytics.UnlockRewardedDialog)
|
||||||
|
adsManager.requestRewarded(requireActivity(), "ca-app-pub-3940256099942544/5224354917") {
|
||||||
|
if (targetThemeId > 0) {
|
||||||
|
themeRepository.setTheme(targetThemeId)
|
||||||
|
requireActivity().recreate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setNeutralButton(R.string.rating_button_no) { _, _ ->
|
||||||
|
analyticsManager.sentEvent(Analytics.DenyIapDialog)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setPositiveButton(if (unlockMessage) R.string.unlock else R.string.support_action) { _, _ ->
|
|
||||||
|
setPositiveButton(if (showUnlockMessage) R.string.unlock else R.string.support_action) { _, _ ->
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
analyticsManager.sentEvent(Analytics.UnlockIapDialog)
|
analyticsManager.sentEvent(Analytics.UnlockIapDialog)
|
||||||
billingManager.charge(requireActivity())
|
billingManager.charge(requireActivity())
|
||||||
|
@ -47,11 +67,21 @@ class SupportAppDialogFragment : AppCompatDialogFragment() {
|
||||||
val TAG = SupportAppDialogFragment::class.simpleName
|
val TAG = SupportAppDialogFragment::class.simpleName
|
||||||
|
|
||||||
private const val UNLOCK_LABEL = "support_unlock_label"
|
private const val UNLOCK_LABEL = "support_unlock_label"
|
||||||
|
private const val TARGET_THEME_ID = "target_theme_id"
|
||||||
|
|
||||||
fun newInstance(unlockMessage: Boolean): SupportAppDialogFragment {
|
fun newRequestSupportDialog(): SupportAppDialogFragment {
|
||||||
return SupportAppDialogFragment().apply {
|
return SupportAppDialogFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putBoolean(UNLOCK_LABEL, unlockMessage)
|
putBoolean(UNLOCK_LABEL, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun newChangeThemeDialog(targetThemeId: Long): SupportAppDialogFragment {
|
||||||
|
return SupportAppDialogFragment().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putBoolean(UNLOCK_LABEL, true)
|
||||||
|
putLong(TARGET_THEME_ID, targetThemeId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ class ThemeActivity : ThematicActivity(R.layout.activity_theme) {
|
||||||
launch {
|
launch {
|
||||||
themeViewModel.observeEvent().collect {
|
themeViewModel.observeEvent().collect {
|
||||||
if (it is ThemeEvent.Unlock) {
|
if (it is ThemeEvent.Unlock) {
|
||||||
showUnlockDialog()
|
showUnlockDialog(it.themeId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,9 @@ class ThemeActivity : ThematicActivity(R.layout.activity_theme) {
|
||||||
launch {
|
launch {
|
||||||
themeViewModel.observeState().collect {
|
themeViewModel.observeState().collect {
|
||||||
if (usingTheme.id != it.current.id) {
|
if (usingTheme.id != it.current.id) {
|
||||||
recreate()
|
finish()
|
||||||
|
startActivity(intent)
|
||||||
|
overridePendingTransition(0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,9 +83,9 @@ class ThemeActivity : ThematicActivity(R.layout.activity_theme) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showUnlockDialog() {
|
private fun showUnlockDialog(themeId: Long) {
|
||||||
if (supportFragmentManager.findFragmentByTag(SupportAppDialogFragment.TAG) == null) {
|
if (supportFragmentManager.findFragmentByTag(SupportAppDialogFragment.TAG) == null) {
|
||||||
SupportAppDialogFragment.newInstance(true).apply {
|
SupportAppDialogFragment.newChangeThemeDialog(themeId).apply {
|
||||||
show(supportFragmentManager, SupportAppDialogFragment.TAG)
|
show(supportFragmentManager, SupportAppDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@ package dev.lucasnlm.antimine.theme.viewmodel
|
||||||
import dev.lucasnlm.antimine.core.themes.model.AppTheme
|
import dev.lucasnlm.antimine.core.themes.model.AppTheme
|
||||||
|
|
||||||
sealed class ThemeEvent {
|
sealed class ThemeEvent {
|
||||||
object Unlock : ThemeEvent()
|
data class Unlock(
|
||||||
|
val themeId: Long
|
||||||
|
) : ThemeEvent()
|
||||||
|
|
||||||
data class ChangeTheme(
|
data class ChangeTheme(
|
||||||
val newTheme: AppTheme,
|
val newTheme: AppTheme,
|
||||||
|
|
|
@ -20,7 +20,7 @@ class ThemeViewModel(
|
||||||
private val analyticsManager: IAnalyticsManager,
|
private val analyticsManager: IAnalyticsManager,
|
||||||
) : IntentViewModel<ThemeEvent, ThemeState>() {
|
) : IntentViewModel<ThemeEvent, ThemeState>() {
|
||||||
private fun setTheme(theme: AppTheme) {
|
private fun setTheme(theme: AppTheme) {
|
||||||
themeRepository.setTheme(theme)
|
themeRepository.setTheme(theme.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun observeEvent(): Flow<ThemeEvent> {
|
override fun observeEvent(): Flow<ThemeEvent> {
|
||||||
|
@ -35,7 +35,7 @@ class ThemeViewModel(
|
||||||
billingManager.isEnabled() &&
|
billingManager.isEnabled() &&
|
||||||
!preferencesRepository.isPremiumEnabled()
|
!preferencesRepository.isPremiumEnabled()
|
||||||
) {
|
) {
|
||||||
ThemeEvent.Unlock
|
ThemeEvent.Unlock(it.newTheme.id)
|
||||||
} else {
|
} else {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ val TestCommonModule = module {
|
||||||
|
|
||||||
override fun getAllThemes(): List<AppTheme> = listOf(LightTheme)
|
override fun getAllThemes(): List<AppTheme> = listOf(LightTheme)
|
||||||
|
|
||||||
override fun setTheme(theme: AppTheme) { }
|
override fun setTheme(themeId: Long) { }
|
||||||
|
|
||||||
override fun reset(): AppTheme = LightTheme
|
override fun reset(): AppTheme = LightTheme
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ class ThemeViewModelTest : IntentViewModelTest() {
|
||||||
}
|
}
|
||||||
assertEquals(ThemeState(darkTheme, allThemes), state)
|
assertEquals(ThemeState(darkTheme, allThemes), state)
|
||||||
|
|
||||||
verify { themeRepository.setTheme(darkTheme) }
|
verify { themeRepository.setTheme(darkTheme.id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -46,7 +46,7 @@ dependencies {
|
||||||
implementation "androidx.fragment:fragment-ktx:1.2.5"
|
implementation "androidx.fragment:fragment-ktx:1.2.5"
|
||||||
|
|
||||||
// Constraint
|
// Constraint
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
api 'android.arch.lifecycle:extensions:1.1.1'
|
api 'android.arch.lifecycle:extensions:1.1.1'
|
||||||
|
|
|
@ -109,6 +109,8 @@ sealed class Analytics(
|
||||||
|
|
||||||
object UnlockIapDialog : Analytics("IAP Dialog Unlock")
|
object UnlockIapDialog : Analytics("IAP Dialog Unlock")
|
||||||
|
|
||||||
|
object UnlockRewardedDialog : Analytics("Rewarded Dialog Unlock")
|
||||||
|
|
||||||
class ShowRatingRequest(usages: Int) : Analytics("Shown Rating Request", mapOf("Usages" to usages.toString()))
|
class ShowRatingRequest(usages: Int) : Analytics("Shown Rating Request", mapOf("Usages" to usages.toString()))
|
||||||
|
|
||||||
object TapRatingRequest : Analytics("Rating Request")
|
object TapRatingRequest : Analytics("Rating Request")
|
||||||
|
|
|
@ -10,6 +10,7 @@ class PreferencesRepository(
|
||||||
) : IPreferencesRepository {
|
) : IPreferencesRepository {
|
||||||
init {
|
init {
|
||||||
migrateOldPreferences()
|
migrateOldPreferences()
|
||||||
|
revertTestTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasCustomizations(): Boolean {
|
override fun hasCustomizations(): Boolean {
|
||||||
|
@ -121,6 +122,12 @@ class PreferencesRepository(
|
||||||
preferencesManager.putBoolean(PREFERENCE_REQUEST_RATING, false)
|
preferencesManager.putBoolean(PREFERENCE_REQUEST_RATING, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun revertTestTheme() {
|
||||||
|
if (!isPremiumEnabled()) {
|
||||||
|
useTheme(0L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun migrateOldPreferences() {
|
private fun migrateOldPreferences() {
|
||||||
// Migrate Double Click to the new Control settings
|
// Migrate Double Click to the new Control settings
|
||||||
if (preferencesManager.contains(PREFERENCE_OLD_DOUBLE_CLICK)) {
|
if (preferencesManager.contains(PREFERENCE_OLD_DOUBLE_CLICK)) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ interface IThemeRepository {
|
||||||
fun getCustomTheme(): AppTheme?
|
fun getCustomTheme(): AppTheme?
|
||||||
fun getTheme(): AppTheme
|
fun getTheme(): AppTheme
|
||||||
fun getAllThemes(): List<AppTheme>
|
fun getAllThemes(): List<AppTheme>
|
||||||
fun setTheme(theme: AppTheme)
|
fun setTheme(themeId: Long)
|
||||||
fun reset(): AppTheme
|
fun reset(): AppTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ class ThemeRepository(
|
||||||
override fun getAllThemes(): List<AppTheme> =
|
override fun getAllThemes(): List<AppTheme> =
|
||||||
listOf(buildSystemTheme()) + Themes.getAllCustom()
|
listOf(buildSystemTheme()) + Themes.getAllCustom()
|
||||||
|
|
||||||
override fun setTheme(theme: AppTheme) {
|
override fun setTheme(themeId: Long) {
|
||||||
preferenceRepository.useTheme(theme.id)
|
preferenceRepository.useTheme(themeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset(): AppTheme {
|
override fun reset(): AppTheme {
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
<string name="close_menu">Close Menu</string>
|
<string name="close_menu">Close Menu</string>
|
||||||
<string name="delete_all">Delete all</string>
|
<string name="delete_all">Delete all</string>
|
||||||
<string name="themes">Themes</string>
|
<string name="themes">Themes</string>
|
||||||
|
<string name="try_it">Try It</string>
|
||||||
<string name="delete_all_message">Delete all events permanently.</string>
|
<string name="delete_all_message">Delete all events permanently.</string>
|
||||||
<string name="all_mines_disabled">All mines were disabled.</string>
|
<string name="all_mines_disabled">All mines were disabled.</string>
|
||||||
<string name="desc_convered_area">Covered area</string>
|
<string name="desc_convered_area">Covered area</string>
|
||||||
|
|
10
external/src/main/java/dev/lucasnlm/external/IAdsManager.kt
vendored
Normal file
10
external/src/main/java/dev/lucasnlm/external/IAdsManager.kt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package dev.lucasnlm.external
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
interface IAdsManager {
|
||||||
|
fun start(context: Context)
|
||||||
|
fun isReady(): Boolean
|
||||||
|
fun requestRewarded(activity: Activity, adUnitId: String, onRewarded: () -> Unit)
|
||||||
|
}
|
1
instant/.gitignore
vendored
Normal file
1
instant/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
37
instant/build.gradle
Normal file
37
instant/build.gradle
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
id 'kotlin-android'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 30
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 30
|
||||||
|
versionCode 1
|
||||||
|
versionName '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Dependencies must be hardcoded to support F-droid
|
||||||
|
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
}
|
0
instant/consumer-rules.pro
Normal file
0
instant/consumer-rules.pro
Normal file
21
instant/proguard-rules.pro
vendored
Normal file
21
instant/proguard-rules.pro
vendored
Normal file
|
@ -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
|
7
instant/src/main/AndroidManifest.xml
Normal file
7
instant/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="dev.lucasnlm.antimine.instant"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<application>
|
||||||
|
<meta-data android:name="com.google.android.gms.instant.flavor" android:value="1337"/>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
|
@ -22,6 +22,13 @@ android {
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||||
|
freeCompilerArgs += [
|
||||||
|
'-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi',
|
||||||
|
'-Xuse-experimental=kotlinx.coroutines.FlowPreview']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -35,6 +42,7 @@ dependencies {
|
||||||
implementation 'com.google.android.gms:play-services-instantapps:17.0.0'
|
implementation 'com.google.android.gms:play-services-instantapps:17.0.0'
|
||||||
implementation 'com.google.android.gms:play-services-games:20.0.0'
|
implementation 'com.google.android.gms:play-services-games:20.0.0'
|
||||||
implementation 'com.google.android.gms:play-services-auth:18.1.0'
|
implementation 'com.google.android.gms:play-services-auth:18.1.0'
|
||||||
|
implementation 'com.google.android.gms:play-services-ads:19.3.0'
|
||||||
implementation 'com.google.android.play:core-ktx:1.8.1'
|
implementation 'com.google.android.play:core-ktx:1.8.1'
|
||||||
|
|
||||||
// Firebase
|
// Firebase
|
||||||
|
|
|
@ -11,5 +11,8 @@
|
||||||
android:value="@string/app_id"/>
|
android:value="@string/app_id"/>
|
||||||
<meta-data android:name="com.google.android.gms.version"
|
<meta-data android:name="com.google.android.gms.version"
|
||||||
android:value="@integer/google_play_services_version"/>
|
android:value="@integer/google_play_services_version"/>
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||||
|
android:value="ca-app-pub-3940256099942544~3347511713"/>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
75
proprietary/src/main/java/dev/lucasnlm/external/AdsManager.kt
vendored
Normal file
75
proprietary/src/main/java/dev/lucasnlm/external/AdsManager.kt
vendored
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package dev.lucasnlm.external
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.annotation.NonNull
|
||||||
|
import com.google.android.gms.ads.AdError
|
||||||
|
import com.google.android.gms.ads.AdRequest
|
||||||
|
import com.google.android.gms.ads.LoadAdError
|
||||||
|
import com.google.android.gms.ads.MobileAds
|
||||||
|
import com.google.android.gms.ads.rewarded.RewardItem
|
||||||
|
import com.google.android.gms.ads.rewarded.RewardedAd
|
||||||
|
import com.google.android.gms.ads.rewarded.RewardedAdCallback
|
||||||
|
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback
|
||||||
|
|
||||||
|
class AdsManager : IAdsManager {
|
||||||
|
private var unlockTheme: RewardedAd? = null
|
||||||
|
|
||||||
|
override fun start(context: Context) {
|
||||||
|
MobileAds.initialize(context) {
|
||||||
|
unlockTheme = loadRewardedAd(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadRewardedAd(context: Context): RewardedAd {
|
||||||
|
return RewardedAd(context, "ca-app-pub-3940256099942544/5224354917").apply {
|
||||||
|
val adLoadCallback = object: RewardedAdLoadCallback() {
|
||||||
|
override fun onRewardedAdLoaded() {
|
||||||
|
// Loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRewardedAdFailedToLoad(adError: LoadAdError) {
|
||||||
|
// Ad failed to load.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAd(AdRequest.Builder().build(), adLoadCallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isReady(): Boolean {
|
||||||
|
return unlockTheme != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun requestRewarded(activity: Activity, adUnitId: String, onRewarded: () -> Unit) {
|
||||||
|
if (isReady()) {
|
||||||
|
val context = activity.applicationContext
|
||||||
|
|
||||||
|
unlockTheme?.let {
|
||||||
|
val adCallback = object : RewardedAdCallback() {
|
||||||
|
override fun onRewardedAdOpened() {
|
||||||
|
// Ad opened
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRewardedAdClosed() {
|
||||||
|
// Ad closed
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUserEarnedReward(@NonNull reward: RewardItem) {
|
||||||
|
onRewarded()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRewardedAdFailedToShow(adError: AdError) {
|
||||||
|
// Ad failed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unlockTheme = loadRewardedAd(context)
|
||||||
|
|
||||||
|
if (!activity.isFinishing) {
|
||||||
|
it.show(activity, adCallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
include ':app', ':wear', ':common', ':proprietary', ':foss'
|
include ':app', ':wear', ':common', ':proprietary', ':foss'
|
||||||
include ':external'
|
include ':external'
|
||||||
|
include ':instant'
|
||||||
|
|
|
@ -49,7 +49,7 @@ dependencies {
|
||||||
|
|
||||||
// Constraint
|
// Constraint
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.activity:activity-ktx:1.1.0'
|
implementation 'androidx.activity:activity-ktx:1.1.0'
|
||||||
|
|
Loading…
Reference in a new issue