aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel.gultsch@rwth-aachen.de>2014-04-25 16:24:56 +0200
committerDaniel Gultsch <daniel.gultsch@rwth-aachen.de>2014-04-25 16:24:56 +0200
commitbf2d0d5596a08872230056d056241ee906962171 (patch)
tree08f722037b19e7a94985360874f7de2f646b2f13
parent18c183a7676e24fa3141a50f628688a0a690f259 (diff)
smoother scrolling (first step)
-rw-r--r--res/layout/conversation_list_row.xml21
-rw-r--r--res/layout/message_sent.xml2
-rw-r--r--res/values/strings.xml2
-rw-r--r--src/eu/siacs/conversations/entities/Conversation.java4
-rw-r--r--src/eu/siacs/conversations/persistance/FileBackend.java56
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java2
-rw-r--r--src/eu/siacs/conversations/ui/ConversationActivity.java138
-rw-r--r--src/eu/siacs/conversations/ui/ConversationFragment.java60
-rw-r--r--src/eu/siacs/conversations/utils/UIHelper.java20
9 files changed, 243 insertions, 62 deletions
diff --git a/res/layout/conversation_list_row.xml b/res/layout/conversation_list_row.xml
index 469a0cde..76016ada 100644
--- a/res/layout/conversation_list_row.xml
+++ b/res/layout/conversation_list_row.xml
@@ -22,24 +22,39 @@
android:id="@+id/conversation_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/conversation_lastmsg"
+ android:layout_alignLeft="@+id/conversation_lastwrapper"
android:layout_toLeftOf="@+id/conversation_lastupdate"
android:singleLine="true"
android:textColor="#636363"
android:textSize="20sp"
android:typeface="sans" />
+ <LinearLayout
+ android:orientation="vertical"
+ android:id="@+id/conversation_lastwrapper"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/conversation_name"
+ android:paddingTop="3dp"
+ >
<TextView
android:id="@+id/conversation_lastmsg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:layout_below="@id/conversation_name"
+
android:textColor="#636363"
android:textSize="14sp"
android:singleLine="true"
android:scrollHorizontally="false"
- android:paddingTop="3dp"/>
+ />
+
+ <ImageView
+ android:id="@+id/conversation_lastimage"
+ android:layout_width="fill_parent"
+ android:layout_height="36dp"
+ android:scaleType="centerCrop" />
+ </LinearLayout>
<TextView
android:id="@+id/conversation_lastupdate"
android:layout_width="wrap_content"
diff --git a/res/layout/message_sent.xml b/res/layout/message_sent.xml
index 1ae422bb..f0950ef9 100644
--- a/res/layout/message_sent.xml
+++ b/res/layout/message_sent.xml
@@ -25,8 +25,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
- android:maxHeight="288dp"
- android:maxWidth="288dp"
android:paddingBottom="2dp"
/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index df096179..1bc03a91 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -66,4 +66,6 @@
<string name="send_pgp_message">Send openPGP encrypted message</string>
<string name="your_nick_has_been_changed">Your nickname has been changed</string>
<string name="download_image">Download Image</string>
+ <string name="error_loading_image">Error loading image (File not found)</string>
+ <string name="image_offered_for_download"><i>Image file offered for download</i></string>
</resources>
diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java
index 6eb688ae..0f4d24e5 100644
--- a/src/eu/siacs/conversations/entities/Conversation.java
+++ b/src/eu/siacs/conversations/entities/Conversation.java
@@ -116,7 +116,9 @@ public class Conversation extends AbstractEntity {
message.setTime(getCreated());
return message;
} else {
- return this.messages.get(this.messages.size() - 1);
+ Message message = this.messages.get(this.messages.size() - 1);
+ message.setConversation(this);
+ return message;
}
}
diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java
index 3032f375..129176a4 100644
--- a/src/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/eu/siacs/conversations/persistance/FileBackend.java
@@ -6,6 +6,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.ref.WeakReference;
import android.content.Context;
import android.graphics.Bitmap;
@@ -13,6 +14,9 @@ import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.util.LruCache;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
@@ -39,6 +43,10 @@ public class FileBackend {
};
}
+
+ public LruCache<String, Bitmap> getThumbnailCache() {
+ return thumbnailCache;
+ }
public JingleFile getJingleFile(Message message) {
Conversation conversation = message.getConversation();
@@ -49,7 +57,7 @@ public class FileBackend {
return new JingleFile(path + "/" + filename);
}
- private Bitmap resize(Bitmap originalBitmap, int size) {
+ public Bitmap resize(Bitmap originalBitmap, int size) {
int w = originalBitmap.getWidth();
int h = originalBitmap.getHeight();
if (Math.max(w, h) > size) {
@@ -87,7 +95,12 @@ public class FileBackend {
if (!success) {
// Log.d("xmppService", "couldnt compress");
}
+ os.flush();
os.close();
+ long size = file.getSize();
+ int width = scalledBitmap.getWidth();
+ int height = scalledBitmap.getHeight();
+ message.setBody(""+size+","+width+","+height);
return file;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
@@ -105,7 +118,7 @@ public class FileBackend {
.getAbsolutePath());
}
- public Bitmap getThumbnailFromMessage(Message message, int size)
+ public Bitmap getThumbnail(Message message, int size)
throws FileNotFoundException {
Bitmap thumbnail = thumbnailCache.get(message.getUuid());
if (thumbnail == null) {
@@ -119,6 +132,45 @@ public class FileBackend {
}
return thumbnail;
}
+
+ public void getThumbnailAsync(final Message message, final int size, ImageView imageView, TextView textView) {
+
+ Bitmap thumbnail = thumbnailCache.get(message.getUuid());
+ if (thumbnail == null) {
+ final WeakReference<ImageView> image = new WeakReference<ImageView>(imageView);
+ final WeakReference<TextView> text = new WeakReference<TextView>(textView);
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ if (image.get()!=null) {
+ image.get().setVisibility(View.GONE);
+ }
+ if (text.get()!=null) {
+ text.get().setVisibility(View.VISIBLE);
+ text.get().setText("loading image");
+ }
+ Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
+ .getAbsolutePath());
+ if (fullsize!=null) {
+ Bitmap thumbnail = resize(fullsize, size);
+ thumbnailCache.put(message.getUuid(), thumbnail);
+ if (image.get()!=null) {
+ image.get().setVisibility(View.VISIBLE);
+ image.get().setImageBitmap(thumbnail);
+ }
+ if (text.get()!=null) {
+ text.get().setVisibility(View.GONE);
+ }
+ }
+ }
+ }).start();
+ } else {
+ textView.setVisibility(View.GONE);
+ imageView.setVisibility(View.VISIBLE);
+ imageView.setImageBitmap(thumbnail);
+ }
+ }
public void removeFiles(Conversation conversation) {
String prefix = context.getFilesDir().getAbsolutePath();
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index b6930219..981e6baa 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -423,8 +423,8 @@ public class XmppConnectionService extends Service {
convChangedListener.onConversationListChanged();
}
getFileBackend().copyImageToPrivateStorage(message, uri);
- databaseBackend.createMessage(message);
message.setStatus(Message.STATUS_OFFERED);
+ databaseBackend.createMessage(message);
if (convChangedListener!=null) {
convChangedListener.onConversationListChanged();
}
diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java
index 41d9ad0f..32e3588b 100644
--- a/src/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/eu/siacs/conversations/ui/ConversationActivity.java
@@ -1,5 +1,7 @@
package eu.siacs.conversations.ui;
+import java.io.FileNotFoundException;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
@@ -11,20 +13,26 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.utils.UIHelper;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.support.v4.widget.SlidingPaneLayout;
import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
+import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -57,7 +65,7 @@ public class ConversationActivity extends XmppActivity {
private List<Conversation> conversationList = new ArrayList<Conversation>();
private Conversation selectedConversation = null;
private ListView listView;
-
+
private boolean paneShouldBeOpen = true;
private boolean useSubject = true;
private ArrayAdapter<Conversation> listAdapter;
@@ -91,6 +99,7 @@ public class ConversationActivity extends XmppActivity {
};
protected ConversationActivity activity = this;
+ private DisplayMetrics metrics;
public List<Conversation> getConversationList() {
return this.conversationList;
@@ -115,6 +124,8 @@ public class ConversationActivity extends XmppActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
+ metrics = getResources().getDisplayMetrics();
+
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_conversations_overview);
@@ -150,7 +161,35 @@ public class ConversationActivity extends XmppActivity {
convName.setText(conv.getName(useSubject));
TextView convLastMsg = (TextView) view
.findViewById(R.id.conversation_lastmsg);
- convLastMsg.setText(conv.getLatestMessage().getBody());
+ ImageView imagePreview = (ImageView) view.findViewById(R.id.conversation_lastimage);
+
+ Message latestMessage = conv.getLatestMessage();
+
+ if (latestMessage.getType() == Message.TYPE_TEXT) {
+ convLastMsg.setText(conv.getLatestMessage().getBody());
+ convLastMsg.setVisibility(View.VISIBLE);
+ imagePreview.setVisibility(View.GONE);
+ } else if (latestMessage.getType() == Message.TYPE_IMAGE) {
+ if ((latestMessage.getStatus() >= Message.STATUS_RECIEVED)&&(latestMessage.getStatus() != Message.STATUS_PREPARING)) {
+ convLastMsg.setVisibility(View.GONE);
+ imagePreview.setVisibility(View.VISIBLE);
+ loadBitmap(latestMessage, imagePreview);
+ } else {
+ convLastMsg.setVisibility(View.VISIBLE);
+ imagePreview.setVisibility(View.GONE);
+ if (latestMessage.getStatus() == Message.STATUS_PREPARING) {
+ convLastMsg.setText(getText(R.string.preparing_image));
+ } else if (latestMessage.getStatus() == Message.STATUS_RECEIVED_OFFER) {
+ convLastMsg.setText(getText(R.string.image_offered_for_download));
+ } else if (latestMessage.getStatus() == Message.STATUS_RECIEVING) {
+ convLastMsg.setText(getText(R.string.receiving_image));
+ } else {
+ convLastMsg.setText("");
+ }
+ }
+ }
+
+
if (!conv.isRead()) {
convName.setTypeface(null, Typeface.BOLD);
@@ -164,10 +203,11 @@ public class ConversationActivity extends XmppActivity {
.setText(UIHelper.readableTimeDifference(conv
.getLatestMessage().getTimeSent()));
- ImageView imageView = (ImageView) view
+ ImageView profilePicture = (ImageView) view
.findViewById(R.id.conversation_image);
- imageView.setImageBitmap(UIHelper.getContactPicture(
+ profilePicture.setImageBitmap(UIHelper.getContactPicture(
conv, 56, activity.getApplicationContext(), false));
+
return view;
}
@@ -602,4 +642,92 @@ public class ConversationActivity extends XmppActivity {
});
builder.create().show();
}
+
+
+ class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> {
+ private final WeakReference<ImageView> imageViewReference;
+ private Message message = null;
+
+ public BitmapWorkerTask(ImageView imageView) {
+ // Use a WeakReference to ensure the ImageView can be garbage collected
+ imageViewReference = new WeakReference<ImageView>(imageView);
+ }
+
+ // Decode image in background.
+ @Override
+ protected Bitmap doInBackground(Message... params) {
+ message = params[0];
+ try {
+ return xmppConnectionService.getFileBackend().getThumbnail(message, (int) (metrics.density * 288));
+ } catch (FileNotFoundException e) {
+ Log.d("xmppService","file not found!");
+ return null;
+ }
+ }
+
+ // Once complete, see if ImageView is still around and set bitmap.
+ @Override
+ protected void onPostExecute(Bitmap bitmap) {
+ if (imageViewReference != null && bitmap != null) {
+ final ImageView imageView = imageViewReference.get();
+ if (imageView != null) {
+ imageView.setImageBitmap(bitmap);
+ }
+ }
+ }
+ }
+
+ public void loadBitmap(Message message, ImageView imageView) {
+ if (cancelPotentialWork(message, imageView)) {
+ final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
+ final AsyncDrawable asyncDrawable =
+ new AsyncDrawable(getResources(), null, task);
+ imageView.setImageDrawable(asyncDrawable);
+ task.execute(message);
+ }
+ }
+
+ public static boolean cancelPotentialWork(Message message, ImageView imageView) {
+ final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+ if (bitmapWorkerTask != null) {
+ final Message oldMessage = bitmapWorkerTask.message;
+ // If bitmapData is not yet set or it differs from the new data
+ if (oldMessage == null || message != oldMessage) {
+ // Cancel previous task
+ bitmapWorkerTask.cancel(true);
+ } else {
+ // The same work is already in progress
+ return false;
+ }
+ }
+ // No task associated with the ImageView, or an existing task was cancelled
+ return true;
+ }
+
+ private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
+ if (imageView != null) {
+ final Drawable drawable = imageView.getDrawable();
+ if (drawable instanceof AsyncDrawable) {
+ final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+ return asyncDrawable.getBitmapWorkerTask();
+ }
+ }
+ return null;
+ }
+
+ static class AsyncDrawable extends BitmapDrawable {
+ private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
+
+ public AsyncDrawable(Resources res, Bitmap bitmap,
+ BitmapWorkerTask bitmapWorkerTask) {
+ super(res, bitmap);
+ bitmapWorkerTaskReference =
+ new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
+ }
+
+ public BitmapWorkerTask getBitmapWorkerTask() {
+ return bitmapWorkerTaskReference.get();
+ }
+ }
}
diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java
index a4259f27..d42b33c4 100644
--- a/src/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/eu/siacs/conversations/ui/ConversationFragment.java
@@ -297,27 +297,38 @@ public class ConversationFragment extends Fragment {
}
});
} else {
- try {
- Bitmap thumbnail = activity.xmppConnectionService.getFileBackend().getThumbnailFromMessage(item,(int) (metrics.density * 288));
- viewHolder.image.setImageBitmap(thumbnail);
- viewHolder.messageBody.setVisibility(View.GONE);
- viewHolder.image.setVisibility(View.VISIBLE);
- viewHolder.image.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- Uri uri = Uri.parse("content://eu.siacs.conversations.images/"+item.getConversationUuid()+"/"+item.getUuid());
- Log.d("xmppService","staring intent with uri:"+uri.toString());
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/*");
- startActivity(intent);
- }
- });
- } catch (FileNotFoundException e) {
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.messageBody.setText("error loading image file");
- viewHolder.messageBody.setVisibility(View.VISIBLE);
- }
+ viewHolder.messageBody.setVisibility(View.GONE);
+ viewHolder.image.setVisibility(View.VISIBLE);
+ String[] params = item.getBody().split(",");
+ if (params.length==3) {
+ int target = (int) (metrics.density * 288);
+ int w = Integer.parseInt(params[1]);
+ int h = Integer.parseInt(params[2]);
+ int scalledW;
+ int scalledH;
+ if (w <= h) {
+ scalledW = (int) (w / ((double) h / target));
+ scalledH = target;
+ } else {
+ scalledW = target;
+ scalledH = (int) (h / ((double) w / target));
+ }
+ viewHolder.image.setLayoutParams(new LinearLayout.LayoutParams(scalledW, scalledH));
+ } else {
+ Log.d("xmppService","message body has less than 3 params");
+ }
+ activity.loadBitmap(item, viewHolder.image);
+ viewHolder.image.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ Uri uri = Uri.parse("content://eu.siacs.conversations.images/"+item.getConversationUuid()+"/"+item.getUuid());
+ Log.d("xmppService","staring intent with uri:"+uri.toString());
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(uri, "image/*");
+ startActivity(intent);
+ }
+ });
}
} else {
viewHolder.image.setVisibility(View.GONE);
@@ -686,13 +697,6 @@ public class ConversationFragment extends Fragment {
return bm;
}
}
-
- public Bitmap getError() {
- if (error == null) {
- error = UIHelper.getErrorPicture(200);
- }
- return error;
- }
}
class DecryptMessage extends AsyncTask<Message, Void, Boolean> {
diff --git a/src/eu/siacs/conversations/utils/UIHelper.java b/src/eu/siacs/conversations/utils/UIHelper.java
index f058b9ee..1c52ff0b 100644
--- a/src/eu/siacs/conversations/utils/UIHelper.java
+++ b/src/eu/siacs/conversations/utils/UIHelper.java
@@ -302,26 +302,6 @@ public class UIHelper {
bgColor, fgColor);
}
- public static Bitmap getErrorPicture(int size) {
- Bitmap bitmap = Bitmap
- .createBitmap(size, size, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
-
- bitmap.eraseColor(0xFFe92727);
-
- Paint paint = new Paint();
- paint.setColor(0xffe5e5e5);
- paint.setTextSize((float) (size * 0.9));
- paint.setAntiAlias(true);
- Rect rect = new Rect();
- paint.getTextBounds("!", 0, 1, rect);
- float width = paint.measureText("!");
- canvas.drawText("!", (size / 2) - (width / 2),
- (size / 2) + (rect.height() / 2), paint);
-
- return bitmap;
- }
-
public static void showErrorNotification(Context context, List<Account> accounts) {
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);