Move database module from :core to :data
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
/
|
||||
</manifest>
|
||||
@@ -0,0 +1,156 @@
|
||||
@file:Suppress("ClassName")
|
||||
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import de.mm20.launcher2.database.daos.ThemeDao
|
||||
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
|
||||
import de.mm20.launcher2.database.migrations.Migration_13_14
|
||||
import de.mm20.launcher2.database.migrations.Migration_14_15
|
||||
import de.mm20.launcher2.database.migrations.Migration_15_16
|
||||
import de.mm20.launcher2.database.migrations.Migration_16_17
|
||||
import de.mm20.launcher2.database.migrations.Migration_17_18
|
||||
import de.mm20.launcher2.database.migrations.Migration_18_19
|
||||
import de.mm20.launcher2.database.migrations.Migration_19_20
|
||||
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
|
||||
import de.mm20.launcher2.database.migrations.Migration_9_10
|
||||
import de.mm20.launcher2.ktx.toBytes
|
||||
import java.util.UUID
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
ForecastEntity::class,
|
||||
SavedSearchableEntity::class,
|
||||
CurrencyEntity::class,
|
||||
IconEntity::class,
|
||||
IconPackEntity::class,
|
||||
WidgetEntity::class,
|
||||
CustomAttributeEntity::class,
|
||||
SearchActionEntity::class,
|
||||
ThemeEntity::class,
|
||||
], version = 25, exportSchema = true
|
||||
)
|
||||
@TypeConverters(ComponentNameConverter::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun weatherDao(): WeatherDao
|
||||
abstract fun iconDao(): IconDao
|
||||
|
||||
abstract fun searchableDao(): SearchableDao
|
||||
abstract fun widgetDao(): WidgetDao
|
||||
abstract fun currencyDao(): CurrencyDao
|
||||
abstract fun backupDao(): BackupRestoreDao
|
||||
abstract fun customAttrsDao(): CustomAttrsDao
|
||||
|
||||
abstract fun searchActionDao(): SearchActionDao
|
||||
|
||||
abstract fun themeDao(): ThemeDao
|
||||
|
||||
companion object {
|
||||
private var _instance: AppDatabase? = null
|
||||
fun getInstance(context: Context): AppDatabase {
|
||||
val instance = _instance
|
||||
?: Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "room")
|
||||
//.fallbackToDestructiveMigration()
|
||||
.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`, `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,
|
||||
)
|
||||
)
|
||||
|
||||
db.execSQL(
|
||||
"INSERT INTO Widget (`type`, `position`, `id`) VALUES " +
|
||||
"('weather', 0, ?)," +
|
||||
"('music', 1, ?)," +
|
||||
"('calendar', 2, ?);",
|
||||
arrayOf(
|
||||
UUID.randomUUID().toBytes(),
|
||||
UUID.randomUUID().toBytes(),
|
||||
UUID.randomUUID().toBytes()
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
.addMigrations(
|
||||
Migration_6_7(),
|
||||
Migration_7_8(),
|
||||
Migration_8_9(),
|
||||
Migration_9_10(),
|
||||
Migration_10_11(),
|
||||
Migration_11_12(),
|
||||
Migration_12_13(),
|
||||
Migration_13_14(),
|
||||
Migration_14_15(),
|
||||
Migration_15_16(),
|
||||
Migration_16_17(),
|
||||
Migration_17_18(),
|
||||
Migration_18_19(),
|
||||
Migration_19_20(),
|
||||
Migration_20_21(),
|
||||
Migration_21_22(),
|
||||
Migration_22_23(),
|
||||
Migration_23_24(),
|
||||
Migration_24_25(context),
|
||||
).build()
|
||||
if (_instance == null) _instance = instance
|
||||
return instance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import de.mm20.launcher2.database.entities.CustomAttributeEntity
|
||||
import de.mm20.launcher2.database.entities.SavedSearchableEntity
|
||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||
import de.mm20.launcher2.database.entities.WebsearchEntity
|
||||
import de.mm20.launcher2.database.entities.WidgetEntity
|
||||
|
||||
@Dao
|
||||
interface BackupRestoreDao {
|
||||
|
||||
@Query("DELETE FROM Searchable")
|
||||
suspend fun wipeFavorites()
|
||||
|
||||
@Query("SELECT * FROM Searchable LIMIT :limit OFFSET :offset")
|
||||
suspend fun exportFavorites(limit: Int, offset: Int): List<SavedSearchableEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun importFavorites(items: List<SavedSearchableEntity>)
|
||||
|
||||
@Query("DELETE FROM Widget")
|
||||
suspend fun wipeWidgets()
|
||||
|
||||
@Query("SELECT * FROM Widget LIMIT :limit OFFSET :offset")
|
||||
suspend fun exportWidgets(limit: Int, offset: Int): List<WidgetEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun importWidgets(items: List<WidgetEntity>)
|
||||
|
||||
@Query("DELETE FROM SearchAction")
|
||||
suspend fun wipeSearchActions()
|
||||
|
||||
@Query("SELECT * FROM SearchAction LIMIT :limit OFFSET :offset")
|
||||
suspend fun exportSearchActions(limit: Int, offset: Int): List<SearchActionEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun importSearchActions(items: List<SearchActionEntity>)
|
||||
|
||||
@Query("DELETE FROM CustomAttributes")
|
||||
suspend fun wipeCustomAttributes()
|
||||
|
||||
@Query("SELECT * FROM CustomAttributes LIMIT :limit OFFSET :offset")
|
||||
suspend fun exportCustomAttributes(limit: Int, offset: Int): List<CustomAttributeEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun importCustomAttributes(items: List<CustomAttributeEntity>)
|
||||
|
||||
@Query("DELETE FROM CustomAttributes WHERE (type = 'tag' OR type = 'label') AND NOT EXISTS(SELECT 1 FROM Searchable WHERE CustomAttributes.key = Searchable.key)")
|
||||
suspend fun cleanUp(): Int
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import android.content.ComponentName
|
||||
import androidx.room.TypeConverter
|
||||
import org.json.JSONArray
|
||||
|
||||
class ComponentNameConverter {
|
||||
@TypeConverter
|
||||
fun toString(componentName: ComponentName?): String? {
|
||||
return componentName?.flattenToString()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun toComponentName(string: String?) : ComponentName? {
|
||||
string ?: return null
|
||||
return ComponentName.unflattenFromString(string)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StringListConverter {
|
||||
@TypeConverter
|
||||
fun toString(list: List<String>): String {
|
||||
val json = JSONArray()
|
||||
list.forEach { json.put(it) }
|
||||
return json.toString()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun toStringList(string: String): List<String> {
|
||||
val json = JSONArray(string)
|
||||
return (0..json.length()).map { json.getString(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.*
|
||||
import de.mm20.launcher2.database.entities.CurrencyEntity
|
||||
|
||||
@Dao
|
||||
interface CurrencyDao {
|
||||
|
||||
@Query("SELECT value FROM Currency WHERE symbol = :symbol")
|
||||
fun getExchangeRate(symbol: String) : Double?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(currency: CurrencyEntity)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertAll(currencies: List<CurrencyEntity>)
|
||||
|
||||
@Query("SELECT * FROM Currency WHERE symbol = :symbol")
|
||||
fun getCurrency(symbol: String) : CurrencyEntity?
|
||||
|
||||
@Query("SELECT * FROM Currency WHERE symbol IN (:symbols)")
|
||||
fun getCurrencies(symbols: List<String>) : List<CurrencyEntity>
|
||||
|
||||
@Query("SELECT * FROM Currency")
|
||||
fun getAllCurrencies() : List<CurrencyEntity>
|
||||
|
||||
@Transaction
|
||||
fun exists(symbol: String): Boolean {
|
||||
return getCurrency(symbol) != null
|
||||
}
|
||||
|
||||
@Query("SELECT lastUpdate FROM Currency WHERE symbol = :symbol")
|
||||
fun getLastUpdate(symbol: String) : Long
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import de.mm20.launcher2.database.entities.CustomAttributeEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CustomAttrsDao {
|
||||
@Query("SELECT * FROM CustomAttributes WHERE type = :type AND `key` = :key LIMIT 1")
|
||||
fun getCustomAttribute(key: String, type: String) : Flow<CustomAttributeEntity?>
|
||||
|
||||
@Query("DELETE FROM CustomAttributes WHERE type = :type AND `key` = :key")
|
||||
fun clearCustomAttribute(key: String, type: String)
|
||||
|
||||
@Insert
|
||||
fun setCustomAttribute(entity: CustomAttributeEntity)
|
||||
|
||||
@Insert
|
||||
suspend fun insertCustomAttributes(entities: List<CustomAttributeEntity>)
|
||||
|
||||
@Query("SELECT * FROM CustomAttributes WHERE type = :type AND `key` IN (:keys)")
|
||||
fun getCustomAttributes(keys: List<String>, type: String) : Flow<List<CustomAttributeEntity>>
|
||||
|
||||
@Query("SELECT DISTINCT `key` FROM CustomAttributes WHERE (type = 'label' OR type = 'tag') AND value LIKE :query")
|
||||
fun search(query: String): Flow<List<String>>
|
||||
|
||||
@Transaction
|
||||
suspend fun setTags(key: String, tags: List<CustomAttributeEntity>) {
|
||||
clearCustomAttribute(key, "tag")
|
||||
insertCustomAttributes(tags)
|
||||
}
|
||||
|
||||
@Query("SELECT DISTINCT value FROM CustomAttributes WHERE type = 'tag' AND value LIKE :like ORDER BY value")
|
||||
fun getAllTagsLike(like: String): Flow<List<String>>
|
||||
|
||||
@Query("SELECT DISTINCT value FROM CustomAttributes WHERE type = 'tag' ORDER BY value")
|
||||
fun getAllTags(): Flow<List<String>>
|
||||
|
||||
@Query("SELECT `key` FROM CustomAttributes WHERE type = 'tag' AND value = :tag")
|
||||
fun getItemsWithTag(tag: String): Flow<List<String>>
|
||||
|
||||
@Transaction
|
||||
suspend fun setItemsWithTag(tag: String, items: List<String>) {
|
||||
deleteTag(tag)
|
||||
insertCustomAttributes(items.map { CustomAttributeEntity(it, "tag", tag) })
|
||||
}
|
||||
|
||||
@Transaction
|
||||
suspend fun addTag(key: String, tag: String) {
|
||||
removeTag(key, tag)
|
||||
insertTag(key, tag)
|
||||
}
|
||||
|
||||
@Query("DELETE FROM CustomAttributes WHERE type = 'tag' AND `key` = :key AND value = :tag")
|
||||
suspend fun removeTag(key: String, tag: String)
|
||||
|
||||
@Query("INSERT INTO CustomAttributes (`key`, value, type) VALUES (:key, :tag, 'tag')")
|
||||
suspend fun insertTag(key: String, tag: String)
|
||||
|
||||
@Query("UPDATE CustomAttributes SET value = :newName WHERE value = :oldName AND type = 'tag'")
|
||||
suspend fun renameTag(oldName: String, newName: String)
|
||||
|
||||
@Query("DELETE FROM CustomAttributes WHERE type = 'tag' AND value = :tag")
|
||||
suspend fun deleteTag(tag: String)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.*
|
||||
import de.mm20.launcher2.database.entities.IconEntity
|
||||
import de.mm20.launcher2.database.entities.IconPackEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface IconDao {
|
||||
@Insert
|
||||
suspend fun insertAll(icons: List<IconEntity>)
|
||||
|
||||
@Query("SELECT * FROM Icons WHERE packageName = :packageName AND (activityName = :activityName OR activityName IS NULL) AND iconPack = :iconPack AND type IN ('app', 'calendar', 'clock') ORDER BY type DESC LIMIT 1")
|
||||
suspend fun getIcon(packageName: String, activityName: String?, iconPack: String): IconEntity?
|
||||
|
||||
@Query("SELECT * FROM Icons WHERE packageName = :packageName AND (activityName = :activityName OR activityName IS NULL) AND type IN ('app', 'calendar', 'clock')")
|
||||
suspend fun getIconsFromAllPacks(packageName: String, activityName: String): List<IconEntity>
|
||||
|
||||
@Query("SELECT * FROM Icons WHERE type IN ('app', 'calendar', 'clock') AND (drawable LIKE :drawableQuery OR packageName LIKE :componentQuery OR activityName LIKE :componentQuery OR name LIKE :nameQuery) AND (:iconPack IS NULL OR iconPack = :iconPack) GROUP BY drawable ORDER BY iconPack, drawable LIMIT :limit")
|
||||
suspend fun searchIconPackIcons(
|
||||
componentQuery: String,
|
||||
nameQuery: String,
|
||||
drawableQuery: String,
|
||||
iconPack: String?,
|
||||
limit: Int = 100
|
||||
): List<IconEntity>
|
||||
|
||||
@Query("DELETE FROM Icons WHERE iconPack = :iconPack")
|
||||
fun deleteIcons(iconPack: String)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun installIconPack(iconPack: IconPackEntity)
|
||||
|
||||
@Query("SELECT * FROM IconPack ORDER BY name ASC")
|
||||
fun getInstalledIconPacks(): Flow<List<IconPackEntity>>
|
||||
|
||||
@Query("SELECT * FROM IconPack WHERE packageName = :packageName LIMIT 1")
|
||||
suspend fun getIconPack(packageName: String): IconPackEntity?
|
||||
|
||||
@Delete
|
||||
fun deleteIconPack(iconPack: IconPackEntity)
|
||||
|
||||
@Query("SELECT drawable FROM Icons WHERE iconPack = :pack AND type = 'iconback'")
|
||||
suspend fun getIconBacks(pack: String): List<String>
|
||||
|
||||
@Query("SELECT drawable FROM Icons WHERE iconPack = :pack AND type = 'iconupon'")
|
||||
suspend fun getIconUpons(pack: String): List<String>
|
||||
|
||||
@Query("SELECT drawable FROM Icons WHERE iconPack = :pack AND type = 'iconmask'")
|
||||
suspend fun getIconMasks(pack: String): List<String>
|
||||
|
||||
@Query("SELECT scale FROM IconPack WHERE packageName = :pack")
|
||||
suspend fun getScale(pack: String): Float?
|
||||
|
||||
@Query("DELETE FROM Icons WHERE iconPack NOT IN (:keep)")
|
||||
suspend fun deleteIconsNotIn(keep: List<String>)
|
||||
|
||||
@Query("DELETE FROM IconPack WHERE packageName NOT IN (:keep)")
|
||||
suspend fun deleteIconPacksNotIn(keep: List<String>)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.mm20.launcher2.database
|
||||
import org.koin.dsl.module
|
||||
|
||||
val databaseModule = module {
|
||||
single { AppDatabase.getInstance(get()) }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SearchActionDao {
|
||||
@Query("SELECT * FROM SearchAction ORDER BY position ASC")
|
||||
fun getSearchActions(): Flow<List<SearchActionEntity>>
|
||||
|
||||
@Transaction
|
||||
suspend fun replaceAll(actions: List<SearchActionEntity>) {
|
||||
deleteAll()
|
||||
insertAll(actions)
|
||||
}
|
||||
|
||||
@Query("DELETE FROM `SearchAction`")
|
||||
suspend fun deleteAll()
|
||||
|
||||
@Insert
|
||||
suspend fun insertAll(actions: List<SearchActionEntity>)
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Update
|
||||
import androidx.room.Upsert
|
||||
import de.mm20.launcher2.database.entities.SavedSearchableEntity
|
||||
import de.mm20.launcher2.database.entities.SavedSearchableUpdatePinEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SearchableDao {
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insert(searchable: SavedSearchableEntity)
|
||||
|
||||
@Upsert(entity = SavedSearchableEntity::class)
|
||||
suspend fun upsert(searchable: SavedSearchableEntity)
|
||||
|
||||
@Upsert(entity = SavedSearchableEntity::class)
|
||||
suspend fun upsert(searchable: List<SavedSearchableUpdatePinEntity>)
|
||||
|
||||
@Update(entity = SavedSearchableEntity::class)
|
||||
suspend fun update(searchable: SavedSearchableUpdatePinEntity)
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM Searchable " +
|
||||
"WHERE (" +
|
||||
"(:manuallySorted AND pinPosition > 1) OR " +
|
||||
"(:automaticallySorted AND pinPosition = 1) OR" +
|
||||
"(:frequentlyUsed AND pinPosition = 0 AND launchCount > 0) OR " +
|
||||
"(:hidden AND hidden = 1)" +
|
||||
") AND hidden = :hidden ORDER BY pinPosition DESC, weight DESC, launchCount DESC LIMIT :limit"
|
||||
)
|
||||
fun get(
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
hidden: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<SavedSearchableEntity>>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM Searchable " +
|
||||
"WHERE (`type` IN (:includeTypes)) AND " +
|
||||
"(" +
|
||||
"(:manuallySorted AND pinPosition > 1) OR " +
|
||||
"(:automaticallySorted AND pinPosition = 1) OR" +
|
||||
"(:frequentlyUsed AND pinPosition = 0 AND launchCount > 0) OR " +
|
||||
"(:hidden AND hidden = 1)" +
|
||||
") AND hidden = :hidden ORDER BY pinPosition DESC, weight DESC, launchCount DESC LIMIT :limit"
|
||||
)
|
||||
fun getIncludeTypes(
|
||||
includeTypes: List<String>?,
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
hidden: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<SavedSearchableEntity>>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM Searchable " +
|
||||
"WHERE (`type` NOT IN (:excludeTypes)) AND " +
|
||||
"(" +
|
||||
"(:manuallySorted AND pinPosition > 1) OR " +
|
||||
"(:automaticallySorted AND pinPosition = 1) OR" +
|
||||
"(:frequentlyUsed AND pinPosition = 0 AND launchCount > 0) OR " +
|
||||
"(:hidden AND hidden = 1)" +
|
||||
") AND hidden = :hidden ORDER BY pinPosition DESC, weight DESC, launchCount DESC LIMIT :limit"
|
||||
)
|
||||
fun getExcludeTypes(
|
||||
excludeTypes: List<String>?,
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
hidden: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<SavedSearchableEntity>>
|
||||
|
||||
@Query(
|
||||
"SELECT `key` FROM Searchable " +
|
||||
"WHERE (" +
|
||||
"(:manuallySorted AND pinPosition > 1) OR " +
|
||||
"(:automaticallySorted AND pinPosition = 1) OR" +
|
||||
"(:frequentlyUsed AND pinPosition = 0 AND launchCount > 0) OR " +
|
||||
"(:hidden AND hidden = 1)" +
|
||||
") AND hidden = :hidden ORDER BY pinPosition DESC, weight DESC, launchCount DESC LIMIT :limit"
|
||||
)
|
||||
fun getKeys(
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
hidden: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<String>>
|
||||
|
||||
@Query(
|
||||
"SELECT `key` FROM Searchable " +
|
||||
"WHERE (`type` IN (:includeTypes)) AND " +
|
||||
"(" +
|
||||
"(:manuallySorted AND pinPosition > 1) OR " +
|
||||
"(:automaticallySorted AND pinPosition = 1) OR" +
|
||||
"(:frequentlyUsed AND pinPosition = 0 AND launchCount > 0) OR " +
|
||||
"(:hidden AND hidden = 1)" +
|
||||
") AND hidden = :hidden ORDER BY pinPosition DESC, weight DESC, launchCount DESC LIMIT :limit"
|
||||
)
|
||||
fun getKeysIncludeTypes(
|
||||
includeTypes: List<String>?,
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
hidden: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<String>>
|
||||
|
||||
@Query(
|
||||
"SELECT `key` FROM Searchable " +
|
||||
"WHERE (`type` NOT IN (:excludeTypes)) AND " +
|
||||
"(" +
|
||||
"(:manuallySorted AND pinPosition > 1) OR " +
|
||||
"(:automaticallySorted AND pinPosition = 1) OR" +
|
||||
"(:frequentlyUsed AND pinPosition = 0 AND launchCount > 0) OR " +
|
||||
"(:hidden AND hidden = 1)" +
|
||||
") AND hidden = :hidden ORDER BY pinPosition DESC, weight DESC, launchCount DESC LIMIT :limit"
|
||||
)
|
||||
fun getKeysExcludeTypes(
|
||||
excludeTypes: List<String>?,
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
hidden: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<String>>
|
||||
|
||||
@Query("SELECT * FROM Searchable WHERE `key` IN (:keys)")
|
||||
suspend fun getByKeys(keys: List<String>): List<SavedSearchableEntity>
|
||||
|
||||
@Query("SELECT * FROM Searchable WHERE `key` = :key")
|
||||
fun getByKey(key: String): Flow<SavedSearchableEntity?>
|
||||
|
||||
@Transaction
|
||||
suspend fun touch(item: SavedSearchableEntity, alpha: Double) {
|
||||
incrementLaunchCount(item.key)
|
||||
increaseWeightWhere(item.key, alpha)
|
||||
reduceWeightExcept(item.key, alpha)
|
||||
insert(item)
|
||||
}
|
||||
|
||||
@Query("UPDATE Searchable SET launchCount = launchCount + 1 WHERE `key` = :key")
|
||||
fun incrementLaunchCount(key: String)
|
||||
|
||||
@Query("UPDATE Searchable SET `weight` = `weight` * (1.0 - :alpha) WHERE `key` != :key")
|
||||
fun reduceWeightExcept(key: String, alpha: Double)
|
||||
|
||||
@Query("UPDATE Searchable SET `weight` = `weight` + :alpha * (1.0 - `weight`) WHERE `key` == :key")
|
||||
fun increaseWeightWhere(key: String, alpha: Double)
|
||||
|
||||
@Query("DELETE FROM Searchable WHERE `key` = :key")
|
||||
suspend fun delete(key: String)
|
||||
|
||||
@Query("UPDATE Searchable SET `pinPosition` = 0")
|
||||
suspend fun unpinAll()
|
||||
|
||||
@Query("SELECT `key` FROM Searchable WHERE `key` IN (:keys) AND launchCount > 0 ORDER BY launchCount DESC, pinPosition DESC")
|
||||
fun sortByRelevance(keys: List<String>): Flow<List<String>>
|
||||
|
||||
@Query("SELECT `key` FROM Searchable WHERE `key` IN (:keys) ORDER BY `weight` DESC, pinPosition DESC")
|
||||
fun sortByWeight(keys: List<String>): Flow<List<String>>
|
||||
|
||||
@Query("SELECT hidden FROM Searchable WHERE `key` = :key UNION SELECT 0 as hidden ORDER BY hidden DESC LIMIT 1")
|
||||
fun isHidden(key: String): Flow<Boolean>
|
||||
|
||||
@Query("SELECT pinPosition FROM Searchable WHERE `key` = :key UNION SELECT 0 as pinPosition ORDER BY pinPosition DESC LIMIT 1")
|
||||
fun isPinned(key: String): Flow<Boolean>
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.*
|
||||
import de.mm20.launcher2.database.entities.ForecastEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface WeatherDao {
|
||||
@Query("SELECT * FROM ${ForecastEntity.TABLE_NAME} ORDER BY timestamp ASC")
|
||||
fun getForecasts(): Flow<List<ForecastEntity>>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertAll(forecasts: List<ForecastEntity>)
|
||||
|
||||
@Query("DELETE FROM ${ForecastEntity.TABLE_NAME}")
|
||||
fun deleteAll()
|
||||
|
||||
@Transaction
|
||||
fun replaceAll(forecasts: List<ForecastEntity>) {
|
||||
deleteAll()
|
||||
insertAll(forecasts)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import de.mm20.launcher2.database.entities.WidgetEntity
|
||||
import de.mm20.launcher2.database.entities.PartialWidgetEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.util.UUID
|
||||
|
||||
@Dao
|
||||
interface WidgetDao {
|
||||
@Query("SELECT * FROM Widget WHERE parentId IS NULL ORDER BY position ASC LIMIT :limit OFFSET :offset")
|
||||
fun queryRoot(limit: Int, offset: Int): Flow<List<WidgetEntity>>
|
||||
|
||||
@Query("SELECT * FROM Widget WHERE parentId = :parentId ORDER BY position ASC LIMIT :limit OFFSET :offset")
|
||||
fun queryByParent(parentId: UUID,limit: Int, offset: Int): Flow<List<WidgetEntity>>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(widget: WidgetEntity)
|
||||
|
||||
@Insert
|
||||
suspend fun insert(widgets: List<WidgetEntity>)
|
||||
|
||||
@Update(entity = WidgetEntity::class)
|
||||
suspend fun patch(widget: PartialWidgetEntity)
|
||||
|
||||
@Update(entity = WidgetEntity::class)
|
||||
suspend fun patch(widgets: List<PartialWidgetEntity>)
|
||||
|
||||
@Update
|
||||
suspend fun update(widget: WidgetEntity)
|
||||
|
||||
@Update
|
||||
suspend fun update(widgets: List<WidgetEntity>)
|
||||
|
||||
@Query("DELETE FROM Widget WHERE id = :id")
|
||||
suspend fun delete(id: UUID)
|
||||
|
||||
@Query("DELETE FROM WIDGET WHERE id IN (:ids)")
|
||||
suspend fun delete(ids: List<UUID>)
|
||||
|
||||
@Query("DELETE FROM Widget WHERE parentId = :parentId")
|
||||
suspend fun deleteByParent(parentId: UUID)
|
||||
|
||||
@Query("DELETE FROM Widget WHERE parentId IS NULL")
|
||||
suspend fun deleteRoot()
|
||||
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM Widget WHERE type = :type)")
|
||||
fun exists(type: String): Flow<Boolean>
|
||||
|
||||
@Query("SELECT COUNT(*) FROM Widget WHERE type = :type")
|
||||
fun count(type: String): Flow<Int>
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.mm20.launcher2.database.daos
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import de.mm20.launcher2.database.entities.ThemeEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.util.UUID
|
||||
|
||||
@Dao
|
||||
interface ThemeDao {
|
||||
@Query("SELECT * FROM Theme")
|
||||
fun getAll(): Flow<List<ThemeEntity>>
|
||||
|
||||
@Query("SELECT * FROM Theme WHERE id = :id LIMIT 1")
|
||||
fun get(id: UUID): Flow<ThemeEntity?>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(theme: ThemeEntity)
|
||||
|
||||
@Update
|
||||
suspend fun update(theme: ThemeEntity)
|
||||
|
||||
@Query("DELETE FROM Theme WHERE id = :id")
|
||||
suspend fun delete(id: UUID)
|
||||
|
||||
@Query("DELETE FROM Theme")
|
||||
suspend fun deleteAll()
|
||||
|
||||
@Insert
|
||||
fun insertAll(themes: List<ThemeEntity>)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "Currency")
|
||||
data class CurrencyEntity(
|
||||
@PrimaryKey val symbol: String,
|
||||
val value: Double,
|
||||
val lastUpdate: Long
|
||||
)
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "CustomAttributes")
|
||||
data class CustomAttributeEntity(
|
||||
val key: String,
|
||||
val type: String,
|
||||
val value: String,
|
||||
@PrimaryKey(autoGenerate = true) val id: Int? = null,
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = ForecastEntity.TABLE_NAME)
|
||||
data class ForecastEntity(
|
||||
@PrimaryKey val timestamp: Long,
|
||||
val temperature: Double,
|
||||
val minTemp: Double = -1.0,
|
||||
val maxTemp: Double = -1.0,
|
||||
val pressure: Double = -1.0,
|
||||
val humidity: Double = -1.0,
|
||||
val icon: Int,
|
||||
val condition: String,
|
||||
val clouds: Int = -1,
|
||||
val windSpeed: Double = -1.0,
|
||||
val windDirection: Double = -1.0,
|
||||
@ColumnInfo(name = "rain") val precipitation: Double = -1.0,
|
||||
val snow: Double = -1.0,
|
||||
val night: Boolean = false,
|
||||
val location: String,
|
||||
val provider: String,
|
||||
val providerUrl: String = "",
|
||||
@ColumnInfo(name = "rainProbability") val precipProbability: Int = -1,
|
||||
val snowProbability: Int = -1,
|
||||
val updateTime: Long
|
||||
) {
|
||||
companion object {
|
||||
const val TABLE_NAME = "forecasts"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "Icons")
|
||||
data class IconEntity(
|
||||
val type: String,
|
||||
val packageName: String? = null,
|
||||
val activityName: String? = null,
|
||||
val drawable: String?,
|
||||
val extras: String? = null,
|
||||
val iconPack: String,
|
||||
val name: String? = null,
|
||||
val themed: Boolean = false,
|
||||
@PrimaryKey(autoGenerate = true) val id : Long? = null
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "IconPack")
|
||||
data class IconPackEntity(
|
||||
val name: String,
|
||||
@PrimaryKey val packageName: String,
|
||||
val version: String,
|
||||
var scale: Float = 1f,
|
||||
val themed: Boolean = false,
|
||||
)
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "Searchable")
|
||||
data class SavedSearchableEntity(
|
||||
@PrimaryKey val key: String,
|
||||
val type: String,
|
||||
@ColumnInfo(name = "searchable") val serializedSearchable: String,
|
||||
@ColumnInfo(defaultValue = "0") val launchCount: Int,
|
||||
@ColumnInfo(defaultValue = "0") val pinPosition: Int,
|
||||
@ColumnInfo(defaultValue = "0") val hidden: Boolean,
|
||||
@ColumnInfo(defaultValue = "0.0") val weight: Double
|
||||
)
|
||||
|
||||
data class SavedSearchableUpdatePinEntity(
|
||||
val key: String,
|
||||
val type: String,
|
||||
@ColumnInfo(name = "searchable") val serializedSearchable: String,
|
||||
val pinPosition: Int? = null,
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "SearchAction")
|
||||
data class SearchActionEntity(
|
||||
@PrimaryKey val position: Int,
|
||||
val type: String,
|
||||
val data: String? = null,
|
||||
val label: String? = null,
|
||||
val icon: Int? = null,
|
||||
val color: Int? = null,
|
||||
val customIcon: String? = null,
|
||||
val options: String? = null,
|
||||
)
|
||||
@@ -0,0 +1,92 @@
|
||||
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 name: String,
|
||||
|
||||
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?,
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "Websearch")
|
||||
data class WebsearchEntity(
|
||||
var urlTemplate: String,
|
||||
var label: String,
|
||||
var color: Int,
|
||||
var icon: String?,
|
||||
var encoding: Int?,
|
||||
@PrimaryKey(autoGenerate = true) val id: Long?
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.util.UUID
|
||||
|
||||
|
||||
@Entity(tableName = "Widget")
|
||||
data class WidgetEntity(
|
||||
val type: String,
|
||||
var config: String?,
|
||||
var position: Int,
|
||||
@PrimaryKey val id: UUID,
|
||||
val parentId: UUID? = null,
|
||||
)
|
||||
|
||||
/**
|
||||
* Partial entity for updating and deleting
|
||||
*/
|
||||
data class PartialWidgetEntity(
|
||||
val type: String,
|
||||
var config: String?,
|
||||
@PrimaryKey val id: UUID,
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_10_11 : Migration(10, 11) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `temp` (`key` TEXT NOT NULL, `searchable` TEXT NOT NULL, `launchCount` INTEGER NOT NULL, `pinned` INTEGER NOT NULL, `hidden` INTEGER NOT NULL, PRIMARY KEY(`key`))")
|
||||
database.execSQL("INSERT INTO `temp` SELECT `key`, `searchable`, `launchCount`, `pinned`, `hidden` FROM `Searchable`")
|
||||
database.execSQL("DROP TABLE `Searchable`")
|
||||
database.execSQL("ALTER TABLE `temp` RENAME TO `Searchable`")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_11_12 : Migration(11, 12) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `Currency` (`symbol` TEXT NOT NULL, `value` REAL NOT NULL, `lastUpdate` INTEGER NOT NULL, PRIMARY KEY(`symbol`))")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_12_13 : Migration(12, 13) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `Plugin` (`packageName` TEXT NOT NULL, `data` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`packageName`, `data`))")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_13_14 : Migration(13, 14) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS `Plugins`;")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_14_15 : Migration(14, 15) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_15_16 : Migration(15, 16) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `CustomAttributes` (
|
||||
`key` TEXT NOT NULL,
|
||||
`type` TEXT NOT NULL,
|
||||
`value` TEXT NOT NULL,
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT
|
||||
)
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_16_17 : Migration(16, 17) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Websearch ADD COLUMN encoding INTEGER")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_17_18 : Migration(17, 18) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Searchable ADD COLUMN type TEXT NOT NULL DEFAULT ''")
|
||||
database.execSQL(
|
||||
"""
|
||||
UPDATE Searchable
|
||||
SET type = SUBSTR(`key`, 0, INSTR(`key`, '://')),
|
||||
searchable = SUBSTR(`searchable`, INSTR(`searchable`, '#') + 1)
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.core.database.getStringOrNull
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
|
||||
class Migration_18_19 : Migration(18, 19) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
val websearches =
|
||||
database.query("SELECT label, urlTemplate, color, icon, encoding FROM `Websearch` ORDER BY label ASC")
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `SearchAction` (`position` INTEGER NOT NULL, `type` TEXT NOT NULL, `data` TEXT, `label` TEXT, `icon` INTEGER, `color` INTEGER, `customIcon` TEXT, `options` TEXT, PRIMARY KEY(`position`))"
|
||||
)
|
||||
database.execSQL("INSERT INTO `SearchAction` (`position`, `type`) VALUES" +
|
||||
"(0, 'call')," +
|
||||
"(1, 'message')," +
|
||||
"(2, 'email')," +
|
||||
"(3, 'contact')," +
|
||||
"(4, 'alarm')," +
|
||||
"(5, 'timer')," +
|
||||
"(6, 'calendar')," +
|
||||
"(7, 'website')"
|
||||
)
|
||||
var position = 8
|
||||
while (websearches.moveToNext()) {
|
||||
val label = websearches.getString(0)
|
||||
val data = websearches.getString(1)
|
||||
val color = 0
|
||||
val icon = websearches.getStringOrNull(3)
|
||||
val encoding = websearches.getStringOrNull(4)
|
||||
|
||||
val options = encoding?.let{
|
||||
jsonObjectOf("encoding" to encoding).toString()
|
||||
}
|
||||
|
||||
database.execSQL(
|
||||
"INSERT INTO `SearchAction` (`position`, `type`, `data`, `label`, `color`, `icon`, `customIcon`, `options`)" +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
arrayOf(
|
||||
position,
|
||||
"url",
|
||||
data,
|
||||
label,
|
||||
color,
|
||||
if (icon == null) 0 else 1,
|
||||
icon,
|
||||
options
|
||||
)
|
||||
)
|
||||
position++
|
||||
}
|
||||
database.execSQL("DROP TABLE `Websearch`")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_19_20: Migration(19, 20) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE `Icons` RENAME TO `Icons_old`")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS `Icons` (
|
||||
`type` TEXT NOT NULL,
|
||||
`componentName` TEXT,
|
||||
`drawable` TEXT,
|
||||
`iconPack` TEXT NOT NULL,
|
||||
`name` TEXT,
|
||||
`themed` INTEGER NOT NULL DEFAULT 0,
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT)
|
||||
""")
|
||||
database.execSQL("INSERT INTO `Icons` (`type`, `componentName`, `drawable`, `iconPack`, `themed`, `name`) SELECT `type`, `componentName`, `drawable`, `iconPack`, 0, null FROM `Icons_old`")
|
||||
database.execSQL("DROP TABLE `Icons_old`")
|
||||
database.execSQL("ALTER TABLE `IconPack` ADD COLUMN `themed` INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_20_21: Migration(20, 21) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE `Icons`")
|
||||
database.execSQL("DELETE FROM `IconPack`")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS `Icons` (
|
||||
`type` TEXT NOT NULL,
|
||||
`packageName` TEXT,
|
||||
`activityName` TEXT,
|
||||
`drawable` TEXT,
|
||||
`extras` TEXT,
|
||||
`iconPack` TEXT NOT NULL,
|
||||
`name` TEXT,
|
||||
`themed` INTEGER NOT NULL DEFAULT 0,
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT)
|
||||
""")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import android.util.Log
|
||||
import androidx.core.database.getIntOrNull
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_21_22: Migration(21, 22) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
ALTER TABLE `Searchable`
|
||||
ADD `weight` DOUBLE NOT NULL DEFAULT 0.0
|
||||
""")
|
||||
|
||||
database.query("""
|
||||
SELECT MAX(`launchCount`)
|
||||
FROM `Searchable`
|
||||
""")
|
||||
.runCatching {
|
||||
|
||||
if (!this.moveToFirst()) {
|
||||
return
|
||||
}
|
||||
|
||||
this.getIntOrNull(0)
|
||||
?.run {
|
||||
database.execSQL("""
|
||||
UPDATE `Searchable`
|
||||
SET `weight` = `launchCount` / $this
|
||||
""")
|
||||
}
|
||||
|
||||
}.onFailure {
|
||||
Log.e("Migration_21_22", "Setting default values for weight failed", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import de.mm20.launcher2.ktx.toBytes
|
||||
import org.koin.core.component.KoinComponent
|
||||
import java.util.UUID
|
||||
|
||||
class Migration_22_23 : Migration(22, 23), KoinComponent {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Widget RENAME TO Widget_old")
|
||||
database.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Widget` (
|
||||
`type` TEXT NOT NULL,
|
||||
`config` TEXT,
|
||||
`position` INTEGER NOT NULL,
|
||||
`id` BLOB NOT NULL,
|
||||
`parentId` BLOB,
|
||||
PRIMARY KEY(`id`)
|
||||
)
|
||||
"""
|
||||
)
|
||||
val oldWidgets =
|
||||
database.query("SELECT `type`, `data`, `height`, `position` FROM `Widget_old`")
|
||||
while (oldWidgets.moveToNext()) {
|
||||
val oldType = oldWidgets.getString(0)
|
||||
val data = oldWidgets.getString(1)
|
||||
val newType = if (oldType == "3rdparty") "app" else data
|
||||
val height = oldWidgets.getInt(2)
|
||||
val position = oldWidgets.getInt(3)
|
||||
val id = UUID.randomUUID()
|
||||
val config = if (oldType == "3rdparty") {
|
||||
"{\"widgetId\": $data, \"height\": $height}"
|
||||
} else null
|
||||
database.execSQL(
|
||||
"INSERT INTO `Widget` (`type`, `config`, `position`, `id`) VALUES (?, ?, ?, ?)",
|
||||
arrayOf(newType, config, position, id.toBytes())
|
||||
)
|
||||
}
|
||||
oldWidgets.close()
|
||||
database.execSQL("DROP TABLE Widget_old")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_23_24 : Migration(23, 24) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Searchable RENAME TO Searchable_old")
|
||||
database.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Searchable` (
|
||||
`key` TEXT NOT NULL,
|
||||
`type` TEXT NOT NULL,
|
||||
`searchable` TEXT NOT NULL,
|
||||
`launchCount` INTEGER NOT NULL DEFAULT 0,
|
||||
`pinPosition` INTEGER NOT NULL DEFAULT 0,
|
||||
`hidden` INTEGER NOT NULL DEFAULT 0,
|
||||
`weight` DOUBLE NOT NULL DEFAULT 0.0,
|
||||
PRIMARY KEY(`key`)
|
||||
)
|
||||
"""
|
||||
)
|
||||
database.execSQL(
|
||||
"""
|
||||
INSERT INTO `Searchable` (`key`, `type`, `searchable`, `launchCount`, `pinPosition`, `hidden`, `weight`)
|
||||
SELECT `key`, `type`, `searchable`, `launchCount`, `pinned`, `hidden`, `weight` FROM `Searchable_old`
|
||||
"""
|
||||
)
|
||||
database.execSQL("DROP TABLE Searchable_old")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import de.mm20.launcher2.database.R
|
||||
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,
|
||||
`name` TEXT 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(),
|
||||
context.getString(R.string.preference_colors_custom),
|
||||
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')}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_6_7 : Migration(6, 7) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE Searchable2 (`key` TEXT NOT NULL, `searchable` TEXT, `launchCount` INTEGER NOT NULL, `pinned` INTEGER NOT NULL, `hidden` INTEGER NOT NULL, `inAllApps` INTEGER NOT NULL, PRIMARY KEY(`key`))")
|
||||
database.execSQL("INSERT INTO Searchable2 SELECT * FROM Searchable")
|
||||
database.execSQL("DROP TABLE Searchable")
|
||||
database.execSQL("ALTER TABLE Searchable2 RENAME TO Searchable")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import de.mm20.launcher2.database.entities.ForecastEntity
|
||||
|
||||
class Migration_7_8 : Migration(7, 8) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `${ForecastEntity.TABLE_NAME}2` (`timestamp` INTEGER NOT NULL, `temperature` REAL NOT NULL, `minTemp` REAL NOT NULL, `maxTemp` REAL NOT NULL, `pressure` REAL NOT NULL, `humidity` REAL NOT NULL, `icon` INTEGER NOT NULL, `condition` TEXT NOT NULL, `clouds` INTEGER NOT NULL, `windSpeed` REAL NOT NULL, `windDirection` REAL NOT NULL, `rain` REAL NOT NULL, `snow` REAL NOT NULL, `night` INTEGER NOT NULL, `location` TEXT NOT NULL, `provider` TEXT NOT NULL, `providerUrl` TEXT NOT NULL, `rainPropability` INTEGER NOT NULL, `snowProbability` INTEGER NOT NULL, PRIMARY KEY(`timestamp`))")
|
||||
database.execSQL("INSERT INTO ${ForecastEntity.TABLE_NAME}2 SELECT *, -1 as rainPropability, -1 as snowPropability FROM ${ForecastEntity.TABLE_NAME}")
|
||||
database.execSQL("DROP TABLE ${ForecastEntity.TABLE_NAME}")
|
||||
database.execSQL("ALTER TABLE ${ForecastEntity.TABLE_NAME}2 RENAME TO ${ForecastEntity.TABLE_NAME}")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import de.mm20.launcher2.database.entities.ForecastEntity
|
||||
|
||||
class Migration_8_9 : Migration(8, 9) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS `${ForecastEntity.TABLE_NAME}2` (" +
|
||||
"`timestamp` INTEGER NOT NULL, " +
|
||||
"`temperature` REAL NOT NULL, " +
|
||||
"`minTemp` REAL NOT NULL, " +
|
||||
"`maxTemp` REAL NOT NULL, " +
|
||||
"`pressure` REAL NOT NULL, " +
|
||||
"`humidity` REAL NOT NULL, " +
|
||||
"`icon` INTEGER NOT NULL, " +
|
||||
"`condition` TEXT NOT NULL, " +
|
||||
"`clouds` INTEGER NOT NULL, " +
|
||||
"`windSpeed` REAL NOT NULL, " +
|
||||
"`windDirection` REAL NOT NULL, " +
|
||||
"`rain` REAL NOT NULL, " +
|
||||
"`snow` REAL NOT NULL, " +
|
||||
"`night` INTEGER NOT NULL, " +
|
||||
"`location` TEXT NOT NULL, " +
|
||||
"`provider` TEXT NOT NULL, " +
|
||||
"`providerUrl` TEXT NOT NULL, " +
|
||||
"`rainProbability` INTEGER NOT NULL, " +
|
||||
"`snowProbability` INTEGER NOT NULL, " +
|
||||
"`updateTime` INTEGER NOT NULL, " +
|
||||
"PRIMARY KEY(`timestamp`))"
|
||||
)
|
||||
database.execSQL("INSERT INTO ${ForecastEntity.TABLE_NAME}2 SELECT timestamp, temperature, minTemp, maxTemp, pressure, humidity, icon, condition, clouds, windSpeed, windDirection, rain, snow, night, location, provider, providerUrl, rainPropability as rainProbability, snowProbability, 0 as updateTime FROM ${ForecastEntity.TABLE_NAME}")
|
||||
database.execSQL("DROP TABLE ${ForecastEntity.TABLE_NAME}")
|
||||
database.execSQL("ALTER TABLE ${ForecastEntity.TABLE_NAME}2 RENAME TO ${ForecastEntity.TABLE_NAME}")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration_9_10 : Migration(9, 10) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `Plugins` (`packageName` TEXT NOT NULL, `label` TEXT NOT NULL, `description` TEXT NOT NULL, `pluginClassName` TEXT NOT NULL, `enabled` INTEGER NOT NULL, PRIMARY KEY(`packageName`) );")
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user