176 lines
5.4 KiB
Dart
176 lines
5.4 KiB
Dart
import 'package:sqflite/sqflite.dart';
|
||
import 'package:path/path.dart';
|
||
import 'package:chepuhagram/data/models/message_model.dart';
|
||
|
||
class LocalDbService {
|
||
static final LocalDbService _instance = LocalDbService._internal();
|
||
static Database? _database;
|
||
|
||
factory LocalDbService() => _instance;
|
||
LocalDbService._internal();
|
||
|
||
Future<Database> get database async {
|
||
if (_database != null) return _database!;
|
||
_database = await _initDb();
|
||
return _database!;
|
||
}
|
||
|
||
Future<Database> _initDb() async {
|
||
String path = join(await getDatabasesPath(), 'chat_app.db');
|
||
return await openDatabase(
|
||
path,
|
||
version: 4,
|
||
onCreate: (db, version) async {
|
||
await db.execute('''
|
||
CREATE TABLE messages(
|
||
id INTEGER PRIMARY KEY,
|
||
sender_id INTEGER,
|
||
receiver_id INTEGER,
|
||
content TEXT,
|
||
timestamp TEXT,
|
||
delivered_at TEXT,
|
||
read_at TEXT,
|
||
reply_to_id INTEGER,
|
||
reply_to_text TEXT,
|
||
edited_at TEXT
|
||
)
|
||
''');
|
||
},
|
||
onUpgrade: (db, oldVersion, newVersion) async {
|
||
if (oldVersion < 2) {
|
||
await db.execute('ALTER TABLE messages ADD COLUMN delivered_at TEXT');
|
||
await db.execute('ALTER TABLE messages ADD COLUMN read_at TEXT');
|
||
}
|
||
if (oldVersion < 3) {
|
||
await db.execute(
|
||
'ALTER TABLE messages ADD COLUMN reply_to_id INTEGER',
|
||
);
|
||
await db.execute(
|
||
'ALTER TABLE messages ADD COLUMN reply_to_text TEXT',
|
||
);
|
||
}
|
||
if (oldVersion < 4) {
|
||
await db.execute('ALTER TABLE messages ADD COLUMN edited_at TEXT');
|
||
}
|
||
},
|
||
);
|
||
}
|
||
|
||
// Сохранение списка сообщений (из истории)
|
||
Future<void> saveMessages(List<dynamic> messages) async {
|
||
final db = await database;
|
||
Batch batch = db.batch();
|
||
for (var msg in messages) {
|
||
if (msg is MessageModel) {
|
||
batch.insert('messages', {
|
||
'id': msg.id,
|
||
'sender_id': msg.senderId,
|
||
'receiver_id': msg.receiverId,
|
||
'content': msg.text, // ВАЖНО: сохраняй зашифрованный текст!
|
||
'timestamp': msg.createdAt.toIso8601String(),
|
||
'delivered_at': null,
|
||
'read_at': null,
|
||
'reply_to_id': msg.replyToId,
|
||
'reply_to_text': msg.replyToText,
|
||
'edited_at': msg.editedAt?.toIso8601String(),
|
||
}, conflictAlgorithm: ConflictAlgorithm.replace);
|
||
} else {
|
||
// Если это Map из API
|
||
batch.insert('messages', {
|
||
'id': msg['id'],
|
||
'sender_id': msg['sender_id'],
|
||
'receiver_id':
|
||
msg['receiver_id'], // Убедись, что ключ совпадает с API
|
||
'content': msg['content'],
|
||
'timestamp': msg['timestamp'],
|
||
'delivered_at': msg['delivered_at'],
|
||
'read_at': msg['read_at'],
|
||
'reply_to_id': msg['reply_to_id'],
|
||
'reply_to_text': msg['reply_to_text'],
|
||
'edited_at': msg['edited_at'],
|
||
}, conflictAlgorithm: ConflictAlgorithm.replace);
|
||
}
|
||
}
|
||
await batch.commit(noResult: true);
|
||
}
|
||
|
||
// Получение сообщений конкретного чата
|
||
Future<List<Map<String, dynamic>>> getChatHistory(
|
||
int contactId,
|
||
int myId,
|
||
) async {
|
||
final db = await database;
|
||
return await db.query(
|
||
'messages',
|
||
where:
|
||
'(sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)',
|
||
whereArgs: [contactId, myId, myId, contactId],
|
||
orderBy: 'timestamp ASC',
|
||
);
|
||
}
|
||
|
||
Future<int> deleteChatHistory(int contactId, int myId) async {
|
||
final db = await database;
|
||
return await db.delete(
|
||
'messages',
|
||
where:
|
||
'(sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)',
|
||
whereArgs: [contactId, myId, myId, contactId],
|
||
);
|
||
}
|
||
|
||
Future<Map<String, dynamic>?> getLastMessage(int contactId, int myId) async {
|
||
final db = await database;
|
||
final rows = await db.query(
|
||
'messages',
|
||
columns: ['sender_id', 'receiver_id', 'content', 'timestamp'],
|
||
where:
|
||
'(sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)',
|
||
whereArgs: [contactId, myId, myId, contactId],
|
||
orderBy: 'timestamp DESC',
|
||
limit: 1,
|
||
);
|
||
if (rows.isEmpty) return null;
|
||
return rows.first;
|
||
}
|
||
|
||
Future<void> updateDeliveredAt(int messageId, DateTime deliveredAt) async {
|
||
final db = await database;
|
||
await db.update(
|
||
'messages',
|
||
{'delivered_at': deliveredAt.toIso8601String()},
|
||
where: 'id = ?',
|
||
whereArgs: [messageId],
|
||
);
|
||
}
|
||
|
||
Future<void> updateReadAt(int messageId, DateTime readAt) async {
|
||
final db = await database;
|
||
await db.update(
|
||
'messages',
|
||
{'read_at': readAt.toIso8601String()},
|
||
where: 'id = ?',
|
||
whereArgs: [messageId],
|
||
);
|
||
}
|
||
|
||
Future<void> updateMessageContent(
|
||
int messageId,
|
||
String content,
|
||
DateTime? editedAt,
|
||
) async {
|
||
final db = await database;
|
||
await db.update(
|
||
'messages',
|
||
{'content': content, 'edited_at': editedAt?.toIso8601String()},
|
||
where: 'id = ?',
|
||
whereArgs: [messageId],
|
||
);
|
||
}
|
||
|
||
Future<void> deleteMessage(int messageId) async {
|
||
final db = await database;
|
||
await db.delete('messages', where: 'id = ?', whereArgs: [messageId]);
|
||
}
|
||
}
|