package com.peachpasswords import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow /** * Launch actions the app declares to the system: the three launcher shortcuts in * `res/xml/shortcuts.xml` and the credential-provider unlock entry point in * [com.peachpasswords.passkeys.PasskeyUnlockIntent]. These strings are a public * contract with the launcher and with system UI — they must stay byte-identical * to the manifest/XML, so they live in one place rather than being retyped. */ object PeachActions { const val SEARCH = "com.peachpasswords.action.SEARCH" const val ADD = "com.peachpasswords.action.ADD" const val PAIR = "com.peachpasswords.action.PAIR" const val PASSKEY_UNLOCK = "com.peachpasswords.passkeys.ACTION_PASSKEY_UNLOCK" } /** What a launch action asks the app to do once the vault is actually open. */ enum class PendingAction { Search, AddEntry, Pair, PasskeyUnlock } /** Unknown/absent actions (the plain launcher icon) route nowhere — start destination wins. */ fun routeAction(action: String?): PendingAction? = when (action) { PeachActions.SEARCH -> PendingAction.Search PeachActions.ADD -> PendingAction.AddEntry PeachActions.PAIR -> PendingAction.Pair PeachActions.PASSKEY_UNLOCK -> PendingAction.PasskeyUnlock else -> null } /** * Holds the action from the launch intent until the vault is unlocked. Every one * of these destinations needs an open vault, and a shortcut can be tapped while * the app is locked or not running at all, so the request has to outlive the * lock screen instead of being spent on it. * * ponytail: a process-scoped object rather than a Hilt singleton + ViewModel like * [com.peachpasswords.autofill.AutofillNavRepository]. Single activity, single * process, one consumer — the DI ceremony buys nothing here. Promote it if a * second consumer or a test that needs isolation ever appears. */ object PendingActionQueue { private val _pending = MutableStateFlow(null) val pending: StateFlow = _pending.asStateFlow() fun request(action: PendingAction) { _pending.value = action } fun consume() { _pending.value = null } }