mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 18:48:40 +00:00
delete contact requested users and improve logging
This commit is contained in:
parent
b8aeb0e6ed
commit
036c4cab77
10 changed files with 150 additions and 58 deletions
|
|
@ -65,6 +65,7 @@
|
||||||
"chatListViewSendFirstTwonly": "Sende dein erstes twonly!",
|
"chatListViewSendFirstTwonly": "Sende dein erstes twonly!",
|
||||||
"chatListDetailInput": "Nachricht eingeben",
|
"chatListDetailInput": "Nachricht eingeben",
|
||||||
"userDeletedAccount": "Der Nutzer hat sein Konto gelöscht.",
|
"userDeletedAccount": "Der Nutzer hat sein Konto gelöscht.",
|
||||||
|
"contextMenuUserProfile": "Userprofil",
|
||||||
"contextMenuVerifyUser": "Verifizieren",
|
"contextMenuVerifyUser": "Verifizieren",
|
||||||
"@contextMenuVerifyUser": {},
|
"@contextMenuVerifyUser": {},
|
||||||
"contextMenuArchiveUser": "Archivieren",
|
"contextMenuArchiveUser": "Archivieren",
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@
|
||||||
"chatListDetailInput": "Type a message",
|
"chatListDetailInput": "Type a message",
|
||||||
"@chatListDetailInput": {},
|
"@chatListDetailInput": {},
|
||||||
"userDeletedAccount": "The user has deleted its account.",
|
"userDeletedAccount": "The user has deleted its account.",
|
||||||
|
"contextMenuUserProfile": "User profile",
|
||||||
"contextMenuVerifyUser": "Verify",
|
"contextMenuVerifyUser": "Verify",
|
||||||
"@contextMenuVerifyUser": {},
|
"@contextMenuVerifyUser": {},
|
||||||
"contextMenuArchiveUser": "Archive",
|
"contextMenuArchiveUser": "Archive",
|
||||||
|
|
|
||||||
|
|
@ -452,6 +452,12 @@ abstract class AppLocalizations {
|
||||||
/// **'The user has deleted its account.'**
|
/// **'The user has deleted its account.'**
|
||||||
String get userDeletedAccount;
|
String get userDeletedAccount;
|
||||||
|
|
||||||
|
/// No description provided for @contextMenuUserProfile.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'User profile'**
|
||||||
|
String get contextMenuUserProfile;
|
||||||
|
|
||||||
/// No description provided for @contextMenuVerifyUser.
|
/// No description provided for @contextMenuVerifyUser.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get userDeletedAccount => 'Der Nutzer hat sein Konto gelöscht.';
|
String get userDeletedAccount => 'Der Nutzer hat sein Konto gelöscht.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contextMenuUserProfile => 'Userprofil';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contextMenuVerifyUser => 'Verifizieren';
|
String get contextMenuVerifyUser => 'Verifizieren';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get userDeletedAccount => 'The user has deleted its account.';
|
String get userDeletedAccount => 'The user has deleted its account.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contextMenuUserProfile => 'User profile';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contextMenuVerifyUser => 'Verify';
|
String get contextMenuVerifyUser => 'Verify';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,11 @@ Future<bool> checkForFailedUploads() async {
|
||||||
mediaUploadIds.add(message.mediaUploadId!);
|
mediaUploadIds.add(message.mediaUploadId!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (messages.isNotEmpty) {
|
||||||
Log.error(
|
Log.error(
|
||||||
"Got ${messages.length} messages (${mediaUploadIds.length} media upload files) that are not correctly uploaded. Trying from scratch again.",
|
"Got ${messages.length} messages (${mediaUploadIds.length} media upload files) that are not correctly uploaded. Trying from scratch again.",
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return mediaUploadIds.isNotEmpty; // return true if there are affected
|
return mediaUploadIds.isNotEmpty; // return true if there are affected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ Future handleServerMessage(server.ServerToClient msg) async {
|
||||||
Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||||
MessageJson? message = await signalDecryptMessage(fromUserId, body);
|
MessageJson? message = await signalDecryptMessage(fromUserId, body);
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
Log.info("Got invalid cipher text from $fromUserId. Deleting it.");
|
|
||||||
// Message is not valid, so server can delete it
|
// Message is not valid, so server can delete it
|
||||||
var ok = client.Response_Ok()..none = true;
|
var ok = client.Response_Ok()..none = true;
|
||||||
return client.Response()..ok = ok;
|
return client.Response()..ok = ok;
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,10 @@ Future<MessageJson?> signalDecryptMessage(int source, Uint8List msg) async {
|
||||||
}
|
}
|
||||||
return MessageJson.fromJson(
|
return MessageJson.fromJson(
|
||||||
jsonDecode(utf8.decode(gzip.decode(plaintext))));
|
jsonDecode(utf8.decode(gzip.decode(plaintext))));
|
||||||
|
} on InvalidKeyIdException catch (_) {
|
||||||
|
return null; // got the same message again
|
||||||
|
} on DuplicateMessageException catch (_) {
|
||||||
|
return null; // to the same message again
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error(e.toString());
|
Log.error(e.toString());
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,18 @@ 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/chats/chat_messages.view.dart';
|
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
||||||
|
import 'package:twonly/src/views/contact/contact.view.dart';
|
||||||
import 'package:twonly/src/views/contact/contact_verify.view.dart';
|
import 'package:twonly/src/views/contact/contact_verify.view.dart';
|
||||||
|
|
||||||
class UserContextMenu extends StatefulWidget {
|
class UserContextMenu extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final Contact contact;
|
final Contact contact;
|
||||||
|
|
||||||
const UserContextMenu(
|
const UserContextMenu({
|
||||||
{super.key, required this.contact, required this.child});
|
super.key,
|
||||||
|
required this.contact,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<UserContextMenu> createState() => _UserContextMenuState();
|
State<UserContextMenu> createState() => _UserContextMenuState();
|
||||||
|
|
@ -96,6 +100,67 @@ class _UserContextMenuState extends State<UserContextMenu> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UserContextMenuBlocked extends StatefulWidget {
|
||||||
|
final Widget child;
|
||||||
|
final Contact contact;
|
||||||
|
|
||||||
|
const UserContextMenuBlocked({
|
||||||
|
super.key,
|
||||||
|
required this.contact,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UserContextMenuBlocked> createState() => _UserContextMenuBlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserContextMenuBlocked extends State<UserContextMenuBlocked> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PieMenu(
|
||||||
|
onPressed: () => (),
|
||||||
|
actions: [
|
||||||
|
if (!widget.contact.archived)
|
||||||
|
PieAction(
|
||||||
|
tooltip: Text(context.lang.contextMenuArchiveUser),
|
||||||
|
onSelect: () async {
|
||||||
|
final update = ContactsCompanion(archived: Value(true));
|
||||||
|
if (context.mounted) {
|
||||||
|
await twonlyDB.contactsDao
|
||||||
|
.updateContact(widget.contact.userId, update);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: FaIcon(FontAwesomeIcons.boxArchive),
|
||||||
|
),
|
||||||
|
if (widget.contact.archived)
|
||||||
|
PieAction(
|
||||||
|
tooltip: Text(context.lang.contextMenuUndoArchiveUser),
|
||||||
|
onSelect: () async {
|
||||||
|
final update = ContactsCompanion(archived: Value(false));
|
||||||
|
if (context.mounted) {
|
||||||
|
await twonlyDB.contactsDao
|
||||||
|
.updateContact(widget.contact.userId, update);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: FaIcon(FontAwesomeIcons.boxOpen),
|
||||||
|
),
|
||||||
|
PieAction(
|
||||||
|
tooltip: Text(context.lang.contextMenuUserProfile),
|
||||||
|
onSelect: () {
|
||||||
|
Navigator.push(context, MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return ContactView(widget.contact.userId);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
},
|
||||||
|
child: const FaIcon(FontAwesomeIcons.user),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: widget.child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PieTheme getPieCanvasTheme(BuildContext context) {
|
PieTheme getPieCanvasTheme(BuildContext context) {
|
||||||
return PieTheme(
|
return PieTheme(
|
||||||
brightness: Theme.of(context).brightness,
|
brightness: Theme.of(context).brightness,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import 'package:drift/drift.dart' hide Column;
|
import 'package:drift/drift.dart' hide Column;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pie_menu/pie_menu.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/views/components/initialsavatar.dart';
|
import 'package:twonly/src/views/components/initialsavatar.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts_dao.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/components/user_context_menu.dart';
|
||||||
|
|
||||||
class PrivacyViewBlockUsers extends StatefulWidget {
|
class PrivacyViewBlockUsers extends StatefulWidget {
|
||||||
const PrivacyViewBlockUsers({super.key});
|
const PrivacyViewBlockUsers({super.key});
|
||||||
|
|
@ -35,7 +37,9 @@ class _PrivacyViewBlockUsers extends State<PrivacyViewBlockUsers> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(context.lang.settingsPrivacyBlockUsers),
|
title: Text(context.lang.settingsPrivacyBlockUsers),
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: PieCanvas(
|
||||||
|
theme: getPieCanvasTheme(context),
|
||||||
|
child: Padding(
|
||||||
padding: EdgeInsets.only(bottom: 20, left: 10, top: 20, right: 10),
|
padding: EdgeInsets.only(bottom: 20, left: 10, top: 20, right: 10),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -80,6 +84,7 @@ class _PrivacyViewBlockUsers extends State<PrivacyViewBlockUsers> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +111,9 @@ class UserList extends StatelessWidget {
|
||||||
itemCount: users.length,
|
itemCount: users.length,
|
||||||
itemBuilder: (BuildContext context, int i) {
|
itemBuilder: (BuildContext context, int i) {
|
||||||
Contact user = users[i];
|
Contact user = users[i];
|
||||||
return ListTile(
|
return UserContextMenuBlocked(
|
||||||
|
contact: user,
|
||||||
|
child: ListTile(
|
||||||
title: Row(children: [
|
title: Row(children: [
|
||||||
Text(getContactDisplayName(user)),
|
Text(getContactDisplayName(user)),
|
||||||
]),
|
]),
|
||||||
|
|
@ -120,6 +127,7 @@ class UserList extends StatelessWidget {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
block(context, user.userId, !user.blocked);
|
block(context, user.userId, !user.blocked);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue