Skip to content

refactor(database): migrate to androidx.room3, add thumbnail handling…#778

Merged
prathieshna merged 3 commits intoNEXT-FDROID-C2PA-TOR-STORACHA-DWEB-COMPOSEfrom
bugFix/compose-migration-fixes
Mar 26, 2026
Merged

refactor(database): migrate to androidx.room3, add thumbnail handling…#778
prathieshna merged 3 commits intoNEXT-FDROID-C2PA-TOR-STORACHA-DWEB-COMPOSEfrom
bugFix/compose-migration-fixes

Conversation

@Elelan
Copy link
Copy Markdown

@Elelan Elelan commented Mar 24, 2026

refactor(database): migrate to androidx.room3, add thumbnail handling, and improve file cleanup

  • Upgrade Room dependencies to androidx.room3 across the project.
  • Add thumbnail support to Evidence and improve media representation in UI.
  • Enhance file cleanup logic by separating uploaded media artifact deletion.
  • Update database schema version and related migration scripts.

Elelan added 2 commits March 25, 2026 03:11
…, and improve file cleanup

- Upgrade Room dependencies to androidx.room3 across the project.
- Add thumbnail support to Evidence and improve media representation in UI.
- Enhance file cleanup logic by separating uploaded media artifact deletion.
- Update database schema version and related migration scripts.
package net.opendasharchive.openarchive.core.di

import androidx.room.Room
import androidx.room3.Room

Check warning

Code scanning / detekt

Detects imports in non default order Warning

Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end
import androidx.room.AutoMigration
import androidx.room.DeleteColumn
import androidx.room.migration.AutoMigrationSpec
import android.annotation.SuppressLint

Check warning

Code scanning / detekt

Detects imports in non default order Warning

Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end
private const val MAX_DIMENSION_PX = 128
private const val JPEG_QUALITY = 40

fun generateThumbnailBytes(file: File, mimeType: String): ByteArray? {

Check warning

Code scanning / detekt

Restrict the number of return statements in methods. Warning

Function generateThumbnailBytes has 3 return statements which exceeds the limit of 2.
mimeType == "application/pdf" -> createPdfThumbnail(file)
else -> null
}
} catch (e: Exception) {

Check warning

Code scanning / detekt

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled. Warning

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled.
return bitmap.useCompressedJpeg()
}

private fun createImageThumbnail(file: File): Bitmap? {

Check warning

Code scanning / detekt

Restrict the number of return statements in methods. Warning

Function createImageThumbnail has 3 return statements which exceeds the limit of 2.
}
}

private fun createPdfThumbnail(file: File): Bitmap? {

Check warning

Code scanning / detekt

Excessive nesting leads to hidden complexity. Prefer extracting code to make it easier to understand. Warning

Function createPdfThumbnail is nested too deeply.
val scale = minOf(
MAX_DIMENSION_PX.toFloat() / page.width,
MAX_DIMENSION_PX.toFloat() / page.height
).coerceAtLeast(0.1f)

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
Comment on lines +15 to +36
@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class FileCleanupHelperTest {

@Test
fun `deleteUploadedMediaFiles removes internal file and keeps db-backed thumbnail untouched`() {
val context = RuntimeEnvironment.getApplication()
val file = File(context.filesDir, "cleanup-uploaded-file.jpg").apply {
writeBytes(byteArrayOf(1, 2, 3))
}
val evidence = Evidence(
originalFilePath = Uri.fromFile(file).toString(),
thumbnail = byteArrayOf(9, 8, 7),
mediaHashString = ""
)

FileCleanupHelper(context).deleteUploadedMediaFiles(evidence)

assertFalse(file.exists())
assertTrue(evidence.thumbnail!!.isNotEmpty())
}
}

Check warning

Code scanning / detekt

Library classes should not be public. Warning test

Class FileCleanupHelperTest should not be public
Comment on lines +13 to +44
@RunWith(RobolectricTestRunner::class)
@Config(application = android.app.Application::class)
class MediaThumbnailGeneratorTest {

@Test
fun `generateThumbnailBytes creates a small jpeg thumbnail for image files`() {
val source = File.createTempFile("thumbnail-source", ".jpg")
source.outputStream().use { output ->
Bitmap.createBitmap(1200, 800, Bitmap.Config.ARGB_8888).apply {
eraseColor(android.graphics.Color.RED)
compress(Bitmap.CompressFormat.JPEG, 95, output)
recycle()
}
}

val thumbnailBytes = MediaThumbnailGenerator.generateThumbnailBytes(
file = source,
mimeType = "image/jpeg"
)

assertNotNull(thumbnailBytes)
assertTrue(thumbnailBytes!!.size in 1 until 20_000)

val bitmap = BitmapFactory.decodeByteArray(thumbnailBytes, 0, thumbnailBytes.size)
assertNotNull(bitmap)
assertTrue(bitmap!!.width <= 128)
assertTrue(bitmap.height <= 128)

bitmap.recycle()
source.delete()
}
}

Check warning

Code scanning / detekt

Library classes should not be public. Warning test

Class MediaThumbnailGeneratorTest should not be public
@prathieshna prathieshna merged commit 4f5df4c into NEXT-FDROID-C2PA-TOR-STORACHA-DWEB-COMPOSE Mar 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants