@ -0,0 +1,850 @@ | |||
{ | |||
"formatVersion": 1, | |||
"database": { | |||
"version": 6, | |||
"identityHash": "e9ae946be1049502f01f8f30275abc2f", | |||
"entities": [ | |||
{ | |||
"tableName": "identity", | |||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `email` TEXT NOT NULL, `replyto` TEXT, `account` INTEGER NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `starttls` INTEGER NOT NULL, `user` TEXT NOT NULL, `password` TEXT NOT NULL, `auth_type` INTEGER NOT NULL, `primary` INTEGER NOT NULL, `synchronize` INTEGER NOT NULL, `store_sent` INTEGER NOT NULL, `state` TEXT, `error` TEXT, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", | |||
"fields": [ | |||
{ | |||
"fieldPath": "id", | |||
"columnName": "id", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "name", | |||
"columnName": "name", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "email", | |||
"columnName": "email", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "replyto", | |||
"columnName": "replyto", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "account", | |||
"columnName": "account", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "host", | |||
"columnName": "host", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "port", | |||
"columnName": "port", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "starttls", | |||
"columnName": "starttls", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "user", | |||
"columnName": "user", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "password", | |||
"columnName": "password", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "auth_type", | |||
"columnName": "auth_type", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "primary", | |||
"columnName": "primary", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "synchronize", | |||
"columnName": "synchronize", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "store_sent", | |||
"columnName": "store_sent", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "state", | |||
"columnName": "state", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "error", | |||
"columnName": "error", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
} | |||
], | |||
"primaryKey": { | |||
"columnNames": [ | |||
"id" | |||
], | |||
"autoGenerate": true | |||
}, | |||
"indices": [ | |||
{ | |||
"name": "index_identity_account", | |||
"unique": false, | |||
"columnNames": [ | |||
"account" | |||
], | |||
"createSql": "CREATE INDEX `index_identity_account` ON `${TABLE_NAME}` (`account`)" | |||
} | |||
], | |||
"foreignKeys": [ | |||
{ | |||
"table": "account", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"account" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
} | |||
] | |||
}, | |||
{ | |||
"tableName": "account", | |||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `user` TEXT NOT NULL, `password` TEXT NOT NULL, `auth_type` INTEGER NOT NULL, `primary` INTEGER NOT NULL, `synchronize` INTEGER NOT NULL, `store_sent` INTEGER NOT NULL, `poll_interval` INTEGER NOT NULL, `seen_until` INTEGER, `state` TEXT, `error` TEXT)", | |||
"fields": [ | |||
{ | |||
"fieldPath": "id", | |||
"columnName": "id", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "name", | |||
"columnName": "name", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "host", | |||
"columnName": "host", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "port", | |||
"columnName": "port", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "user", | |||
"columnName": "user", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "password", | |||
"columnName": "password", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "auth_type", | |||
"columnName": "auth_type", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "primary", | |||
"columnName": "primary", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "synchronize", | |||
"columnName": "synchronize", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "store_sent", | |||
"columnName": "store_sent", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "poll_interval", | |||
"columnName": "poll_interval", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "seen_until", | |||
"columnName": "seen_until", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "state", | |||
"columnName": "state", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "error", | |||
"columnName": "error", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
} | |||
], | |||
"primaryKey": { | |||
"columnNames": [ | |||
"id" | |||
], | |||
"autoGenerate": true | |||
}, | |||
"indices": [], | |||
"foreignKeys": [] | |||
}, | |||
{ | |||
"tableName": "folder", | |||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` INTEGER, `name` TEXT NOT NULL, `type` TEXT NOT NULL, `synchronize` INTEGER NOT NULL, `after` INTEGER NOT NULL, `state` TEXT, `error` TEXT, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", | |||
"fields": [ | |||
{ | |||
"fieldPath": "id", | |||
"columnName": "id", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "account", | |||
"columnName": "account", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "name", | |||
"columnName": "name", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "type", | |||
"columnName": "type", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "synchronize", | |||
"columnName": "synchronize", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "after", | |||
"columnName": "after", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "state", | |||
"columnName": "state", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "error", | |||
"columnName": "error", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
} | |||
], | |||
"primaryKey": { | |||
"columnNames": [ | |||
"id" | |||
], | |||
"autoGenerate": true | |||
}, | |||
"indices": [ | |||
{ | |||
"name": "index_folder_account_name", | |||
"unique": true, | |||
"columnNames": [ | |||
"account", | |||
"name" | |||
], | |||
"createSql": "CREATE UNIQUE INDEX `index_folder_account_name` ON `${TABLE_NAME}` (`account`, `name`)" | |||
}, | |||
{ | |||
"name": "index_folder_account", | |||
"unique": false, | |||
"columnNames": [ | |||
"account" | |||
], | |||
"createSql": "CREATE INDEX `index_folder_account` ON `${TABLE_NAME}` (`account`)" | |||
}, | |||
{ | |||
"name": "index_folder_name", | |||
"unique": false, | |||
"columnNames": [ | |||
"name" | |||
], | |||
"createSql": "CREATE INDEX `index_folder_name` ON `${TABLE_NAME}` (`name`)" | |||
}, | |||
{ | |||
"name": "index_folder_type", | |||
"unique": false, | |||
"columnNames": [ | |||
"type" | |||
], | |||
"createSql": "CREATE INDEX `index_folder_type` ON `${TABLE_NAME}` (`type`)" | |||
} | |||
], | |||
"foreignKeys": [ | |||
{ | |||
"table": "account", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"account" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
} | |||
] | |||
}, | |||
{ | |||
"tableName": "message", | |||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` INTEGER, `folder` INTEGER NOT NULL, `identity` INTEGER, `replying` INTEGER, `uid` INTEGER, `msgid` TEXT, `references` TEXT, `inreplyto` TEXT, `thread` TEXT, `from` TEXT, `to` TEXT, `cc` TEXT, `bcc` TEXT, `reply` TEXT, `subject` TEXT, `sent` INTEGER, `received` INTEGER NOT NULL, `stored` INTEGER NOT NULL, `seen` INTEGER NOT NULL, `ui_seen` INTEGER NOT NULL, `ui_hide` INTEGER NOT NULL, `ui_found` INTEGER NOT NULL, `error` TEXT, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`folder`) REFERENCES `folder`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`identity`) REFERENCES `identity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`replying`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", | |||
"fields": [ | |||
{ | |||
"fieldPath": "id", | |||
"columnName": "id", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "account", | |||
"columnName": "account", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "folder", | |||
"columnName": "folder", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "identity", | |||
"columnName": "identity", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "replying", | |||
"columnName": "replying", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "uid", | |||
"columnName": "uid", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "msgid", | |||
"columnName": "msgid", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "references", | |||
"columnName": "references", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "inreplyto", | |||
"columnName": "inreplyto", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "thread", | |||
"columnName": "thread", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "from", | |||
"columnName": "from", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "to", | |||
"columnName": "to", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "cc", | |||
"columnName": "cc", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "bcc", | |||
"columnName": "bcc", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "reply", | |||
"columnName": "reply", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "subject", | |||
"columnName": "subject", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "sent", | |||
"columnName": "sent", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "received", | |||
"columnName": "received", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "stored", | |||
"columnName": "stored", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "seen", | |||
"columnName": "seen", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "ui_seen", | |||
"columnName": "ui_seen", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "ui_hide", | |||
"columnName": "ui_hide", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "ui_found", | |||
"columnName": "ui_found", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "error", | |||
"columnName": "error", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
} | |||
], | |||
"primaryKey": { | |||
"columnNames": [ | |||
"id" | |||
], | |||
"autoGenerate": true | |||
}, | |||
"indices": [ | |||
{ | |||
"name": "index_message_account", | |||
"unique": false, | |||
"columnNames": [ | |||
"account" | |||
], | |||
"createSql": "CREATE INDEX `index_message_account` ON `${TABLE_NAME}` (`account`)" | |||
}, | |||
{ | |||
"name": "index_message_folder", | |||
"unique": false, | |||
"columnNames": [ | |||
"folder" | |||
], | |||
"createSql": "CREATE INDEX `index_message_folder` ON `${TABLE_NAME}` (`folder`)" | |||
}, | |||
{ | |||
"name": "index_message_identity", | |||
"unique": false, | |||
"columnNames": [ | |||
"identity" | |||
], | |||
"createSql": "CREATE INDEX `index_message_identity` ON `${TABLE_NAME}` (`identity`)" | |||
}, | |||
{ | |||
"name": "index_message_replying", | |||
"unique": false, | |||
"columnNames": [ | |||
"replying" | |||
], | |||
"createSql": "CREATE INDEX `index_message_replying` ON `${TABLE_NAME}` (`replying`)" | |||
}, | |||
{ | |||
"name": "index_message_folder_uid", | |||
"unique": true, | |||
"columnNames": [ | |||
"folder", | |||
"uid" | |||
], | |||
"createSql": "CREATE UNIQUE INDEX `index_message_folder_uid` ON `${TABLE_NAME}` (`folder`, `uid`)" | |||
}, | |||
{ | |||
"name": "index_message_msgid_folder", | |||
"unique": true, | |||
"columnNames": [ | |||
"msgid", | |||
"folder" | |||
], | |||
"createSql": "CREATE UNIQUE INDEX `index_message_msgid_folder` ON `${TABLE_NAME}` (`msgid`, `folder`)" | |||
}, | |||
{ | |||
"name": "index_message_thread", | |||
"unique": false, | |||
"columnNames": [ | |||
"thread" | |||
], | |||
"createSql": "CREATE INDEX `index_message_thread` ON `${TABLE_NAME}` (`thread`)" | |||
}, | |||
{ | |||
"name": "index_message_received", | |||
"unique": false, | |||
"columnNames": [ | |||
"received" | |||
], | |||
"createSql": "CREATE INDEX `index_message_received` ON `${TABLE_NAME}` (`received`)" | |||
}, | |||
{ | |||
"name": "index_message_ui_seen", | |||
"unique": false, | |||
"columnNames": [ | |||
"ui_seen" | |||
], | |||
"createSql": "CREATE INDEX `index_message_ui_seen` ON `${TABLE_NAME}` (`ui_seen`)" | |||
}, | |||
{ | |||
"name": "index_message_ui_hide", | |||
"unique": false, | |||
"columnNames": [ | |||
"ui_hide" | |||
], | |||
"createSql": "CREATE INDEX `index_message_ui_hide` ON `${TABLE_NAME}` (`ui_hide`)" | |||
} | |||
], | |||
"foreignKeys": [ | |||
{ | |||
"table": "account", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"account" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
}, | |||
{ | |||
"table": "folder", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"folder" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
}, | |||
{ | |||
"table": "identity", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"identity" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
}, | |||
{ | |||
"table": "message", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"replying" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
} | |||
] | |||
}, | |||
{ | |||
"tableName": "attachment", | |||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` INTEGER NOT NULL, `sequence` INTEGER NOT NULL, `name` TEXT, `type` TEXT NOT NULL, `size` INTEGER, `progress` INTEGER, `available` INTEGER NOT NULL, FOREIGN KEY(`message`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", | |||
"fields": [ | |||
{ | |||
"fieldPath": "id", | |||
"columnName": "id", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "message", | |||
"columnName": "message", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "sequence", | |||
"columnName": "sequence", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "name", | |||
"columnName": "name", | |||
"affinity": "TEXT", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "type", | |||
"columnName": "type", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "size", | |||
"columnName": "size", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "progress", | |||
"columnName": "progress", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "available", | |||
"columnName": "available", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
} | |||
], | |||
"primaryKey": { | |||
"columnNames": [ | |||
"id" | |||
], | |||
"autoGenerate": true | |||
}, | |||
"indices": [ | |||
{ | |||
"name": "index_attachment_message", | |||
"unique": false, | |||
"columnNames": [ | |||
"message" | |||
], | |||
"createSql": "CREATE INDEX `index_attachment_message` ON `${TABLE_NAME}` (`message`)" | |||
}, | |||
{ | |||
"name": "index_attachment_message_sequence", | |||
"unique": true, | |||
"columnNames": [ | |||
"message", | |||
"sequence" | |||
], | |||
"createSql": "CREATE UNIQUE INDEX `index_attachment_message_sequence` ON `${TABLE_NAME}` (`message`, `sequence`)" | |||
} | |||
], | |||
"foreignKeys": [ | |||
{ | |||
"table": "message", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"message" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
} | |||
] | |||
}, | |||
{ | |||
"tableName": "operation", | |||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `folder` INTEGER NOT NULL, `message` INTEGER NOT NULL, `name` TEXT NOT NULL, `args` TEXT NOT NULL, `created` INTEGER NOT NULL, FOREIGN KEY(`folder`) REFERENCES `folder`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`message`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", | |||
"fields": [ | |||
{ | |||
"fieldPath": "id", | |||
"columnName": "id", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "folder", | |||
"columnName": "folder", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "message", | |||
"columnName": "message", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "name", | |||
"columnName": "name", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "args", | |||
"columnName": "args", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "created", | |||
"columnName": "created", | |||
"affinity": "INTEGER", | |||
"notNull": true | |||
} | |||
], | |||
"primaryKey": { | |||
"columnNames": [ | |||
"id" | |||
], | |||
"autoGenerate": true | |||
}, | |||
"indices": [ | |||
{ | |||
"name": "index_operation_folder", | |||
"unique": false, | |||
"columnNames": [ | |||
"folder" | |||
], | |||
"createSql": "CREATE INDEX `index_operation_folder` ON `${TABLE_NAME}` (`folder`)" | |||
}, | |||
{ | |||
"name": "index_operation_message", | |||
"unique": false, | |||
"columnNames": [ | |||
"message" | |||
], | |||
"createSql": "CREATE INDEX `index_operation_message` ON `${TABLE_NAME}` (`message`)" | |||
} | |||
], | |||
"foreignKeys": [ | |||
{ | |||
"table": "folder", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"folder" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
}, | |||
{ | |||
"table": "message", | |||
"onDelete": "CASCADE", | |||
"onUpdate": "NO ACTION", | |||
"columns": [ | |||
"message" | |||
], | |||
"referencedColumns": [ | |||
"id" | |||
] | |||
} | |||
] | |||
}, | |||
{ | |||
"tableName": "answer", | |||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `text` TEXT NOT NULL)", | |||
"fields": [ | |||
{ | |||
"fieldPath": "id", | |||
"columnName": "id", | |||
"affinity": "INTEGER", | |||
"notNull": false | |||
}, | |||
{ | |||
"fieldPath": "name", | |||
"columnName": "name", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
}, | |||
{ | |||
"fieldPath": "text", | |||
"columnName": "text", | |||
"affinity": "TEXT", | |||
"notNull": true | |||
} | |||
], | |||
"primaryKey": { | |||
"columnNames": [ | |||
"id" | |||
], | |||
"autoGenerate": true | |||
}, | |||
"indices": [], | |||
"foreignKeys": [] | |||
} | |||
], | |||
"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, \"e9ae946be1049502f01f8f30275abc2f\")" | |||
] | |||
} | |||
} |
@ -1,241 +0,0 @@ | |||
package eu.faircode.email; | |||
import android.content.Context; | |||
import android.os.Handler; | |||
import android.os.Looper; | |||
import android.text.TextUtils; | |||
import android.util.Log; | |||
import android.util.SparseArray; | |||
import android.widget.Toast; | |||
import com.sun.mail.imap.IMAPFolder; | |||
import com.sun.mail.imap.IMAPStore; | |||
import java.io.IOException; | |||
import java.io.UnsupportedEncodingException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Properties; | |||
import javax.mail.FetchProfile; | |||
import javax.mail.Folder; | |||
import javax.mail.Message; | |||
import javax.mail.MessagingException; | |||
import javax.mail.Session; | |||
import javax.mail.UIDFolder; | |||
import javax.mail.internet.MimeMessage; | |||
import javax.mail.search.BodyTerm; | |||
import javax.mail.search.FromStringTerm; | |||
import javax.mail.search.OrTerm; | |||
import javax.mail.search.SubjectTerm; | |||
import androidx.lifecycle.Lifecycle; | |||
import androidx.lifecycle.LifecycleObserver; | |||
import androidx.lifecycle.LifecycleOwner; | |||
import androidx.lifecycle.OnLifecycleEvent; | |||
import androidx.paging.PositionalDataSource; | |||
public class SearchDataSource extends PositionalDataSource<TupleMessageEx> implements LifecycleObserver { | |||
private Context context; | |||
private LifecycleOwner owner; | |||
private long fid; | |||
private String search; | |||
private EntityFolder folder; | |||
private EntityAccount account; | |||
private IMAPStore istore = null; | |||
private IMAPFolder ifolder; | |||
private Message[] imessages; | |||
private SparseArray<TupleMessageEx> cache = new SparseArray<>(); | |||
private static final float MAX_MEMORY_USAGE = 0.6f; // percent | |||
SearchDataSource(Context context, LifecycleOwner owner, long folder, String search) { | |||
Log.i(Helper.TAG, "SDS create"); | |||
this.context = context; | |||
this.owner = owner; | |||
this.fid = folder; | |||
this.search = search; | |||
owner.getLifecycle().addObserver(this); | |||
} | |||
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) | |||
public void onDestroyed() { | |||
Log.i(Helper.TAG, "SDS destroy"); | |||
new Thread(new Runnable() { | |||
@Override | |||
public void run() { | |||
try { | |||
if (istore != null) | |||
istore.close(); | |||
} catch (MessagingException ex) { | |||
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); | |||
} finally { | |||
istore = null; | |||
ifolder = null; | |||
imessages = null; | |||
cache.clear(); | |||
} | |||
} | |||
}).start(); | |||
owner.getLifecycle().removeObserver(this); | |||
} | |||
@Override | |||
public void loadInitial(LoadInitialParams params, LoadInitialCallback<TupleMessageEx> callback) { | |||
Log.i(Helper.TAG, "SDS load initial"); | |||
try { | |||
SearchResult result = search(search, params.requestedStartPosition, params.requestedLoadSize); | |||
callback.onResult(result.messages, params.requestedStartPosition, result.total); | |||
} catch (Throwable ex) { | |||
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); | |||
reportError(ex); | |||
} | |||
} | |||
@Override | |||
public void loadRange(LoadRangeParams params, LoadRangeCallback<TupleMessageEx> callback) { | |||
Log.i(Helper.TAG, "SDS load range"); | |||
try { | |||
SearchResult result = search(search, params.startPosition, params.loadSize); | |||
callback.onResult(result.messages); | |||
} catch (Throwable ex) { | |||
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); | |||
reportError(ex); | |||
} | |||
} | |||
private SearchResult search(String term, int from, int count) throws MessagingException, IOException { | |||
Log.i(Helper.TAG, "SDS search from=" + from + " count=" + count); | |||
if (istore == null) { | |||
DB db = DB.getInstance(context); | |||
folder = db.folder().getFolder(fid); | |||
account = db.account().getAccount(folder.account); | |||
// Refresh token | |||
if (account.auth_type == Helper.AUTH_TYPE_GMAIL) { | |||
account.password = Helper.refreshToken(context, "com.google", account.user, account.password); | |||
db.account().setAccountPassword(account.id, account.password); | |||
} | |||
Properties props = MessageHelper.getSessionProperties(context, account.auth_type); | |||
props.setProperty("mail.imap.throwsearchexception", "true"); | |||
Session isession = Session.getInstance(props, null); | |||
Log.i(Helper.TAG, "SDS connecting account=" + account.name); | |||
istore = (IMAPStore) isession.getStore("imaps"); | |||
istore.connect(account.host, account.port, account.user, account.password); | |||
Log.i(Helper.TAG, "SDS opening folder=" + folder.name); | |||
ifolder = (IMAPFolder) istore.getFolder(folder.name); | |||
ifolder.open(Folder.READ_WRITE); | |||
Log.i(Helper.TAG, "SDS searching term=" + term); | |||
imessages = ifolder.search( | |||
new OrTerm( | |||
new FromStringTerm(term), | |||
new OrTerm( | |||
new SubjectTerm(term), | |||
new BodyTerm(term)))); | |||
Log.i(Helper.TAG, "SDS found messages=" + imessages.length); | |||
} | |||
SearchResult result = new SearchResult(); | |||
result.total = imessages.length; | |||
result.messages = new ArrayList<>(); | |||
List<Message> selected = new ArrayList<>(); | |||
int base = imessages.length - 1 - from; | |||
for (int i = base; i >= 0 && i >= base - count + 1; i--) | |||
selected.add(imessages[i]); | |||
Log.i(Helper.TAG, "SDS selected messages=" + selected.size()); | |||
FetchProfile fp = new FetchProfile(); | |||
fp.add(UIDFolder.FetchProfileItem.UID); | |||
fp.add(IMAPFolder.FetchProfileItem.FLAGS); | |||
fp.add(FetchProfile.Item.ENVELOPE); | |||
fp.add(FetchProfile.Item.CONTENT_INFO); | |||
fp.add(IMAPFolder.FetchProfileItem.HEADERS); | |||
fp.add(IMAPFolder.FetchProfileItem.MESSAGE); | |||
ifolder.fetch(selected.toArray(new Message[0]), fp); | |||
for (int s = 0; s < selected.size(); s++) { | |||
int pos = from + s; | |||
if (cache.get(pos) != null) { | |||
Log.i(Helper.TAG, "SDS from cache pos=" + pos); | |||
result.messages.add(cache.get(pos)); | |||
continue; | |||
} | |||
Message imessage = selected.get(s); | |||
long uid = ifolder.getUID(imessage); | |||
MessageHelper helper = new MessageHelper((MimeMessage) imessage); | |||
boolean seen = helper.getSeen(); | |||
TupleMessageEx message = new TupleMessageEx(); | |||
message.id = uid; | |||
message.account = folder.account; | |||
message.folder = folder.id; | |||
message.uid = uid; | |||
message.msgid = helper.getMessageID(); | |||
message.references = TextUtils.join(" ", helper.getReferences()); | |||
message.inreplyto = helper.getInReplyTo(); | |||
message.thread = helper.getThreadId(uid); | |||
message.from = helper.getFrom(); | |||
message.to = helper.getTo(); | |||
message.cc = helper.getCc(); | |||
message.bcc = helper.getBcc(); | |||
message.reply = helper.getReply(); | |||
message.subject = imessage.getSubject(); | |||
message.received = imessage.getReceivedDate().getTime(); | |||
message.sent = (imessage.getSentDate() == null ? null : imessage.getSentDate().getTime()); | |||
message.seen = seen; | |||
message.ui_seen = seen; | |||
message.ui_hide = false; | |||
message.accountName = account.name; | |||
message.folderName = folder.name; | |||
message.folderType = folder.type; | |||
message.count = 1; | |||
message.unseen = (seen ? 0 : 1); | |||
message.attachments = 0; | |||
message.body = helper.getHtml(); | |||
message.virtual = true; | |||
result.messages.add(message); | |||
Runtime rt = Runtime.getRuntime(); | |||
float used = (float) (rt.totalMemory() - rt.freeMemory()) / rt.maxMemory(); | |||
if (used < MAX_MEMORY_USAGE) | |||
cache.put(pos, message); | |||
else | |||
Log.i(Helper.TAG, "SDS memory used=" + used); | |||
} | |||
Log.i(Helper.TAG, "SDS result=" + result.messages.size()); | |||
return result; | |||
} | |||
private void reportError(final Throwable ex) { | |||
new Handler(Looper.getMainLooper()).post(new Runnable() { | |||
@Override | |||
public void run() { | |||
Toast.makeText(context, Helper.formatThrowable(ex), Toast.LENGTH_LONG).show(); | |||
} | |||
}); | |||
} | |||
private class SearchResult { | |||
int total; | |||
List<TupleMessageEx> messages; | |||
} | |||
} |