Add a one time popup asking for donation from long time users (#3203)
Also remove the empty "Updated to X.Y.Z" popup after app update
This commit is contained in:
@@ -46,4 +46,9 @@ class BasePreferences(
|
||||
)
|
||||
|
||||
val installationId: Preference<String> = preferenceStore.getString(Preference.appStateKey("installation_id"), "")
|
||||
|
||||
val donationCampaignShown: Preference<Boolean> = preferenceStore.getBoolean(
|
||||
Preference.appStateKey("donation_campaign_shown"),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ fun NavigatorAdaptiveSheet(
|
||||
content = { sheetNavigator ->
|
||||
AdaptiveSheet(
|
||||
onDismissRequest = onDismissRequest,
|
||||
enableSwipeDismiss = enableSwipeDismiss(sheetNavigator),
|
||||
enableImplicitDismiss = enableSwipeDismiss(sheetNavigator),
|
||||
) {
|
||||
ScreenTransition(
|
||||
navigator = sheetNavigator,
|
||||
@@ -63,7 +63,7 @@ fun NavigatorAdaptiveSheet(
|
||||
fun AdaptiveSheet(
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enableSwipeDismiss: Boolean = true,
|
||||
enableImplicitDismiss: Boolean = true,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val isTabletUi = isTabletUi()
|
||||
@@ -74,7 +74,7 @@ fun AdaptiveSheet(
|
||||
) {
|
||||
AdaptiveSheetImpl(
|
||||
isTabletUi = isTabletUi,
|
||||
enableSwipeDismiss = enableSwipeDismiss,
|
||||
enableImplicitDismiss = enableImplicitDismiss,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.app.SearchManager
|
||||
import android.app.assist.AssistContent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@@ -14,21 +15,32 @@ import androidx.activity.SystemBarStyle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.windowInsetsBottomHeight
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.OpenInNew
|
||||
import androidx.compose.material.icons.filled.VolunteerActivism
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@@ -41,6 +53,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.splashscreen.SplashScreen
|
||||
@@ -55,6 +69,7 @@ import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.source.interactor.GetIncognitoState
|
||||
import eu.kanade.presentation.components.AdaptiveSheet
|
||||
import eu.kanade.presentation.components.AppStateBanners
|
||||
import eu.kanade.presentation.components.DownloadedOnlyBannerBackgroundColor
|
||||
import eu.kanade.presentation.components.IncognitoModeBannerBackgroundColor
|
||||
@@ -63,12 +78,10 @@ import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen
|
||||
import eu.kanade.presentation.more.settings.screen.data.RestoreBackupScreen
|
||||
import eu.kanade.presentation.util.AssistContentScreen
|
||||
import eu.kanade.presentation.util.DefaultNavigatorScreenTransition
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||
import eu.kanade.tachiyomi.data.updater.AppUpdateChecker
|
||||
import eu.kanade.tachiyomi.data.updater.RELEASE_URL
|
||||
import eu.kanade.tachiyomi.extension.api.ExtensionApi
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
||||
@@ -80,7 +93,6 @@ import eu.kanade.tachiyomi.ui.more.NewUpdateScreen
|
||||
import eu.kanade.tachiyomi.ui.more.OnboardingScreen
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.isNavigationBarNeedsScrim
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
import eu.kanade.tachiyomi.util.system.updaterEnabled
|
||||
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
@@ -93,6 +105,7 @@ import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import mihon.core.migration.Migrator
|
||||
import mihon.feature.support.SupportUsScreen
|
||||
import tachiyomi.core.common.Constants
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
@@ -100,9 +113,14 @@ import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.release.interactor.GetApplicationRelease
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Instant
|
||||
import kotlin.time.times
|
||||
|
||||
class MainActivity : BaseActivity() {
|
||||
|
||||
@@ -131,7 +149,7 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val didMigration = Migrator.awaitAndRelease()
|
||||
Migrator.awaitAndRelease()
|
||||
|
||||
// Do not let the launcher create a new activity http://stackoverflow.com/questions/16283079
|
||||
if (!isTaskRoot) {
|
||||
@@ -240,24 +258,7 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
CheckForUpdates()
|
||||
ShowOnboarding()
|
||||
}
|
||||
|
||||
var showChangelog by remember { mutableStateOf(didMigration && !BuildConfig.DEBUG) }
|
||||
if (showChangelog) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showChangelog = false },
|
||||
title = { Text(text = stringResource(MR.strings.updated_version, BuildConfig.VERSION_NAME)) },
|
||||
dismissButton = {
|
||||
TextButton(onClick = { openInBrowser(RELEASE_URL) }) {
|
||||
Text(text = stringResource(MR.strings.whats_new))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { showChangelog = false }) {
|
||||
Text(text = stringResource(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
)
|
||||
ShowDonationCampaign()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,6 +344,128 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ShowDonationCampaign() {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
var showCampaign by remember { mutableStateOf(false) }
|
||||
if (showCampaign) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val dismissSupportMessage = {
|
||||
preferences.donationCampaignShown.set(true)
|
||||
@Suppress("AssignedValueIsNeverRead")
|
||||
showCampaign = false
|
||||
}
|
||||
AdaptiveSheet(
|
||||
onDismissRequest = dismissSupportMessage,
|
||||
enableImplicitDismiss = false,
|
||||
) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(16.dp)
|
||||
.weight(1f, fill = false)
|
||||
.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(MR.strings.donationCampaign_title),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(MR.strings.donationCampaign_paragraph1),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(MR.strings.donationCampaign_paragraph2),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(MR.strings.donationCampaign_paragraph3),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.padding.small)
|
||||
.padding(horizontal = MaterialTheme.padding.medium)
|
||||
.fillMaxWidth(),
|
||||
onClick = {
|
||||
navigator.push(SupportUsScreen())
|
||||
dismissSupportMessage()
|
||||
},
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.VolunteerActivism,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(MR.strings.label_support_us),
|
||||
color = MaterialTheme.colorScheme.onPrimary,
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||
modifier = Modifier
|
||||
.padding(bottom = MaterialTheme.padding.small)
|
||||
.padding(horizontal = MaterialTheme.padding.medium),
|
||||
) {
|
||||
OutlinedButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
onClick = { uriHandler.openUri(Constants.URL_DISCORD) },
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(MR.strings.donationCampaign_contactPlatform),
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.OpenInNew,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
OutlinedButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
onClick = dismissSupportMessage,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(MR.strings.donationCampaign_dismiss),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
try {
|
||||
val firstInstallTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
|
||||
val eligibleTime = Instant.fromEpochMilliseconds(firstInstallTime).plus(6 * 30.days)
|
||||
@Suppress("AssignedValueIsNeverRead")
|
||||
showCampaign = (Clock.System.now() >= eligibleTime && !preferences.donationCampaignShown.get())
|
||||
} catch (_: PackageManager.NameNotFoundException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets custom splash screen exit animation on devices prior to Android 12.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user