mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Add corrupted attachment icon #691
This commit is contained in:
@@ -20,7 +20,10 @@
|
|||||||
package com.kunzisoft.keepass.adapters
|
package com.kunzisoft.keepass.adapters
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.TypedArray
|
||||||
|
import android.graphics.Color
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
@@ -33,11 +36,24 @@ import com.kunzisoft.keepass.model.AttachmentState
|
|||||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||||
import com.kunzisoft.keepass.model.StreamDirection
|
import com.kunzisoft.keepass.model.StreamDirection
|
||||||
|
|
||||||
|
|
||||||
class EntryAttachmentsItemsAdapter(context: Context)
|
class EntryAttachmentsItemsAdapter(context: Context)
|
||||||
: AnimatedItemsAdapter<EntryAttachmentState, EntryAttachmentsItemsAdapter.EntryBinariesViewHolder>(context) {
|
: AnimatedItemsAdapter<EntryAttachmentState, EntryAttachmentsItemsAdapter.EntryBinariesViewHolder>(context) {
|
||||||
|
|
||||||
var onItemClickListener: ((item: EntryAttachmentState)->Unit)? = null
|
var onItemClickListener: ((item: EntryAttachmentState)->Unit)? = null
|
||||||
|
|
||||||
|
private var mTitleColor: Int
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Get the primary text color of the theme
|
||||||
|
val typedValue = TypedValue()
|
||||||
|
context.theme.resolveAttribute(android.R.attr.textColorPrimary, typedValue, true)
|
||||||
|
val typedArray: TypedArray = context.obtainStyledAttributes(typedValue.data, intArrayOf(
|
||||||
|
android.R.attr.textColor))
|
||||||
|
mTitleColor = typedArray.getColor(0, -1)
|
||||||
|
typedArray.recycle()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EntryBinariesViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EntryBinariesViewHolder {
|
||||||
return EntryBinariesViewHolder(inflater.inflate(R.layout.item_attachment, parent, false))
|
return EntryBinariesViewHolder(inflater.inflate(R.layout.item_attachment, parent, false))
|
||||||
}
|
}
|
||||||
@@ -46,7 +62,20 @@ class EntryAttachmentsItemsAdapter(context: Context)
|
|||||||
val entryAttachmentState = itemsList[position]
|
val entryAttachmentState = itemsList[position]
|
||||||
|
|
||||||
holder.itemView.visibility = View.VISIBLE
|
holder.itemView.visibility = View.VISIBLE
|
||||||
|
holder.binaryFileBroken.apply {
|
||||||
|
setColorFilter(Color.RED)
|
||||||
|
visibility = if (entryAttachmentState.attachment.binaryAttachment.isCorrupted) {
|
||||||
|
View.VISIBLE
|
||||||
|
} else {
|
||||||
|
View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
holder.binaryFileTitle.text = entryAttachmentState.attachment.name
|
holder.binaryFileTitle.text = entryAttachmentState.attachment.name
|
||||||
|
if (entryAttachmentState.attachment.binaryAttachment.isCorrupted) {
|
||||||
|
holder.binaryFileTitle.setTextColor(Color.RED)
|
||||||
|
} else {
|
||||||
|
holder.binaryFileTitle.setTextColor(mTitleColor)
|
||||||
|
}
|
||||||
holder.binaryFileSize.text = Formatter.formatFileSize(context,
|
holder.binaryFileSize.text = Formatter.formatFileSize(context,
|
||||||
entryAttachmentState.attachment.binaryAttachment.length())
|
entryAttachmentState.attachment.binaryAttachment.length())
|
||||||
holder.binaryFileCompression.apply {
|
holder.binaryFileCompression.apply {
|
||||||
@@ -107,6 +136,7 @@ class EntryAttachmentsItemsAdapter(context: Context)
|
|||||||
|
|
||||||
class EntryBinariesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
class EntryBinariesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
|
var binaryFileBroken: ImageView = itemView.findViewById(R.id.item_attachment_broken)
|
||||||
var binaryFileTitle: TextView = itemView.findViewById(R.id.item_attachment_title)
|
var binaryFileTitle: TextView = itemView.findViewById(R.id.item_attachment_title)
|
||||||
var binaryFileSize: TextView = itemView.findViewById(R.id.item_attachment_size)
|
var binaryFileSize: TextView = itemView.findViewById(R.id.item_attachment_size)
|
||||||
var binaryFileCompression: TextView = itemView.findViewById(R.id.item_attachment_compression)
|
var binaryFileCompression: TextView = itemView.findViewById(R.id.item_attachment_compression)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class BinaryAttachment : Parcelable {
|
|||||||
private set
|
private set
|
||||||
var isProtected: Boolean = false
|
var isProtected: Boolean = false
|
||||||
private set
|
private set
|
||||||
|
var isCorrupted: Boolean = false
|
||||||
private var dataFile: File? = null
|
private var dataFile: File? = null
|
||||||
|
|
||||||
fun length(): Long {
|
fun length(): Long {
|
||||||
@@ -43,11 +44,7 @@ class BinaryAttachment : Parcelable {
|
|||||||
/**
|
/**
|
||||||
* Empty protected binary
|
* Empty protected binary
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor()
|
||||||
this.isCompressed = false
|
|
||||||
this.isProtected = false
|
|
||||||
this.dataFile = null
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(dataFile: File, enableProtection: Boolean = false, compressed: Boolean = false) {
|
constructor(dataFile: File, enableProtection: Boolean = false, compressed: Boolean = false) {
|
||||||
this.isCompressed = compressed
|
this.isCompressed = compressed
|
||||||
@@ -59,6 +56,7 @@ class BinaryAttachment : Parcelable {
|
|||||||
val compressedByte = parcel.readByte().toInt()
|
val compressedByte = parcel.readByte().toInt()
|
||||||
isCompressed = compressedByte != 0
|
isCompressed = compressedByte != 0
|
||||||
isProtected = parcel.readByte().toInt() != 0
|
isProtected = parcel.readByte().toInt() != 0
|
||||||
|
isCorrupted = parcel.readByte().toInt() != 0
|
||||||
parcel.readString()?.let {
|
parcel.readString()?.let {
|
||||||
dataFile = File(it)
|
dataFile = File(it)
|
||||||
}
|
}
|
||||||
@@ -164,6 +162,7 @@ class BinaryAttachment : Parcelable {
|
|||||||
|
|
||||||
return isCompressed == other.isCompressed
|
return isCompressed == other.isCompressed
|
||||||
&& isProtected == other.isProtected
|
&& isProtected == other.isProtected
|
||||||
|
&& isCorrupted == other.isCorrupted
|
||||||
&& sameData
|
&& sameData
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,6 +171,7 @@ class BinaryAttachment : Parcelable {
|
|||||||
var result = 0
|
var result = 0
|
||||||
result = 31 * result + if (isCompressed) 1 else 0
|
result = 31 * result + if (isCompressed) 1 else 0
|
||||||
result = 31 * result + if (isProtected) 1 else 0
|
result = 31 * result + if (isProtected) 1 else 0
|
||||||
|
result = 31 * result + if (isCorrupted) 1 else 0
|
||||||
result = 31 * result + dataFile!!.hashCode()
|
result = 31 * result + dataFile!!.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -187,6 +187,7 @@ class BinaryAttachment : Parcelable {
|
|||||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||||
dest.writeByte((if (isCompressed) 1 else 0).toByte())
|
dest.writeByte((if (isCompressed) 1 else 0).toByte())
|
||||||
dest.writeByte((if (isProtected) 1 else 0).toByte())
|
dest.writeByte((if (isProtected) 1 else 0).toByte())
|
||||||
|
dest.writeByte((if (isCorrupted) 1 else 0).toByte())
|
||||||
dest.writeString(dataFile?.absolutePath)
|
dest.writeString(dataFile?.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -995,6 +995,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Unable to read base 64 attachment", e)
|
Log.e(TAG, "Unable to read base 64 attachment", e)
|
||||||
|
binaryAttachment.isCorrupted = true
|
||||||
binaryAttachment.getOutputDataStream().use { outputStream ->
|
binaryAttachment.getOutputDataStream().use { outputStream ->
|
||||||
outputStream.write(base64.toByteArray())
|
outputStream.write(base64.toByteArray())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M 10.191406 1 C 7.8864287 1 6 2.8866579 6 5.1914062 L 6 13.976562 L 7.5722656 13.355469 L 7.5722656 5.1914062 C 7.5722656 3.7248197 8.7248288 2.5722656 10.191406 2.5722656 C 11.657948 2.5722656 12.808594 3.7248197 12.808594 5.1914062 L 12.808594 9.2851562 L 14.380859 8.6640625 L 14.380859 5.1914062 C 14.380859 2.8866579 12.496402 1 10.191406 1 z M 15.953125 5.7148438 L 15.953125 8.0410156 L 17.523438 7.421875 L 17.523438 5.7148438 L 15.953125 5.7148438 z M 9.1425781 7.2851562 L 9.1425781 12.734375 L 10.714844 12.113281 L 10.714844 7.2851562 L 9.1425781 7.2851562 z M 17.523438 11.722656 L 15.953125 12.34375 L 15.953125 17.238281 C 15.953125 19.543273 14.066714 21.427734 11.761719 21.427734 C 9.5944825 21.427734 7.8200908 19.755748 7.6132812 17.640625 L 6.0917969 18.242188 C 6.5643368 20.953226 8.9101628 23 11.761719 23 C 14.956723 23 17.523438 20.433343 17.523438 17.238281 L 17.523438 11.722656 z M 14.380859 12.964844 L 12.808594 13.587891 L 12.808594 17.238281 C 12.808594 17.814256 12.337701 18.285156 11.761719 18.285156 C 11.185737 18.285156 10.714844 17.814256 10.714844 17.238281 L 10.714844 16.414062 L 9.1425781 17.035156 L 9.1425781 17.238281 C 9.1426137 18.704818 10.295141 19.857422 11.761719 19.857422 C 13.228314 19.857422 14.380859 18.704818 14.380859 17.238281 L 14.380859 12.964844 z" />
|
||||||
|
</vector>
|
||||||
@@ -27,11 +27,21 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/item_attachment_broken"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
android:src="@drawable/ic_attach_file_broken_white_24dp"
|
||||||
|
android:contentDescription="@string/entry_attachments" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/item_attachment_title"
|
android:id="@+id/item_attachment_title"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toEndOf="@+id/item_attachment_broken"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/item_attachment_size_container"
|
app:layout_constraintEnd_toStartOf="@+id/item_attachment_size_container"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
96
art/ic_attachment_broken.svg
Normal file
96
art/ic_attachment_broken.svg
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
id="svg4830"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
inkscape:export-filename="/home/joker/Project/Scratcheck/TestExport.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90"
|
||||||
|
sodipodi:docname="ic_attachment_broken.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4832" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#acacac"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="15.999999"
|
||||||
|
inkscape:cx="9.9882808"
|
||||||
|
inkscape:cy="7.7944656"
|
||||||
|
inkscape:current-layer="g4770"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1016"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="74"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0.99999471,22.999999"
|
||||||
|
orientation="22,0"
|
||||||
|
id="guide2987"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0.99999471,0.99999888"
|
||||||
|
orientation="0,22"
|
||||||
|
id="guide2989"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="22.999995,0.99999888"
|
||||||
|
orientation="-22,0"
|
||||||
|
id="guide2991"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="39,23"
|
||||||
|
orientation="0,-22"
|
||||||
|
id="guide2993"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2989" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata4835">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-8)">
|
||||||
|
<g
|
||||||
|
id="g4770"
|
||||||
|
transform="matrix(1.7777778,0,0,1.7777778,-205.48441,-31.997877)">
|
||||||
|
<g
|
||||||
|
id="Layer_1"
|
||||||
|
transform="matrix(-0.00397893,0,0,0.00397893,125.58386,23.674135)" />
|
||||||
|
<path
|
||||||
|
style="stroke-width:0.02762278;fill:#ffffff;fill-opacity:1"
|
||||||
|
d="m 121.54264,23.061306 c -1.29654,0 -2.35766,1.061245 -2.35766,2.357666 v 4.94165 l 0.8844,-0.349365 v -4.592285 c 0,-0.824955 0.64832,-1.473267 1.47326,-1.473267 0.82493,0 1.47217,0.648312 1.47217,1.473267 v 2.302734 l 0.8844,-0.349365 v -1.953369 c 0,-1.296421 -1.06,-2.357666 -2.35657,-2.357666 z m 3.24097,2.6521 v 1.308471 l 0.8833,-0.348266 v -0.960205 z m -3.83093,0.8833 v 3.065186 l 0.8844,-0.349366 v -2.71582 z m 4.71423,2.496094 -0.8833,0.349365 v 2.753174 c 0,1.296558 -1.0611,2.356567 -2.35766,2.356567 -1.21907,0 -2.21717,-0.940492 -2.3335,-2.130249 l -0.85584,0.33838 c 0.26581,1.524958 1.58534,2.676269 3.18934,2.676269 1.79719,0 3.24096,-1.443745 3.24096,-3.240967 z m -1.7677,0.698731 -0.8844,0.350464 v 2.053344 c 0,0.323986 -0.26487,0.588867 -0.58886,0.588867 -0.32399,0 -0.58887,-0.264881 -0.58887,-0.588867 v -0.463623 l -0.8844,0.349365 v 0.114258 c 2e-5,0.824927 0.64832,1.473267 1.47327,1.473267 0.82496,0 1.47326,-0.64834 1.47326,-1.473267 z"
|
||||||
|
id="Icon_3_"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.7 KiB |
Reference in New Issue
Block a user