kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
refactor: move ignore node to `is_ignored` field in `NodeInfo`
rodzic
4a1319a645
commit
1ea55b2209
|
@ -0,0 +1,522 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 15,
|
||||||
|
"identityHash": "2435abd7894404b70957f327189b0de7",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "my_node",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`myNodeNum` INTEGER NOT NULL, `model` TEXT, `firmwareVersion` TEXT, `couldUpdate` INTEGER NOT NULL, `shouldUpdate` INTEGER NOT NULL, `currentPacketId` INTEGER NOT NULL, `messageTimeoutMsec` INTEGER NOT NULL, `minAppVersion` INTEGER NOT NULL, `maxChannels` INTEGER NOT NULL, `hasWifi` INTEGER NOT NULL, PRIMARY KEY(`myNodeNum`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "myNodeNum",
|
||||||
|
"columnName": "myNodeNum",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "model",
|
||||||
|
"columnName": "model",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "firmwareVersion",
|
||||||
|
"columnName": "firmwareVersion",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "couldUpdate",
|
||||||
|
"columnName": "couldUpdate",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "shouldUpdate",
|
||||||
|
"columnName": "shouldUpdate",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "currentPacketId",
|
||||||
|
"columnName": "currentPacketId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "messageTimeoutMsec",
|
||||||
|
"columnName": "messageTimeoutMsec",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "minAppVersion",
|
||||||
|
"columnName": "minAppVersion",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "maxChannels",
|
||||||
|
"columnName": "maxChannels",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasWifi",
|
||||||
|
"columnName": "hasWifi",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"myNodeNum"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "nodes",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`num` INTEGER NOT NULL, `user` BLOB NOT NULL, `long_name` TEXT, `short_name` TEXT, `position` BLOB NOT NULL, `latitude` REAL NOT NULL, `longitude` REAL NOT NULL, `snr` REAL NOT NULL, `rssi` INTEGER NOT NULL, `last_heard` INTEGER NOT NULL, `device_metrics` BLOB NOT NULL, `channel` INTEGER NOT NULL, `via_mqtt` INTEGER NOT NULL, `hops_away` INTEGER NOT NULL, `is_favorite` INTEGER NOT NULL, `is_ignored` INTEGER NOT NULL DEFAULT 0, `environment_metrics` BLOB NOT NULL, `power_metrics` BLOB NOT NULL, `paxcounter` BLOB NOT NULL, PRIMARY KEY(`num`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "num",
|
||||||
|
"columnName": "num",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "user",
|
||||||
|
"columnName": "user",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "longName",
|
||||||
|
"columnName": "long_name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "shortName",
|
||||||
|
"columnName": "short_name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "position",
|
||||||
|
"columnName": "position",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "latitude",
|
||||||
|
"columnName": "latitude",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "longitude",
|
||||||
|
"columnName": "longitude",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "snr",
|
||||||
|
"columnName": "snr",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "rssi",
|
||||||
|
"columnName": "rssi",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastHeard",
|
||||||
|
"columnName": "last_heard",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "deviceTelemetry",
|
||||||
|
"columnName": "device_metrics",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "channel",
|
||||||
|
"columnName": "channel",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "viaMqtt",
|
||||||
|
"columnName": "via_mqtt",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hopsAway",
|
||||||
|
"columnName": "hops_away",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "isFavorite",
|
||||||
|
"columnName": "is_favorite",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "isIgnored",
|
||||||
|
"columnName": "is_ignored",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "environmentTelemetry",
|
||||||
|
"columnName": "environment_metrics",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "powerTelemetry",
|
||||||
|
"columnName": "power_metrics",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "paxcounter",
|
||||||
|
"columnName": "paxcounter",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"num"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "packet",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `myNodeNum` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL, `contact_key` TEXT NOT NULL, `received_time` INTEGER NOT NULL, `read` INTEGER NOT NULL DEFAULT 1, `data` TEXT NOT NULL, `packet_id` INTEGER NOT NULL DEFAULT 0, `routing_error` INTEGER NOT NULL DEFAULT -1, `reply_id` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uuid",
|
||||||
|
"columnName": "uuid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "myNodeNum",
|
||||||
|
"columnName": "myNodeNum",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "port_num",
|
||||||
|
"columnName": "port_num",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "contact_key",
|
||||||
|
"columnName": "contact_key",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "received_time",
|
||||||
|
"columnName": "received_time",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "read",
|
||||||
|
"columnName": "read",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "data",
|
||||||
|
"columnName": "data",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "packetId",
|
||||||
|
"columnName": "packet_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "routingError",
|
||||||
|
"columnName": "routing_error",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "-1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "replyId",
|
||||||
|
"columnName": "reply_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_packet_myNodeNum",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"myNodeNum"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_myNodeNum` ON `${TABLE_NAME}` (`myNodeNum`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_packet_port_num",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"port_num"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_port_num` ON `${TABLE_NAME}` (`port_num`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_packet_contact_key",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"contact_key"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_contact_key` ON `${TABLE_NAME}` (`contact_key`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "contact_settings",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`contact_key` TEXT NOT NULL, `muteUntil` INTEGER NOT NULL, PRIMARY KEY(`contact_key`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "contact_key",
|
||||||
|
"columnName": "contact_key",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "muteUntil",
|
||||||
|
"columnName": "muteUntil",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"contact_key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "log",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `type` TEXT NOT NULL, `received_date` INTEGER NOT NULL, `message` TEXT NOT NULL, `from_num` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL DEFAULT 0, `from_radio` BLOB NOT NULL DEFAULT x'', PRIMARY KEY(`uuid`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uuid",
|
||||||
|
"columnName": "uuid",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "message_type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "received_date",
|
||||||
|
"columnName": "received_date",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "raw_message",
|
||||||
|
"columnName": "message",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "fromNum",
|
||||||
|
"columnName": "from_num",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "portNum",
|
||||||
|
"columnName": "port_num",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "fromRadio",
|
||||||
|
"columnName": "from_radio",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "x''"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_log_from_num",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"from_num"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_log_from_num` ON `${TABLE_NAME}` (`from_num`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_log_port_num",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"port_num"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_log_port_num` ON `${TABLE_NAME}` (`port_num`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "quick_chat",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `message` TEXT NOT NULL, `mode` TEXT NOT NULL, `position` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uuid",
|
||||||
|
"columnName": "uuid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "message",
|
||||||
|
"columnName": "message",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "mode",
|
||||||
|
"columnName": "mode",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "position",
|
||||||
|
"columnName": "position",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "reactions",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`reply_id` INTEGER NOT NULL, `user_id` TEXT NOT NULL, `emoji` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`reply_id`, `user_id`, `emoji`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "replyId",
|
||||||
|
"columnName": "reply_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userId",
|
||||||
|
"columnName": "user_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "emoji",
|
||||||
|
"columnName": "emoji",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "timestamp",
|
||||||
|
"columnName": "timestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"reply_id",
|
||||||
|
"user_id",
|
||||||
|
"emoji"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_reactions_reply_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"reply_id"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_reactions_reply_id` ON `${TABLE_NAME}` (`reply_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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, '2435abd7894404b70957f327189b0de7')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,8 +59,9 @@ import com.geeksville.mesh.database.entity.ReactionEntity
|
||||||
AutoMigration(from = 11, to = 12),
|
AutoMigration(from = 11, to = 12),
|
||||||
AutoMigration(from = 12, to = 13, spec = AutoMigration12to13::class),
|
AutoMigration(from = 12, to = 13, spec = AutoMigration12to13::class),
|
||||||
AutoMigration(from = 13, to = 14),
|
AutoMigration(from = 13, to = 14),
|
||||||
|
AutoMigration(from = 14, to = 15),
|
||||||
],
|
],
|
||||||
version = 14,
|
version = 15,
|
||||||
exportSchema = true,
|
exportSchema = true,
|
||||||
)
|
)
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
|
|
|
@ -74,6 +74,9 @@ data class NodeEntity(
|
||||||
@ColumnInfo(name = "is_favorite")
|
@ColumnInfo(name = "is_favorite")
|
||||||
var isFavorite: Boolean = false,
|
var isFavorite: Boolean = false,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "is_ignored", defaultValue = "0")
|
||||||
|
var isIgnored: Boolean = false,
|
||||||
|
|
||||||
@ColumnInfo(name = "environment_metrics", typeAffinity = ColumnInfo.BLOB)
|
@ColumnInfo(name = "environment_metrics", typeAffinity = ColumnInfo.BLOB)
|
||||||
var environmentTelemetry: TelemetryProtos.Telemetry = TelemetryProtos.Telemetry.getDefaultInstance(),
|
var environmentTelemetry: TelemetryProtos.Telemetry = TelemetryProtos.Telemetry.getDefaultInstance(),
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,6 @@ data class NodesUiState(
|
||||||
val gpsFormat: Int = 0,
|
val gpsFormat: Int = 0,
|
||||||
val distanceUnits: Int = 0,
|
val distanceUnits: Int = 0,
|
||||||
val tempInFahrenheit: Boolean = false,
|
val tempInFahrenheit: Boolean = false,
|
||||||
val ignoreIncomingList: List<Int> = emptyList(),
|
|
||||||
val showDetails: Boolean = false,
|
val showDetails: Boolean = false,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -227,7 +226,6 @@ class UIViewModel @Inject constructor(
|
||||||
gpsFormat = profile.config.display.gpsFormat.number,
|
gpsFormat = profile.config.display.gpsFormat.number,
|
||||||
distanceUnits = profile.config.display.units.number,
|
distanceUnits = profile.config.display.units.number,
|
||||||
tempInFahrenheit = profile.moduleConfig.telemetry.environmentDisplayFahrenheit,
|
tempInFahrenheit = profile.moduleConfig.telemetry.environmentDisplayFahrenheit,
|
||||||
ignoreIncomingList = profile.config.lora.ignoreIncomingList,
|
|
||||||
showDetails = showDetails,
|
showDetails = showDetails,
|
||||||
)
|
)
|
||||||
}.stateIn(
|
}.stateIn(
|
||||||
|
@ -486,19 +484,11 @@ class UIViewModel @Inject constructor(
|
||||||
updateLoraConfig { it.copy { region = value } }
|
updateLoraConfig { it.copy { region = value } }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ignoreNode(nodeNum: Int) = updateLoraConfig {
|
fun ignoreNode(node: NodeEntity) = viewModelScope.launch {
|
||||||
it.copy {
|
try {
|
||||||
val list = ignoreIncoming.toMutableList().apply {
|
radioConfigRepository.onServiceAction(ServiceAction.Ignore(node))
|
||||||
if (contains(nodeNum)) {
|
} catch (ex: RemoteException) {
|
||||||
debug("removing node $nodeNum from ignore list")
|
errormsg("Ignore node error:", ex)
|
||||||
remove(nodeNum)
|
|
||||||
} else {
|
|
||||||
debug("adding node $nodeNum to ignore list")
|
|
||||||
add(nodeNum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ignoreIncoming.clear()
|
|
||||||
ignoreIncoming.addAll(list)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ import javax.inject.Inject
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
sealed class ServiceAction {
|
sealed class ServiceAction {
|
||||||
|
data class Ignore(val node: NodeEntity) : ServiceAction()
|
||||||
data class Reaction(val emoji: String, val replyId: Int, val contactKey: String) : ServiceAction()
|
data class Reaction(val emoji: String, val replyId: Int, val contactKey: String) : ServiceAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +304,7 @@ class MeshService : Service(), Logging {
|
||||||
.launchIn(serviceScope)
|
.launchIn(serviceScope)
|
||||||
radioConfigRepository.serviceAction.onEach { action ->
|
radioConfigRepository.serviceAction.onEach { action ->
|
||||||
when (action) {
|
when (action) {
|
||||||
|
is ServiceAction.Ignore -> ignoreNode(action.node)
|
||||||
is ServiceAction.Reaction -> sendReaction(action)
|
is ServiceAction.Reaction -> sendReaction(action)
|
||||||
}
|
}
|
||||||
}.launchIn(serviceScope)
|
}.launchIn(serviceScope)
|
||||||
|
@ -1453,6 +1455,7 @@ class MeshService : Service(), Logging {
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
it.isFavorite = info.isFavorite
|
it.isFavorite = info.isFavorite
|
||||||
|
it.isIgnored = info.isIgnored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1757,6 +1760,21 @@ class MeshService : Service(), Logging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ignoreNode(node: NodeEntity) = toRemoteExceptions {
|
||||||
|
sendToRadio(newMeshPacketTo(myNodeNum).buildAdminPacket {
|
||||||
|
if (node.isIgnored) {
|
||||||
|
debug("removing node ${node.num} from ignore list")
|
||||||
|
removeIgnoredNode = node.num
|
||||||
|
} else {
|
||||||
|
debug("adding node ${node.num} to ignore list")
|
||||||
|
setIgnoredNode = node.num
|
||||||
|
}
|
||||||
|
})
|
||||||
|
updateNodeInfo(node.num) {
|
||||||
|
it.isIgnored = !node.isIgnored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun sendReaction(reaction: ServiceAction.Reaction) = toRemoteExceptions {
|
private fun sendReaction(reaction: ServiceAction.Reaction) = toRemoteExceptions {
|
||||||
// contactKey: unique contact key filter (channel)+(nodeId)
|
// contactKey: unique contact key filter (channel)+(nodeId)
|
||||||
val channel = reaction.contactKey[0].digitToInt()
|
val channel = reaction.contactKey[0].digitToInt()
|
||||||
|
|
|
@ -60,7 +60,7 @@ import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig
|
||||||
import com.geeksville.mesh.MeshProtos
|
import com.geeksville.mesh.MeshProtos
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
import com.geeksville.mesh.database.entity.NodeEntity
|
import com.geeksville.mesh.database.entity.NodeEntity
|
||||||
import com.geeksville.mesh.ui.components.MenuItemAction
|
import com.geeksville.mesh.ui.components.NodeMenuAction
|
||||||
import com.geeksville.mesh.ui.components.NodeKeyStatusIcon
|
import com.geeksville.mesh.ui.components.NodeKeyStatusIcon
|
||||||
import com.geeksville.mesh.ui.components.NodeMenu
|
import com.geeksville.mesh.ui.components.NodeMenu
|
||||||
import com.geeksville.mesh.ui.components.SignalInfo
|
import com.geeksville.mesh.ui.components.SignalInfo
|
||||||
|
@ -79,13 +79,12 @@ fun NodeItem(
|
||||||
gpsFormat: Int,
|
gpsFormat: Int,
|
||||||
distanceUnits: Int,
|
distanceUnits: Int,
|
||||||
tempInFahrenheit: Boolean,
|
tempInFahrenheit: Boolean,
|
||||||
ignoreIncomingList: List<Int> = emptyList(),
|
onAction: (NodeMenuAction) -> Unit = {},
|
||||||
menuItemActionClicked: (MenuItemAction) -> Unit = {},
|
|
||||||
expanded: Boolean = false,
|
expanded: Boolean = false,
|
||||||
currentTimeMillis: Long,
|
currentTimeMillis: Long,
|
||||||
isConnected: Boolean = false,
|
isConnected: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val isIgnored = ignoreIncomingList.contains(thatNode.num)
|
val isIgnored = thatNode.isIgnored
|
||||||
val longName = thatNode.user.longName.ifEmpty { stringResource(id = R.string.unknown_username) }
|
val longName = thatNode.user.longName.ifEmpty { stringResource(id = R.string.unknown_username) }
|
||||||
|
|
||||||
val isThisNode = thisNode?.num == thatNode.num
|
val isThisNode = thisNode?.num == thatNode.num
|
||||||
|
@ -159,12 +158,10 @@ fun NodeItem(
|
||||||
}
|
}
|
||||||
NodeMenu(
|
NodeMenu(
|
||||||
node = thatNode,
|
node = thatNode,
|
||||||
ignoreIncomingList = ignoreIncomingList,
|
showFullMenu = !isThisNode && isConnected,
|
||||||
isThisNode = isThisNode,
|
onAction = onAction,
|
||||||
onMenuItemAction = menuItemActionClicked,
|
|
||||||
expanded = menuExpanded,
|
expanded = menuExpanded,
|
||||||
onDismissRequest = { menuExpanded = false },
|
onDismissRequest = { menuExpanded = false },
|
||||||
isConnected = isConnected,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
NodeKeyStatusIcon(
|
NodeKeyStatusIcon(
|
||||||
|
|
|
@ -41,7 +41,7 @@ import com.geeksville.mesh.DataPacket
|
||||||
import com.geeksville.mesh.android.Logging
|
import com.geeksville.mesh.android.Logging
|
||||||
import com.geeksville.mesh.database.entity.NodeEntity
|
import com.geeksville.mesh.database.entity.NodeEntity
|
||||||
import com.geeksville.mesh.model.UIViewModel
|
import com.geeksville.mesh.model.UIViewModel
|
||||||
import com.geeksville.mesh.ui.components.MenuItemAction
|
import com.geeksville.mesh.ui.components.NodeMenuAction
|
||||||
import com.geeksville.mesh.ui.components.NodeFilterTextField
|
import com.geeksville.mesh.ui.components.NodeFilterTextField
|
||||||
import com.geeksville.mesh.ui.components.rememberTimeTickWithLifecycle
|
import com.geeksville.mesh.ui.components.rememberTimeTickWithLifecycle
|
||||||
import com.geeksville.mesh.ui.message.navigateToMessages
|
import com.geeksville.mesh.ui.message.navigateToMessages
|
||||||
|
@ -131,16 +131,15 @@ fun NodesScreen(
|
||||||
gpsFormat = state.gpsFormat,
|
gpsFormat = state.gpsFormat,
|
||||||
distanceUnits = state.distanceUnits,
|
distanceUnits = state.distanceUnits,
|
||||||
tempInFahrenheit = state.tempInFahrenheit,
|
tempInFahrenheit = state.tempInFahrenheit,
|
||||||
ignoreIncomingList = state.ignoreIncomingList,
|
onAction = { menuItem ->
|
||||||
menuItemActionClicked = { menuItem ->
|
|
||||||
when (menuItem) {
|
when (menuItem) {
|
||||||
MenuItemAction.Remove -> model.removeNode(node.num)
|
is NodeMenuAction.Remove -> model.removeNode(node.num)
|
||||||
MenuItemAction.Ignore -> model.ignoreNode(node.num)
|
is NodeMenuAction.Ignore -> model.ignoreNode(node)
|
||||||
MenuItemAction.DirectMessage -> navigateToMessages(node)
|
is NodeMenuAction.DirectMessage -> navigateToMessages(node)
|
||||||
MenuItemAction.RequestUserInfo -> model.requestUserInfo(node.num)
|
is NodeMenuAction.RequestUserInfo -> model.requestUserInfo(node.num)
|
||||||
MenuItemAction.RequestPosition -> model.requestPosition(node.num)
|
is NodeMenuAction.RequestPosition -> model.requestPosition(node.num)
|
||||||
MenuItemAction.TraceRoute -> model.requestTraceroute(node.num)
|
is NodeMenuAction.TraceRoute -> model.requestTraceroute(node.num)
|
||||||
MenuItemAction.MoreDetails -> navigateToNodeDetails(node.num)
|
is NodeMenuAction.MoreDetails -> navigateToNodeDetails(node.num)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
expanded = state.showDetails,
|
expanded = state.showDetails,
|
||||||
|
|
|
@ -42,26 +42,23 @@ import com.geeksville.mesh.database.entity.NodeEntity
|
||||||
@Composable
|
@Composable
|
||||||
fun NodeMenu(
|
fun NodeMenu(
|
||||||
node: NodeEntity,
|
node: NodeEntity,
|
||||||
ignoreIncomingList: List<Int>,
|
showFullMenu: Boolean = false,
|
||||||
isThisNode: Boolean = false,
|
|
||||||
onMenuItemAction: (MenuItemAction) -> Unit,
|
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
expanded: Boolean = false,
|
expanded: Boolean = false,
|
||||||
isConnected: Boolean = false,
|
onAction: (NodeMenuAction) -> Unit
|
||||||
) {
|
) {
|
||||||
val isIgnored = ignoreIncomingList.contains(node.num)
|
|
||||||
var displayIgnoreDialog by remember { mutableStateOf(false) }
|
var displayIgnoreDialog by remember { mutableStateOf(false) }
|
||||||
var displayRemoveDialog by remember { mutableStateOf(false) }
|
var displayRemoveDialog by remember { mutableStateOf(false) }
|
||||||
if (displayIgnoreDialog) {
|
if (displayIgnoreDialog) {
|
||||||
SimpleAlertDialog(
|
SimpleAlertDialog(
|
||||||
title = R.string.ignore,
|
title = R.string.ignore,
|
||||||
text = stringResource(
|
text = stringResource(
|
||||||
id = if (isIgnored) R.string.ignore_remove else R.string.ignore_add,
|
id = if (node.isIgnored) R.string.ignore_remove else R.string.ignore_add,
|
||||||
node.user.longName
|
node.user.longName
|
||||||
),
|
),
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
displayIgnoreDialog = false
|
displayIgnoreDialog = false
|
||||||
onMenuItemAction(MenuItemAction.Ignore)
|
onAction(NodeMenuAction.Ignore(node))
|
||||||
},
|
},
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
displayIgnoreDialog = false
|
displayIgnoreDialog = false
|
||||||
|
@ -74,7 +71,7 @@ fun NodeMenu(
|
||||||
text = R.string.remove_node_text,
|
text = R.string.remove_node_text,
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
displayRemoveDialog = false
|
displayRemoveDialog = false
|
||||||
onMenuItemAction(MenuItemAction.Remove)
|
onAction(NodeMenuAction.Remove(node))
|
||||||
},
|
},
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
displayRemoveDialog = false
|
displayRemoveDialog = false
|
||||||
|
@ -87,32 +84,32 @@ fun NodeMenu(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if (!isThisNode && isConnected) {
|
if (showFullMenu) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
onClick = {
|
onClick = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
onMenuItemAction(MenuItemAction.DirectMessage)
|
onAction(NodeMenuAction.DirectMessage(node))
|
||||||
},
|
},
|
||||||
content = { Text(stringResource(R.string.direct_message)) }
|
content = { Text(stringResource(R.string.direct_message)) }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
onClick = {
|
onClick = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
onMenuItemAction(MenuItemAction.RequestUserInfo)
|
onAction(NodeMenuAction.RequestUserInfo(node))
|
||||||
},
|
},
|
||||||
content = { Text(stringResource(R.string.request_userinfo)) }
|
content = { Text(stringResource(R.string.request_userinfo)) }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
onClick = {
|
onClick = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
onMenuItemAction(MenuItemAction.RequestPosition)
|
onAction(NodeMenuAction.RequestPosition(node))
|
||||||
},
|
},
|
||||||
content = { Text(stringResource(R.string.request_position)) }
|
content = { Text(stringResource(R.string.request_position)) }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
onClick = {
|
onClick = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
onMenuItemAction(MenuItemAction.TraceRoute)
|
onAction(NodeMenuAction.TraceRoute(node))
|
||||||
},
|
},
|
||||||
content = { Text(stringResource(R.string.traceroute)) }
|
content = { Text(stringResource(R.string.traceroute)) }
|
||||||
)
|
)
|
||||||
|
@ -121,17 +118,15 @@ fun NodeMenu(
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
displayIgnoreDialog = true
|
displayIgnoreDialog = true
|
||||||
},
|
},
|
||||||
enabled = ignoreIncomingList.size < 3 || isIgnored
|
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.ignore))
|
Text(stringResource(R.string.ignore))
|
||||||
Spacer(Modifier.weight(1f))
|
Spacer(Modifier.weight(1f))
|
||||||
Checkbox(
|
Checkbox(
|
||||||
checked = isIgnored,
|
checked = node.isIgnored,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
displayIgnoreDialog = true
|
displayIgnoreDialog = true
|
||||||
},
|
},
|
||||||
enabled = isIgnored || ignoreIncomingList.size < 3,
|
|
||||||
modifier = Modifier.size(24.dp),
|
modifier = Modifier.size(24.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -140,25 +135,26 @@ fun NodeMenu(
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
displayRemoveDialog = true
|
displayRemoveDialog = true
|
||||||
},
|
},
|
||||||
|
enabled = !node.isIgnored,
|
||||||
) { Text(stringResource(R.string.remove)) }
|
) { Text(stringResource(R.string.remove)) }
|
||||||
Divider(Modifier.padding(vertical = 8.dp))
|
Divider(Modifier.padding(vertical = 8.dp))
|
||||||
}
|
}
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
onClick = {
|
onClick = {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
onMenuItemAction(MenuItemAction.MoreDetails)
|
onAction(NodeMenuAction.MoreDetails(node))
|
||||||
},
|
},
|
||||||
content = { Text(stringResource(R.string.more_details)) }
|
content = { Text(stringResource(R.string.more_details)) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class MenuItemAction {
|
sealed class NodeMenuAction {
|
||||||
Remove,
|
data class Remove(val node: NodeEntity) : NodeMenuAction()
|
||||||
Ignore,
|
data class Ignore(val node: NodeEntity) : NodeMenuAction()
|
||||||
DirectMessage,
|
data class DirectMessage(val node: NodeEntity) : NodeMenuAction()
|
||||||
RequestUserInfo,
|
data class RequestUserInfo(val node: NodeEntity) : NodeMenuAction()
|
||||||
RequestPosition,
|
data class RequestPosition(val node: NodeEntity) : NodeMenuAction()
|
||||||
TraceRoute,
|
data class TraceRoute(val node: NodeEntity) : NodeMenuAction()
|
||||||
MoreDetails
|
data class MoreDetails(val node: NodeEntity) : NodeMenuAction()
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue