Matthias Nott
2026-06-11 39392618ecfeb89576387b0229fd1ebee6229946
lib/services/purchase_service.dart
....@@ -5,13 +5,15 @@
55 import 'package:shared_preferences/shared_preferences.dart';
66
77 /// Product ID for the one-time full-access purchase.
8
-const String kFullAccessProductId = 'com.tekmidian.pailot.fullaccess';
8
+/// Matches the IAPs registered in App Store Connect (Apple ID 6779190925)
9
+/// and Google Play Console (one-time product `com.tekmidian.pailot.pro`).
10
+const String kFullAccessProductId = 'com.tekmidian.pailot.pro';
911
1012 /// Maximum sessions allowed on the free tier.
1113 const int kFreeTierMaxSessions = 2;
1214
13
-/// Maximum message age for free-tier users (15 minutes).
14
-const Duration kFreeTierMessageTtl = Duration(minutes: 15);
15
+/// Maximum message age for free-tier users.
16
+const Duration kFreeTierMessageTtl = Duration(minutes: 30);
1517
1618 /// Shared preference key for caching purchase status locally.
1719 const String _kProCacheKey = 'pailot_is_pro';
....@@ -51,20 +53,27 @@
5153
5254 /// Initialize the service. Call once at app startup.
5355 Future<void> initialize() async {
54
- // Restore cached value immediately so UI doesn't flicker.
55
- // Default to true for dev/sideloaded builds (no StoreKit configured).
56
+ // Hydrate from local cache first so UI doesn't flash "Free" before the
57
+ // store reply lands. The cache is authoritative for offline / cold-start
58
+ // rendering; restorePurchases() reconciles it with the platform stores.
5659 final prefs = await SharedPreferences.getInstance();
57
- // Force pro for now — clear any stale false value from earlier testing
58
- _isPro = true;
59
- await prefs.setBool(_kProCacheKey, true);
60
+ _isPro = prefs.getBool(_kProCacheKey) ?? false;
6061 notifyListeners();
6162
62
- // Check if IAP is available — may not be on dev/sideloaded builds
63
+ // If the platform IAP layer isn't available (sideloaded dev build, no
64
+ // network, simulator without StoreKit config), keep the cached value as-is
65
+ // and skip the store dance. In debug, default to Pro so dev testing isn't
66
+ // blocked by the paywall — but never override in release builds.
6367 final available = await InAppPurchase.instance.isAvailable();
6468 if (!available) {
65
- debugPrint('[IAP] StoreKit not available — assuming pro (dev build)');
66
- _isPro = true;
67
- notifyListeners();
69
+ if (kDebugMode && !_isPro) {
70
+ debugPrint('[IAP] Store unavailable in debug build — granting Pro for dev testing');
71
+ _isPro = true;
72
+ await prefs.setBool(_kProCacheKey, true);
73
+ notifyListeners();
74
+ } else {
75
+ debugPrint('[IAP] Store unavailable; using cached isPro=$_isPro');
76
+ }
6877 return;
6978 }
7079