From b2a122ec71c8c2af58ea6d99806d07d76efcb0f4 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Wed, 26 Sep 2018 20:27:33 +0200 Subject: show conversation media in contact/conference details --- .../messenger/ui/ConferenceDetailsActivity.java | 22 +- .../messenger/ui/ContactDetailsActivity.java | 23 ++- .../pixart/messenger/ui/ConversationFragment.java | 2 +- .../de/pixart/messenger/ui/RecordingActivity.java | 2 +- .../de/pixart/messenger/ui/UpdaterActivity.java | 4 +- .../de/pixart/messenger/ui/WelcomeActivity.java | 14 +- .../pixart/messenger/ui/adapter/MediaAdapter.java | 226 +++++++++++++++++++++ .../messenger/ui/adapter/MediaPreviewAdapter.java | 50 +---- .../messenger/ui/adapter/MessageAdapter.java | 26 +-- .../messenger/ui/interfaces/OnMediaLoaded.java | 10 + .../de/pixart/messenger/ui/util/Attachment.java | 14 ++ .../de/pixart/messenger/ui/util/GridManager.java | 71 +++++++ .../java/de/pixart/messenger/ui/util/ViewUtil.java | 50 +++++ .../messenger/ui/widget/SquareFrameLayout.java | 25 +++ 14 files changed, 457 insertions(+), 82 deletions(-) create mode 100644 src/main/java/de/pixart/messenger/ui/adapter/MediaAdapter.java create mode 100644 src/main/java/de/pixart/messenger/ui/interfaces/OnMediaLoaded.java create mode 100644 src/main/java/de/pixart/messenger/ui/util/GridManager.java create mode 100644 src/main/java/de/pixart/messenger/ui/util/ViewUtil.java create mode 100644 src/main/java/de/pixart/messenger/ui/widget/SquareFrameLayout.java (limited to 'src/main/java/de/pixart/messenger/ui') diff --git a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java index 38479b459..fd7c66c18 100644 --- a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java @@ -32,6 +32,7 @@ import org.openintents.openpgp.util.OpenPgpUtils; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicInteger; @@ -49,6 +50,10 @@ import de.pixart.messenger.entities.MucOptions.User; import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.services.XmppConnectionService.OnConversationUpdate; import de.pixart.messenger.services.XmppConnectionService.OnMucRosterUpdate; +import de.pixart.messenger.ui.adapter.MediaAdapter; +import de.pixart.messenger.ui.interfaces.OnMediaLoaded; +import de.pixart.messenger.ui.util.Attachment; +import de.pixart.messenger.ui.util.GridManager; import de.pixart.messenger.ui.util.MucDetailsContextMenuHelper; import de.pixart.messenger.ui.util.MyLinkify; import de.pixart.messenger.ui.util.SoftKeyboardUtils; @@ -64,7 +69,7 @@ import rocks.xmpp.addr.Jid; import static de.pixart.messenger.entities.Bookmark.printableValue; import static de.pixart.messenger.utils.StringUtils.changed; -public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, XmppConnectionService.OnRoleChanged, XmppConnectionService.OnConfigurationPushed, TextWatcher { +public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, XmppConnectionService.OnRoleChanged, XmppConnectionService.OnConfigurationPushed, TextWatcher, OnMediaLoaded { public static final String ACTION_VIEW_MUC = "view_muc"; private static final float INACTIVE_ALPHA = 0.4684f; //compromise between dark and light theme private Conversation mConversation; @@ -96,6 +101,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } }; private ActivityMucDetailsBinding binding; + private MediaAdapter mMediaAdapter; private String uuid = null; private User mSelectedUser = null; @@ -319,6 +325,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers this.binding.mucEditTitle.addTextChangedListener(this); this.binding.mucEditSubject.addTextChangedListener(this); this.binding.mucEditSubject.addTextChangedListener(new StylingHelper.MessageEditorStyler(this.binding.mucEditSubject)); + mMediaAdapter = new MediaAdapter(this, R.dimen.media_size); + this.binding.media.setAdapter(mMediaAdapter); + GridManager.setupLayoutManager(this, this.binding.media, R.dimen.media_size); } @Override @@ -475,6 +484,15 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers return true; } + @Override + public void onMediaLoaded(List attachments) { + runOnUiThread(() -> { + int limit = GridManager.getCurrentColumnCount(binding.media); + mMediaAdapter.setAttachments(attachments.subList(0, Math.min(limit, attachments.size()))); + binding.mediaWrapper.setVisibility(attachments.size() > 0 ? View.VISIBLE : View.GONE); + }); + } + protected void saveAsBookmark() { xmppConnectionService.saveConversationAsBookmark(mConversation, mConversation.getMucOptions().getName()); updateView(); @@ -503,6 +521,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers if (uuid != null) { this.mConversation = xmppConnectionService.findConversationByUuid(uuid); if (this.mConversation != null) { + final int limit = GridManager.getCurrentColumnCount(this.binding.media); + xmppConnectionService.getAttachments(this.mConversation, limit, this); updateView(); } } diff --git a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java index 5dce3fca2..d488419d2 100644 --- a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java @@ -30,6 +30,7 @@ import android.widget.Toast; import org.openintents.openpgp.util.OpenPgpUtils; +import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -45,6 +46,10 @@ import de.pixart.messenger.entities.Conversation; import de.pixart.messenger.entities.ListItem; import de.pixart.messenger.services.XmppConnectionService.OnAccountUpdate; import de.pixart.messenger.services.XmppConnectionService.OnRosterUpdate; +import de.pixart.messenger.ui.adapter.MediaAdapter; +import de.pixart.messenger.ui.interfaces.OnMediaLoaded; +import de.pixart.messenger.ui.util.Attachment; +import de.pixart.messenger.ui.util.GridManager; import de.pixart.messenger.utils.CryptoHelper; import de.pixart.messenger.utils.IrregularUnicodeDetector; import de.pixart.messenger.utils.MenuDoubleTabUtil; @@ -57,12 +62,13 @@ import de.pixart.messenger.xmpp.OnUpdateBlocklist; import de.pixart.messenger.xmpp.XmppConnection; import rocks.xmpp.addr.Jid; -public class ContactDetailsActivity extends OmemoActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist, OnKeyStatusUpdated { +public class ContactDetailsActivity extends OmemoActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist, OnKeyStatusUpdated, OnMediaLoaded { public static final String ACTION_VIEW_CONTACT = "view_contact"; private Contact contact; private Conversation mConversation; ActivityContactDetailsBinding binding; + private MediaAdapter mMediaAdapter; private DialogInterface.OnClickListener removeFromRoster = new DialogInterface.OnClickListener() { @Override @@ -260,6 +266,9 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp this.mNotifyStatusButton = findViewById(R.id.notification_status_button); this.mNotifyStatusButton.setOnClickListener(this.mNotifyStatusClickListener); this.mNotifyStatusText = findViewById(R.id.notification_status_text); + mMediaAdapter = new MediaAdapter(this, R.dimen.media_size); + this.binding.media.setAdapter(mMediaAdapter); + GridManager.setupLayoutManager(this, this.binding.media, R.dimen.media_size); } @Override @@ -279,6 +288,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp this.showDynamicTags = preferences.getBoolean(SettingsActivity.SHOW_DYNAMIC_TAGS, false); this.showLastSeen = preferences.getBoolean("last_activity", false); } + mMediaAdapter.setAttachments(Collections.emptyList()); } @Override @@ -657,6 +667,8 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp processFingerprintVerification(mPendingFingerprintVerificationUri); mPendingFingerprintVerificationUri = null; } + final int limit = GridManager.getCurrentColumnCount(this.binding.media); + xmppConnectionService.getAttachments(account, contact.getJid().asBareJid(), limit, this); populateView(); } } @@ -676,4 +688,13 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp Toast.makeText(this, R.string.invalid_barcode, Toast.LENGTH_SHORT).show(); } } + + @Override + public void onMediaLoaded(List attachments) { + runOnUiThread(() -> { + int limit = GridManager.getCurrentColumnCount(binding.media); + mMediaAdapter.setAttachments(attachments.subList(0, Math.min(limit, attachments.size()))); + binding.mediaWrapper.setVisibility(attachments.size() > 0 ? View.VISIBLE : View.GONE); + }); + } } diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 9961e014b..c2e2902ac 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -1375,7 +1375,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke if (m.isFileOrImage() && !deleted) { String path = m.getRelativeFilePath(); Log.d(Config.LOGTAG, "Path = " + path); - if (path == null || !path.startsWith("/") || path.contains(FileBackend.getConversationsDirectory("null", false))) { + if (path == null || !path.startsWith("/") || path.contains(FileBackend.getConversationsDirectory("null"))) { deleteFile.setVisible(true); deleteFile.setTitle(activity.getString(R.string.delete_x_file, UIHelper.getFileDescriptionString(activity, m))); } diff --git a/src/main/java/de/pixart/messenger/ui/RecordingActivity.java b/src/main/java/de/pixart/messenger/ui/RecordingActivity.java index 455bbf3c3..31dc1681a 100644 --- a/src/main/java/de/pixart/messenger/ui/RecordingActivity.java +++ b/src/main/java/de/pixart/messenger/ui/RecordingActivity.java @@ -127,7 +127,7 @@ public class RecordingActivity extends Activity implements View.OnClickListener private static File generateOutputFilename(Context context) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US); - return new File(FileBackend.getConversationsDirectory("Audios", true) + "/" + return new File(FileBackend.getConversationsDirectory("Audios") + dateFormat.format(new Date()) + ".m4a"); } diff --git a/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java b/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java index 959060101..9e35d7ebf 100644 --- a/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java +++ b/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java @@ -114,7 +114,7 @@ public class UpdaterActivity extends XmppActivity { store = null; } //delete old downloaded localVersion files - File dir = new File(FileBackend.getConversationsDirectory("Update", false)); + File dir = new File(FileBackend.getAppUpdateDirectory()); if (dir.isDirectory()) { String[] children = dir.list(); for (String aChildren : children) { @@ -291,7 +291,7 @@ public class UpdaterActivity extends XmppActivity { private class DownloadTask extends AsyncTask { - File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + FileBackend.getDirectoryName("Update", false)); + File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + FileBackend.getAppUpdateDirectory()); File file = new File(dir, FileName); private Context context; private PowerManager.WakeLock mWakeLock; diff --git a/src/main/java/de/pixart/messenger/ui/WelcomeActivity.java b/src/main/java/de/pixart/messenger/ui/WelcomeActivity.java index 9d5b76c1c..e2bf9d8e9 100644 --- a/src/main/java/de/pixart/messenger/ui/WelcomeActivity.java +++ b/src/main/java/de/pixart/messenger/ui/WelcomeActivity.java @@ -193,7 +193,7 @@ public class WelcomeActivity extends XmppActivity { private boolean BackupAvailable() { // Set the folder on the SDcard - File filePath = new File(FileBackend.getConversationsDirectory("Database", false) + "database.db.crypt"); + File filePath = new File(FileBackend.getBackupDirectory() + "database.db.crypt"); Log.d(Config.LOGTAG, "DB Path: " + filePath.toString()); if (filePath.exists()) { Log.d(Config.LOGTAG, "DB Path existing"); @@ -206,11 +206,11 @@ public class WelcomeActivity extends XmppActivity { private void checkDatabase(String DecryptionKey) throws IOException { // Set the folder on the SDcard - File directory = new File(FileBackend.getConversationsDirectory("Database", false)); + File directory = new File(FileBackend.getBackupDirectory()); // Set the input file stream up: - FileInputStream InputFile = new FileInputStream(directory.getPath() + "/database.db.crypt"); + FileInputStream InputFile = new FileInputStream(directory.getPath() + "database.db.crypt"); // Temp output for DB checks - File TempFile = new File(directory.getPath() + "/database.bak"); + File TempFile = new File(directory.getPath() + "database.bak"); FileOutputStream OutputTemp = new FileOutputStream(TempFile); try { @@ -286,11 +286,11 @@ public class WelcomeActivity extends XmppActivity { // Set location for the db: final OutputStream OutputFile = new FileOutputStream(this.getDatabasePath(DatabaseBackend.DATABASE_NAME)); // Set the folder on the SDcard - File directory = new File(FileBackend.getConversationsDirectory("Database", false)); + File directory = new File(FileBackend.getBackupDirectory()); // Set the input file stream up: - final InputStream InputFile = new FileInputStream(directory.getPath() + "/database.bak"); + final InputStream InputFile = new FileInputStream(directory.getPath() + "database.bak"); //set temp file - File TempFile = new File(directory.getPath() + "/database.bak"); + File TempFile = new File(directory.getPath() + "database.bak"); // Transfer bytes from the input file to the output file byte[] buffer = new byte[1024]; diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MediaAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MediaAdapter.java new file mode 100644 index 000000000..0472c6d11 --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/adapter/MediaAdapter.java @@ -0,0 +1,226 @@ +package de.pixart.messenger.ui.adapter; + +import android.content.Context; +import android.content.res.Resources; +import android.databinding.DataBindingUtil; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.support.annotation.AttrRes; +import android.support.annotation.DimenRes; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.widget.ImageView; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.RejectedExecutionException; + +import de.pixart.messenger.R; +import de.pixart.messenger.databinding.MediaBinding; +import de.pixart.messenger.ui.XmppActivity; +import de.pixart.messenger.ui.util.Attachment; +import de.pixart.messenger.ui.util.StyledAttributes; +import de.pixart.messenger.ui.util.ViewUtil; + +public class MediaAdapter extends RecyclerView.Adapter { + + private static final List DOCUMENT_MIMES = Arrays.asList( + "application/pdf", + "application/vnd.oasis.opendocument.text", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "text/x-tex", + "text/plain" + ); + + private final ArrayList attachments = new ArrayList<>(); + + private final XmppActivity activity; + + private int mediaSize = 0; + + public MediaAdapter(XmppActivity activity, @DimenRes int mediaSize) { + this.activity = activity; + this.mediaSize = Math.round(activity.getResources().getDimension(mediaSize)); + } + + public static void setMediaSize(RecyclerView recyclerView, int mediaSize) { + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter instanceof MediaAdapter) { + ((MediaAdapter) adapter).setMediaSize(mediaSize); + } + } + + private static @AttrRes + int getImageAttr(Attachment attachment) { + final @AttrRes int attr; + if (attachment.getType() == Attachment.Type.LOCATION) { + attr = R.attr.media_preview_location; + } else if (attachment.getType() == Attachment.Type.RECORDING) { + attr = R.attr.media_preview_recording; + } else { + final String mime = attachment.getMime(); + if (mime == null) { + attr = R.attr.media_preview_unknown; + } else if (mime.startsWith("audio/")) { + attr = R.attr.media_preview_audio; + } else if (mime.equals("text/calendar") || (mime.equals("text/x-vcalendar"))) { + attr = R.attr.media_preview_calendar; + } else if (mime.equals("text/x-vcard")) { + attr = R.attr.media_preview_contact; + } else if (mime.equals("application/vnd.android.package-archive")) { + attr = R.attr.media_preview_app; + } else if (mime.equals("application/zip") || mime.equals("application/rar")) { + attr = R.attr.media_preview_archive; + } else if (DOCUMENT_MIMES.contains(mime)) { + attr = R.attr.media_preview_document; + } else { + attr = R.attr.media_preview_unknown; + } + } + return attr; + } + + public static void renderPreview(Context context, Attachment attachment, ImageView imageView) { + imageView.setBackgroundColor(StyledAttributes.getColor(context, R.attr.color_background_tertiary)); + imageView.setImageAlpha(Math.round(StyledAttributes.getFloat(context, R.attr.icon_alpha) * 255)); + imageView.setImageDrawable(StyledAttributes.getDrawable(context, getImageAttr(attachment))); + } + + private static boolean cancelPotentialWork(Attachment attachment, ImageView imageView) { + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (bitmapWorkerTask != null) { + final Attachment oldAttachment = bitmapWorkerTask.attachment; + if (oldAttachment == null || !oldAttachment.equals(attachment)) { + bitmapWorkerTask.cancel(true); + } else { + return false; + } + } + 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; + } + + @NonNull + @Override + public MediaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); + MediaBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.media, parent, false); + return new MediaViewHolder(binding); + } + + @Override + public void onBindViewHolder(@NonNull MediaViewHolder holder, int position) { + final Attachment attachment = attachments.get(position); + if (attachment.renderThumbnail()) { + holder.binding.media.setImageAlpha(255); + loadPreview(attachment, holder.binding.media); + } else { + cancelPotentialWork(attachment, holder.binding.media); + renderPreview(activity, attachment, holder.binding.media); + } + holder.binding.media.setOnClickListener(v -> ViewUtil.view(activity, attachment)); + } + + public void setAttachments(List attachments) { + this.attachments.clear(); + this.attachments.addAll(attachments); + notifyDataSetChanged(); + } + + private void setMediaSize(int mediaSize) { + this.mediaSize = mediaSize; + } + + private void loadPreview(Attachment attachment, ImageView imageView) { + if (cancelPotentialWork(attachment, imageView)) { + final Bitmap bm = activity.xmppConnectionService.getFileBackend().getPreviewForUri(attachment, mediaSize, true); + if (bm != null) { + cancelPotentialWork(attachment, imageView); + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else { + imageView.setBackgroundColor(0xff333333); + imageView.setImageDrawable(null); + final BitmapWorkerTask task = new BitmapWorkerTask(imageView); + final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); + imageView.setImageDrawable(asyncDrawable); + try { + task.execute(attachment); + } catch (final RejectedExecutionException ignored) { + } + } + } + } + + @Override + public int getItemCount() { + return attachments.size(); + } + + static class AsyncDrawable extends BitmapDrawable { + private final WeakReference bitmapWorkerTaskReference; + + AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); + } + + BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } + + class MediaViewHolder extends RecyclerView.ViewHolder { + + private final MediaBinding binding; + + MediaViewHolder(MediaBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } + } + + class BitmapWorkerTask extends AsyncTask { + private final WeakReference imageViewReference; + private Attachment attachment = null; + + BitmapWorkerTask(ImageView imageView) { + imageViewReference = new WeakReference<>(imageView); + } + + @Override + protected Bitmap doInBackground(Attachment... params) { + this.attachment = params[0]; + return activity.xmppConnectionService.getFileBackend().getPreviewForUri(this.attachment, mediaSize, false); + } + + @Override + protected void onPostExecute(Bitmap bitmap) { + if (bitmap != null && !isCancelled()) { + final ImageView imageView = imageViewReference.get(); + if (imageView != null) { + imageView.setImageBitmap(bitmap); + imageView.setBackgroundColor(0x00000000); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java index 9192c6555..ae4c42816 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java @@ -8,7 +8,6 @@ import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; -import android.support.annotation.AttrRes; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -17,7 +16,6 @@ import android.widget.ImageView; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.concurrent.RejectedExecutionException; @@ -26,19 +24,9 @@ import de.pixart.messenger.databinding.MediaPreviewBinding; import de.pixart.messenger.ui.ConversationFragment; import de.pixart.messenger.ui.XmppActivity; import de.pixart.messenger.ui.util.Attachment; -import de.pixart.messenger.ui.util.StyledAttributes; public class MediaPreviewAdapter extends RecyclerView.Adapter { - private static final List DOCUMENT_MIMES = Arrays.asList( - "application/pdf", - "application/vnd.oasis.opendocument.text", - "application/msword", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "text/x-tex", - "text/plain" - ); - private final ArrayList mediaPreviews = new ArrayList<>(); private final ConversationFragment conversationFragment; @@ -89,34 +77,7 @@ public class MediaPreviewAdapter extends RecyclerView.Adapter { int pos = mediaPreviews.indexOf(attachment); @@ -166,6 +127,10 @@ public class MediaPreviewAdapter extends RecyclerView.Adapter bitmapWorkerTaskReference; @@ -179,11 +144,6 @@ public class MediaPreviewAdapter extends RecyclerView.Adapter implements CopyTextVie //ignored } } - Intent openIntent = new Intent(Intent.ACTION_VIEW); if (mime == null) { mime = "*/*"; } - Uri uri; - try { - uri = FileBackend.getUriForFile(activity, file); - } catch (SecurityException e) { - Log.d(Config.LOGTAG, "No permission to access " + file.getAbsolutePath(), e); - Toast.makeText(activity, activity.getString(R.string.no_permission_to_access_x, file.getAbsolutePath()), Toast.LENGTH_SHORT).show(); - return; - } - openIntent.setDataAndType(uri, mime); - openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - PackageManager manager = activity.getPackageManager(); - List info = manager.queryIntentActivities(openIntent, 0); - if (info.size() == 0) { - openIntent.setDataAndType(uri,"*/*"); - } - try { - getContext().startActivity(openIntent); - activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out); - } catch (ActivityNotFoundException e) { - Toast.makeText(activity, R.string.no_application_found_to_open_file, Toast.LENGTH_SHORT).show(); - } + ViewUtil.view(activity, file, mime); } public void showLocation(Message message) { diff --git a/src/main/java/de/pixart/messenger/ui/interfaces/OnMediaLoaded.java b/src/main/java/de/pixart/messenger/ui/interfaces/OnMediaLoaded.java new file mode 100644 index 000000000..0441be96d --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/interfaces/OnMediaLoaded.java @@ -0,0 +1,10 @@ +package de.pixart.messenger.ui.interfaces; + +import java.util.List; + +import de.pixart.messenger.ui.util.Attachment; + +public interface OnMediaLoaded { + + void onMediaLoaded(List attachments); +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/util/Attachment.java b/src/main/java/de/pixart/messenger/ui/util/Attachment.java index f11efd0d1..96159c1bd 100644 --- a/src/main/java/de/pixart/messenger/ui/util/Attachment.java +++ b/src/main/java/de/pixart/messenger/ui/util/Attachment.java @@ -37,6 +37,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.Log; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -61,12 +62,21 @@ public class Attachment implements Parcelable { private final Type type; private final UUID uuid; private final String mime; + Attachment(Parcel in) { uri = in.readParcelable(Uri.class.getClassLoader()); mime = in.readString(); uuid = UUID.fromString(in.readString()); type = Type.valueOf(in.readString()); } + + private Attachment(UUID uuid, Uri uri, Type type, String mime) { + this.uri = uri; + this.type = type; + this.mime = mime; + this.uuid = uuid; + } + private Attachment(Uri uri, Type type, String mime) { this.uri = uri; this.type = type; @@ -88,6 +98,10 @@ public class Attachment implements Parcelable { return attachments; } + public static Attachment of(UUID uuid, final File file, String mime) { + return new Attachment(uuid, Uri.fromFile(file), mime != null && (mime.startsWith("image/") || mime.startsWith("video/")) ? Type.IMAGE : Type.FILE, mime); + } + public static List extractAttachments(final Context context, final Intent intent, Type type) { List uris = new ArrayList<>(); if (intent == null) { diff --git a/src/main/java/de/pixart/messenger/ui/util/GridManager.java b/src/main/java/de/pixart/messenger/ui/util/GridManager.java new file mode 100644 index 000000000..717fef526 --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/util/GridManager.java @@ -0,0 +1,71 @@ +package de.pixart.messenger.ui.util; + +import android.content.Context; +import android.support.annotation.DimenRes; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.ViewTreeObserver; + +import de.pixart.messenger.Config; +import de.pixart.messenger.ui.adapter.MediaAdapter; + +public class GridManager { + + public static void setupLayoutManager(final Context context, RecyclerView recyclerView, @DimenRes int desiredSize) { + int maxWidth = context.getResources().getDisplayMetrics().widthPixels; + ColumnInfo columnInfo = calculateColumnCount(context, maxWidth, desiredSize); + Log.d(Config.LOGTAG, "preliminary count=" + columnInfo.count); + MediaAdapter.setMediaSize(recyclerView, columnInfo.width); + recyclerView.setLayoutManager(new GridLayoutManager(context, columnInfo.count)); + recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + final ColumnInfo columnInfo = calculateColumnCount(context, recyclerView.getMeasuredWidth(), desiredSize); + Log.d(Config.LOGTAG, "final count " + columnInfo.count); + if (recyclerView.getAdapter().getItemCount() != 0) { + Log.e(Config.LOGTAG, "adapter already has items; just go with it now"); + return; + } + setupLayoutManagerInternal(recyclerView, columnInfo); + MediaAdapter.setMediaSize(recyclerView, columnInfo.width); + } + }); + } + + private static void setupLayoutManagerInternal(RecyclerView recyclerView, final ColumnInfo columnInfo) { + RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + if (layoutManager instanceof GridLayoutManager) { + ((GridLayoutManager) layoutManager).setSpanCount(columnInfo.count); + } + } + + private static ColumnInfo calculateColumnCount(Context context, int availableWidth, @DimenRes int desiredSize) { + final float desiredWidth = context.getResources().getDimension(desiredSize); + final int columns = Math.round(availableWidth / desiredWidth); + final int realWidth = availableWidth / columns; + Log.d(Config.LOGTAG, "desired=" + desiredWidth + " real=" + realWidth); + return new ColumnInfo(columns, realWidth); + } + + public static int getCurrentColumnCount(RecyclerView recyclerView) { + RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + if (layoutManager instanceof GridLayoutManager) { + return ((GridLayoutManager) layoutManager).getSpanCount(); + } else { + return 0; + } + } + + public static class ColumnInfo { + private final int count; + private final int width; + + private ColumnInfo(int count, int width) { + this.count = count; + this.width = width; + } + } + +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/util/ViewUtil.java b/src/main/java/de/pixart/messenger/ui/util/ViewUtil.java new file mode 100644 index 000000000..2442df8dc --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/util/ViewUtil.java @@ -0,0 +1,50 @@ +package de.pixart.messenger.ui.util; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.util.Log; +import android.widget.Toast; + +import java.io.File; +import java.util.List; + +import de.pixart.messenger.Config; +import de.pixart.messenger.R; +import de.pixart.messenger.persistance.FileBackend; + +public class ViewUtil { + + public static void view(Context context, Attachment attachment) { + File file = new File(attachment.getUri().getPath()); + final String mime = attachment.getMime() == null ? "*/*" : attachment.getMime(); + view(context, file, mime); + } + + public static void view(Context context, File file, String mime) { + Intent openIntent = new Intent(Intent.ACTION_VIEW); + Uri uri; + try { + uri = FileBackend.getUriForFile(context, file); + } catch (SecurityException e) { + Log.d(Config.LOGTAG, "No permission to access " + file.getAbsolutePath(), e); + Toast.makeText(context, context.getString(R.string.no_permission_to_access_x, file.getAbsolutePath()), Toast.LENGTH_SHORT).show(); + return; + } + openIntent.setDataAndType(uri, mime); + openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + PackageManager manager = context.getPackageManager(); + List info = manager.queryIntentActivities(openIntent, 0); + if (info.size() == 0) { + openIntent.setDataAndType(uri, "*/*"); + } + try { + context.startActivity(openIntent); + } catch (ActivityNotFoundException e) { + Toast.makeText(context, R.string.no_application_found_to_open_file, Toast.LENGTH_SHORT).show(); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/widget/SquareFrameLayout.java b/src/main/java/de/pixart/messenger/ui/widget/SquareFrameLayout.java new file mode 100644 index 000000000..4d2fcf92d --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/widget/SquareFrameLayout.java @@ -0,0 +1,25 @@ +package de.pixart.messenger.ui.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.FrameLayout; + +public class SquareFrameLayout extends FrameLayout { + public SquareFrameLayout(Context context) { + super(context); + } + + public SquareFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public SquareFrameLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + //noinspection SuspiciousNameCombination + super.onMeasure(widthMeasureSpec, widthMeasureSpec); + } +} \ No newline at end of file -- cgit v1.2.3