Loading packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ class CredentialSelectorActivity : Hilt_CredentialSelectorActivity() { setContent { MaterialTheme { WearApp( viewModel = viewModel, flowEngine = viewModel, onCloseApp = { finish() }, ) } Loading packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +1 −30 Original line number Diff line number Diff line Loading @@ -24,9 +24,6 @@ import com.android.credentialmanager.CredentialSelectorUiState.Get import com.android.credentialmanager.model.Request import com.android.credentialmanager.client.CredentialManagerClient import com.android.credentialmanager.model.EntryInfo import com.android.credentialmanager.model.get.ActionEntryInfo import com.android.credentialmanager.model.get.AuthenticationEntryInfo import com.android.credentialmanager.model.get.CredentialEntryInfo import com.android.credentialmanager.ui.mappers.toGet import android.util.Log import androidx.activity.compose.rememberLauncherForActivityResult Loading @@ -53,7 +50,7 @@ class CredentialSelectorViewModel @Inject constructor( private val shouldClose = MutableStateFlow(false) private lateinit var selectedEntry: EntryInfo private var isAutoSelected: Boolean = false val uiState: StateFlow<CredentialSelectorUiState> = override val uiState: StateFlow<CredentialSelectorUiState> = combine( credentialManagerClient.requests, isPrimaryScreen, Loading Loading @@ -137,29 +134,3 @@ class CredentialSelectorViewModel @Inject constructor( } } sealed class CredentialSelectorUiState { data object Idle : CredentialSelectorUiState() sealed class Get : CredentialSelectorUiState() { data class SingleEntry(val entry: CredentialEntryInfo) : Get() data class SingleEntryPerAccount( val sortedEntries: List<CredentialEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() data class MultipleEntry( val accounts: List<PerUserNameEntries>, val actionEntryList: List<ActionEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() { data class PerUserNameEntries( val userName: String, val sortedCredentialEntryList: List<CredentialEntryInfo>, ) } // TODO: b/301206470 add the remaining states } data object Create : CredentialSelectorUiState() data class Cancel(val appName: String) : CredentialSelectorUiState() data object Close : CredentialSelectorUiState() } packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt +42 −0 Original line number Diff line number Diff line Loading @@ -20,9 +20,15 @@ import android.content.Intent import androidx.activity.result.IntentSenderRequest import androidx.compose.runtime.Composable import com.android.credentialmanager.model.EntryInfo import com.android.credentialmanager.model.get.ActionEntryInfo import com.android.credentialmanager.model.get.AuthenticationEntryInfo import com.android.credentialmanager.model.get.CredentialEntryInfo import kotlinx.coroutines.flow.StateFlow /** Engine of the credential selecting flow. */ interface FlowEngine { /** UI state of the selector app */ val uiState: StateFlow<CredentialSelectorUiState> /** Back from previous stage. */ fun back() /** Cancels the selection flow. */ Loading Loading @@ -55,3 +61,39 @@ interface FlowEngine { @Composable fun getEntrySelector(): (entry: EntryInfo, isAutoSelected: Boolean) -> Unit } /** UI state of the selector app */ sealed class CredentialSelectorUiState { /** Idle UI state, no request is going on. */ data object Idle : CredentialSelectorUiState() /** Getting credential UI state. */ sealed class Get : CredentialSelectorUiState() { /** Getting credential UI state when there is only one credential available. */ data class SingleEntry(val entry: CredentialEntryInfo) : Get() /** * Getting credential UI state when there is only one account while with multiple * credentials, with different types(eg, passkey vs password) or providers. */ data class SingleEntryPerAccount( val sortedEntries: List<CredentialEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() /** Getting credential UI state when there are multiple accounts available. */ data class MultipleEntry( val accounts: List<PerUserNameEntries>, val actionEntryList: List<ActionEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() { data class PerUserNameEntries( val userName: String, val sortedCredentialEntryList: List<CredentialEntryInfo>, ) } } /** Creating credential UI state. */ data object Create : CredentialSelectorUiState() /** Request is cancelling by [appName]. */ data class Cancel(val appName: String) : CredentialSelectorUiState() /** Request is closed peacefully. */ data object Close : CredentialSelectorUiState() } No newline at end of file packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt +3 −5 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import com.android.credentialmanager.CredentialSelectorUiState import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntryPerAccount import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntry import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry import com.android.credentialmanager.CredentialSelectorViewModel import com.android.credentialmanager.FlowEngine import com.android.credentialmanager.TAG import com.android.credentialmanager.ui.screens.LoadingScreen Loading @@ -52,8 +51,7 @@ import com.android.credentialmanager.ui.screens.multiple.MultiCredentialsFlatten @OptIn(ExperimentalHorologistApi::class) @Composable fun WearApp( viewModel: CredentialSelectorViewModel, flowEngine: FlowEngine = viewModel, flowEngine: FlowEngine, onCloseApp: () -> Unit, ) { val navController = rememberSwipeDismissableNavController() Loading @@ -62,7 +60,7 @@ fun WearApp( rememberSwipeDismissableNavHostState(swipeToDismissBoxState = swipeToDismissBoxState) val selectEntry = flowEngine.getEntrySelector() val uiState by viewModel.uiState.collectAsStateWithLifecycle() val uiState by flowEngine.uiState.collectAsStateWithLifecycle() WearNavScaffold( startDestination = Screen.Loading.route, navController = navController, Loading Loading @@ -112,7 +110,7 @@ fun WearApp( } } BackHandler(true) { viewModel.back() flowEngine.back() } Log.d(TAG, "uiState change, state: $uiState") when (val state = uiState) { Loading Loading
packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ class CredentialSelectorActivity : Hilt_CredentialSelectorActivity() { setContent { MaterialTheme { WearApp( viewModel = viewModel, flowEngine = viewModel, onCloseApp = { finish() }, ) } Loading
packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +1 −30 Original line number Diff line number Diff line Loading @@ -24,9 +24,6 @@ import com.android.credentialmanager.CredentialSelectorUiState.Get import com.android.credentialmanager.model.Request import com.android.credentialmanager.client.CredentialManagerClient import com.android.credentialmanager.model.EntryInfo import com.android.credentialmanager.model.get.ActionEntryInfo import com.android.credentialmanager.model.get.AuthenticationEntryInfo import com.android.credentialmanager.model.get.CredentialEntryInfo import com.android.credentialmanager.ui.mappers.toGet import android.util.Log import androidx.activity.compose.rememberLauncherForActivityResult Loading @@ -53,7 +50,7 @@ class CredentialSelectorViewModel @Inject constructor( private val shouldClose = MutableStateFlow(false) private lateinit var selectedEntry: EntryInfo private var isAutoSelected: Boolean = false val uiState: StateFlow<CredentialSelectorUiState> = override val uiState: StateFlow<CredentialSelectorUiState> = combine( credentialManagerClient.requests, isPrimaryScreen, Loading Loading @@ -137,29 +134,3 @@ class CredentialSelectorViewModel @Inject constructor( } } sealed class CredentialSelectorUiState { data object Idle : CredentialSelectorUiState() sealed class Get : CredentialSelectorUiState() { data class SingleEntry(val entry: CredentialEntryInfo) : Get() data class SingleEntryPerAccount( val sortedEntries: List<CredentialEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() data class MultipleEntry( val accounts: List<PerUserNameEntries>, val actionEntryList: List<ActionEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() { data class PerUserNameEntries( val userName: String, val sortedCredentialEntryList: List<CredentialEntryInfo>, ) } // TODO: b/301206470 add the remaining states } data object Create : CredentialSelectorUiState() data class Cancel(val appName: String) : CredentialSelectorUiState() data object Close : CredentialSelectorUiState() }
packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt +42 −0 Original line number Diff line number Diff line Loading @@ -20,9 +20,15 @@ import android.content.Intent import androidx.activity.result.IntentSenderRequest import androidx.compose.runtime.Composable import com.android.credentialmanager.model.EntryInfo import com.android.credentialmanager.model.get.ActionEntryInfo import com.android.credentialmanager.model.get.AuthenticationEntryInfo import com.android.credentialmanager.model.get.CredentialEntryInfo import kotlinx.coroutines.flow.StateFlow /** Engine of the credential selecting flow. */ interface FlowEngine { /** UI state of the selector app */ val uiState: StateFlow<CredentialSelectorUiState> /** Back from previous stage. */ fun back() /** Cancels the selection flow. */ Loading Loading @@ -55,3 +61,39 @@ interface FlowEngine { @Composable fun getEntrySelector(): (entry: EntryInfo, isAutoSelected: Boolean) -> Unit } /** UI state of the selector app */ sealed class CredentialSelectorUiState { /** Idle UI state, no request is going on. */ data object Idle : CredentialSelectorUiState() /** Getting credential UI state. */ sealed class Get : CredentialSelectorUiState() { /** Getting credential UI state when there is only one credential available. */ data class SingleEntry(val entry: CredentialEntryInfo) : Get() /** * Getting credential UI state when there is only one account while with multiple * credentials, with different types(eg, passkey vs password) or providers. */ data class SingleEntryPerAccount( val sortedEntries: List<CredentialEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() /** Getting credential UI state when there are multiple accounts available. */ data class MultipleEntry( val accounts: List<PerUserNameEntries>, val actionEntryList: List<ActionEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() { data class PerUserNameEntries( val userName: String, val sortedCredentialEntryList: List<CredentialEntryInfo>, ) } } /** Creating credential UI state. */ data object Create : CredentialSelectorUiState() /** Request is cancelling by [appName]. */ data class Cancel(val appName: String) : CredentialSelectorUiState() /** Request is closed peacefully. */ data object Close : CredentialSelectorUiState() } No newline at end of file
packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt +3 −5 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import com.android.credentialmanager.CredentialSelectorUiState import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntryPerAccount import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntry import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry import com.android.credentialmanager.CredentialSelectorViewModel import com.android.credentialmanager.FlowEngine import com.android.credentialmanager.TAG import com.android.credentialmanager.ui.screens.LoadingScreen Loading @@ -52,8 +51,7 @@ import com.android.credentialmanager.ui.screens.multiple.MultiCredentialsFlatten @OptIn(ExperimentalHorologistApi::class) @Composable fun WearApp( viewModel: CredentialSelectorViewModel, flowEngine: FlowEngine = viewModel, flowEngine: FlowEngine, onCloseApp: () -> Unit, ) { val navController = rememberSwipeDismissableNavController() Loading @@ -62,7 +60,7 @@ fun WearApp( rememberSwipeDismissableNavHostState(swipeToDismissBoxState = swipeToDismissBoxState) val selectEntry = flowEngine.getEntrySelector() val uiState by viewModel.uiState.collectAsStateWithLifecycle() val uiState by flowEngine.uiState.collectAsStateWithLifecycle() WearNavScaffold( startDestination = Screen.Loading.route, navController = navController, Loading Loading @@ -112,7 +110,7 @@ fun WearApp( } } BackHandler(true) { viewModel.back() flowEngine.back() } Log.d(TAG, "uiState change, state: $uiState") when (val state = uiState) { Loading