Implement backup and restore for new theme types

This commit is contained in:
MM20 2025-07-03 22:46:14 +02:00
parent 37e73c1dd4
commit 4aa02a89df
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
6 changed files with 108 additions and 16 deletions

View File

@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.ksp)
alias(libs.plugins.kotlin.plugin.serialization)
}
android {
@ -54,5 +55,6 @@ dependencies {
implementation(project(":core:i18n"))
implementation(project(":core:ktx"))
implementation(project(":core:preferences"))
implementation(project(":core:base"))
}

View File

@ -2,11 +2,15 @@ package de.mm20.launcher2.database.entities
import androidx.room.Entity
import androidx.room.PrimaryKey
import de.mm20.launcher2.serialization.UUIDSerializer
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import java.util.UUID
@Serializable
@Entity(tableName = "Theme")
data class ColorsEntity(
@PrimaryKey val id: UUID,
@Serializable(with = UUIDSerializer::class) @PrimaryKey val id: UUID,
val name: String,
val corePaletteA1: Int?,

View File

@ -2,11 +2,14 @@ package de.mm20.launcher2.database.entities
import androidx.room.Entity
import androidx.room.PrimaryKey
import de.mm20.launcher2.serialization.UUIDSerializer
import kotlinx.serialization.Serializable
import java.util.UUID
@Serializable
@Entity(tableName = "Shapes")
data class ShapesEntity(
@PrimaryKey val id: UUID,
@Serializable(with = UUIDSerializer::class) @PrimaryKey val id: UUID,
val name: String,
val baseShape: String,

View File

@ -2,11 +2,14 @@ package de.mm20.launcher2.database.entities
import androidx.room.Entity
import androidx.room.PrimaryKey
import de.mm20.launcher2.serialization.UUIDSerializer
import kotlinx.serialization.Serializable
import java.util.UUID
@Serializable
@Entity(tableName = "Transparencies")
data class TransparenciesEntity(
@PrimaryKey val id: UUID,
@Serializable(with = UUIDSerializer::class) @PrimaryKey val id: UUID,
val name: String,
val background: Float?,

View File

@ -2,11 +2,14 @@ package de.mm20.launcher2.database.entities
import androidx.room.Entity
import androidx.room.PrimaryKey
import de.mm20.launcher2.serialization.UUIDSerializer
import kotlinx.serialization.Serializable
import java.util.UUID
@Serializable
@Entity(tableName = "Typography")
data class TypographyEntity(
@PrimaryKey val id: UUID,
@Serializable(with = UUIDSerializer::class) @PrimaryKey val id: UUID,
val name: String,
val fonts: String? = null,

View File

@ -4,7 +4,11 @@ import android.content.Context
import de.mm20.launcher2.backup.Backupable
import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.database.AppDatabase
import de.mm20.launcher2.themes.colors.Colors
import de.mm20.launcher2.database.entities.ColorsEntity
import de.mm20.launcher2.database.entities.ShapesEntity
import de.mm20.launcher2.database.entities.TransparenciesEntity
import de.mm20.launcher2.database.entities.TypographyEntity
import de.mm20.launcher2.serialization.Json
import de.mm20.launcher2.themes.colors.ColorsRepository
import de.mm20.launcher2.themes.shapes.ShapesRepository
import de.mm20.launcher2.themes.transparencies.TransparenciesRepository
@ -27,12 +31,29 @@ class ThemeRepository(
override suspend fun backup(toDir: File) = withContext(Dispatchers.IO) {
val dao = database.themeDao()
val colors = dao.getAllColors().first().map { Colors(it) }
val data = LegacyThemeJson.encodeToString(colors)
val file = File(toDir, "themes.0000")
file.bufferedWriter().use {
it.write(data)
val colors = dao.getAllColors().first()
val colorsFile = File(toDir, "colors.0000")
colorsFile.bufferedWriter().use {
it.write(Json.Lenient.encodeToString(colors))
}
val shapes = dao.getAllShapes().first()
val shapesFile = File(toDir, "shapes.0000")
shapesFile.bufferedWriter().use {
it.write(Json.Lenient.encodeToString(shapes))
}
val transparencies = dao.getAllTransparencies().first()
val transparenciesFile = File(toDir, "transparencies.0000")
transparenciesFile.bufferedWriter().use {
it.write(Json.Lenient.encodeToString(transparencies))
}
val typographies = dao.getAllTypographies().first()
val typographiesFile = File(toDir, "typographies.0000")
typographiesFile.bufferedWriter().use {
it.write(Json.Lenient.encodeToString(typographies))
}
}
@ -40,14 +61,14 @@ class ThemeRepository(
val dao = database.themeDao()
dao.deleteAllColors()
val files =
fromDir.listFiles { _, name -> name.startsWith("themes.") }
val colorFiles =
fromDir.listFiles { _, name -> name.startsWith("colors.") }
?: return@withContext
for (file in files) {
for (file in colorFiles) {
val data = file.inputStream().reader().readText()
val colors: List<Colors> = try {
LegacyThemeJson.decodeFromString(data)
val colors: List<ColorsEntity> = try {
Json.Lenient.decodeFromString(data)
} catch (e: SerializationException) {
CrashReporter.logException(e)
continue
@ -55,7 +76,63 @@ class ThemeRepository(
CrashReporter.logException(e)
continue
}
dao.insertAllColors(colors.map { it.toEntity() })
dao.insertAllColors(colors)
}
dao.deleteAllShapes()
val shapeFiles =
fromDir.listFiles { _, name -> name.startsWith("shapes.") }
?: return@withContext
for (file in shapeFiles) {
val data = file.inputStream().reader().readText()
val shapes: List<ShapesEntity> = try {
Json.Lenient.decodeFromString(data)
} catch (e: SerializationException) {
CrashReporter.logException(e)
continue
} catch (e: IllegalArgumentException) {
CrashReporter.logException(e)
continue
}
dao.insertAllShapes(shapes)
}
dao.deleteAllTransparencies()
val transparencyFiles =
fromDir.listFiles { _, name -> name.startsWith("transparencies.") }
?: return@withContext
for (file in transparencyFiles) {
val data = file.inputStream().reader().readText()
val transparencies: List<TransparenciesEntity> = try {
Json.Lenient.decodeFromString(data)
} catch (e: SerializationException) {
CrashReporter.logException(e)
continue
} catch (e: IllegalArgumentException) {
CrashReporter.logException(e)
continue
}
dao.insertAllTransparencies(transparencies)
}
dao.deleteAllTypographies()
val typographyFiles =
fromDir.listFiles { _, name -> name.startsWith("typographies.") }
?: return@withContext
for (file in typographyFiles) {
val data = file.inputStream().reader().readText()
val typographies: List<TypographyEntity> = try {
Json.Lenient.decodeFromString(data)
} catch (e: SerializationException) {
CrashReporter.logException(e)
continue
} catch (e: IllegalArgumentException) {
CrashReporter.logException(e)
continue
}
dao.insertAllTypographies(typographies)
}
}
}