You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
7.8 KiB
226 lines
7.8 KiB
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<Message> lastMessage(String conversationId) async { |
|
await _dbIsOpen(); |
|
String sql = 'SELECT * FROM Message WHERE conversationId = ? ORDER BY time DESC LIMIT 1'; |
|
List<Message> 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<List<Message>> 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<List<Message>> 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<List<Message>> 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<Map<String, int>> messageUnreadCount(List<String> conversationIds) async { |
|
await _dbIsOpen(); |
|
String userStr = conversationIds.join("','"); |
|
debugPrint("userStr: $userStr"); |
|
List<Message> 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<List<Map>> queryListAll() async{ |
|
await _dbIsOpen(); |
|
String sql = 'SELECT * FROM Message ORDER BY time DESC'; |
|
return db.rawQuery(sql); |
|
} |
|
|
|
Future<int> deleteByUser(String conversationId) async { |
|
return db.delete("Message",where: "conversationId = ?", whereArgs: [conversationId]); |
|
} |
|
|
|
Future<int> deleteByMsgId(String id) async { |
|
return db.delete("Message",where: "id = ?", whereArgs: [id]); |
|
} |
|
|
|
Future<int> deleteAll() async { |
|
return db.delete("Message"); |
|
} |
|
|
|
update(Map<dynamic, dynamic> message) async{ |
|
await _dbIsOpen(); |
|
debugPrint("Message_insert: $message"); |
|
return db.update("Message", message, |
|
where: 'id = ?', whereArgs: [message['id']]); |
|
} |
|
|
|
Future<int> 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<int> 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<List<ImUser>> queryImUser(List<String> 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<ImUser> queryImUserById(String userId) async { |
|
await _dbIsOpen(); |
|
List<ImUser> 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<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); |
|
} |
|
} |
|
}
|
|
|