Add task completion animations, subscription trials, and quiet debug console
- Completion animations: play user-selected animation on task card after completing, with DataManager guard to prevent race condition during animation playback. Works in both AllTasksView and ResidenceDetailView. Animation preference persisted via @AppStorage and configurable from Settings. - Subscription: add trial fields (trialStart, trialEnd, trialActive) and subscriptionSource to model, cross-platform purchase guard, trial banner in upgrade prompt, and platform-aware subscription management in profile. - Analytics: disable PostHog SDK debug logging and remove console print statements to reduce debug console noise. - Documents: remove redundant nested do-catch blocks in ViewModel wrapper. - Widgets: add debounced timeline reloads and thread-safe file I/O queue. - Onboarding: fix animation leak on disappear, remove unused state vars. - Remove unused files (ContentView, StateFlowExtensions, CustomView). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -45,12 +45,13 @@ object SubscriptionHelper {
|
||||
|
||||
/**
|
||||
* Derive the current subscription tier from DataManager.
|
||||
* "pro" if the backend subscription has a non-empty expiresAt (active paid plan),
|
||||
* "pro" if the backend subscription has an active trial or a non-empty expiresAt (active paid plan),
|
||||
* "free" otherwise.
|
||||
*/
|
||||
val currentTier: String
|
||||
get() {
|
||||
val subscription = DataManager.subscription.value ?: return "free"
|
||||
if (subscription.trialActive) return "pro"
|
||||
val expiresAt = subscription.expiresAt
|
||||
return if (!expiresAt.isNullOrEmpty()) "pro" else "free"
|
||||
}
|
||||
@@ -68,6 +69,25 @@ object SubscriptionHelper {
|
||||
return currentTier == "pro"
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user can purchase a subscription on the given platform.
|
||||
* If the user already has an active Pro subscription from a different platform,
|
||||
* purchasing on this platform is not allowed.
|
||||
*
|
||||
* @param currentPlatform The platform attempting the purchase ("ios", "android", or "stripe")
|
||||
* @return UsageCheck with allowed=false if already subscribed on another platform
|
||||
*/
|
||||
fun canPurchaseOnPlatform(currentPlatform: String): UsageCheck {
|
||||
val subscription = DataManager.subscription.value
|
||||
?: return UsageCheck(allowed = true, triggerKey = null)
|
||||
if (currentTier != "pro") return UsageCheck(allowed = true, triggerKey = null)
|
||||
val source = subscription.subscriptionSource
|
||||
if (source != null && source != currentPlatform) {
|
||||
return UsageCheck(allowed = false, triggerKey = "already_subscribed_other_platform")
|
||||
}
|
||||
return UsageCheck(allowed = true, triggerKey = null)
|
||||
}
|
||||
|
||||
// ===== PROPERTY (RESIDENCE) =====
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user