import 'package:flutter/cupertino.dart'; import 'package:huixiang/constant.dart'; import 'package:huixiang/im/database/message.dart'; import 'package:huixiang/im/database/migration.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sqflite/sqflite.dart'; import '../../retrofit/data/im_user.dart'; class HxDatabase { Database db; void open({String key}) async { // _migrations.add(Migration(3, 4, (Database database) async { // await database.execute('ALTER TABLE ImUser ADD COLUMN IF NOT EXISTS `isTop` INTEGER DEFAULT 0'); // })); String databaseName = 'hx.db'; if (key?.isNotEmpty ?? false) { databaseName = 'hx_$key.db'; } await openDatabase(databaseName, version: 1, onCreate: (Database db, int version) async { db.execute('CREATE TABLE IF NOT EXISTS `Message` (`id` INTEGER, `conversationId` VARCHAR(40), `fromId` VARCHAR(20), `toId` VARCHAR(20), `replyId` VARCHAR(20), `content` TEXT, `attach` TEXT, `msgType` INTEGER, `time` VARCHAR(20), `state` INTEGER, `isDelete` INTEGER, PRIMARY KEY (`id`))'); db.execute('CREATE TABLE IF NOT EXISTS `ImUser` (`id` INTEGER, `mid` VARCHAR(20), `nickname` VARCHAR(20), `avatar` VARCHAR(200), `phone` VARCHAR(200), `isDelete` INTEGER, `isTop` INTEGER, PRIMARY KEY (`id`))'); }, onConfigure: (database) async { await database.execute('PRAGMA foreign_keys = ON'); debugPrint("database-version: ${await database.getVersion()}"); }, onUpgrade: (database, startVersion, endVersion) async { await runMigrations(database, startVersion, endVersion, _migrations); }, onOpen: (Database db) { this.db = db; }); } void close() { db.close(); } _dbIsOpen() async { if (db == null || !db.isOpen) { var sp = await SharedPreferences.getInstance(); open(key: sp.getString("userId")); } } Future lastMessage(String conversationId) async { await _dbIsOpen(); String sql = 'SELECT * FROM Message WHERE conversationId = ? ORDER BY time DESC LIMIT 1'; List messages = await db.rawQuery(sql, [conversationId]).then((value) { return value.map((e) { debugPrint("Message: $e"); return Message.fromJson(e); }).toList(); }, onError: (error) { debugPrint("Message_error: $error"); }); return (messages?.isNotEmpty ?? false) ? messages.first : null; } Future> queryList() async{ await _dbIsOpen(); String sql = '''SELECT * FROM `Message` WHERE ROWID IN ( SELECT ROWID FROM ( SELECT ROWID, conversationId, MAX(`time`) AS max_time FROM `Message` GROUP BY conversationId ) AS grouped_messages WHERE max_time = ( SELECT MAX(`time`) FROM `Message` WHERE conversationId = grouped_messages.conversationId ) ) ORDER BY `time` DESC;'''; return db.rawQuery(sql).then((value) { return value.map((e) { debugPrint("Message: $e"); return Message.fromJson(e); }).toList(); }, onError: (error) { debugPrint("Message-error: $error"); }); } Future> queryUList(conversationId, {int page = 1, int pageSize = 10}) async{ await _dbIsOpen(); int start = (page - 1) * pageSize; String sql = 'SELECT * FROM Message WHERE conversationId = ? ORDER BY time DESC LIMIT ?, ?'; return db.rawQuery(sql, [conversationId, start, pageSize]).then((value) { return value.map((e) => Message.fromJson(e)).toList(); }, onError: (error) { debugPrint("Message-error: $error"); }); } Future> queryTList(conversationId) async{ await _dbIsOpen(); String sql = 'SELECT *, time / 300000 * 300000 AS time_interval FROM Message WHERE conversationId = ? GROUP BY time_interval ORDER BY time DESC'; return db.rawQuery(sql, [conversationId]).then((value) { return value.map((e) => Message.fromJson(e)).toList(); }, onError: (error) { debugPrint("Message-error: $error"); }); } Future> messageUnreadCount(List conversationIds) async { await _dbIsOpen(); String userStr = conversationIds.join("','"); debugPrint("userStr: $userStr"); List messages = await db.query("Message", where: "conversationId IN ('$userStr') AND state = 0 AND isDelete = 0", whereArgs: [], ).then((value) { return value.map((e) => Message.fromJson(e)).toList(); }, onError: (error) { debugPrint("Message-error: $error"); }); return (messages??[]).lGroupBy((p) => p.conversationId).mGroupCount; } Future> queryListAll() async{ await _dbIsOpen(); String sql = 'SELECT * FROM Message ORDER BY time DESC'; return db.rawQuery(sql); } Future deleteByUser(String conversationId) async { return db.delete("Message",where: "conversationId = ?", whereArgs: [conversationId]); } Future deleteAll() async { return db.delete("Message"); } update(Map message) async{ await _dbIsOpen(); debugPrint("Message_insert: $message"); return db.update("Message", message, where: 'id = ?', whereArgs: [message['id']]); } Future insert(Map message) async { await _dbIsOpen(); debugPrint("Message_insert: $message"); return db.insert("Message", message); } /// update message read state readMessage(String conversationId) async{ await _dbIsOpen(); db.update("Message", {"state": 1}, where: "conversationId = ? AND state = 0 AND isDelete = 0", whereArgs: [conversationId]); } Future insertOrUpdateImUser(Map imUserMap) async { await _dbIsOpen(); debugPrint("imUser_insert: $imUserMap"); if ((await queryImUserById(imUserMap['mid'])) == null) return db.insert("ImUser", imUserMap); else return db.update("ImUser", imUserMap, where: 'mid = ?', whereArgs: [imUserMap['mid']]); } Future> queryImUser(List userIds) async { await _dbIsOpen(); String query = 'SELECT * FROM ImUser WHERE mid IN (${userIds.map((mid) => "'$mid'").join(',')})'; return db.rawQuery(query).then((value) { return value.map((e) => ImUser.fromJson(e)).toList(); }, onError: (error) { debugPrint("ImUser_error: $error"); }); } Future queryImUserById(String userId) async { await _dbIsOpen(); List imUser = await db.query("ImUser", distinct: true, where: "mid = ?", whereArgs: [userId]).then((value) { return value.map((e) => ImUser.fromJson(e)).toList(); }, onError: (error) { debugPrint("ImUser_error: $error"); }); return (imUser?.isNotEmpty ?? false) ? imUser.first : null; } final List _migrations = []; addMigrations(List migrations) { _migrations.addAll(migrations); return this; } Future runMigrations( final Database migrationDatabase, final int startVersion, final int endVersion, final List migrations, ) async { final relevantMigrations = migrations .where((migration) => migration.startVersion >= startVersion) .toList() ..sort( (first, second) => first.startVersion.compareTo(second.startVersion)); if (relevantMigrations.isEmpty || relevantMigrations.last.endVersion != endVersion) { throw StateError( 'There is no migration supplied to update the database to the current version.' ' Aborting the migration.', ); } for (final migration in relevantMigrations) { await migration.migrate(migrationDatabase); } } }