From 46f2f47cdaa5c0b0d66ea305d44f046affaf2069 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Tue, 22 Aug 2023 21:34:46 +0200 Subject: [PATCH] Custom color schemes v2 - Part 2 Add database entity and migrations --- core/database/build.gradle.kts | 1 + .../de/mm20/launcher2/database/AppDatabase.kt | 61 +++-- .../database/entities/ThemeEntity.kt | 90 ++++++++ .../database/migrations/Migration_24_25.kt | 213 ++++++++++++++++++ 4 files changed, 348 insertions(+), 17 deletions(-) create mode 100644 core/database/src/main/java/de/mm20/launcher2/database/entities/ThemeEntity.kt create mode 100644 core/database/src/main/java/de/mm20/launcher2/database/migrations/Migration_24_25.kt diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts index 6fdcb992..8f83f906 100644 --- a/core/database/build.gradle.kts +++ b/core/database/build.gradle.kts @@ -53,5 +53,6 @@ dependencies { implementation(project(":core:i18n")) implementation(project(":core:ktx")) + implementation(project(":core:preferences")) } \ No newline at end of file diff --git a/core/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt b/core/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt index 92af7b80..afedd858 100644 --- a/core/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt +++ b/core/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt @@ -8,7 +8,15 @@ import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.TypeConverters import androidx.sqlite.db.SupportSQLiteDatabase -import de.mm20.launcher2.database.entities.* +import de.mm20.launcher2.database.entities.CurrencyEntity +import de.mm20.launcher2.database.entities.CustomAttributeEntity +import de.mm20.launcher2.database.entities.ForecastEntity +import de.mm20.launcher2.database.entities.IconEntity +import de.mm20.launcher2.database.entities.IconPackEntity +import de.mm20.launcher2.database.entities.SavedSearchableEntity +import de.mm20.launcher2.database.entities.SearchActionEntity +import de.mm20.launcher2.database.entities.ThemeEntity +import de.mm20.launcher2.database.entities.WidgetEntity import de.mm20.launcher2.database.migrations.Migration_10_11 import de.mm20.launcher2.database.migrations.Migration_11_12 import de.mm20.launcher2.database.migrations.Migration_12_13 @@ -23,6 +31,7 @@ import de.mm20.launcher2.database.migrations.Migration_20_21 import de.mm20.launcher2.database.migrations.Migration_21_22 import de.mm20.launcher2.database.migrations.Migration_22_23 import de.mm20.launcher2.database.migrations.Migration_23_24 +import de.mm20.launcher2.database.migrations.Migration_24_25 import de.mm20.launcher2.database.migrations.Migration_6_7 import de.mm20.launcher2.database.migrations.Migration_7_8 import de.mm20.launcher2.database.migrations.Migration_8_9 @@ -39,8 +48,9 @@ import java.util.UUID IconPackEntity::class, WidgetEntity::class, CustomAttributeEntity::class, - SearchActionEntity::class - ], version = 24, exportSchema = true + SearchActionEntity::class, + ThemeEntity::class, + ], version = 25, exportSchema = true ) @TypeConverters(ComponentNameConverter::class) abstract class AppDatabase : RoomDatabase() { @@ -65,23 +75,39 @@ abstract class AppDatabase : RoomDatabase() { .addCallback(object : Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) - db.execSQL("INSERT INTO `SearchAction` (`position`, `type`) VALUES" + - "(0, 'call')," + - "(1, 'message')," + - "(2, 'email')," + - "(3, 'contact')," + - "(4, 'alarm')," + - "(5, 'timer')," + - "(6, 'calendar')," + - "(7, 'website')," + - "(8, 'websearch')" + db.execSQL( + "INSERT INTO `SearchAction` (`position`, `type`) VALUES" + + "(0, 'call')," + + "(1, 'message')," + + "(2, 'email')," + + "(3, 'contact')," + + "(4, 'alarm')," + + "(5, 'timer')," + + "(6, 'calendar')," + + "(7, 'website')," + + "(8, 'websearch')" ) - db.execSQL("INSERT INTO `SearchAction` (`position`, `type`, `data`, `label`, `color`, `icon`, `customIcon`, `options`) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?)", + db.execSQL( + "INSERT INTO `SearchAction` (`position`, `type`, `data`, `label`, `color`, `icon`, `customIcon`, `options`) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?)", arrayOf( - 9, "url", context.getString(R.string.default_websearch_2_url), context.getString(R.string.default_websearch_2_name), 0, 0, null, null, - 10, "url", context.getString(R.string.default_websearch_3_url), context.getString(R.string.default_websearch_3_name), 0, 0, null, null, + 9, + "url", + context.getString(R.string.default_websearch_2_url), + context.getString(R.string.default_websearch_2_name), + 0, + 0, + null, + null, + 10, + "url", + context.getString(R.string.default_websearch_3_url), + context.getString(R.string.default_websearch_3_name), + 0, + 0, + null, + null, ) ) @@ -117,6 +143,7 @@ abstract class AppDatabase : RoomDatabase() { Migration_21_22(), Migration_22_23(), Migration_23_24(), + Migration_24_25(context), ).build() if (_instance == null) _instance = instance return instance diff --git a/core/database/src/main/java/de/mm20/launcher2/database/entities/ThemeEntity.kt b/core/database/src/main/java/de/mm20/launcher2/database/entities/ThemeEntity.kt new file mode 100644 index 00000000..69099ffb --- /dev/null +++ b/core/database/src/main/java/de/mm20/launcher2/database/entities/ThemeEntity.kt @@ -0,0 +1,90 @@ +package de.mm20.launcher2.database.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey +import java.util.UUID + +@Entity(tableName = "Theme") +data class ThemeEntity( + @PrimaryKey val id: UUID, + val corePaletteA1: Int?, + val corePaletteA2: Int?, + val corePaletteA3: Int?, + val corePaletteN1: Int?, + val corePaletteN2: Int?, + val corePaletteE: Int?, + + val lightPrimary: String?, + val lightOnPrimary: String?, + val lightPrimaryContainer: String?, + val lightOnPrimaryContainer: String?, + val lightSecondary: String?, + val lightOnSecondary: String?, + val lightSecondaryContainer: String?, + val lightOnSecondaryContainer: String?, + val lightTertiary: String?, + val lightOnTertiary: String?, + val lightTertiaryContainer: String?, + val lightOnTertiaryContainer: String?, + val lightError: String?, + val lightOnError: String?, + val lightErrorContainer: String?, + val lightOnErrorContainer: String?, + val lightSurface: String?, + val lightOnSurface: String?, + val lightOnSurfaceVariant: String?, + val lightOutline: String?, + val lightOutlineVariant: String?, + val lightInverseSurface: String?, + val lightInverseOnSurface: String?, + val lightInversePrimary: String?, + val lightSurfaceDim: String?, + val lightSurfaceBright: String?, + val lightSurfaceContainerLowest: String?, + val lightSurfaceContainerLow: String?, + val lightSurfaceContainer: String?, + val lightSurfaceContainerHigh: String?, + val lightSurfaceContainerHighest: String?, + val lightBackground: String?, + val lightOnBackground: String?, + val lightSurfaceTint: String?, + val lightScrim: String?, + val lightSurfaceVariant: String?, + + val darkPrimary: String?, + val darkOnPrimary: String?, + val darkPrimaryContainer: String?, + val darkOnPrimaryContainer: String?, + val darkSecondary: String?, + val darkOnSecondary: String?, + val darkSecondaryContainer: String?, + val darkOnSecondaryContainer: String?, + val darkTertiary: String?, + val darkOnTertiary: String?, + val darkTertiaryContainer: String?, + val darkOnTertiaryContainer: String?, + val darkError: String?, + val darkOnError: String?, + val darkErrorContainer: String?, + val darkOnErrorContainer: String?, + val darkSurface: String?, + val darkOnSurface: String?, + val darkOnSurfaceVariant: String?, + val darkOutline: String?, + val darkOutlineVariant: String?, + val darkInverseSurface: String?, + val darkInverseOnSurface: String?, + val darkInversePrimary: String?, + val darkSurfaceDim: String?, + val darkSurfaceBright: String?, + val darkSurfaceContainerLowest: String?, + val darkSurfaceContainerLow: String?, + val darkSurfaceContainer: String?, + val darkSurfaceContainerHigh: String?, + val darkSurfaceContainerHighest: String?, + val darkBackground: String?, + val darkOnBackground: String?, + val darkSurfaceTint: String?, + val darkScrim: String?, + val darkSurfaceVariant: String?, +) \ No newline at end of file diff --git a/core/database/src/main/java/de/mm20/launcher2/database/migrations/Migration_24_25.kt b/core/database/src/main/java/de/mm20/launcher2/database/migrations/Migration_24_25.kt new file mode 100644 index 00000000..11143b83 --- /dev/null +++ b/core/database/src/main/java/de/mm20/launcher2/database/migrations/Migration_24_25.kt @@ -0,0 +1,213 @@ +package de.mm20.launcher2.database.migrations + +import android.content.Context +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase +import de.mm20.launcher2.ktx.toBytes +import de.mm20.launcher2.preferences.LauncherDataStore +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import java.util.UUID + +class Migration_24_25( + private val context: Context, +) : Migration(24, 25), KoinComponent { + private val dataStore: LauncherDataStore by inject() + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + """ + CREATE TABLE IF NOT EXISTS `Theme` ( + `id` BLOB NOT NULL, + `corePaletteA1` INTEGER, + `corePaletteA2` INTEGER, + `corePaletteA3` INTEGER, + `corePaletteN1` INTEGER, + `corePaletteN2` INTEGER, + `corePaletteE` INTEGER, + `lightPrimary` TEXT, + `lightOnPrimary` TEXT, + `lightPrimaryContainer` TEXT, + `lightOnPrimaryContainer` TEXT, + `lightSecondary` TEXT, + `lightOnSecondary` TEXT, + `lightSecondaryContainer` TEXT, + `lightOnSecondaryContainer` TEXT, + `lightTertiary` TEXT, + `lightOnTertiary` TEXT, + `lightTertiaryContainer` TEXT, + `lightOnTertiaryContainer` TEXT, + `lightError` TEXT, + `lightOnError` TEXT, + `lightErrorContainer` TEXT, + `lightOnErrorContainer` TEXT, + `lightSurface` TEXT, + `lightOnSurface` TEXT, + `lightOnSurfaceVariant` TEXT, + `lightOutline` TEXT, + `lightOutlineVariant` TEXT, + `lightInverseSurface` TEXT, + `lightInverseOnSurface` TEXT, + `lightInversePrimary` TEXT, + `lightSurfaceDim` TEXT, + `lightSurfaceBright` TEXT, + `lightSurfaceContainerLowest` TEXT, + `lightSurfaceContainerLow` TEXT, + `lightSurfaceContainer` TEXT, + `lightSurfaceContainerHigh` TEXT, + `lightSurfaceContainerHighest` TEXT, + `lightBackground` TEXT, + `lightOnBackground` TEXT, + `lightSurfaceTint` TEXT, + `lightScrim` TEXT, + `lightSurfaceVariant` TEXT, + + `darkPrimary` TEXT, + `darkOnPrimary` TEXT, + `darkPrimaryContainer` TEXT, + `darkOnPrimaryContainer` TEXT, + `darkSecondary` TEXT, + `darkOnSecondary` TEXT, + `darkSecondaryContainer` TEXT, + `darkOnSecondaryContainer` TEXT, + `darkTertiary` TEXT, + `darkOnTertiary` TEXT, + `darkTertiaryContainer` TEXT, + `darkOnTertiaryContainer` TEXT, + `darkError` TEXT, + `darkOnError` TEXT, + `darkErrorContainer` TEXT, + `darkOnErrorContainer` TEXT, + `darkSurface` TEXT, + `darkOnSurface` TEXT, + `darkOnSurfaceVariant` TEXT, + `darkOutline` TEXT, + `darkOutlineVariant` TEXT, + `darkInverseSurface` TEXT, + `darkInverseOnSurface` TEXT, + `darkInversePrimary` TEXT, + `darkSurfaceDim` TEXT, + `darkSurfaceBright` TEXT, + `darkSurfaceContainerLowest` TEXT, + `darkSurfaceContainerLow` TEXT, + `darkSurfaceContainer` TEXT, + `darkSurfaceContainerHigh` TEXT, + `darkSurfaceContainerHighest` TEXT, + `darkBackground` TEXT, + `darkOnBackground` TEXT, + `darkSurfaceTint` TEXT, + `darkScrim` TEXT, + `darkSurfaceVariant` TEXT, + PRIMARY KEY(`id`) + ) + """.trimIndent() + ) + // Special UUID for migrated custom color scheme. Same UUID is used in data store migration 16..17 + val uuid = UUID(1L, 1L) + val customColors = runBlocking { + dataStore.data.map { it.appearance.customColors }.first() + } + + database.execSQL("""INSERT INTO `Theme` VALUES ( + ?,?,?,?,?,?,?,?,?,?, + ?,?,?,?,?,?,?,?,?,?, + ?,?,?,?,?,?,?,?,?,?, + ?,?,?,?,?,?,?,?,?,?, + ?,?,?,?,?,?,?,?,?,?, + ?,?,?,?,?,?,?,?,?,?, + ?,?,?,?,?,?,?,?,?,?, + ?,?,?,?,?,?,?,?,? + ) + """.trimIndent(), + arrayOf( + uuid.toBytes(), + customColors.baseColors.accent1.toHexColor(), + customColors.baseColors.accent2.toHexColor(), + customColors.baseColors.accent3.toHexColor(), + customColors.baseColors.neutral1.toHexColor(), + customColors.baseColors.neutral2.toHexColor(), + customColors.baseColors.error.toHexColor(), + customColors.lightScheme.primary.toHexColor(), + customColors.lightScheme.onPrimary.toHexColor(), + customColors.lightScheme.primaryContainer.toHexColor(), + customColors.lightScheme.onPrimaryContainer.toHexColor(), + customColors.lightScheme.secondary.toHexColor(), + customColors.lightScheme.onSecondary.toHexColor(), + customColors.lightScheme.secondaryContainer.toHexColor(), + customColors.lightScheme.onSecondaryContainer.toHexColor(), + customColors.lightScheme.tertiary.toHexColor(), + customColors.lightScheme.onTertiary.toHexColor(), + customColors.lightScheme.tertiaryContainer.toHexColor(), + customColors.lightScheme.onTertiaryContainer.toHexColor(), + customColors.lightScheme.error.toHexColor(), + customColors.lightScheme.onError.toHexColor(), + customColors.lightScheme.errorContainer.toHexColor(), + customColors.lightScheme.onErrorContainer.toHexColor(), + customColors.lightScheme.surface.toHexColor(), + customColors.lightScheme.onSurface.toHexColor(), + customColors.lightScheme.onSurfaceVariant.toHexColor(), + customColors.lightScheme.outline.toHexColor(), + customColors.lightScheme.outlineVariant.toHexColor(), + customColors.lightScheme.inverseSurface.toHexColor(), + customColors.lightScheme.inverseOnSurface.toHexColor(), + customColors.lightScheme.inversePrimary.toHexColor(), + customColors.lightScheme.surfaceDim.toHexColor(), + customColors.lightScheme.surfaceBright.toHexColor(), + customColors.lightScheme.surfaceContainerLowest.toHexColor(), + customColors.lightScheme.surfaceContainerLow.toHexColor(), + customColors.lightScheme.surfaceContainer.toHexColor(), + customColors.lightScheme.surfaceContainerHigh.toHexColor(), + customColors.lightScheme.surfaceContainerHighest.toHexColor(), + customColors.lightScheme.background.toHexColor(), + customColors.lightScheme.onBackground.toHexColor(), + customColors.lightScheme.surfaceTint.toHexColor(), + customColors.lightScheme.scrim.toHexColor(), + customColors.lightScheme.surfaceVariant.toHexColor(), + + customColors.darkScheme.primary.toHexColor(), + customColors.darkScheme.onPrimary.toHexColor(), + customColors.darkScheme.primaryContainer.toHexColor(), + customColors.darkScheme.onPrimaryContainer.toHexColor(), + customColors.darkScheme.secondary.toHexColor(), + customColors.darkScheme.onSecondary.toHexColor(), + customColors.darkScheme.secondaryContainer.toHexColor(), + customColors.darkScheme.onSecondaryContainer.toHexColor(), + customColors.darkScheme.tertiary.toHexColor(), + customColors.darkScheme.onTertiary.toHexColor(), + customColors.darkScheme.tertiaryContainer.toHexColor(), + customColors.darkScheme.onTertiaryContainer.toHexColor(), + customColors.darkScheme.error.toHexColor(), + customColors.darkScheme.onError.toHexColor(), + customColors.darkScheme.errorContainer.toHexColor(), + customColors.darkScheme.onErrorContainer.toHexColor(), + customColors.darkScheme.surface.toHexColor(), + customColors.darkScheme.onSurface.toHexColor(), + customColors.darkScheme.onSurfaceVariant.toHexColor(), + customColors.darkScheme.outline.toHexColor(), + customColors.darkScheme.outlineVariant.toHexColor(), + customColors.darkScheme.inverseSurface.toHexColor(), + customColors.darkScheme.inverseOnSurface.toHexColor(), + customColors.darkScheme.inversePrimary.toHexColor(), + customColors.darkScheme.surfaceDim.toHexColor(), + customColors.darkScheme.surfaceBright.toHexColor(), + customColors.darkScheme.surfaceContainerLowest.toHexColor(), + customColors.darkScheme.surfaceContainerLow.toHexColor(), + customColors.darkScheme.surfaceContainer.toHexColor(), + customColors.darkScheme.surfaceContainerHigh.toHexColor(), + customColors.darkScheme.surfaceContainerHighest.toHexColor(), + customColors.darkScheme.background.toHexColor(), + customColors.darkScheme.onBackground.toHexColor(), + customColors.darkScheme.surfaceTint.toHexColor(), + customColors.darkScheme.scrim.toHexColor(), + customColors.darkScheme.surfaceVariant.toHexColor(), + ) + ) + } + + fun Int.toHexColor(): String { + return "#${toUInt().toString(16).padStart(6, '0')}" + } +} \ No newline at end of file