Stripe Onboarding Provider Refactor Summary

Overview

The StripeOnboardingService has been refactored to follow the standardized Riverpod pattern used throughout the codebase, with proper integration with the AppStore singleton.

Key Changes

1. Removed Unnecessary Provider

  • Before: Had a separate @riverpod provider for StripeOnboardingPersistenceService
  • After: Creates the persistence service directly in the build method
  • Reason: The persistence service is an implementation detail and doesn’t need to be a provider

2. AppStore Integration

  • Uses AppStore.instance directly (singleton pattern)
  • Properly calls ensureSetup() before using AppStore
  • Falls back to default state if AppStore setup fails

3. Synchronous Notifier Pattern

  • Before: Attempted to use AsyncNotifier (incomplete refactor)
  • After: Uses synchronous Notifier<StripeOnboardingState>
  • Reason: Matches the pattern used in other services (ChatService, PledgeService, HomeFilterService)
  • Async initialization happens in background via _initializeAsync()

4. State Management

@override
StripeOnboardingState build() {
  // Initialize AppStore
  final appStore = AppStore.instance;
  if (!appStore.ensureSetup()) {
    return StripeOnboardingState.defaultState();
  }

  // Create persistence service
  _persistenceService = StripeOnboardingPersistenceService(appStore);

  // Load async in background
  if (!_isInitialized) {
    _initializeAsync();
  }

  // Return default immediately
  return StripeOnboardingState.defaultState();
}

5. Persistence Methods

All persistence operations properly use the _persistenceService:

  • updateState() - Updates state and persists
  • setCurrency() - Updates currency and persists
  • setAccount() - Updates account and persists
  • resetToDefault() - Resets and persists
  • clearPersistedState() - Clears storage
  • refresh() - Reloads from storage

6. Standardized API

Provides consistent methods matching other services:

  • updateState() - Main state update method
  • clearError() - No-op for consistency (Stripe state has no errors)
  • refresh() - Reload from persistence
  • reset() - Reset to default without persistence
  • isModified - Check if state differs from default

Architecture

┌─────────────────────────────────────┐
│  StripeOnboardingService            │
│  (Riverpod Notifier)                │
│                                     │
│  - build() - Sync initialization    │
│  - _initializeAsync() - Load data   │
│  - updateState() - Update & persist │
│  - setCurrency() - Update currency  │
│  - setAccount() - Update account    │
└──────────────┬──────────────────────┘
               │
               │ uses
               ▼
┌─────────────────────────────────────┐
│  StripeOnboardingPersistenceService │
│                                     │
│  - saveStripeState()                │
│  - loadStripeState()                │
│  - clearStripeState()               │
└──────────────┬──────────────────────┘
               │
               │ uses
               ▼
┌─────────────────────────────────────┐
│  AppStore (Singleton)               │
│                                     │
│  - ensureSetup()                    │
│  - read(key)                        │
│  - write(key, value)                │
│  - delete(key)                      │
└─────────────────────────────────────┘

Convenience Providers

The service includes several convenience providers for easy state access:

// Loading state
@riverpod bool stripeOnboardingIsLoading(Ref ref)

// Error state
@riverpod String? stripeOnboardingError(Ref ref)

// Modified check
@riverpod bool stripeOnboardingIsModified(Ref ref)

// Currency access
@riverpod StoredCurrencyModel stripeOnboardingCurrency(Ref ref)

// Account access
@riverpod StoredAccount stripeOnboardingAccount(Ref ref)

// Selection checks
@riverpod bool stripeOnboardingCurrencySelected(Ref ref)
@riverpod bool stripeOnboardingAccountSelected(Ref ref)
@riverpod bool stripeOnboardingReadyToProceed(Ref ref)

Usage Example

// Watch the state
final state = ref.watch(stripeOnboardingServiceProvider);

// Access notifier for updates
final notifier = ref.read(stripeOnboardingServiceProvider.notifier);

// Update currency
await notifier.setCurrency(newCurrency);

// Update account
await notifier.setAccount(newAccount);

// Check if ready to proceed
final isReady = ref.watch(stripeOnboardingReadyToProceedProvider);

// Reset state
await notifier.resetToDefault();

// Clear persisted data
await notifier.clearPersistedState();

Backward Compatibility

The alias stripeOnboardStartProvider is maintained for existing code:

/// Backward compatibility alias
final stripeOnboardStartProvider = stripeOnboardingServiceProvider;

Benefits

  1. Consistent Pattern: Matches other service providers in the codebase
  2. Proper AppStore Integration: Uses singleton pattern correctly
  3. Async Safety: Background loading doesn’t block initialization
  4. Persistence: Automatic state persistence on updates
  5. Type Safety: Full type safety with Riverpod code generation
  6. Convenience: Multiple convenience providers for common operations
  7. Error Handling: Graceful handling of storage failures

Notes

  • The service uses synchronous build() with async background loading
  • Storage failures are logged but don’t break the app
  • Default state is always available immediately
  • Persisted state loads in background and updates UI reactively
  • The AppStore singleton is still used (not converted to provider)