Reorganize and group modules
This commit is contained in:
4
core/database/src/main/AndroidManifest.xml
Normal file
4
core/database/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
/
|
||||
</manifest>
|
||||
@@ -0,0 +1,108 @@
|
||||
@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.entities.*
|
||||
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_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
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
ForecastEntity::class,
|
||||
SavedSearchableEntity::class,
|
||||
CurrencyEntity::class,
|
||||
IconEntity::class,
|
||||
IconPackEntity::class,
|
||||
WidgetEntity::class,
|
||||
CustomAttributeEntity::class,
|
||||
SearchActionEntity::class,
|
||||
], version = 19, exportSchema = true
|
||||
)
|
||||
@TypeConverters(ComponentNameConverter::class, StringListConverter::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun weatherDao(): WeatherDao
|
||||
abstract fun searchDao(): SearchDao
|
||||
abstract fun iconDao(): IconDao
|
||||
abstract fun widgetDao(): WidgetDao
|
||||
abstract fun currencyDao(): CurrencyDao
|
||||
abstract fun backupDao(): BackupRestoreDao
|
||||
abstract fun customAttrsDao(): CustomAttrsDao
|
||||
|
||||
abstract fun searchActionDao(): SearchActionDao
|
||||
|
||||
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')"
|
||||
)
|
||||
|
||||
db.execSQL("INSERT INTO `SearchAction` (`position`, `type`, `data`, `label`, `color`, `icon`, `customIcon`, `options`) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
arrayOf(
|
||||
8, "url", context.getString(R.string.default_websearch_1_url), context.getString(R.string.default_websearch_1_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,
|
||||
)
|
||||
)
|
||||
|
||||
db.execSQL(
|
||||
"INSERT INTO Widget (type, data, height, position, label) VALUES " +
|
||||
"('internal', 'weather', -1, 0, '${context.getString(R.string.widget_name_weather)}')," +
|
||||
"('internal', 'music', -1, 1, '${context.getString(R.string.widget_name_music)}')," +
|
||||
"('internal', 'calendar', -1, 2, '${context.getString(R.string.widget_name_calendar)}');"
|
||||
)
|
||||
}
|
||||
})
|
||||
.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(),
|
||||
).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,63 @@
|
||||
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")
|
||||
suspend fun getAllTagsLike(like: String): List<String>
|
||||
|
||||
@Query("SELECT DISTINCT value FROM CustomAttributes WHERE type = 'tag' ORDER BY value")
|
||||
suspend fun getAllTags(): List<String>
|
||||
|
||||
@Query("SELECT key FROM CustomAttributes WHERE type = 'tag' AND value = :tag")
|
||||
fun getItemsWithTag(tag: String): Flow<List<String>>
|
||||
|
||||
@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,91 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.*
|
||||
import de.mm20.launcher2.database.entities.IconEntity
|
||||
import de.mm20.launcher2.database.entities.IconPackEntity
|
||||
|
||||
@Dao
|
||||
interface IconDao {
|
||||
@Insert
|
||||
fun insertAll(icons: List<IconEntity>)
|
||||
|
||||
@Query("SELECT drawable FROM Icons WHERE componentName = :componentName AND iconPack = :iconPack")
|
||||
suspend fun getIconName(componentName: String, iconPack: String): String?
|
||||
|
||||
@Query("SELECT * FROM Icons WHERE componentName = :componentName AND iconPack = :iconPack AND (type = 'app' OR type = 'calendar') LIMIT 1")
|
||||
suspend fun getIcon(componentName: String, iconPack: String): IconEntity?
|
||||
|
||||
@Query("SELECT * FROM Icons WHERE componentName = :componentName AND (type = 'app' OR type = 'calendar')")
|
||||
suspend fun getIconsFromAllPacks(componentName: String): List<IconEntity>
|
||||
|
||||
@Query("SELECT * FROM Icons WHERE (type = 'app' OR type = 'calendar') AND (drawable LIKE :query OR componentName LIKE :query) ORDER BY iconPack, drawable LIMIT :limit")
|
||||
suspend fun searchIconPackIcons(query: String, limit: Int = 100): List<IconEntity>
|
||||
|
||||
@Query("SELECT * FROM Icons WHERE (type = 'greyscale_icon') AND componentName LIKE :query GROUP BY componentName ORDER BY drawable LIMIT :limit")
|
||||
suspend fun searchGreyscaleIcons(query: String, limit: Int = 100): List<IconEntity>
|
||||
|
||||
@Query("DELETE FROM Icons WHERE iconPack = :iconPack")
|
||||
fun deleteIcons(iconPack: String)
|
||||
|
||||
@Transaction
|
||||
suspend fun installIconPack(iconPack: IconPackEntity, icons: List<IconEntity>) {
|
||||
deleteIconPack(iconPack)
|
||||
deleteIcons(iconPack.packageName)
|
||||
insertAll(icons)
|
||||
installIconPack(iconPack)
|
||||
}
|
||||
|
||||
@Transaction
|
||||
suspend fun installGrayscaleIconMap(packageName: String, icons: List<IconEntity>) {
|
||||
deleteIcons(packageName)
|
||||
insertAll(icons)
|
||||
}
|
||||
|
||||
@Insert
|
||||
fun installIconPack(iconPack: IconPackEntity)
|
||||
|
||||
@Query("SELECT * FROM IconPack")
|
||||
suspend fun getInstalledIconPacks(): List<IconPackEntity>
|
||||
|
||||
@Query("SELECT * FROM IconPack")
|
||||
fun getInstalledIconPacksLiveData(): LiveData<List<IconPackEntity>>
|
||||
|
||||
@Delete
|
||||
fun deleteIconPack(iconPack: IconPackEntity)
|
||||
|
||||
@Query("SELECT * FROM IconPack WHERE packageName = :packageName AND version = :version")
|
||||
suspend fun getPacks(packageName: String, version: String): List<IconPackEntity>
|
||||
|
||||
@Transaction
|
||||
suspend fun isInstalled(iconPack: IconPackEntity): Boolean {
|
||||
return getPacks(iconPack.packageName, iconPack.version).isNotEmpty()
|
||||
}
|
||||
|
||||
@Query("DELETE FROM Icons WHERE iconPack NOT IN (:packs)")
|
||||
fun deleteAllIconsExcept(packs: List<String>)
|
||||
|
||||
@Query("DELETE FROM IconPack WHERE packageName NOT IN (:packs)")
|
||||
fun deleteAllPacksExcept(packs: List<String>)
|
||||
|
||||
@Transaction
|
||||
fun uninstallIconPacksExcept(packs: List<String>) {
|
||||
deleteAllIconsExcept(packs)
|
||||
deleteAllPacksExcept(packs)
|
||||
}
|
||||
|
||||
@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("SELECT * FROM Icons WHERE type = 'greyscale_icon' AND componentName = :componentName")
|
||||
suspend fun getGreyscaleIcon(componentName: String): IconEntity?
|
||||
}
|
||||
@@ -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,148 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.*
|
||||
import de.mm20.launcher2.database.entities.SavedSearchableEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SearchDao {
|
||||
|
||||
@Insert()
|
||||
fun insertAll(items: List<SavedSearchableEntity>)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
fun insertAllSkipExisting(items: List<SavedSearchableEntity>)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
fun insertSkipExisting(items: SavedSearchableEntity)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertAllReplaceExisting(items: List<SavedSearchableEntity>)
|
||||
|
||||
|
||||
@Query("SELECT * FROM Searchable " +
|
||||
"WHERE ((:manuallySorted AND pinned > 1) OR " +
|
||||
"(:automaticallySorted AND pinned = 1) OR" +
|
||||
"(:frequentlyUsed AND pinned = 0 AND launchCount > 0)" +
|
||||
") ORDER BY pinned DESC, launchCount DESC LIMIT :limit")
|
||||
fun getFavorites(
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<SavedSearchableEntity>>
|
||||
|
||||
@Query("SELECT * FROM Searchable " +
|
||||
"WHERE SUBSTR(`key`, 0, INSTR(`key`, '://')) IN (:includeTypes) AND (" +
|
||||
"(:manuallySorted AND pinned > 1) OR " +
|
||||
"(:automaticallySorted AND pinned = 1) OR" +
|
||||
"(:frequentlyUsed AND pinned = 0 AND launchCount > 0)" +
|
||||
") ORDER BY pinned DESC, launchCount DESC LIMIT :limit")
|
||||
fun getFavoritesWithTypes(
|
||||
includeTypes: List<String>,
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<SavedSearchableEntity>>
|
||||
|
||||
@Query("SELECT * FROM Searchable " +
|
||||
"WHERE `type` NOT IN (:excludeTypes) AND (" +
|
||||
"(:manuallySorted AND pinned > 1) OR " +
|
||||
"(:automaticallySorted AND pinned = 1) OR" +
|
||||
"(:frequentlyUsed AND pinned = 0 AND launchCount > 0)" +
|
||||
") ORDER BY pinned DESC, launchCount DESC LIMIT :limit")
|
||||
fun getFavoritesWithoutTypes(
|
||||
excludeTypes: List<String>,
|
||||
manuallySorted: Boolean = false,
|
||||
automaticallySorted: Boolean = false,
|
||||
frequentlyUsed: Boolean = false,
|
||||
limit: Int,
|
||||
): Flow<List<SavedSearchableEntity>>
|
||||
|
||||
@Query("SELECT `key` FROM Searchable WHERE hidden = 1 AND type = 'calendar'")
|
||||
fun getHiddenCalendarEventKeys(): Flow<List<String>>
|
||||
|
||||
|
||||
|
||||
@Query("DELETE FROM Searchable WHERE `key` IN (:keys)")
|
||||
fun deleteAll(keys: List<String>)
|
||||
|
||||
|
||||
@Query("UPDATE Searchable SET pinned = 1, hidden = 0 WHERE `key` = :key")
|
||||
fun pinExistingItem(key: String)
|
||||
|
||||
@Transaction
|
||||
fun pinToFavorites(item: SavedSearchableEntity) {
|
||||
pinExistingItem(item.key)
|
||||
insertSkipExisting(item)
|
||||
}
|
||||
|
||||
@Query("UPDATE Searchable SET pinned = 0 WHERE `key` = :key")
|
||||
fun unpinFavorite(key: String)
|
||||
|
||||
@Query("DELETE FROM Searchable WHERE `key` = :key")
|
||||
suspend fun deleteByKey(key: String)
|
||||
|
||||
@Query("UPDATE Searchable SET pinned = 0 WHERE `key` = :key")
|
||||
fun unpinApp(key: String)
|
||||
|
||||
|
||||
@Query("SELECT pinned FROM Searchable WHERE `key` = :key UNION SELECT 0 as pinned ORDER BY pinned DESC LIMIT 1")
|
||||
fun isPinned(key: String): Flow<Boolean>
|
||||
|
||||
|
||||
@Query("UPDATE Searchable SET hidden = 1, pinned = 0 WHERE `key` = :key")
|
||||
fun hideExistingItem(key: String)
|
||||
|
||||
@Transaction
|
||||
fun hideItem(item: SavedSearchableEntity) {
|
||||
hideExistingItem(item.key)
|
||||
insertSkipExisting(item)
|
||||
}
|
||||
|
||||
@Query("UPDATE Searchable SET hidden = 0 WHERE `key` = :key")
|
||||
fun unhideItem(key: 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 `key` FROM SEARCHABLE WHERE hidden = 1")
|
||||
fun getHiddenItemKeys(): Flow<List<String>>
|
||||
|
||||
@Query("SELECT * FROM SEARCHABLE WHERE hidden = 1")
|
||||
fun getHiddenItems(): Flow<List<SavedSearchableEntity>>
|
||||
|
||||
@Query("UPDATE Searchable SET launchCount = launchCount + 1 WHERE `key` = :key")
|
||||
fun incrementExistingLaunchCount(key: String)
|
||||
|
||||
@Transaction
|
||||
fun incrementLaunchCount(item: SavedSearchableEntity) {
|
||||
incrementExistingLaunchCount(item.key)
|
||||
insertSkipExisting(item)
|
||||
}
|
||||
|
||||
@Query("SELECT * FROM Searchable WHERE `key` = :key")
|
||||
fun getFavorite(key: String): SavedSearchableEntity?
|
||||
|
||||
@Query("SELECT * FROM Searchable WHERE `key` IN (:keys)")
|
||||
suspend fun getFromKeys(keys: List<String>): List<SavedSearchableEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertReplaceExisting(toDatabaseEntity: SavedSearchableEntity)
|
||||
|
||||
@Transaction
|
||||
fun saveFavorites(favorites: List<SavedSearchableEntity>) {
|
||||
deleteAllFavorites()
|
||||
insertAll(favorites)
|
||||
}
|
||||
|
||||
@Query("DELETE FROM Searchable WHERE hidden = 0")
|
||||
fun deleteAllFavorites()
|
||||
|
||||
@Query("UPDATE Searchable SET `pinned` = 0")
|
||||
fun unpinAll()
|
||||
|
||||
@Query("UPDATE Searchable Set `pinned` = 0, `launchCount` = 0 WHERE `key` = :key")
|
||||
suspend fun resetPinStatusAndLaunchCounter(key: String)
|
||||
}
|
||||
@@ -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,39 @@
|
||||
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.WidgetEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface WidgetDao {
|
||||
@Query("SELECT * FROM Widget ORDER BY position ASC")
|
||||
fun getWidgets(): Flow<List<WidgetEntity>>
|
||||
|
||||
@Transaction
|
||||
fun updateWidgets(widgets: List<WidgetEntity>) {
|
||||
deleteAll()
|
||||
insertAll(widgets)
|
||||
}
|
||||
|
||||
@Insert
|
||||
fun insertAll(widgets: List<WidgetEntity>)
|
||||
|
||||
@Insert
|
||||
fun insert(widget: WidgetEntity)
|
||||
|
||||
@Query("DELETE FROM Widget")
|
||||
fun deleteAll()
|
||||
|
||||
|
||||
@Query("DELETE FROM Widget WHERE data = :data AND type = :type")
|
||||
fun deleteWidget(type: String, data: String)
|
||||
|
||||
@Query("UPDATE Widget SET height = :newHeight WHERE data = :data AND type = :type")
|
||||
fun updateHeight(type: String, data: String, newHeight: Int)
|
||||
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM Widget WHERE type = :type AND data = :data)")
|
||||
fun exists(type: String, data: String) : Flow<Boolean>
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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,15 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import android.content.ComponentName
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "Icons")
|
||||
data class IconEntity(
|
||||
val type: String,
|
||||
val componentName: ComponentName?,
|
||||
val drawable: String?,
|
||||
val iconPack: String,
|
||||
val scale : Float? = null,
|
||||
@PrimaryKey(autoGenerate = true) val id : Long? = null
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
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
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
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,
|
||||
var launchCount: Int,
|
||||
@ColumnInfo(name = "pinned") var pinPosition: Int,
|
||||
var hidden: Boolean
|
||||
)
|
||||
@@ -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,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,15 @@
|
||||
package de.mm20.launcher2.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
|
||||
@Entity(tableName = "Widget")
|
||||
data class WidgetEntity(
|
||||
val type: String,
|
||||
var data: String,
|
||||
var height: Int,
|
||||
var position: Int,
|
||||
val label: String = "",
|
||||
@PrimaryKey(autoGenerate = true) val id: Int? = null
|
||||
)
|
||||
@@ -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,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