This commit is contained in:
otsmr 2025-04-08 16:14:01 +02:00
parent 59b73b3213
commit db8e4d4419
15 changed files with 2638 additions and 19 deletions

File diff suppressed because one or more lines are too long

View file

@ -31,8 +31,6 @@ void main() async {
} }
}); });
// await deleteLogFile();
await setupPushNotification(); await setupPushNotification();
await initMediaStorage(); await initMediaStorage();

View file

@ -1,6 +1,8 @@
import 'package:drift/drift.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:pie_menu/pie_menu.dart'; import 'package:pie_menu/pie_menu.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera_to_share/share_image_view.dart'; import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
@ -25,6 +27,17 @@ class _UserContextMenuState extends State<UserContextMenu> {
return PieMenu( return PieMenu(
onPressed: () => (), onPressed: () => (),
actions: [ actions: [
PieAction(
tooltip: Text(context.lang.contextMenuArchiveUser),
onSelect: () async {
final update = ContactsCompanion(archived: Value(true));
if (context.mounted) {
await twonlyDatabase.contactsDao
.updateContact(widget.contact.userId, update);
}
},
child: FaIcon(FontAwesomeIcons.boxArchive),
),
PieAction( PieAction(
tooltip: Text(context.lang.contextMenuVerifyUser), tooltip: Text(context.lang.contextMenuVerifyUser),
onSelect: () { onSelect: () {

View file

@ -9,7 +9,7 @@ class ContactsDao extends DatabaseAccessor<TwonlyDatabase>
with _$ContactsDaoMixin { with _$ContactsDaoMixin {
// this constructor is required so that the main database can create an instance // this constructor is required so that the main database can create an instance
// of this object. // of this object.
ContactsDao(TwonlyDatabase db) : super(db); ContactsDao(super.db);
Future<int> insertContact(ContactsCompanion contact) async { Future<int> insertContact(ContactsCompanion contact) async {
try { try {
@ -117,13 +117,25 @@ class ContactsDao extends DatabaseAccessor<TwonlyDatabase>
.watchSingle(); .watchSingle();
} }
Stream<List<Contact>> watchContactsForChatList() { Stream<List<Contact>> watchContactsForShareView() {
return (select(contacts) return (select(contacts)
..where((t) => t.accepted.equals(true) & t.blocked.equals(false)) ..where((t) => t.accepted.equals(true) & t.blocked.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)])) ..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch(); .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() { Future<List<Contact>> getAllNotBlockedContacts() {
return (select(contacts) return (select(contacts)
..where((t) => t.blocked.equals(false)) ..where((t) => t.blocked.equals(false))

View file

@ -14,6 +14,10 @@ class Contacts extends Table {
BoolColumn get requested => boolean().withDefault(Constant(false))(); BoolColumn get requested => boolean().withDefault(Constant(false))();
BoolColumn get blocked => boolean().withDefault(Constant(false))(); BoolColumn get blocked => boolean().withDefault(Constant(false))();
BoolColumn get verified => boolean().withDefault(Constant(false))(); BoolColumn get verified => boolean().withDefault(Constant(false))();
BoolColumn get archived => boolean().withDefault(Constant(false))();
IntColumn get deleteMessagesAfterXMinutes =>
integer().withDefault(Constant(60 * 24))();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();

View file

@ -35,7 +35,7 @@ class TwonlyDatabase extends _$TwonlyDatabase {
TwonlyDatabase.forTesting(DatabaseConnection super.connection); TwonlyDatabase.forTesting(DatabaseConnection super.connection);
@override @override
int get schemaVersion => 2; int get schemaVersion => 3;
static QueryExecutor _openConnection() { static QueryExecutor _openConnection() {
return driftDatabase( return driftDatabase(
@ -49,9 +49,16 @@ class TwonlyDatabase extends _$TwonlyDatabase {
@override @override
MigrationStrategy get migration { MigrationStrategy get migration {
return MigrationStrategy( return MigrationStrategy(
onUpgrade: stepByStep(from1To2: (m, schema) async { onUpgrade: stepByStep(
m.addColumn(schema.messages, schema.messages.errorWhileSending); from1To2: (m, schema) async {
}), m.addColumn(schema.messages, schema.messages.errorWhileSending);
},
from2To3: (m, schema) async {
m.addColumn(schema.contacts, schema.contacts.archived);
m.addColumn(
schema.contacts, schema.contacts.deleteMessagesAfterXMinutes);
},
),
); );
} }

View file

@ -87,6 +87,25 @@ class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> {
defaultConstraints: defaultConstraints:
GeneratedColumn.constraintIsAlways('CHECK ("verified" IN (0, 1))'), GeneratedColumn.constraintIsAlways('CHECK ("verified" IN (0, 1))'),
defaultValue: Constant(false)); defaultValue: Constant(false));
static const VerificationMeta _archivedMeta =
const VerificationMeta('archived');
@override
late final GeneratedColumn<bool> archived = GeneratedColumn<bool>(
'archived', aliasedName, false,
type: DriftSqlType.bool,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('CHECK ("archived" IN (0, 1))'),
defaultValue: Constant(false));
static const VerificationMeta _deleteMessagesAfterXMinutesMeta =
const VerificationMeta('deleteMessagesAfterXMinutes');
@override
late final GeneratedColumn<int> deleteMessagesAfterXMinutes =
GeneratedColumn<int>(
'delete_messages_after_x_minutes', aliasedName, false,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultValue: Constant(60 * 24));
static const VerificationMeta _createdAtMeta = static const VerificationMeta _createdAtMeta =
const VerificationMeta('createdAt'); const VerificationMeta('createdAt');
@override @override
@ -149,6 +168,8 @@ class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> {
requested, requested,
blocked, blocked,
verified, verified,
archived,
deleteMessagesAfterXMinutes,
createdAt, createdAt,
totalMediaCounter, totalMediaCounter,
lastMessageSend, lastMessageSend,
@ -213,6 +234,17 @@ class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> {
context.handle(_verifiedMeta, context.handle(_verifiedMeta,
verified.isAcceptableOrUnknown(data['verified']!, _verifiedMeta)); verified.isAcceptableOrUnknown(data['verified']!, _verifiedMeta));
} }
if (data.containsKey('archived')) {
context.handle(_archivedMeta,
archived.isAcceptableOrUnknown(data['archived']!, _archivedMeta));
}
if (data.containsKey('delete_messages_after_x_minutes')) {
context.handle(
_deleteMessagesAfterXMinutesMeta,
deleteMessagesAfterXMinutes.isAcceptableOrUnknown(
data['delete_messages_after_x_minutes']!,
_deleteMessagesAfterXMinutesMeta));
}
if (data.containsKey('created_at')) { if (data.containsKey('created_at')) {
context.handle(_createdAtMeta, context.handle(_createdAtMeta,
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
@ -282,6 +314,11 @@ class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> {
.read(DriftSqlType.bool, data['${effectivePrefix}blocked'])!, .read(DriftSqlType.bool, data['${effectivePrefix}blocked'])!,
verified: attachedDatabase.typeMapping verified: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}verified'])!, .read(DriftSqlType.bool, data['${effectivePrefix}verified'])!,
archived: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}archived'])!,
deleteMessagesAfterXMinutes: attachedDatabase.typeMapping.read(
DriftSqlType.int,
data['${effectivePrefix}delete_messages_after_x_minutes'])!,
createdAt: attachedDatabase.typeMapping createdAt: attachedDatabase.typeMapping
.read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!,
totalMediaCounter: attachedDatabase.typeMapping.read( totalMediaCounter: attachedDatabase.typeMapping.read(
@ -319,6 +356,8 @@ class Contact extends DataClass implements Insertable<Contact> {
final bool requested; final bool requested;
final bool blocked; final bool blocked;
final bool verified; final bool verified;
final bool archived;
final int deleteMessagesAfterXMinutes;
final DateTime createdAt; final DateTime createdAt;
final int totalMediaCounter; final int totalMediaCounter;
final DateTime? lastMessageSend; final DateTime? lastMessageSend;
@ -337,6 +376,8 @@ class Contact extends DataClass implements Insertable<Contact> {
required this.requested, required this.requested,
required this.blocked, required this.blocked,
required this.verified, required this.verified,
required this.archived,
required this.deleteMessagesAfterXMinutes,
required this.createdAt, required this.createdAt,
required this.totalMediaCounter, required this.totalMediaCounter,
this.lastMessageSend, this.lastMessageSend,
@ -363,6 +404,9 @@ class Contact extends DataClass implements Insertable<Contact> {
map['requested'] = Variable<bool>(requested); map['requested'] = Variable<bool>(requested);
map['blocked'] = Variable<bool>(blocked); map['blocked'] = Variable<bool>(blocked);
map['verified'] = Variable<bool>(verified); map['verified'] = Variable<bool>(verified);
map['archived'] = Variable<bool>(archived);
map['delete_messages_after_x_minutes'] =
Variable<int>(deleteMessagesAfterXMinutes);
map['created_at'] = Variable<DateTime>(createdAt); map['created_at'] = Variable<DateTime>(createdAt);
map['total_media_counter'] = Variable<int>(totalMediaCounter); map['total_media_counter'] = Variable<int>(totalMediaCounter);
if (!nullToAbsent || lastMessageSend != null) { if (!nullToAbsent || lastMessageSend != null) {
@ -398,6 +442,8 @@ class Contact extends DataClass implements Insertable<Contact> {
requested: Value(requested), requested: Value(requested),
blocked: Value(blocked), blocked: Value(blocked),
verified: Value(verified), verified: Value(verified),
archived: Value(archived),
deleteMessagesAfterXMinutes: Value(deleteMessagesAfterXMinutes),
createdAt: Value(createdAt), createdAt: Value(createdAt),
totalMediaCounter: Value(totalMediaCounter), totalMediaCounter: Value(totalMediaCounter),
lastMessageSend: lastMessageSend == null && nullToAbsent lastMessageSend: lastMessageSend == null && nullToAbsent
@ -428,6 +474,9 @@ class Contact extends DataClass implements Insertable<Contact> {
requested: serializer.fromJson<bool>(json['requested']), requested: serializer.fromJson<bool>(json['requested']),
blocked: serializer.fromJson<bool>(json['blocked']), blocked: serializer.fromJson<bool>(json['blocked']),
verified: serializer.fromJson<bool>(json['verified']), verified: serializer.fromJson<bool>(json['verified']),
archived: serializer.fromJson<bool>(json['archived']),
deleteMessagesAfterXMinutes:
serializer.fromJson<int>(json['deleteMessagesAfterXMinutes']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']), createdAt: serializer.fromJson<DateTime>(json['createdAt']),
totalMediaCounter: serializer.fromJson<int>(json['totalMediaCounter']), totalMediaCounter: serializer.fromJson<int>(json['totalMediaCounter']),
lastMessageSend: serializer.fromJson<DateTime?>(json['lastMessageSend']), lastMessageSend: serializer.fromJson<DateTime?>(json['lastMessageSend']),
@ -454,6 +503,9 @@ class Contact extends DataClass implements Insertable<Contact> {
'requested': serializer.toJson<bool>(requested), 'requested': serializer.toJson<bool>(requested),
'blocked': serializer.toJson<bool>(blocked), 'blocked': serializer.toJson<bool>(blocked),
'verified': serializer.toJson<bool>(verified), 'verified': serializer.toJson<bool>(verified),
'archived': serializer.toJson<bool>(archived),
'deleteMessagesAfterXMinutes':
serializer.toJson<int>(deleteMessagesAfterXMinutes),
'createdAt': serializer.toJson<DateTime>(createdAt), 'createdAt': serializer.toJson<DateTime>(createdAt),
'totalMediaCounter': serializer.toJson<int>(totalMediaCounter), 'totalMediaCounter': serializer.toJson<int>(totalMediaCounter),
'lastMessageSend': serializer.toJson<DateTime?>(lastMessageSend), 'lastMessageSend': serializer.toJson<DateTime?>(lastMessageSend),
@ -476,6 +528,8 @@ class Contact extends DataClass implements Insertable<Contact> {
bool? requested, bool? requested,
bool? blocked, bool? blocked,
bool? verified, bool? verified,
bool? archived,
int? deleteMessagesAfterXMinutes,
DateTime? createdAt, DateTime? createdAt,
int? totalMediaCounter, int? totalMediaCounter,
Value<DateTime?> lastMessageSend = const Value.absent(), Value<DateTime?> lastMessageSend = const Value.absent(),
@ -494,6 +548,9 @@ class Contact extends DataClass implements Insertable<Contact> {
requested: requested ?? this.requested, requested: requested ?? this.requested,
blocked: blocked ?? this.blocked, blocked: blocked ?? this.blocked,
verified: verified ?? this.verified, verified: verified ?? this.verified,
archived: archived ?? this.archived,
deleteMessagesAfterXMinutes:
deleteMessagesAfterXMinutes ?? this.deleteMessagesAfterXMinutes,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
totalMediaCounter: totalMediaCounter ?? this.totalMediaCounter, totalMediaCounter: totalMediaCounter ?? this.totalMediaCounter,
lastMessageSend: lastMessageSend.present lastMessageSend: lastMessageSend.present
@ -523,6 +580,10 @@ class Contact extends DataClass implements Insertable<Contact> {
requested: data.requested.present ? data.requested.value : this.requested, requested: data.requested.present ? data.requested.value : this.requested,
blocked: data.blocked.present ? data.blocked.value : this.blocked, blocked: data.blocked.present ? data.blocked.value : this.blocked,
verified: data.verified.present ? data.verified.value : this.verified, verified: data.verified.present ? data.verified.value : this.verified,
archived: data.archived.present ? data.archived.value : this.archived,
deleteMessagesAfterXMinutes: data.deleteMessagesAfterXMinutes.present
? data.deleteMessagesAfterXMinutes.value
: this.deleteMessagesAfterXMinutes,
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
totalMediaCounter: data.totalMediaCounter.present totalMediaCounter: data.totalMediaCounter.present
? data.totalMediaCounter.value ? data.totalMediaCounter.value
@ -558,6 +619,8 @@ class Contact extends DataClass implements Insertable<Contact> {
..write('requested: $requested, ') ..write('requested: $requested, ')
..write('blocked: $blocked, ') ..write('blocked: $blocked, ')
..write('verified: $verified, ') ..write('verified: $verified, ')
..write('archived: $archived, ')
..write('deleteMessagesAfterXMinutes: $deleteMessagesAfterXMinutes, ')
..write('createdAt: $createdAt, ') ..write('createdAt: $createdAt, ')
..write('totalMediaCounter: $totalMediaCounter, ') ..write('totalMediaCounter: $totalMediaCounter, ')
..write('lastMessageSend: $lastMessageSend, ') ..write('lastMessageSend: $lastMessageSend, ')
@ -581,6 +644,8 @@ class Contact extends DataClass implements Insertable<Contact> {
requested, requested,
blocked, blocked,
verified, verified,
archived,
deleteMessagesAfterXMinutes,
createdAt, createdAt,
totalMediaCounter, totalMediaCounter,
lastMessageSend, lastMessageSend,
@ -602,6 +667,9 @@ class Contact extends DataClass implements Insertable<Contact> {
other.requested == this.requested && other.requested == this.requested &&
other.blocked == this.blocked && other.blocked == this.blocked &&
other.verified == this.verified && other.verified == this.verified &&
other.archived == this.archived &&
other.deleteMessagesAfterXMinutes ==
this.deleteMessagesAfterXMinutes &&
other.createdAt == this.createdAt && other.createdAt == this.createdAt &&
other.totalMediaCounter == this.totalMediaCounter && other.totalMediaCounter == this.totalMediaCounter &&
other.lastMessageSend == this.lastMessageSend && other.lastMessageSend == this.lastMessageSend &&
@ -622,6 +690,8 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
final Value<bool> requested; final Value<bool> requested;
final Value<bool> blocked; final Value<bool> blocked;
final Value<bool> verified; final Value<bool> verified;
final Value<bool> archived;
final Value<int> deleteMessagesAfterXMinutes;
final Value<DateTime> createdAt; final Value<DateTime> createdAt;
final Value<int> totalMediaCounter; final Value<int> totalMediaCounter;
final Value<DateTime?> lastMessageSend; final Value<DateTime?> lastMessageSend;
@ -640,6 +710,8 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
this.requested = const Value.absent(), this.requested = const Value.absent(),
this.blocked = const Value.absent(), this.blocked = const Value.absent(),
this.verified = const Value.absent(), this.verified = const Value.absent(),
this.archived = const Value.absent(),
this.deleteMessagesAfterXMinutes = const Value.absent(),
this.createdAt = const Value.absent(), this.createdAt = const Value.absent(),
this.totalMediaCounter = const Value.absent(), this.totalMediaCounter = const Value.absent(),
this.lastMessageSend = const Value.absent(), this.lastMessageSend = const Value.absent(),
@ -659,6 +731,8 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
this.requested = const Value.absent(), this.requested = const Value.absent(),
this.blocked = const Value.absent(), this.blocked = const Value.absent(),
this.verified = const Value.absent(), this.verified = const Value.absent(),
this.archived = const Value.absent(),
this.deleteMessagesAfterXMinutes = const Value.absent(),
this.createdAt = const Value.absent(), this.createdAt = const Value.absent(),
this.totalMediaCounter = const Value.absent(), this.totalMediaCounter = const Value.absent(),
this.lastMessageSend = const Value.absent(), this.lastMessageSend = const Value.absent(),
@ -678,6 +752,8 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
Expression<bool>? requested, Expression<bool>? requested,
Expression<bool>? blocked, Expression<bool>? blocked,
Expression<bool>? verified, Expression<bool>? verified,
Expression<bool>? archived,
Expression<int>? deleteMessagesAfterXMinutes,
Expression<DateTime>? createdAt, Expression<DateTime>? createdAt,
Expression<int>? totalMediaCounter, Expression<int>? totalMediaCounter,
Expression<DateTime>? lastMessageSend, Expression<DateTime>? lastMessageSend,
@ -697,6 +773,9 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
if (requested != null) 'requested': requested, if (requested != null) 'requested': requested,
if (blocked != null) 'blocked': blocked, if (blocked != null) 'blocked': blocked,
if (verified != null) 'verified': verified, if (verified != null) 'verified': verified,
if (archived != null) 'archived': archived,
if (deleteMessagesAfterXMinutes != null)
'delete_messages_after_x_minutes': deleteMessagesAfterXMinutes,
if (createdAt != null) 'created_at': createdAt, if (createdAt != null) 'created_at': createdAt,
if (totalMediaCounter != null) 'total_media_counter': totalMediaCounter, if (totalMediaCounter != null) 'total_media_counter': totalMediaCounter,
if (lastMessageSend != null) 'last_message_send': lastMessageSend, if (lastMessageSend != null) 'last_message_send': lastMessageSend,
@ -721,6 +800,8 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
Value<bool>? requested, Value<bool>? requested,
Value<bool>? blocked, Value<bool>? blocked,
Value<bool>? verified, Value<bool>? verified,
Value<bool>? archived,
Value<int>? deleteMessagesAfterXMinutes,
Value<DateTime>? createdAt, Value<DateTime>? createdAt,
Value<int>? totalMediaCounter, Value<int>? totalMediaCounter,
Value<DateTime?>? lastMessageSend, Value<DateTime?>? lastMessageSend,
@ -739,6 +820,9 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
requested: requested ?? this.requested, requested: requested ?? this.requested,
blocked: blocked ?? this.blocked, blocked: blocked ?? this.blocked,
verified: verified ?? this.verified, verified: verified ?? this.verified,
archived: archived ?? this.archived,
deleteMessagesAfterXMinutes:
deleteMessagesAfterXMinutes ?? this.deleteMessagesAfterXMinutes,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
totalMediaCounter: totalMediaCounter ?? this.totalMediaCounter, totalMediaCounter: totalMediaCounter ?? this.totalMediaCounter,
lastMessageSend: lastMessageSend ?? this.lastMessageSend, lastMessageSend: lastMessageSend ?? this.lastMessageSend,
@ -783,6 +867,13 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
if (verified.present) { if (verified.present) {
map['verified'] = Variable<bool>(verified.value); map['verified'] = Variable<bool>(verified.value);
} }
if (archived.present) {
map['archived'] = Variable<bool>(archived.value);
}
if (deleteMessagesAfterXMinutes.present) {
map['delete_messages_after_x_minutes'] =
Variable<int>(deleteMessagesAfterXMinutes.value);
}
if (createdAt.present) { if (createdAt.present) {
map['created_at'] = Variable<DateTime>(createdAt.value); map['created_at'] = Variable<DateTime>(createdAt.value);
} }
@ -823,6 +914,8 @@ class ContactsCompanion extends UpdateCompanion<Contact> {
..write('requested: $requested, ') ..write('requested: $requested, ')
..write('blocked: $blocked, ') ..write('blocked: $blocked, ')
..write('verified: $verified, ') ..write('verified: $verified, ')
..write('archived: $archived, ')
..write('deleteMessagesAfterXMinutes: $deleteMessagesAfterXMinutes, ')
..write('createdAt: $createdAt, ') ..write('createdAt: $createdAt, ')
..write('totalMediaCounter: $totalMediaCounter, ') ..write('totalMediaCounter: $totalMediaCounter, ')
..write('lastMessageSend: $lastMessageSend, ') ..write('lastMessageSend: $lastMessageSend, ')
@ -2575,6 +2668,8 @@ typedef $$ContactsTableCreateCompanionBuilder = ContactsCompanion Function({
Value<bool> requested, Value<bool> requested,
Value<bool> blocked, Value<bool> blocked,
Value<bool> verified, Value<bool> verified,
Value<bool> archived,
Value<int> deleteMessagesAfterXMinutes,
Value<DateTime> createdAt, Value<DateTime> createdAt,
Value<int> totalMediaCounter, Value<int> totalMediaCounter,
Value<DateTime?> lastMessageSend, Value<DateTime?> lastMessageSend,
@ -2594,6 +2689,8 @@ typedef $$ContactsTableUpdateCompanionBuilder = ContactsCompanion Function({
Value<bool> requested, Value<bool> requested,
Value<bool> blocked, Value<bool> blocked,
Value<bool> verified, Value<bool> verified,
Value<bool> archived,
Value<int> deleteMessagesAfterXMinutes,
Value<DateTime> createdAt, Value<DateTime> createdAt,
Value<int> totalMediaCounter, Value<int> totalMediaCounter,
Value<DateTime?> lastMessageSend, Value<DateTime?> lastMessageSend,
@ -2663,6 +2760,13 @@ class $$ContactsTableFilterComposer
ColumnFilters<bool> get verified => $composableBuilder( ColumnFilters<bool> get verified => $composableBuilder(
column: $table.verified, builder: (column) => ColumnFilters(column)); column: $table.verified, builder: (column) => ColumnFilters(column));
ColumnFilters<bool> get archived => $composableBuilder(
column: $table.archived, builder: (column) => ColumnFilters(column));
ColumnFilters<int> get deleteMessagesAfterXMinutes => $composableBuilder(
column: $table.deleteMessagesAfterXMinutes,
builder: (column) => ColumnFilters(column));
ColumnFilters<DateTime> get createdAt => $composableBuilder( ColumnFilters<DateTime> get createdAt => $composableBuilder(
column: $table.createdAt, builder: (column) => ColumnFilters(column)); column: $table.createdAt, builder: (column) => ColumnFilters(column));
@ -2751,6 +2855,13 @@ class $$ContactsTableOrderingComposer
ColumnOrderings<bool> get verified => $composableBuilder( ColumnOrderings<bool> get verified => $composableBuilder(
column: $table.verified, builder: (column) => ColumnOrderings(column)); column: $table.verified, builder: (column) => ColumnOrderings(column));
ColumnOrderings<bool> get archived => $composableBuilder(
column: $table.archived, builder: (column) => ColumnOrderings(column));
ColumnOrderings<int> get deleteMessagesAfterXMinutes => $composableBuilder(
column: $table.deleteMessagesAfterXMinutes,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<DateTime> get createdAt => $composableBuilder( ColumnOrderings<DateTime> get createdAt => $composableBuilder(
column: $table.createdAt, builder: (column) => ColumnOrderings(column)); column: $table.createdAt, builder: (column) => ColumnOrderings(column));
@ -2818,6 +2929,12 @@ class $$ContactsTableAnnotationComposer
GeneratedColumn<bool> get verified => GeneratedColumn<bool> get verified =>
$composableBuilder(column: $table.verified, builder: (column) => column); $composableBuilder(column: $table.verified, builder: (column) => column);
GeneratedColumn<bool> get archived =>
$composableBuilder(column: $table.archived, builder: (column) => column);
GeneratedColumn<int> get deleteMessagesAfterXMinutes => $composableBuilder(
column: $table.deleteMessagesAfterXMinutes, builder: (column) => column);
GeneratedColumn<DateTime> get createdAt => GeneratedColumn<DateTime> get createdAt =>
$composableBuilder(column: $table.createdAt, builder: (column) => column); $composableBuilder(column: $table.createdAt, builder: (column) => column);
@ -2894,6 +3011,8 @@ class $$ContactsTableTableManager extends RootTableManager<
Value<bool> requested = const Value.absent(), Value<bool> requested = const Value.absent(),
Value<bool> blocked = const Value.absent(), Value<bool> blocked = const Value.absent(),
Value<bool> verified = const Value.absent(), Value<bool> verified = const Value.absent(),
Value<bool> archived = const Value.absent(),
Value<int> deleteMessagesAfterXMinutes = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(), Value<DateTime> createdAt = const Value.absent(),
Value<int> totalMediaCounter = const Value.absent(), Value<int> totalMediaCounter = const Value.absent(),
Value<DateTime?> lastMessageSend = const Value.absent(), Value<DateTime?> lastMessageSend = const Value.absent(),
@ -2913,6 +3032,8 @@ class $$ContactsTableTableManager extends RootTableManager<
requested: requested, requested: requested,
blocked: blocked, blocked: blocked,
verified: verified, verified: verified,
archived: archived,
deleteMessagesAfterXMinutes: deleteMessagesAfterXMinutes,
createdAt: createdAt, createdAt: createdAt,
totalMediaCounter: totalMediaCounter, totalMediaCounter: totalMediaCounter,
lastMessageSend: lastMessageSend, lastMessageSend: lastMessageSend,
@ -2932,6 +3053,8 @@ class $$ContactsTableTableManager extends RootTableManager<
Value<bool> requested = const Value.absent(), Value<bool> requested = const Value.absent(),
Value<bool> blocked = const Value.absent(), Value<bool> blocked = const Value.absent(),
Value<bool> verified = const Value.absent(), Value<bool> verified = const Value.absent(),
Value<bool> archived = const Value.absent(),
Value<int> deleteMessagesAfterXMinutes = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(), Value<DateTime> createdAt = const Value.absent(),
Value<int> totalMediaCounter = const Value.absent(), Value<int> totalMediaCounter = const Value.absent(),
Value<DateTime?> lastMessageSend = const Value.absent(), Value<DateTime?> lastMessageSend = const Value.absent(),
@ -2951,6 +3074,8 @@ class $$ContactsTableTableManager extends RootTableManager<
requested: requested, requested: requested,
blocked: blocked, blocked: blocked,
verified: verified, verified: verified,
archived: archived,
deleteMessagesAfterXMinutes: deleteMessagesAfterXMinutes,
createdAt: createdAt, createdAt: createdAt,
totalMediaCounter: totalMediaCounter, totalMediaCounter: totalMediaCounter,
lastMessageSend: lastMessageSend, lastMessageSend: lastMessageSend,

View file

@ -408,8 +408,200 @@ class Shape5 extends i0.VersionedTable {
i1.GeneratedColumn<i2.Uint8List> _column_38(String aliasedName) => i1.GeneratedColumn<i2.Uint8List> _column_38(String aliasedName) =>
i1.GeneratedColumn<i2.Uint8List>('session_record', aliasedName, false, i1.GeneratedColumn<i2.Uint8List>('session_record', aliasedName, false,
type: i1.DriftSqlType.blob); type: i1.DriftSqlType.blob);
final class Schema3 extends i0.VersionedSchema {
Schema3({required super.database}) : super(version: 3);
@override
late final List<i1.DatabaseSchemaEntity> entities = [
contacts,
messages,
signalIdentityKeyStores,
signalPreKeyStores,
signalSenderKeyStores,
signalSessionStores,
];
late final Shape6 contacts = Shape6(
source: i0.VersionedTable(
entityName: 'contacts',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(user_id)',
],
columns: [
_column_0,
_column_1,
_column_2,
_column_3,
_column_4,
_column_5,
_column_6,
_column_7,
_column_8,
_column_9,
_column_39,
_column_40,
_column_10,
_column_11,
_column_12,
_column_13,
_column_14,
_column_15,
_column_16,
],
attachedDatabase: database,
),
alias: null);
late final Shape1 messages = Shape1(
source: i0.VersionedTable(
entityName: 'messages',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [
_column_17,
_column_18,
_column_19,
_column_20,
_column_21,
_column_22,
_column_23,
_column_24,
_column_25,
_column_26,
_column_27,
_column_28,
_column_29,
_column_30,
],
attachedDatabase: database,
),
alias: null);
late final Shape2 signalIdentityKeyStores = Shape2(
source: i0.VersionedTable(
entityName: 'signal_identity_key_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(device_id, name)',
],
columns: [
_column_31,
_column_32,
_column_33,
_column_10,
],
attachedDatabase: database,
),
alias: null);
late final Shape3 signalPreKeyStores = Shape3(
source: i0.VersionedTable(
entityName: 'signal_pre_key_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(pre_key_id)',
],
columns: [
_column_34,
_column_35,
_column_10,
],
attachedDatabase: database,
),
alias: null);
late final Shape4 signalSenderKeyStores = Shape4(
source: i0.VersionedTable(
entityName: 'signal_sender_key_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(sender_key_name)',
],
columns: [
_column_36,
_column_37,
],
attachedDatabase: database,
),
alias: null);
late final Shape5 signalSessionStores = Shape5(
source: i0.VersionedTable(
entityName: 'signal_session_stores',
withoutRowId: false,
isStrict: false,
tableConstraints: [
'PRIMARY KEY(device_id, name)',
],
columns: [
_column_31,
_column_32,
_column_38,
_column_10,
],
attachedDatabase: database,
),
alias: null);
}
class Shape6 extends i0.VersionedTable {
Shape6({required super.source, required super.alias}) : super.aliased();
i1.GeneratedColumn<int> get userId =>
columnsByName['user_id']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<String> get username =>
columnsByName['username']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get displayName =>
columnsByName['display_name']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get nickName =>
columnsByName['nick_name']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get avatarSvg =>
columnsByName['avatar_svg']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<int> get myAvatarCounter =>
columnsByName['my_avatar_counter']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<bool> get accepted =>
columnsByName['accepted']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<bool> get requested =>
columnsByName['requested']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<bool> get blocked =>
columnsByName['blocked']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<bool> get verified =>
columnsByName['verified']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<bool> get archived =>
columnsByName['archived']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<int> get deleteMessagesAfterXMinutes =>
columnsByName['delete_messages_after_x_minutes']!
as i1.GeneratedColumn<int>;
i1.GeneratedColumn<DateTime> get createdAt =>
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<int> get totalMediaCounter =>
columnsByName['total_media_counter']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<DateTime> get lastMessageSend =>
columnsByName['last_message_send']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<DateTime> get lastMessageReceived =>
columnsByName['last_message_received']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<DateTime> get lastFlameCounterChange =>
columnsByName['last_flame_counter_change']!
as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<DateTime> get lastMessageExchange =>
columnsByName['last_message_exchange']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<int> get flameCounter =>
columnsByName['flame_counter']! as i1.GeneratedColumn<int>;
}
i1.GeneratedColumn<bool> _column_39(String aliasedName) =>
i1.GeneratedColumn<bool>('archived', aliasedName, false,
type: i1.DriftSqlType.bool,
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
'CHECK ("archived" IN (0, 1))'),
defaultValue: const CustomExpression('0'));
i1.GeneratedColumn<int> _column_40(String aliasedName) =>
i1.GeneratedColumn<int>(
'delete_messages_after_x_minutes', aliasedName, false,
type: i1.DriftSqlType.int,
defaultValue: const CustomExpression('1440'));
i0.MigrationStepWithVersion migrationSteps({ i0.MigrationStepWithVersion migrationSteps({
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2, required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
}) { }) {
return (currentVersion, database) async { return (currentVersion, database) async {
switch (currentVersion) { switch (currentVersion) {
@ -418,6 +610,11 @@ i0.MigrationStepWithVersion migrationSteps({
final migrator = i1.Migrator(database, schema); final migrator = i1.Migrator(database, schema);
await from1To2(migrator, schema); await from1To2(migrator, schema);
return 2; return 2;
case 2:
final schema = Schema3(database: database);
final migrator = i1.Migrator(database, schema);
await from2To3(migrator, schema);
return 3;
default: default:
throw ArgumentError.value('Unknown migration from $currentVersion'); throw ArgumentError.value('Unknown migration from $currentVersion');
} }
@ -426,8 +623,10 @@ i0.MigrationStepWithVersion migrationSteps({
i1.OnUpgrade stepByStep({ i1.OnUpgrade stepByStep({
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2, required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
}) => }) =>
i0.VersionedSchema.stepByStepHelper( i0.VersionedSchema.stepByStepHelper(
step: migrationSteps( step: migrationSteps(
from1To2: from1To2, from1To2: from1To2,
from2To3: from2To3,
)); ));

View file

@ -31,6 +31,8 @@
"shareImagedEditorSavedImage": "Gespeichert", "shareImagedEditorSavedImage": "Gespeichert",
"shareImageAllUsers": "Alle Kontakte", "shareImageAllUsers": "Alle Kontakte",
"shareImageAllTwonlyWarning": "Twonlies können nur an verifizierte Kontakte gesendet werden!", "shareImageAllTwonlyWarning": "Twonlies können nur an verifizierte Kontakte gesendet werden!",
"shareImageSearchAllContacts": "Alle Kontakte durchsuchen",
"@shareImageSearchAllContacts": {},
"searchUsernameInput": "Benutzername", "searchUsernameInput": "Benutzername",
"searchUsernameTitle": "Benutzernamen suchen", "searchUsernameTitle": "Benutzernamen suchen",
"searchUsernameNotFound": "Benutzername nicht gefunden", "searchUsernameNotFound": "Benutzername nicht gefunden",
@ -40,8 +42,11 @@
"chatListViewSearchUserNameBtn": "Füge deinen ersten twonly-Kontakt hinzu!", "chatListViewSearchUserNameBtn": "Füge deinen ersten twonly-Kontakt hinzu!",
"chatListViewSendFirstTwonly": "Sende dein erstes twonly!", "chatListViewSendFirstTwonly": "Sende dein erstes twonly!",
"chatListDetailInput": "Nachricht eingeben", "chatListDetailInput": "Nachricht eingeben",
"contextMenuVerifyUser": "Kontakt verifizieren", "contextMenuVerifyUser": "Verifizieren",
"contextMenuOpenChat": "Chat öffnen", "@contextMenuVerifyUser": {},
"contextMenuArchiveUser": "Archivieren",
"@contextMenuArchiveUser": {},
"contextMenuOpenChat": "Chat",
"contextMenuSendImage": "Bild senden", "contextMenuSendImage": "Bild senden",
"mediaViewerAuthReason": "Bitte authentifiziere dich, um diesen twonly zu sehen!", "mediaViewerAuthReason": "Bitte authentifiziere dich, um diesen twonly zu sehen!",
"messageSendState_Received": "Empfangen", "messageSendState_Received": "Empfangen",

View file

@ -58,6 +58,8 @@
"@shareImagedEditorSaveImage": {}, "@shareImagedEditorSaveImage": {},
"shareImagedEditorSavedImage": "Saved", "shareImagedEditorSavedImage": "Saved",
"@shareImagedEditorSavedImage": {}, "@shareImagedEditorSavedImage": {},
"shareImageSearchAllContacts": "Search all contacts",
"@shareImageSearchAllContacts": {},
"shareImageAllUsers": "All contacts", "shareImageAllUsers": "All contacts",
"@shareImageAllUsers": {}, "@shareImageAllUsers": {},
"shareImageAllTwonlyWarning": "twonlies can only be send to verified contacts!", "shareImageAllTwonlyWarning": "twonlies can only be send to verified contacts!",
@ -84,8 +86,10 @@
"@chatListViewSendFirstTwonly": {}, "@chatListViewSendFirstTwonly": {},
"chatListDetailInput": "Type a message", "chatListDetailInput": "Type a message",
"@chatListDetailInput": {}, "@chatListDetailInput": {},
"contextMenuVerifyUser": "Verify user", "contextMenuVerifyUser": "Verify",
"@contextMenuVerifyUser": {}, "@contextMenuVerifyUser": {},
"contextMenuArchiveUser": "Archive",
"@contextMenuArchiveUser": {},
"contextMenuOpenChat": "Open chat", "contextMenuOpenChat": "Open chat",
"@contextMenuOpenChat": {}, "@contextMenuOpenChat": {},
"contextMenuSendImage": "Send image", "contextMenuSendImage": "Send image",

View file

@ -324,6 +324,12 @@ Future sendImage(
), ),
), ),
), ),
); // dearchive contact when sending a new message
twonlyDatabase.contactsDao.updateContact(
userId,
ContactsCompanion(
archived: Value(false),
),
); );
if (messageId != null) { if (messageId != null) {
metadata.messageIds[userId] = messageId; metadata.messageIds[userId] = messageId;

View file

@ -327,6 +327,13 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
} }
} }
} }
// dearchive contact when receiving a new message
await twonlyDatabase.contactsDao.updateContact(
fromUserId,
ContactsCompanion(
archived: Value(false),
),
);
} }
} }
var ok = client.Response_Ok()..none = true; var ok = client.Response_Ok()..none = true;

View file

@ -52,17 +52,15 @@ class _ShareImageView extends State<ShareImageView> {
} }
Stream<List<Contact>> allContacts = Stream<List<Contact>> allContacts =
twonlyDatabase.contactsDao.watchContactsForChatList(); twonlyDatabase.contactsDao.watchContactsForShareView();
contactSub = allContacts.listen((allContacts) { contactSub = allContacts.listen((allContacts) {
setState(() { setState(() {
contacts = allContacts; contacts = allContacts;
}); });
updateUsers(allContacts); updateUsers(allContacts.where((x) => !x.archived).toList());
}); });
//_users = await DbContacts.getActiveUsers();
// _updateUsers(_users);
initAsync(); initAsync();
} }
@ -102,7 +100,9 @@ class _ShareImageView extends State<ShareImageView> {
List<Contact> otherUsers = []; List<Contact> otherUsers = [];
for (var contact in users) { for (var contact in users) {
if ((getFlameCounterFromContact(contact)) > 0 && bestFriends.length < 6) { if (!contact.archived &&
(getFlameCounterFromContact(contact)) > 0 &&
bestFriends.length < 6) {
bestFriends.add(contact); bestFriends.add(contact);
} else { } else {
otherUsers.add(contact); otherUsers.add(contact);
@ -117,7 +117,7 @@ class _ShareImageView extends State<ShareImageView> {
Future _filterUsers(String query) async { Future _filterUsers(String query) async {
if (query.isEmpty) { if (query.isEmpty) {
updateUsers(contacts); updateUsers(contacts.where((x) => !x.archived).toList());
return; return;
} }
List<Contact> usersFiltered = contacts List<Contact> usersFiltered = contacts
@ -172,7 +172,9 @@ class _ShareImageView extends State<ShareImageView> {
child: TextField( child: TextField(
onChanged: _filterUsers, onChanged: _filterUsers,
decoration: getInputDecoration( decoration: getInputDecoration(
context, context.lang.searchUsernameInput), context,
context.lang.shareImageSearchAllContacts,
),
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),

View file

@ -5,6 +5,7 @@ import 'package:drift/drift.dart';
import 'package:drift/internal/migrations.dart'; import 'package:drift/internal/migrations.dart';
import 'schema_v1.dart' as v1; import 'schema_v1.dart' as v1;
import 'schema_v2.dart' as v2; import 'schema_v2.dart' as v2;
import 'schema_v3.dart' as v3;
class GeneratedHelper implements SchemaInstantiationHelper { class GeneratedHelper implements SchemaInstantiationHelper {
@override @override
@ -14,10 +15,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
return v1.DatabaseAtV1(db); return v1.DatabaseAtV1(db);
case 2: case 2:
return v2.DatabaseAtV2(db); return v2.DatabaseAtV2(db);
case 3:
return v3.DatabaseAtV3(db);
default: default:
throw MissingSchemaException(version, versions); throw MissingSchemaException(version, versions);
} }
} }
static const versions = const [1, 2]; static const versions = const [1, 2, 3];
} }

File diff suppressed because it is too large Load diff