Compare commits
4 Commits
04c0c1c0e2
...
0e768e7768
Author | SHA1 | Date | |
---|---|---|---|
0e768e7768 | |||
d59a37f185 | |||
f0c6713d76 | |||
0eeac949ea |
@ -37,6 +37,19 @@
|
||||
"startTlsFailed": "Failed to establish a secure connection",
|
||||
"noConnection": "Failed to establish a connection",
|
||||
"unspecified": "Unspecified error"
|
||||
},
|
||||
"message": {
|
||||
"unspecified": "Unknown error",
|
||||
"fileUploadFailed": "The file upload failed",
|
||||
"contactDoesntSupportOmemo": "The contact does not support encryption using OMEMO:2",
|
||||
"fileDownloadFailed": "The file download failed",
|
||||
"serviceUnavailable": "The message could not be delivered to the contact",
|
||||
"remoteServerTimeout": "The message could not be delivered to the contact's server",
|
||||
"remoteServerNotFound": "The message could not be delivered to the contact's server as it cannot be found",
|
||||
"failedToEncrypt": "The message could not be encrypted",
|
||||
"failedToEncryptFile": "The file could not be encrypted",
|
||||
"failedToDecryptFile": "The file could not be decrypted",
|
||||
"fileNotEncrypted": "The chat is encrypted but the file is not encrypted"
|
||||
}
|
||||
},
|
||||
"warnings": {
|
||||
|
@ -37,6 +37,19 @@
|
||||
"startTlsFailed": "Konnte keine sichere Verbindung zum Server aufbauen",
|
||||
"noConnection": "Konnte keine Verbindung zum Server aufbauen",
|
||||
"unspecified": "Unbestimmter Fehler"
|
||||
},
|
||||
"message": {
|
||||
"unspecified": "Unbekannter Fehler",
|
||||
"fileUploadFailed": "Das Hochladen der Datei ist fehlgeschlagen",
|
||||
"contactDoesntSupportOmemo": "Der Kontakt unterstützt Verschlüsselung mit OMEMO:2 nicht",
|
||||
"fileDownloadFailed": "Das Herunterladen der Datei ist fehlgeschlagen",
|
||||
"serviceUnavailable": "Die Nachricht konnte nicht gesendet werden",
|
||||
"remoteServerTimeout": "Die Nachricht konnte nicht zugestellt werden",
|
||||
"remoteServerNotFound": "Die Nachricht konnte nicht gesendet werden, da der Empfängerserver unbekannt ist",
|
||||
"failedToEncrypt": "Die Nachricht konnte nicht verschlüsselt werden",
|
||||
"failedToEncryptFile": "Die Datei konnte nicht verschlüsselt werden",
|
||||
"failedToDecryptFile": "Die Datei konnte nicht entschlüsselt werden",
|
||||
"fileNotEncrypted": "Der Chat ist verschlüsselt, aber die Datei wurde unverschlüsselt übertragen"
|
||||
}
|
||||
},
|
||||
"warnings": {
|
||||
|
@ -776,6 +776,50 @@ class XmppService {
|
||||
&& await _automaticFileDownloadAllowed()
|
||||
&& await GetIt.I.get<RosterService>().isInRoster(conversationJid);
|
||||
}
|
||||
|
||||
/// Handles receiving a message stanza of type error.
|
||||
Future<void> _handleErrorMessage(MessageEvent event) async {
|
||||
if (event.error == null) {
|
||||
_log.warning('Received error for message ${event.sid} without an error element');
|
||||
return;
|
||||
}
|
||||
|
||||
final ms = GetIt.I.get<MessageService>();
|
||||
final msg = await ms.getMessageByStanzaId(
|
||||
event.fromJid.toBare().toString(),
|
||||
event.sid,
|
||||
);
|
||||
|
||||
if (msg == null) {
|
||||
_log.warning('Received error for message ${event.sid} we cannot find');
|
||||
return;
|
||||
}
|
||||
|
||||
int error;
|
||||
switch (event.error!.error) {
|
||||
case 'service-unavailable':
|
||||
error = messageServiceUnavailable;
|
||||
break;
|
||||
case 'remote-server-timeout':
|
||||
error = messageRemoteServerTimeout;
|
||||
break;
|
||||
case 'remote-server-not-found':
|
||||
error = messageRemoteServerNotFound;
|
||||
break;
|
||||
default:
|
||||
error = unspecifiedError;
|
||||
break;
|
||||
}
|
||||
|
||||
final newMsg = await ms.updateMessage(
|
||||
msg.id,
|
||||
errorType: error,
|
||||
);
|
||||
|
||||
// TODO(PapaTutuWawa): Show a notification for certain error types, i.e. those
|
||||
// that mean that the message could not be delivered.
|
||||
sendEvent(MessageUpdatedEvent(message: newMsg));
|
||||
}
|
||||
|
||||
Future<void> _onMessage(MessageEvent event, { dynamic extra }) async {
|
||||
// The jid this message event is meant for
|
||||
@ -783,6 +827,12 @@ class XmppService {
|
||||
? event.toJid.toBare().toString()
|
||||
: event.fromJid.toBare().toString();
|
||||
|
||||
if (event.type == 'error') {
|
||||
await _handleErrorMessage(event);
|
||||
_log.finest('Processed error message. Ending event processing here.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Process the chat state update. Can also be attached to other messages
|
||||
if (event.chatState != null) await _onChatState(event.chatState!, conversationJid);
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
import 'package:moxxmpp/moxxmpp.dart';
|
||||
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||
import 'package:omemo_dart/omemo_dart.dart';
|
||||
|
||||
const unspecifiedError = -1;
|
||||
const noError = 0;
|
||||
const fileUploadFailedError = 1;
|
||||
const messageNotEncryptedForDevice = 2;
|
||||
@ -14,6 +16,9 @@ const messageContactDoesNotSupportOmemo = 9;
|
||||
const messageChatEncryptedButFileNot = 10;
|
||||
const messageFailedToEncryptFile = 11;
|
||||
const fileDownloadFailedError = 12;
|
||||
const messageServiceUnavailable = 13;
|
||||
const messageRemoteServerTimeout = 14;
|
||||
const messageRemoteServerNotFound = 15;
|
||||
|
||||
int errorTypeFromException(dynamic exception) {
|
||||
if (exception is NoDecryptionKeyException) {
|
||||
@ -32,3 +37,24 @@ int errorTypeFromException(dynamic exception) {
|
||||
|
||||
return noError;
|
||||
}
|
||||
|
||||
String errorToTranslatableString(int error) {
|
||||
assert(error != noError, 'Calling errorToTranslatableString with noError makes no sense');
|
||||
|
||||
switch (error) {
|
||||
case fileUploadFailedError: return t.errors.message.fileUploadFailed;
|
||||
case messageContactDoesNotSupportOmemo: return t.errors.message.contactDoesntSupportOmemo;
|
||||
case fileDownloadFailedError: return t.errors.message.fileDownloadFailed;
|
||||
case messageServiceUnavailable: return t.errors.message.serviceUnavailable;
|
||||
case messageRemoteServerTimeout: return t.errors.message.remoteServerTimeout;
|
||||
case messageRemoteServerNotFound: return t.errors.message.remoteServerNotFound;
|
||||
case messageFailedToEncrypt: return t.errors.message.failedToEncrypt;
|
||||
case messageFailedToDecryptFile: return t.errors.message.failedToDecryptFile;
|
||||
case messageChatEncryptedButFileNot: return t.errors.message.fileNotEncrypted;
|
||||
case messageFailedToEncryptFile: return t.errors.message.failedToEncryptFile;
|
||||
case unspecifiedError: return t.errors.message.unspecified;
|
||||
}
|
||||
|
||||
assert(false, 'Invalid error code $error used');
|
||||
return '';
|
||||
}
|
||||
|
@ -109,14 +109,10 @@ class Message with _$Message {
|
||||
}
|
||||
|
||||
/// Returns true if the message is an error. If not, then returns false.
|
||||
bool isError() {
|
||||
return errorType != null && errorType != noError;
|
||||
}
|
||||
bool get hasError => errorType != null && errorType != noError;
|
||||
|
||||
/// Returns true if the message is a warning. If not, then returns false.
|
||||
bool isWarning() {
|
||||
return warningType != null && warningType != noWarning;
|
||||
}
|
||||
bool get hasWarning => warningType != null && warningType != noWarning;
|
||||
|
||||
/// Returns a representative emoji for a message. Its primary purpose is
|
||||
/// to provide a universal fallback for quoted media messages.
|
||||
@ -125,7 +121,7 @@ class Message with _$Message {
|
||||
}
|
||||
|
||||
/// Returns true if the message can be quoted. False if not.
|
||||
bool get isQuotable => !isError() && !isRetracted && !isFileUploadNotification && !isUploading && !isDownloading;
|
||||
bool get isQuotable => !hasError && !isRetracted && !isFileUploadNotification && !isUploading && !isDownloading;
|
||||
|
||||
/// Returns true if the message can be retracted. False if not.
|
||||
/// [sentBySelf] asks whether or not the message was sent by us (the current Jid).
|
||||
@ -142,4 +138,13 @@ class Message with _$Message {
|
||||
/// Returns true if the message can open the selection menu by longpressing. False if
|
||||
/// not.
|
||||
bool get isLongpressable => !isRetracted;
|
||||
|
||||
/// Returns true if the menu item to show the error should be shown in the
|
||||
/// longpress menu.
|
||||
bool get errorMenuVisible {
|
||||
return hasError && (
|
||||
errorType! < messageNotEncryptedForDevice ||
|
||||
errorType! > messageInvalidNumber
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class MessageBubbleBottomState extends State<MessageBubbleBottom> {
|
||||
),
|
||||
),
|
||||
] : [],
|
||||
...widget.message.isError() ? [
|
||||
...widget.message.hasError ? [
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 3),
|
||||
child: Icon(
|
||||
@ -106,7 +106,7 @@ class MessageBubbleBottomState extends State<MessageBubbleBottom> {
|
||||
),
|
||||
),
|
||||
] : [],
|
||||
...widget.message.isWarning() ? [
|
||||
...widget.message.hasWarning ? [
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 3),
|
||||
child: Icon(
|
||||
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_vibrate/flutter_vibrate.dart';
|
||||
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||
//import 'package:moxxyv2/shared/error_types.dart';
|
||||
import 'package:moxxyv2/shared/error_types.dart';
|
||||
import 'package:moxxyv2/shared/helpers.dart';
|
||||
import 'package:moxxyv2/shared/models/message.dart';
|
||||
import 'package:moxxyv2/shared/warning_types.dart';
|
||||
@ -323,7 +323,20 @@ class ChatBubbleState extends State<ChatBubble>
|
||||
},
|
||||
),
|
||||
] : [],
|
||||
...widget.message.isWarning() ? [
|
||||
...widget.message.errorMenuVisible ? [
|
||||
_buildMessageOption(
|
||||
Icons.info_outline,
|
||||
'Show Error',
|
||||
() {
|
||||
showInfoDialog(
|
||||
'Error',
|
||||
errorToTranslatableString(widget.message.errorType!),
|
||||
context,
|
||||
);
|
||||
},
|
||||
),
|
||||
] : [],
|
||||
...widget.message.hasWarning ? [
|
||||
_buildMessageOption(
|
||||
Icons.warning,
|
||||
'Show warning',
|
||||
|
@ -36,7 +36,7 @@ class TextChatWidget extends StatelessWidget {
|
||||
final Widget? topWidget;
|
||||
|
||||
String getMessageText() {
|
||||
if (message.isError()) {
|
||||
if (message.hasError) {
|
||||
return errorTypeToText(message.errorType!);
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ class TextChatWidget extends StatelessWidget {
|
||||
final fontsize = EmojiUtil.hasOnlyEmojis(
|
||||
message.body,
|
||||
ignoreWhitespace: true,
|
||||
) && !message.isError() ?
|
||||
) && !message.hasError ?
|
||||
fontsizeBodyOnlyEmojis :
|
||||
fontsizeBody;
|
||||
|
||||
|
@ -753,14 +753,14 @@ packages:
|
||||
name: moxxmpp
|
||||
url: "https://git.polynom.me/api/packages/Moxxy/pub/"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
moxxmpp_socket_tcp:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: moxxmpp_socket_tcp
|
||||
url: "https://git.polynom.me/api/packages/Moxxy/pub/"
|
||||
source: hosted
|
||||
version: "0.1.2+6"
|
||||
version: "0.1.2+7"
|
||||
moxxyv2_builders:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -60,10 +60,10 @@ dependencies:
|
||||
version: 0.1.15
|
||||
moxxmpp:
|
||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||
version: 0.1.4
|
||||
version: 0.1.5
|
||||
moxxmpp_socket_tcp:
|
||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||
version: 0.1.2+6
|
||||
version: 0.1.2+7
|
||||
moxxyv2_builders:
|
||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||
version: 0.1.0
|
||||
|
Loading…
Reference in New Issue
Block a user