add force P2P menu item to failed HTTP uploads

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 34 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java        | 29 
src/main/res/menu/message_context.xml                                    |  3 
src/main/res/values/strings.xml                                          |  1 
4 files changed, 45 insertions(+), 22 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -1816,11 +1816,15 @@ public class XmppConnectionService extends Service {
         }
     }
 
-    private void sendFileMessage(final Message message, final boolean delay) {
-        Log.d(Config.LOGTAG, "send file message");
-        final Account account = message.getConversation().getAccount();
-        if (account.httpUploadAvailable(fileBackend.getFile(message, false).getSize())
-                || message.getConversation().getMode() == Conversation.MODE_MULTI) {
+    private void sendFileMessage(
+            final Message message, final boolean delay, final boolean forceP2P) {
+        final var account = message.getConversation().getAccount();
+        Log.d(
+                Config.LOGTAG,
+                account.getJid().asBareJid() + ": send file message. forceP2P=" + forceP2P);
+        if ((account.httpUploadAvailable(fileBackend.getFile(message, false).getSize())
+                        || message.getConversation().getMode() == Conversation.MODE_MULTI)
+                && !forceP2P) {
             mHttpConnectionManager.createNewUploadConnection(message, delay);
         } else {
             mJingleConnectionManager.startJingleFileTransfer(message);
@@ -1828,10 +1832,14 @@ public class XmppConnectionService extends Service {
     }
 
     public void sendMessage(final Message message) {
-        sendMessage(message, false, false);
+        sendMessage(message, false, false, false);
     }
 
-    private void sendMessage(final Message message, final boolean resend, final boolean delay) {
+    private void sendMessage(
+            final Message message,
+            final boolean resend,
+            final boolean delay,
+            final boolean forceP2P) {
         final Account account = message.getConversation().getAccount();
         if (account.setShowErrorNotification(true)) {
             databaseBackend.updateAccount(account);
@@ -1878,7 +1886,7 @@ public class XmppConnectionService extends Service {
                                         fileBackend.getFile(message, false).getSize())
                                 || conversation.getMode() == Conversation.MODE_MULTI
                                 || message.fixCounterpart()) {
-                            this.sendFileMessage(message, delay);
+                            this.sendFileMessage(message, delay, forceP2P);
                         } else {
                             break;
                         }
@@ -1893,7 +1901,7 @@ public class XmppConnectionService extends Service {
                                         fileBackend.getFile(message, false).getSize())
                                 || conversation.getMode() == Conversation.MODE_MULTI
                                 || message.fixCounterpart()) {
-                            this.sendFileMessage(message, delay);
+                            this.sendFileMessage(message, delay, forceP2P);
                         } else {
                             break;
                         }
@@ -1908,7 +1916,7 @@ public class XmppConnectionService extends Service {
                                         fileBackend.getFile(message, false).getSize())
                                 || conversation.getMode() == Conversation.MODE_MULTI
                                 || message.fixCounterpart()) {
-                            this.sendFileMessage(message, delay);
+                            this.sendFileMessage(message, delay, forceP2P);
                         } else {
                             break;
                         }
@@ -2030,7 +2038,7 @@ public class XmppConnectionService extends Service {
     }
 
     public void resendMessage(final Message message, final boolean delay) {
-        sendMessage(message, true, delay);
+        sendMessage(message, true, delay, false);
     }
 
     public void requestEasyOnboardingInvite(
@@ -5992,10 +6000,10 @@ public class XmppConnectionService extends Service {
         return this.mHttpConnectionManager;
     }
 
-    public void resendFailedMessages(final Message message) {
+    public void resendFailedMessages(final Message message, final boolean forceP2P) {
         message.setTime(System.currentTimeMillis());
         markMessage(message, Message.STATUS_WAITING);
-        this.resendMessage(message, false);
+        this.sendMessage(message, true, false, forceP2P);
         if (message.getConversation() instanceof Conversation c) {
             c.sort();
         }

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -1305,6 +1305,7 @@ public class ConversationFragment extends XmppFragment
             final MenuItem correctMessage = menu.findItem(R.id.correct_message);
             final MenuItem shareWith = menu.findItem(R.id.share_with);
             final MenuItem sendAgain = menu.findItem(R.id.send_again);
+            final MenuItem retryAsP2P = menu.findItem(R.id.send_again_as_p2p);
             final MenuItem copyUrl = menu.findItem(R.id.copy_url);
             final MenuItem downloadFile = menu.findItem(R.id.download_file);
             final MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission);
@@ -1372,6 +1373,12 @@ public class ConversationFragment extends XmppFragment
             }
             if (m.getStatus() == Message.STATUS_SEND_FAILED) {
                 sendAgain.setVisible(true);
+                final var fileNotUploaded = m.isFileOrImage() && !m.hasFileOnRemoteHost();
+                final var isPeerOnline =
+                        conversational.getMode() == Conversation.MODE_SINGLE
+                                && (conversational instanceof Conversation c)
+                                && !c.getContact().getPresences().isEmpty();
+                retryAsP2P.setVisible(fileNotUploaded && isPeerOnline);
             }
             if (m.hasFileOnRemoteHost()
                     || m.isGeoUri()
@@ -1438,7 +1445,10 @@ public class ConversationFragment extends XmppFragment
                 quoteMessage(selectedMessage);
                 return true;
             case R.id.send_again:
-                resendMessage(selectedMessage);
+                resendMessage(selectedMessage, false);
+                return true;
+            case R.id.send_again_as_p2p:
+                resendMessage(selectedMessage, true);
                 return true;
             case R.id.copy_url:
                 ShareUtil.copyUrlToClipboard(activity, selectedMessage);
@@ -2195,12 +2205,11 @@ public class ConversationFragment extends XmppFragment
         builder.create().show();
     }
 
-    private void resendMessage(final Message message) {
+    private void resendMessage(final Message message, final boolean forceP2P) {
         if (message.isFileOrImage()) {
-            if (!(message.getConversation() instanceof Conversation)) {
+            if (!(message.getConversation() instanceof Conversation conversation)) {
                 return;
             }
-            final Conversation conversation = (Conversation) message.getConversation();
             final DownloadableFile file =
                     activity.xmppConnectionService.getFileBackend().getFile(message);
             if ((file.exists() && file.canRead()) || message.hasFileOnRemoteHost()) {
@@ -2208,14 +2217,16 @@ public class ConversationFragment extends XmppFragment
                 if (!message.hasFileOnRemoteHost()
                         && xmppConnection != null
                         && conversation.getMode() == Conversational.MODE_SINGLE
-                        && !xmppConnection
-                                .getFeatures()
-                                .httpUpload(message.getFileParams().getSize())) {
+                        && (!xmppConnection
+                                        .getFeatures()
+                                        .httpUpload(message.getFileParams().getSize())
+                                || forceP2P)) {
                     activity.selectPresence(
                             conversation,
                             () -> {
                                 message.setCounterpart(conversation.getNextCounterpart());
-                                activity.xmppConnectionService.resendFailedMessages(message);
+                                activity.xmppConnectionService.resendFailedMessages(
+                                        message, forceP2P);
                                 new Handler()
                                         .post(
                                                 () -> {
@@ -2238,7 +2249,7 @@ public class ConversationFragment extends XmppFragment
                 return;
             }
         }
-        activity.xmppConnectionService.resendFailedMessages(message);
+        activity.xmppConnectionService.resendFailedMessages(message, false);
         new Handler()
                 .post(
                         () -> {

src/main/res/menu/message_context.xml 🔗

@@ -55,6 +55,9 @@
         android:id="@+id/send_again"
         android:title="@string/send_again"
         android:visible="false" />
+    <item android:id="@+id/send_again_as_p2p"
+        android:title="@string/retry_with_p2p"
+        android:visible="false"/>
     <item
         android:id="@+id/download_file"
         android:title="@string/download_x_file"

src/main/res/values/strings.xml 🔗

@@ -315,6 +315,7 @@
     <string name="paste_as_quote">Paste as quote</string>
     <string name="copy_original_url">Copy original URL</string>
     <string name="send_again">Send again</string>
+    <string name="retry_with_p2p">Retry with P2P</string>
     <string name="file_url">File URL</string>
     <string name="url_copied_to_clipboard">Copied URL to clipboard</string>
     <string name="jabber_id_copied_to_clipboard">Copied XMPP address to clipboard</string>