Compare commits

..

4 Commits

Author SHA1 Message Date
Torsten Grote
e6e077ff40 [android] enable image shared element transition for API 21+22
There's an Android framework bug (#224270) on these APIs that causes a NPE
when the shared element is not visible anymore when returning.
Since we know restore the list position, the shared element should be
visible and thus not produce NPEs anymore.
2018-12-13 14:20:52 -02:00
Torsten Grote
4e5e354af2 [android] Fix enter transition to fullscreen ImageActivity 2018-12-13 14:20:52 -02:00
Torsten Grote
9ea3623c85 [android] Save and restore list position of conversation across restarts 2018-12-13 14:20:51 -02:00
Torsten Grote
84089f5e16 DO NOT MERGE: Return multiple fake image attachements in MessagingManager
(cherry picked from commit d9cb675)
2018-12-13 14:20:04 -02:00
25 changed files with 113 additions and 66 deletions

View File

@@ -6,8 +6,6 @@ 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;
@@ -46,7 +44,6 @@ 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;
@@ -131,9 +128,8 @@ class AttachmentController {
} }
Size size = new Size(); Size size = new Size();
InputStream is = new MarkEnforcingInputStream( InputStream is = new BufferedInputStream(a.getStream());
new BufferedInputStream(a.getStream())); is.mark(Integer.MAX_VALUE);
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")) {
@@ -146,8 +142,6 @@ 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) {
@@ -164,11 +158,12 @@ class AttachmentController {
} }
// get file extension // get file extension
String extension = getExtensionFromMimeType(size.mimeType); String extension = getExtensionFromMimeType(size.mimeType);
boolean hasError = extension == null || size.error; if (extension == null) {
if (extension == null) extension = ""; return new AttachmentItem(messageId, 0, 0, "", "", 0, 0, true);
}
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, hasError); thumbnailSize.height, size.error);
} }
@Nullable @Nullable

View File

@@ -8,6 +8,7 @@ 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;
@@ -107,7 +108,6 @@ 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,6 +194,8 @@ 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);
@@ -309,6 +311,21 @@ 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
@@ -428,8 +445,12 @@ 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();
// Scroll to the bottom if (layoutManagerState == null) {
list.scrollToPosition(adapter.getItemCount() - 1); // Scroll to the bottom
list.scrollToPosition(adapter.getItemCount() - 1);
} else {
layoutManager.onRestoreInstanceState(layoutManagerState);
}
} else { } else {
LOG.info("Concurrent update, reloading"); LOG.info("Concurrent update, reloading");
loadMessages(); loadMessages();
@@ -471,7 +492,8 @@ 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 = adapter.isScrolledToBottom(layoutManager); boolean bottom = layoutManagerState == null &&
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);
} }
@@ -502,7 +524,8 @@ 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 = adapter.isScrolledToBottom(layoutManager); boolean bottom = layoutManagerState == null &&
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);
} }
@@ -553,7 +576,8 @@ public class ConversationActivity extends BriarActivity
private void addConversationItem(ConversationItem item) { private void addConversationItem(ConversationItem item) {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
boolean bottom = adapter.isScrolledToBottom(layoutManager); boolean bottom = layoutManagerState == null &&
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);
@@ -820,15 +844,11 @@ 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());
if (SDK_INT >= 23) { // restoring list position should not trigger android bug #224270
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
supportPostponeEnterTransition(); if (state == null) supportPostponeEnterTransition();
Window window = getWindow(); Window window = getWindow();
if (SDK_INT >= 21) { if (SDK_INT >= 21) {
Transition transition = new Fade(); Transition transition = new Fade();
@@ -298,13 +298,18 @@ 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) {
return ImageFragment.newInstance(attachments.get(position)); Fragment f = ImageFragment
.newInstance(attachments.get(position), isFirst);
isFirst = false;
return f;
} }
@Override @Override

View File

@@ -35,17 +35,21 @@ 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) { static ImageFragment newInstance(AttachmentItem a, boolean isFirst) {
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;
} }
@@ -63,6 +67,7 @@ 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
@@ -77,7 +82,6 @@ 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
@@ -86,7 +90,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) if (getActivity() != null && isFirst)
getActivity().supportStartPostponedEnterTransition(); getActivity().supportStartPostponedEnterTransition();
return false; return false;
} }
@@ -105,8 +109,9 @@ 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) if (getActivity() != null && isFirst) {
getActivity().supportStartPostponedEnterTransition(); getActivity().supportStartPostponedEnterTransition();
}
return false; return false;
} }
}; };
@@ -114,10 +119,9 @@ 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,6 +15,7 @@ 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;
@@ -42,6 +43,9 @@ 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,12 +50,9 @@ 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
@@ -109,9 +106,8 @@ public class ImageViewModel extends AndroidViewModel {
} }
/** /**
* A LiveData that is true if there was an error * A LiveData that is true if the image was saved,
* and false if the image was saved. * false if there was an error and null otherwise.
* 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.
*/ */
@@ -130,7 +126,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(true); saveState.setValue(false);
} else { } else {
saveImage(attachment, () -> getOutputStream(uri), null); saveImage(attachment, () -> getOutputStream(uri), null);
} }

View File

@@ -138,6 +138,7 @@ 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);
} }
@@ -207,6 +208,7 @@ 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,7 +49,8 @@
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,16 +1,13 @@
<?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"
android:visible="false" app:showAsAction="ifRoom"/>
app:showAsAction="ifRoom"
tools:visible="true"/>
<item <item
android:id="@+id/action_group_member_list" android:id="@+id/action_group_member_list"
@@ -22,24 +19,18 @@
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"
android:visible="false" app:showAsAction="never"/>
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"
android:visible="false" app:showAsAction="never"/>
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"
android:visible="false" app:showAsAction="never"/>
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 org.briarproject.bramble.util.StringUtils.fromHexString; import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
@Immutable @Immutable
@@ -219,8 +219,18 @@ 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(), true, emptyList())); read, s.isSent(), s.isSeen(), hasText, attachments));
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
@@ -241,11 +251,30 @@ class MessagingManagerImpl extends ConversationClientImpl
@Override @Override
public Attachment getAttachment(MessageId m) { public Attachment getAttachment(MessageId m) {
// TODO add real implementation // TODO add real implementation
byte[] bytes = fromHexString("89504E470D0A1A0A0000000D49484452" + String[] files = new String[] {
"000000010000000108060000001F15C4" + // "error_animated.gif",
"890000000A49444154789C6300010000" + // "error_high.jpg",
"0500010D0A2DB40000000049454E44AE426082"); // "error_wide.jpg",
return new Attachment(new ByteArrayInputStream(bytes)); // "error_huge.gif",
// "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.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB