mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 09:28:41 +00:00
allow deletion of chats and groups
This commit is contained in:
parent
678a22dd11
commit
5235a01626
16 changed files with 339 additions and 127 deletions
|
|
@ -164,7 +164,11 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<List<Group>> watchGroupsForShareImage() {
|
Stream<List<Group>> watchGroupsForShareImage() {
|
||||||
return (select(groups)..where((g) => g.leftGroup.equals(false))).watch();
|
return (select(groups)
|
||||||
|
..where(
|
||||||
|
(g) => g.leftGroup.equals(false) & g.deletedContent.equals(false),
|
||||||
|
))
|
||||||
|
.watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<Group?> watchGroup(String groupId) {
|
Stream<Group?> watchGroup(String groupId) {
|
||||||
|
|
@ -174,10 +178,18 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
||||||
|
|
||||||
Stream<List<Group>> watchGroupsForChatList() {
|
Stream<List<Group>> watchGroupsForChatList() {
|
||||||
return (select(groups)
|
return (select(groups)
|
||||||
|
..where((t) => t.deletedContent.equals(false))
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
||||||
.watch();
|
.watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream<List<Group>> watchGroupsForStartNewChat() {
|
||||||
|
return (select(groups)
|
||||||
|
..where((t) => t.isDirectChat.equals(false))
|
||||||
|
..orderBy([(t) => OrderingTerm.asc(t.groupName)]))
|
||||||
|
.watch();
|
||||||
|
}
|
||||||
|
|
||||||
Future<Group?> getGroup(String groupId) {
|
Future<Group?> getGroup(String groupId) {
|
||||||
return (select(groups)..where((t) => t.groupId.equals(groupId)))
|
return (select(groups)..where((t) => t.groupId.equals(groupId)))
|
||||||
.getSingleOrNull();
|
.getSingleOrNull();
|
||||||
|
|
|
||||||
|
|
@ -380,6 +380,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
GroupsCompanion(
|
GroupsCompanion(
|
||||||
lastMessageExchange: Value(DateTime.now()),
|
lastMessageExchange: Value(DateTime.now()),
|
||||||
archived: const Value(false),
|
archived: const Value(false),
|
||||||
|
deletedContent: const Value(false),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -468,6 +469,10 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> deleteMessagesByGroupId(String groupId) {
|
||||||
|
return (delete(messages)..where((t) => t.groupId.equals(groupId))).go();
|
||||||
|
}
|
||||||
|
|
||||||
// Future<void> deleteAllMessagesByContactId(int contactId) {
|
// Future<void> deleteAllMessagesByContactId(int contactId) {
|
||||||
// return (delete(messages)..where((t) => t.contactId.equals(contactId))).go();
|
// return (delete(messages)..where((t) => t.contactId.equals(contactId))).go();
|
||||||
// }
|
// }
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ class Groups extends Table {
|
||||||
|
|
||||||
BoolColumn get joinedGroup => boolean().withDefault(const Constant(false))();
|
BoolColumn get joinedGroup => boolean().withDefault(const Constant(false))();
|
||||||
BoolColumn get leftGroup => boolean().withDefault(const Constant(false))();
|
BoolColumn get leftGroup => boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get deletedContent =>
|
||||||
|
boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
IntColumn get stateVersionId => integer().withDefault(const Constant(0))();
|
IntColumn get stateVersionId => integer().withDefault(const Constant(0))();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -724,6 +724,16 @@ class $GroupsTable extends Groups with TableInfo<$GroupsTable, Group> {
|
||||||
defaultConstraints:
|
defaultConstraints:
|
||||||
GeneratedColumn.constraintIsAlways('CHECK ("left_group" IN (0, 1))'),
|
GeneratedColumn.constraintIsAlways('CHECK ("left_group" IN (0, 1))'),
|
||||||
defaultValue: const Constant(false));
|
defaultValue: const Constant(false));
|
||||||
|
static const VerificationMeta _deletedContentMeta =
|
||||||
|
const VerificationMeta('deletedContent');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<bool> deletedContent = GeneratedColumn<bool>(
|
||||||
|
'deleted_content', aliasedName, false,
|
||||||
|
type: DriftSqlType.bool,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
|
'CHECK ("deleted_content" IN (0, 1))'),
|
||||||
|
defaultValue: const Constant(false));
|
||||||
static const VerificationMeta _stateVersionIdMeta =
|
static const VerificationMeta _stateVersionIdMeta =
|
||||||
const VerificationMeta('stateVersionId');
|
const VerificationMeta('stateVersionId');
|
||||||
@override
|
@override
|
||||||
|
|
@ -848,6 +858,7 @@ class $GroupsTable extends Groups with TableInfo<$GroupsTable, Group> {
|
||||||
archived,
|
archived,
|
||||||
joinedGroup,
|
joinedGroup,
|
||||||
leftGroup,
|
leftGroup,
|
||||||
|
deletedContent,
|
||||||
stateVersionId,
|
stateVersionId,
|
||||||
stateEncryptionKey,
|
stateEncryptionKey,
|
||||||
myGroupPrivateKey,
|
myGroupPrivateKey,
|
||||||
|
|
@ -911,6 +922,12 @@ class $GroupsTable extends Groups with TableInfo<$GroupsTable, Group> {
|
||||||
context.handle(_leftGroupMeta,
|
context.handle(_leftGroupMeta,
|
||||||
leftGroup.isAcceptableOrUnknown(data['left_group']!, _leftGroupMeta));
|
leftGroup.isAcceptableOrUnknown(data['left_group']!, _leftGroupMeta));
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('deleted_content')) {
|
||||||
|
context.handle(
|
||||||
|
_deletedContentMeta,
|
||||||
|
deletedContent.isAcceptableOrUnknown(
|
||||||
|
data['deleted_content']!, _deletedContentMeta));
|
||||||
|
}
|
||||||
if (data.containsKey('state_version_id')) {
|
if (data.containsKey('state_version_id')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_stateVersionIdMeta,
|
_stateVersionIdMeta,
|
||||||
|
|
@ -1029,6 +1046,8 @@ class $GroupsTable extends Groups with TableInfo<$GroupsTable, Group> {
|
||||||
.read(DriftSqlType.bool, data['${effectivePrefix}joined_group'])!,
|
.read(DriftSqlType.bool, data['${effectivePrefix}joined_group'])!,
|
||||||
leftGroup: attachedDatabase.typeMapping
|
leftGroup: attachedDatabase.typeMapping
|
||||||
.read(DriftSqlType.bool, data['${effectivePrefix}left_group'])!,
|
.read(DriftSqlType.bool, data['${effectivePrefix}left_group'])!,
|
||||||
|
deletedContent: attachedDatabase.typeMapping
|
||||||
|
.read(DriftSqlType.bool, data['${effectivePrefix}deleted_content'])!,
|
||||||
stateVersionId: attachedDatabase.typeMapping
|
stateVersionId: attachedDatabase.typeMapping
|
||||||
.read(DriftSqlType.int, data['${effectivePrefix}state_version_id'])!,
|
.read(DriftSqlType.int, data['${effectivePrefix}state_version_id'])!,
|
||||||
stateEncryptionKey: attachedDatabase.typeMapping.read(
|
stateEncryptionKey: attachedDatabase.typeMapping.read(
|
||||||
|
|
@ -1083,6 +1102,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
final bool archived;
|
final bool archived;
|
||||||
final bool joinedGroup;
|
final bool joinedGroup;
|
||||||
final bool leftGroup;
|
final bool leftGroup;
|
||||||
|
final bool deletedContent;
|
||||||
final int stateVersionId;
|
final int stateVersionId;
|
||||||
final Uint8List? stateEncryptionKey;
|
final Uint8List? stateEncryptionKey;
|
||||||
final Uint8List? myGroupPrivateKey;
|
final Uint8List? myGroupPrivateKey;
|
||||||
|
|
@ -1107,6 +1127,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
required this.archived,
|
required this.archived,
|
||||||
required this.joinedGroup,
|
required this.joinedGroup,
|
||||||
required this.leftGroup,
|
required this.leftGroup,
|
||||||
|
required this.deletedContent,
|
||||||
required this.stateVersionId,
|
required this.stateVersionId,
|
||||||
this.stateEncryptionKey,
|
this.stateEncryptionKey,
|
||||||
this.myGroupPrivateKey,
|
this.myGroupPrivateKey,
|
||||||
|
|
@ -1133,6 +1154,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
map['archived'] = Variable<bool>(archived);
|
map['archived'] = Variable<bool>(archived);
|
||||||
map['joined_group'] = Variable<bool>(joinedGroup);
|
map['joined_group'] = Variable<bool>(joinedGroup);
|
||||||
map['left_group'] = Variable<bool>(leftGroup);
|
map['left_group'] = Variable<bool>(leftGroup);
|
||||||
|
map['deleted_content'] = Variable<bool>(deletedContent);
|
||||||
map['state_version_id'] = Variable<int>(stateVersionId);
|
map['state_version_id'] = Variable<int>(stateVersionId);
|
||||||
if (!nullToAbsent || stateEncryptionKey != null) {
|
if (!nullToAbsent || stateEncryptionKey != null) {
|
||||||
map['state_encryption_key'] = Variable<Uint8List>(stateEncryptionKey);
|
map['state_encryption_key'] = Variable<Uint8List>(stateEncryptionKey);
|
||||||
|
|
@ -1177,6 +1199,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
archived: Value(archived),
|
archived: Value(archived),
|
||||||
joinedGroup: Value(joinedGroup),
|
joinedGroup: Value(joinedGroup),
|
||||||
leftGroup: Value(leftGroup),
|
leftGroup: Value(leftGroup),
|
||||||
|
deletedContent: Value(deletedContent),
|
||||||
stateVersionId: Value(stateVersionId),
|
stateVersionId: Value(stateVersionId),
|
||||||
stateEncryptionKey: stateEncryptionKey == null && nullToAbsent
|
stateEncryptionKey: stateEncryptionKey == null && nullToAbsent
|
||||||
? const Value.absent()
|
? const Value.absent()
|
||||||
|
|
@ -1221,6 +1244,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
archived: serializer.fromJson<bool>(json['archived']),
|
archived: serializer.fromJson<bool>(json['archived']),
|
||||||
joinedGroup: serializer.fromJson<bool>(json['joinedGroup']),
|
joinedGroup: serializer.fromJson<bool>(json['joinedGroup']),
|
||||||
leftGroup: serializer.fromJson<bool>(json['leftGroup']),
|
leftGroup: serializer.fromJson<bool>(json['leftGroup']),
|
||||||
|
deletedContent: serializer.fromJson<bool>(json['deletedContent']),
|
||||||
stateVersionId: serializer.fromJson<int>(json['stateVersionId']),
|
stateVersionId: serializer.fromJson<int>(json['stateVersionId']),
|
||||||
stateEncryptionKey:
|
stateEncryptionKey:
|
||||||
serializer.fromJson<Uint8List?>(json['stateEncryptionKey']),
|
serializer.fromJson<Uint8List?>(json['stateEncryptionKey']),
|
||||||
|
|
@ -1257,6 +1281,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
'archived': serializer.toJson<bool>(archived),
|
'archived': serializer.toJson<bool>(archived),
|
||||||
'joinedGroup': serializer.toJson<bool>(joinedGroup),
|
'joinedGroup': serializer.toJson<bool>(joinedGroup),
|
||||||
'leftGroup': serializer.toJson<bool>(leftGroup),
|
'leftGroup': serializer.toJson<bool>(leftGroup),
|
||||||
|
'deletedContent': serializer.toJson<bool>(deletedContent),
|
||||||
'stateVersionId': serializer.toJson<int>(stateVersionId),
|
'stateVersionId': serializer.toJson<int>(stateVersionId),
|
||||||
'stateEncryptionKey': serializer.toJson<Uint8List?>(stateEncryptionKey),
|
'stateEncryptionKey': serializer.toJson<Uint8List?>(stateEncryptionKey),
|
||||||
'myGroupPrivateKey': serializer.toJson<Uint8List?>(myGroupPrivateKey),
|
'myGroupPrivateKey': serializer.toJson<Uint8List?>(myGroupPrivateKey),
|
||||||
|
|
@ -1286,6 +1311,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
bool? archived,
|
bool? archived,
|
||||||
bool? joinedGroup,
|
bool? joinedGroup,
|
||||||
bool? leftGroup,
|
bool? leftGroup,
|
||||||
|
bool? deletedContent,
|
||||||
int? stateVersionId,
|
int? stateVersionId,
|
||||||
Value<Uint8List?> stateEncryptionKey = const Value.absent(),
|
Value<Uint8List?> stateEncryptionKey = const Value.absent(),
|
||||||
Value<Uint8List?> myGroupPrivateKey = const Value.absent(),
|
Value<Uint8List?> myGroupPrivateKey = const Value.absent(),
|
||||||
|
|
@ -1310,6 +1336,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
archived: archived ?? this.archived,
|
archived: archived ?? this.archived,
|
||||||
joinedGroup: joinedGroup ?? this.joinedGroup,
|
joinedGroup: joinedGroup ?? this.joinedGroup,
|
||||||
leftGroup: leftGroup ?? this.leftGroup,
|
leftGroup: leftGroup ?? this.leftGroup,
|
||||||
|
deletedContent: deletedContent ?? this.deletedContent,
|
||||||
stateVersionId: stateVersionId ?? this.stateVersionId,
|
stateVersionId: stateVersionId ?? this.stateVersionId,
|
||||||
stateEncryptionKey: stateEncryptionKey.present
|
stateEncryptionKey: stateEncryptionKey.present
|
||||||
? stateEncryptionKey.value
|
? stateEncryptionKey.value
|
||||||
|
|
@ -1355,6 +1382,9 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
joinedGroup:
|
joinedGroup:
|
||||||
data.joinedGroup.present ? data.joinedGroup.value : this.joinedGroup,
|
data.joinedGroup.present ? data.joinedGroup.value : this.joinedGroup,
|
||||||
leftGroup: data.leftGroup.present ? data.leftGroup.value : this.leftGroup,
|
leftGroup: data.leftGroup.present ? data.leftGroup.value : this.leftGroup,
|
||||||
|
deletedContent: data.deletedContent.present
|
||||||
|
? data.deletedContent.value
|
||||||
|
: this.deletedContent,
|
||||||
stateVersionId: data.stateVersionId.present
|
stateVersionId: data.stateVersionId.present
|
||||||
? data.stateVersionId.value
|
? data.stateVersionId.value
|
||||||
: this.stateVersionId,
|
: this.stateVersionId,
|
||||||
|
|
@ -1413,6 +1443,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
..write('archived: $archived, ')
|
..write('archived: $archived, ')
|
||||||
..write('joinedGroup: $joinedGroup, ')
|
..write('joinedGroup: $joinedGroup, ')
|
||||||
..write('leftGroup: $leftGroup, ')
|
..write('leftGroup: $leftGroup, ')
|
||||||
|
..write('deletedContent: $deletedContent, ')
|
||||||
..write('stateVersionId: $stateVersionId, ')
|
..write('stateVersionId: $stateVersionId, ')
|
||||||
..write('stateEncryptionKey: $stateEncryptionKey, ')
|
..write('stateEncryptionKey: $stateEncryptionKey, ')
|
||||||
..write('myGroupPrivateKey: $myGroupPrivateKey, ')
|
..write('myGroupPrivateKey: $myGroupPrivateKey, ')
|
||||||
|
|
@ -1443,6 +1474,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
archived,
|
archived,
|
||||||
joinedGroup,
|
joinedGroup,
|
||||||
leftGroup,
|
leftGroup,
|
||||||
|
deletedContent,
|
||||||
stateVersionId,
|
stateVersionId,
|
||||||
$driftBlobEquality.hash(stateEncryptionKey),
|
$driftBlobEquality.hash(stateEncryptionKey),
|
||||||
$driftBlobEquality.hash(myGroupPrivateKey),
|
$driftBlobEquality.hash(myGroupPrivateKey),
|
||||||
|
|
@ -1471,6 +1503,7 @@ class Group extends DataClass implements Insertable<Group> {
|
||||||
other.archived == this.archived &&
|
other.archived == this.archived &&
|
||||||
other.joinedGroup == this.joinedGroup &&
|
other.joinedGroup == this.joinedGroup &&
|
||||||
other.leftGroup == this.leftGroup &&
|
other.leftGroup == this.leftGroup &&
|
||||||
|
other.deletedContent == this.deletedContent &&
|
||||||
other.stateVersionId == this.stateVersionId &&
|
other.stateVersionId == this.stateVersionId &&
|
||||||
$driftBlobEquality.equals(
|
$driftBlobEquality.equals(
|
||||||
other.stateEncryptionKey, this.stateEncryptionKey) &&
|
other.stateEncryptionKey, this.stateEncryptionKey) &&
|
||||||
|
|
@ -1500,6 +1533,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
final Value<bool> archived;
|
final Value<bool> archived;
|
||||||
final Value<bool> joinedGroup;
|
final Value<bool> joinedGroup;
|
||||||
final Value<bool> leftGroup;
|
final Value<bool> leftGroup;
|
||||||
|
final Value<bool> deletedContent;
|
||||||
final Value<int> stateVersionId;
|
final Value<int> stateVersionId;
|
||||||
final Value<Uint8List?> stateEncryptionKey;
|
final Value<Uint8List?> stateEncryptionKey;
|
||||||
final Value<Uint8List?> myGroupPrivateKey;
|
final Value<Uint8List?> myGroupPrivateKey;
|
||||||
|
|
@ -1525,6 +1559,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
this.archived = const Value.absent(),
|
this.archived = const Value.absent(),
|
||||||
this.joinedGroup = const Value.absent(),
|
this.joinedGroup = const Value.absent(),
|
||||||
this.leftGroup = const Value.absent(),
|
this.leftGroup = const Value.absent(),
|
||||||
|
this.deletedContent = const Value.absent(),
|
||||||
this.stateVersionId = const Value.absent(),
|
this.stateVersionId = const Value.absent(),
|
||||||
this.stateEncryptionKey = const Value.absent(),
|
this.stateEncryptionKey = const Value.absent(),
|
||||||
this.myGroupPrivateKey = const Value.absent(),
|
this.myGroupPrivateKey = const Value.absent(),
|
||||||
|
|
@ -1551,6 +1586,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
this.archived = const Value.absent(),
|
this.archived = const Value.absent(),
|
||||||
this.joinedGroup = const Value.absent(),
|
this.joinedGroup = const Value.absent(),
|
||||||
this.leftGroup = const Value.absent(),
|
this.leftGroup = const Value.absent(),
|
||||||
|
this.deletedContent = const Value.absent(),
|
||||||
this.stateVersionId = const Value.absent(),
|
this.stateVersionId = const Value.absent(),
|
||||||
this.stateEncryptionKey = const Value.absent(),
|
this.stateEncryptionKey = const Value.absent(),
|
||||||
this.myGroupPrivateKey = const Value.absent(),
|
this.myGroupPrivateKey = const Value.absent(),
|
||||||
|
|
@ -1578,6 +1614,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
Expression<bool>? archived,
|
Expression<bool>? archived,
|
||||||
Expression<bool>? joinedGroup,
|
Expression<bool>? joinedGroup,
|
||||||
Expression<bool>? leftGroup,
|
Expression<bool>? leftGroup,
|
||||||
|
Expression<bool>? deletedContent,
|
||||||
Expression<int>? stateVersionId,
|
Expression<int>? stateVersionId,
|
||||||
Expression<Uint8List>? stateEncryptionKey,
|
Expression<Uint8List>? stateEncryptionKey,
|
||||||
Expression<Uint8List>? myGroupPrivateKey,
|
Expression<Uint8List>? myGroupPrivateKey,
|
||||||
|
|
@ -1604,6 +1641,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
if (archived != null) 'archived': archived,
|
if (archived != null) 'archived': archived,
|
||||||
if (joinedGroup != null) 'joined_group': joinedGroup,
|
if (joinedGroup != null) 'joined_group': joinedGroup,
|
||||||
if (leftGroup != null) 'left_group': leftGroup,
|
if (leftGroup != null) 'left_group': leftGroup,
|
||||||
|
if (deletedContent != null) 'deleted_content': deletedContent,
|
||||||
if (stateVersionId != null) 'state_version_id': stateVersionId,
|
if (stateVersionId != null) 'state_version_id': stateVersionId,
|
||||||
if (stateEncryptionKey != null)
|
if (stateEncryptionKey != null)
|
||||||
'state_encryption_key': stateEncryptionKey,
|
'state_encryption_key': stateEncryptionKey,
|
||||||
|
|
@ -1638,6 +1676,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
Value<bool>? archived,
|
Value<bool>? archived,
|
||||||
Value<bool>? joinedGroup,
|
Value<bool>? joinedGroup,
|
||||||
Value<bool>? leftGroup,
|
Value<bool>? leftGroup,
|
||||||
|
Value<bool>? deletedContent,
|
||||||
Value<int>? stateVersionId,
|
Value<int>? stateVersionId,
|
||||||
Value<Uint8List?>? stateEncryptionKey,
|
Value<Uint8List?>? stateEncryptionKey,
|
||||||
Value<Uint8List?>? myGroupPrivateKey,
|
Value<Uint8List?>? myGroupPrivateKey,
|
||||||
|
|
@ -1663,6 +1702,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
archived: archived ?? this.archived,
|
archived: archived ?? this.archived,
|
||||||
joinedGroup: joinedGroup ?? this.joinedGroup,
|
joinedGroup: joinedGroup ?? this.joinedGroup,
|
||||||
leftGroup: leftGroup ?? this.leftGroup,
|
leftGroup: leftGroup ?? this.leftGroup,
|
||||||
|
deletedContent: deletedContent ?? this.deletedContent,
|
||||||
stateVersionId: stateVersionId ?? this.stateVersionId,
|
stateVersionId: stateVersionId ?? this.stateVersionId,
|
||||||
stateEncryptionKey: stateEncryptionKey ?? this.stateEncryptionKey,
|
stateEncryptionKey: stateEncryptionKey ?? this.stateEncryptionKey,
|
||||||
myGroupPrivateKey: myGroupPrivateKey ?? this.myGroupPrivateKey,
|
myGroupPrivateKey: myGroupPrivateKey ?? this.myGroupPrivateKey,
|
||||||
|
|
@ -1709,6 +1749,9 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
if (leftGroup.present) {
|
if (leftGroup.present) {
|
||||||
map['left_group'] = Variable<bool>(leftGroup.value);
|
map['left_group'] = Variable<bool>(leftGroup.value);
|
||||||
}
|
}
|
||||||
|
if (deletedContent.present) {
|
||||||
|
map['deleted_content'] = Variable<bool>(deletedContent.value);
|
||||||
|
}
|
||||||
if (stateVersionId.present) {
|
if (stateVersionId.present) {
|
||||||
map['state_version_id'] = Variable<int>(stateVersionId.value);
|
map['state_version_id'] = Variable<int>(stateVersionId.value);
|
||||||
}
|
}
|
||||||
|
|
@ -1780,6 +1823,7 @@ class GroupsCompanion extends UpdateCompanion<Group> {
|
||||||
..write('archived: $archived, ')
|
..write('archived: $archived, ')
|
||||||
..write('joinedGroup: $joinedGroup, ')
|
..write('joinedGroup: $joinedGroup, ')
|
||||||
..write('leftGroup: $leftGroup, ')
|
..write('leftGroup: $leftGroup, ')
|
||||||
|
..write('deletedContent: $deletedContent, ')
|
||||||
..write('stateVersionId: $stateVersionId, ')
|
..write('stateVersionId: $stateVersionId, ')
|
||||||
..write('stateEncryptionKey: $stateEncryptionKey, ')
|
..write('stateEncryptionKey: $stateEncryptionKey, ')
|
||||||
..write('myGroupPrivateKey: $myGroupPrivateKey, ')
|
..write('myGroupPrivateKey: $myGroupPrivateKey, ')
|
||||||
|
|
@ -8333,6 +8377,7 @@ typedef $$GroupsTableCreateCompanionBuilder = GroupsCompanion Function({
|
||||||
Value<bool> archived,
|
Value<bool> archived,
|
||||||
Value<bool> joinedGroup,
|
Value<bool> joinedGroup,
|
||||||
Value<bool> leftGroup,
|
Value<bool> leftGroup,
|
||||||
|
Value<bool> deletedContent,
|
||||||
Value<int> stateVersionId,
|
Value<int> stateVersionId,
|
||||||
Value<Uint8List?> stateEncryptionKey,
|
Value<Uint8List?> stateEncryptionKey,
|
||||||
Value<Uint8List?> myGroupPrivateKey,
|
Value<Uint8List?> myGroupPrivateKey,
|
||||||
|
|
@ -8359,6 +8404,7 @@ typedef $$GroupsTableUpdateCompanionBuilder = GroupsCompanion Function({
|
||||||
Value<bool> archived,
|
Value<bool> archived,
|
||||||
Value<bool> joinedGroup,
|
Value<bool> joinedGroup,
|
||||||
Value<bool> leftGroup,
|
Value<bool> leftGroup,
|
||||||
|
Value<bool> deletedContent,
|
||||||
Value<int> stateVersionId,
|
Value<int> stateVersionId,
|
||||||
Value<Uint8List?> stateEncryptionKey,
|
Value<Uint8List?> stateEncryptionKey,
|
||||||
Value<Uint8List?> myGroupPrivateKey,
|
Value<Uint8List?> myGroupPrivateKey,
|
||||||
|
|
@ -8459,6 +8505,10 @@ class $$GroupsTableFilterComposer extends Composer<_$TwonlyDB, $GroupsTable> {
|
||||||
ColumnFilters<bool> get leftGroup => $composableBuilder(
|
ColumnFilters<bool> get leftGroup => $composableBuilder(
|
||||||
column: $table.leftGroup, builder: (column) => ColumnFilters(column));
|
column: $table.leftGroup, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
|
ColumnFilters<bool> get deletedContent => $composableBuilder(
|
||||||
|
column: $table.deletedContent,
|
||||||
|
builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
ColumnFilters<int> get stateVersionId => $composableBuilder(
|
ColumnFilters<int> get stateVersionId => $composableBuilder(
|
||||||
column: $table.stateVersionId,
|
column: $table.stateVersionId,
|
||||||
builder: (column) => ColumnFilters(column));
|
builder: (column) => ColumnFilters(column));
|
||||||
|
|
@ -8614,6 +8664,10 @@ class $$GroupsTableOrderingComposer extends Composer<_$TwonlyDB, $GroupsTable> {
|
||||||
ColumnOrderings<bool> get leftGroup => $composableBuilder(
|
ColumnOrderings<bool> get leftGroup => $composableBuilder(
|
||||||
column: $table.leftGroup, builder: (column) => ColumnOrderings(column));
|
column: $table.leftGroup, builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
|
ColumnOrderings<bool> get deletedContent => $composableBuilder(
|
||||||
|
column: $table.deletedContent,
|
||||||
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<int> get stateVersionId => $composableBuilder(
|
ColumnOrderings<int> get stateVersionId => $composableBuilder(
|
||||||
column: $table.stateVersionId,
|
column: $table.stateVersionId,
|
||||||
builder: (column) => ColumnOrderings(column));
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
@ -8708,6 +8762,9 @@ class $$GroupsTableAnnotationComposer
|
||||||
GeneratedColumn<bool> get leftGroup =>
|
GeneratedColumn<bool> get leftGroup =>
|
||||||
$composableBuilder(column: $table.leftGroup, builder: (column) => column);
|
$composableBuilder(column: $table.leftGroup, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<bool> get deletedContent => $composableBuilder(
|
||||||
|
column: $table.deletedContent, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<int> get stateVersionId => $composableBuilder(
|
GeneratedColumn<int> get stateVersionId => $composableBuilder(
|
||||||
column: $table.stateVersionId, builder: (column) => column);
|
column: $table.stateVersionId, builder: (column) => column);
|
||||||
|
|
||||||
|
|
@ -8853,6 +8910,7 @@ class $$GroupsTableTableManager extends RootTableManager<
|
||||||
Value<bool> archived = const Value.absent(),
|
Value<bool> archived = const Value.absent(),
|
||||||
Value<bool> joinedGroup = const Value.absent(),
|
Value<bool> joinedGroup = const Value.absent(),
|
||||||
Value<bool> leftGroup = const Value.absent(),
|
Value<bool> leftGroup = const Value.absent(),
|
||||||
|
Value<bool> deletedContent = const Value.absent(),
|
||||||
Value<int> stateVersionId = const Value.absent(),
|
Value<int> stateVersionId = const Value.absent(),
|
||||||
Value<Uint8List?> stateEncryptionKey = const Value.absent(),
|
Value<Uint8List?> stateEncryptionKey = const Value.absent(),
|
||||||
Value<Uint8List?> myGroupPrivateKey = const Value.absent(),
|
Value<Uint8List?> myGroupPrivateKey = const Value.absent(),
|
||||||
|
|
@ -8879,6 +8937,7 @@ class $$GroupsTableTableManager extends RootTableManager<
|
||||||
archived: archived,
|
archived: archived,
|
||||||
joinedGroup: joinedGroup,
|
joinedGroup: joinedGroup,
|
||||||
leftGroup: leftGroup,
|
leftGroup: leftGroup,
|
||||||
|
deletedContent: deletedContent,
|
||||||
stateVersionId: stateVersionId,
|
stateVersionId: stateVersionId,
|
||||||
stateEncryptionKey: stateEncryptionKey,
|
stateEncryptionKey: stateEncryptionKey,
|
||||||
myGroupPrivateKey: myGroupPrivateKey,
|
myGroupPrivateKey: myGroupPrivateKey,
|
||||||
|
|
@ -8905,6 +8964,7 @@ class $$GroupsTableTableManager extends RootTableManager<
|
||||||
Value<bool> archived = const Value.absent(),
|
Value<bool> archived = const Value.absent(),
|
||||||
Value<bool> joinedGroup = const Value.absent(),
|
Value<bool> joinedGroup = const Value.absent(),
|
||||||
Value<bool> leftGroup = const Value.absent(),
|
Value<bool> leftGroup = const Value.absent(),
|
||||||
|
Value<bool> deletedContent = const Value.absent(),
|
||||||
Value<int> stateVersionId = const Value.absent(),
|
Value<int> stateVersionId = const Value.absent(),
|
||||||
Value<Uint8List?> stateEncryptionKey = const Value.absent(),
|
Value<Uint8List?> stateEncryptionKey = const Value.absent(),
|
||||||
Value<Uint8List?> myGroupPrivateKey = const Value.absent(),
|
Value<Uint8List?> myGroupPrivateKey = const Value.absent(),
|
||||||
|
|
@ -8931,6 +8991,7 @@ class $$GroupsTableTableManager extends RootTableManager<
|
||||||
archived: archived,
|
archived: archived,
|
||||||
joinedGroup: joinedGroup,
|
joinedGroup: joinedGroup,
|
||||||
leftGroup: leftGroup,
|
leftGroup: leftGroup,
|
||||||
|
deletedContent: deletedContent,
|
||||||
stateVersionId: stateVersionId,
|
stateVersionId: stateVersionId,
|
||||||
stateEncryptionKey: stateEncryptionKey,
|
stateEncryptionKey: stateEncryptionKey,
|
||||||
myGroupPrivateKey: myGroupPrivateKey,
|
myGroupPrivateKey: myGroupPrivateKey,
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@
|
||||||
"@shareImageUserNotVerifiedDesc": {},
|
"@shareImageUserNotVerifiedDesc": {},
|
||||||
"shareImageShowArchived": "Archivierte Benutzer anzeigen",
|
"shareImageShowArchived": "Archivierte Benutzer anzeigen",
|
||||||
"@shareImageShowArchived": {},
|
"@shareImageShowArchived": {},
|
||||||
|
"startNewChatSearchHint": "Name, Benutzername oder Gruppenname",
|
||||||
"searchUsernameInput": "Benutzername",
|
"searchUsernameInput": "Benutzername",
|
||||||
"@searchUsernameInput": {},
|
"@searchUsernameInput": {},
|
||||||
"searchUsernameTitle": "Benutzernamen suchen",
|
"searchUsernameTitle": "Benutzernamen suchen",
|
||||||
|
|
@ -692,6 +693,9 @@
|
||||||
"@durationShortHour": {},
|
"@durationShortHour": {},
|
||||||
"durationShortDays": "Tagen",
|
"durationShortDays": "Tagen",
|
||||||
"@durationShortDays": {},
|
"@durationShortDays": {},
|
||||||
|
"contacts": "Kontakte",
|
||||||
|
"groups": "Gruppen",
|
||||||
|
"@groups": {},
|
||||||
"newGroup": "Neue Gruppe",
|
"newGroup": "Neue Gruppe",
|
||||||
"@newGroup": {},
|
"@newGroup": {},
|
||||||
"selectMembers": "Mitglieder auswählen",
|
"selectMembers": "Mitglieder auswählen",
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@
|
||||||
"@shareImagedEditorSavedImage": {},
|
"@shareImagedEditorSavedImage": {},
|
||||||
"shareImageSearchAllContacts": "Search all contacts",
|
"shareImageSearchAllContacts": "Search all contacts",
|
||||||
"@shareImageSearchAllContacts": {},
|
"@shareImageSearchAllContacts": {},
|
||||||
|
"startNewChatSearchHint": "Name, username or groupname",
|
||||||
"shareImagedSelectAll": "Select all",
|
"shareImagedSelectAll": "Select all",
|
||||||
"@shareImagedSelectAll": {},
|
"@shareImagedSelectAll": {},
|
||||||
"startNewChatTitle": "Select Contact",
|
"startNewChatTitle": "Select Contact",
|
||||||
|
|
@ -516,6 +517,8 @@
|
||||||
"durationShortMinute": "Min.",
|
"durationShortMinute": "Min.",
|
||||||
"durationShortHour": "Hrs.",
|
"durationShortHour": "Hrs.",
|
||||||
"durationShortDays": "Days",
|
"durationShortDays": "Days",
|
||||||
|
"contacts": "Contacts",
|
||||||
|
"groups": "Groups",
|
||||||
"newGroup": "New group",
|
"newGroup": "New group",
|
||||||
"selectMembers": "Select members",
|
"selectMembers": "Select members",
|
||||||
"selectGroupName": "Select group name",
|
"selectGroupName": "Select group name",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,12 @@ abstract class AppLocalizations {
|
||||||
/// **'Search all contacts'**
|
/// **'Search all contacts'**
|
||||||
String get shareImageSearchAllContacts;
|
String get shareImageSearchAllContacts;
|
||||||
|
|
||||||
|
/// No description provided for @startNewChatSearchHint.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Name, username or groupname'**
|
||||||
|
String get startNewChatSearchHint;
|
||||||
|
|
||||||
/// No description provided for @shareImagedSelectAll.
|
/// No description provided for @shareImagedSelectAll.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -2198,6 +2204,18 @@ abstract class AppLocalizations {
|
||||||
/// **'Days'**
|
/// **'Days'**
|
||||||
String get durationShortDays;
|
String get durationShortDays;
|
||||||
|
|
||||||
|
/// No description provided for @contacts.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Contacts'**
|
||||||
|
String get contacts;
|
||||||
|
|
||||||
|
/// No description provided for @groups.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Groups'**
|
||||||
|
String get groups;
|
||||||
|
|
||||||
/// No description provided for @newGroup.
|
/// No description provided for @newGroup.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get shareImageSearchAllContacts => 'Alle Kontakte durchsuchen';
|
String get shareImageSearchAllContacts => 'Alle Kontakte durchsuchen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startNewChatSearchHint => 'Name, Benutzername oder Gruppenname';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get shareImagedSelectAll => 'Alle auswählen';
|
String get shareImagedSelectAll => 'Alle auswählen';
|
||||||
|
|
||||||
|
|
@ -1166,6 +1169,12 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get durationShortDays => 'Tagen';
|
String get durationShortDays => 'Tagen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts => 'Kontakte';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get groups => 'Gruppen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get newGroup => 'Neue Gruppe';
|
String get newGroup => 'Neue Gruppe';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get shareImageSearchAllContacts => 'Search all contacts';
|
String get shareImageSearchAllContacts => 'Search all contacts';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startNewChatSearchHint => 'Name, username or groupname';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get shareImagedSelectAll => 'Select all';
|
String get shareImagedSelectAll => 'Select all';
|
||||||
|
|
||||||
|
|
@ -1159,6 +1162,12 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get durationShortDays => 'Days';
|
String get durationShortDays => 'Days';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts => 'Contacts';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get groups => 'Groups';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get newGroup => 'New group';
|
String get newGroup => 'New group';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ Future<void> insertMediaFileInMessagesTable(
|
||||||
message.groupId,
|
message.groupId,
|
||||||
const GroupsCompanion(
|
const GroupsCompanion(
|
||||||
archived: Value(false),
|
archived: Value(false),
|
||||||
|
deletedContent: Value(false),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ class ContactsListView extends StatelessWidget {
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: context.lang.searchUserNameArchiveUserTooltip,
|
message: context.lang.searchUserNameArchiveUserTooltip,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const FaIcon(FontAwesomeIcons.boxArchive, size: 15),
|
icon: const FaIcon(Icons.archive_outlined, size: 15),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
const update = ContactsCompanion(requested: Value(false));
|
const update = ContactsCompanion(requested: Value(false));
|
||||||
await twonlyDB.contactsDao.updateContact(contact.userId, update);
|
await twonlyDB.contactsDao.updateContact(contact.userId, update);
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,9 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
String currentInputText = '';
|
String currentInputText = '';
|
||||||
late StreamSubscription<Group?> userSub;
|
late StreamSubscription<Group?> userSub;
|
||||||
late StreamSubscription<List<Message>> messageSub;
|
late StreamSubscription<List<Message>> messageSub;
|
||||||
late StreamSubscription<List<GroupHistory>>? groupActionsSub;
|
StreamSubscription<List<GroupHistory>>? groupActionsSub;
|
||||||
late StreamSubscription<List<Contact>>? contactSub;
|
StreamSubscription<List<Contact>>? contactSub;
|
||||||
late StreamSubscription<Future<List<(Message, Contact)>>>?
|
StreamSubscription<Future<List<(Message, Contact)>>>?
|
||||||
lastOpenedMessageByContactSub;
|
lastOpenedMessageByContactSub;
|
||||||
|
|
||||||
Map<int, Contact> userIdToContact = {};
|
Map<int, Contact> userIdToContact = {};
|
||||||
|
|
|
||||||
|
|
@ -47,16 +47,16 @@ class ChatTextEntry extends StatelessWidget {
|
||||||
|
|
||||||
var displayTime = !combineTextMessageWithNext(message, nextMessage);
|
var displayTime = !combineTextMessageWithNext(message, nextMessage);
|
||||||
var displayUserName = '';
|
var displayUserName = '';
|
||||||
if (message.senderId != null && userIdToContact != null) {
|
if (message.senderId != null &&
|
||||||
|
userIdToContact != null &&
|
||||||
|
userIdToContact![message.senderId] != null) {
|
||||||
if (prevMessage == null) {
|
if (prevMessage == null) {
|
||||||
displayUserName =
|
displayUserName =
|
||||||
getContactDisplayName(userIdToContact![message.senderId]!);
|
getContactDisplayName(userIdToContact![message.senderId]!);
|
||||||
} else {
|
} else {
|
||||||
if (!combineTextMessageWithNext(prevMessage!, message)) {
|
if (!combineTextMessageWithNext(prevMessage!, message)) {
|
||||||
if (userIdToContact![message.senderId] != null) {
|
displayUserName =
|
||||||
displayUserName =
|
getContactDisplayName(userIdToContact![message.senderId]!);
|
||||||
getContactDisplayName(userIdToContact![message.senderId]!);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/flame.dart';
|
import 'package:twonly/src/views/components/flame.dart';
|
||||||
|
import 'package:twonly/src/views/components/group_context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/components/user_context_menu.component.dart';
|
import 'package:twonly/src/views/components/user_context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/groups/group_create_select_members.view.dart';
|
import 'package:twonly/src/views/groups/group_create_select_members.view.dart';
|
||||||
|
|
||||||
|
|
@ -20,18 +21,20 @@ class StartNewChatView extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _StartNewChatView extends State<StartNewChatView> {
|
class _StartNewChatView extends State<StartNewChatView> {
|
||||||
List<Contact> contacts = [];
|
List<Contact> filteredContacts = [];
|
||||||
|
List<Group> filteredGroups = [];
|
||||||
List<Contact> allContacts = [];
|
List<Contact> allContacts = [];
|
||||||
|
List<Group> allNonDirectGroups = [];
|
||||||
final TextEditingController searchUserName = TextEditingController();
|
final TextEditingController searchUserName = TextEditingController();
|
||||||
late StreamSubscription<List<Contact>> contactSub;
|
late StreamSubscription<List<Contact>> contactSub;
|
||||||
|
late StreamSubscription<List<Group>> allNonDirectGroupsSub;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
final stream = twonlyDB.contactsDao.watchAllAcceptedContacts();
|
contactSub =
|
||||||
|
twonlyDB.contactsDao.watchAllAcceptedContacts().listen((update) async {
|
||||||
contactSub = stream.listen((update) async {
|
|
||||||
update.sort(
|
update.sort(
|
||||||
(a, b) => getContactDisplayName(a).compareTo(getContactDisplayName(b)),
|
(a, b) => getContactDisplayName(a).compareTo(getContactDisplayName(b)),
|
||||||
);
|
);
|
||||||
|
|
@ -40,18 +43,28 @@ class _StartNewChatView extends State<StartNewChatView> {
|
||||||
});
|
});
|
||||||
await filterUsers();
|
await filterUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
allNonDirectGroupsSub =
|
||||||
|
twonlyDB.groupsDao.watchGroupsForStartNewChat().listen((update) async {
|
||||||
|
setState(() {
|
||||||
|
allNonDirectGroups = update;
|
||||||
|
});
|
||||||
|
await filterUsers();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
unawaited(contactSub.cancel());
|
allNonDirectGroupsSub.cancel();
|
||||||
|
contactSub.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> filterUsers() async {
|
Future<void> filterUsers() async {
|
||||||
if (searchUserName.value.text.isEmpty) {
|
if (searchUserName.value.text.isEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
contacts = allContacts;
|
filteredContacts = allContacts;
|
||||||
|
filteredGroups = [];
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -62,11 +75,54 @@ class _StartNewChatView extends State<StartNewChatView> {
|
||||||
.contains(searchUserName.value.text.toLowerCase()),
|
.contains(searchUserName.value.text.toLowerCase()),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
final groupsFiltered = allNonDirectGroups
|
||||||
|
.where(
|
||||||
|
(g) => g.groupName
|
||||||
|
.toLowerCase()
|
||||||
|
.contains(searchUserName.value.text.toLowerCase()),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
setState(() {
|
setState(() {
|
||||||
contacts = usersFiltered;
|
filteredContacts = usersFiltered;
|
||||||
|
filteredGroups = groupsFiltered;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _onTapUser(Contact user) async {
|
||||||
|
var directChat = await twonlyDB.groupsDao.getDirectChat(user.userId);
|
||||||
|
if (directChat == null) {
|
||||||
|
await twonlyDB.groupsDao.createNewDirectChat(
|
||||||
|
user.userId,
|
||||||
|
GroupsCompanion(
|
||||||
|
groupName: Value(
|
||||||
|
getContactDisplayName(user),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
directChat = await twonlyDB.groupsDao.getDirectChat(user.userId);
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
await Navigator.pushReplacement(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return ChatMessagesView(directChat!);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onTapGroup(Group group) async {
|
||||||
|
await Navigator.pushReplacement(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return ChatMessagesView(group);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|
@ -88,14 +144,137 @@ class _StartNewChatView extends State<StartNewChatView> {
|
||||||
controller: searchUserName,
|
controller: searchUserName,
|
||||||
decoration: getInputDecoration(
|
decoration: getInputDecoration(
|
||||||
context,
|
context,
|
||||||
context.lang.shareImageSearchAllContacts,
|
context.lang.startNewChatSearchHint,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: UserList(
|
child: ListView.builder(
|
||||||
contacts,
|
restorationId: 'new_message_users_list',
|
||||||
|
itemCount:
|
||||||
|
filteredContacts.length + 3 + filteredGroups.length,
|
||||||
|
itemBuilder: (BuildContext context, int i) {
|
||||||
|
if (searchUserName.text.isEmpty) {
|
||||||
|
if (i == 0) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(context.lang.newGroup),
|
||||||
|
leading: const CircleAvatar(
|
||||||
|
child: FaIcon(
|
||||||
|
FontAwesomeIcons.userGroup,
|
||||||
|
size: 13,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const GroupCreateSelectMembersView(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (i == 1) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(context.lang.startNewChatNewContact),
|
||||||
|
leading: const CircleAvatar(
|
||||||
|
child: FaIcon(
|
||||||
|
FontAwesomeIcons.userPlus,
|
||||||
|
size: 13,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const AddNewUserView(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (i == 2) {
|
||||||
|
return const Divider();
|
||||||
|
}
|
||||||
|
i = i - 3;
|
||||||
|
} else {
|
||||||
|
if (i == 0) {
|
||||||
|
return filteredContacts.isNotEmpty
|
||||||
|
? ListTile(
|
||||||
|
title: Text(
|
||||||
|
context.lang.contacts,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container();
|
||||||
|
} else {
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < filteredContacts.length) {
|
||||||
|
return UserContextMenu(
|
||||||
|
key: Key(filteredContacts[i].userId.toString()),
|
||||||
|
contact: filteredContacts[i],
|
||||||
|
child: ListTile(
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Text(getContactDisplayName(filteredContacts[i])),
|
||||||
|
FlameCounterWidget(
|
||||||
|
contactId: filteredContacts[i].userId,
|
||||||
|
prefix: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
leading: AvatarIcon(
|
||||||
|
contactId: filteredContacts[i].userId,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
onTap: () => _onTapUser(filteredContacts[i]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
i -= filteredContacts.length;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
return filteredGroups.isNotEmpty
|
||||||
|
? ListTile(
|
||||||
|
title: Text(
|
||||||
|
context.lang.groups,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
i -= 1;
|
||||||
|
|
||||||
|
if (i < filteredGroups.length) {
|
||||||
|
return GroupContextMenu(
|
||||||
|
key: Key(filteredGroups[i].groupId),
|
||||||
|
group: filteredGroups[i],
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(
|
||||||
|
filteredGroups[i].groupName,
|
||||||
|
),
|
||||||
|
leading: AvatarIcon(
|
||||||
|
group: filteredGroups[i],
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
onTap: () => _onTapGroup(filteredGroups[i]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -105,107 +284,3 @@ class _StartNewChatView extends State<StartNewChatView> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserList extends StatelessWidget {
|
|
||||||
const UserList(
|
|
||||||
this.users, {
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
final List<Contact> users;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListView.builder(
|
|
||||||
restorationId: 'new_message_users_list',
|
|
||||||
itemCount: users.length + 3,
|
|
||||||
itemBuilder: (BuildContext context, int i) {
|
|
||||||
if (i == 1) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(context.lang.startNewChatNewContact),
|
|
||||||
leading: const CircleAvatar(
|
|
||||||
child: FaIcon(
|
|
||||||
FontAwesomeIcons.userPlus,
|
|
||||||
size: 13,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () async {
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const AddNewUserView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (i == 0) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(context.lang.newGroup),
|
|
||||||
leading: const CircleAvatar(
|
|
||||||
child: FaIcon(
|
|
||||||
FontAwesomeIcons.userGroup,
|
|
||||||
size: 13,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () async {
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const GroupCreateSelectMembersView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (i == 2) {
|
|
||||||
return const Divider();
|
|
||||||
}
|
|
||||||
final user = users[i - 3];
|
|
||||||
return UserContextMenu(
|
|
||||||
key: Key(user.userId.toString()),
|
|
||||||
contact: user,
|
|
||||||
child: ListTile(
|
|
||||||
title: Row(
|
|
||||||
children: [
|
|
||||||
Text(getContactDisplayName(user)),
|
|
||||||
FlameCounterWidget(
|
|
||||||
contactId: user.userId,
|
|
||||||
prefix: true,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
leading: AvatarIcon(
|
|
||||||
contactId: user.userId,
|
|
||||||
fontSize: 13,
|
|
||||||
),
|
|
||||||
onTap: () async {
|
|
||||||
var directChat =
|
|
||||||
await twonlyDB.groupsDao.getDirectChat(user.userId);
|
|
||||||
if (directChat == null) {
|
|
||||||
await twonlyDB.groupsDao.createNewDirectChat(
|
|
||||||
user.userId,
|
|
||||||
GroupsCompanion(
|
|
||||||
groupName: Value(
|
|
||||||
getContactDisplayName(user),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
directChat =
|
|
||||||
await twonlyDB.groupsDao.getDirectChat(user.userId);
|
|
||||||
}
|
|
||||||
if (!context.mounted) return;
|
|
||||||
await Navigator.pushReplacement(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return ChatMessagesView(directChat!);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class GroupContextMenu extends StatelessWidget {
|
||||||
await twonlyDB.groupsDao.updateGroup(group.groupId, update);
|
await twonlyDB.groupsDao.updateGroup(group.groupId, update);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: FontAwesomeIcons.boxArchive,
|
icon: Icons.archive_outlined,
|
||||||
),
|
),
|
||||||
if (group.archived)
|
if (group.archived)
|
||||||
ContextMenuItem(
|
ContextMenuItem(
|
||||||
|
|
@ -40,7 +40,7 @@ class GroupContextMenu extends StatelessWidget {
|
||||||
await twonlyDB.groupsDao.updateGroup(group.groupId, update);
|
await twonlyDB.groupsDao.updateGroup(group.groupId, update);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: FontAwesomeIcons.boxOpen,
|
icon: Icons.unarchive_outlined,
|
||||||
),
|
),
|
||||||
ContextMenuItem(
|
ContextMenuItem(
|
||||||
title: context.lang.contextMenuOpenChat,
|
title: context.lang.contextMenuOpenChat,
|
||||||
|
|
@ -71,6 +71,19 @@ class GroupContextMenu extends StatelessWidget {
|
||||||
? FontAwesomeIcons.thumbtackSlash
|
? FontAwesomeIcons.thumbtackSlash
|
||||||
: FontAwesomeIcons.thumbtack,
|
: FontAwesomeIcons.thumbtack,
|
||||||
),
|
),
|
||||||
|
ContextMenuItem(
|
||||||
|
title: context.lang.delete,
|
||||||
|
icon: FontAwesomeIcons.trashCan,
|
||||||
|
onTap: () async {
|
||||||
|
await twonlyDB.messagesDao.deleteMessagesByGroupId(group.groupId);
|
||||||
|
await twonlyDB.groupsDao.updateGroup(
|
||||||
|
group.groupId,
|
||||||
|
const GroupsCompanion(
|
||||||
|
deletedContent: Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ class _BackupViewState extends State<BackupView> {
|
||||||
label: 'twonly Backup',
|
label: 'twonly Backup',
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: const FaIcon(FontAwesomeIcons.boxArchive, size: 17),
|
icon: const FaIcon(Icons.archive_outlined, size: 17),
|
||||||
label: context.lang.backupData,
|
label: context.lang.backupData,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue