Skip to content

Add maInit callback to MobileApp for post-context IO #189

@jappeace-sloth

Description

@jappeace-sloth

Problem

startMobileApp sets up the platform context (Android JNI env, files directory, etc.) before invoking any callbacks. But the MobileApp value must be fully constructed before calling startMobileApp, so there is no way to run IO that depends on the platform context during app setup.

This forces consumer apps to use either:

Both are awkward. The IORef cache adds complexity, and the lazy init means the first render pays the full DB setup cost.

Proposed solution

Change startMobileApp to accept an IO MobileApp builder instead of a plain MobileApp:

-- before
startMobileApp :: MobileApp -> IO (Ptr AppContext)

-- after
startMobileApp :: IO MobileApp -> IO (Ptr AppContext)

startMobileApp would set up the platform context first, then run the IO MobileApp action to let the consumer build its app with full filesystem/JNI access, then proceed with the first render.

This lets consumer apps construct state eagerly:

main = startMobileApp $ do
  actionState <- newActionState
  appState <- withDatabase $ \conn -> do
    initDB conn
    loadRecords conn >>= newAppState
  appActions <- runActionM actionState (createAppActions appState)
  pure MobileApp
    { maContext     = ...
    , maView        = \userState -> appRootView appActions appState
    , maActionState = actionState
    }

No unsafePerformIO, no deferred caching, no lazy init on first render.

Context

Discovered while removing unsafePerformIO globals from prrrrrrrrr (jappeace/prrrrrrrrr#60). The app crashed on Android because get_app_files_dir was called before startMobileApp had set up the JNI context.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions