57 lines
2.1 KiB
Dart
57 lines
2.1 KiB
Dart
import 'dart:async';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import '../services/license_service.dart';
|
||
|
||
/// 起動時にキャッシュから事前ロードした値を保持するプロバイダー
|
||
///
|
||
/// main() で override して初期値を渡すことで、
|
||
/// licenseStatusProvider が loading 状態を経由せず即座に AsyncData になる。
|
||
final licenseInitialStatusProvider = Provider<LicenseStatus?>((ref) => null);
|
||
|
||
/// ライセンス状態プロバイダー
|
||
///
|
||
/// - build() は licenseInitialStatusProvider に値がある場合は同期で返す(ちらつきなし)
|
||
/// - 同時にバックグラウンドでサーバー検証を実行し、差異があれば状態を更新する
|
||
final licenseStatusProvider =
|
||
AsyncNotifierProvider<LicenseStatusNotifier, LicenseStatus>(
|
||
LicenseStatusNotifier.new,
|
||
);
|
||
|
||
class LicenseStatusNotifier extends AsyncNotifier<LicenseStatus> {
|
||
@override
|
||
FutureOr<LicenseStatus> build() {
|
||
final initial = ref.read(licenseInitialStatusProvider);
|
||
if (initial != null) {
|
||
// キャッシュ値を同期で返すことで loading 状態をスキップ
|
||
_refreshFromServer();
|
||
return initial;
|
||
}
|
||
// override なし(テスト等): 通常フロー
|
||
return LicenseService.checkStatus();
|
||
}
|
||
|
||
/// バックグラウンドでサーバー検証を実行し、変化があれば状態を更新する
|
||
Future<void> _refreshFromServer() async {
|
||
try {
|
||
final fresh = await LicenseService.checkStatus();
|
||
if (state.hasValue && state.value != fresh) {
|
||
state = AsyncData(fresh);
|
||
}
|
||
} catch (_) {
|
||
// ネットワークエラーはキャッシュ値を維持
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Pro版かどうか(ナビゲーション・機能解放の分岐に使う)
|
||
///
|
||
/// licenseStatusProvider が同期で AsyncData を返すため、
|
||
/// アプリ起動時に false をちらつかせることなく正しい値を返す。
|
||
final isProProvider = Provider<bool>((ref) {
|
||
final statusAsync = ref.watch(licenseStatusProvider);
|
||
return statusAsync.maybeWhen(
|
||
data: (status) => status == LicenseStatus.pro,
|
||
orElse: () => false,
|
||
);
|
||
});
|