|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:huixiang/im/database/message.dart';
|
|
|
|
import 'package:huixiang/im/database/migration.dart';
|
|
|
|
import 'package:sqflite/sqflite.dart';
|
|
|
|
|
|
|
|
import '../../retrofit/data/im_user_list.dart';
|
|
|
|
|
|
|
|
class HxDatabase {
|
|
|
|
Database db;
|
|
|
|
|
|
|
|
void open({String key}) async {
|
|
|
|
// _migrations.add(Migration(1, 2, (Database database) async {
|
|
|
|
// database.execute('ALTER TABLE `Message` ADD COLUMN `replyId` VARCHAR(20) DEFAULT NULL AFTER `toId`');
|
|
|
|
// }));
|
|
|
|
|
|
|
|
String databaseName = 'hx.db';
|
|
|
|
if (key?.isNotEmpty ?? false) {
|
|
|
|
databaseName = 'hx_$key.db';
|
|
|
|
}
|
|
|
|
await openDatabase(databaseName, version: 2,
|
|
|
|
onCreate: (Database db, int version) async {
|
|
|
|
db.execute(
|
|
|
|
'CREATE TABLE IF NOT EXISTS `Message` (`id` INTEGER, `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, PRIMARY KEY (`id`))');
|
|
|
|
}, onConfigure: (database) async {
|
|
|
|
await database.execute('PRAGMA foreign_keys = ON');
|
|
|
|
}, onUpgrade: (database, startVersion, endVersion) async {
|
|
|
|
await runMigrations(database, startVersion, endVersion, _migrations);
|
|
|
|
}, onOpen: (Database db) {
|
|
|
|
this.db = db;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void close() {
|
|
|
|
db.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<Message> lastMessage(String userId) async {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value();
|
|
|
|
}
|
|
|
|
String sql =
|
|
|
|
'SELECT * FROM Message WHERE toId = ? OR fromId = ? ORDER BY time DESC LIMIT 1';
|
|
|
|
List<Message> messages =
|
|
|
|
await db.rawQuery(sql, [userId, userId]).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<List<Message>> queryList(userId) {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value(<Message>[]);
|
|
|
|
}
|
|
|
|
String sql =
|
|
|
|
'SELECT * FROM Message WHERE toId = ? OR fromId = ? GROUP BY toId,fromId ORDER BY time DESC';
|
|
|
|
return db.rawQuery(sql, [userId, userId]).then((value) {
|
|
|
|
return value.map((e) {
|
|
|
|
debugPrint("Message: ${e}");
|
|
|
|
return Message.fromJson(e);
|
|
|
|
}).toList();
|
|
|
|
}, onError: (error) {
|
|
|
|
debugPrint("Messageerror: $error");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<List<Message>> queryUList(userId) {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value(<Message>[]);
|
|
|
|
}
|
|
|
|
String sql =
|
|
|
|
'SELECT * FROM Message WHERE toId = ? OR fromId = ? ORDER BY time DESC';
|
|
|
|
return db.rawQuery(sql, [userId, userId]).then((value) {
|
|
|
|
return value.map((e) => Message.fromJson(e)).toList();
|
|
|
|
}, onError: (error) {
|
|
|
|
debugPrint("Messageerror: $error");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<Map<String, int>> messageUnreadCount(List<String> userIds, String selfUserId) async {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value({});
|
|
|
|
}
|
|
|
|
List<Message> messages = await db.query(
|
|
|
|
"Message",
|
|
|
|
where: 'fromId IN (?) AND toId = ? AND state = 0 AND isDelete = 0',
|
|
|
|
whereArgs: []..addAll(userIds)..add(selfUserId)
|
|
|
|
).then((value) {
|
|
|
|
return value.map((e) => Message.fromJson(e)).toList();
|
|
|
|
}, onError: (error) {
|
|
|
|
debugPrint("Message-error: $error");
|
|
|
|
});
|
|
|
|
return messages.lGroupBy((p)=> p.fromId).mGroupCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<List<Map>> queryListAll() {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value();
|
|
|
|
}
|
|
|
|
String sql = 'SELECT * FROM Message ORDER BY time DESC';
|
|
|
|
return db.rawQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<int> deleteAll() async {
|
|
|
|
return db.delete("Message");
|
|
|
|
}
|
|
|
|
|
|
|
|
update(Map<dynamic, dynamic> message) {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value(0);
|
|
|
|
}
|
|
|
|
debugPrint("Message_insert: $message");
|
|
|
|
return db.update("Message", message,
|
|
|
|
where: 'id = ?', whereArgs: [message['id']]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<int> insert(Map message) async {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value(0);
|
|
|
|
}
|
|
|
|
debugPrint("Message_insert: $message");
|
|
|
|
return db.insert("Message", message);
|
|
|
|
}
|
|
|
|
/// update message read state
|
|
|
|
readMessage(String selfUserId, String userId) {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value(<Message>[]);
|
|
|
|
}
|
|
|
|
db.update("Message", {"state": 1}, where: "fromId = ? AND toId = ? AND state = 0 AND isDelete = 0", whereArgs: [userId, selfUserId]);
|
|
|
|
}
|
|
|
|
Future<int> insertOrUpdateImUser(Map imUserMap) async {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value(0);
|
|
|
|
}
|
|
|
|
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<List<ImUserList>> queryImUser(List<String> userIds) async {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value(<ImUserList>[]);
|
|
|
|
}
|
|
|
|
String query = 'SELECT * FROM ImUser WHERE mid IN (${userIds.map((mid) => "'$mid'").join(',')})';
|
|
|
|
return db.rawQuery(query).then((value) {
|
|
|
|
return value.map((e) => ImUserList.fromJson(e)).toList();
|
|
|
|
}, onError: (error) {
|
|
|
|
debugPrint("ImUser_error: $error");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<ImUserList> queryImUserById(String userId) async {
|
|
|
|
if (db == null) {
|
|
|
|
return Future.value();
|
|
|
|
}
|
|
|
|
List<ImUserList> imUser = await db.query("ImUser",
|
|
|
|
distinct: true, where: "mid = ?", whereArgs: [userId]).then((value) {
|
|
|
|
return value.map((e) => ImUserList.fromJson(e)).toList();
|
|
|
|
}, onError: (error) {
|
|
|
|
debugPrint("ImUser_error: $error");
|
|
|
|
});
|
|
|
|
return (imUser?.isNotEmpty ?? false) ? imUser.first : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
final List<Migration> _migrations = [];
|
|
|
|
|
|
|
|
addMigrations(List<Migration> migrations) {
|
|
|
|
_migrations.addAll(migrations);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> runMigrations(
|
|
|
|
final Database migrationDatabase,
|
|
|
|
final int startVersion,
|
|
|
|
final int endVersion,
|
|
|
|
final List<Migration> 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|