Switch refactored entities to ViewBinding (#695)

* build: Enable ViewBinding

* autofill: oreo: Switch to ViewBinding

* PasswordFragment: switch to ViewBinding

* AutofillPublisherChangedActivity: use with(binding) { } syntax

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2020-04-11 01:07:49 +05:30 committed by GitHub
parent 575ef84726
commit f21b6426af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 49 deletions

View file

@ -31,6 +31,8 @@ android {
} }
} }
viewBinding.enabled = true
defaultConfig { defaultConfig {
applicationId versions.packageName applicationId versions.packageName
} }

View file

@ -22,6 +22,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.zeapo.pwdstore.databinding.PasswordRecyclerViewBinding
import com.zeapo.pwdstore.git.GitActivity import com.zeapo.pwdstore.git.GitActivity
import com.zeapo.pwdstore.ui.OnOffItemAnimator import com.zeapo.pwdstore.ui.OnOffItemAnimator
import com.zeapo.pwdstore.ui.adapters.PasswordItemRecyclerAdapter import com.zeapo.pwdstore.ui.adapters.PasswordItemRecyclerAdapter
@ -39,8 +40,10 @@ class PasswordFragment : Fragment() {
private var recyclerViewStateToRestore: Parcelable? = null private var recyclerViewStateToRestore: Parcelable? = null
private var actionMode: ActionMode? = null private var actionMode: ActionMode? = null
private var _binding: PasswordRecyclerViewBinding? = null
private val model: SearchableRepositoryViewModel by activityViewModels() private val model: SearchableRepositoryViewModel by activityViewModels()
private val binding get() = _binding!!
private fun requireStore() = requireActivity() as PasswordStore private fun requireStore() = requireActivity() as PasswordStore
@ -49,28 +52,28 @@ class PasswordFragment : Fragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
val view = inflater.inflate(R.layout.password_recycler_view, container, false) _binding = PasswordRecyclerViewBinding.inflate(inflater, container, false)
initializePasswordList(view) initializePasswordList()
val fab = view.findViewById<FloatingActionButton>(R.id.fab) val fab = binding.fab
fab.setOnClickListener { fab.setOnClickListener {
toggleFabExpand(fab) toggleFabExpand(fab)
} }
view.findViewById<FloatingActionButton>(R.id.create_folder).setOnClickListener { binding.createFolder.setOnClickListener {
requireStore().createFolder() requireStore().createFolder()
toggleFabExpand(fab) toggleFabExpand(fab)
} }
view.findViewById<FloatingActionButton>(R.id.create_password).setOnClickListener { binding.createPassword.setOnClickListener {
requireStore().createPassword() requireStore().createPassword()
toggleFabExpand(fab) toggleFabExpand(fab)
} }
return view return binding.root
} }
private fun initializePasswordList(rootView: View) { private fun initializePasswordList() {
swipeRefresher = rootView.findViewById(R.id.swipe_refresher) swipeRefresher = binding.swipeRefresher
swipeRefresher.setOnRefreshListener { swipeRefresher.setOnRefreshListener {
if (!PasswordRepository.isGitRepo()) { if (!PasswordRepository.isGitRepo()) {
Snackbar.make(rootView, getString(R.string.clone_git_repo), Snackbar.LENGTH_SHORT) Snackbar.make(binding.root, getString(R.string.clone_git_repo), Snackbar.LENGTH_SHORT)
.show() .show()
swipeRefresher.isRefreshing = false swipeRefresher.isRefreshing = false
} else { } else {
@ -100,7 +103,7 @@ class PasswordFragment : Fragment() {
actionMode!!.finish() actionMode!!.finish()
} }
} }
recyclerView = rootView.findViewById(R.id.pass_recycler) recyclerView = binding.passRecycler
recyclerView.apply { recyclerView.apply {
layoutManager = LinearLayoutManager(requireContext()) layoutManager = LinearLayoutManager(requireContext())
itemAnimator = OnOffItemAnimator() itemAnimator = OnOffItemAnimator()
@ -129,6 +132,11 @@ class PasswordFragment : Fragment() {
} }
} }
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
private fun toggleFabExpand(fab: FloatingActionButton) = with(fab) { private fun toggleFabExpand(fab: FloatingActionButton) = with(fab) {
isExpanded = !isExpanded isExpanded = !isExpanded
isActivated = isExpanded isActivated = isExpanded
@ -142,7 +150,7 @@ class PasswordFragment : Fragment() {
// Inflate a menu resource providing context menu items // Inflate a menu resource providing context menu items
mode.menuInflater.inflate(R.menu.context_pass, menu) mode.menuInflater.inflate(R.menu.context_pass, menu)
// hide the fab // hide the fab
requireActivity().findViewById<View>(R.id.fab).visibility = View.GONE binding.fab.visibility = View.GONE
return true return true
} }
@ -188,7 +196,7 @@ class PasswordFragment : Fragment() {
recyclerAdapter.requireSelectionTracker().clearSelection() recyclerAdapter.requireSelectionTracker().clearSelection()
actionMode = null actionMode = null
// show the fab // show the fab
requireActivity().findViewById<View>(R.id.fab).visibility = View.VISIBLE binding.fab.visibility = View.VISIBLE
} }
} }

View file

@ -33,8 +33,8 @@ import com.zeapo.pwdstore.autofill.oreo.AutofillMatcher
import com.zeapo.pwdstore.autofill.oreo.AutofillPreferences import com.zeapo.pwdstore.autofill.oreo.AutofillPreferences
import com.zeapo.pwdstore.autofill.oreo.DirectoryStructure import com.zeapo.pwdstore.autofill.oreo.DirectoryStructure
import com.zeapo.pwdstore.autofill.oreo.FormOrigin import com.zeapo.pwdstore.autofill.oreo.FormOrigin
import com.zeapo.pwdstore.databinding.ActivityOreoAutofillFilterBinding
import com.zeapo.pwdstore.utils.PasswordItem import com.zeapo.pwdstore.utils.PasswordItem
import kotlinx.android.synthetic.main.activity_oreo_autofill_filter.*
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
class AutofillFilterView : AppCompatActivity() { class AutofillFilterView : AppCompatActivity() {
@ -71,6 +71,7 @@ class AutofillFilterView : AppCompatActivity() {
private lateinit var formOrigin: FormOrigin private lateinit var formOrigin: FormOrigin
private lateinit var directoryStructure: DirectoryStructure private lateinit var directoryStructure: DirectoryStructure
private lateinit var binding: ActivityOreoAutofillFilterBinding
private val model: SearchableRepositoryViewModel by viewModels { private val model: SearchableRepositoryViewModel by viewModels {
ViewModelProvider.AndroidViewModelFactory(application) ViewModelProvider.AndroidViewModelFactory(application)
@ -78,7 +79,8 @@ class AutofillFilterView : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_oreo_autofill_filter) binding = ActivityOreoAutofillFilterBinding.inflate(layoutInflater)
setContentView(binding.root)
setFinishOnTouchOutside(true) setFinishOnTouchOutside(true)
val params = window.attributes val params = window.attributes
@ -127,13 +129,13 @@ class AutofillFilterView : AppCompatActivity() {
}.onItemClicked { _, item -> }.onItemClicked { _, item ->
decryptAndFill(item) decryptAndFill(item)
} }
rvPassword.apply { binding.rvPassword.apply {
adapter = recyclerAdapter adapter = recyclerAdapter
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)
} }
val initialFilter = formOrigin.getPrettyIdentifier(applicationContext, untrusted = false) val initialFilter = formOrigin.getPrettyIdentifier(applicationContext, untrusted = false)
search.setText(initialFilter, TextView.BufferType.EDITABLE) binding.search.setText(initialFilter, TextView.BufferType.EDITABLE)
val filterMode = val filterMode =
if (formOrigin is FormOrigin.Web) FilterMode.StrictDomain else FilterMode.Fuzzy if (formOrigin is FormOrigin.Web) FilterMode.StrictDomain else FilterMode.Fuzzy
model.search( model.search(
@ -142,7 +144,7 @@ class AutofillFilterView : AppCompatActivity() {
searchMode = SearchMode.RecursivelyInSubdirectories, searchMode = SearchMode.RecursivelyInSubdirectories,
listMode = ListMode.FilesOnly listMode = ListMode.FilesOnly
) )
search.addTextChangedListener { binding.search.addTextChangedListener {
model.search( model.search(
it.toString().trim(), it.toString().trim(),
filterMode = FilterMode.Fuzzy, filterMode = FilterMode.Fuzzy,
@ -155,21 +157,21 @@ class AutofillFilterView : AppCompatActivity() {
recyclerAdapter.submitList(list) recyclerAdapter.submitList(list)
// Switch RecyclerView out for a "no results" message if the new list is empty and // Switch RecyclerView out for a "no results" message if the new list is empty and
// the message is not yet shown (and vice versa). // the message is not yet shown (and vice versa).
if ((list.isEmpty() && rvPasswordSwitcher.nextView.id == rvPasswordEmpty.id) || if ((list.isEmpty() && binding.rvPasswordSwitcher.nextView.id == binding.rvPasswordEmpty.id) ||
(list.isNotEmpty() && rvPasswordSwitcher.nextView.id == rvPassword.id) (list.isNotEmpty() && binding.rvPasswordSwitcher.nextView.id == binding.rvPassword.id)
) )
rvPasswordSwitcher.showNext() binding.rvPasswordSwitcher.showNext()
} }
shouldMatch.text = getString( binding.shouldMatch.text = getString(
R.string.oreo_autofill_match_with, R.string.oreo_autofill_match_with,
formOrigin.getPrettyIdentifier(applicationContext) formOrigin.getPrettyIdentifier(applicationContext)
) )
} }
private fun decryptAndFill(item: PasswordItem) { private fun decryptAndFill(item: PasswordItem) {
if (shouldClear.isChecked) AutofillMatcher.clearMatchesFor(applicationContext, formOrigin) if (binding.shouldClear.isChecked) AutofillMatcher.clearMatchesFor(applicationContext, formOrigin)
if (shouldMatch.isChecked) AutofillMatcher.addMatchFor( if (binding.shouldMatch.isChecked) AutofillMatcher.addMatchFor(
applicationContext, applicationContext,
formOrigin, formOrigin,
item.file item.file

View file

@ -21,7 +21,7 @@ import com.zeapo.pwdstore.autofill.oreo.AutofillMatcher
import com.zeapo.pwdstore.autofill.oreo.AutofillPublisherChangedException import com.zeapo.pwdstore.autofill.oreo.AutofillPublisherChangedException
import com.zeapo.pwdstore.autofill.oreo.FormOrigin import com.zeapo.pwdstore.autofill.oreo.FormOrigin
import com.zeapo.pwdstore.autofill.oreo.computeCertificatesHash import com.zeapo.pwdstore.autofill.oreo.computeCertificatesHash
import kotlinx.android.synthetic.main.activity_oreo_autofill_publisher_changed.* import com.zeapo.pwdstore.databinding.ActivityOreoAutofillPublisherChangedBinding
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
class AutofillPublisherChangedActivity : AppCompatActivity() { class AutofillPublisherChangedActivity : AppCompatActivity() {
@ -45,10 +45,12 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
} }
private lateinit var appPackage: String private lateinit var appPackage: String
private lateinit var binding: ActivityOreoAutofillPublisherChangedBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_oreo_autofill_publisher_changed) binding = ActivityOreoAutofillPublisherChangedBinding.inflate(layoutInflater)
setContentView(binding.root)
setFinishOnTouchOutside(true) setFinishOnTouchOutside(true)
appPackage = intent.getStringExtra(EXTRA_APP_PACKAGE) ?: run { appPackage = intent.getStringExtra(EXTRA_APP_PACKAGE) ?: run {
@ -58,7 +60,7 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
} }
supportActionBar?.hide() supportActionBar?.hide()
showPackageInfo() showPackageInfo()
with(binding) {
okButton.setOnClickListener { finish() } okButton.setOnClickListener { finish() }
advancedButton.setOnClickListener { advancedButton.setOnClickListener {
advancedButton.visibility = View.INVISIBLE advancedButton.visibility = View.INVISIBLE
@ -66,13 +68,15 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
resetButton.visibility = View.VISIBLE resetButton.visibility = View.VISIBLE
} }
resetButton.setOnClickListener { resetButton.setOnClickListener {
AutofillMatcher.clearMatchesFor(this, FormOrigin.App(appPackage)) AutofillMatcher.clearMatchesFor(this@AutofillPublisherChangedActivity, FormOrigin.App(appPackage))
finish() finish()
} }
} }
}
private fun showPackageInfo() { private fun showPackageInfo() {
try { try {
with(binding) {
val packageInfo = val packageInfo =
packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA) packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA)
val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime) val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime)
@ -82,12 +86,13 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA) packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA)
warningAppName.text = "${packageManager.getApplicationLabel(appInfo)}" warningAppName.text = "${packageManager.getApplicationLabel(appInfo)}"
val currentHash = computeCertificatesHash(this, appPackage) val currentHash = computeCertificatesHash(this@AutofillPublisherChangedActivity, appPackage)
warningAppAdvancedInfo.text = getString( warningAppAdvancedInfo.text = getString(
R.string.oreo_autofill_warning_publisher_advanced_info_template, R.string.oreo_autofill_warning_publisher_advanced_info_template,
appPackage, appPackage,
currentHash currentHash
) )
}
} catch (exception: Exception) { } catch (exception: Exception) {
e(exception) { "Failed to retrieve package info for $appPackage" } e(exception) { "Failed to retrieve package info for $appPackage" }
finish() finish()