SolPanViewModel

class SolPanViewModel(val initialMode: TiltMode, preferencesRepository: UserPreferencesRepository, locationRepository: LocationRepository, analytics: AnalyticsTracker, magneticDeclinationProvider: MagneticDeclinationProvider = AndroidMagneticDeclinationProvider()) : ViewModel

Main state management ViewModel for SolPan.

Combines multiple reactive streams (location, orientation, magnetic declination, preferences) to produce a unified uiState that the UI observes. All state updates are reactive and observable via StateFlow, ensuring the UI always reflects the current system state.

Reactive Architecture

The ViewModel follows a reactive architecture pattern:

  • Location updates are debounced (300ms) to avoid excessive recomputation

  • Magnetic declination is computed lazily from location changes

  • Solar calculations are recomputed when tilt mode or location changes

  • Realtime mode ticks every 30 seconds to update sun position

  • UI state combines all streams with WhileSubscribed(5000) to auto-cleanup when UI is backgrounded

Key Flows

  • optimalPanelParameters: Combines location, declination, mode, and realtime ticks

  • uiState: Master state object combining all UI-relevant data

  • showTutorial: Combines user preferences with manual tutorial overrides

Thread Safety

All state flows are thread-safe and backed by coroutines. Updates from sensors/location providers are marshalled through the viewModelScope dispatcher.

Parameters

initialMode

The starting tilt mode (typically TiltMode.REALTIME)

preferencesRepository

User preferences (tutorial state, saved settings)

locationRepository

Location stream and persistence

analytics

Analytics event tracking

magneticDeclinationProvider

Magnetic declination calculator (injectable for testing)

Constructors

Link copied to clipboard
constructor(initialMode: TiltMode, preferencesRepository: UserPreferencesRepository, locationRepository: LocationRepository, analytics: AnalyticsTracker, magneticDeclinationProvider: MagneticDeclinationProvider = AndroidMagneticDeclinationProvider())

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
val currentLocation: StateFlow<LocationData?>

Current user location from GPS or fused location provider. Null if permission not granted.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
val showTutorial: StateFlow<Boolean>
Link copied to clipboard
val uiState: StateFlow<SolPanUiState>

The single source of truth for the UI. Masterclass Architecture: Unifying multiple streams into one immutable state object.

Functions

Link copied to clipboard
open fun addCloseable(closeable: AutoCloseable)
fun addCloseable(key: String, closeable: AutoCloseable)
Link copied to clipboard

Dismisses the tutorial overlay and marks it as seen.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard

Manually requests to show the tutorial overlay.

Link copied to clipboard

Toggles debug mode for testing panel alignment without GPS lock.

Link copied to clipboard
fun updateLocation(newLocation: LocationData?)

Updates the current location for optimization calculations.

Link copied to clipboard

Updates the current device orientation from sensors.