Commit d210215b authored by Torsten Grote's avatar Torsten Grote

Merge branch '1585-new-messaging-client' into 'master'

Add support for image attachments to messaging client

Closes #1585

See merge request !1133
parents f73d2987 00705447
Pipeline #3595 passed with stage
in 8 minutes and 57 seconds
...@@ -25,7 +25,10 @@ public interface ClientHelper { ...@@ -25,7 +25,10 @@ public interface ClientHelper {
throws DbException, FormatException; throws DbException, FormatException;
void addLocalMessage(Transaction txn, Message m, BdfDictionary metadata, void addLocalMessage(Transaction txn, Message m, BdfDictionary metadata,
boolean shared) throws DbException, FormatException; boolean shared, boolean temporary)
throws DbException, FormatException;
Message createMessage(GroupId g, long timestamp, byte[] body);
Message createMessage(GroupId g, long timestamp, BdfList body) Message createMessage(GroupId g, long timestamp, BdfList body)
throws FormatException; throws FormatException;
...@@ -108,7 +111,7 @@ public interface ClientHelper { ...@@ -108,7 +111,7 @@ public interface ClientHelper {
Author parseAndValidateAuthor(BdfList author) throws FormatException; Author parseAndValidateAuthor(BdfList author) throws FormatException;
PublicKey parseAndValidateAgreementPublicKey(byte[] publicKeyBytes) PublicKey parseAndValidateAgreementPublicKey(byte[] publicKeyBytes)
throws FormatException; throws FormatException;
TransportProperties parseAndValidateTransportProperties( TransportProperties parseAndValidateTransportProperties(
BdfDictionary properties) throws FormatException; BdfDictionary properties) throws FormatException;
......
...@@ -85,15 +85,21 @@ class ClientHelperImpl implements ClientHelper { ...@@ -85,15 +85,21 @@ class ClientHelperImpl implements ClientHelper {
@Override @Override
public void addLocalMessage(Message m, BdfDictionary metadata, public void addLocalMessage(Message m, BdfDictionary metadata,
boolean shared) throws DbException, FormatException { boolean shared) throws DbException, FormatException {
db.transaction(false, txn -> addLocalMessage(txn, m, metadata, shared)); db.transaction(false, txn -> addLocalMessage(txn, m, metadata, shared,
false));
} }
@Override @Override
public void addLocalMessage(Transaction txn, Message m, public void addLocalMessage(Transaction txn, Message m,
BdfDictionary metadata, boolean shared) BdfDictionary metadata, boolean shared, boolean temporary)
throws DbException, FormatException { throws DbException, FormatException {
db.addLocalMessage(txn, m, metadataEncoder.encode(metadata), shared, db.addLocalMessage(txn, m, metadataEncoder.encode(metadata), shared,
false); temporary);
}
@Override
public Message createMessage(GroupId g, long timestamp, byte[] body) {
return messageFactory.createMessage(g, timestamp, body);
} }
@Override @Override
......
...@@ -284,7 +284,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, ...@@ -284,7 +284,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
meta.put("transportId", t.getString()); meta.put("transportId", t.getString());
meta.put("version", version); meta.put("version", version);
meta.put("local", local); meta.put("local", local);
clientHelper.addLocalMessage(txn, m, meta, shared); clientHelper.addLocalMessage(txn, m, meta, shared, false);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
......
...@@ -314,6 +314,7 @@ class ValidationManagerImpl implements ValidationManager, Service, ...@@ -314,6 +314,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
try { try {
shareMsg = hook.incomingMessage(txn, m, meta); shareMsg = hook.incomingMessage(txn, m, meta);
} catch (InvalidMessageException e) { } catch (InvalidMessageException e) {
logException(LOG, INFO, e);
invalidateMessage(txn, m.getId()); invalidateMessage(txn, m.getId());
return new DeliveryResult(false, false); return new DeliveryResult(false, false);
} }
......
...@@ -438,7 +438,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, ...@@ -438,7 +438,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_UPDATE_VERSION, updateVersion); meta.put(MSG_KEY_UPDATE_VERSION, updateVersion);
meta.put(MSG_KEY_LOCAL, true); meta.put(MSG_KEY_LOCAL, true);
clientHelper.addLocalMessage(txn, m, meta, true); clientHelper.addLocalMessage(txn, m, meta, true, false);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
......
...@@ -637,7 +637,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { ...@@ -637,7 +637,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
will(returnValue(timestamp)); will(returnValue(timestamp));
oneOf(clientHelper).createMessage(g, timestamp, body); oneOf(clientHelper).createMessage(g, timestamp, body);
will(returnValue(message)); will(returnValue(message));
oneOf(clientHelper).addLocalMessage(txn, message, meta, shared); oneOf(clientHelper).addLocalMessage(txn, message, meta, shared,
false);
}}); }});
} }
} }
package org.briarproject.bramble.test; package org.briarproject.bramble.test;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.battery.DefaultBatteryManagerModule; import org.briarproject.bramble.battery.DefaultBatteryManagerModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.DefaultEventExecutorModule;
import dagger.Module; import dagger.Module;
import dagger.Provides;
@Module(includes = { @Module(includes = {
DefaultBatteryManagerModule.class, DefaultBatteryManagerModule.class,
...@@ -13,4 +15,20 @@ import dagger.Module; ...@@ -13,4 +15,20 @@ import dagger.Module;
TestSecureRandomModule.class TestSecureRandomModule.class
}) })
public class BrambleCoreIntegrationTestModule { public class BrambleCoreIntegrationTestModule {
@Provides
FeatureFlags provideFeatureFlags() {
return new FeatureFlags() {
@Override
public boolean shouldEnableImageAttachments() {
return true;
}
@Override
public boolean shouldEnableRemoteContacts() {
return true;
}
};
}
} }
...@@ -131,7 +131,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase { ...@@ -131,7 +131,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
localUpdateBody); localUpdateBody);
will(returnValue(localUpdate)); will(returnValue(localUpdate));
oneOf(clientHelper).addLocalMessage(txn, localUpdate, oneOf(clientHelper).addLocalMessage(txn, localUpdate,
localUpdateMeta, true); localUpdateMeta, true, false);
}}); }});
} }
...@@ -284,7 +284,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase { ...@@ -284,7 +284,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
newLocalUpdateBody); newLocalUpdateBody);
will(returnValue(newLocalUpdate)); will(returnValue(newLocalUpdate));
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate, oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
newLocalUpdateMeta, true); newLocalUpdateMeta, true, false);
// No visibilities have changed // No visibilities have changed
}}); }});
...@@ -382,7 +382,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase { ...@@ -382,7 +382,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
newLocalUpdateBody); newLocalUpdateBody);
will(returnValue(newLocalUpdate)); will(returnValue(newLocalUpdate));
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate, oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
newLocalUpdateMeta, true); newLocalUpdateMeta, true, false);
// The client's visibility has changed // The client's visibility has changed
oneOf(hook).onClientVisibilityChanging(txn, contact, visibility); oneOf(hook).onClientVisibilityChanging(txn, contact, visibility);
}}); }});
...@@ -567,7 +567,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase { ...@@ -567,7 +567,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
newLocalUpdateBody); newLocalUpdateBody);
will(returnValue(newLocalUpdate)); will(returnValue(newLocalUpdate));
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate, oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
newLocalUpdateMeta, true); newLocalUpdateMeta, true, false);
// The client's visibility has changed // The client's visibility has changed
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
...@@ -640,7 +640,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase { ...@@ -640,7 +640,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
newLocalUpdateBody); newLocalUpdateBody);
will(returnValue(newLocalUpdate)); will(returnValue(newLocalUpdate));
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate, oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
newLocalUpdateMeta, true); newLocalUpdateMeta, true, false);
// The client's visibility has changed // The client's visibility has changed
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
......
...@@ -34,7 +34,6 @@ import org.briarproject.bramble.api.Pair; ...@@ -34,7 +34,6 @@ import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchContactException;
...@@ -46,7 +45,6 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; ...@@ -46,7 +45,6 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionRegistry; import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent; import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent; import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent; import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
import org.briarproject.bramble.api.sync.event.MessagesSentEvent; import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
...@@ -65,10 +63,9 @@ import org.briarproject.briar.android.util.BriarSnackbarBuilder; ...@@ -65,10 +63,9 @@ import org.briarproject.briar.android.util.BriarSnackbarBuilder;
import org.briarproject.briar.android.view.BriarRecyclerView; import org.briarproject.briar.android.view.BriarRecyclerView;
import org.briarproject.briar.android.view.ImagePreview; import org.briarproject.briar.android.view.ImagePreview;
import org.briarproject.briar.android.view.TextAttachmentController; import org.briarproject.briar.android.view.TextAttachmentController;
import org.briarproject.briar.android.view.TextAttachmentController.AttachImageListener; import org.briarproject.briar.android.view.TextAttachmentController.AttachmentListener;
import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.android.view.TextInputView;
import org.briarproject.briar.android.view.TextSendController; import org.briarproject.briar.android.view.TextSendController;
import org.briarproject.briar.android.view.TextSendController.SendListener;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.blog.BlogSharingManager; import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.client.ProtocolStateException;
...@@ -83,7 +80,6 @@ import org.briarproject.briar.api.introduction.IntroductionManager; ...@@ -83,7 +80,6 @@ import org.briarproject.briar.api.introduction.IntroductionManager;
import org.briarproject.briar.api.messaging.Attachment; import org.briarproject.briar.api.messaging.Attachment;
import org.briarproject.briar.api.messaging.AttachmentHeader; import org.briarproject.briar.api.messaging.AttachmentHeader;
import org.briarproject.briar.api.messaging.MessagingManager; import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
...@@ -94,7 +90,6 @@ import java.util.List; ...@@ -94,7 +90,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
...@@ -129,6 +124,7 @@ import static org.briarproject.briar.android.conversation.ImageActivity.NAME; ...@@ -129,6 +124,7 @@ import static org.briarproject.briar.android.conversation.ImageActivity.NAME;
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName; import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
import static org.briarproject.briar.android.util.UiUtils.getBulbTransitionName; import static org.briarproject.briar.android.util.UiUtils.getBulbTransitionName;
import static org.briarproject.briar.android.util.UiUtils.observeOnce; import static org.briarproject.briar.android.util.UiUtils.observeOnce;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_ATTACHMENTS_PER_MESSAGE;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_TEXT_LENGTH; import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_TEXT_LENGTH;
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED; import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED;
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED; import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED;
...@@ -136,8 +132,8 @@ import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.S ...@@ -136,8 +132,8 @@ import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.S
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class ConversationActivity extends BriarActivity public class ConversationActivity extends BriarActivity
implements EventListener, ConversationListener, SendListener, implements EventListener, ConversationListener, TextCache,
TextCache, AttachmentCache, AttachImageListener { AttachmentCache, AttachmentListener {
public static final String CONTACT_ID = "briar.CONTACT_ID"; public static final String CONTACT_ID = "briar.CONTACT_ID";
...@@ -152,9 +148,6 @@ public class ConversationActivity extends BriarActivity ...@@ -152,9 +148,6 @@ public class ConversationActivity extends BriarActivity
@Inject @Inject
ConnectionRegistry connectionRegistry; ConnectionRegistry connectionRegistry;
@Inject @Inject
@CryptoExecutor
Executor cryptoExecutor;
@Inject
ViewModelProvider.Factory viewModelFactory; ViewModelProvider.Factory viewModelFactory;
@Inject @Inject
FeatureFlags featureFlags; FeatureFlags featureFlags;
...@@ -169,10 +162,6 @@ public class ConversationActivity extends BriarActivity ...@@ -169,10 +162,6 @@ public class ConversationActivity extends BriarActivity
@Inject @Inject
volatile EventBus eventBus; volatile EventBus eventBus;
@Inject @Inject
volatile SettingsManager settingsManager;
@Inject
volatile PrivateMessageFactory privateMessageFactory;
@Inject
volatile IntroductionManager introductionManager; volatile IntroductionManager introductionManager;
@Inject @Inject
volatile ForumSharingManager forumSharingManager; volatile ForumSharingManager forumSharingManager;
...@@ -267,10 +256,10 @@ public class ConversationActivity extends BriarActivity ...@@ -267,10 +256,10 @@ public class ConversationActivity extends BriarActivity
if (featureFlags.shouldEnableImageAttachments()) { if (featureFlags.shouldEnableImageAttachments()) {
ImagePreview imagePreview = findViewById(R.id.imagePreview); ImagePreview imagePreview = findViewById(R.id.imagePreview);
sendController = new TextAttachmentController(textInputView, sendController = new TextAttachmentController(textInputView,
imagePreview, this, this, viewModel); imagePreview, this, viewModel);
observeOnce(viewModel.hasImageSupport(), this, hasSupport -> { observeOnce(viewModel.hasImageSupport(), this, hasSupport -> {
if (hasSupport != null && hasSupport) { if (hasSupport != null && hasSupport) {
// remove cast when removing FEATURE_FLAG_IMAGE_ATTACHMENTS // TODO: remove cast when removing feature flag
((TextAttachmentController) sendController) ((TextAttachmentController) sendController)
.setImagesSupported(); .setImagesSupported();
} }
...@@ -305,7 +294,7 @@ public class ConversationActivity extends BriarActivity ...@@ -305,7 +294,7 @@ public class ConversationActivity extends BriarActivity
Snackbar.LENGTH_SHORT) Snackbar.LENGTH_SHORT)
.show(); .show();
} else if (request == REQUEST_ATTACH_IMAGE && result == RESULT_OK) { } else if (request == REQUEST_ATTACH_IMAGE && result == RESULT_OK) {
// remove cast when removing FEATURE_FLAG_IMAGE_ATTACHMENTS // TODO: remove cast when removing feature flag
((TextAttachmentController) sendController).onImageReceived(data); ((TextAttachmentController) sendController).onImageReceived(data);
} }
} }
...@@ -454,7 +443,7 @@ public class ConversationActivity extends BriarActivity ...@@ -454,7 +443,7 @@ public class ConversationActivity extends BriarActivity
if (text == null) { if (text == null) {
LOG.info("Eagerly loading text for latest message"); LOG.info("Eagerly loading text for latest message");
text = messagingManager.getMessageText(id); text = messagingManager.getMessageText(id);
textCache.put(id, text); textCache.put(id, requireNonNull(text));
} }
} }
// If the message has a single image, load its size - for multiple // If the message has a single image, load its size - for multiple
...@@ -478,8 +467,10 @@ public class ConversationActivity extends BriarActivity ...@@ -478,8 +467,10 @@ public class ConversationActivity extends BriarActivity
adapter.incrementRevision(); adapter.incrementRevision();
textInputView.setReady(true); textInputView.setReady(true);
// start observing onboarding after enabling // start observing onboarding after enabling
viewModel.showImageOnboarding().observeEvent(this, if (featureFlags.shouldEnableImageAttachments()) {
this::showImageOnboarding); viewModel.showImageOnboarding().observeEvent(this,
this::showImageOnboarding);
}
List<ConversationItem> items = createItems(headers); List<ConversationItem> items = createItems(headers);
adapter.addAll(items); adapter.addAll(items);
list.showData(); list.showData();
...@@ -515,7 +506,7 @@ public class ConversationActivity extends BriarActivity ...@@ -515,7 +506,7 @@ public class ConversationActivity extends BriarActivity
long start = now(); long start = now();
String text = messagingManager.getMessageText(m); String text = messagingManager.getMessageText(m);
logDuration(LOG, "Loading text", start); logDuration(LOG, "Loading text", start);
displayMessageText(m, text); displayMessageText(m, requireNonNull(text));
} catch (DbException e) { } catch (DbException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
} }
...@@ -660,6 +651,14 @@ public class ConversationActivity extends BriarActivity ...@@ -660,6 +651,14 @@ public class ConversationActivity extends BriarActivity
startActivityForResult(intent, REQUEST_ATTACH_IMAGE); startActivityForResult(intent, REQUEST_ATTACH_IMAGE);
} }
@Override
public void onTooManyAttachments() {
String format = getResources().getString(
R.string.messaging_too_many_attachments_toast);
String warning = String.format(format, MAX_ATTACHMENTS_PER_MESSAGE);
Toast.makeText(this, warning, LENGTH_SHORT).show();
}
@Override @Override
public void onSendClick(@Nullable String text, public void onSendClick(@Nullable String text,
List<AttachmentHeader> attachmentHeaders) { List<AttachmentHeader> attachmentHeaders) {
...@@ -729,7 +728,7 @@ public class ConversationActivity extends BriarActivity ...@@ -729,7 +728,7 @@ public class ConversationActivity extends BriarActivity
} }
private void showImageOnboarding() { private void showImageOnboarding() {
// remove cast when removing FEATURE_FLAG_IMAGE_ATTACHMENTS // TODO: remove cast when removing feature flag
((TextAttachmentController) sendController) ((TextAttachmentController) sendController)
.showImageOnboarding(this, () -> .showImageOnboarding(this, () ->
viewModel.onImageOnboardingSeen()); viewModel.onImageOnboardingSeen());
......
...@@ -61,6 +61,7 @@ public class ConversationViewModel extends AndroidViewModel ...@@ -61,6 +61,7 @@ public class ConversationViewModel extends AndroidViewModel
private static Logger LOG = private static Logger LOG =
getLogger(ConversationViewModel.class.getName()); getLogger(ConversationViewModel.class.getName());
private static final String SHOW_ONBOARDING_IMAGE = private static final String SHOW_ONBOARDING_IMAGE =
"showOnboardingImage"; "showOnboardingImage";
private static final String SHOW_ONBOARDING_INTRODUCTION = private static final String SHOW_ONBOARDING_INTRODUCTION =
...@@ -181,12 +182,17 @@ public class ConversationViewModel extends AndroidViewModel ...@@ -181,12 +182,17 @@ public class ConversationViewModel extends AndroidViewModel
}); });
} }
@UiThread
void sendMessage(@Nullable String text, void sendMessage(@Nullable String text,
List<AttachmentHeader> attachmentHeaders, long timestamp) { List<AttachmentHeader> headers, long timestamp) {
// messagingGroupId is loaded with the contact // messagingGroupId is loaded with the contact
observeForeverOnce(messagingGroupId, groupId -> { observeForeverOnce(messagingGroupId, groupId -> {
if (groupId == null) throw new IllegalStateException(); requireNonNull(groupId);
createMessage(groupId, text, attachmentHeaders, timestamp); observeForeverOnce(imageSupport, hasImageSupport -> {
requireNonNull(hasImageSupport);
createMessage(groupId, text, headers, timestamp,
hasImageSupport);
});
}); });
} }
...@@ -270,21 +276,24 @@ public class ConversationViewModel extends AndroidViewModel ...@@ -270,21 +276,24 @@ public class ConversationViewModel extends AndroidViewModel
} }
private void createMessage(GroupId groupId, @Nullable String text, private void createMessage(GroupId groupId, @Nullable String text,
List<AttachmentHeader> attachments, long timestamp) { List<AttachmentHeader> headers, long timestamp,
boolean hasImageSupport) {
try { try {
// TODO remove when text can be null in the backend PrivateMessage pm;
String msgText = text == null ? "null" : text; if (hasImageSupport) {
PrivateMessage pm = privateMessageFactory pm = privateMessageFactory.createPrivateMessage(groupId,
.createPrivateMessage(groupId, timestamp, msgText, timestamp, text, headers);
attachments); } else {
storeMessage(pm, msgText, attachments); pm = privateMessageFactory.createLegacyPrivateMessage(
groupId, timestamp, requireNonNull(text));
}
storeMessage(pm);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new AssertionError(e);
} }
} }
private void storeMessage(PrivateMessage m, @Nullable String text, private void storeMessage(PrivateMessage m) {
List<AttachmentHeader> attachments) {
attachmentCreator.onAttachmentsSent(m.getMessage().getId()); attachmentCreator.onAttachmentsSent(m.getMessage().getId());
dbExecutor.execute(() -> { dbExecutor.execute(() -> {
try { try {
...@@ -295,7 +304,7 @@ public class ConversationViewModel extends AndroidViewModel ...@@ -295,7 +304,7 @@ public class ConversationViewModel extends AndroidViewModel
PrivateMessageHeader h = new PrivateMessageHeader( PrivateMessageHeader h = new PrivateMessageHeader(
message.getId(), message.getGroupId(), message.getId(), message.getGroupId(),
message.getTimestamp(), true, true, false, false, message.getTimestamp(), true, true, false, false,
text != null, attachments); m.hasText(), m.getAttachmentHeaders());
// TODO add text to cache when available here // TODO add text to cache when available here
addedHeader.postEvent(h); addedHeader.postEvent(h);
} catch (DbException e) { } catch (DbException e) {
......
...@@ -41,9 +41,9 @@ import static android.support.v4.content.ContextCompat.getColor; ...@@ -41,9 +41,9 @@ import static android.support.v4.content.ContextCompat.getColor;
import static android.support.v4.view.AbsSavedState.EMPTY_STATE; import static android.support.v4.view.AbsSavedState.EMPTY_STATE;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static java.util.Objects.requireNonNull;
import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute; import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute;
import static org.briarproject.briar.api.messaging.MessagingConstants.IMAGE_MIME_TYPES; import static org.briarproject.briar.api.messaging.MessagingConstants.IMAGE_MIME_TYPES;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_ATTACHMENTS_PER_MESSAGE;
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED; import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED;
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED; import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED;
...@@ -53,7 +53,7 @@ public class TextAttachmentController extends TextSendController ...@@ -53,7 +53,7 @@ public class TextAttachmentController extends TextSendController
implements ImagePreviewListener { implements ImagePreviewListener {
private final ImagePreview imagePreview; private final ImagePreview imagePreview;
private final AttachImageListener imageListener; private final AttachmentListener attachmentListener;
private final CompositeSendButton sendButton; private final CompositeSendButton sendButton;
private final AttachmentManager attachmentManager; private final AttachmentManager attachmentManager;
...@@ -62,10 +62,10 @@ public class TextAttachmentController extends TextSendController ...@@ -62,10 +62,10 @@ public class TextAttachmentController extends TextSendController
private boolean loadingUris = false; private boolean loadingUris = false;