Add file database history info as sub part of recyclerview element

This commit is contained in:
J-Jamet
2019-08-26 13:32:33 +02:00
parent f3ba6e800a
commit 8d6db78f55
8 changed files with 200 additions and 253 deletions

View File

@@ -33,6 +33,7 @@ import android.support.annotation.RequiresApi
import android.support.design.widget.Snackbar
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.SimpleItemAnimator
import android.support.v7.widget.Toolbar
import android.util.Log
import android.view.Menu
@@ -43,7 +44,6 @@ import android.widget.TextView
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
import com.kunzisoft.keepass.activities.dialogs.BrowserDialogFragment
import com.kunzisoft.keepass.activities.dialogs.FileInformationDialogFragment
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.OpenFileHelper
import com.kunzisoft.keepass.activities.stylish.StylishActivity
@@ -69,8 +69,7 @@ import java.io.FileNotFoundException
class FileDatabaseSelectActivity : StylishActivity(),
AssignMasterKeyDialogFragment.AssignPasswordDialogListener,
FileDatabaseHistoryAdapter.FileItemOpenListener,
FileDatabaseHistoryAdapter.FileSelectClearListener,
FileDatabaseHistoryAdapter.FileInformationShowListener {
FileDatabaseHistoryAdapter.FileSelectClearListener {
// Views
private var fileListContainer: View? = null
@@ -123,10 +122,6 @@ class FileDatabaseSelectActivity : StylishActivity(),
fileSelectExpandableLayout?.expand()
}
// History list
val databaseFileListView = findViewById<RecyclerView>(R.id.file_list)
databaseFileListView.layoutManager = LinearLayoutManager(this)
// Open button
openButtonView = findViewById(R.id.open_database)
openButtonView?.setOnClickListener { _ ->
@@ -160,12 +155,17 @@ class FileDatabaseSelectActivity : StylishActivity(),
Uri.parse("file://" + openFileNameView!!.text.toString())
})
// History list
val fileDatabaseHistoryRecyclerView = findViewById<RecyclerView>(R.id.file_list)
fileDatabaseHistoryRecyclerView.layoutManager = LinearLayoutManager(this)
// Removes blinks
(fileDatabaseHistoryRecyclerView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
// Construct adapter with listeners
mAdapterDatabaseHistory = FileDatabaseHistoryAdapter(this@FileDatabaseSelectActivity)
mAdapterDatabaseHistory = FileDatabaseHistoryAdapter(this)
mAdapterDatabaseHistory?.setOnItemClickListener(this)
mAdapterDatabaseHistory?.setFileSelectClearListener(this)
mAdapterDatabaseHistory?.setFileInformationShowListener(this)
databaseFileListView.adapter = mAdapterDatabaseHistory
fileDatabaseHistoryRecyclerView.adapter = mAdapterDatabaseHistory
// Load default database if not an orientation change
if (!(savedInstanceState != null
@@ -401,10 +401,6 @@ class FileDatabaseSelectActivity : StylishActivity(),
updateFileListVisibility()
}
override fun onClickFileInformation(fileInfo: FileInfo) {
FileInformationDialogFragment.newInstance(fileInfo).show(supportFragmentManager, "fileInformation")
}
override fun onFileSelectClearListener(fileInfo: FileInfo): Boolean {
fileInfo.fileUri?.let {

View File

@@ -1,99 +0,0 @@
/*
* Copyright 2019 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePass DX.
*
* KeePass DX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePass DX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.activities.dialogs
import android.app.Dialog
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.support.v7.app.AlertDialog
import android.view.View
import android.widget.TextView
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.adapters.FileInfo
import java.text.DateFormat
class FileInformationDialogFragment : DialogFragment() {
private var fileSizeContainerView: View? = null
private var fileModificationContainerView: View? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
activity?.let { activity ->
val builder = AlertDialog.Builder(activity)
val inflater = activity.layoutInflater
val root = inflater.inflate(R.layout.fragment_file_selection_information, null)
val fileNameView = root.findViewById<TextView>(R.id.file_filename)
val filePathView = root.findViewById<TextView>(R.id.file_path)
fileSizeContainerView = root.findViewById(R.id.file_size_container)
val fileSizeView = root.findViewById<TextView>(R.id.file_size)
fileModificationContainerView = root.findViewById(R.id.file_modification_container)
val fileModificationView = root.findViewById<TextView>(R.id.file_modification)
arguments?.apply {
if (containsKey(FILE_SELECT_BEEN_ARG)) {
(getSerializable(FILE_SELECT_BEEN_ARG) as FileInfo?)?.let { fileDatabaseModel ->
fileDatabaseModel.fileUri?.let { fileUri ->
filePathView.text = Uri.decode(fileUri.toString())
}
fileNameView.text = fileDatabaseModel.fileName
if (fileDatabaseModel.notFound()) {
hideFileInfo()
} else {
showFileInfo()
fileSizeView.text = fileDatabaseModel.size.toString()
fileModificationView.text = DateFormat.getDateTimeInstance()
.format(fileDatabaseModel.lastModification)
}
} ?: hideFileInfo()
}
}
builder.setView(root)
builder.setPositiveButton(android.R.string.ok) { _, _ -> }
return builder.create()
}
return super.onCreateDialog(savedInstanceState)
}
private fun showFileInfo() {
fileSizeContainerView?.visibility = View.VISIBLE
fileModificationContainerView?.visibility = View.VISIBLE
}
private fun hideFileInfo() {
fileSizeContainerView?.visibility = View.GONE
fileModificationContainerView?.visibility = View.GONE
}
companion object {
private const val FILE_SELECT_BEEN_ARG = "FILE_SELECT_BEEN_ARG"
fun newInstance(fileInfo: FileInfo): FileInformationDialogFragment {
val fileInformationDialogFragment = FileInformationDialogFragment()
val args = Bundle()
args.putSerializable(FILE_SELECT_BEEN_ARG, fileInfo)
fileInformationDialogFragment.arguments = args
return fileInformationDialogFragment
}
}
}

View File

@@ -37,10 +37,12 @@ class FileDatabaseHistoryAdapter(private val context: Context)
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var fileItemOpenListener: FileItemOpenListener? = null
private var fileSelectClearListener: FileSelectClearListener? = null
private var fileInformationShowListener: FileInformationShowListener? = null
private val listDatabaseFiles = ArrayList<FileDatabaseHistoryEntity>()
private var mExpandedPosition = -1
private var mPreviousExpandedPosition = -1
@ColorInt
private val defaultColor: Int
@ColorInt
@@ -65,20 +67,47 @@ class FileDatabaseHistoryAdapter(private val context: Context)
val fileHistoryEntity = listDatabaseFiles[position]
val fileDatabaseInfo = FileInfo(context, fileHistoryEntity.databaseUri)
// Context menu creation
holder.fileContainer.setOnCreateContextMenuListener(ContextMenuBuilder(fileDatabaseInfo))
// Click item to open file
if (fileItemOpenListener != null)
holder.fileContainer.setOnClickListener(FileItemClickListener(fileHistoryEntity))
// Assign file name
if (PreferencesUtil.isFullFilePathEnable(context))
holder.fileName.text = Uri.decode(fileDatabaseInfo.fileUri.toString())
else
holder.fileName.text = fileDatabaseInfo.fileName
holder.fileName.textSize = PreferencesUtil.getListTextSize(context)
// File alias
val aliasText = fileHistoryEntity.databaseAlias
holder.fileAlias.text = when {
aliasText.isNotEmpty() -> aliasText
PreferencesUtil.isFullFilePathEnable(context) -> Uri.decode(fileDatabaseInfo.fileUri.toString())
else -> fileDatabaseInfo.fileName
}
// File path
holder.filePath.text = Uri.decode(fileDatabaseInfo.fileUri.toString())
holder.filePath.textSize = PreferencesUtil.getListTextSize(context)
holder.filePreciseInfoContainer.visibility = if (fileDatabaseInfo.found()) {
// Modification
holder.fileModification.text = fileDatabaseInfo.getModificationString()
// Size
holder.fileSize.text = fileDatabaseInfo.getSizeString()
View.VISIBLE
} else
View.GONE
// Click on information
if (fileInformationShowListener != null)
holder.fileInformation.setOnClickListener(FileInformationClickListener(fileDatabaseInfo))
val isExpanded = position == mExpandedPosition
//This line hides or shows the layout in question
holder.fileExpandContainer.visibility = if (isExpanded) View.VISIBLE else View.GONE
if (isExpanded)
mPreviousExpandedPosition = position
holder.fileInformation.setOnClickListener {
mExpandedPosition = if (isExpanded) -1 else position
notifyItemChanged(mPreviousExpandedPosition)
notifyItemChanged(position)
}
}
override fun getItemCount(): Int {
@@ -102,10 +131,6 @@ class FileDatabaseHistoryAdapter(private val context: Context)
this.fileSelectClearListener = fileSelectClearListener
}
fun setFileInformationShowListener(fileInformationShowListener: FileInformationShowListener) {
this.fileInformationShowListener = fileInformationShowListener
}
interface FileItemOpenListener {
fun onFileItemOpenListener(fileDatabaseHistoryEntity: FileDatabaseHistoryEntity)
}
@@ -114,10 +139,6 @@ class FileDatabaseHistoryAdapter(private val context: Context)
fun onFileSelectClearListener(fileInfo: FileInfo): Boolean
}
interface FileInformationShowListener {
fun onClickFileInformation(fileInfo: FileInfo)
}
private inner class FileItemClickListener(private val fileDatabaseHistoryEntity: FileDatabaseHistoryEntity) : View.OnClickListener {
override fun onClick(v: View) {
@@ -125,13 +146,6 @@ class FileDatabaseHistoryAdapter(private val context: Context)
}
}
private inner class FileInformationClickListener(private val fileInfo: FileInfo) : View.OnClickListener {
override fun onClick(view: View) {
fileInformationShowListener?.onClickFileInformation(fileInfo)
}
}
private inner class ContextMenuBuilder(private val fileInfo: FileInfo) : View.OnCreateContextMenuListener {
private val mOnMyActionClickListener = MenuItem.OnMenuItemClickListener { item ->
@@ -151,9 +165,16 @@ class FileDatabaseHistoryAdapter(private val context: Context)
inner class FileDatabaseHistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var fileContainer: View = itemView.findViewById(R.id.file_container)
var fileName: TextView = itemView.findViewById(R.id.file_filename)
var fileContainer: ViewGroup = itemView.findViewById(R.id.file_main_container)
var fileAlias: TextView = itemView.findViewById(R.id.file_alias)
var fileInformation: ImageView = itemView.findViewById(R.id.file_information)
var fileExpandContainer: ViewGroup = itemView.findViewById(R.id.file_expand_container)
var filePath: TextView = itemView.findViewById(R.id.file_path)
var filePreciseInfoContainer: ViewGroup = itemView.findViewById(R.id.file_precise_info_container)
var fileModification: TextView = itemView.findViewById(R.id.file_modification)
var fileSize: TextView = itemView.findViewById(R.id.file_size)
}
companion object {

View File

@@ -22,12 +22,14 @@ package com.kunzisoft.keepass.adapters
import android.content.Context
import android.net.Uri
import android.support.v4.provider.DocumentFile
import com.kunzisoft.keepass.R
import java.io.File
import java.io.Serializable
import java.text.DateFormat
import java.util.Date
class FileInfo(context: Context, pathFile: String) : Serializable {
class FileInfo(private val context: Context, pathFile: String) : Serializable {
var fileName: String? = ""
var fileUri: Uri? = null
@@ -53,8 +55,17 @@ class FileInfo(context: Context, pathFile: String) : Serializable {
}
}
fun notFound(): Boolean {
return size == 0L
fun found(): Boolean {
return size != 0L
}
fun getModificationString(): String {
return DateFormat.getDateTimeInstance()
.format(lastModification)
}
fun getSizeString(): String {
return (size.toString() + " " + context.getString(R.string.bytes))
}
companion object {

View File

@@ -125,39 +125,37 @@
app:layout_constraintTop_toBottomOf="@+id/file_selection_title_container"
android:visibility="gone" />
<android.support.v7.widget.CardView
<LinearLayout
android:id="@+id/container_file_list"
android:layout_height="wrap_content"
android:layout_width="0dp"
style="@style/KeepassDXStyle.CardView.PrimaryColor"
android:layout_margin="12dp"
android:padding="8dp"
android:elevation="12dp"
android:background="@color/transparent"
app:layout_constraintWidth_percent="@dimen/content_percent"
app:layout_constraintTop_toBottomOf="@+id/label_warning"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
android:orientation="vertical">
<TextView android:id="@+id/file_list_title"
<TextView
android:id="@+id/file_list_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
style="@style/KeepassDXStyle.TextAppearance.Title"
android:background="?attr/colorPrimary"
android:textColor="?android:attr/textColorHintInverse"
android:text="@string/open_recent"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/textColorHintInverse"/>
android:background="?attr/colorPrimaryDark"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/file_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>

View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.constraint.ConstraintLayout
android:id="@+id/container_create_document"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin"
android:importantForAutofill="noExcludeDescendants"
android:background="@drawable/background_stroke_element"
tools:targetApi="o">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/create_document_path"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:minHeight="48dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/browse_button"
android:paddingStart="@dimen/default_margin"
android:paddingEnd="@dimen/default_margin"
android:gravity="center"
android:hint="@string/path"
android:maxLines="1"
android:singleLine="true"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/browse_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:contentDescription="@string/content_description_open_file"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:drawableRight="@drawable/ic_folder_white_24dp" />
</android.support.constraint.ConstraintLayout>
</FrameLayout>

View File

@@ -17,41 +17,114 @@
You should have received a copy of the GNU General Public License
along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/file_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="?attr/colorPrimary"
tools:targetApi="lollipop">
<android.support.constraint.ConstraintLayout
android:id="@+id/file_main_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingStart="12dp"
android:background="?android:attr/selectableItemBackground">
android:background="?android:attr/selectableItemBackground"
app:layout_constraintTop_toTopOf="parent"
android:elevation="8dp">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/file_filename"
android:layout_width="wrap_content"
android:id="@+id/file_alias"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:minHeight="48dp"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/file_information"
android:layout_toStartOf="@+id/file_information"
android:gravity="center_vertical"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/file_information"
android:textColor="?attr/textColorInverse"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingStart="12dp" />
tools:text="DatabaseAlias" />
<android.support.v7.widget.AppCompatImageView
android:id="@+id/file_information"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:layout_centerVertical="true"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/file_alias"
app:layout_constraintEnd_toEndOf="parent"
android:src="@drawable/ic_info_white_24dp"
android:contentDescription="@string/content_description_file_information"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:tint="?android:attr/textColorHintInverse"/>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
<LinearLayout
android:id="@+id/file_expand_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimaryDark"
app:layout_constraintTop_toBottomOf="@+id/file_main_container"
android:padding="8dp">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/file_path"
android:textIsSelectable="true"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:text="/path/to/DatabaseName.kdbx"
android:textColor="?android:attr/textColorHintInverse"
android:gravity="end"
android:textStyle="italic"/>
<android.support.constraint.ConstraintLayout
android:id="@+id/file_precise_info_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/file_modification"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
tools:text="25 Augst"
android:textColor="?android:attr/textColorHintInverse"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/file_size"
android:layout_margin="8dp"
android:gravity="start"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/file_size"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
tools:text="8 bytes"
android:textColor="?android:attr/textColorHintInverse"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/file_modification"
app:layout_constraintEnd_toEndOf="parent"
android:layout_margin="8dp"
android:gravity="end"/>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -213,11 +213,6 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<!-- CardView -->
<style name="KeepassDXStyle.CardView.PrimaryColor" parent="CardView">
<item name="cardBackgroundColor">?attr/colorPrimary</item>
</style>
<!-- CheckBox -->
<style name="KeepassDXStyle.CheckBox" parent="Widget.AppCompat.CompoundButton.CheckBox">
<item name="android:textColor">?android:attr/textColor</item>