import 'dart:io'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart' show openDatabase, Database, OpenDatabaseOptions; import 'package:sqflite_common_ffi/sqflite_ffi.dart' show sqfliteFfiInit, databaseFactoryFfi; /// 数据库单例 —— 桌面端用 FFI, 移动端用原生 sqflite class AppDatabase { AppDatabase._(); static final AppDatabase instance = AppDatabase._(); static Database? _db; static bool _isDesktop() => Platform.isWindows || Platform.isLinux || Platform.isMacOS; Future get database async { if (_db != null) return _db!; final dir = await getApplicationSupportDirectory(); final path = p.join(dir.path, 'mail_hub.db'); if (_isDesktop()) { sqfliteFfiInit(); _db = await databaseFactoryFfi.openDatabase( path, options: OpenDatabaseOptions( version: 1, onCreate: (db, version) async { await _createTables(db); }, ), ); } else { _db = await openDatabase( path, version: 1, onCreate: (db, version) async { await _createTables(db); }, ); } return _db!; } static Future _createTables(Database db) async { await db.execute(''' CREATE TABLE accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, display_name TEXT DEFAULT '', provider TEXT DEFAULT 'custom', imap_host TEXT NOT NULL, imap_port INTEGER NOT NULL, imap_ssl INTEGER DEFAULT 1, smtp_host TEXT NOT NULL, smtp_port INTEGER NOT NULL, smtp_ssl INTEGER DEFAULT 1, username TEXT DEFAULT '', signature TEXT DEFAULT '', enabled INTEGER DEFAULT 1, last_sync_at INTEGER, color INTEGER DEFAULT 4278190051 ) '''); await db.execute(''' CREATE TABLE folders ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, name TEXT NOT NULL, delim TEXT DEFAULT '/', attrs TEXT DEFAULT '', subscribed INTEGER DEFAULT 1, UNIQUE(account_id, name) ) '''); await db.execute(''' CREATE TABLE emails ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, folder TEXT NOT NULL, uid INTEGER NOT NULL, message_id TEXT DEFAULT '', in_reply_to TEXT DEFAULT '', references TEXT DEFAULT '', subject TEXT DEFAULT '', from_name TEXT DEFAULT '', from_addr TEXT DEFAULT '', to_json TEXT DEFAULT '', cc_json TEXT DEFAULT '', bcc_json TEXT DEFAULT '', reply_to_json TEXT DEFAULT '', date INTEGER, size INTEGER DEFAULT 0, seen INTEGER DEFAULT 1, flagged INTEGER DEFAULT 0, answered INTEGER DEFAULT 0, deleted INTEGER DEFAULT 0, draft INTEGER DEFAULT 0, snippet TEXT DEFAULT '', has_attachments INTEGER DEFAULT 0, body_html TEXT, body_text TEXT, attachments_json TEXT DEFAULT '', headers_json TEXT DEFAULT '', fetched INTEGER DEFAULT 0, UNIQUE(account_id, folder, uid) ) '''); await db.execute( 'CREATE INDEX idx_emails_folder ON emails(account_id, folder, date DESC)'); await db.execute(''' CREATE TABLE contacts ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER, email TEXT NOT NULL, name TEXT DEFAULT '', last_used INTEGER DEFAULT 0, UNIQUE(account_id, email) ) '''); await db.execute(''' CREATE TABLE prefs ( key TEXT PRIMARY KEY, value TEXT ) '''); } Future close() async { await _db?.close(); _db = null; } }