Compare commits

..

8 Commits

Author SHA1 Message Date
Torsten Grote
115675d7b6 [android] Hide role-dependant private group menu items by default
and only enable them once we know our role
2018-12-18 10:30:39 -02:00
akwizgran
0089c1ac6d Merge branch '1468-restrict-image-size' into 'master'
Fix first issues related to image size

See merge request briar/briar!1018
2018-12-17 12:48:15 +00:00
akwizgran
a37b6d81ed Merge branch '1242-save-snackbar-fix' into 'master'
[android] Clarify the meaning of image save state

See merge request briar/briar!1017
2018-12-17 11:17:12 +00:00
Torsten Grote
1d09a6708a [android] don't ever load an entire image into memory
This happens on API 27+28 if loading TIFF or WebP files.
Using an InputStream with a read limit prevents this.
2018-12-14 20:11:43 -02:00
Torsten Grote
d3b6f484c8 [android] allow image transformations in full-screen view
to prevent crashes from huge images
2018-12-14 20:11:43 -02:00
Torsten Grote
039c6edb66 [android] increase scale levels of PhotoView 2018-12-14 20:11:43 -02:00
Torsten Grote
8b9f89eab2 [android] Clarify the meaning of image save state 2018-12-14 12:27:47 -02:00
akwizgran
1e2c17b170 Merge branch '1242-display-image-attachments-multiple' into 'master'
Swipe left/right in image screen for images from same message

See merge request briar/briar!1012
2018-12-13 16:33:24 +00:00
25 changed files with 66 additions and 113 deletions

View File

@@ -6,6 +6,8 @@ import android.support.annotation.Nullable;
import android.support.media.ExifInterface; import android.support.media.ExifInterface;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import com.bumptech.glide.util.MarkEnforcingInputStream;
import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.Pair;
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;
@@ -44,6 +46,7 @@ class AttachmentController {
private static final Logger LOG = private static final Logger LOG =
getLogger(AttachmentController.class.getName()); getLogger(AttachmentController.class.getName());
private static final int READ_LIMIT = 1024 * 8192;
private final MessagingManager messagingManager; private final MessagingManager messagingManager;
private final int defaultSize; private final int defaultSize;
@@ -128,8 +131,9 @@ class AttachmentController {
} }
Size size = new Size(); Size size = new Size();
InputStream is = new BufferedInputStream(a.getStream()); InputStream is = new MarkEnforcingInputStream(
is.mark(Integer.MAX_VALUE); new BufferedInputStream(a.getStream()));
is.mark(READ_LIMIT);
try { try {
// use exif to get size // use exif to get size
if (h.getContentType().equals("image/jpeg")) { if (h.getContentType().equals("image/jpeg")) {
@@ -142,6 +146,8 @@ class AttachmentController {
// use BitmapFactory to get size // use BitmapFactory to get size
if (size.error) { if (size.error) {
is.reset(); is.reset();
// need to mark again to re-add read limit
is.mark(READ_LIMIT);
size = getSizeFromBitmap(is); size = getSizeFromBitmap(is);
} }
} catch (IOException e) { } catch (IOException e) {
@@ -158,12 +164,11 @@ class AttachmentController {
} }
// get file extension // get file extension
String extension = getExtensionFromMimeType(size.mimeType); String extension = getExtensionFromMimeType(size.mimeType);
if (extension == null) { boolean hasError = extension == null || size.error;
return new AttachmentItem(messageId, 0, 0, "", "", 0, 0, true); if (extension == null) extension = "";
}
return new AttachmentItem(messageId, size.width, size.height, return new AttachmentItem(messageId, size.width, size.height,
size.mimeType, extension, thumbnailSize.width, size.mimeType, extension, thumbnailSize.width,
thumbnailSize.height, size.error); thumbnailSize.height, hasError);
} }
@Nullable @Nullable

View File

@@ -8,7 +8,6 @@ import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
@@ -108,6 +107,7 @@ import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAn
import static android.support.v4.view.ViewCompat.setTransitionName; import static android.support.v4.view.ViewCompat.setTransitionName;
import static android.support.v7.util.SortedList.INVALID_POSITION; import static android.support.v7.util.SortedList.INVALID_POSITION;
import static android.view.Gravity.RIGHT; import static android.view.Gravity.RIGHT;
import static android.widget.Toast.LENGTH_LONG;
import static android.widget.Toast.LENGTH_SHORT; import static android.widget.Toast.LENGTH_SHORT;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.sort; import static java.util.Collections.sort;
@@ -121,9 +121,9 @@ import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_IMAGE_ATTACHMENTS; import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_IMAGE_ATTACHMENTS;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_ATTACH_IMAGE; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_ATTACH_IMAGE;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_INTRODUCTION; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_INTRODUCTION;
import static org.briarproject.briar.android.conversation.ImageActivity.ATTACHMENTS;
import static org.briarproject.briar.android.conversation.ImageActivity.ATTACHMENT_POSITION; import static org.briarproject.briar.android.conversation.ImageActivity.ATTACHMENT_POSITION;
import static org.briarproject.briar.android.conversation.ImageActivity.DATE; import static org.briarproject.briar.android.conversation.ImageActivity.DATE;
import static org.briarproject.briar.android.conversation.ImageActivity.ATTACHMENTS;
import static org.briarproject.briar.android.conversation.ImageActivity.NAME; import static org.briarproject.briar.android.conversation.ImageActivity.NAME;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName; import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
@@ -194,8 +194,6 @@ public class ConversationActivity extends BriarActivity
ViewModelProvider.Factory viewModelFactory; ViewModelProvider.Factory viewModelFactory;
private volatile ContactId contactId; private volatile ContactId contactId;
@Nullable
private Parcelable layoutManagerState;
private final Observer<String> contactNameObserver = name -> { private final Observer<String> contactNameObserver = name -> {
requireNonNull(name); requireNonNull(name);
@@ -311,21 +309,6 @@ public class ConversationActivity extends BriarActivity
list.stopPeriodicUpdate(); list.stopPeriodicUpdate();
} }
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (layoutManager != null) {
layoutManagerState = layoutManager.onSaveInstanceState();
outState.putParcelable("layoutManager", layoutManagerState);
}
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
layoutManagerState = savedInstanceState.getParcelable("layoutManager");
}
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar // Inflate the menu items for use in the action bar
@@ -445,12 +428,8 @@ public class ConversationActivity extends BriarActivity
List<ConversationItem> items = createItems(headers); List<ConversationItem> items = createItems(headers);
adapter.addAll(items); adapter.addAll(items);
list.showData(); list.showData();
if (layoutManagerState == null) {
// Scroll to the bottom // Scroll to the bottom
list.scrollToPosition(adapter.getItemCount() - 1); list.scrollToPosition(adapter.getItemCount() - 1);
} else {
layoutManager.onRestoreInstanceState(layoutManagerState);
}
} else { } else {
LOG.info("Concurrent update, reloading"); LOG.info("Concurrent update, reloading");
loadMessages(); loadMessages();
@@ -492,8 +471,7 @@ public class ConversationActivity extends BriarActivity
adapter.getMessageItem(m); adapter.getMessageItem(m);
if (pair != null) { if (pair != null) {
pair.getSecond().setText(text); pair.getSecond().setText(text);
boolean bottom = layoutManagerState == null && boolean bottom = adapter.isScrolledToBottom(layoutManager);
adapter.isScrolledToBottom(layoutManager);
adapter.notifyItemChanged(pair.getFirst()); adapter.notifyItemChanged(pair.getFirst());
if (bottom) list.scrollToPosition(adapter.getItemCount() - 1); if (bottom) list.scrollToPosition(adapter.getItemCount() - 1);
} }
@@ -524,8 +502,7 @@ public class ConversationActivity extends BriarActivity
adapter.getMessageItem(m); adapter.getMessageItem(m);
if (pair != null) { if (pair != null) {
pair.getSecond().setAttachments(items); pair.getSecond().setAttachments(items);
boolean bottom = layoutManagerState == null && boolean bottom = adapter.isScrolledToBottom(layoutManager);
adapter.isScrolledToBottom(layoutManager);
adapter.notifyItemChanged(pair.getFirst()); adapter.notifyItemChanged(pair.getFirst());
if (bottom) list.scrollToPosition(adapter.getItemCount() - 1); if (bottom) list.scrollToPosition(adapter.getItemCount() - 1);
} }
@@ -576,8 +553,7 @@ public class ConversationActivity extends BriarActivity
private void addConversationItem(ConversationItem item) { private void addConversationItem(ConversationItem item) {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
boolean bottom = layoutManagerState == null && boolean bottom = adapter.isScrolledToBottom(layoutManager);
adapter.isScrolledToBottom(layoutManager);
adapter.incrementRevision(); adapter.incrementRevision();
adapter.add(item); adapter.add(item);
if (bottom) list.scrollToPosition(adapter.getItemCount() - 1); if (bottom) list.scrollToPosition(adapter.getItemCount() - 1);
@@ -844,11 +820,15 @@ public class ConversationActivity extends BriarActivity
i.putExtra(ATTACHMENT_POSITION, attachments.indexOf(item)); i.putExtra(ATTACHMENT_POSITION, attachments.indexOf(item));
i.putExtra(NAME, name); i.putExtra(NAME, name);
i.putExtra(DATE, messageItem.getTime()); i.putExtra(DATE, messageItem.getTime());
// restoring list position should not trigger android bug #224270 if (SDK_INT >= 23) {
String transitionName = item.getTransitionName(); String transitionName = item.getTransitionName();
ActivityOptionsCompat options = ActivityOptionsCompat options =
makeSceneTransitionAnimation(this, view, transitionName); makeSceneTransitionAnimation(this, view, transitionName);
ActivityCompat.startActivity(this, i, options.toBundle()); ActivityCompat.startActivity(this, i, options.toBundle());
} else {
// work-around for android bug #224270
startActivity(i);
}
} }
@DatabaseExecutor @DatabaseExecutor

View File

@@ -82,7 +82,7 @@ public class ImageActivity extends BriarActivity
super.onCreate(state); super.onCreate(state);
// Transitions // Transitions
if (state == null) supportPostponeEnterTransition(); supportPostponeEnterTransition();
Window window = getWindow(); Window window = getWindow();
if (SDK_INT >= 21) { if (SDK_INT >= 21) {
Transition transition = new Fade(); Transition transition = new Fade();
@@ -298,18 +298,13 @@ public class ImageActivity extends BriarActivity
private class ImagePagerAdapter extends FragmentStatePagerAdapter { private class ImagePagerAdapter extends FragmentStatePagerAdapter {
private boolean isFirst = true;
private ImagePagerAdapter(FragmentManager fm) { private ImagePagerAdapter(FragmentManager fm) {
super(fm); super(fm);
} }
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
Fragment f = ImageFragment return ImageFragment.newInstance(attachments.get(position));
.newInstance(attachments.get(position), isFirst);
isFirst = false;
return f;
} }
@Override @Override

View File

@@ -35,21 +35,17 @@ import static org.briarproject.briar.android.conversation.ImageActivity.ATTACHME
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public class ImageFragment extends Fragment { public class ImageFragment extends Fragment {
private final static String IS_FIRST = "isFirst";
@Inject @Inject
ViewModelProvider.Factory viewModelFactory; ViewModelProvider.Factory viewModelFactory;
private AttachmentItem attachment; private AttachmentItem attachment;
private boolean isFirst;
private ImageViewModel viewModel; private ImageViewModel viewModel;
private PhotoView photoView; private PhotoView photoView;
static ImageFragment newInstance(AttachmentItem a, boolean isFirst) { static ImageFragment newInstance(AttachmentItem a) {
ImageFragment f = new ImageFragment(); ImageFragment f = new ImageFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelable(ATTACHMENT_POSITION, a); args.putParcelable(ATTACHMENT_POSITION, a);
args.putBoolean(IS_FIRST, isFirst);
f.setArguments(args); f.setArguments(args);
return f; return f;
} }
@@ -67,7 +63,6 @@ public class ImageFragment extends Fragment {
Bundle args = requireNonNull(getArguments()); Bundle args = requireNonNull(getArguments());
attachment = requireNonNull(args.getParcelable(ATTACHMENT_POSITION)); attachment = requireNonNull(args.getParcelable(ATTACHMENT_POSITION));
isFirst = args.getBoolean(IS_FIRST);
} }
@Nullable @Nullable
@@ -82,6 +77,7 @@ public class ImageFragment extends Fragment {
viewModelFactory).get(ImageViewModel.class); viewModelFactory).get(ImageViewModel.class);
photoView = v.findViewById(R.id.photoView); photoView = v.findViewById(R.id.photoView);
photoView.setScaleLevels(1, 2, 4);
photoView.setOnClickListener(view -> viewModel.clickImage()); photoView.setOnClickListener(view -> viewModel.clickImage());
// Request Listener // Request Listener
@@ -90,7 +86,7 @@ public class ImageFragment extends Fragment {
public boolean onLoadFailed(@Nullable GlideException e, public boolean onLoadFailed(@Nullable GlideException e,
Object model, Target<Drawable> target, Object model, Target<Drawable> target,
boolean isFirstResource) { boolean isFirstResource) {
if (getActivity() != null && isFirst) if (getActivity() != null)
getActivity().supportStartPostponedEnterTransition(); getActivity().supportStartPostponedEnterTransition();
return false; return false;
} }
@@ -109,9 +105,8 @@ public class ImageFragment extends Fragment {
if (viewModel.isOverlappingToolbar(photoView, resource)) { if (viewModel.isOverlappingToolbar(photoView, resource)) {
photoView.setScaleType(FIT_START); photoView.setScaleType(FIT_START);
} }
if (getActivity() != null && isFirst) { if (getActivity() != null)
getActivity().supportStartPostponedEnterTransition(); getActivity().supportStartPostponedEnterTransition();
}
return false; return false;
} }
}; };
@@ -119,9 +114,10 @@ public class ImageFragment extends Fragment {
// Load Image // Load Image
GlideApp.with(this) GlideApp.with(this)
.load(attachment) .load(attachment)
// TODO allow if size < maxTextureSize ?
// .override(SIZE_ORIGINAL)
.diskCacheStrategy(NONE) .diskCacheStrategy(NONE)
.error(R.drawable.ic_image_broken) .error(R.drawable.ic_image_broken)
.dontTransform()
.addListener(listener) .addListener(listener)
.into(photoView); .into(photoView);

View File

@@ -15,7 +15,6 @@ import org.briarproject.briar.android.conversation.glide.BriarImageTransformatio
import org.briarproject.briar.android.conversation.glide.GlideApp; import org.briarproject.briar.android.conversation.glide.GlideApp;
import org.briarproject.briar.android.conversation.glide.Radii; import org.briarproject.briar.android.conversation.glide.Radii;
import static android.os.Build.VERSION.SDK_INT;
import static com.bumptech.glide.load.engine.DiskCacheStrategy.NONE; import static com.bumptech.glide.load.engine.DiskCacheStrategy.NONE;
import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade; import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
@@ -43,9 +42,6 @@ class ImageViewHolder extends ViewHolder {
} else { } else {
setImageViewDimensions(attachment, single, needsStretch); setImageViewDimensions(attachment, single, needsStretch);
loadImage(attachment, r); loadImage(attachment, r);
if (SDK_INT >= 21) {
imageView.setTransitionName(attachment.getTransitionName());
}
} }
} }

View File

@@ -50,9 +50,12 @@ public class ImageViewModel extends AndroidViewModel {
@IoExecutor @IoExecutor
private final Executor ioExecutor; private final Executor ioExecutor;
/**
* true means there was an error saving the image, false if image was saved.
*/
private final MutableLiveData<Boolean> saveState = new MutableLiveData<>();
private final MutableLiveData<Boolean> imageClicked = private final MutableLiveData<Boolean> imageClicked =
new MutableLiveData<>(); new MutableLiveData<>();
private final MutableLiveData<Boolean> saveState = new MutableLiveData<>();
private int toolbarTop, toolbarBottom; private int toolbarTop, toolbarBottom;
@Inject @Inject
@@ -106,8 +109,9 @@ public class ImageViewModel extends AndroidViewModel {
} }
/** /**
* A LiveData that is true if the image was saved, * A LiveData that is true if there was an error
* false if there was an error and null otherwise. * and false if the image was saved.
* It can be null otherwise, if no image was saved recently.
* *
* Call {@link #onSaveStateSeen()} after consuming an update. * Call {@link #onSaveStateSeen()} after consuming an update.
*/ */
@@ -126,7 +130,7 @@ public class ImageViewModel extends AndroidViewModel {
@UiThread @UiThread
void saveImage(AttachmentItem attachment, @Nullable Uri uri) { void saveImage(AttachmentItem attachment, @Nullable Uri uri) {
if (uri == null) { if (uri == null) {
saveState.setValue(false); saveState.setValue(true);
} else { } else {
saveImage(attachment, () -> getOutputStream(uri), null); saveImage(attachment, () -> getOutputStream(uri), null);
} }

View File

@@ -138,7 +138,6 @@ public class GroupActivity extends
inviteMenuItem = menu.findItem(R.id.action_group_invite); inviteMenuItem = menu.findItem(R.id.action_group_invite);
leaveMenuItem = menu.findItem(R.id.action_group_leave); leaveMenuItem = menu.findItem(R.id.action_group_leave);
dissolveMenuItem = menu.findItem(R.id.action_group_dissolve); dissolveMenuItem = menu.findItem(R.id.action_group_dissolve);
showMenuItems();
return super.onCreateOptionsMenu(menu); return super.onCreateOptionsMenu(menu);
} }
@@ -208,7 +207,6 @@ public class GroupActivity extends
} }
private void showMenuItems() { private void showMenuItems() {
if (leaveMenuItem == null || dissolveMenuItem == null) return;
if (isCreator) { if (isCreator) {
revealMenuItem.setVisible(false); revealMenuItem.setVisible(false);
inviteMenuItem.setVisible(true); inviteMenuItem.setVisible(true);

View File

@@ -49,8 +49,7 @@
android:id="@+id/conversationView" android:id="@+id/conversationView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="2" android:layout_weight="2"/>
app:scrollToEnd="false"/>
<org.briarproject.briar.android.view.ImagePreview <org.briarproject.briar.android.view.ImagePreview
android:id="@+id/imagePreview" android:id="@+id/imagePreview"

View File

@@ -1,13 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu <menu
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item <item
android:id="@+id/action_group_invite" android:id="@+id/action_group_invite"
android:icon="@drawable/social_share_white" android:icon="@drawable/social_share_white"
android:title="@string/groups_invite_members" android:title="@string/groups_invite_members"
app:showAsAction="ifRoom"/> android:visible="false"
app:showAsAction="ifRoom"
tools:visible="true"/>
<item <item
android:id="@+id/action_group_member_list" android:id="@+id/action_group_member_list"
@@ -19,18 +22,24 @@
android:id="@+id/action_group_reveal" android:id="@+id/action_group_reveal"
android:icon="@drawable/ic_visibility_white" android:icon="@drawable/ic_visibility_white"
android:title="@string/groups_reveal_contacts" android:title="@string/groups_reveal_contacts"
app:showAsAction="never"/> android:visible="false"
app:showAsAction="never"
tools:visible="true"/>
<item <item
android:id="@+id/action_group_leave" android:id="@+id/action_group_leave"
android:icon="@drawable/action_delete_white" android:icon="@drawable/action_delete_white"
android:title="@string/groups_leave" android:title="@string/groups_leave"
app:showAsAction="never"/> android:visible="false"
app:showAsAction="never"
tools:visible="true"/>
<item <item
android:id="@+id/action_group_dissolve" android:id="@+id/action_group_dissolve"
android:icon="@drawable/action_delete_white" android:icon="@drawable/action_delete_white"
android:title="@string/groups_dissolve" android:title="@string/groups_dissolve"
app:showAsAction="never"/> android:visible="false"
app:showAsAction="never"
tools:visible="true"/>
</menu> </menu>

View File

@@ -32,11 +32,11 @@ import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent; import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
import org.briarproject.briar.client.ConversationClientImpl; import org.briarproject.briar.client.ConversationClientImpl;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@@ -44,7 +44,7 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
@Immutable @Immutable
@@ -219,18 +219,8 @@ class MessagingManagerImpl extends ConversationClientImpl
long timestamp = meta.getLong("timestamp"); long timestamp = meta.getLong("timestamp");
boolean local = meta.getBoolean("local"); boolean local = meta.getBoolean("local");
boolean read = meta.getBoolean("read"); boolean read = meta.getBoolean("read");
// TODO replace fake attachments by real ones
int num = (int) (timestamp % 5);
boolean hasText = num == 0 || id.hashCode() % 2 == 0;
List<AttachmentHeader> attachments = new ArrayList<>(num);
for (int i = 0; i < num; i++) {
byte[] aIdBytes = id.getBytes().clone();
aIdBytes[0] = (byte) i;
MessageId aId = new MessageId(aIdBytes);
attachments.add(new AttachmentHeader(aId, "image/jpeg"));
}
headers.add(new PrivateMessageHeader(id, g, timestamp, local, headers.add(new PrivateMessageHeader(id, g, timestamp, local,
read, s.isSent(), s.isSeen(), hasText, attachments)); read, s.isSent(), s.isSeen(), true, emptyList()));
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
@@ -251,30 +241,11 @@ class MessagingManagerImpl extends ConversationClientImpl
@Override @Override
public Attachment getAttachment(MessageId m) { public Attachment getAttachment(MessageId m) {
// TODO add real implementation // TODO add real implementation
String[] files = new String[] { byte[] bytes = fromHexString("89504E470D0A1A0A0000000D49484452" +
// "error_animated.gif", "000000010000000108060000001F15C4" +
// "error_high.jpg", "890000000A49444154789C6300010000" +
// "error_wide.jpg", "0500010D0A2DB40000000049454E44AE426082");
// "error_huge.gif", return new Attachment(new ByteArrayInputStream(bytes));
// "error_large.gif",
// "error_malformed.jpg",
// "wide.jpg",
// "high.jpg",
// "small.png",
"kitten1.jpg",
"kitten2.jpg",
"kitten3.gif",
"kitten4.jpg",
"kitten5.jpg",
"kitten6.png",
};
int index = Math.abs(m.hashCode() % files.length);
String file = files[index];
getLogger(MessagingManagerImpl.class.getName())
.warning("Loading file: " + file);
InputStream is = getClass().getClassLoader().getResourceAsStream(file);
return new Attachment(is);
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB