Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mahmoud-b28887f9.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

KPdfOpenDocumentState is a sealed interface that models the full lifecycle of letting a user pick a PDF from their device storage. Collect it from KPdfViewerState.openDocumentState (a StateFlow) and, on Success, pass the returned KPdfSource directly to viewerState.open() to load the chosen file. Trigger the picker by calling viewerState.requestOpenFromDevice(). The state resets to Idle when a new request is initiated.

Variants

Idle
data object
No picker session is in progress. This is the initial state and the state after a terminal event (Success, Cancelled, or Error) has been handled and the next request starts.
AwaitingSelection
data class
The platform file picker is open and waiting for the user to select a file.
requestId
Long
required
Unique identifier for this open request. Use it to correlate picker events when your UI logic needs to distinguish between multiple requests.
mimeTypes
List<String>
required
The MIME type filter list passed to the platform picker, typically ["application/pdf"]. The picker shows only files matching these types.
Success
data class
The user selected a file and the SDK has wrapped it in a KPdfSource ready for opening.
source
KPdfSource
required
A KPdfSource instance representing the chosen file. Pass this value to viewerState.open(source) to replace the current document.
Cancelled
data object
The user dismissed the picker without selecting a file. The current document remains open and unchanged.
Error
data class
The picker session failed or the SDK was unable to create a KPdfSource from the selected file.
reason
KPdfError
required
A sealed KPdfError value describing the failure. Inspect reason.message to get a human-readable explanation.

Handling a successful picker result in Compose

Use a LaunchedEffect keyed on openDocumentState to call viewerState.open() as soon as the user’s selection arrives. Pair it with a Button that calls requestOpenFromDevice() to launch the picker.
@Composable
fun OpenFromDeviceButton(viewerState: KPdfViewerState) {
    val openState by viewerState.openDocumentState.collectAsState()

    // React to a successful pick
    LaunchedEffect(openState) {
        val selectedSource = (openState as? KPdfOpenDocumentState.Success)?.source
            ?: return@LaunchedEffect

        viewerState.open(selectedSource)
    }

    // Trigger the picker
    Button(onClick = { viewerState.requestOpenFromDevice() }) {
        Text("Open Local PDF")
    }

    // Optional: surface picker status to the user
    when (openState) {
        KPdfOpenDocumentState.Idle -> Unit

        is KPdfOpenDocumentState.AwaitingSelection -> {
            Text("Choose a PDF file…")
        }

        is KPdfOpenDocumentState.Success -> {
            // LaunchedEffect above handles the open call;
            // you can show a brief "Opening…" indicator here.
            Text("Opening selected file…")
        }

        KPdfOpenDocumentState.Cancelled -> {
            Text("No file selected.")
        }

        is KPdfOpenDocumentState.Error -> {
            val error = (openState as KPdfOpenDocumentState.Error).reason
            Text("Could not open file: ${error.message}")
        }
    }
}

Notes

  • KPdfViewerState.openDocumentState is a StateFlow<KPdfOpenDocumentState>, so it is safe to collect from any composable without suspension on the first frame.
    • If you use rememberPdfViewerState, the native file-picker result callback is already wired automatically. You do not need to register any platform callbacks yourself.
  • If openDocumentState never advances past Idle after calling requestOpenFromDevice(), the most common cause is an unstable KPdfViewerConfig being rebuilt on every recomposition, which recreates the KPdfViewerState and clears the in-flight request. Wrap your config in a top-level remember block as shown in the rememberPdfViewerState reference.
  • After calling viewerState.open(selectedSource), loadState transitions through LoadingReady (or Error). You can observe both flows simultaneously.