mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 13:08:42 +00:00
finishes #332
This commit is contained in:
parent
25114daee2
commit
1a2aa5edb9
8 changed files with 177 additions and 15 deletions
|
|
@ -4,6 +4,10 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>aps-environment</key>
|
<key>aps-environment</key>
|
||||||
<string>development</string>
|
<string>development</string>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:me.twonly.eu</string>
|
||||||
|
</array>
|
||||||
<key>keychain-access-groups</key>
|
<key>keychain-access-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(AppIdentifierPrefix)eu.twonly.shared</string>
|
<string>$(AppIdentifierPrefix)eu.twonly.shared</string>
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
"searchUserNameBlockUserTooltip": "Benutzer ohne Benachrichtigung blockieren.",
|
"searchUserNameBlockUserTooltip": "Benutzer ohne Benachrichtigung blockieren.",
|
||||||
"searchUserNameRejectUserTooltip": "Die Anfrage ablehnen und den Anfragenden informieren.",
|
"searchUserNameRejectUserTooltip": "Die Anfrage ablehnen und den Anfragenden informieren.",
|
||||||
"searchUserNameArchiveUserTooltip": "Benutzer archivieren. Du wirst informiert sobald er deine Anfrage akzeptiert.",
|
"searchUserNameArchiveUserTooltip": "Benutzer archivieren. Du wirst informiert sobald er deine Anfrage akzeptiert.",
|
||||||
"userFound": "Benutzer gefunden",
|
"userFound": "{username} gefunden",
|
||||||
"userFoundBody": "Möchtest du eine Folgeanfrage stellen?",
|
"userFoundBody": "Möchtest du eine Folgeanfrage stellen?",
|
||||||
"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!",
|
||||||
|
|
@ -446,5 +446,10 @@
|
||||||
"voiceMessageCancel": "Abbrechen",
|
"voiceMessageCancel": "Abbrechen",
|
||||||
"shareYourProfile": "Teile dein Profil",
|
"shareYourProfile": "Teile dein Profil",
|
||||||
"scanOtherProfile": "Scanne ein anderes Profil",
|
"scanOtherProfile": "Scanne ein anderes Profil",
|
||||||
"skipForNow": "Vorerst überspringen"
|
"skipForNow": "Vorerst überspringen",
|
||||||
|
"linkFromUsername": "Ist der Link von {username}?",
|
||||||
|
"linkFromUsernameLong": "Wenn du den Link von der Person direkt erhalten hast, kannst du den Kontakt als verifiziert markieren, da der öffentliche Schlüssel im Link mit dem bereits für diesen Benutzer gespeicherten öffentlichen Schlüssel übereinstimmt.",
|
||||||
|
"gotLinkFromFriend": "Ja, der Link kommt direkt von der Person.",
|
||||||
|
"couldNotVerifyUsername": "{username} konnte nicht verifiziert werden",
|
||||||
|
"linkPubkeyDoesNotMatch": "Der öffentliche Schlüssel im Link stimmt nicht mit dem für diesen Kontakt gespeicherten öffentlichen Schlüssel überein. Triff die Person persönlich und scanne den QR-Code direkt!"
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +205,7 @@
|
||||||
"addEmoji": "Emoji",
|
"addEmoji": "Emoji",
|
||||||
"toggleFlashLight": "Toggle the flash light",
|
"toggleFlashLight": "Toggle the flash light",
|
||||||
"toggleHighQuality": "Toggle better resolution",
|
"toggleHighQuality": "Toggle better resolution",
|
||||||
"userFound": "User found",
|
"userFound": "{username} found",
|
||||||
"userFoundBody": "Do you want to create a follow request?",
|
"userFoundBody": "Do you want to create a follow request?",
|
||||||
"searchUsernameNotFoundLong": "\"{username}\" is not a twonly user. Please check the username and try again.",
|
"searchUsernameNotFoundLong": "\"{username}\" is not a twonly user. Please check the username and try again.",
|
||||||
"@searchUsernameNotFoundLong": {
|
"@searchUsernameNotFoundLong": {
|
||||||
|
|
@ -476,5 +476,10 @@
|
||||||
"voiceMessageCancel": "Cancel",
|
"voiceMessageCancel": "Cancel",
|
||||||
"shareYourProfile": "Share your profile",
|
"shareYourProfile": "Share your profile",
|
||||||
"scanOtherProfile": "Scan other profile",
|
"scanOtherProfile": "Scan other profile",
|
||||||
"skipForNow": "Skip for now"
|
"skipForNow": "Skip for now",
|
||||||
|
"linkFromUsername": "Is the link from {username}?",
|
||||||
|
"linkFromUsernameLong": "If you received the link from your friend, you can mark the user as verified, as the public key in the link matches the public key already stored for that user?",
|
||||||
|
"gotLinkFromFriend": "Yes, I got the link from my friend!",
|
||||||
|
"couldNotVerifyUsername": "Could not verify {username}",
|
||||||
|
"linkPubkeyDoesNotMatch": "The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!"
|
||||||
}
|
}
|
||||||
|
|
@ -1181,8 +1181,8 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @userFound.
|
/// No description provided for @userFound.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'User found'**
|
/// **'{username} found'**
|
||||||
String get userFound;
|
String userFound(Object username);
|
||||||
|
|
||||||
/// No description provided for @userFoundBody.
|
/// No description provided for @userFoundBody.
|
||||||
///
|
///
|
||||||
|
|
@ -2779,6 +2779,36 @@ abstract class AppLocalizations {
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Skip for now'**
|
/// **'Skip for now'**
|
||||||
String get skipForNow;
|
String get skipForNow;
|
||||||
|
|
||||||
|
/// No description provided for @linkFromUsername.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Is the link from {username}?'**
|
||||||
|
String linkFromUsername(Object username);
|
||||||
|
|
||||||
|
/// No description provided for @linkFromUsernameLong.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'If you received the link from your friend, you can mark the user as verified, as the public key in the link matches the public key already stored for that user?'**
|
||||||
|
String get linkFromUsernameLong;
|
||||||
|
|
||||||
|
/// No description provided for @gotLinkFromFriend.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Yes, I got the link from my friend!'**
|
||||||
|
String get gotLinkFromFriend;
|
||||||
|
|
||||||
|
/// No description provided for @couldNotVerifyUsername.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Could not verify {username}'**
|
||||||
|
String couldNotVerifyUsername(Object username);
|
||||||
|
|
||||||
|
/// No description provided for @linkPubkeyDoesNotMatch.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!'**
|
||||||
|
String get linkPubkeyDoesNotMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate
|
class _AppLocalizationsDelegate
|
||||||
|
|
|
||||||
|
|
@ -598,7 +598,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
String get toggleHighQuality => 'Bessere Auflösung umschalten';
|
String get toggleHighQuality => 'Bessere Auflösung umschalten';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get userFound => 'Benutzer gefunden';
|
String userFound(Object username) {
|
||||||
|
return '$username gefunden';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get userFoundBody => 'Möchtest du eine Folgeanfrage stellen?';
|
String get userFoundBody => 'Möchtest du eine Folgeanfrage stellen?';
|
||||||
|
|
@ -1531,4 +1533,25 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get skipForNow => 'Vorerst überspringen';
|
String get skipForNow => 'Vorerst überspringen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String linkFromUsername(Object username) {
|
||||||
|
return 'Ist der Link von $username?';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get linkFromUsernameLong =>
|
||||||
|
'Wenn du den Link von der Person direkt erhalten hast, kannst du den Kontakt als verifiziert markieren, da der öffentliche Schlüssel im Link mit dem bereits für diesen Benutzer gespeicherten öffentlichen Schlüssel übereinstimmt.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get gotLinkFromFriend => 'Ja, der Link kommt direkt von der Person.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String couldNotVerifyUsername(Object username) {
|
||||||
|
return '$username konnte nicht verifiziert werden';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get linkPubkeyDoesNotMatch =>
|
||||||
|
'Der öffentliche Schlüssel im Link stimmt nicht mit dem für diesen Kontakt gespeicherten öffentlichen Schlüssel überein. Triff die Person persönlich und scanne den QR-Code direkt!';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -593,7 +593,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
String get toggleHighQuality => 'Toggle better resolution';
|
String get toggleHighQuality => 'Toggle better resolution';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get userFound => 'User found';
|
String userFound(Object username) {
|
||||||
|
return '$username found';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get userFoundBody => 'Do you want to create a follow request?';
|
String get userFoundBody => 'Do you want to create a follow request?';
|
||||||
|
|
@ -1521,4 +1523,25 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get skipForNow => 'Skip for now';
|
String get skipForNow => 'Skip for now';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String linkFromUsername(Object username) {
|
||||||
|
return 'Is the link from $username?';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get linkFromUsernameLong =>
|
||||||
|
'If you received the link from your friend, you can mark the user as verified, as the public key in the link matches the public key already stored for that user?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get gotLinkFromFriend => 'Yes, I got the link from my friend!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String couldNotVerifyUsername(Object username) {
|
||||||
|
return 'Could not verify $username';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get linkPubkeyDoesNotMatch =>
|
||||||
|
'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
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:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
@ -16,7 +17,14 @@ import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/headline.dart';
|
import 'package:twonly/src/views/components/headline.dart';
|
||||||
|
|
||||||
class AddNewUserView extends StatefulWidget {
|
class AddNewUserView extends StatefulWidget {
|
||||||
const AddNewUserView({super.key});
|
const AddNewUserView({
|
||||||
|
this.username,
|
||||||
|
this.publicKey,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String? username;
|
||||||
|
final Uint8List? publicKey;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AddNewUserView> createState() => _SearchUsernameView();
|
State<AddNewUserView> createState() => _SearchUsernameView();
|
||||||
|
|
@ -38,6 +46,13 @@ class _SearchUsernameView extends State<AddNewUserView> {
|
||||||
contacts = update;
|
contacts = update;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (widget.username != null) {
|
||||||
|
searchUserName.text = widget.username!;
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_addNewUser(context);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -73,7 +88,7 @@ class _SearchUsernameView extends State<AddNewUserView> {
|
||||||
|
|
||||||
final addUser = await showAlertDialog(
|
final addUser = await showAlertDialog(
|
||||||
context,
|
context,
|
||||||
context.lang.userFound,
|
context.lang.userFound(searchUserName.text),
|
||||||
context.lang.userFoundBody,
|
context.lang.userFoundBody,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -88,6 +103,10 @@ class _SearchUsernameView extends State<AddNewUserView> {
|
||||||
requested: const Value(false),
|
requested: const Value(false),
|
||||||
blocked: const Value(false),
|
blocked: const Value(false),
|
||||||
deletedByUser: const Value(false),
|
deletedByUser: const Value(false),
|
||||||
|
verified: Value(
|
||||||
|
!(widget.publicKey == null) &&
|
||||||
|
userdata.publicIdentityKey.equals(widget.publicKey!),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:typed_data';
|
||||||
import 'package:app_links/app_links.dart';
|
import 'package:app_links/app_links.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
||||||
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
||||||
import 'package:twonly/src/services/signal/session.signal.dart';
|
import 'package:twonly/src/services/signal/session.signal.dart';
|
||||||
|
|
@ -15,7 +18,10 @@ import 'package:twonly/src/views/camera/camera_preview_components/camera_preview
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
|
||||||
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
|
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_list.view.dart';
|
import 'package:twonly/src/views/chats/chat_list.view.dart';
|
||||||
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
|
import 'package:twonly/src/views/contact/contact.view.dart';
|
||||||
import 'package:twonly/src/views/memories/memories.view.dart';
|
import 'package:twonly/src/views/memories/memories.view.dart';
|
||||||
import 'package:twonly/src/views/public_profile.view.dart';
|
import 'package:twonly/src/views/public_profile.view.dart';
|
||||||
|
|
||||||
|
|
@ -144,18 +150,65 @@ class HomeViewState extends State<HomeView> {
|
||||||
final contacts =
|
final contacts =
|
||||||
await twonlyDB.contactsDao.getContactsByUsername(username);
|
await twonlyDB.contactsDao.getContactsByUsername(username);
|
||||||
if (contacts.isEmpty) {
|
if (contacts.isEmpty) {
|
||||||
// load user from server...
|
if (!mounted) return;
|
||||||
|
Uint8List? publicKeyBytes;
|
||||||
|
if (publicKey != null) {
|
||||||
|
publicKeyBytes = base64Url.decode(publicKey);
|
||||||
|
}
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return AddNewUserView(
|
||||||
|
username: username,
|
||||||
|
publicKey: publicKeyBytes,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
} else if (publicKey != null) {
|
} else if (publicKey != null) {
|
||||||
try {
|
try {
|
||||||
final contact = contacts.first;
|
final contact = contacts.first;
|
||||||
final storedPublicKey = await getPublicKeyFromContact(contact.userId);
|
final storedPublicKey = await getPublicKeyFromContact(contact.userId);
|
||||||
final receivedPublicKey = base64Url.decode(publicKey);
|
final receivedPublicKey = base64Url.decode(publicKey);
|
||||||
if (storedPublicKey == null || receivedPublicKey.isEmpty) return;
|
if (storedPublicKey == null ||
|
||||||
|
receivedPublicKey.isEmpty ||
|
||||||
|
!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (storedPublicKey.equals(receivedPublicKey)) {
|
if (storedPublicKey.equals(receivedPublicKey)) {
|
||||||
Log.info('Could verify the user');
|
if (!contact.verified) {
|
||||||
|
final markAsVerified = await showAlertDialog(
|
||||||
|
context,
|
||||||
|
context.lang.linkFromUsername(contact.username),
|
||||||
|
context.lang.linkFromUsernameLong,
|
||||||
|
customOk: context.lang.gotLinkFromFriend,
|
||||||
|
);
|
||||||
|
if (markAsVerified) {
|
||||||
|
await twonlyDB.contactsDao.updateContact(
|
||||||
|
contact.userId,
|
||||||
|
const ContactsCompanion(
|
||||||
|
verified: Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return ContactView(contact.userId);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.error('Show error message');
|
await showAlertDialog(
|
||||||
|
context,
|
||||||
|
context.lang.couldNotVerifyUsername(contact.username),
|
||||||
|
context.lang.linkPubkeyDoesNotMatch,
|
||||||
|
customCancel: '',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.warn(e);
|
Log.warn(e);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue