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.android.library)
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
alias(libs.plugins.ksp) alias(libs.plugins.ksp)
alias(libs.plugins.kotlin.plugin.serialization)
} }
android { android {
@ -54,5 +55,6 @@ dependencies {
implementation(project(":core:i18n")) implementation(project(":core:i18n"))
implementation(project(":core:ktx")) implementation(project(":core:ktx"))
implementation(project(":core:preferences")) 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.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import de.mm20.launcher2.serialization.UUIDSerializer
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import java.util.UUID import java.util.UUID
@Serializable
@Entity(tableName = "Theme") @Entity(tableName = "Theme")
data class ColorsEntity( data class ColorsEntity(
@PrimaryKey val id: UUID, @Serializable(with = UUIDSerializer::class) @PrimaryKey val id: UUID,
val name: String, val name: String,
val corePaletteA1: Int?, val corePaletteA1: Int?,

View File

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

View File

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

View File

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

View File

@ -4,7 +4,11 @@ import android.content.Context
import de.mm20.launcher2.backup.Backupable import de.mm20.launcher2.backup.Backupable
import de.mm20.launcher2.crashreporter.CrashReporter import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.database.AppDatabase 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.colors.ColorsRepository
import de.mm20.launcher2.themes.shapes.ShapesRepository import de.mm20.launcher2.themes.shapes.ShapesRepository
import de.mm20.launcher2.themes.transparencies.TransparenciesRepository import de.mm20.launcher2.themes.transparencies.TransparenciesRepository
@ -27,12 +31,29 @@ class ThemeRepository(
override suspend fun backup(toDir: File) = withContext(Dispatchers.IO) { override suspend fun backup(toDir: File) = withContext(Dispatchers.IO) {
val dao = database.themeDao() val dao = database.themeDao()
val colors = dao.getAllColors().first().map { Colors(it) }
val data = LegacyThemeJson.encodeToString(colors)
val file = File(toDir, "themes.0000") val colors = dao.getAllColors().first()
file.bufferedWriter().use { val colorsFile = File(toDir, "colors.0000")
it.write(data) 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() val dao = database.themeDao()
dao.deleteAllColors() dao.deleteAllColors()
val files = val colorFiles =
fromDir.listFiles { _, name -> name.startsWith("themes.") } fromDir.listFiles { _, name -> name.startsWith("colors.") }
?: return@withContext ?: return@withContext
for (file in files) { for (file in colorFiles) {
val data = file.inputStream().reader().readText() val data = file.inputStream().reader().readText()
val colors: List<Colors> = try { val colors: List<ColorsEntity> = try {
LegacyThemeJson.decodeFromString(data) Json.Lenient.decodeFromString(data)
} catch (e: SerializationException) { } catch (e: SerializationException) {
CrashReporter.logException(e) CrashReporter.logException(e)
continue continue
@ -55,7 +76,63 @@ class ThemeRepository(
CrashReporter.logException(e) CrashReporter.logException(e)
continue 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)
}
} }
} }