diff options
| author | Harsh Shandilya <msfjarvis@gmail.com> | 2019-11-04 19:18:49 +0530 |
|---|---|---|
| committer | Harsh Shandilya <msfjarvis@gmail.com> | 2019-11-04 19:50:48 +0530 |
| commit | 8fc7dd3d4296735575ba6890bac23db9fc5b5965 (patch) | |
| tree | 9979eee9e3e665e09a98d6b9829ba11833904131 /app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt | |
| parent | 14d997f50078af890c7cf0359ec7c94f5194cb7f (diff) | |
| download | HardenedPass-8fc7dd3d4296735575ba6890bac23db9fc5b5965.tar.gz HardenedPass-8fc7dd3d4296735575ba6890bac23db9fc5b5965.zip | |
Rewrite PasswordFragment in Kotlin
Signed-off-by: Harsh Shandilya <msfjarvis@gmail.com>
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt')
| -rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt new file mode 100644 index 00000000..d41d9286 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt @@ -0,0 +1,206 @@ +/* + * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore + +import android.content.Context +import android.content.SharedPreferences +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.preference.PreferenceManager +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.floatingactionbutton.FloatingActionButton +import com.zeapo.pwdstore.ui.adapters.PasswordRecyclerAdapter +import com.zeapo.pwdstore.utils.PasswordItem +import com.zeapo.pwdstore.utils.PasswordRepository +import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getPasswords +import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory +import com.zeapo.pwdstore.utils.PasswordRepository.PasswordSortOrder.Companion.getSortOrder +import java.io.File +import java.util.Locale +import java.util.Stack + +/** + * A fragment representing a list of Items. + * + * + * Large screen devices (such as tablets) are supported by replacing the ListView with a + * GridView. + * + * + * + */ +class PasswordFragment +/** + * Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon + * screen orientation changes). + */ + : Fragment() { + // store the pass files list in a stack + private var passListStack: Stack<ArrayList<PasswordItem>> = Stack() + private var pathStack: Stack<File> = Stack() + private var scrollPosition: Stack<Int> = Stack() + private lateinit var recyclerAdapter: PasswordRecyclerAdapter + private lateinit var recyclerView: RecyclerView + private lateinit var listener: OnFragmentInteractionListener + private lateinit var settings: SharedPreferences + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val path = requireNotNull(requireArguments().getString("Path")) + settings = PreferenceManager.getDefaultSharedPreferences(requireActivity()) + recyclerAdapter = PasswordRecyclerAdapter((requireActivity() as PasswordStore), + listener, getPasswords(File(path), getRepositoryDirectory(requireContext()), sortOrder)) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.password_recycler_view, container, false) + // use a linear layout manager + val layoutManager = LinearLayoutManager(requireContext()) + recyclerView = view.findViewById(R.id.pass_recycler) + recyclerView.layoutManager = layoutManager + // use divider + recyclerView.addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)) + // Set the adapter + recyclerView.adapter = recyclerAdapter + val fab: FloatingActionButton = view.findViewById(R.id.fab) + fab.setOnClickListener { (requireActivity() as PasswordStore).createPassword() } + registerForContextMenu(recyclerView) + return view + } + + override fun onAttach(context: Context) { + super.onAttach(context) + try { + listener = object : OnFragmentInteractionListener { + override fun onFragmentInteraction(item: PasswordItem) { + if (item.type == PasswordItem.TYPE_CATEGORY) { // push the current password list (non filtered plz!) + passListStack.push( + if (pathStack.isEmpty()) + getPasswords(getRepositoryDirectory(context), sortOrder) + else + getPasswords(pathStack.peek(), getRepositoryDirectory(context), sortOrder) + ) + // push the category were we're going + pathStack.push(item.file) + scrollPosition.push(recyclerView.verticalScrollbarPosition) + recyclerView.scrollToPosition(0) + recyclerAdapter.clear() + recyclerAdapter.addAll(getPasswords(item.file, getRepositoryDirectory(context), sortOrder)) + (requireActivity() as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) + } else { + if (requireArguments().getBoolean("matchWith", false)) { + (requireActivity() as PasswordStore).matchPasswordWithApp(item) + } else { + (requireActivity() as PasswordStore).decryptPassword(item) + } + } + } + } + } catch (e: ClassCastException) { + throw ClassCastException("$context must implement OnFragmentInteractionListener") + } + } + + /** clears the adapter content and sets it back to the root view */ + fun updateAdapter() { + passListStack.clear() + pathStack.clear() + scrollPosition.clear() + recyclerAdapter.clear() + recyclerAdapter.addAll(getPasswords(getRepositoryDirectory(requireContext()), sortOrder)) + (requireActivity() as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(false) + } + + /** refreshes the adapter with the latest opened category */ + fun refreshAdapter() { + recyclerAdapter.clear() + recyclerAdapter.addAll( + if (pathStack.isEmpty()) + getPasswords(getRepositoryDirectory(requireContext()), sortOrder) + else + getPasswords(pathStack.peek(), getRepositoryDirectory(requireContext()), sortOrder) + ) + } + + /** + * filters the list adapter + * + * @param filter the filter to apply + */ + fun filterAdapter(filter: String) { + if (filter.isEmpty()) { + refreshAdapter() + } else { + recursiveFilter(filter, if (pathStack.isEmpty()) null else pathStack.peek()) + } + } + + /** + * recursively filters a directory and extract all the matching items + * + * @param filter the filter to apply + * @param dir the directory to filter + */ + private fun recursiveFilter(filter: String, dir: File?) { // on the root the pathStack is empty + val passwordItems = if (dir == null) + getPasswords(getRepositoryDirectory(requireContext()), sortOrder) + else + getPasswords(dir, getRepositoryDirectory(requireContext()), sortOrder) + val rec = settings.getBoolean("filter_recursively", true) + for (item in passwordItems) { + if (item.type == PasswordItem.TYPE_CATEGORY && rec) { + recursiveFilter(filter, item.file) + } + val matches = item.toString().toLowerCase(Locale.ROOT).contains(filter.toLowerCase(Locale.ROOT)) + val inAdapter = recyclerAdapter.values.contains(item) + if (matches && !inAdapter) { + recyclerAdapter.add(item) + } else if (!matches && inAdapter) { + recyclerAdapter.remove(recyclerAdapter.values.indexOf(item)) + } + } + } + + /** Goes back one level back in the path */ + fun popBack() { + if (passListStack.isEmpty()) return + recyclerView.scrollToPosition(scrollPosition.pop()) + recyclerAdapter.clear() + recyclerAdapter.addAll(passListStack.pop()) + pathStack.pop() + } + + /** + * gets the current directory + * + * @return the current directory + */ + val currentDir: File? + get() = if (pathStack.isEmpty()) getRepositoryDirectory(requireContext()) else pathStack.peek() + + val isNotEmpty: Boolean + get() = !passListStack.isEmpty() + + fun dismissActionMode() { + recyclerAdapter.actionMode?.finish() + } + + private val sortOrder: PasswordRepository.PasswordSortOrder + get() = getSortOrder(settings) + + interface OnFragmentInteractionListener { + fun onFragmentInteraction(item: PasswordItem) + } +} |
