diff --git a/app/schemas/com.greenart7c3.nostrsigner.database.AppDatabase/6.json b/app/schemas/com.greenart7c3.nostrsigner.database.AppDatabase/6.json index 6330ab91..9f690c29 100644 --- a/app/schemas/com.greenart7c3.nostrsigner.database.AppDatabase/6.json +++ b/app/schemas/com.greenart7c3.nostrsigner.database.AppDatabase/6.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 6, - "identityHash": "3d67ebb3b84f49af6a6823444e1a28e9", + "identityHash": "437f7ffd0c8160d9af569118ec489368", "entities": [ { "tableName": "application", @@ -215,7 +215,26 @@ "id" ] }, - "indices": [], + "indices": [ + { + "name": "index_notification_eventId", + "unique": true, + "columnNames": [ + "eventId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_notification_eventId` ON `${TABLE_NAME}` (`eventId`)" + }, + { + "name": "index_notification_time", + "unique": false, + "columnNames": [ + "time" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_notification_time` ON `${TABLE_NAME}` (`time`)" + } + ], "foreignKeys": [] }, { @@ -347,7 +366,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3d67ebb3b84f49af6a6823444e1a28e9')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '437f7ffd0c8160d9af569118ec489368')" ] } } \ No newline at end of file diff --git a/app/schemas/com.greenart7c3.nostrsigner.database.AppDatabase/7.json b/app/schemas/com.greenart7c3.nostrsigner.database.AppDatabase/7.json new file mode 100644 index 00000000..ea1b9f85 --- /dev/null +++ b/app/schemas/com.greenart7c3.nostrsigner.database.AppDatabase/7.json @@ -0,0 +1,372 @@ +{ + "formatVersion": 1, + "database": { + "version": 7, + "identityHash": "e33ced3a06fb3f42b864b74040933487", + "entities": [ + { + "tableName": "application", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `name` TEXT NOT NULL, `relays` TEXT NOT NULL, `url` TEXT NOT NULL, `icon` TEXT NOT NULL, `description` TEXT NOT NULL, `pubKey` TEXT NOT NULL, `isConnected` INTEGER NOT NULL, `secret` TEXT NOT NULL, `useSecret` INTEGER NOT NULL, `signPolicy` INTEGER NOT NULL, `closeApplication` INTEGER NOT NULL, PRIMARY KEY(`key`))", + "fields": [ + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "relays", + "columnName": "relays", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pubKey", + "columnName": "pubKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isConnected", + "columnName": "isConnected", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "secret", + "columnName": "secret", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "useSecret", + "columnName": "useSecret", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "signPolicy", + "columnName": "signPolicy", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "closeApplication", + "columnName": "closeApplication", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "key" + ] + }, + "indices": [ + { + "name": "index_key", + "unique": true, + "columnNames": [ + "key" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_key` ON `${TABLE_NAME}` (`key`)" + }, + { + "name": "index_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_name` ON `${TABLE_NAME}` (`name`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "applicationPermission", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER, `pkKey` TEXT NOT NULL, `type` TEXT NOT NULL, `kind` INTEGER, `acceptable` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`pkKey`) REFERENCES `application`(`key`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "pkKey", + "columnName": "pkKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "acceptable", + "columnName": "acceptable", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "permissions_by_pk_key", + "unique": false, + "columnNames": [ + "pkKey" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `permissions_by_pk_key` ON `${TABLE_NAME}` (`pkKey`)" + }, + { + "name": "permissions_unique", + "unique": true, + "columnNames": [ + "pkKey", + "type", + "kind" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `permissions_unique` ON `${TABLE_NAME}` (`pkKey`, `type`, `kind`)" + } + ], + "foreignKeys": [ + { + "table": "application", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "pkKey" + ], + "referencedColumns": [ + "key" + ] + } + ] + }, + { + "tableName": "notification", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `eventId` TEXT NOT NULL, `time` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_notification_eventId", + "unique": false, + "columnNames": [ + "eventId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_notification_eventId` ON `${TABLE_NAME}` (`eventId`)" + }, + { + "name": "index_notification_time", + "unique": false, + "columnNames": [ + "time" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_notification_time` ON `${TABLE_NAME}` (`time`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "history", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `pkKey` TEXT NOT NULL, `type` TEXT NOT NULL, `kind` INTEGER, `time` INTEGER NOT NULL, `accepted` INTEGER NOT NULL, FOREIGN KEY(`pkKey`) REFERENCES `application`(`key`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "pkKey", + "columnName": "pkKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accepted", + "columnName": "accepted", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "history_by_pk_key", + "unique": false, + "columnNames": [ + "pkKey" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `history_by_pk_key` ON `${TABLE_NAME}` (`pkKey`)" + }, + { + "name": "history_by_id", + "unique": false, + "columnNames": [ + "id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `history_by_id` ON `${TABLE_NAME}` (`id`)" + } + ], + "foreignKeys": [ + { + "table": "application", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "pkKey" + ], + "referencedColumns": [ + "key" + ] + } + ] + }, + { + "tableName": "amber_log", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `type` TEXT NOT NULL, `message` TEXT NOT NULL, `time` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "message", + "columnName": "message", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e33ced3a06fb3f42b864b74040933487')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/AppDatabase.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/AppDatabase.kt index 03ecb3f4..0abcc4f1 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/AppDatabase.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/AppDatabase.kt @@ -47,6 +47,14 @@ val MIGRATION_5_6 = } } +val MIGRATION_6_7 = + object : Migration(6, 7) { + override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL("CREATE INDEX IF NOT EXISTS `index_notification_eventId` ON `notification` (`eventId`)") + db.execSQL("CREATE INDEX IF NOT EXISTS `index_notification_time` ON `notification` (`time`)") + } + } + @Database( entities = [ ApplicationEntity::class, @@ -55,7 +63,7 @@ val MIGRATION_5_6 = HistoryEntity::class, LogEntity::class, ], - version = 6, + version = 7, ) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { @@ -78,6 +86,7 @@ abstract class AppDatabase : RoomDatabase() { .addMigrations(MIGRATION_3_4) .addMigrations(MIGRATION_4_5) .addMigrations(MIGRATION_5_6) + .addMigrations(MIGRATION_6_7) .build() instance } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt index cccd4dfa..04056351 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt @@ -7,6 +7,7 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Transaction +import com.vitorpamplona.quartz.utils.TimeUtils import kotlinx.coroutines.flow.Flow @Dao @@ -21,7 +22,19 @@ interface ApplicationDao { suspend fun getNotification(eventId: String): NotificationEntity? @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insertNotification(notificationEntity: NotificationEntity): Long? + @Transaction + suspend fun insertNotification(notificationEntity: NotificationEntity): Long? { + deleteNotification(TimeUtils.oneDayAgo()) + return innerInsertNotification(notificationEntity) + } + + @Query("DELETE FROM notification WHERE time <= :time") + @Transaction + suspend fun deleteNotification(time: Long) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + @Transaction + suspend fun innerInsertNotification(notificationEntity: NotificationEntity): Long? @Query("SELECT * FROM application where pubKey = :pubKey order by name") suspend fun getAll(pubKey: String): List @@ -182,7 +195,7 @@ interface ApplicationDao { @Transaction suspend fun countOldNotification(time: Long): Long - @Query("SELECT * FROM notification WHERE time < :time LIMIT 100") + @Query("SELECT * FROM notification WHERE time <= :time ORDER BY TIME DESC LIMIT 100") @Transaction suspend fun getOldNotification(time: Long): List diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/NotificationEntity.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/NotificationEntity.kt index 0c57c5ba..9f828108 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/NotificationEntity.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/NotificationEntity.kt @@ -1,10 +1,15 @@ package com.greenart7c3.nostrsigner.database import androidx.room.Entity +import androidx.room.Index import androidx.room.PrimaryKey @Entity( tableName = "notification", + indices = [ + Index(value = ["eventId"]), + Index(value = ["time"]), + ], ) data class NotificationEntity( @PrimaryKey(autoGenerate = true)