From 39392618ecfeb89576387b0229fd1ebee6229946 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Thu, 11 Jun 2026 15:59:12 +0200
Subject: [PATCH] fix(iap): align PurchaseService with the live store products

---
 lib/services/purchase_service.dart |   33 +++++++++++++++++++++------------
 1 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/lib/services/purchase_service.dart b/lib/services/purchase_service.dart
index a611657..d6dbe83 100644
--- a/lib/services/purchase_service.dart
+++ b/lib/services/purchase_service.dart
@@ -5,13 +5,15 @@
 import 'package:shared_preferences/shared_preferences.dart';
 
 /// Product ID for the one-time full-access purchase.
-const String kFullAccessProductId = 'com.tekmidian.pailot.fullaccess';
+/// Matches the IAPs registered in App Store Connect (Apple ID 6779190925)
+/// and Google Play Console (one-time product `com.tekmidian.pailot.pro`).
+const String kFullAccessProductId = 'com.tekmidian.pailot.pro';
 
 /// Maximum sessions allowed on the free tier.
 const int kFreeTierMaxSessions = 2;
 
-/// Maximum message age for free-tier users (15 minutes).
-const Duration kFreeTierMessageTtl = Duration(minutes: 15);
+/// Maximum message age for free-tier users.
+const Duration kFreeTierMessageTtl = Duration(minutes: 30);
 
 /// Shared preference key for caching purchase status locally.
 const String _kProCacheKey = 'pailot_is_pro';
@@ -51,20 +53,27 @@
 
   /// Initialize the service. Call once at app startup.
   Future<void> initialize() async {
-    // Restore cached value immediately so UI doesn't flicker.
-    // Default to true for dev/sideloaded builds (no StoreKit configured).
+    // Hydrate from local cache first so UI doesn't flash "Free" before the
+    // store reply lands. The cache is authoritative for offline / cold-start
+    // rendering; restorePurchases() reconciles it with the platform stores.
     final prefs = await SharedPreferences.getInstance();
-    // Force pro for now — clear any stale false value from earlier testing
-    _isPro = true;
-    await prefs.setBool(_kProCacheKey, true);
+    _isPro = prefs.getBool(_kProCacheKey) ?? false;
     notifyListeners();
 
-    // Check if IAP is available — may not be on dev/sideloaded builds
+    // If the platform IAP layer isn't available (sideloaded dev build, no
+    // network, simulator without StoreKit config), keep the cached value as-is
+    // and skip the store dance. In debug, default to Pro so dev testing isn't
+    // blocked by the paywall — but never override in release builds.
     final available = await InAppPurchase.instance.isAvailable();
     if (!available) {
-      debugPrint('[IAP] StoreKit not available — assuming pro (dev build)');
-      _isPro = true;
-      notifyListeners();
+      if (kDebugMode && !_isPro) {
+        debugPrint('[IAP] Store unavailable in debug build — granting Pro for dev testing');
+        _isPro = true;
+        await prefs.setBool(_kProCacheKey, true);
+        notifyListeners();
+      } else {
+        debugPrint('[IAP] Store unavailable; using cached isPro=$_isPro');
+      }
       return;
     }
 

--
Gitblit v1.3.1