twonly-app/lib/src/database/daos/contacts_dao.dart
2025-06-22 01:25:04 +02:00

239 lines
7.5 KiB
Dart

import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts_table.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
part 'contacts_dao.g.dart';
@DriftAccessor(tables: [Contacts])
class ContactsDao extends DatabaseAccessor<TwonlyDatabase>
with _$ContactsDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
ContactsDao(super.db);
Future<int> insertContact(ContactsCompanion contact) async {
try {
return await into(contacts).insert(contact);
} catch (e) {
return 0;
}
}
Future incFlameCounter(
int contactId, bool received, DateTime timestamp) async {
Contact contact = (await (select(contacts)
..where((t) => t.userId.equals(contactId)))
.get())
.first;
int totalMediaCounter = contact.totalMediaCounter + 1;
int flameCounter = contact.flameCounter;
if (contact.lastMessageReceived != null &&
contact.lastMessageSend != null) {
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
final twoDaysAgo = startOfToday.subtract(Duration(days: 2));
if (contact.lastMessageSend!.isBefore(twoDaysAgo) ||
contact.lastMessageReceived!.isBefore(twoDaysAgo)) {
flameCounter = 0;
}
}
Value<DateTime?> lastMessageSend = Value.absent();
Value<DateTime?> lastMessageReceived = Value.absent();
Value<DateTime?> lastFlameCounterChange = Value.absent();
if (contact.lastFlameCounterChange != null) {
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
if (contact.lastFlameCounterChange!.isBefore(startOfToday)) {
// last flame update was yesterday. check if it can be updated.
bool updateFlame = false;
if (received) {
if (contact.lastMessageSend != null &&
contact.lastMessageSend!.isAfter(startOfToday)) {
// today a message was already send -> update flame
updateFlame = true;
}
} else if (contact.lastMessageReceived != null &&
contact.lastMessageReceived!.isAfter(startOfToday)) {
// today a message was already received -> update flame
updateFlame = true;
}
if (updateFlame) {
flameCounter += 1;
lastFlameCounterChange = Value(timestamp);
}
}
} else {
// There where no message until no...
lastFlameCounterChange = Value(timestamp);
}
if (received) {
lastMessageReceived = Value(timestamp);
} else {
lastMessageSend = Value(timestamp);
}
return (update(contacts)..where((t) => t.userId.equals(contactId))).write(
ContactsCompanion(
totalMediaCounter: Value(totalMediaCounter),
lastFlameCounterChange: lastFlameCounterChange,
lastMessageReceived: lastMessageReceived,
lastMessageSend: lastMessageSend,
flameCounter: Value(flameCounter),
),
);
}
SingleOrNullSelectable<Contact> getContactByUserId(int userId) {
return select(contacts)..where((t) => t.userId.equals(userId));
}
Future deleteContactByUserId(int userId) {
return (delete(contacts)..where((t) => t.userId.equals(userId))).go();
}
Future updateContact(int userId, ContactsCompanion updatedValues) async {
await ((update(contacts)..where((c) => c.userId.equals(userId)))
.write(updatedValues));
if (updatedValues.blocked.present ||
updatedValues.displayName.present ||
updatedValues.nickName.present) {
final contact = await getContactByUserId(userId).getSingleOrNull();
if (contact != null) {
await updatePushUser(contact);
}
}
}
Future newMessageExchange(int userId) {
return updateContact(
userId,
ContactsCompanion(
lastMessageExchange: Value(DateTime.now()),
),
);
}
Stream<List<Contact>> watchNotAcceptedContacts() {
return (select(contacts)
..where((t) =>
t.accepted.equals(false) &
t.archived.equals(false) &
t.blocked.equals(false)))
.watch();
// return (select(contacts)).watch();
}
Stream<Contact?> watchContact(int userid) {
return (select(contacts)..where((t) => t.userId.equals(userid)))
.watchSingleOrNull();
}
Stream<List<Contact>> watchContactsForShareView() {
return (select(contacts)
..where((t) =>
t.accepted.equals(true) &
t.blocked.equals(false) &
t.deleted.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch();
}
Stream<List<Contact>> watchContactsForStartNewChat() {
return (select(contacts)
..where((t) => t.accepted.equals(true) & t.blocked.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch();
}
Stream<List<Contact>> watchContactsForChatList() {
return (select(contacts)
..where(
(t) =>
t.accepted.equals(true) &
t.blocked.equals(false) &
t.archived.equals(false),
)
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch();
}
Future<List<Contact>> getAllNotBlockedContacts() {
return (select(contacts)
..where((t) => t.blocked.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.get();
}
Stream<int?> watchContactsBlocked() {
final count = contacts.userId.count();
final query = selectOnly(contacts)..where(contacts.blocked.equals(true));
query.addColumns([count]);
return query.map((row) => row.read(count)).watchSingle();
}
Stream<int?> watchContactsRequested() {
final count = contacts.requested.count(distinct: true);
final query = selectOnly(contacts)
..where(contacts.requested.equals(true) &
contacts.accepted.equals(true).not());
query.addColumns([count]);
return query.map((row) => row.read(count)).watchSingle();
}
Stream<List<Contact>> watchAllContacts() {
return select(contacts).watch();
}
Stream<int> watchFlameCounter(int userId) {
return (select(contacts)
..where(
(u) =>
u.userId.equals(userId) &
u.lastMessageReceived.isNotNull() &
u.lastMessageSend.isNotNull(),
))
.watchSingle()
.asyncMap((contact) {
return getFlameCounterFromContact(contact);
});
}
}
String getContactDisplayName(Contact user) {
String name = user.username;
if (user.nickName != null && user.nickName != "") {
name = user.nickName!;
} else if (user.displayName != null) {
name = user.displayName!;
}
if (user.deleted) {
name = applyStrikethrough(name);
}
return name;
}
String applyStrikethrough(String text) {
return text.split('').map((char) => '$char\u0336').join('');
}
int getFlameCounterFromContact(Contact contact) {
if (contact.lastMessageSend == null || contact.lastMessageReceived == null) {
return 0;
}
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
final twoDaysAgo = startOfToday.subtract(Duration(days: 2));
if (contact.lastMessageSend!.isAfter(twoDaysAgo) &&
contact.lastMessageReceived!.isAfter(twoDaysAgo)) {
return contact.flameCounter + 1;
} else {
return 0;
}
}