Refactor widgets
This commit is contained in:
@@ -21,10 +21,13 @@ 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_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 = [
|
||||
@@ -36,7 +39,7 @@ import de.mm20.launcher2.database.migrations.Migration_9_10
|
||||
WidgetEntity::class,
|
||||
CustomAttributeEntity::class,
|
||||
SearchActionEntity::class
|
||||
], version = 22, exportSchema = true
|
||||
], version = 23, exportSchema = true
|
||||
)
|
||||
@TypeConverters(ComponentNameConverter::class, StringListConverter::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
@@ -81,10 +84,15 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
)
|
||||
|
||||
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)}');"
|
||||
"INSERT INTO Widget (`type`, `position`, `id`) VALUES " +
|
||||
"('weather', 0, ?)," +
|
||||
"('music', 1, ?)," +
|
||||
"('calendar', 2, ?);",
|
||||
arrayOf(
|
||||
UUID.randomUUID().toBytes(),
|
||||
UUID.randomUUID().toBytes(),
|
||||
UUID.randomUUID().toBytes()
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -104,7 +112,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration_18_19(),
|
||||
Migration_19_20(),
|
||||
Migration_20_21(),
|
||||
Migration_21_22()
|
||||
Migration_21_22(),
|
||||
Migration_22_23(),
|
||||
).build()
|
||||
if (_instance == null) _instance = instance
|
||||
return instance
|
||||
|
||||
@@ -1,42 +1,54 @@
|
||||
package de.mm20.launcher2.database
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
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 ORDER BY position ASC")
|
||||
fun getWidgets(): Flow<List<WidgetEntity>>
|
||||
@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>>
|
||||
|
||||
@Transaction
|
||||
fun updateWidgets(widgets: List<WidgetEntity>) {
|
||||
deleteAll()
|
||||
insertAll(widgets)
|
||||
}
|
||||
@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
|
||||
fun insertAll(widgets: List<WidgetEntity>)
|
||||
suspend fun insert(widget: WidgetEntity)
|
||||
|
||||
@Insert
|
||||
fun insert(widget: WidgetEntity)
|
||||
suspend fun insert(widgets: List<WidgetEntity>)
|
||||
|
||||
@Query("DELETE FROM Widget")
|
||||
fun deleteAll()
|
||||
@Update(entity = WidgetEntity::class)
|
||||
suspend fun patch(widget: PartialWidgetEntity)
|
||||
|
||||
@Update(entity = WidgetEntity::class)
|
||||
suspend fun patch(widgets: List<PartialWidgetEntity>)
|
||||
|
||||
@Query("DELETE FROM Widget WHERE data = :data AND type = :type")
|
||||
fun deleteWidget(type: String, data: String)
|
||||
@Update
|
||||
suspend fun update(widget: WidgetEntity)
|
||||
|
||||
@Query("UPDATE Widget SET height = :newHeight WHERE data = :data AND type = :type")
|
||||
fun updateHeight(type: String, data: String, newHeight: Int)
|
||||
@Update
|
||||
suspend fun update(widgets: List<WidgetEntity>)
|
||||
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM Widget WHERE type = :type AND data = :data)")
|
||||
fun exists(type: String, data: String) : Flow<Boolean>
|
||||
@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 * FROM Widget ORDER BY position ASC LIMIT 1")
|
||||
fun getFirst() : Flow<WidgetEntity?>
|
||||
}
|
||||
@@ -2,14 +2,23 @@ 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 data: String,
|
||||
var height: Int,
|
||||
var config: String?,
|
||||
var position: Int,
|
||||
val label: String = "",
|
||||
@PrimaryKey(autoGenerate = true) val id: Int? = null
|
||||
@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,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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user