Skip to content

Commit

Permalink
Fix for the Missing or strange icons on the AllItemsScreen
Browse files Browse the repository at this point in the history
Deactivating deleteRealmIfMigrationNeeded for both MainDbConfig and BundleDataConfig. Implementing AllItemsScreen’s DbRow typeIconName type change migration
Explicitly specifying which RealmObject belongs to MainDbConfig and which to BundleDataConfig to avoid a possibility of the DbRequest executing on the wrong DbConfig.

Upping schemaVersion to 2
Upping versionCode to 74
  • Loading branch information
Dima-Android committed Jun 12, 2024
1 parent aadb1a5 commit d46e16f
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 56 deletions.
13 changes: 13 additions & 0 deletions app/src/main/java/org/zotero/android/androidx/content/Context.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.annotation.AttrRes
import androidx.annotation.DimenRes
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalDensity
import androidx.core.content.ContextCompat
import timber.log.Timber
Expand Down Expand Up @@ -97,5 +98,17 @@ fun Context.getFileSize(uri: Uri): Long? {
}
}

@Composable
fun Context.getDrawableByItemType(typeIconString: String): Int {
val drawableId = remember(typeIconString) {
resources.getIdentifier(
typeIconString,
"drawable",
packageName
)
}
return drawableId
}

@Composable
fun Int.pxToDp() = with(LocalDensity.current) { this@pxToDp.toDp() }
115 changes: 111 additions & 4 deletions app/src/main/java/org/zotero/android/database/Database.kt
Original file line number Diff line number Diff line change
@@ -1,34 +1,141 @@
package org.zotero.android.database

import io.realm.DynamicRealm
import io.realm.FieldAttribute
import io.realm.RealmConfiguration
import io.realm.annotations.RealmModule
import org.zotero.android.database.objects.AllItemsDbRow
import org.zotero.android.database.objects.FieldKeys
import org.zotero.android.database.objects.ItemTypes
import org.zotero.android.database.objects.RCollection
import org.zotero.android.database.objects.RCondition
import org.zotero.android.database.objects.RCreator
import org.zotero.android.database.objects.RCustomLibrary
import org.zotero.android.database.objects.RGroup
import org.zotero.android.database.objects.RItem
import org.zotero.android.database.objects.RItemField
import org.zotero.android.database.objects.RLink
import org.zotero.android.database.objects.RObjectChange
import org.zotero.android.database.objects.RPageIndex
import org.zotero.android.database.objects.RPath
import org.zotero.android.database.objects.RPathCoordinate
import org.zotero.android.database.objects.RRect
import org.zotero.android.database.objects.RRelation
import org.zotero.android.database.objects.RSearch
import org.zotero.android.database.objects.RTag
import org.zotero.android.database.objects.RTranslatorMetadata
import org.zotero.android.database.objects.RTypedTag
import org.zotero.android.database.objects.RUser
import org.zotero.android.database.objects.RVersions
import org.zotero.android.database.objects.RWebDavDeletion
import org.zotero.android.database.requests.key
import org.zotero.android.files.FileStore
import java.io.File

class Database {
companion object {
private const val schemaVersion = 1L //From now on must only increase by 1 whenever db schema changes
private const val schemaVersion = 2L //From now on must only increase by 1 whenever db schema changes

fun mainConfiguration(dbFile: File): RealmConfiguration {
val builder = RealmConfiguration.Builder()
.directory(dbFile.parentFile!!)
.name(dbFile.name)
.modules(MainConfigurationDbModule())
.schemaVersion(schemaVersion)
.allowWritesOnUiThread(true)
.deleteRealmIfMigrationNeeded()
.migration { dynamicRealm, oldVersion, newVersion ->
if (oldVersion < 2) {
migrateAllItemsDbRowTypeIconNameTypeChange(dynamicRealm)
}
}

return builder.build()
}

private fun migrateAllItemsDbRowTypeIconNameTypeChange(dynamicRealm: DynamicRealm) {
val realmSchema = dynamicRealm.schema

val allItemsDbRowSchema = realmSchema.get(AllItemsDbRow::class.java.simpleName)

allItemsDbRowSchema?.run {
removeField("typeIconName")
addField("typeIconName", String::class.java, FieldAttribute.REQUIRED)
transform {
it.set("typeIconName", "")
}
}
val allItems = dynamicRealm.where(RItem::class.java.simpleName).findAll()
for (item in allItems) {
val dbRow = item.getObject("allItemsDbRow")
if (dbRow == null) {
println()
continue
}

val rawType = item.getString("rawType")
val fields = item.getList("fields")

val contentType = if (rawType == ItemTypes.attachment) fields.where().key(
FieldKeys.Item.Attachment.contentType
).findFirst()?.getString("value") else null
dbRow.setString(
"typeIconName", ItemTypes.iconName(
rawType = rawType,
contentType = contentType
)
)
}

}

fun bundledDataConfiguration(fileStorage: FileStore): RealmConfiguration {
val dbFile = fileStorage.bundledDataDbFile()
val builder = RealmConfiguration.Builder()
.directory(dbFile.parentFile!!)
.name(dbFile.name)
.modules(BundledDataConfigurationDbModule())
.schemaVersion(schemaVersion)
.allowWritesOnUiThread(true)
.deleteRealmIfMigrationNeeded()

.migration { dynamicRealm, oldVersion, newVersion ->
//no-op for bundle migration for now
}
return builder.build()
}
}
}

@RealmModule(
library = false, classes = [
RCollection::class,
RCreator::class,
RCustomLibrary::class,
RGroup::class,
RItem::class,
RItemField::class,
RLink::class,
RPageIndex::class,
RPath::class,
RPathCoordinate::class,
RRect::class,
RRelation::class,
RSearch::class,
RCondition::class,
RTag::class,
RTypedTag::class,
RUser::class,
RWebDavDeletion::class,
RVersions::class,
RObjectChange::class,
AllItemsDbRow::class,
]
)
data class MainConfigurationDbModule(val placeholder: String) { // empty data class for equals/hashcode
constructor(): this("")
}

@RealmModule(library = false, classes=[
RTranslatorMetadata::class
])
data class BundledDataConfigurationDbModule(val placeholder: String) { // empty data class for equals/hashcode
constructor(): this("")
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.realm.annotations.RealmClass

@RealmClass(embedded = true)
open class AllItemsDbRow : RealmObject() {
var typeIconName: Int = 0
var typeIconName: String = ""
var title: String = ""
var subtitle: String = ""
var hasNote: Boolean = false
Expand Down
80 changes: 39 additions & 41 deletions app/src/main/java/org/zotero/android/database/objects/ItemTypes.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.zotero.android.database.objects

import org.zotero.android.uicomponents.Drawables

class ItemTypes {
companion object {
const val note = "note"
Expand All @@ -15,121 +13,121 @@ class ItemTypes {

var excludedFromTypePicker: Set<String> = setOf(attachment, annotation)

fun iconName(rawType: String, contentType: String?): Int {
fun iconName(rawType: String, contentType: String?): String {
when (rawType) {
"artwork" -> {
return Drawables.item_type_artwork
return "item_type_artwork"
}
"attachment" -> {
if (contentType?.contains("pdf") == true) {
return Drawables.item_type_pdf
return "item_type_pdf"
}
return Drawables.item_type_document
return "item_type_document"
}
"audioRecording" -> {
return Drawables.item_type_audiorecording
return "item_type_audiorecording"
}
"book" -> {
return Drawables.item_type_book
return "item_type_book"
}
"bookSection" -> {
return Drawables.item_type_booksection
return "item_type_booksection"
}
"bill" -> {
return Drawables.item_type_bill
return "item_type_bill"
}
"blogPost" -> {
return Drawables.item_type_blogpost
return "item_type_blogpost"
}
"case" -> {
return Drawables.item_type_case
return "item_type_case"
}
"computerProgram" -> {
return Drawables.item_type_computerprogram
return "item_type_computerprogram"
}
"conferencePaper" -> {
return Drawables.item_type_conferencepaper
return "item_type_conferencepaper"
}
"dictionaryEntry" -> {
return Drawables.item_type_dictionaryentry
return "item_type_dictionaryentry"
}
"document" -> {
return Drawables.item_type_document
return "item_type_document"
}
"email" -> {
return Drawables.item_type_email
return "item_type_email"
}
"encyclopediaArticle" -> {
return Drawables.item_type_encyclopediaarticle
return "item_type_encyclopediaarticle"
}
"film" -> {
return Drawables.item_type_film
return "item_type_film"
}
"forumPost" -> {
return Drawables.item_type_forumpost
return "item_type_forumpost"
}
"hearing" -> {
return Drawables.item_type_hearing
return "item_type_hearing"
}
"instantMessage" -> {
return Drawables.item_type_instantmessage
return "item_type_instantmessage"
}
"interview" -> {
return Drawables.item_type_interview
return "item_type_interview"
}
"journalArticle" -> {
return Drawables.item_type_journalarticle
return "item_type_journalarticle"
}
"letter" -> {
return Drawables.item_type_letter
return "item_type_letter"
}
"magazineArticle" -> {
return Drawables.item_type_magazinearticle
return "item_type_magazinearticle"
}
"map" -> {
return Drawables.item_type_map
return "item_type_map"
}
"manuscript" -> {
return Drawables.item_type_manuscript
return "item_type_manuscript"
}
"note" -> {
return Drawables.item_type_note
return "item_type_note"
}
"newspaperArticle" -> {
return Drawables.item_type_newspaperarticle
return "item_type_newspaperarticle"
}
"patent" -> {
return Drawables.item_type_patent
return "item_type_patent"
}
"podcast" -> {
return Drawables.item_type_podcast
return "item_type_podcast"
}
"presentation" -> {
return Drawables.item_type_presentation
return "item_type_presentation"
}
"radioBroadcast" -> {
return Drawables.item_type_radiobroadcast
return "item_type_radiobroadcast"
}
"report" -> {
return Drawables.item_type_report
return "item_type_report"
}
"statute" -> {
return Drawables.item_type_statute
return "item_type_statute"
}
"thesis" -> {
return Drawables.item_type_thesis
return "item_type_thesis"
}
"tvBroadcast" -> {
return Drawables.item_type_tvbroadcast
return "item_type_tvbroadcast"
}
"videoRecording" -> {
return Drawables.item_type_videorecording
return "item_type_videorecording"
}
"webpage" -> {
return Drawables.item_type_webpage
return "item_type_webpage"
}
else -> {
return Drawables.item_type_document
return "item_type_document"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import org.zotero.android.database.objects.ItemTypes
import org.zotero.android.androidx.content.getDrawableByItemType
import org.zotero.android.screens.addnote.data.AddOrEditNoteArgs
import org.zotero.android.uicomponents.Strings
import org.zotero.android.uicomponents.theme.CustomTheme
Expand All @@ -31,10 +32,10 @@ internal fun AddNoteTopBar(
modifier = modifier.padding(start = 40.dp),
verticalAlignment = Alignment.CenterVertically
) {
val iconInt = titleData?.type?.let { ItemTypes.iconName(it, null) }
if (iconInt != null) {
val type = titleData?.type
if (type != null) {
Image(
painter = painterResource(id = iconInt),
painter = painterResource(id = LocalContext.current.getDrawableByItemType(type)),
contentDescription = null,
)
Spacer(modifier = Modifier.width(10.dp))
Expand Down
Loading

0 comments on commit d46e16f

Please sign in to comment.