Verified Commit 8af820c9 authored by Jonas L.'s avatar Jonas L.

Add preview images for content from the local network

parent bcf6eceb
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "fffb49c0c1d9b566df186f03c47b33df",
"entities": [
{
"tableName": "downloaded_local_network_project",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`project_id` TEXT NOT NULL, `hash` TEXT NOT NULL, `local_filename` TEXT NOT NULL, `file_size` INTEGER NOT NULL, `title` TEXT NOT NULL, `description` TEXT NOT NULL, `preview_image_filename` TEXT, PRIMARY KEY(`project_id`))",
"fields": [
{
"fieldPath": "projectId",
"columnName": "project_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "hash",
"columnName": "hash",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "localFilename",
"columnName": "local_filename",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "fileSize",
"columnName": "file_size",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "previewImageFilename",
"columnName": "preview_image_filename",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"project_id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "package_source_project",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`project_id` TEXT NOT NULL, `url` TEXT NOT NULL, `image` TEXT NOT NULL, `image_source` TEXT NOT NULL, `local_image_filename` TEXT NOT NULL, `package_source_url` TEXT, `local_hash` TEXT, `local_filename` TEXT, `local_file_size` INTEGER, `title` TEXT NOT NULL, `resolution` INTEGER NOT NULL, PRIMARY KEY(`project_id`))",
"fields": [
{
"fieldPath": "projectId",
"columnName": "project_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "image",
"columnName": "image",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "imageSource",
"columnName": "image_source",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "localImageFilename",
"columnName": "local_image_filename",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "packageSourceUrl",
"columnName": "package_source_url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "localHash",
"columnName": "local_hash",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "localFilename",
"columnName": "local_filename",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "projectJsonLocalFileSize",
"columnName": "local_file_size",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "resolution",
"columnName": "resolution",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"project_id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "package_source",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `last_query_failed` INTEGER NOT NULL, PRIMARY KEY(`url`))",
"fields": [
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "lastQueryFailed",
"columnName": "last_query_failed",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"url"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"fffb49c0c1d9b566df186f03c47b33df\")"
]
}
}
\ No newline at end of file
package de.determapp.android.content
import android.util.JsonReader
import android.util.JsonToken
import de.determapp.android.content.projectdata.*
import java.io.IOException
import java.util.*
......@@ -20,6 +21,7 @@ object ContentJsonParser {
var description: String? = null
var hash: String? = null
var projectId: String? = null
var previewImageId: String? = null
reader.beginObject()
while (reader.hasNext()) {
......@@ -33,6 +35,15 @@ object ContentJsonParser {
"description" -> description = reader.nextString()
"hash" -> hash = reader.nextString()
"projectId" -> projectId = reader.nextString()
"previewImageId" -> {
if (reader.peek() == JsonToken.STRING) {
previewImageId = reader.nextString()
} else {
reader.nextNull()
previewImageId = null
}
}
else -> reader.skipValue()
}
}
......@@ -47,7 +58,8 @@ object ContentJsonParser {
imprint = imprint!!,
description = description!!,
hash = hash!!,
projectId = projectId!!
projectId = projectId!!,
previewImageId = previewImageId
)
}
}
......
......@@ -15,7 +15,7 @@ import de.determapp.android.content.database.item.PackageSourceProject
PackageSourceProject::class,
PackageSource::class
],
version = 2
version = 3
)
abstract class AppDatabase : RoomDatabase() {
abstract fun localNetworkProjectDao(): DownloadedLocalNetworkProjectDao
......
......@@ -23,6 +23,11 @@ object AppDatabaseInstance {
database.execSQL("ALTER TABLE package_source_project ADD COLUMN `local_image_filename` TEXT NOT NULL DEFAULT \"\"")
}
})
.addMigrations(object: Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE downloaded_local_network_project ADD COLUMN `preview_image_filename` TEXT")
}
})
.build()
}
......
......@@ -23,8 +23,8 @@ interface DownloadedLocalNetworkProjectDao {
@Insert
fun addProject(project: DownloadedLocalNetworkProject)
@Query("UPDATE downloaded_local_network_project SET hash = :hash, local_filename = :localFilename, file_size = :fileSize, title = :title, description = :description WHERE project_id = :projectId")
fun updateProject(projectId: String, hash: String, localFilename: String, fileSize: Long, title: String, description: String)
@Query("UPDATE downloaded_local_network_project SET hash = :hash, local_filename = :localFilename, file_size = :fileSize, title = :title, description = :description, preview_image_filename = :previewImageFilename WHERE project_id = :projectId")
fun updateProject(projectId: String, hash: String, localFilename: String, fileSize: Long, title: String, description: String, previewImageFilename: String?)
@Query("DELETE FROM downloaded_local_network_project WHERE project_id = :projectId")
fun removeProjectById(projectId: String)
......
......@@ -18,5 +18,7 @@ data class DownloadedLocalNetworkProject(
@ColumnInfo(name = "file_size")
val fileSize: Long = 0,
val title: String,
val description: String
val description: String,
@ColumnInfo(name = "preview_image_filename")
val previewImageFilename: String?
)
......@@ -61,6 +61,10 @@ fun downloadOrUpdateLocalNetworkContent(context: Context, request: DownloadLocal
)
// save the new project version
val previewImageFilename = downloadResponse.project.previewImageId?.let { previewImageId ->
downloadResponse.project.image.get(previewImageId)?.getByResolution(1024)?.filename
}
if (oldDatabaseEntry == null) {
// create entry
database.localNetworkProjectDao().addProject(
......@@ -69,7 +73,8 @@ fun downloadOrUpdateLocalNetworkContent(context: Context, request: DownloadLocal
hash = downloadResponse.project.hash,
localFilename = downloadResponse.filename,
title = downloadResponse.project.title,
description = downloadResponse.project.description
description = downloadResponse.project.description,
previewImageFilename = previewImageFilename
)
)
} else {
......@@ -80,7 +85,8 @@ fun downloadOrUpdateLocalNetworkContent(context: Context, request: DownloadLocal
downloadResponse.filename,
downloadResponse.fileSize,
downloadResponse.project.title,
downloadResponse.project.description
downloadResponse.project.description,
previewImageFilename
);
// delete old file
......
......@@ -54,6 +54,10 @@ fun installDocumentFileContent(context: Context, documentFile: DocumentFile, pro
)
// save the new project version
val previewImageFilename = downloadResponse.project.previewImageId?.let { previewImageId ->
downloadResponse.project.image.get(previewImageId)?.getByResolution(1024)?.filename
}
if (oldDatabaseEntry == null) {
// create entry
database.localNetworkProjectDao().addProject(
......@@ -62,7 +66,8 @@ fun installDocumentFileContent(context: Context, documentFile: DocumentFile, pro
hash = project.hash,
localFilename = downloadResponse.filename,
title = project.title,
description = project.description
description = project.description,
previewImageFilename = previewImageFilename
)
)
} else {
......@@ -73,7 +78,8 @@ fun installDocumentFileContent(context: Context, documentFile: DocumentFile, pro
downloadResponse.filename,
downloadResponse.fileSize,
project.title,
project.description
project.description,
previewImageFilename
);
// delete old file
......
......@@ -12,7 +12,8 @@ data class Project(
val imprint: String,
val description: String,
val hash: String,
val projectId: String
val projectId: String,
val previewImageId: String?
) {
init {
Validator.assertIdValid(projectId)
......
......@@ -3,10 +3,13 @@ package de.determapp.android.ui.contentlist
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import de.determapp.android.content.ContentStorage
import de.determapp.android.content.database.AppDatabaseInstance
import de.determapp.android.content.database.item.DownloadedLocalNetworkProject
import de.determapp.android.content.database.item.PackageSourceProject
import de.determapp.android.ui.viewer.PackageSource
import de.determapp.android.ui.viewer.ProjectSpec
import java.io.File
class ContentList private constructor(context: Context) {
......@@ -14,6 +17,7 @@ class ContentList private constructor(context: Context) {
private val downloadedLocalNetworkProjectsLive: LiveData<List<DownloadedLocalNetworkProject>>
private val packageSourcesContentLive: LiveData<List<PackageSourceProject>>
private val database = AppDatabaseInstance.with(context)
private val contentStorage = ContentStorage.with(context)
init {
downloadedLocalNetworkProjectsLive = database.localNetworkProjectDao().getProjectsLive()
......@@ -36,11 +40,20 @@ class ContentList private constructor(context: Context) {
data.value =
downloadedLocalNetworkProjects.map { item ->
val projectSpec = ProjectSpec(
projectId = item.projectId,
type = PackageSource.DownloadedFromLocalNetwork
)
val imageDirectory = contentStorage.getImageDirectory(projectSpec)
ContentListItem(
item.title,
item.projectId,
PackageSource.DownloadedFromLocalNetwork,
localImageFilename = ""
previewImage = item.previewImageFilename?.let { previewImageFilename ->
File(imageDirectory, previewImageFilename)
}
)
} +
packageSourcesContent.map { item ->
......@@ -48,7 +61,7 @@ class ContentList private constructor(context: Context) {
item.title,
item.projectId,
PackageSource.WebPackageSource,
localImageFilename = item.localImageFilename
previewImage = File(contentStorage.previewImagesDirectory, item.localImageFilename)
)
}
}
......
......@@ -57,7 +57,7 @@ class ContentListAdapter: RecyclerView.Adapter<ViewHolder>() {
holder.binding.item = item
holder.binding.handlers = handlers
if (item.localImageFilename.isEmpty()) {
if (item.previewImage == null) {
Picasso.get()
.load(null as String?)
.placeholder(R.drawable.placeholder)
......@@ -66,12 +66,7 @@ class ContentListAdapter: RecyclerView.Adapter<ViewHolder>() {
.into(holder.binding.previewImage)
} else {
Picasso.get()
.load(
File(
ContentStorage.with(holder.binding.root.context).previewImagesDirectory,
item.localImageFilename
)
)
.load(item.previewImage)
.placeholder(R.drawable.loading_placeholder)
.error(R.drawable.placeholder)
.fit()
......
package de.determapp.android.ui.contentlist
import de.determapp.android.ui.viewer.PackageSource
import java.io.File
data class ContentListItem(
val title: String,
val projectId: String,
val source: PackageSource,
val localImageFilename: String
val previewImage: File?
) {
fun generateId(): Long {
return 5000000000L * source.ordinal.toLong() + projectId.hashCode().toLong()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment