Merge "Remote authenticator settings layout." into main

This commit is contained in:
Justin McClain
2023-08-15 19:40:49 +00:00
committed by Android (Google) Code Review
11 changed files with 487 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.remoteauth.settings
data class RemoteAuthAuthenticatorItemUiState(
val name: String,
val isActive: Boolean,
val unregister: () -> Unit,
)

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.remoteauth.settings
import android.os.Bundle
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.settings.R
import kotlinx.coroutines.launch
class RemoteAuthSettings : Fragment(R.layout.remote_auth_settings) {
// TODO(b/293906345): Scope viewModel to navigation graph when implementing navigation.
val viewModel = RemoteAuthSettingsViewModel()
private val adapter = RemoteAuthSettingsRecyclerViewAdapter()
private val recyclerView by lazy {
view!!.findViewById<RecyclerView>(R.id.registered_authenticator_list)
}
private val addAuthenticatorLayout by lazy {
view!!.findViewById<ConstraintLayout>(R.id.add_authenticator_layout)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.adapter = adapter
// Collect UIState and update UI on changes.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
updateUi(it)
}
}
}
// Add new remote authenticator click listener
addAuthenticatorLayout.setOnClickListener {
// TODO(b/293906345): Wire up navigation
}
}
private fun updateUi(uiState: RemoteAuthSettingsUiState) {
adapter.uiStates = uiState.registeredAuthenticatorUiStates
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.remoteauth.settings
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.android.settings.R
class RemoteAuthSettingsRecyclerViewAdapter() :
RecyclerView.Adapter<RemoteAuthSettingsRecyclerViewAdapter.ViewHolder>() {
var uiStates = listOf<RemoteAuthAuthenticatorItemUiState>()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.remote_auth_settings_authenticator_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder.bind(uiStates[position])
}
override fun getItemCount() = uiStates.size
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val titleTextView: TextView = view.findViewById(R.id.authenticator_name_text)
private val unregisterButton: ImageView = view.findViewById(R.id.remove_icon)
fun bind(authenticatorUiState: RemoteAuthAuthenticatorItemUiState) {
titleTextView.text = authenticatorUiState.name
unregisterButton.setOnClickListener { authenticatorUiState.unregister() }
}
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.remoteauth.settings
data class RemoteAuthSettingsUiState(
val registeredAuthenticatorUiStates: List<RemoteAuthAuthenticatorItemUiState> = listOf(),
// TODO(b/295524962): Change to error code in teamfood and add errors to strings.xml
val errorMsg: String? = null,
)

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.remoteauth.settings
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class RemoteAuthSettingsViewModel : ViewModel() {
private val _uiState = MutableStateFlow(RemoteAuthSettingsUiState())
val uiState: StateFlow<RemoteAuthSettingsUiState> = _uiState.asStateFlow()
private var errorMessage: String? = null
set(value) {
field = value
_uiState.update { currentState ->
currentState.copy(
errorMsg = value,
)
}
}
fun refreshAuthenticatorList() {
// TODO(b/290768873): Pull from RemoteAuthenticationManager and map to UIState
val authenticatorUiStates = listOf<RemoteAuthAuthenticatorItemUiState>()
_uiState.update { currentState ->
currentState.copy(
registeredAuthenticatorUiStates = authenticatorUiStates,
)
}
}
/** Called by UI when user has acknowledged they seen the error dialog, via ok button. */
fun resetErrorMessage() {
errorMessage = null
}
}