mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-05 10:58:23 +00:00
added option to delete a bunker automatically
This commit is contained in:
@@ -0,0 +1,455 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 10,
|
||||
"identityHash": "bd08ac27efa990e98825cdcc6e8e167d",
|
||||
"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, `deleteAfter` 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
|
||||
},
|
||||
{
|
||||
"fieldPath": "deleteAfter",
|
||||
"columnName": "deleteAfter",
|
||||
"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`)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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, `rememberType` INTEGER NOT NULL, `acceptUntil` INTEGER NOT NULL, `rejectUntil` 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"
|
||||
},
|
||||
{
|
||||
"fieldPath": "pkKey",
|
||||
"columnName": "pkKey",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "kind",
|
||||
"columnName": "kind",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "acceptable",
|
||||
"columnName": "acceptable",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "rememberType",
|
||||
"columnName": "rememberType",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "acceptUntil",
|
||||
"columnName": "acceptUntil",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "rejectUntil",
|
||||
"columnName": "rejectUntil",
|
||||
"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`)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "history2",
|
||||
"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)",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"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_key2",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"pkKey"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `history_by_pk_key2` ON `${TABLE_NAME}` (`pkKey`)"
|
||||
},
|
||||
{
|
||||
"name": "history_by_id2",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `history_by_id2` ON `${TABLE_NAME}` (`id`)"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"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, 'bd08ac27efa990e98825cdcc6e8e167d')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 9,
|
||||
"identityHash": "08bd4cb1d1d0fd652f0234b33fcd367b",
|
||||
"identityHash": "bd08ac27efa990e98825cdcc6e8e167d",
|
||||
"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`))",
|
||||
"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, `deleteAfter` INTEGER NOT NULL, PRIMARY KEY(`key`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "key",
|
||||
@@ -79,6 +79,12 @@
|
||||
"columnName": "closeApplication",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deleteAfter",
|
||||
"columnName": "deleteAfter",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
@@ -443,7 +449,7 @@
|
||||
],
|
||||
"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, '08bd4cb1d1d0fd652f0234b33fcd367b')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'bd08ac27efa990e98825cdcc6e8e167d')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,7 @@ class Amber : Application(), LifecycleObserver {
|
||||
_instance = this
|
||||
|
||||
LocalPreferences.allSavedAccounts(this).forEach {
|
||||
databases[it.npub] = AppDatabase.getDatabase(this, it.npub)
|
||||
databases[it.npub] = getDatabase(it.npub)
|
||||
applicationIOScope.launch {
|
||||
databases[it.npub]?.applicationDao()?.getAllNotConnected()?.forEach { app ->
|
||||
if (app.application.secret.isNotEmpty() && app.application.secret != app.application.key) {
|
||||
|
||||
@@ -87,6 +87,12 @@ val MIGRATION_8_9 =
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_9_10 = object : Migration(9, 10) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE application ADD COLUMN deleteAfter INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
ApplicationEntity::class,
|
||||
@@ -96,7 +102,7 @@ val MIGRATION_8_9 =
|
||||
LogEntity::class,
|
||||
HistoryEntity2::class,
|
||||
],
|
||||
version = 9,
|
||||
version = 10,
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
@@ -127,6 +133,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
.addMigrations(MIGRATION_6_7)
|
||||
.addMigrations(MIGRATION_7_8)
|
||||
.addMigrations(MIGRATION_8_9)
|
||||
.addMigrations(MIGRATION_9_10)
|
||||
.build()
|
||||
instance.openHelper.writableDatabase.execSQL("VACUUM")
|
||||
|
||||
|
||||
@@ -46,11 +46,16 @@ interface ApplicationDao {
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT a.*, MAX(h.time) as latestTime
|
||||
SELECT
|
||||
a.*,
|
||||
MAX(h.time) AS latestTime
|
||||
FROM application a
|
||||
LEFT JOIN history2 h ON a.`key` = h.pkKey
|
||||
AND a.pubKey = :pubKey
|
||||
GROUP BY a.`key`, a.description, a.icon, a.isConnected, a.name, a.pubKey, a.secret, a.signPolicy, a.url
|
||||
WHERE a.pubKey = :pubKey
|
||||
GROUP BY
|
||||
a.`key`, a.description, a.icon, a.isConnected, a.name,
|
||||
a.pubKey, a.secret, a.signPolicy, a.url, a.useSecret,
|
||||
a.closeApplication, a.deleteAfter, a.relays
|
||||
ORDER BY latestTime DESC
|
||||
""",
|
||||
)
|
||||
@@ -233,4 +238,8 @@ interface ApplicationDao {
|
||||
@Delete
|
||||
@Transaction
|
||||
suspend fun deleteLog(logEntity: LogEntity)
|
||||
|
||||
@Query("DELETE FROM application WHERE deleteAfter < :time AND deleteAfter > 0")
|
||||
@Transaction
|
||||
suspend fun deleteOldApplications(time: Long): Int
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ data class ApplicationEntity(
|
||||
val useSecret: Boolean,
|
||||
var signPolicy: Int,
|
||||
var closeApplication: Boolean,
|
||||
var deleteAfter: Long,
|
||||
) {
|
||||
companion object {
|
||||
fun empty() = ApplicationEntity(
|
||||
@@ -54,6 +55,7 @@ data class ApplicationEntity(
|
||||
useSecret = false,
|
||||
signPolicy = 0,
|
||||
closeApplication = true,
|
||||
deleteAfter = 0L,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ object BunkerRequestUtils {
|
||||
shouldCloseApplication: Boolean? = null,
|
||||
rememberType: RememberType,
|
||||
oldKey: String = "",
|
||||
deleteAfter: Long = 0L,
|
||||
) {
|
||||
onLoading(true)
|
||||
Amber.instance.applicationIOScope.launch {
|
||||
@@ -262,6 +263,9 @@ object BunkerRequestUtils {
|
||||
}
|
||||
}
|
||||
savedApplication = database.applicationDao().getByKey(key)
|
||||
if (bunkerRequest.request is BunkerRequestConnect) {
|
||||
savedApplication?.application?.deleteAfter = deleteAfter
|
||||
}
|
||||
val relays = savedApplication?.application?.relays?.ifEmpty { defaultRelays } ?: bunkerRequest.relays.ifEmpty { defaultRelays }
|
||||
val secret = if (bunkerRequest.request is BunkerRequestConnect) bunkerRequest.request.secret ?: "" else ""
|
||||
|
||||
@@ -280,6 +284,7 @@ object BunkerRequestUtils {
|
||||
secret.isNotBlank(),
|
||||
account.signPolicy,
|
||||
shouldCloseApplication ?: bunkerRequest.closeApplication,
|
||||
deleteAfter = deleteAfter,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
@@ -420,6 +425,7 @@ object BunkerRequestUtils {
|
||||
secret.isNotBlank(),
|
||||
account.signPolicy,
|
||||
bunkerRequest.closeApplication,
|
||||
deleteAfter = 0L,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
|
||||
@@ -9,6 +9,8 @@ import android.os.IBinder
|
||||
import android.util.Log
|
||||
import com.greenart7c3.nostrsigner.Amber
|
||||
import com.greenart7c3.nostrsigner.BuildConfig
|
||||
import com.greenart7c3.nostrsigner.LocalPreferences
|
||||
import com.greenart7c3.nostrsigner.database.LogEntity
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -123,6 +125,23 @@ class ConnectivityService : Service() {
|
||||
}
|
||||
if (Amber.instance.settings.killSwitch.value) return
|
||||
|
||||
scope.launch {
|
||||
LocalPreferences.allSavedAccounts(Amber.instance).forEach { accountInfo ->
|
||||
val now = System.currentTimeMillis() / 1000
|
||||
val deleted = Amber.instance.getDatabase(accountInfo.npub).applicationDao().deleteOldApplications(now)
|
||||
Log.d(Amber.TAG, "Deleted $deleted expired applications")
|
||||
Amber.instance.getDatabase(accountInfo.npub).applicationDao().insertLog(
|
||||
LogEntity(
|
||||
id = 0,
|
||||
url = "",
|
||||
type = "deleteApplications",
|
||||
message = "Deleted $deleted expired applications",
|
||||
time = System.currentTimeMillis(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
if (!Amber.instance.client.isActive()) {
|
||||
Amber.instance.client.connect()
|
||||
|
||||
@@ -562,6 +562,7 @@ object IntentUtils {
|
||||
onRemoveIntentData: (List<IntentData>, IntentResultType) -> Unit,
|
||||
shouldCloseApplication: Boolean? = null,
|
||||
rememberType: RememberType,
|
||||
deleteAfter: Long = 0L,
|
||||
) {
|
||||
onLoading(true)
|
||||
Amber.instance.applicationIOScope.launch {
|
||||
@@ -592,6 +593,7 @@ object IntentUtils {
|
||||
false,
|
||||
account.signPolicy,
|
||||
shouldCloseApplication != false,
|
||||
deleteAfter = deleteAfter,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
@@ -756,6 +758,7 @@ object IntentUtils {
|
||||
false,
|
||||
account.signPolicy,
|
||||
true,
|
||||
deleteAfter = 0L,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.greenart7c3.nostrsigner.ui
|
||||
|
||||
import android.content.ClipData
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -22,6 +23,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -51,7 +53,9 @@ import com.greenart7c3.nostrsigner.database.ApplicationEntity
|
||||
import com.greenart7c3.nostrsigner.models.Account
|
||||
import com.greenart7c3.nostrsigner.ui.actions.onAddRelay
|
||||
import com.greenart7c3.nostrsigner.ui.components.AmberButton
|
||||
import com.greenart7c3.nostrsigner.ui.components.TitleExplainer
|
||||
import java.util.UUID
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -78,6 +82,16 @@ fun NewNsecBunkerScreen(
|
||||
val isLoading = remember { mutableStateOf(false) }
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val focusManager = LocalFocusManager.current
|
||||
val deleteAfterItems =
|
||||
persistentListOf(
|
||||
TitleExplainer(stringResource(DeleteAfterType.NEVER.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.FIVE_MINUTES.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.TEN_MINUTES.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.ONE_HOUR.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.ONE_DAY.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.ONE_WEEK.resourceId)),
|
||||
)
|
||||
var deleteAfterIndex by remember { mutableIntStateOf(DeleteAfterType.NEVER.screenCode) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
@@ -113,6 +127,17 @@ fun NewNsecBunkerScreen(
|
||||
.padding(vertical = 20.dp),
|
||||
)
|
||||
|
||||
Box {
|
||||
SettingsRow(
|
||||
R.string.delete_after,
|
||||
null,
|
||||
deleteAfterItems,
|
||||
deleteAfterIndex,
|
||||
) {
|
||||
deleteAfterIndex = it
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -213,6 +238,8 @@ fun NewNsecBunkerScreen(
|
||||
}
|
||||
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val deleteAfter = deleteAfterToSeconds(parseDeleteAfterType(deleteAfterIndex))
|
||||
|
||||
val application =
|
||||
ApplicationEntity(
|
||||
secret.value,
|
||||
@@ -227,6 +254,7 @@ fun NewNsecBunkerScreen(
|
||||
true,
|
||||
account.signPolicy,
|
||||
true,
|
||||
deleteAfter = deleteAfter,
|
||||
)
|
||||
|
||||
Amber.instance.getDatabase(account.npub).applicationDao().insertApplication(
|
||||
|
||||
@@ -456,6 +456,38 @@ enum class RememberType(val screenCode: Int, val resourceId: Int) {
|
||||
ALWAYS(4, R.string.always),
|
||||
}
|
||||
|
||||
enum class DeleteAfterType(val screenCode: Int, val resourceId: Int) {
|
||||
NEVER(0, R.string.never),
|
||||
FIVE_MINUTES(1, R.string.five_minutes),
|
||||
TEN_MINUTES(2, R.string.ten_minutes),
|
||||
ONE_HOUR(3, R.string.one_hour),
|
||||
ONE_DAY(4, R.string.one_day),
|
||||
ONE_WEEK(5, R.string.one_week),
|
||||
}
|
||||
|
||||
fun parseDeleteAfterType(screenCode: Int): DeleteAfterType {
|
||||
return when (screenCode) {
|
||||
DeleteAfterType.FIVE_MINUTES.screenCode -> DeleteAfterType.FIVE_MINUTES
|
||||
DeleteAfterType.TEN_MINUTES.screenCode -> DeleteAfterType.TEN_MINUTES
|
||||
DeleteAfterType.ONE_HOUR.screenCode -> DeleteAfterType.ONE_HOUR
|
||||
DeleteAfterType.ONE_DAY.screenCode -> DeleteAfterType.ONE_DAY
|
||||
DeleteAfterType.ONE_WEEK.screenCode -> DeleteAfterType.ONE_WEEK
|
||||
else -> DeleteAfterType.NEVER
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteAfterToSeconds(deleteAfterType: DeleteAfterType): Long {
|
||||
val now = System.currentTimeMillis() / 1000
|
||||
return when (deleteAfterType) {
|
||||
DeleteAfterType.FIVE_MINUTES -> now + 300
|
||||
DeleteAfterType.TEN_MINUTES -> now + 600
|
||||
DeleteAfterType.ONE_HOUR -> now + 3600
|
||||
DeleteAfterType.ONE_DAY -> now + 86400
|
||||
DeleteAfterType.ONE_WEEK -> now + 604800
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
enum class BiometricsTimeType(val screenCode: Int, val resourceId: Int) {
|
||||
EVERY_TIME(0, R.string.every_time),
|
||||
ONE_MINUTE(1, R.string.one_minute),
|
||||
|
||||
+32
-2
@@ -2,6 +2,7 @@ package com.greenart7c3.nostrsigner.ui.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -29,8 +30,13 @@ import androidx.compose.ui.unit.sp
|
||||
import com.greenart7c3.nostrsigner.R
|
||||
import com.greenart7c3.nostrsigner.models.Account
|
||||
import com.greenart7c3.nostrsigner.models.Permission
|
||||
import com.greenart7c3.nostrsigner.ui.DeleteAfterType
|
||||
import com.greenart7c3.nostrsigner.ui.RememberType
|
||||
import com.greenart7c3.nostrsigner.ui.SettingsRow
|
||||
import com.greenart7c3.nostrsigner.ui.deleteAfterToSeconds
|
||||
import com.greenart7c3.nostrsigner.ui.parseDeleteAfterType
|
||||
import kotlin.collections.forEach
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
fun BunkerConnectRequestScreen(
|
||||
@@ -39,7 +45,7 @@ fun BunkerConnectRequestScreen(
|
||||
account: Account,
|
||||
appName: String,
|
||||
permissions: List<Permission>?,
|
||||
onAccept: (List<Permission>?, Int, Boolean?, RememberType) -> Unit,
|
||||
onAccept: (List<Permission>?, Int, Boolean?, RememberType, Long) -> Unit,
|
||||
onReject: (RememberType) -> Unit,
|
||||
) {
|
||||
val localPermissions = remember {
|
||||
@@ -70,6 +76,16 @@ fun BunkerConnectRequestScreen(
|
||||
)
|
||||
|
||||
var selectedOption by remember { mutableIntStateOf(account.signPolicy) }
|
||||
val deleteAfterItems =
|
||||
persistentListOf(
|
||||
TitleExplainer(stringResource(DeleteAfterType.NEVER.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.FIVE_MINUTES.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.TEN_MINUTES.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.ONE_HOUR.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.ONE_DAY.resourceId)),
|
||||
TitleExplainer(stringResource(DeleteAfterType.ONE_WEEK.resourceId)),
|
||||
)
|
||||
var deleteAfterIndex by remember { mutableIntStateOf(DeleteAfterType.NEVER.screenCode) }
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.handle_application_permissions),
|
||||
@@ -99,6 +115,19 @@ fun BunkerConnectRequestScreen(
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
Modifier.padding(4.dp),
|
||||
) {
|
||||
SettingsRow(
|
||||
R.string.delete_after,
|
||||
null,
|
||||
deleteAfterItems,
|
||||
deleteAfterIndex,
|
||||
) {
|
||||
deleteAfterIndex = it
|
||||
}
|
||||
}
|
||||
|
||||
ChooseSignPolicy(
|
||||
selectedOption = selectedOption,
|
||||
onSelected = {
|
||||
@@ -122,7 +151,8 @@ fun BunkerConnectRequestScreen(
|
||||
AmberButton(
|
||||
modifier = Modifier.padding(vertical = 20.dp),
|
||||
onClick = {
|
||||
onAccept(localPermissions, selectedOption, closeApp, rememberType)
|
||||
val deleteAfter = deleteAfterToSeconds(parseDeleteAfterType(deleteAfterIndex))
|
||||
onAccept(localPermissions, selectedOption, closeApp, rememberType, deleteAfter)
|
||||
},
|
||||
text = stringResource(R.string.grant_permissions),
|
||||
)
|
||||
|
||||
+8
-3
@@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableLongStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
@@ -26,7 +27,6 @@ import androidx.compose.ui.unit.sp
|
||||
import com.greenart7c3.nostrsigner.Amber
|
||||
import com.greenart7c3.nostrsigner.LocalPreferences
|
||||
import com.greenart7c3.nostrsigner.R
|
||||
import com.greenart7c3.nostrsigner.database.AppDatabase
|
||||
import com.greenart7c3.nostrsigner.database.ApplicationWithPermissions
|
||||
import com.greenart7c3.nostrsigner.models.Account
|
||||
import com.greenart7c3.nostrsigner.models.AmberBunkerRequest
|
||||
@@ -90,6 +90,7 @@ fun BunkerSingleEventHomeScreen(
|
||||
var localSignPolicy by remember { mutableIntStateOf(0) }
|
||||
var localRememberType by remember { mutableStateOf(RememberType.NEVER) }
|
||||
var existingAppKey by remember { mutableStateOf("") }
|
||||
var localDeleteAfter by remember { mutableLongStateOf(0L) }
|
||||
|
||||
if (showExistingAppDialog) {
|
||||
AlertDialog(
|
||||
@@ -122,6 +123,7 @@ fun BunkerSingleEventHomeScreen(
|
||||
signPolicy = localSignPolicy,
|
||||
shouldCloseApplication = localCloseApplication,
|
||||
rememberType = localRememberType,
|
||||
deleteAfter = localDeleteAfter,
|
||||
)
|
||||
},
|
||||
text = stringResource(R.string.replace),
|
||||
@@ -144,6 +146,7 @@ fun BunkerSingleEventHomeScreen(
|
||||
signPolicy = localSignPolicy,
|
||||
shouldCloseApplication = localCloseApplication,
|
||||
rememberType = localRememberType,
|
||||
deleteAfter = localDeleteAfter,
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -171,7 +174,7 @@ fun BunkerSingleEventHomeScreen(
|
||||
Permission(split[0].trim(), null)
|
||||
}
|
||||
},
|
||||
onAccept = { permissions, signPolicy, closeApplication, rememberType ->
|
||||
onAccept = { permissions, signPolicy, closeApplication, rememberType, deleteAfter ->
|
||||
val result = bunkerRequest.nostrConnectSecret.ifBlank { "ack" }
|
||||
|
||||
localPermissions = permissions
|
||||
@@ -181,7 +184,7 @@ fun BunkerSingleEventHomeScreen(
|
||||
|
||||
if (bunkerRequest.name.isNotBlank()) {
|
||||
Amber.instance.applicationIOScope.launch {
|
||||
val existingApp = AppDatabase.getDatabase(Amber.instance, account.npub).applicationDao().getByName(bunkerRequest.name)
|
||||
val existingApp = Amber.instance.getDatabase(account.npub).applicationDao().getByName(bunkerRequest.name)
|
||||
if (existingApp == null) {
|
||||
BunkerRequestUtils.sendResult(
|
||||
context = context,
|
||||
@@ -196,6 +199,7 @@ fun BunkerSingleEventHomeScreen(
|
||||
signPolicy = signPolicy,
|
||||
shouldCloseApplication = closeApplication,
|
||||
rememberType = rememberType,
|
||||
deleteAfter = deleteAfter,
|
||||
)
|
||||
} else {
|
||||
existingAppKey = existingApp.application.key
|
||||
@@ -216,6 +220,7 @@ fun BunkerSingleEventHomeScreen(
|
||||
signPolicy = signPolicy,
|
||||
shouldCloseApplication = closeApplication,
|
||||
rememberType = rememberType,
|
||||
deleteAfter = deleteAfter,
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -241,6 +241,7 @@ fun IntentMultiEventHomeScreen(
|
||||
false,
|
||||
thisAccount.signPolicy,
|
||||
true,
|
||||
0L,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
@@ -433,6 +434,7 @@ fun IntentMultiEventHomeScreen(
|
||||
false,
|
||||
thisAccount.signPolicy,
|
||||
true,
|
||||
0L,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
@@ -611,6 +613,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
secret.isNotBlank(),
|
||||
thisAccount.signPolicy,
|
||||
request.closeApplication,
|
||||
0L,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
@@ -878,6 +881,7 @@ fun BunkerMultiEventHomeScreen(
|
||||
secret.isNotBlank(),
|
||||
thisAccount.signPolicy,
|
||||
request.closeApplication,
|
||||
0L,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
|
||||
@@ -554,4 +554,8 @@
|
||||
<string name="disable_kill_switch">Disable kill switch</string>
|
||||
<string name="kill_switch_message">Kill Switch enabled, remote login and profile fetching will not work</string>
|
||||
<string name="edit_relays">Edit Relays</string>
|
||||
<string name="one_hour">One hour</string>
|
||||
<string name="one_day">One day</string>
|
||||
<string name="one_week">One week</string>
|
||||
<string name="delete_after">Delete after</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user