mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 11:18:41 +00:00
bug fix
This commit is contained in:
parent
b756682f7c
commit
bf34920350
10 changed files with 207 additions and 139 deletions
|
|
@ -33,7 +33,7 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "eu.twonly.testng"
|
||||
applicationId = "eu.twonly.testing"
|
||||
multiDexEnabled true
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
951DB0F2008EB94699D02555 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F3BB8E3AC9CEA61248BD989 /* libPods-Runner.a */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
A8E4DD3B3139A6996AC817E0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F3BB8E3AC9CEA61248BD989 /* libPods-Runner.a */; };
|
||||
F3C66D726A2EB28484DF0B10 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A8E4DD3B3139A6996AC817E0 /* libPods-Runner.a in Frameworks */,
|
||||
951DB0F2008EB94699D02555 /* libPods-Runner.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
arb-dir: lib/src/localization
|
||||
template-arb-file: app_en.arb
|
||||
output-localization-file: app_localizations.dart
|
||||
untranslated-messages-file: build/l10n.log
|
||||
|
|
|
|||
|
|
@ -144,11 +144,14 @@ class MessagesDao extends DatabaseAccessor<TwonlyDatabase>
|
|||
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
||||
}
|
||||
|
||||
Future<bool> containsOtherMessageId(int messageOtherId) async {
|
||||
Future<bool> containsOtherMessageId(
|
||||
int fromUserId, int messageOtherId) async {
|
||||
final query = select(messages)
|
||||
..where((t) => t.messageOtherId.equals(messageOtherId));
|
||||
final entry = await query.getSingleOrNull();
|
||||
return entry != null;
|
||||
..where((t) =>
|
||||
t.messageOtherId.equals(messageOtherId) &
|
||||
t.contactId.equals(fromUserId));
|
||||
final entry = await query.get();
|
||||
return entry.isNotEmpty;
|
||||
}
|
||||
|
||||
SingleOrNullSelectable<Message> getMessageByMessageId(int messageId) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
"contextMenuVerifyUser": "Kontakt verifizieren",
|
||||
"contextMenuOpenChat": "Chat öffnen",
|
||||
"contextMenuSendImage": "Bild senden",
|
||||
"mediaViewerAuthReason": "Bitte authentifiziere dich, um diesen twonly zu sehen!",
|
||||
"messageSendState_Received": "Empfangen",
|
||||
"messageSendState_Opened": "Geöffnet",
|
||||
"messageSendState_Send": "Gesendet",
|
||||
|
|
|
|||
|
|
@ -1,40 +1,79 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
"registerTitle": "Welcome to twonly!",
|
||||
"@registerTitle": {},
|
||||
"registerSlogan": "twonly, a privacy friendly way to connect with friends through secure, spontaneous image sharing",
|
||||
"@registerSlogan": {},
|
||||
"onboardingWelcomeTitle": "Welcome to twonly!",
|
||||
"@onboardingWelcomeTitle": {},
|
||||
"onboardingWelcomeBody": "Experience a private and secure way to stay in touch with friends by sharing instant pictures.",
|
||||
"@onboardingWelcomeBody": {},
|
||||
"onboardingE2eTitle": "Carefree sharing",
|
||||
"@onboardingE2eTitle": {},
|
||||
"onboardingE2eBody": "With end-to-end encryption, enjoy the peace of mind that only you and your friends can see the moments you share.",
|
||||
"@onboardingE2eBody": {},
|
||||
"onboardingFocusTitle": "Focus on sharing moments",
|
||||
"@onboardingFocusTitle": {},
|
||||
"onboardingFocusBody": "Say goodbye to addictive features! twonly was created for sharing moments, free from useless distractions or ads.",
|
||||
"@onboardingFocusBody": {},
|
||||
"onboardingSendTwonliesTitle": "Send twonlies",
|
||||
"@onboardingSendTwonliesTitle": {},
|
||||
"onboardingSendTwonliesBody": "Share moments securely with your partner. twonly ensures that only your partner can open it, keeping your moments with your partner a two(o)nly thing!",
|
||||
"@onboardingSendTwonliesBody": {},
|
||||
"onboardingNotProductTitle": "You are not the product!",
|
||||
"@onboardingNotProductTitle": {},
|
||||
"onboardingNotProductBody": "twonly is financed by a small monthly fee and not by selling your data.",
|
||||
"@onboardingNotProductBody": {},
|
||||
"onboardingBuyOneGetTwoTitle": "Buy one get two",
|
||||
"@onboardingBuyOneGetTwoTitle": {},
|
||||
"onboardingBuyOneGetTwoBody": "twonly always requires at least two people, which is why you receive a second free license for your twonly partner with your purchase.",
|
||||
"@onboardingBuyOneGetTwoBody": {},
|
||||
"onboardingGetStartedTitle": "Let's go!",
|
||||
"@onboardingGetStartedTitle": {},
|
||||
"onboardingGetStartedBody": "You can test twonly free of charge for 14 days, after that it costs either 1€/month or 9€/year.",
|
||||
"@onboardingGetStartedBody": {},
|
||||
"onboardingTryForFree": "Try for free",
|
||||
"@onboardingTryForFree": {},
|
||||
"registerUsernameSlogan": "Please select a username so others can find you!",
|
||||
"@registerUsernameSlogan": {},
|
||||
"registerUsernameDecoration": "Username",
|
||||
"@registerUsernameDecoration": {},
|
||||
"registerUsernameLimits": "Username must be 3 to 12 characters long, consisting only of letters (a-z) and numbers (0-9).",
|
||||
"@registerUsernameLimits": {},
|
||||
"registerSubmitButton": "Register now!",
|
||||
"@registerSubmitButton": {},
|
||||
"newMessageTitle": "New message",
|
||||
"@newMessageTitle": {},
|
||||
"chatsTapToSend": "Click to send your first image",
|
||||
"@chatsTapToSend": {},
|
||||
"shareImageTitle": "Share with",
|
||||
"@shareImageTitle": {},
|
||||
"shareImageBestFriends": "Best friends",
|
||||
"@shareImageBestFriends": {},
|
||||
"shareImagedEditorSendImage": "Send",
|
||||
"@shareImagedEditorSendImage": {},
|
||||
"shareImagedEditorShareWith": "Share with",
|
||||
"@shareImagedEditorShareWith": {},
|
||||
"shareImagedEditorSaveImage": "Save",
|
||||
"@shareImagedEditorSaveImage": {},
|
||||
"shareImagedEditorSavedImage": "Saved",
|
||||
"@shareImagedEditorSavedImage": {},
|
||||
"shareImageAllUsers": "All contacts",
|
||||
"@shareImageAllUsers": {},
|
||||
"shareImageAllTwonlyWarning": "twonlies can only be send to verified contacts!",
|
||||
"@shareImageAllTwonlyWarning": {},
|
||||
"searchUsernameInput": "Username",
|
||||
"@searchUsernameInput": {},
|
||||
"searchUsernameTitle": "Search username",
|
||||
"@searchUsernameTitle": {},
|
||||
"searchUsernameNotFound": "Username not found",
|
||||
"searchUsernameNotFoundBody": "There is no user with the username \"{username}\" registered.",
|
||||
"@searchUsernameNotFound": {},
|
||||
"searchUsernameNotFoundBody": "There is no user with the username \"{username}\" registered",
|
||||
"@searchUsernameNotFoundBody": {
|
||||
"placeholders": {
|
||||
"username": {}
|
||||
}
|
||||
},
|
||||
"searchUsernameNewFollowerTitle": "Follow requests",
|
||||
"searchUsernameQrCodeBtn": "Scan QR code",
|
||||
"chatListViewSearchUserNameBtn": "Add your first twonly contact!",
|
||||
|
|
|
|||
|
|
@ -162,28 +162,18 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
|||
|
||||
Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||
MessageJson? message = await SignalHelper.getDecryptedText(fromUserId, body);
|
||||
if (message != null) {
|
||||
if (message == null) {
|
||||
Logger("server_messages")
|
||||
.info("Got invalid cypher text from $fromUserId. Deleting it.");
|
||||
// Message is not valid, so server can delete it
|
||||
var ok = client.Response_Ok()..none = true;
|
||||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
||||
switch (message.kind) {
|
||||
case MessageKind.contactRequest:
|
||||
Result username = await apiProvider.getUsername(fromUserId);
|
||||
if (username.isSuccess) {
|
||||
Uint8List name = username.value.userdata.username;
|
||||
return handleContactRequest(fromUserId, message);
|
||||
|
||||
int added =
|
||||
await twonlyDatabase.contactsDao.insertContact(ContactsCompanion(
|
||||
username: Value(utf8.decode(name)),
|
||||
userId: Value(fromUserId),
|
||||
requested: Value(true),
|
||||
));
|
||||
if (added > 0) {
|
||||
localPushNotificationNewMessage(
|
||||
fromUserId.toInt(),
|
||||
message,
|
||||
999999,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MessageKind.opened:
|
||||
final update = MessagesCompanion(openedAt: Value(message.timestamp));
|
||||
await twonlyDatabase.messagesDao.updateMessageByOtherUser(
|
||||
|
|
@ -192,15 +182,18 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
|||
update,
|
||||
);
|
||||
break;
|
||||
|
||||
case MessageKind.rejectRequest:
|
||||
await twonlyDatabase.contactsDao.deleteContactByUserId(fromUserId);
|
||||
break;
|
||||
|
||||
case MessageKind.acceptRequest:
|
||||
final update = ContactsCompanion(accepted: Value(true));
|
||||
await twonlyDatabase.contactsDao.updateContact(fromUserId, update);
|
||||
localPushNotificationNewMessage(fromUserId.toInt(), message, 8888888);
|
||||
notifyContactsAboutProfileChange();
|
||||
break;
|
||||
|
||||
case MessageKind.profileChange:
|
||||
var content = message.content;
|
||||
if (content is ProfileContent) {
|
||||
|
|
@ -211,6 +204,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
|||
twonlyDatabase.contactsDao.updateContact(fromUserId, update);
|
||||
}
|
||||
break;
|
||||
|
||||
case MessageKind.ack:
|
||||
final update = MessagesCompanion(acknowledgeByUser: Value(true));
|
||||
await twonlyDatabase.messagesDao.updateMessageByOtherUser(
|
||||
|
|
@ -219,17 +213,29 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
|||
update,
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (message.kind != MessageKind.textMessage &&
|
||||
message.kind != MessageKind.media &&
|
||||
message.kind != MessageKind.storedMediaFile) {
|
||||
Logger("handleServerMessages")
|
||||
.shout("Got unknown MessageKind $message");
|
||||
} else if (message.content != null && message.messageId != null) {
|
||||
} else if (message.content == null || message.messageId == null) {
|
||||
Logger("handleServerMessages")
|
||||
.shout("Content or messageid not defined $message");
|
||||
} else {
|
||||
// when a message is received doubled ignore it...
|
||||
if ((await twonlyDatabase.messagesDao
|
||||
.containsOtherMessageId(fromUserId, message.messageId!))) {
|
||||
var ok = client.Response_Ok()..none = true;
|
||||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
||||
String content = jsonEncode(message.content!.toJson());
|
||||
|
||||
bool acknowledgeByUser = false;
|
||||
DateTime? openedAt;
|
||||
|
||||
if (message.kind == MessageKind.storedMediaFile) {
|
||||
acknowledgeByUser = true;
|
||||
openedAt = DateTime.now();
|
||||
|
|
@ -241,13 +247,6 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
|||
responseToMessageId = textContent.responseToMessageId;
|
||||
}
|
||||
|
||||
// when a message is received doubled ignore it...
|
||||
if ((await twonlyDatabase.messagesDao
|
||||
.containsOtherMessageId(message.messageId!))) {
|
||||
var ok = client.Response_Ok()..none = true;
|
||||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
||||
final update = MessagesCompanion(
|
||||
contactId: Value(fromUserId),
|
||||
kind: Value(message.kind),
|
||||
|
|
@ -303,7 +302,6 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
|||
localPushNotificationNewMessage(fromUserId, message, messageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
var ok = client.Response_Ok()..none = true;
|
||||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
|
@ -321,3 +319,31 @@ Future<client.Response> handleRequestNewPreKey() async {
|
|||
var ok = client.Response_Ok()..prekeys = prekeys;
|
||||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
||||
Future<client.Response> handleContactRequest(
|
||||
int fromUserId, MessageJson message) async {
|
||||
// request the username by the server so an attacker can not
|
||||
// forge the displayed username in the contact request
|
||||
Result username = await apiProvider.getUsername(fromUserId);
|
||||
if (username.isSuccess) {
|
||||
Uint8List name = username.value.userdata.username;
|
||||
|
||||
int added = await twonlyDatabase.contactsDao.insertContact(
|
||||
ContactsCompanion(
|
||||
username: Value(utf8.decode(name)),
|
||||
userId: Value(fromUserId),
|
||||
requested: Value(true),
|
||||
),
|
||||
);
|
||||
|
||||
if (added > 0) {
|
||||
localPushNotificationNewMessage(
|
||||
fromUserId,
|
||||
message,
|
||||
999999,
|
||||
);
|
||||
}
|
||||
}
|
||||
var ok = client.Response_Ok()..none = true;
|
||||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,9 +279,6 @@ Future<MessageJson?> getDecryptedText(int source, Uint8List msg) async {
|
|||
if (msgs == null) return null;
|
||||
Uint8List body = msgs[0];
|
||||
int type = bytesToInt(msgs[1]);
|
||||
|
||||
// gzip.decode(body);
|
||||
|
||||
Uint8List plaintext;
|
||||
if (type == CiphertextMessage.prekeyType) {
|
||||
PreKeySignalMessage pre = PreKeySignalMessage(body);
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ packages:
|
|||
source: hosted
|
||||
version: "3.10.4"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ dependencies:
|
|||
avatar_maker: ^0.2.0
|
||||
flutter_svg: ^2.0.17
|
||||
flutter_volume_controller: ^1.3.3
|
||||
fixnum: ^1.1.1
|
||||
# avatar_maker
|
||||
# avatar_maker:
|
||||
# path: ./dependencies/avatar_maker/
|
||||
|
|
|
|||
Loading…
Reference in a new issue