diff options
13 files changed, 473 insertions, 4 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ContactDetailsActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ContactDetailsActivity.java index c84f9b89..bf0c126e 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ContactDetailsActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/ContactDetailsActivity.java @@ -39,6 +39,7 @@ import de.thedevstack.conversationsplus.entities.Contact; import de.thedevstack.conversationsplus.entities.ListItem; import de.thedevstack.conversationsplus.services.XmppConnectionService.OnAccountUpdate; import de.thedevstack.conversationsplus.services.XmppConnectionService.OnRosterUpdate; +import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener; import de.thedevstack.conversationsplus.utils.CryptoHelper; import de.thedevstack.conversationsplus.utils.UIHelper; import de.thedevstack.conversationsplus.xmpp.OnUpdateBlocklist; @@ -350,6 +351,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd } else { contactJidTv.setText(contact.getJid().toString()); } + contactJidTv.setOnClickListener(new ShowResourcesListDialogListener(ContactDetailsActivity.this, contact)); accountJidTv.setText(getString(R.string.using_account, contact.getAccount().getJid().toBareJid())); badge.setImageBitmap(avatarService().get(contact, getPixel(72))); badge.setOnClickListener(this.onBadgeClick); diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java index 8bd7e81e..d715aee2 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java @@ -42,8 +42,8 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentLinkedQueue; +import de.thedevstack.conversationsplus.ui.dialogs.MessageDetailsDialog; import de.thedevstack.conversationsplus.ui.listeners.ConversationSwipeRefreshListener; -import de.tzur.conversations.Settings; import de.thedevstack.conversationsplus.Config; import de.thedevstack.conversationsplus.R; import de.thedevstack.conversationsplus.crypto.PgpEngine; @@ -66,7 +66,6 @@ import de.thedevstack.conversationsplus.utils.GeoHelper; import de.thedevstack.conversationsplus.utils.UIHelper; import de.thedevstack.conversationsplus.xmpp.chatstate.ChatState; import de.thedevstack.conversationsplus.xmpp.jid.Jid; -import github.ankushsachdeva.emojicon.EmojiconEditText; import github.ankushsachdeva.emojicon.EmojiconGridView; import github.ankushsachdeva.emojicon.EmojiconsPopup; import github.ankushsachdeva.emojicon.emoji.Emojicon; @@ -502,6 +501,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa @Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.msg_ctx_mnu_details: + new MessageDetailsDialog(getActivity(), selectedMessage).show(); + return true; case R.id.share_with: shareWith(selectedMessage); return true; diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java index d6b944d0..dab291cc 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java @@ -21,6 +21,7 @@ import java.lang.ref.WeakReference; import java.util.List; import java.util.concurrent.RejectedExecutionException; +import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener; import de.tzur.conversations.Settings; import de.thedevstack.conversationsplus.R; import de.thedevstack.conversationsplus.entities.Account; @@ -128,7 +129,8 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> { mTimestamp.setText(UIHelper.readableTimeDifference(activity,conversation.getLatestMessage().getTimeSent())); ImageView profilePicture = (ImageView) view.findViewById(R.id.conversation_image); - loadAvatar(conversation,profilePicture); + profilePicture.setOnLongClickListener(new ShowResourcesListDialogListener(activity, conversation.getContact())); + loadAvatar(conversation, profilePicture); return view; } diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/PresencesArrayAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/PresencesArrayAdapter.java new file mode 100644 index 00000000..0b5cb897 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/PresencesArrayAdapter.java @@ -0,0 +1,63 @@ +package de.thedevstack.conversationsplus.ui.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Map; + +import de.thedevstack.conversationsplus.R; +import de.thedevstack.conversationsplus.entities.Presences; +import de.thedevstack.conversationsplus.utils.UIHelper; + +/** + * Created by tzur on 27.09.2015. + */ +public class PresencesArrayAdapter extends ArrayAdapter<Presence> { + private final Context context; + private final Presence[] values; + + public PresencesArrayAdapter(Context context, Presences presences) { + super(context, R.layout.dialog_resources_status); + this.context = context; + this.values = getPresenceArray(presences); + addAll(this.values); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rowView = inflater.inflate(R.layout.dialog_resources_status, parent, false); + TextView textView = (TextView) rowView.findViewById(R.id.dlg_res_stat_resource_name); + textView.setText(this.values[position].resource); + textView.setTextColor(Color.parseColor(UIHelper.getStatusColor(this.values[position].status))); + + return rowView; + } + + private static Presence[] getPresenceArray(Presences presences) { + ArrayList<Presence> presenceArrayList = new ArrayList<>(); + if (null != presences && null != presences.getPresences() && !presences.getPresences().isEmpty()) { + for (Map.Entry<String, Integer> entry : presences.getPresences().entrySet()) { + Presence p = new Presence(); + p.resource = entry.getKey(); + p.status = entry.getValue(); + presenceArrayList.add(p); + } + presenceArrayList.trimToSize(); + } + return presenceArrayList.toArray(new Presence[0]); + } +} + +class Presence { + String resource; + int status; +} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/AbstractAlertDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/AbstractAlertDialog.java new file mode 100644 index 00000000..10764798 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/AbstractAlertDialog.java @@ -0,0 +1,125 @@ +package de.thedevstack.conversationsplus.ui.dialogs; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.database.Cursor; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ListAdapter; + +import de.thedevstack.conversationsplus.R; + +/** + * Created by tzur on 29.09.2015. + */ +public class AbstractAlertDialog { + protected AlertDialog.Builder builder; + + public AbstractAlertDialog(Context context, String title) { + this.builder = new AlertDialog.Builder(context); + this.builder.setTitle(title); + this.builder.setPositiveButton(R.string.cplus_ok, null); + } + + public AbstractAlertDialog(Context context, int titleTextId) { + this(context, context.getString(titleTextId)); + } + + public void show() { + this.builder.show(); + } + + public Context getContext() { + return builder.getContext(); + } + + public AlertDialog.Builder setTitle(int titleId) { + return builder.setTitle(titleId); + } + + public AlertDialog.Builder setTitle(CharSequence title) { + return builder.setTitle(title); + } + + public AlertDialog.Builder setIcon(int iconId) { + return builder.setIcon(iconId); + } + + public AlertDialog.Builder setIcon(Drawable icon) { + return builder.setIcon(icon); + } + + public AlertDialog.Builder setMessage(CharSequence message) { + return builder.setMessage(message); + } + + public AlertDialog.Builder setMessage(int messageId) { + return builder.setMessage(messageId); + } + + public AlertDialog.Builder setIconAttribute(int attrId) { + return builder.setIconAttribute(attrId); + } + + public AlertDialog.Builder setPositiveButton(int textId, DialogInterface.OnClickListener listener) { + return builder.setPositiveButton(textId, listener); + } + + public AlertDialog.Builder setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) { + return builder.setPositiveButton(text, listener); + } + + public AlertDialog.Builder setNegativeButton(int textId, DialogInterface.OnClickListener listener) { + return builder.setNegativeButton(textId, listener); + } + + public AlertDialog.Builder setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) { + return builder.setNegativeButton(text, listener); + } + + public AlertDialog.Builder setNeutralButton(int textId, DialogInterface.OnClickListener listener) { + return builder.setNeutralButton(textId, listener); + } + + public AlertDialog.Builder setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) { + return builder.setNeutralButton(text, listener); + } + + public AlertDialog.Builder setCancelable(boolean cancelable) { + return builder.setCancelable(cancelable); + } + + public AlertDialog.Builder setOnCancelListener(DialogInterface.OnCancelListener onCancelListener) { + return builder.setOnCancelListener(onCancelListener); + } + + public AlertDialog.Builder setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) { + return builder.setOnDismissListener(onDismissListener); + } + + public AlertDialog.Builder setOnKeyListener(DialogInterface.OnKeyListener onKeyListener) { + return builder.setOnKeyListener(onKeyListener); + } + + public AlertDialog.Builder setAdapter(ListAdapter adapter, DialogInterface.OnClickListener listener) { + return builder.setAdapter(adapter, listener); + } + + public AlertDialog.Builder setCursor(Cursor cursor, DialogInterface.OnClickListener listener, String labelColumn) { + return builder.setCursor(cursor, listener, labelColumn); + } + + public AlertDialog.Builder setView(View view) { + return builder.setView(view); + } + + public AlertDialog.Builder setView(int layoutResId) { + return builder.setView(layoutResId); + } + + public AlertDialog.Builder setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) { + return builder.setOnItemSelectedListener(listener); + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/MessageDetailsDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/MessageDetailsDialog.java new file mode 100644 index 00000000..05830c75 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/MessageDetailsDialog.java @@ -0,0 +1,59 @@ +package de.thedevstack.conversationsplus.ui.dialogs; + +import android.app.Activity; +import android.app.AlertDialog; +import android.text.format.DateFormat; +import android.view.View; +import android.widget.TextView; + +import java.util.Date; + +import de.thedevstack.conversationsplus.R; +import de.thedevstack.conversationsplus.entities.Message; +import de.thedevstack.conversationsplus.utils.UIHelper; + +/** + * Created by tzur on 29.09.2015. + */ +public class MessageDetailsDialog extends AbstractAlertDialog { + private AlertDialog.Builder builder; + + public MessageDetailsDialog(Activity context, Message message) { + super(context, R.string.dlg_msg_details_title); + this.createView(context, message); + } + + protected void createView(Activity context, Message message) { + int viewId = R.layout.dialog_message_details; + View view = context.getLayoutInflater().inflate(viewId, null); + TextView timeSent = (TextView) view.findViewById(R.id.dlgMsgDetTimeSent); + timeSent.setText(DateFormat.format("dd.MM.yyyy kk:mm:ss", new Date(message.getMergedTimeSent()))); + TextView sender = (TextView) view.findViewById(R.id.dlgMsgDetSender); + TextView receipient = (TextView) view.findViewById(R.id.dlgMsgDetReceipient); + String me = message.getConversation().getAccount().getJid().getResourcepart(); + String other = message.getCounterpart().getResourcepart(); + if (Message.STATUS_RECEIVED == message.getStatus()) { + sender.setText(other); + receipient.setText(me); + } else { + sender.setText(me); + receipient.setText(other); + } + + if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getTransferable() != null) { + view.findViewById(R.id.dlgMsgDetFileTable).setVisibility(View.VISIBLE); + if (null != message.getFileParams()) { + Message.FileParams params = message.getFileParams(); + TextView tvFilesize = (TextView) view.findViewById(R.id.dlgMsgDetFileSize); + tvFilesize.setText(UIHelper.getHumanReadableFileSize(params.size)); + } + TextView mimetype = (TextView) view.findViewById(R.id.dlgMsgDetFileMimeType); + mimetype.setText(message.getMimeType()); + } + this.setView(view); + } + + public void show() { + this.builder.show(); + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShowResourcesListDialogListener.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShowResourcesListDialogListener.java new file mode 100644 index 00000000..070ea58c --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShowResourcesListDialogListener.java @@ -0,0 +1,47 @@ +package de.thedevstack.conversationsplus.ui.listeners; + +import android.content.Context; +import android.view.View; + +import de.thedevstack.conversationsplus.R; +import de.thedevstack.conversationsplus.entities.Contact; +import de.thedevstack.conversationsplus.ui.adapter.PresencesArrayAdapter; +import de.thedevstack.conversationsplus.ui.dialogs.AbstractAlertDialog; + +/** + * This listener shows the dialog with the resources of a contact. + * The resources are shown with the color of their current online mode. + * This listener implements OnClickListener and OnLongClickListener. + */ +public class ShowResourcesListDialogListener extends AbstractAlertDialog implements View.OnClickListener, View.OnLongClickListener { + private Contact contact; + + public ShowResourcesListDialogListener(Context context, Contact contact) { + super(context, getTitle(context, contact)); + this.contact = contact; + this.init(); + } + + private static final String getTitle(Context context, Contact contact) { + if (null != contact && null != contact.getJid() && null != contact.getJid().toBareJid()) { + int presenceCount = null != contact.getPresences() ? contact.getPresences().size() : 0; + return context.getString(R.string.dlg_resources_title, contact.getJid().toBareJid().toString(), presenceCount); + } + return null != contact ? contact.toString() : ""; + } + + protected void init() { + this.builder.setAdapter(new PresencesArrayAdapter(getContext(), this.contact.getPresences()), null); + } + + @Override + public void onClick(View v) { + this.show(); + } + + @Override + public boolean onLongClick(View view) { + this.show(); + return true; + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/UIHelper.java b/src/main/java/de/thedevstack/conversationsplus/utils/UIHelper.java index 0ef07808..532ff1cb 100644 --- a/src/main/java/de/thedevstack/conversationsplus/utils/UIHelper.java +++ b/src/main/java/de/thedevstack/conversationsplus/utils/UIHelper.java @@ -1,5 +1,7 @@ package de.thedevstack.conversationsplus.utils; +import java.math.BigDecimal; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.net.URLConnection; @@ -286,4 +288,20 @@ public class UIHelper { body = body.replace("?","").replace("¿",""); return LOCATION_QUESTIONS.contains(body); } + + public static String getHumanReadableFileSize(long filesize) { + if (0 > filesize) { + return "?"; + } + double size = Double.valueOf(filesize); + String[] sizes = {" bytes", " Kb", " Mb", " Gb", " Tb"}; + int i = 0; + while (1023 < size) { + size /= 1024d; + ++i; + } + BigDecimal readableSize = new BigDecimal(size); + readableSize = readableSize.setScale(2, BigDecimal.ROUND_HALF_UP); + return readableSize.doubleValue() + sizes[i]; + } } diff --git a/src/main/res/layout/dialog_message_details.xml b/src/main/res/layout/dialog_message_details.xml new file mode 100644 index 00000000..67561ae7 --- /dev/null +++ b/src/main/res/layout/dialog_message_details.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="8dp"> + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Time Sent:" + android:id="@+id/dlgMsgDetLblTimeSent" /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/dlgMsgDetTimeSent" + android:width="200dp" + android:layout_alignParentTop="true" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Sender Resource:" + android:id="@+id/dlgMsgDetLblSender" + android:layout_below="@+id/dlgMsgDetLblTimeSent" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/dlgMsgDetSender" + android:layout_below="@+id/dlgMsgDetTimeSent" + android:layout_alignRight="@+id/dlgMsgDetTimeSent" + android:layout_alignEnd="@+id/dlgMsgDetTimeSent" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Receipient Resource:" + android:id="@+id/dlgMsgDetLblReceipient" + android:layout_below="@+id/dlgMsgDetLblSender" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/dlgMsgDetReceipient" + android:layout_below="@+id/dlgMsgDetSender" + android:layout_alignRight="@+id/dlgMsgDetSender" + android:layout_alignEnd="@+id/dlgMsgDetSender" /> + + <TableLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/dlgMsgDetLblReceipient" + android:layout_marginTop="11dp" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:stretchColumns="1" + android:background="@color/black87" + android:id="@+id/dlgMsgDetFileTable"> + + <TableRow + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/white" + android:layout_marginTop="0.3dp" + android:layout_marginLeft="0.3dp" + android:layout_marginRight="0.3dp"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="File Details" + android:layout_column="0"/> + </TableRow> + + <TableRow + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/white" + android:layout_marginTop="0.3dp" + android:layout_marginLeft="0.3dp" + android:layout_marginRight="0.3dp"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Mime Type" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="" + android:id="@+id/dlgMsgDetFileMimeType" /> + </TableRow> + + <TableRow + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/white" + android:layout_marginLeft="0.3dp" + android:layout_marginTop="0.3dp" + android:layout_marginRight="0.3dp"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Size" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="" + android:id="@+id/dlgMsgDetFileSize"/> + </TableRow> + </TableLayout> + </RelativeLayout> + + + +</LinearLayout>
\ No newline at end of file diff --git a/src/main/res/layout/dialog_resources_status.xml b/src/main/res/layout/dialog_resources_status.xml new file mode 100644 index 00000000..4dd511f5 --- /dev/null +++ b/src/main/res/layout/dialog_resources_status.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="Medium Text" + android:id="@+id/dlg_res_stat_resource_name" + android:layout_marginLeft="10dp" /> +</LinearLayout>
\ No newline at end of file diff --git a/src/main/res/menu/message_context.xml b/src/main/res/menu/message_context.xml index 4e1316d3..2fe1ca22 100644 --- a/src/main/res/menu/message_context.xml +++ b/src/main/res/menu/message_context.xml @@ -1,6 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > - + <item + android:id="@+id/msg_ctx_mnu_details" + android:title="@string/msg_ctx_mnu_details" + android:visible="true"/> <item android:id="@+id/copy_text" android:title="@string/copy_text" diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 2d5337be..c9724e5a 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -466,4 +466,8 @@ <string name="search_for_contacts_or_groups">Nach Kontakten oder Konferenzen suchen</string> <string name="pref_led_notification_color">LED-Benachrichtigung Farbe</string> <string name="pref_led_notification_color_summary">Setze die Farbe der LED-Benachrichtigung</string> + <string name="msg_ctx_mnu_details">Nachrichtendetails</string> + <string name="dlg_msg_details_title">Nachrichtendetails</string> + <string name="cplus_ok">Ok</string> + <string name="dlg_resources_title">%1$s (%2$d)</string><!-- %s = bare jid, %d = count of online resources --> </resources> diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 77e7d23e..0bcbb9c4 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -495,4 +495,8 @@ <string name="search_for_contacts_or_groups">Search for contacts or groups</string> <string name="pref_led_notification_color">LED notification color</string> <string name="pref_led_notification_color_summary">Change the color of the LED notification</string> + <string name="msg_ctx_mnu_details">Message Details</string> + <string name="dlg_msg_details_title">Message Details</string> + <string name="cplus_ok">Ok</string> + <string name="dlg_resources_title">%1$s (%2$d)</string><!-- %s = bare jid, %d = count of online resources --> </resources> |