Add content type in history rows

And use some of the parsed content for the content text view.
This commit is contained in:
Markus Fisch
2026-06-05 18:20:07 +02:00
parent f90aaac4f9
commit d11dac7f13
4 changed files with 83 additions and 14 deletions
@@ -13,6 +13,7 @@ import android.widget.Spinner
import android.widget.TextView
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.content.ParsedContentType
import de.markusfisch.android.binaryeye.content.getContentPreview
import de.markusfisch.android.binaryeye.content.parsedContentTypeFromName
import de.markusfisch.android.binaryeye.database.Database
import java.text.DateFormat
@@ -31,6 +32,7 @@ class ScansAdapter(
private val timeIndex = cursor.getColumnIndex(Database.SCANS_DATETIME)
private val nameIndex = cursor.getColumnIndex(Database.SCANS_NAME)
private val textIndex = cursor.getColumnIndex(Database.SCANS_TEXT)
private val rawIndex = cursor.getColumnIndex(Database.SCANS_RAW)
private val contentTypeIndex = cursor.getColumnIndex(Database.SCANS_CONTENT_TYPE)
private val formatIndex = cursor.getColumnIndex(Database.SCANS_FORMAT)
private val selections = mutableMapOf<Long, Int>()
@@ -99,15 +101,19 @@ class ScansAdapter(
val id = cursor.getLong(idIndex)
val pinned = cursor.getInt(pinnedIndex) != 0
val format = cursor.getString(formatIndex)
val contentType = parsedContentTypeFromName(
cursor.getString(contentTypeIndex)
)
getViewHolder(view).apply {
metaView.text = context.getString(
R.string.scan_meta_data,
formatDateTime(cursor.getString(timeIndex)),
format.prettifyFormatName()
metaView.text = formatDateTime(cursor.getString(timeIndex))
formatView.text = format.prettifyFormatName().withContentType(
context,
contentType
)
formatIconView.setImageResource(format.toBarcodeIcon())
val name = cursor.getString(nameIndex)
val text = cursor.getString(textIndex)
val raw = cursor.getBlob(rawIndex)
var icon = 0
contentView.text = when {
name?.isNotEmpty() == true -> {
@@ -115,8 +121,11 @@ class ScansAdapter(
name
}
text.isNullOrEmpty() -> context.getString(
cursor.getString(contentTypeIndex).toBinaryDataStringResId()
text.isNullOrEmpty() -> getContentPreview(
context,
text ?: "",
raw ?: ByteArray(0),
format
)
else -> text
@@ -161,6 +170,7 @@ class ScansAdapter(
): ViewHolder = view.tag as ViewHolder? ?: ViewHolder(
view.findViewById(R.id.format_icon),
view.findViewById(R.id.meta),
view.findViewById(R.id.format),
view.findViewById(R.id.content),
view.findViewById(R.id.pin)
).also {
@@ -170,6 +180,7 @@ class ScansAdapter(
private data class ViewHolder(
val formatIconView: ImageView,
val metaView: TextView,
val formatView: TextView,
val contentView: TextView,
val pinView: ImageButton
)
@@ -204,13 +215,17 @@ fun Context.setupFormatSpinner(spinner: Spinner): List<String> {
fun String.prettifyFormatName() = replace("_", " ")
.replace(formatWordBoundary, " ")
private fun String?.toBinaryDataStringResId(): Int {
val type = parsedContentTypeFromName(this)
return if (type == ParsedContentType.UNKNOWN) {
R.string.binary_data
} else {
type.resId
}
private fun String.withContentType(
context: Context,
type: ParsedContentType
) = if (type == ParsedContentType.UNKNOWN) {
this
} else {
context.getString(
R.string.scan_meta_data,
this,
context.getString(type.resId)
)
}
fun String.toFormatDescriptionResId(): Int = when (this) {
@@ -185,6 +185,51 @@ fun parsedContentTypeFromName(
ParsedContentType.UNKNOWN
}
fun getContentPreview(
context: Context,
text: String,
bytes: ByteArray,
format: String,
action: Action = ActionRegistry.getAction(bytes)
): CharSequence {
val parsedData = parseData(context, text, bytes, format, action)
return when (parsedData.type) {
ParsedContentType.UNKNOWN -> text.ifEmpty {
bytes.toHexString()
}
ParsedContentType.URL -> parsedData.valueFor(R.string.host)
?: text
ParsedContentType.WIFI_NETWORK -> parsedData.valueFor(R.string.wifi_ssid)
?: parsedData.firstValue()
?: text
ParsedContentType.EMAIL -> parsedData.valueFor(R.string.email_to)
?: parsedData.valueFor(R.string.email_subject)
?: parsedData.firstValue()
?: text
ParsedContentType.OTP -> parsedData.valueFor(R.string.otp_account)
?: parsedData.firstValue()
?: text
else -> parsedData.firstValue() ?: text
}
}
private fun ParsedData.valueFor(key: Int): CharSequence? =
fields.firstValue { it.key == key }
private fun ParsedData.firstValue(): CharSequence? =
fields.firstValue()
private fun List<ParsedField>.firstValue(
predicate: (ParsedField) -> Boolean = { true }
): CharSequence? = firstOrNull {
predicate(it) && !it.value.isNullOrBlank()
}?.value
private fun MutableList<ParsedField>.addField(
key: Any,
value: CharSequence?,
@@ -31,6 +31,7 @@ class Database {
$SCANS_DATETIME,
$SCANS_NAME,
$SCANS_TEXT,
$SCANS_RAW,
$SCANS_CONTENT_TYPE,
$SCANS_FORMAT
FROM $SCANS
+9 -1
View File
@@ -22,6 +22,14 @@
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/format_icon"
android:layout_marginStart="32dp"/>
<TextView
style="@style/SecondaryText"
android:id="@+id/format"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/meta"
android:layout_toEndOf="@+id/format_icon"
android:layout_marginStart="32dp"/>
<ImageButton
android:id="@+id/pin"
android:layout_width="48dp"
@@ -41,7 +49,7 @@
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/meta"
android:layout_below="@+id/format"
android:layout_toEndOf="@+id/format_icon"
android:layout_toStartOf="@+id/pin"
android:layout_marginStart="32dp"