Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import org.cryptomator.presentation.service.PendingCallbackQueue
import org.cryptomator.presentation.service.ProductInfo
import org.cryptomator.presentation.service.PurchaseRevokedToastObserver
import org.cryptomator.presentation.service.RestoreOutcome
import org.cryptomator.presentation.service.RestoreOutcomeDialogObserver
import org.cryptomator.util.FlavorConfig
import org.cryptomator.util.NoOpActivityLifecycleCallbacks
import org.cryptomator.util.SharedPreferencesHandler
Expand All @@ -53,11 +52,6 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
@Volatile
private var iapBillingServiceBinder: IapBillingService.Binder? = null

fun restorePurchasesAndStore() {
val handler = SharedPreferencesHandler(applicationContext())
restorePurchases { outcome -> handler.setPendingRestoreOutcome(outcome.kind.name) }
}

private val pendingProductDetailsCallbacks = PendingCallbackQueue<List<ProductInfo>>()

override fun onCreate() {
Expand Down Expand Up @@ -87,7 +81,6 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
registerActivityLifecycleCallbacks(serviceNotifier)
if (FlavorConfig.isFreemiumFlavor) {
registerActivityLifecycleCallbacks(PurchaseRevokedToastObserver(sharedPreferencesHandler))
registerActivityLifecycleCallbacks(RestoreOutcomeDialogObserver(sharedPreferencesHandler))
}
AppCompatDelegate.setDefaultNightMode(sharedPreferencesHandler.screenStyleMode)
cleanupCache()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class LicenseStateOrchestrator(
interface Callback {
fun onLicenseStateChanged(uiState: LicenseEnforcer.LicenseUiState)
fun onSubscriptionActivatedFirstTime() {}
fun onSubscriptionUpgradedToLifetime() {}
}

private val licenseChangeListener = Consumer<String> { _ -> updateState() }
Expand All @@ -41,9 +40,6 @@ class LicenseStateOrchestrator(
val wasSubOnly = wasSubscriptionOnly
wasSubscriptionOnly = nowSubOnly

if (wasSubOnly && uiState.hasLifetimeLicense && uiState.hasRunningSubscription) {
callback.onSubscriptionUpgradedToLifetime()
}
if (!wasSubOnly && nowSubOnly) {
callback.onSubscriptionActivatedFirstTime()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,10 @@ sealed interface RestoreOutcome {
data object RESTORED : RestoreOutcome
data object NOTHING_TO_RESTORE : RestoreOutcome
data class FAILED(val cause: Throwable? = null) : RestoreOutcome

/** Stable identifier for persisting a pending outcome via SharedPreferences (see [RestoreOutcomeDialogObserver]). */
val kind: Kind
get() = when (this) {
RESTORED -> Kind.RESTORED
NOTHING_TO_RESTORE -> Kind.NOTHING_TO_RESTORE
is FAILED -> Kind.FAILED
}

enum class Kind { RESTORED, NOTHING_TO_RESTORE, FAILED }
}

fun RestoreOutcome.Kind.toDialogFragment(): DialogFragment = when (this) {
RestoreOutcome.Kind.RESTORED -> RestoreSuccessfulDialog()
RestoreOutcome.Kind.NOTHING_TO_RESTORE -> NoFullVersionDialog()
RestoreOutcome.Kind.FAILED -> RestoreFailedDialog()
fun RestoreOutcome.toDialogFragment(): DialogFragment = when (this) {
RestoreOutcome.RESTORED -> RestoreSuccessfulDialog()
RestoreOutcome.NOTHING_TO_RESTORE -> NoFullVersionDialog()
is RestoreOutcome.FAILED -> RestoreFailedDialog()
}

fun RestoreOutcome.toDialogFragment(): DialogFragment = kind.toDialogFragment()

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ abstract class BaseActivity<VB : ViewBinding>(val bindingFactory: (LayoutInflate
override fun context(): Context = this

override fun showDialog(dialog: DialogFragment) {
if (isFinishing || isDestroyed || supportFragmentManager.isStateSaved) {
Timber.tag("BaseActivity").i("Skipping showDialog for %s; activity not in a state to commit fragments", dialog.javaClass.simpleName)
return
}
closeDialog()
currentDialog = dialog
dialog.show(supportFragmentManager, ACTIVE_DIALOG)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import org.cryptomator.presentation.licensing.LicenseEnforcer
import org.cryptomator.presentation.licensing.LicenseStateOrchestrator
import org.cryptomator.presentation.presenter.LicenseCheckPresenter
import org.cryptomator.presentation.ui.activity.view.LicenseView
import org.cryptomator.presentation.ui.dialog.CancelSubscriptionReminderDialog
import org.cryptomator.presentation.ui.dialog.EnterLicenseDialog
import org.cryptomator.presentation.ui.dialog.LicenseConfirmationDialog
import org.cryptomator.presentation.ui.layout.LicenseContentViewBinder
Expand Down Expand Up @@ -52,10 +51,6 @@ class LicenseCheckActivity : BaseActivity<ActivityLicenseCheckBinding>(ActivityL
override fun onSubscriptionActivatedFirstTime() {
finish()
}

override fun onSubscriptionUpgradedToLifetime() {
showDialog(CancelSubscriptionReminderDialog.newInstance())
}
},
priceLoader = { licenseContentViewBinder.loadAndBindPrices(application as CryptomatorApp) }
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.cryptomator.presentation.CryptomatorApp
import org.cryptomator.presentation.R
import org.cryptomator.presentation.databinding.FragmentWelcomeLicenseBinding
import org.cryptomator.presentation.licensing.LicenseEnforcer
import org.cryptomator.presentation.ui.activity.WelcomeActivity
import org.cryptomator.presentation.ui.layout.LicenseContentViewBinder
import org.cryptomator.util.FlavorConfig

Expand Down Expand Up @@ -45,7 +46,7 @@ class WelcomeLicenseFragment : BaseFragment<FragmentWelcomeLicenseBinding>(Fragm
licenseContentViewBinder.bindInitialIapLayout()
licenseContentViewBinder.bindLegalLinks()
licenseContentViewBinder.bindPurchaseButtons(
activity = requireActivity(),
activity = activity(),
app = app,
onTrialClicked = { listener?.onStartTrial() }
)
Expand Down Expand Up @@ -81,4 +82,7 @@ class WelcomeLicenseFragment : BaseFragment<FragmentWelcomeLicenseBinding>(Fragm
}
listener?.onLicenseTextChanged(license)
}

private fun activity(): WelcomeActivity = this.activity as WelcomeActivity

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.cryptomator.presentation.ui.layout

import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.view.View
Expand All @@ -9,7 +8,10 @@ import org.cryptomator.presentation.R
import org.cryptomator.presentation.databinding.ViewLicenseCheckContentBinding
import org.cryptomator.presentation.licensing.LicenseEnforcer
import org.cryptomator.presentation.service.ProductInfo
import org.cryptomator.presentation.service.RestoreOutcome
import org.cryptomator.presentation.service.resolveProductPrices
import org.cryptomator.presentation.service.toDialogFragment
import org.cryptomator.presentation.ui.activity.BaseActivity
import java.lang.ref.WeakReference

/** Shared visibility-toggling logic for the license check content included layout. */
Expand Down Expand Up @@ -78,7 +80,7 @@ class LicenseContentViewBinder(

/** Wires trial, subscription, lifetime, and restore button click listeners. */
fun bindPurchaseButtons(
activity: Activity,
activity: BaseActivity<*>,
app: CryptomatorApp,
onTrialClicked: () -> Unit
) {
Expand All @@ -90,10 +92,20 @@ class LicenseContentViewBinder(
app.launchPurchaseFlow(WeakReference(activity), ProductInfo.PRODUCT_FULL_VERSION)
}
binding.tvRestorePurchase.setOnClickListener {
app.restorePurchasesAndStore()
binding.tvRestorePurchase.isEnabled = false
app.restorePurchases { outcome ->
binding.root.post {
binding.tvRestorePurchase.isEnabled = true
showRestoreOutcome(activity, outcome)
}
}
}
}

private fun showRestoreOutcome(activity: BaseActivity<*>, outcome: RestoreOutcome) {
activity.showDialog(outcome.toDialogFragment())
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/** Queries product details and updates price buttons on the UI thread. */
fun loadAndBindPrices(app: CryptomatorApp) {
app.queryProductDetails { products ->
Expand Down Expand Up @@ -180,6 +192,7 @@ class LicenseContentViewBinder(
val text: String? = when {
lockedAction != null -> context.getString(lockedAction.headerMessageRes)
uiState.hasSubscriptionUpgradeHint -> context.getString(R.string.screen_license_check_subscription_upgrade_hint)
uiState.hasCancelSubscriptionHint -> context.getString(R.string.screen_license_check_cancel_subscription_hint, context.getString(R.string.screen_settings_manage_subscription))
uiState.trialState.isExpired && !uiState.hasPaidLicense -> context.getString(R.string.screen_license_check_trial_expired_info)
else -> null
}
Expand All @@ -190,3 +203,6 @@ class LicenseContentViewBinder(

private val LicenseEnforcer.LicenseUiState.hasSubscriptionUpgradeHint: Boolean
get() = hasRunningSubscription && !hasLifetimeLicense

private val LicenseEnforcer.LicenseUiState.hasCancelSubscriptionHint: Boolean
get() = hasRunningSubscription && hasLifetimeLicense

This file was deleted.

6 changes: 1 addition & 5 deletions presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
<string name="screen_license_check_trial_active_info">Trial expires: %s</string>
<string name="screen_license_check_trial_expired_info">Your trial has expired.</string>
<string name="screen_license_check_subscription_upgrade_hint">You have an active subscription. Buy the lifetime license and cancel your subscription to switch.</string>
<string name="screen_license_check_cancel_subscription_hint">You now have a lifetime license. To avoid future charges, cancel your yearly subscription via the %1$s option in Settings.</string>
<string name="screen_welcome_title">Welcome</string>
<string name="screen_welcome_notifications_title">Stay notified</string>
<string name="screen_welcome_notifications_message">Allow notifications so Cryptomator can inform you about background activity, auto uploads, or other important events.</string>
Expand Down Expand Up @@ -619,11 +620,6 @@
<string name="dialog_restore_failed_message">We couldn\u0027t reach the Play Store. Please check your connection and try again.</string>
<string name="dialog_restore_failed_positive_button" translatable="false">@string/dialog_unable_to_share_positive_button</string>

<string name="dialog_cancel_subscription_reminder_title">Remember to cancel your subscription</string>
<string name="dialog_cancel_subscription_reminder_message">You now have a lifetime license. To avoid future charges, please cancel your yearly subscription in the Google Play Store.</string>
<string name="dialog_cancel_subscription_reminder_manage_button">Manage Subscription</string>
<string name="dialog_cancel_subscription_reminder_close_button">Close</string>

<string name="dialog_hub_user_setup_required_title">User setup required</string>
<string name="dialog_hub_user_setup_required_hint">To proceed, please complete the steps required in your Hub user profile.</string>
<string name="dialog_hub_user_setup_required_neutral_button">Go to Profile</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,18 +246,6 @@ constructor(context: Context) : SharedPreferences.OnSharedPreferenceChangeListen
setPurchaseRevokedState(pending = false, reason = "")
}

fun pendingRestoreOutcome(): String {
return defaultSharedPreferences.getValue(PENDING_RESTORE_OUTCOME, "")
}

fun setPendingRestoreOutcome(kind: String) {
defaultSharedPreferences.setValue(PENDING_RESTORE_OUTCOME, kind)
}

fun clearPendingRestoreOutcome() {
defaultSharedPreferences.setValue(PENDING_RESTORE_OUTCOME, "")
}

fun hasRunningSubscription(): Boolean {
return defaultSharedPreferences.getValue(HAS_RUNNING_SUBSCRIPTION, false)
}
Expand Down Expand Up @@ -415,7 +403,6 @@ constructor(context: Context) : SharedPreferences.OnSharedPreferenceChangeListen
private const val HAS_RUNNING_SUBSCRIPTION = "hasRunningSubscription"
private const val PURCHASE_REVOKED_PENDING = "purchaseRevokedPending"
private const val PURCHASE_REVOKED_REASON = "purchaseRevokedReason"
private const val PENDING_RESTORE_OUTCOME = "pendingRestoreOutcome"
const val DEBUG_MODE = "debugMode"
const val DISABLE_APP_WHEN_OBSCURED = "disableAppWhenObscured"
const val SECURE_SCREEN = "secureScreen"
Expand Down
Loading