import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:hiddify/core/preferences/preferences_provider.dart'; import 'package:hiddify/features/config_option/data/config_option_repository.dart'; import 'package:hiddify/features/config_option/model/config_option_failure.dart'; import 'package:hiddify/singbox/service/singbox_service_provider.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shared_preferences/shared_preferences.dart'; part 'warp_option_notifier.freezed.dart'; part 'warp_option_notifier.g.dart'; @Riverpod(keepAlive: true) class WarpOptionNotifier extends _$WarpOptionNotifier with AppLogger { @override WarpOptions build() { final consent = _prefs.getBool(warpConsentGiven) ?? false; bool hasWarpConfig = false; try { final accountId = _prefs.getString("warp-account-id"); final accessToken = _prefs.getString("warp-access-token"); hasWarpConfig = accountId != null && accessToken != null; } catch (e) { loggy.warning(e); } return WarpOptions( consentGiven: consent, configGeneration: hasWarpConfig ? const AsyncValue.data("") : AsyncError(const MissingWarpConfigFailure(), StackTrace.current), ); } SharedPreferences get _prefs => ref.read(sharedPreferencesProvider).requireValue; Future agree() async { await ref.read(sharedPreferencesProvider).requireValue.setBool(warpConsentGiven, true); state = state.copyWith(consentGiven: true); await generateWarpConfig(); } Future generateWarpConfig() async { if (state.configGeneration.isLoading) return; state = state.copyWith(configGeneration: const AsyncLoading()); final result = await AsyncValue.guard(() async { final warp = await ref .read(singboxServiceProvider) .generateWarpConfig( licenseKey: ref.read(ConfigOptions.warpLicenseKey), previousAccountId: ref.read(ConfigOptions.warpAccountId), previousAccessToken: ref.read(ConfigOptions.warpAccessToken), ) .getOrElse((l) => throw l) .run(); await ref.read(ConfigOptions.warpAccountId.notifier).update(warp.accountId); await ref.read(ConfigOptions.warpAccessToken.notifier).update(warp.accessToken); await ref.read(ConfigOptions.warpWireguardConfig.notifier).update(warp.wireguardConfig); return warp.log; }); state = state.copyWith(configGeneration: result); } Future generateWarp2Config() async { if (state.configGeneration.isLoading) return; state = state.copyWith(configGeneration: const AsyncLoading()); final result = await AsyncValue.guard(() async { final warp = await ref .read(singboxServiceProvider) .generateWarpConfig( licenseKey: ref.read(ConfigOptions.warpLicenseKey), previousAccountId: ref.read(ConfigOptions.warp2AccountId), previousAccessToken: ref.read(ConfigOptions.warp2AccessToken), ) .getOrElse((l) => throw l) .run(); await ref.read(ConfigOptions.warp2AccountId.notifier).update(warp.accountId); await ref.read(ConfigOptions.warp2AccessToken.notifier).update(warp.accessToken); await ref.read(ConfigOptions.warp2WireguardConfig.notifier).update(warp.wireguardConfig); return warp.log; }); state = state.copyWith(configGeneration: result); } static const warpConsentGiven = "warp_consent_given"; } @freezed class WarpOptions with _$WarpOptions { const factory WarpOptions({ required bool consentGiven, required AsyncValue configGeneration, }) = _WarpOptions; }