// ignore_for_file: deprecated_member_use import 'package:didvan/services/auth/token_storage.dart'; import 'package:didvan/services/storage/storage.dart'; import 'package:flutter/foundation.dart'; import 'package:package_info_plus/package_info_plus.dart'; /// ساده‌ساز migrationهای داده‌ی محلی هنگام آپدیت اپ. /// /// انگیزه: کاربرانی که از نسخه‌های قبل از سوییچ به API جدید آپدیت می‌کنند /// توکن/cache قدیمی با schema سرور جدید نمی‌خواند و موقع splash گیر می‌افتد /// (تا اینکه کاربر دستی Clear Data بکند). این کلاس همان clear data را خودش /// انجام می‌دهد — فقط یک بار، روی اولین اجرا با نسخه‌ی جدید. class AppMigration { /// آخرین نسخه‌ای که schema داده‌ی محلی را شکست و باید کاربران را خروج کند. /// هر کاربر با نسخه‌ی قبل از این، در آپدیت بعدی auto-logout می‌شود. /// اگر در آینده schema باز هم شکست، این عدد را افزایش بده. static const int _breakingDataVersion = 2; /// کلید storage برای نگه‌داری نسخه‌ی schema که آخرین بار کاربر رویش بود. static const String _storageKey = '_app_data_schema_version'; /// کلیدهایی که هنگام پاکسازی **حفظ** می‌شوند (UI preferences کاربر). static const Set _keysToKeep = { 'brightness', 'fontFamily', 'fontScale', 'hasSeenOnboarding', _storageKey, }; /// در اولین مرحله‌ی splash صدا زده می‌شود (قبل از هر API call). /// در صورت لزوم data قدیمی را پاک می‌کند و سپس نسخه‌ی فعلی را ذخیره می‌کند. static Future runIfNeeded() async { try { final stored = await StorageService.getValue(key: _storageKey); final int previousVersion = _parseInt(stored); if (previousVersion >= _breakingDataVersion) { return; // نیازی به migration نیست. } debugPrint( 'AppMigration: detected previous schema=$previousVersion ' '(< $_breakingDataVersion), running cleanup...', ); await _clearLegacyData(); await StorageService.setValue( key: _storageKey, value: _breakingDataVersion.toString(), ); debugPrint('AppMigration: done, marker set to $_breakingDataVersion'); } catch (e) { // migration نباید app رو crash بده — اگه چیزی شکست، فقط log debugPrint('AppMigration failed (non-fatal): $e'); } } /// پاکسازی auth + همه‌ی state صفحه‌ای؛ UI prefs حفظ می‌شوند. static Future _clearLegacyData() async { // 1. توکن‌ها (legacy + keycloak) try { await TokenStorage.clear(); } catch (e) { debugPrint('AppMigration: TokenStorage.clear failed: $e'); } // 2. کلیدهای متفرقه‌ی legacy const legacyKeys = [ 'token', 'refresh_token', 'user_data', 'user_id', 'notification', // پایه‌ی notification ids 'image-cache', ]; for (final k in legacyKeys) { try { await StorageService.delete(key: k); } catch (_) {} } } static int _parseInt(dynamic v) { if (v == null) return 0; if (v is int) return v; return int.tryParse(v.toString()) ?? 0; } /// برای debug — نسخه‌ی فعلی app static Future currentAppVersion() async { try { final info = await PackageInfo.fromPlatform(); return info.version; } catch (_) { return 'unknown'; } } }