From 63b2ab6e47d7baf41703dd5e91e619589822f5af Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 14 Sep 2018 18:33:33 +0200 Subject: update strings --- src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main') diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 26a8a7112..6beb4ab3d 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -812,7 +812,7 @@ Address book Unable to save recording Foreground service - This notification category is used to display a permanent notification indicating that Conversations is running. + This notification category is used to display a permanent notification indicating that Pix-Art Messenger is running. Status Information Connectivity Problems This notification category is used to display a notification in case there is a problem connecting to an account. -- cgit v1.2.3 From abd87c0128241c45522cf20aea42be9d45d7cef9 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 14 Sep 2018 20:18:56 +0200 Subject: optimize some multi account handling in SettingsActivity --- .../messenger/services/XmppConnectionService.java | 9 +++ .../de/pixart/messenger/ui/SettingsActivity.java | 72 +++++++++++++++++----- 2 files changed, 64 insertions(+), 17 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index b6d23668c..b46c2f606 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -727,6 +727,7 @@ public class XmppConnectionService extends Service { } private boolean processAccountState(Account account, boolean interactive, boolean isUiAction, boolean isAccountPushed, HashSet pingCandidates) { + storeNumberOfAccounts(this.getAccounts().size()); boolean pingNow = false; if (account.getStatus().isAttemptReconnect()) { if (!hasInternetConnection()) { @@ -802,6 +803,14 @@ public class XmppConnectionService extends Service { return pingNow; } + private void storeNumberOfAccounts(int accounts) { + //write No of accounts to file + final SharedPreferences.Editor editor = getPreferences().edit(); + Log.d(Config.LOGTAG, "Number of accounts is " + accounts); + editor.putInt(SettingsActivity.NUMBER_OF_ACCOUNTS, accounts); + editor.apply(); + } + public boolean isDataSaverDisabled() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); diff --git a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java index 4bf9d26cc..0e4b5d391 100644 --- a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java @@ -60,6 +60,7 @@ public class SettingsActivity extends XmppActivity implements public static final String USE_BUNDLED_EMOJIS = "use_bundled_emoji"; public static final String USE_MULTI_ACCOUNTS = "use_multi_accounts"; public static final String QUICK_SHARE_ATTACHMENT_CHOICE = "quick_share_attachment_choice"; + public static final String NUMBER_OF_ACCOUNTS = "number_of_accounts"; public static final int REQUEST_WRITE_LOGS = 0xbf8701; Preference multiAccountPreference; @@ -75,6 +76,7 @@ public class SettingsActivity extends XmppActivity implements super.onCreate(savedInstanceState); this.mTheme = findTheme(); setTheme(this.mTheme); + updateTheme(); setContentView(R.layout.activity_settings); FragmentManager fm = getFragmentManager(); mSettingsFragment = (SettingsFragment) fm.findFragmentById(R.id.settings_content); @@ -96,12 +98,11 @@ public class SettingsActivity extends XmppActivity implements @Override public void onStart() { super.onStart(); - updateTheme(); - PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); multiAccountPreference = mSettingsFragment.findPreference("enable_multi_accounts"); if (multiAccountPreference != null) { isMultiAccountChecked = ((CheckBoxPreference) multiAccountPreference).isChecked(); + handleMultiAccountChanges(); } BundledEmojiPreference = mSettingsFragment.findPreference("use_bundled_emoji"); @@ -112,7 +113,7 @@ public class SettingsActivity extends XmppActivity implements QuickShareAttachmentChoicePreference = mSettingsFragment.findPreference("quick_share_attachment_choice"); if (QuickShareAttachmentChoicePreference != null) { QuickShareAttachmentChoicePreference.setOnPreferenceChangeListener((preference, newValue) -> { - recreate(); + refreshUiReal(); return true; }); isQuickShareAttachmentChoiceChecked = ((CheckBoxPreference) QuickShareAttachmentChoicePreference).isChecked(); @@ -287,20 +288,19 @@ public class SettingsActivity extends XmppActivity implements Log.d(Config.LOGTAG, "Multi account checkbox checked: " + isMultiAccountChecked); if (isMultiAccountChecked) { enableMultiAccountsPreference.setEnabled(false); - if (xmppConnectionService != null) { - final List accounts = xmppConnectionService.getAccounts(); - Log.d(Config.LOGTAG, "Disabled multi account: Number of accounts " + accounts.size()); - if (accounts.size() > 1) { - Log.d(Config.LOGTAG, "Disabled multi account not possible because you have more than one account"); + int accounts = getNumberOfAccounts(); + Log.d(Config.LOGTAG, "Disabled multi account: Number of accounts " + accounts); + if (accounts > 1) { + Log.d(Config.LOGTAG, "Disabling multi account not possible because you have more than one account"); enableMultiAccountsPreference.setEnabled(false); } else { - Log.d(Config.LOGTAG, "Disabled multi account possible because you have one account"); + Log.d(Config.LOGTAG, "Disabling multi account possible because you have only one account"); enableMultiAccountsPreference.setEnabled(true); + enableMultiAccountsPreference.setOnPreferenceClickListener(preference -> { + refreshUiReal(); + return true; + }); } - } else { - Log.d(Config.LOGTAG, "Disabled multi account not possible because XmppConnectionService == null"); - enableMultiAccountsPreference.setEnabled(false); - } } else { enableMultiAccountsPreference.setEnabled(true); enableMultiAccountsPreference.setOnPreferenceClickListener(preference -> { @@ -314,7 +314,7 @@ public class SettingsActivity extends XmppActivity implements private void updateTheme() { final int theme = findTheme(); if (this.mTheme != theme) { - recreate(); + refreshUiReal(); } } @@ -478,12 +478,17 @@ public class SettingsActivity extends XmppActivity implements SharedPreferences multiaccount_prefs = getApplicationContext().getSharedPreferences(USE_MULTI_ACCOUNTS, Context.MODE_PRIVATE); SharedPreferences.Editor editor = multiaccount_prefs.edit(); editor.putString("BackupPW", pw1); - editor.commit(); + boolean passwordstored = editor.commit(); + Log.d(Config.LOGTAG, "saving multiaccount password " + passwordstored); + if (passwordstored) { + recreate(); + } else { + handleMultiAccountChanges(); + } } }) .setNegativeButton(R.string.cancel, null); alertDialogBuilder.create().show(); - } @@ -558,6 +563,39 @@ public class SettingsActivity extends XmppActivity implements } public void refreshUiReal() { - //nothing to do. This Activity doesn't implement any listeners + recreate(); + handleMultiAccountChanges(); + } + + private void handleMultiAccountChanges() { + multiAccountPreference = mSettingsFragment.findPreference("enable_multi_accounts"); + if (multiAccountPreference != null) { + //check if password = null + final SharedPreferences multiaccount_prefs = getApplicationContext().getSharedPreferences(USE_MULTI_ACCOUNTS, Context.MODE_PRIVATE); + if (multiaccount_prefs != null && multiaccount_prefs.getString("BackupPW", null) == null) { + Log.d(Config.LOGTAG, "uncheck multiaccount because password = null"); + if (multiAccountPreference != null) { + ((CheckBoxPreference) multiAccountPreference).setChecked(false); + } + } + //if multiAccountDisabled reset password + final Preference enableMultiAccountsPreference = mSettingsFragment.findPreference("enable_multi_accounts"); + if (enableMultiAccountsPreference != null && !isMultiAccountChecked) { + SharedPreferences.Editor editor = multiaccount_prefs.edit(); + editor.putString("BackupPW", null); + if (editor.commit()) { + Log.d(Config.LOGTAG, "resetting multiaccount password because multiaccount = unchecked"); + } else { + Log.d(Config.LOGTAG, "resetting multiaccount password failed"); + } + } + } + } + + private int getNumberOfAccounts() { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + int NumberOfAccounts = preferences.getInt(NUMBER_OF_ACCOUNTS, 0); + Log.d(Config.LOGTAG, "Get number of accounts from file: " + NumberOfAccounts); + return NumberOfAccounts; } } -- cgit v1.2.3 From 9e2b83afa44cc2182773c30af5d0edbf122ec19b Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 14 Sep 2018 20:51:30 +0200 Subject: highlight selected conversation in tablet view --- .../de/pixart/messenger/ui/adapter/ConversationAdapter.java | 2 +- src/main/res/layout/conversation_list_row.xml | 2 +- src/main/res/layout/fragment_conversation.xml | 10 +++++----- src/main/res/values/themes.xml | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java index 5294ba7cd..7e29de8a6 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java @@ -99,7 +99,7 @@ public class ConversationAdapter extends RecyclerView.Adapter diff --git a/src/main/res/layout/fragment_conversation.xml b/src/main/res/layout/fragment_conversation.xml index d081b6543..3ddcd69c7 100644 --- a/src/main/res/layout/fragment_conversation.xml +++ b/src/main/res/layout/fragment_conversation.xml @@ -5,7 +5,7 @@ @@ -107,7 +107,7 @@ android:layout_height="48dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" - android:background="?attr/color_background_secondary" + android:background="?attr/color_background_tertiary" android:contentDescription="@string/send_message" android:src="@drawable/ic_send_text_offline" /> diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index c17bb820f..0e58f26a6 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -150,9 +150,9 @@ @color/accent @color/realwhite - @color/grey800 - @color/grey900 - @color/grey700 + @color/grey700 + @color/grey800 + @color/grey900 @color/red_a700 @color/green500 @color/red500 -- cgit v1.2.3 From 43e5ab1701fdd39506d690c11eefc2bac3678914 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 14 Sep 2018 21:30:59 +0200 Subject: change text highlight color --- src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java index b720375e7..efd3b8842 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java @@ -498,7 +498,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } else { viewHolder.messageBody.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Body1); } - viewHolder.messageBody.setHighlightColor(darkBackground ? type == SENT ? ContextCompat.getColor(activity, R.color.black26) : ContextCompat.getColor(activity, R.color.grey800) : ContextCompat.getColor(activity, R.color.grey500)); + viewHolder.messageBody.setHighlightColor(darkBackground ? type == SENT ? ContextCompat.getColor(activity, R.color.accent) : ContextCompat.getColor(activity, R.color.accent) : ContextCompat.getColor(activity, R.color.accent)); viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); if (message.getBody() != null) { final String nick = UIHelper.getMessageDisplayName(message); -- cgit v1.2.3 From e561d869fabad799ed5af5b89532b4500710c958 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 14 Sep 2018 22:51:15 +0200 Subject: show contact/group details as icons in tablet view --- .../de/pixart/messenger/ui/ConversationFragment.java | 18 ++++++++++++++++++ src/main/res/drawable-hdpi/ic_contact_white_24dp.png | Bin 0 -> 324 bytes src/main/res/drawable-mdpi/ic_contact_white_24dp.png | Bin 0 -> 201 bytes src/main/res/drawable-xhdpi/ic_contact_white_24dp.png | Bin 0 -> 370 bytes .../res/drawable-xxhdpi/ic_contact_white_24dp.png | Bin 0 -> 647 bytes .../res/drawable-xxxhdpi/ic_contact_white_24dp.png | Bin 0 -> 756 bytes src/main/res/menu/fragment_conversation.xml | 12 ++++++++++++ src/main/res/values/strings.xml | 1 + 8 files changed, 31 insertions(+) create mode 100644 src/main/res/drawable-hdpi/ic_contact_white_24dp.png create mode 100644 src/main/res/drawable-mdpi/ic_contact_white_24dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_contact_white_24dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_contact_white_24dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_contact_white_24dp.png (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 0d4610c8e..def4b8a69 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -1207,14 +1207,20 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke final MenuItem menuNeedHelp = menu.findItem(R.id.action_create_issue); final MenuItem menuSearchUpdates = menu.findItem(R.id.action_check_updates); final MenuItem menuArchiveChat = menu.findItem(R.id.action_archive_chat); + final MenuItem menuGroupDetails = menu.findItem(R.id.action_group_details); + final MenuItem menuContactDetails = menu.findItem(R.id.action_contact_details); if (conversation != null) { if (conversation.getMode() == Conversation.MODE_MULTI) { menuInviteContact.setVisible(true); menuArchiveChat.setTitle(R.string.action_end_conversation_muc); + menuGroupDetails.setVisible(true); + menuContactDetails.setVisible(false); } else { menuInviteContact.setVisible(false); menuArchiveChat.setTitle(R.string.action_end_conversation); + menuGroupDetails.setVisible(false); + menuContactDetails.setVisible(true); } menuNeedHelp.setVisible(true); menuSearchUpdates.setVisible(false); @@ -1223,6 +1229,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } else { menuNeedHelp.setVisible(false); menuSearchUpdates.setVisible(true); + menuInviteContact.setVisible(false); + menuGroupDetails.setVisible(false); + menuContactDetails.setVisible(false); } super.onCreateOptionsMenu(menu, menuInflater); } @@ -1541,6 +1550,15 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke case R.id.action_clear_history: clearHistoryDialog(conversation); break; + case R.id.action_group_details: + Intent intent = new Intent(activity, ConferenceDetailsActivity.class); + intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC); + intent.putExtra("uuid", conversation.getUuid()); + startActivity(intent); + break; + case R.id.action_contact_details: + activity.switchToContactDetails(conversation.getContact()); + break; case R.id.action_block: case R.id.action_unblock: final Activity activity = getActivity(); diff --git a/src/main/res/drawable-hdpi/ic_contact_white_24dp.png b/src/main/res/drawable-hdpi/ic_contact_white_24dp.png new file mode 100644 index 000000000..7c046b21c Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_contact_white_24dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_contact_white_24dp.png b/src/main/res/drawable-mdpi/ic_contact_white_24dp.png new file mode 100644 index 000000000..c61747dc2 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_contact_white_24dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_contact_white_24dp.png b/src/main/res/drawable-xhdpi/ic_contact_white_24dp.png new file mode 100644 index 000000000..eedda1b40 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_contact_white_24dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_contact_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_contact_white_24dp.png new file mode 100644 index 000000000..91e0d9a6b Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_contact_white_24dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_contact_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_contact_white_24dp.png new file mode 100644 index 000000000..f36920906 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_contact_white_24dp.png differ diff --git a/src/main/res/menu/fragment_conversation.xml b/src/main/res/menu/fragment_conversation.xml index d67bf5253..197dc8137 100644 --- a/src/main/res/menu/fragment_conversation.xml +++ b/src/main/res/menu/fragment_conversation.xml @@ -77,4 +77,16 @@ android:orderInCategory="100" app:showAsAction="never" android:title="@string/create_issue" /> + + \ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 6beb4ab3d..523893d91 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -825,4 +825,5 @@ Video compression Database backup App update + Group details -- cgit v1.2.3 From 51887fe4971405e3cabcb985629296d3329480d9 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 14 Sep 2018 22:58:59 +0200 Subject: show background in chatoverview a bit darker --- src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java index 7e29de8a6..36cae0eb3 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java @@ -99,7 +99,7 @@ public class ConversationAdapter extends RecyclerView.Adapter Date: Fri, 14 Sep 2018 23:04:20 +0200 Subject: do some performance optimizations on jid host suggestions --- .../messenger/ui/adapter/KnownHostsAdapter.java | 184 +++------------------ 1 file changed, 22 insertions(+), 162 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/adapter/KnownHostsAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/KnownHostsAdapter.java index 9f4a52d95..2e0bfccc6 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/KnownHostsAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/KnownHostsAdapter.java @@ -7,8 +7,6 @@ import android.widget.Filter; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.Locale; public class KnownHostsAdapter extends ArrayAdapter { @@ -17,34 +15,31 @@ public class KnownHostsAdapter extends ArrayAdapter { @Override protected FilterResults performFiltering(CharSequence constraint) { - if (constraint != null) { - ArrayList suggestions = new ArrayList<>(); - final String[] split = constraint.toString().split("@"); - if (split.length == 1) { - for (String domain : domains) { - suggestions.add(split[0].toLowerCase(Locale - .getDefault()) + "@" + domain); - } - } else if (split.length == 2) { - for (String domain : domains) { - if (domain.contentEquals(split[1])) { - suggestions.clear(); - break; - } else if (domain.contains(split[1])) { - suggestions.add(split[0].toLowerCase(Locale - .getDefault()) + "@" + domain); - } - } - } else { + final ArrayList suggestions = new ArrayList<>(); + final String[] split = constraint == null ? new String[0] : constraint.toString().split("@"); + if (split.length == 1) { + final String local = split[0].toLowerCase(Locale.ENGLISH); + for (String domain : domains) { + suggestions.add(local + "@" + domain); + } + } else if (split.length == 2) { + final String localPart = split[0].toLowerCase(Locale.ENGLISH); + final String domainPart = split[1].toLowerCase(Locale.ENGLISH); + if (domains.contains(domainPart)) { return new FilterResults(); } - FilterResults filterResults = new FilterResults(); - filterResults.values = suggestions; - filterResults.count = suggestions.size(); - return filterResults; + for (String domain : domains) { + if (domain.contains(domainPart)) { + suggestions.add(localPart + "@" + domain); + } + } } else { return new FilterResults(); } + FilterResults filterResults = new FilterResults(); + filterResults.values = suggestions; + filterResults.count = suggestions.size(); + return filterResults; } @Override @@ -52,9 +47,7 @@ public class KnownHostsAdapter extends ArrayAdapter { ArrayList filteredList = (ArrayList) results.values; if (results.count > 0) { clear(); - for (Object c : filteredList) { - add((String) c); - } + addAll(filteredList); notifyDataSetChanged(); } } @@ -62,140 +55,7 @@ public class KnownHostsAdapter extends ArrayAdapter { public KnownHostsAdapter(Context context, int viewResourceId, Collection mKnownHosts) { super(context, viewResourceId, new ArrayList<>()); - - if (mKnownHosts == null) { - domains = new ArrayList<>(); - } else { - domains = new ArrayList<>(mKnownHosts); - } - - HashSet hashSet = new HashSet<>(); - - // get servers from https://conversations.im/compliance/ - new Thread(() -> { - domains.add("pix-art.de"); - domains.add("conversations.im"); - domains.add("jabber.cat"); - domains.add("jabjab.de"); - domains.add("im.koderoot.net"); - domains.add("riotcat.org"); - domains.add("magicbroccoli.de"); - domains.add("kode.im"); - domains.add("jabber-germany.de"); - domains.add("simplewire.de"); - domains.add("suchat.org"); - domains.add("jabber.at"); - domains.add("trashserver.net"); - domains.add("wiuwiu.de"); - domains.add("5222.de"); - domains.add("dismail.de"); - domains.add("chat.sum7.eu"); - domains.add("xmpp.zone"); - domains.add("libranet.de"); - domains.add("laborversuch.de"); - domains.add("creep.im"); - domains.add("jabber.systemausfall.org"); - domains.add("jabber.hot-chilli.net"); - domains.add("jabber.fr"); - domains.add("jabber.de"); - domains.add("draugr.de"); - domains.add("elaon.de"); - domains.add("high-way.me"); - domains.add("jabber.rwth-aachen.de"); - domains.add("deshalbfrei.org"); - domains.add("mail.de"); - domains.add("bommboo.de"); - domains.add("jabber.systemli.org"); - domains.add("jabb.im"); - domains.add("mailbox.org"); - domains.add("hot-chilli.net"); - domains.add("jabberpl.org"); - domains.add("chinwag.im"); - domains.add("tchncs.de"); - domains.add("zsim.de"); - domains.add("patchcord.be"); - domains.add("gajim.org"); - domains.add("talker.to"); - domains.add("pimux.de"); - domains.add("jabber.home.vdlinde.org"); - domains.add("im.apinc.org"); - domains.add("chatme.im"); - domains.add("fusselkater.org"); - domains.add("datenknoten.me"); - domains.add("fysh.in"); - domains.add("jabber.chaos-darmstadt.de"); - domains.add("yax.im"); - domains.add("neko.im"); - domains.add("jabberzac.org"); - domains.add("xmpp.is"); - domains.add("home.zom.im"); - domains.add("jabber.ccc.de"); - domains.add("jwchat.org"); - domains.add("kdetalk.net"); - domains.add("kde.org"); - domains.add("riseup.net"); - domains.add("ruhr-uni-bochum.de"); - domains.add("njs.netlab.cz"); - domains.add("schokokeks.org"); - domains.add("jabber.cz"); - domains.add("ubuntu-jabber.de"); - domains.add("xabber.de"); - domains.add("ubuntu-jabber.net"); - domains.add("jabber.ru"); - domains.add("darknet.nz"); - domains.add("movim.eu"); - domains.add("404.city"); - domains.add("igniterealtime.org"); - domains.add("kapsi.fi"); - domains.add("jabbel.net"); - domains.add("joindiaspora.com"); - domains.add("alpha-labs.net"); - domains.add("xmppnet.de"); - domains.add("hoth.one"); - domains.add("blah.im"); - domains.add("xmpp.jp"); - domains.add("jabber.uni-mainz.de"); - domains.add("richim.org"); - domains.add("tigase.im"); - domains.add("jappix.com"); - domains.add("member.fsf.org"); - domains.add("jabber.rueckgr.at"); - domains.add("swissjabber.ch"); - domains.add("twattle.net"); - domains.add("jabber.calyxinstitute.org"); - domains.add("sapo.pt"); - domains.add("uprod.biz"); - domains.add("krautspace.de"); - domains.add("kraut.space"); - domains.add("null.pm"); - domains.add("anonymitaet-im-inter.net"); - domains.add("0nl1ne.at"); - domains.add("linuxlovers.at"); - domains.add("jabber.org"); - domains.add("jabber.no-sense.net"); - domains.add("swissjabber.eu"); - domains.add("swissjabber.org"); - domains.add("swissjabber.de"); - domains.add("swissjabber.li"); - domains.add("jabber.no"); - domains.add("cypherpunks.it"); - domains.add("adastra.re"); - domains.add("jabber-br.org"); - domains.add("einfachjabber.de"); - domains.add("jabber.smash-net.org"); - domains.add("freifunk.im"); - domains.add("openmailbox.org"); - domains.add("jabber.otr.im"); - domains.add("evil.im"); - domains.add("xmpp.slack.com"); - domains.add("chat.hipchat.com"); - domains.add("googlemail.com"); - - hashSet.addAll(domains); - domains.clear(); - domains.addAll(hashSet); - Collections.sort(domains, String::compareToIgnoreCase); - }).start(); + domains = new ArrayList<>(mKnownHosts); } public KnownHostsAdapter(Context context, int viewResourceId) { -- cgit v1.2.3 From 90463b8570ed55d262bb7d7f827b35c87841fb88 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 14 Sep 2018 23:10:22 +0200 Subject: slighten darken some more backgrounds in dark theme --- src/main/res/layout/activity_choose_contact.xml | 2 +- src/main/res/layout/activity_manage_accounts.xml | 2 +- src/main/res/layout/activity_start_conversation.xml | 2 +- src/main/res/layout/conversation_list_row.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/main') diff --git a/src/main/res/layout/activity_choose_contact.xml b/src/main/res/layout/activity_choose_contact.xml index f720864a3..26f1c7494 100644 --- a/src/main/res/layout/activity_choose_contact.xml +++ b/src/main/res/layout/activity_choose_contact.xml @@ -13,7 +13,7 @@ + android:background="?attr/color_background_secondary"> diff --git a/src/main/res/layout/activity_start_conversation.xml b/src/main/res/layout/activity_start_conversation.xml index 1cb95b456..7adb8714a 100644 --- a/src/main/res/layout/activity_start_conversation.xml +++ b/src/main/res/layout/activity_start_conversation.xml @@ -29,7 +29,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tab_layout" - android:background="?attr/color_background_primary" /> + android:background="?attr/color_background_secondary" /> + android:background="?attr/color_background_secondary"> Date: Fri, 14 Sep 2018 23:13:50 +0200 Subject: update strings --- src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main') diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 523893d91..aefe978c0 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -819,7 +819,7 @@ Messages Messages Silent messages - This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period). + This notification category is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period). Notification Settings Importance, Sound, Vibrate Video compression -- cgit v1.2.3 From 1e63a8291579043659f86dbb46d4d63d3225c471 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 23 Sep 2018 16:42:56 +0200 Subject: preview media before sending them and allow sharing and attaching of multiple files --- src/main/AndroidManifest.xml | 12 +- .../pixart/messenger/persistance/FileBackend.java | 51 +++- .../services/ContactChooserTargetService.java | 6 +- .../pixart/messenger/ui/ConversationFragment.java | 224 ++++++---------- .../pixart/messenger/ui/ConversationsActivity.java | 15 +- .../de/pixart/messenger/ui/SearchActivity.java | 8 +- .../de/pixart/messenger/ui/SettingsActivity.java | 3 +- .../de/pixart/messenger/ui/ShareWithActivity.java | 297 +++------------------ .../messenger/ui/adapter/AccountAdapter.java | 8 +- .../messenger/ui/adapter/ConversationAdapter.java | 10 +- .../messenger/ui/adapter/ListItemAdapter.java | 8 +- .../messenger/ui/adapter/MediaPreviewAdapter.java | 211 +++++++++++++++ .../messenger/ui/forms/FormFieldWrapper.java | 8 +- .../de/pixart/messenger/ui/util/Attachment.java | 120 +++++++++ .../pixart/messenger/ui/util/AttachmentTool.java | 60 ----- .../java/de/pixart/messenger/ui/util/Color.java | 48 ---- .../java/de/pixart/messenger/ui/util/Drawable.java | 43 --- .../pixart/messenger/ui/util/StyledAttributes.java | 60 +++++ .../messenger/utils/IrregularUnicodeDetector.java | 4 +- .../res/drawable-hdpi/ic_android_black_48dp.png | Bin 0 -> 710 bytes .../res/drawable-hdpi/ic_android_white_48dp.png | Bin 0 -> 733 bytes .../res/drawable-hdpi/ic_archive_black_48dp.png | Bin 0 -> 560 bytes .../res/drawable-hdpi/ic_archive_white_48dp.png | Bin 0 -> 557 bytes .../drawable-hdpi/ic_description_black_48dp.png | Bin 0 -> 405 bytes .../drawable-hdpi/ic_description_white_48dp.png | Bin 0 -> 421 bytes src/main/res/drawable-hdpi/ic_event_black_48dp.png | Bin 0 -> 344 bytes src/main/res/drawable-hdpi/ic_event_white_48dp.png | Bin 0 -> 342 bytes .../res/drawable-hdpi/ic_headset_black_48dp.png | Bin 0 -> 857 bytes .../res/drawable-hdpi/ic_headset_white_48dp.png | Bin 0 -> 865 bytes src/main/res/drawable-hdpi/ic_mic_black_48dp.png | Bin 0 -> 866 bytes src/main/res/drawable-hdpi/ic_mic_white_48dp.png | Bin 0 -> 870 bytes .../res/drawable-hdpi/ic_person_black_48dp.png | Bin 0 -> 622 bytes .../res/drawable-hdpi/ic_person_white_48dp.png | Bin 0 -> 623 bytes src/main/res/drawable-hdpi/ic_room_black_48dp.png | Bin 0 -> 948 bytes src/main/res/drawable-hdpi/ic_room_white_48dp.png | Bin 0 -> 966 bytes .../res/drawable-mdpi/ic_android_black_48dp.png | Bin 0 -> 410 bytes .../res/drawable-mdpi/ic_android_white_48dp.png | Bin 0 -> 416 bytes .../res/drawable-mdpi/ic_archive_black_48dp.png | Bin 0 -> 309 bytes .../res/drawable-mdpi/ic_archive_white_48dp.png | Bin 0 -> 306 bytes .../drawable-mdpi/ic_description_black_48dp.png | Bin 0 -> 247 bytes .../drawable-mdpi/ic_description_white_48dp.png | Bin 0 -> 257 bytes src/main/res/drawable-mdpi/ic_event_black_48dp.png | Bin 0 -> 228 bytes src/main/res/drawable-mdpi/ic_event_white_48dp.png | Bin 0 -> 221 bytes .../res/drawable-mdpi/ic_headset_black_48dp.png | Bin 0 -> 466 bytes .../res/drawable-mdpi/ic_headset_white_48dp.png | Bin 0 -> 473 bytes src/main/res/drawable-mdpi/ic_mic_black_48dp.png | Bin 0 -> 487 bytes src/main/res/drawable-mdpi/ic_mic_white_48dp.png | Bin 0 -> 489 bytes .../res/drawable-mdpi/ic_person_black_48dp.png | Bin 0 -> 359 bytes .../res/drawable-mdpi/ic_person_white_48dp.png | Bin 0 -> 351 bytes src/main/res/drawable-mdpi/ic_room_black_48dp.png | Bin 0 -> 524 bytes src/main/res/drawable-mdpi/ic_room_white_48dp.png | Bin 0 -> 537 bytes .../res/drawable-xhdpi/ic_android_black_48dp.png | Bin 0 -> 838 bytes .../res/drawable-xhdpi/ic_android_white_48dp.png | Bin 0 -> 852 bytes .../res/drawable-xhdpi/ic_archive_black_48dp.png | Bin 0 -> 607 bytes .../res/drawable-xhdpi/ic_archive_white_48dp.png | Bin 0 -> 620 bytes .../drawable-xhdpi/ic_description_black_48dp.png | Bin 0 -> 460 bytes .../drawable-xhdpi/ic_description_white_48dp.png | Bin 0 -> 485 bytes .../res/drawable-xhdpi/ic_event_black_48dp.png | Bin 0 -> 435 bytes .../res/drawable-xhdpi/ic_event_white_48dp.png | Bin 0 -> 439 bytes .../res/drawable-xhdpi/ic_headset_black_48dp.png | Bin 0 -> 1006 bytes .../res/drawable-xhdpi/ic_headset_white_48dp.png | Bin 0 -> 1017 bytes src/main/res/drawable-xhdpi/ic_mic_black_48dp.png | Bin 0 -> 1002 bytes src/main/res/drawable-xhdpi/ic_mic_white_48dp.png | Bin 0 -> 1008 bytes .../res/drawable-xhdpi/ic_person_black_48dp.png | Bin 0 -> 751 bytes .../res/drawable-xhdpi/ic_person_white_48dp.png | Bin 0 -> 738 bytes src/main/res/drawable-xhdpi/ic_room_black_48dp.png | Bin 0 -> 1093 bytes src/main/res/drawable-xhdpi/ic_room_white_48dp.png | Bin 0 -> 1121 bytes .../res/drawable-xxhdpi/ic_android_black_48dp.png | Bin 0 -> 1548 bytes .../res/drawable-xxhdpi/ic_android_white_48dp.png | Bin 0 -> 1602 bytes .../res/drawable-xxhdpi/ic_archive_black_48dp.png | Bin 0 -> 1073 bytes .../res/drawable-xxhdpi/ic_archive_white_48dp.png | Bin 0 -> 1084 bytes .../drawable-xxhdpi/ic_description_black_48dp.png | Bin 0 -> 824 bytes .../drawable-xxhdpi/ic_description_white_48dp.png | Bin 0 -> 861 bytes .../res/drawable-xxhdpi/ic_event_black_48dp.png | Bin 0 -> 787 bytes .../res/drawable-xxhdpi/ic_event_white_48dp.png | Bin 0 -> 800 bytes .../res/drawable-xxhdpi/ic_headset_black_48dp.png | Bin 0 -> 1867 bytes .../res/drawable-xxhdpi/ic_headset_white_48dp.png | Bin 0 -> 1896 bytes src/main/res/drawable-xxhdpi/ic_mic_black_48dp.png | Bin 0 -> 1846 bytes src/main/res/drawable-xxhdpi/ic_mic_white_48dp.png | Bin 0 -> 1866 bytes .../res/drawable-xxhdpi/ic_person_black_48dp.png | Bin 0 -> 1351 bytes .../res/drawable-xxhdpi/ic_person_white_48dp.png | Bin 0 -> 1360 bytes .../res/drawable-xxhdpi/ic_room_black_48dp.png | Bin 0 -> 2010 bytes .../res/drawable-xxhdpi/ic_room_white_48dp.png | Bin 0 -> 2071 bytes .../res/drawable-xxxhdpi/ic_android_black_48dp.png | Bin 0 -> 1868 bytes .../res/drawable-xxxhdpi/ic_android_white_48dp.png | Bin 0 -> 1951 bytes .../res/drawable-xxxhdpi/ic_archive_black_48dp.png | Bin 0 -> 1219 bytes .../res/drawable-xxxhdpi/ic_archive_white_48dp.png | Bin 0 -> 1243 bytes .../drawable-xxxhdpi/ic_description_black_48dp.png | Bin 0 -> 1050 bytes .../drawable-xxxhdpi/ic_description_white_48dp.png | Bin 0 -> 1087 bytes .../res/drawable-xxxhdpi/ic_event_black_48dp.png | Bin 0 -> 1061 bytes .../res/drawable-xxxhdpi/ic_event_white_48dp.png | Bin 0 -> 1053 bytes .../res/drawable-xxxhdpi/ic_headset_black_48dp.png | Bin 0 -> 2162 bytes .../res/drawable-xxxhdpi/ic_headset_white_48dp.png | Bin 0 -> 2214 bytes .../res/drawable-xxxhdpi/ic_mic_black_48dp.png | Bin 0 -> 2108 bytes .../res/drawable-xxxhdpi/ic_mic_white_48dp.png | Bin 0 -> 2141 bytes .../res/drawable-xxxhdpi/ic_person_black_48dp.png | Bin 0 -> 1552 bytes .../res/drawable-xxxhdpi/ic_person_white_48dp.png | Bin 0 -> 1552 bytes .../res/drawable-xxxhdpi/ic_room_black_48dp.png | Bin 0 -> 2283 bytes .../res/drawable-xxxhdpi/ic_room_white_48dp.png | Bin 0 -> 2439 bytes src/main/res/layout/fragment_conversation.xml | 26 +- src/main/res/layout/media_preview.xml | 28 ++ src/main/res/values/attrs.xml | 10 + src/main/res/values/defaults.xml | 1 - src/main/res/values/dimens.xml | 1 + src/main/res/values/strings.xml | 2 - src/main/res/values/themes.xml | 20 ++ src/main/res/xml/preferences.xml | 5 - 107 files changed, 682 insertions(+), 607 deletions(-) create mode 100644 src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java create mode 100644 src/main/java/de/pixart/messenger/ui/util/Attachment.java delete mode 100644 src/main/java/de/pixart/messenger/ui/util/AttachmentTool.java delete mode 100644 src/main/java/de/pixart/messenger/ui/util/Color.java delete mode 100644 src/main/java/de/pixart/messenger/ui/util/Drawable.java create mode 100644 src/main/java/de/pixart/messenger/ui/util/StyledAttributes.java create mode 100644 src/main/res/drawable-hdpi/ic_android_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_android_white_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_archive_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_archive_white_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_description_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_description_white_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_event_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_event_white_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_headset_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_headset_white_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_mic_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_mic_white_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_person_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_person_white_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_room_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_room_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_android_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_android_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_archive_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_archive_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_description_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_description_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_event_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_event_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_headset_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_headset_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_mic_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_mic_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_person_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_person_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_room_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_room_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_android_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_android_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_archive_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_archive_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_description_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_description_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_event_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_event_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_headset_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_headset_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_mic_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_mic_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_person_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_person_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_room_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_room_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_android_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_android_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_archive_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_archive_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_description_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_description_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_event_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_event_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_headset_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_headset_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_mic_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_mic_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_person_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_person_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_room_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_room_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_android_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_android_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_archive_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_archive_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_description_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_description_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_event_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_event_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_headset_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_headset_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_mic_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_mic_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_person_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_person_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_room_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_room_white_48dp.png create mode 100644 src/main/res/layout/media_preview.xml (limited to 'src/main') diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 79b621878..f9a50b2a1 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -214,18 +214,10 @@ android:launchMode="singleTop"> - - - - - - - - - + - + uris, long max) { + public static boolean allFilesUnderSize(Context context, List attachments, long max) { if (max <= 0) { Log.d(Config.LOGTAG, "server did not report max file size for http upload"); return true; //exception to be compatible with HTTP Upload < v0.2 } - for (Uri uri : uris) { - String mime = context.getContentResolver().getType(uri); + for (Attachment attachment : attachments) { + if (attachment.getType() != Attachment.Type.FILE) { + continue; + } + String mime = attachment.getMime(); if (mime != null && mime.startsWith("video/")) { try { - Dimensions dimensions = FileBackend.getVideoDimensions(context, uri); + Dimensions dimensions = FileBackend.getVideoDimensions(context, attachment.getUri()); if (dimensions.getMin() >= 720) { Log.d(Config.LOGTAG, "do not consider video file with min width larger or equal than 720 for size check"); continue; @@ -190,7 +194,7 @@ public class FileBackend { //ignore and fall through } } - if (FileBackend.getFileSize(context, uri) > max) { + if (FileBackend.getFileSize(context, attachment.getUri()) > max) { Log.d(Config.LOGTAG, "not all files are under " + max + " bytes. suggesting falling back to jingle"); return false; } @@ -554,6 +558,21 @@ public class FileBackend { return paint; } + private Bitmap cropCenterSquareVideo(Uri uri, int size) { + MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever(); + Bitmap frame; + try { + metadataRetriever.setDataSource(mXmppConnectionService, uri); + frame = metadataRetriever.getFrameAtTime(0); + metadataRetriever.release(); + return cropCenterSquare(frame, size); + } catch (Exception e) { + frame = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + frame.eraseColor(0xff000000); + return frame; + } + } + private Bitmap getVideoPreview(File file, int size) throws IOException { MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever(); Bitmap frame; @@ -1041,6 +1060,28 @@ public class FileBackend { return getVideoDimensions(metadataRetriever); } + public Bitmap getPreviewForUri(Attachment attachment, int size, boolean cacheOnly) { + final LruCache cache = mXmppConnectionService.getBitmapCache(); + Bitmap bitmap = cache.get(attachment.getUuid().toString()); + if (bitmap != null || cacheOnly) { + return bitmap; + } + Log.d(Config.LOGTAG, "attachment mime=" + attachment.getMime()); + if (attachment.getMime() != null && attachment.getMime().startsWith("video/")) { + bitmap = cropCenterSquareVideo(attachment.getUri(), size); + drawOverlay(bitmap, R.drawable.play_video, 0.75f); + } else { + bitmap = cropCenterSquare(attachment.getUri(), size); + if ("image/gif".equals(attachment.getMime())) { + Bitmap withGifOverlay = bitmap.copy(Bitmap.Config.ARGB_8888, true); + drawOverlay(withGifOverlay, R.drawable.play_gif, 1.0f); + bitmap.recycle(); + bitmap = withGifOverlay; + } + } + cache.put(attachment.getUuid().toString(), bitmap); + return bitmap; + } private static Dimensions getVideoDimensions(Context context, Uri uri) throws NotAVideoFile { MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); diff --git a/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java b/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java index d20f9c1f3..4c0aec3ca 100644 --- a/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java +++ b/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java @@ -17,7 +17,7 @@ import java.util.ArrayList; import java.util.List; import de.pixart.messenger.entities.Conversation; -import de.pixart.messenger.ui.ShareWithActivity; +import de.pixart.messenger.ui.ConversationsActivity; @TargetApi(Build.VERSION_CODES.M) public class ContactChooserTargetService extends ChooserTargetService implements ServiceConnection { @@ -41,7 +41,7 @@ public class ContactChooserTargetService extends ChooserTargetService implements return chooserTargets; } mXmppConnectionService.populateWithOrderedConversations(conversations, false); - final ComponentName componentName = new ComponentName(this, ShareWithActivity.class); + final ComponentName componentName = new ComponentName(this, ConversationsActivity.class); final int pixel = (int) (48 * getResources().getDisplayMetrics().density); for (Conversation conversation : conversations) { if (conversation.sentMessagesCount() == 0) { @@ -51,7 +51,7 @@ public class ContactChooserTargetService extends ChooserTargetService implements final Icon icon = Icon.createWithBitmap(mXmppConnectionService.getAvatarService().get(conversation, pixel)); final float score = 1 - (1.0f / MAX_TARGETS) * chooserTargets.size(); final Bundle extras = new Bundle(); - extras.putString("uuid", conversation.getUuid()); + extras.putString(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid()); chooserTargets.add(new ChooserTarget(name, icon, score, componentName, extras)); if (chooserTargets.size() >= MAX_TARGETS) { break; diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index def4b8a69..451ac6bde 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -15,8 +15,6 @@ import android.content.IntentSender.SendIntentException; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.databinding.DataBindingUtil; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -27,7 +25,6 @@ import android.provider.MediaStore; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.annotation.StringRes; -import android.support.media.ExifInterface; import android.support.v13.view.inputmethod.InputConnectionCompat; import android.support.v13.view.inputmethod.InputContentInfoCompat; import android.support.v7.app.AlertDialog; @@ -54,16 +51,12 @@ import android.widget.AbsListView.OnScrollListener; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; import net.java.otr4j.session.SessionStatus; -import java.io.File; -import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -98,9 +91,10 @@ import de.pixart.messenger.http.HttpDownloadConnection; import de.pixart.messenger.persistance.FileBackend; import de.pixart.messenger.services.MessageArchiveService; import de.pixart.messenger.services.XmppConnectionService; +import de.pixart.messenger.ui.adapter.MediaPreviewAdapter; import de.pixart.messenger.ui.adapter.MessageAdapter; import de.pixart.messenger.ui.util.ActivityResult; -import de.pixart.messenger.ui.util.AttachmentTool; +import de.pixart.messenger.ui.util.Attachment; import de.pixart.messenger.ui.util.ConversationMenuConfigurator; import de.pixart.messenger.ui.util.DateSeparator; import de.pixart.messenger.ui.util.EditMessageActionModeCallback; @@ -113,7 +107,6 @@ import de.pixart.messenger.ui.util.SendButtonAction; import de.pixart.messenger.ui.util.SendButtonTool; import de.pixart.messenger.ui.util.ShareUtil; import de.pixart.messenger.ui.widget.EditMessage; -import de.pixart.messenger.utils.FileUtils; import de.pixart.messenger.utils.MenuDoubleTabUtil; import de.pixart.messenger.utils.MessageUtils; import de.pixart.messenger.utils.NickValidityChecker; @@ -129,7 +122,6 @@ import rocks.xmpp.addr.Jid; import static de.pixart.messenger.ui.XmppActivity.EXTRA_ACCOUNT; import static de.pixart.messenger.ui.XmppActivity.REQUEST_INVITE_TO_CONVERSATION; -import static de.pixart.messenger.ui.util.SendButtonAction.TEXT; import static de.pixart.messenger.ui.util.SoftKeyboardUtils.hideSoftKeyboard; import static de.pixart.messenger.xmpp.Patches.ENCRYPTION_EXCEPTIONS; @@ -179,6 +171,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke private Toast messageLoaderToast; private ConversationsActivity activity; private boolean reInitRequiredOnStart = true; + private MediaPreviewAdapter mediaPreviewAdapter; private SimpleFingerGestures gesturesDetector = new SimpleFingerGestures(); @@ -851,111 +844,19 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } public void attachEditorContentToConversation(Uri uri) { - this.attachFileToConversation(conversation, uri, null); + mediaPreviewAdapter.addMediaPreviews(Attachment.of(getActivity(), uri, Attachment.Type.FILE)); + toggleInputMethod(); } - private void attachImageToConversation(Conversation conversation, Uri uri, boolean sendAsIs) { + private void attachImageToConversation(Conversation conversation, Uri uri) { if (conversation == null) { return; } - if (sendAsIs) { - sendImage(conversation, uri); - return; - } - final Conversation conversation_preview = conversation; - final Uri uri_preview = uri; - Bitmap bitmap = null; - try { - bitmap = BitmapFactory.decodeFile(FileUtils.getPath(activity, uri)); - } catch (Exception e) { - e.printStackTrace(); - } - File file = null; - ExifInterface exif = null; - int orientation = 0; - try { - file = new File(FileUtils.getPath(activity, uri)); - } catch (Exception e) { - e.printStackTrace(); - } - if (file != null) { - try { - exif = new ExifInterface(file.toString()); - } catch (IOException e) { - e.printStackTrace(); - } - orientation = exif != null ? exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) : 0; - } - Log.d(Config.LOGTAG, "EXIF: " + orientation); - Bitmap rotated_image = null; - Log.d(Config.LOGTAG, "Rotate image"); - try { - rotated_image = FileBackend.rotateBitmap(file, bitmap, orientation); - } catch (Exception e) { - e.printStackTrace(); - } - if (rotated_image != null) { - int scaleSize = 600; - int originalWidth = rotated_image.getWidth(); - int originalHeight = rotated_image.getHeight(); - int newWidth = -1; - int newHeight = -1; - float multFactor; - if (originalHeight > originalWidth) { - newHeight = scaleSize; - multFactor = (float) originalWidth / (float) originalHeight; - newWidth = (int) (newHeight * multFactor); - } else if (originalWidth > originalHeight) { - newWidth = scaleSize; - multFactor = (float) originalHeight / (float) originalWidth; - newHeight = (int) (newWidth * multFactor); - } else if (originalHeight == originalWidth) { - newHeight = scaleSize; - newWidth = scaleSize; - } - Log.d(Config.LOGTAG, "Scaling preview image from " + originalHeight + "px x " + originalWidth + "px to " + newHeight + "px x " + newWidth + "px"); - Bitmap preview = null; - - try { - preview = Bitmap.createScaledBitmap(rotated_image, newWidth, newHeight, false); - } catch (Exception e) { - e.printStackTrace(); - } - if (preview != null) { - ImageView ImagePreview = new ImageView(activity); - LinearLayout.LayoutParams vp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); - ImagePreview.setLayoutParams(vp); - ImagePreview.setMaxWidth(newWidth); - ImagePreview.setMaxHeight(newHeight); - ImagePreview.setPadding(5, 5, 5, 5); - ImagePreview.setImageBitmap(preview); - getActivity().runOnUiThread(() -> { - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setView(ImagePreview); - builder.setTitle(R.string.send_image); - builder.setPositiveButton(R.string.ok, (dialog, which) -> sendImage(conversation_preview, uri_preview)); - builder.setOnCancelListener(dialog -> mPendingImageUris.clear()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - builder.setOnDismissListener(dialog -> mPendingImageUris.clear()); - } - AlertDialog alertDialog = builder.create(); - alertDialog.show(); - }); - } else { - getActivity().runOnUiThread(() -> Toast.makeText(getActivity(), getText(R.string.error_file_not_found), Toast.LENGTH_LONG).show()); - } - } else { - getActivity().runOnUiThread(() -> Toast.makeText(getActivity(), getText(R.string.error_file_not_found), Toast.LENGTH_LONG).show()); - } - } - - private void sendImage(Conversation conversation, Uri uri) { final Toast prepareFileToast = Toast.makeText(getActivity(), getText(R.string.preparing_image), Toast.LENGTH_LONG); prepareFileToast.show(); activity.delegateUriPermissionsToService(uri); activity.xmppConnectionService.attachImageToConversation(conversation, uri, new UiCallback() { - @Override public void userInputRequried(PendingIntent pi, Message object) { hidePrepareFileToast(prepareFileToast); @@ -981,6 +882,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } private void sendMessage() { + if (mediaPreviewAdapter.hasAttachments()) { + commitAttachments(); + return; + } final String body = binding.textinput.getText().toString(); final Conversation conversation = this.conversation; if (body.length() == 0 || conversation == null) { @@ -1086,7 +991,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } private void handlePositiveActivityResult(int requestCode, final Intent data) { - final String type = data == null ? null : data.getType(); switch (requestCode) { case REQUEST_TRUST_KEYS_TEXT: final String body = binding.textinput.getText().toString(); @@ -1098,51 +1002,32 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke selectPresenceToAttachFile(choice); break; case ATTACHMENT_CHOICE_CHOOSE_IMAGE: - final List imageUris = AttachmentTool.extractUriFromIntent(data); - final int ImageUrisCount = imageUris.size(); - Log.d(Config.LOGTAG, "ConversationsActivity.onActivityResult() - attaching image - number of uris: " + ImageUrisCount); - if (ImageUrisCount == 1) { - Uri uri = imageUris.get(0); - Log.d(Config.LOGTAG, "ConversationsActivity.onActivityResult() - attaching image to conversations. CHOOSE_IMAGE"); - attachImageToConversation(conversation, uri, false); - } else { - for (Iterator i = imageUris.iterator(); i.hasNext(); i.remove()) { - Log.d(Config.LOGTAG, "ConversationsActivity.onActivityResult() - attaching images to conversations. CHOOSE_IMAGES"); - attachImagesToConversation(conversation, i.next()); - } - } + final List imageUris = Attachment.extractAttachments(getActivity(), data, Attachment.Type.IMAGE); + mediaPreviewAdapter.addMediaPreviews(imageUris); + toggleInputMethod(); break; case ATTACHMENT_CHOICE_TAKE_FROM_CAMERA: final Uri takePhotoUri = pendingTakePhotoUri.pop(); - final Uri takeVideoUri = pendingTakeVideoUri.pop(); if (takePhotoUri != null) { - attachPhotoToConversation(conversation, takePhotoUri); - } else if (takeVideoUri != null) { - attachFileToConversation(conversation, takeVideoUri, type); + mediaPreviewAdapter.addMediaPreviews(Attachment.of(getActivity(), takePhotoUri, Attachment.Type.IMAGE)); + toggleInputMethod(); } else { - Log.d(Config.LOGTAG, "lost take uri. unable to to attach"); + Log.d(Config.LOGTAG, "lost take photo uri. unable to to attach"); } break; case ATTACHMENT_CHOICE_CHOOSE_FILE: case ATTACHMENT_CHOICE_RECORD_VOICE: - final List fileUris = AttachmentTool.extractUriFromIntent(data); - final PresenceSelector.OnPresenceSelected callback = () -> { - for (Iterator i = fileUris.iterator(); i.hasNext(); i.remove()) { - Log.d(Config.LOGTAG, "ConversationsActivity.onActivityResult() - attaching file to conversations. CHOOSE_FILE/RECORD_VOICE"); - attachFileToConversation(conversation, i.next(), type); - } - }; - if (conversation == null || conversation.getMode() == Conversation.MODE_MULTI || FileBackend.allFilesUnderSize(getActivity(), fileUris, getMaxHttpUploadSize(conversation))) { - callback.onPresenceSelected(); - } else { - activity.selectPresence(conversation, callback); - } + final Attachment.Type type = requestCode == ATTACHMENT_CHOICE_RECORD_VOICE ? Attachment.Type.RECORDING : Attachment.Type.FILE; + final List fileUris = Attachment.extractAttachments(getActivity(), data, type); + mediaPreviewAdapter.addMediaPreviews(fileUris); + toggleInputMethod(); break; case ATTACHMENT_CHOICE_LOCATION: double latitude = data.getDoubleExtra("latitude", 0); double longitude = data.getDoubleExtra("longitude", 0); Uri geo = Uri.parse("geo:" + String.valueOf(latitude) + "," + String.valueOf(longitude)); - attachLocationToConversation(conversation, geo); + mediaPreviewAdapter.addMediaPreviews(Attachment.of(getActivity(), geo, Attachment.Type.LOCATION)); + toggleInputMethod(); break; case REQUEST_INVITE_TO_CONVERSATION: XmppActivity.ConferenceInvite invite = XmppActivity.ConferenceInvite.parse(data); @@ -1156,6 +1041,38 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } } + private void commitAttachments() { + final List attachments = mediaPreviewAdapter.getAttachments(); + final PresenceSelector.OnPresenceSelected callback = () -> { + for (Iterator i = attachments.iterator(); i.hasNext(); i.remove()) { + final Attachment attachment = i.next(); + if (attachment.getType() == Attachment.Type.LOCATION) { + attachLocationToConversation(conversation, attachment.getUri()); + } else if (attachment.getType() == Attachment.Type.IMAGE) { + Log.d(Config.LOGTAG, "ConversationsActivity.commitAttachments() - attaching image to conversations. CHOOSE_IMAGE"); + attachImageToConversation(conversation, attachment.getUri()); + } else { + Log.d(Config.LOGTAG, "ConversationsActivity.commitAttachments() - attaching file to conversations. CHOOSE_FILE/RECORD_VOICE/RECORD_VIDEO"); + attachFileToConversation(conversation, attachment.getUri(), attachment.getMime()); + } + } + mediaPreviewAdapter.notifyDataSetChanged(); + toggleInputMethod(); + }; + if (conversation == null || conversation.getMode() == Conversation.MODE_MULTI || FileBackend.allFilesUnderSize(getActivity(), attachments, getMaxHttpUploadSize(conversation))) { + callback.onPresenceSelected(); + } else { + activity.selectPresence(conversation, callback); + } + } + + public void toggleInputMethod() { + boolean hasAttachments = mediaPreviewAdapter.hasAttachments(); + binding.textinput.setVisibility(hasAttachments ? View.GONE : View.VISIBLE); + binding.mediaPreview.setVisibility(hasAttachments ? View.VISIBLE : View.GONE); + updateSendButton(); + } + private void handleNegativeActivityResult(int requestCode) { switch (requestCode) { //nothing to do for now @@ -1253,6 +1170,8 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke binding.messagesView.setOnScrollListener(mOnScrollListener); binding.messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL); + mediaPreviewAdapter = new MediaPreviewAdapter(this); + binding.mediaPreview.setAdapter(mediaPreviewAdapter); messageListAdapter = new MessageAdapter((XmppActivity) getActivity(), this.messageList); messageListAdapter.setOnContactPictureClicked(message -> { String fingerprint; @@ -1871,6 +1790,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke case ATTACHMENT_CHOICE_CHOOSE_FILE: chooser = true; intent.setType("*/*"); + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setAction(Intent.ACTION_GET_CONTENT); break; @@ -2361,6 +2281,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke final String nick = extras.getString(ConversationsActivity.EXTRA_NICK); final boolean asQuote = extras.getBoolean(ConversationsActivity.EXTRA_AS_QUOTE); final boolean pm = extras.getBoolean(ConversationsActivity.EXTRA_IS_PRIVATE_MESSAGE, false); + final List uris = extractUris(extras); + if (uris != null && uris.size() > 0) { + mediaPreviewAdapter.addMediaPreviews(Attachment.of(getActivity(), uris)); + toggleInputMethod(); + return; + } if (nick != null) { if (pm) { Jid jid = conversation.getJid(); @@ -2389,6 +2315,19 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } } + private List extractUris(Bundle extras) { + final List uris = extras.getParcelableArrayList(Intent.EXTRA_STREAM); + if (uris != null) { + return uris; + } + final Uri uri = extras.getParcelable(Intent.EXTRA_STREAM); + if (uri != null) { + return Collections.singletonList(uri); + } else { + return null; + } + } + private boolean showBlockSubmenu(View view) { final Jid jid = conversation.getJid(); if (jid.getLocal() == null) { @@ -2603,11 +2542,17 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } public void updateSendButton() { + boolean hasAttachments = mediaPreviewAdapter != null && mediaPreviewAdapter.hasAttachments(); boolean useSendButtonToIndicateStatus = PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("send_button_status", getResources().getBoolean(R.bool.send_button_status)); final Conversation c = this.conversation; final Presence.Status status; final String text = this.binding.textinput == null ? "" : this.binding.textinput.getText().toString(); - SendButtonAction action = SendButtonTool.getAction(getActivity(), c, text); + final SendButtonAction action; + if (hasAttachments) { + action = SendButtonAction.TEXT; + } else { + action = SendButtonTool.getAction(getActivity(), c, text); + } if (useSendButtonToIndicateStatus && c.getAccount().getStatus() == Account.State.ONLINE) { if (activity.xmppConnectionService != null && activity.xmppConnectionService.getMessageArchiveService().isCatchingUp(c)) { status = Presence.Status.OFFLINE; @@ -2619,9 +2564,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } else { status = Presence.Status.OFFLINE; } - if (action.toString().equals("CHOOSE_ATTACHMENT") && !activity.xmppConnectionService.getAttachmentChoicePreference()) { - action = TEXT; - } this.binding.textSendButton.setTag(action); this.binding.textSendButton.setImageResource(SendButtonTool.getSendButtonImageResource(getActivity(), action, status)); } diff --git a/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java b/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java index 11d4cc31f..05cfe3ab4 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java @@ -63,6 +63,7 @@ import net.java.otr4j.session.SessionStatus; import org.openintents.openpgp.util.OpenPgpApi; +import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -111,6 +112,11 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio public static final String ACTION_DESTROY_MUC = "de.pixart.messenger.DESTROY_MUC"; public static final int REQUEST_OPEN_MESSAGE = 0x9876; public static final int REQUEST_PLAY_PAUSE = 0x5432; + private static List VIEW_AND_SHARE_ACTIONS = Arrays.asList( + ACTION_VIEW_CONVERSATION, + Intent.ACTION_SEND, + Intent.ACTION_SEND_MULTIPLE + ); private boolean showLastSeen = false; @@ -126,8 +132,9 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio private boolean mActivityPaused = true; private AtomicBoolean mRedirectInProcess = new AtomicBoolean(false); - private static boolean isViewIntent(Intent i) { - return i != null && ACTION_VIEW_CONVERSATION.equals(i.getAction()) && i.hasExtra(EXTRA_CONVERSATION); + private static boolean isViewOrShareIntent(Intent i) { + Log.d(Config.LOGTAG, "action: " + (i == null ? null : i.getAction())); + return i != null && VIEW_AND_SHARE_ACTIONS.contains(i.getAction()) && i.hasExtra(EXTRA_CONVERSATION); } private static Intent createLauncherIntent(Context context) { @@ -451,7 +458,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio } else { intent = savedInstanceState.getParcelable("intent"); } - if (isViewIntent(intent)) { + if (isViewOrShareIntent(intent)) { pendingViewIntent.push(intent); setIntent(createLauncherIntent(this)); } @@ -626,7 +633,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio @Override protected void onNewIntent(final Intent intent) { - if (isViewIntent(intent)) { + if (isViewOrShareIntent(intent)) { if (xmppConnectionService != null) { processViewIntent(intent); } else { diff --git a/src/main/java/de/pixart/messenger/ui/SearchActivity.java b/src/main/java/de/pixart/messenger/ui/SearchActivity.java index cc3172670..9ea9e7592 100644 --- a/src/main/java/de/pixart/messenger/ui/SearchActivity.java +++ b/src/main/java/de/pixart/messenger/ui/SearchActivity.java @@ -56,7 +56,7 @@ import de.pixart.messenger.services.MessageSearchTask; import de.pixart.messenger.ui.adapter.MessageAdapter; import de.pixart.messenger.ui.interfaces.OnSearchResultsAvailable; import de.pixart.messenger.ui.util.ChangeWatcher; -import de.pixart.messenger.ui.util.Color; +import de.pixart.messenger.ui.util.StyledAttributes; import de.pixart.messenger.ui.util.DateSeparator; import de.pixart.messenger.ui.util.Drawable; import de.pixart.messenger.ui.util.ListViewUtils; @@ -213,12 +213,12 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc private void changeBackground(boolean hasSearch, boolean hasResults) { if (hasSearch) { if (hasResults) { - binding.searchResults.setBackgroundColor(Color.get(this, R.attr.color_background_secondary)); + binding.searchResults.setBackgroundColor(StyledAttributes.getColor(this, R.attr.color_background_secondary)); } else { - binding.searchResults.setBackground(Drawable.get(this, R.attr.activity_background_no_results)); + binding.searchResults.setBackground(StyledAttributes.getDrawable(this, R.attr.activity_background_no_results)); } } else { - binding.searchResults.setBackground(Drawable.get(this, R.attr.activity_background_search)); + binding.searchResults.setBackground(StyledAttributes.getDrawable(this, R.attr.activity_background_search)); } } diff --git a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java index 0e4b5d391..c9c6006de 100644 --- a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java @@ -38,7 +38,6 @@ import de.pixart.messenger.crypto.OmemoSetting; import de.pixart.messenger.entities.Account; import de.pixart.messenger.services.ExportLogsService; import de.pixart.messenger.services.MemorizingTrustManager; -import de.pixart.messenger.ui.util.Color; import de.pixart.messenger.utils.TimeframeUtils; import rocks.xmpp.addr.Jid; @@ -85,7 +84,7 @@ public class SettingsActivity extends XmppActivity implements fm.beginTransaction().replace(R.id.settings_content, mSettingsFragment).commit(); } mSettingsFragment.setActivityIntent(getIntent()); - getWindow().getDecorView().setBackgroundColor(Color.get(this, R.attr.color_background_secondary)); + getWindow().getDecorView().setBackgroundColor(StyledAttributes.getColor(this, R.attr.color_background_secondary)); setSupportActionBar(findViewById(R.id.toolbar)); configureActionBar(getSupportActionBar()); } diff --git a/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java b/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java index a820378a3..da3d2ff8f 100644 --- a/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java @@ -1,6 +1,5 @@ package de.pixart.messenger.ui; -import android.app.PendingIntent; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; @@ -12,116 +11,32 @@ import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; -import java.net.URLConnection; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import de.pixart.messenger.Config; import de.pixart.messenger.R; import de.pixart.messenger.entities.Account; import de.pixart.messenger.entities.Conversation; -import de.pixart.messenger.entities.Message; -import de.pixart.messenger.persistance.FileBackend; import de.pixart.messenger.services.EmojiService; import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.ui.adapter.ConversationAdapter; -import de.pixart.messenger.ui.util.PresenceSelector; -import de.pixart.messenger.xmpp.XmppConnection; import rocks.xmpp.addr.Jid; import static de.pixart.messenger.ui.SettingsActivity.USE_BUNDLED_EMOJIS; -import static java.lang.String.format; public class ShareWithActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate { private static final int REQUEST_STORAGE_PERMISSION = 0x733f32; - private boolean mReturnToPrevious = false; + private static final int REQUEST_START_NEW_CONVERSATION = 0x0501; private Conversation mPendingConversation = null; - - @Override - public void onConversationUpdate() { - refreshUi(); - } - - private class Share { - public List uris = new ArrayList<>(); - public boolean image; - public String account; - public String contact; - public String text; - public String uuid; - public boolean multiple = false; - public String type; - } - private Share share; - - private static final int REQUEST_START_NEW_CONVERSATION = 0x0501; - private RecyclerView mListView; private ConversationAdapter mAdapter; private List mConversations = new ArrayList<>(); - private Toast mToast; - private AtomicInteger attachmentCounter = new AtomicInteger(0); - - private UiInformableCallback attachFileCallback = new UiInformableCallback() { - - @Override - public void inform(final String text) { - runOnUiThread(() -> replaceToast(text)); - } - - @Override - public void userInputRequried(PendingIntent pi, Message object) { - // TODO Auto-generated method stub - - } - - @Override - public void success(final Message message) { - runOnUiThread(() -> { - if (attachmentCounter.decrementAndGet() <= 0) { - int resId; - if (share.image && share.multiple) { - resId = R.string.shared_images_with_x; - } else if (share.image) { - resId = R.string.shared_image_with_x; - } else { - resId = R.string.shared_file_with_x; - } - Conversation conversation = (Conversation) message.getConversation(); - replaceToast(getString(resId, conversation.getName())); - if (mReturnToPrevious) { - finish(); - } else { - switchToConversation(conversation); - } - } - }); - } - - @Override - public void error(final int errorCode, Message object) { - runOnUiThread(() -> { - replaceToast(getString(errorCode)); - if (attachmentCounter.decrementAndGet() <= 0) { - finish(); - } - }); - } - }; - - protected void hideToast() { - if (mToast != null) { - mToast.cancel(); - } - } - protected void replaceToast(String msg) { - hideToast(); - mToast = Toast.makeText(this, msg, Toast.LENGTH_LONG); - mToast.show(); + @Override + public void onConversationUpdate() { + refreshUi(); } protected void onActivityResult(int requestCode, int resultCode, final Intent data) { @@ -160,20 +75,16 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer super.onCreate(savedInstanceState); boolean useBundledEmoji = getPreferences().getBoolean(USE_BUNDLED_EMOJIS, getResources().getBoolean(R.bool.use_bundled_emoji)); new EmojiService(this).init(useBundledEmoji); - setContentView(R.layout.activity_share_with); - setSupportActionBar(findViewById(R.id.toolbar)); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(false); getSupportActionBar().setHomeButtonEnabled(false); } - setTitle(getString(R.string.title_activity_sharewith)); - - mListView = findViewById(R.id.choose_conversation_list); + RecyclerView mListView = findViewById(R.id.choose_conversation_list); mAdapter = new ConversationAdapter(this, this.mConversations); - mListView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)); + mListView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); mListView.setAdapter(mAdapter); mAdapter.setConversationClickListener((view, conversation) -> share(conversation)); this.share = new Share(); @@ -203,57 +114,28 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer if (intent == null) { return; } - this.mReturnToPrevious = getBooleanPreference("return_to_previous", R.bool.return_to_previous); final String type = intent.getType(); final String action = intent.getAction(); - Log.d(Config.LOGTAG, "action: " + action + ", type:" + type); - share.uuid = intent.getStringExtra("uuid"); if (Intent.ACTION_SEND.equals(action)) { - final String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT); final String text = intent.getStringExtra(Intent.EXTRA_TEXT); final Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (type != null && uri != null && (text == null || !type.equals("text/plain"))) { this.share.uris.clear(); this.share.uris.add(uri); - this.share.image = type.startsWith("image/") || isImage(uri); - this.share.type = type; } else { - if (subject != null) { - this.share.text = format("[%s]%n%s", subject, text); - } else { - this.share.text = text; - } + this.share.text = text; } } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { - this.share.image = type != null && type.startsWith("image/"); - if (!this.share.image) { - return; - } this.share.uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); } if (xmppConnectionServiceBound) { - if (share.uuid != null) { - share(); - } else { - xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0); - } - } - - } - - protected boolean isImage(Uri uri) { - try { - String guess = URLConnection.guessContentTypeFromName(uri.toString()); - return (guess != null && guess.startsWith("image/")); - } catch (final StringIndexOutOfBoundsException ignored) { - return false; + xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0); } } @Override void onBackendConnected() { - if (xmppConnectionServiceBound && share != null - && ((share.contact != null && share.account != null) || share.uuid != null)) { + if (xmppConnectionServiceBound && share != null && ((share.contact != null && share.account != null))) { share(); return; } @@ -262,28 +144,19 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer private void share() { final Conversation conversation; - if (share.uuid != null) { - conversation = xmppConnectionService.findConversationByUuid(share.uuid); - if (conversation == null) { - return; - } - } else { - Account account; - try { - account = xmppConnectionService.findAccountByJid(Jid.of(share.account)); - } catch (final IllegalArgumentException e) { - account = null; - } - if (account == null) { - return; - } - - try { - conversation = xmppConnectionService - .findOrCreateConversation(account, Jid.of(share.contact), false, true); - } catch (final IllegalArgumentException e) { - return; - } + Account account; + try { + account = xmppConnectionService.findAccountByJid(Jid.of(share.account)); + } catch (final IllegalArgumentException e) { + account = null; + } + if (account == null) { + return; + } + try { + conversation = xmppConnectionService.findOrCreateConversation(account, Jid.of(share.contact), false, true); + } catch (final IllegalArgumentException e) { + return; } share(conversation); } @@ -293,110 +166,18 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer mPendingConversation = conversation; return; } - final Account account = conversation.getAccount(); - final XmppConnection connection = account.getXmppConnection(); - final long max = connection == null ? -1 : connection.getFeatures().getMaxHttpUploadSize(); - mListView.setEnabled(false); - if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP && !hasPgp()) { - if (share.uuid == null) { - showInstallPgpDialog(); - } else { - Toast.makeText(this, R.string.openkeychain_not_installed, Toast.LENGTH_SHORT).show(); - finish(); - } - return; + Intent intent = new Intent(this, ConversationsActivity.class); + intent.putExtra(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid()); + if (share.uris.size() > 0) { + intent.setAction(Intent.ACTION_SEND_MULTIPLE); + intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, share.uris); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + } else if (share.text != null) { + intent.setAction(ConversationsActivity.ACTION_VIEW_CONVERSATION); + intent.putExtra(ConversationsActivity.EXTRA_TEXT, share.text); } - if (share.uris.size() != 0) { - PresenceSelector.OnPresenceSelected callback = () -> { - attachmentCounter.set(share.uris.size()); - if (share.image) { - Log.d(Config.LOGTAG, "ShareWithActivity share() image " + share.uris.size() + " uri(s) " + share.uris.toString()); - share.multiple = share.uris.size() > 1; - replaceToast(getString(share.multiple ? R.string.preparing_images : R.string.preparing_image)); - for (Iterator i = share.uris.iterator(); i.hasNext(); i.remove()) { - final Uri uri = i.next(); - delegateUriPermissionsToService(uri); - xmppConnectionService.attachImageToConversation(conversation, uri, attachFileCallback); - } - } else { - Log.d(Config.LOGTAG, "ShareWithActivity share() file " + share.uris.size() + " uri(s) " + share.uris.toString()); - replaceToast(getString(R.string.preparing_file)); - final Uri uri = share.uris.get(0); - delegateUriPermissionsToService(uri); - xmppConnectionService.attachFileToConversation(conversation, uri, share.type, attachFileCallback); - finish(); - } - }; - if (account.httpUploadAvailable() - && ((share.image && !neverCompressPictures()) - || conversation.getMode() == Conversation.MODE_MULTI - || FileBackend.allFilesUnderSize(this, share.uris, max)) - && conversation.getNextEncryption() != Message.ENCRYPTION_OTR) { - callback.onPresenceSelected(); - } else { - selectPresence(conversation, callback); - } - } else { - if (mReturnToPrevious && this.share.text != null && !this.share.text.isEmpty()) { - final PresenceSelector.OnPresenceSelected callback = new PresenceSelector.OnPresenceSelected() { - - private void finishAndSend(Message message) { - replaceToast(getString(R.string.shared_text_with_x, conversation.getName())); - finish(); - } - - private UiCallback messageEncryptionCallback = new UiCallback() { - @Override - public void success(final Message message) { - runOnUiThread(() -> finishAndSend(message)); - } - - @Override - public void error(final int errorCode, Message object) { - runOnUiThread(() -> { - replaceToast(getString(errorCode)); - finish(); - }); - } - - @Override - public void userInputRequried(PendingIntent pi, Message object) { - finish(); - } - }; - - @Override - public void onPresenceSelected() { - - final int encryption = conversation.getNextEncryption(); - - Message message = new Message(conversation,share.text, encryption); - - Log.d(Config.LOGTAG,"on presence selected encrpytion="+encryption); - - if (encryption == Message.ENCRYPTION_PGP) { - replaceToast(getString(R.string.encrypting_message)); - xmppConnectionService.getPgpEngine().encrypt(message,messageEncryptionCallback); - return; - } - - if (encryption == Message.ENCRYPTION_OTR) { - message.setCounterpart(conversation.getNextCounterpart()); - } - xmppConnectionService.sendMessage(message); - finishAndSend(message); - } - }; - if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) { - selectPresence(conversation, callback); - } else { - callback.onPresenceSelected(); - } - } else { - switchToConversation(conversation, this.share.text, true); - } - } - + startActivity(intent); + finish(); } public void refreshUiReal() { @@ -404,12 +185,10 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer mAdapter.notifyDataSetChanged(); } - @Override - public void onBackPressed() { - if (attachmentCounter.get() >= 1) { - replaceToast(getString(R.string.sharing_files_please_wait)); - } else { - super.onBackPressed(); - } + private class Share { + public String account; + public String contact; + public String text; + ArrayList uris = new ArrayList<>(); } } \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/adapter/AccountAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/AccountAdapter.java index 01b432d65..e37ea6121 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/AccountAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/AccountAdapter.java @@ -24,7 +24,7 @@ import de.pixart.messenger.R; import de.pixart.messenger.entities.Account; import de.pixart.messenger.ui.ManageAccountActivity; import de.pixart.messenger.ui.XmppActivity; -import de.pixart.messenger.ui.util.Color; +import de.pixart.messenger.ui.util.StyledAttributes; import de.pixart.messenger.utils.UIHelper; public class AccountAdapter extends ArrayAdapter { @@ -65,14 +65,14 @@ public class AccountAdapter extends ArrayAdapter { statusView.setText(getContext().getString(account.getStatus().getReadableId())); switch (account.getStatus()) { case ONLINE: - statusView.setTextColor(Color.get(activity, R.attr.TextColorOnline)); + statusView.setTextColor(StyledAttributes.getColor(activity, R.attr.TextColorOnline)); break; case DISABLED: case CONNECTING: - statusView.setTextColor(Color.get(activity, android.R.attr.textColorSecondary)); + statusView.setTextColor(StyledAttributes.getColor(activity, android.R.attr.textColorSecondary)); break; default: - statusView.setTextColor(Color.get(activity, R.attr.TextColorError)); + statusView.setTextColor(StyledAttributes.getColor(activity, R.attr.TextColorError)); break; } final SwitchCompat tglAccountState = view.findViewById(R.id.tgl_account_status); diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java index 36cae0eb3..55dd6d65f 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java @@ -31,7 +31,7 @@ import de.pixart.messenger.entities.MucOptions; import de.pixart.messenger.entities.Transferable; import de.pixart.messenger.ui.ConversationFragment; import de.pixart.messenger.ui.XmppActivity; -import de.pixart.messenger.ui.util.Color; +import de.pixart.messenger.ui.util.StyledAttributes; import de.pixart.messenger.ui.widget.UnreadCountCustomView; import de.pixart.messenger.utils.EmojiWrapper; import de.pixart.messenger.utils.IrregularUnicodeDetector; @@ -97,9 +97,9 @@ public class ConversationAdapter extends RecyclerView.Adapter { } } if (offline) { - viewHolder.name.setTextColor(Color.get(activity, R.attr.text_Color_Main)); + viewHolder.name.setTextColor(StyledAttributes.get(activity, R.attr.text_Color_Main)); viewHolder.name.setAlpha(INACTIVE_ALPHA); viewHolder.jid.setAlpha(INACTIVE_ALPHA); viewHolder.avatar.setAlpha(INACTIVE_ALPHA); viewHolder.tags.setAlpha(INACTIVE_ALPHA); } else { if (ShowPresenceColoredNames()) { - viewHolder.name.setTextColor(color != 0 ? color : Color.get(activity, R.attr.text_Color_Main)); + viewHolder.name.setTextColor(color != 0 ? color : StyledAttributes.get(activity, R.attr.text_Color_Main)); } else { - viewHolder.name.setTextColor(Color.get(activity, R.attr.text_Color_Main)); + viewHolder.name.setTextColor(StyledAttributes.get(activity, R.attr.text_Color_Main)); } viewHolder.name.setAlpha(ACTIVE_ALPHA); viewHolder.jid.setAlpha(ACTIVE_ALPHA); diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java new file mode 100644 index 000000000..bbcaa5dc6 --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java @@ -0,0 +1,211 @@ +package de.pixart.messenger.ui.adapter; + +import android.app.Activity; +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.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.List; +import java.util.concurrent.RejectedExecutionException; + +import de.pixart.messenger.R; +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 final List mediaPreviews = new ArrayList<>(); + + private final ConversationFragment conversationFragment; + + public MediaPreviewAdapter(ConversationFragment fragment) { + this.conversationFragment = fragment; + } + + 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 MediaPreviewViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); + MediaPreviewBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.media_preview, parent, false); + return new MediaPreviewViewHolder(binding); + } + + @Override + public void onBindViewHolder(@NonNull MediaPreviewViewHolder holder, int position) { + final Context context = conversationFragment.getActivity(); + final Attachment attachment = mediaPreviews.get(position); + if (attachment.renderThumbnail()) { + holder.binding.mediaPreview.setImageAlpha(255); + loadPreview(attachment, holder.binding.mediaPreview); + } else { + cancelPotentialWork(attachment, holder.binding.mediaPreview); + holder.binding.mediaPreview.setBackgroundColor(StyledAttributes.getColor(context, R.attr.color_background_tertiary)); + holder.binding.mediaPreview.setImageAlpha(Math.round(StyledAttributes.getFloat(context, R.attr.icon_alpha) * 255)); + 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_file; + } 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 { + attr = R.attr.media_preview_file; + } + } + holder.binding.mediaPreview.setImageDrawable(StyledAttributes.getDrawable(context, attr)); + } + holder.binding.deleteButton.setOnClickListener(v -> { + int pos = mediaPreviews.indexOf(attachment); + mediaPreviews.remove(pos); + notifyItemRemoved(pos); + conversationFragment.toggleInputMethod(); + }); + } + + public void addMediaPreviews(List attachments) { + this.mediaPreviews.addAll(attachments); + notifyDataSetChanged(); + } + + private void loadPreview(Attachment attachment, ImageView imageView) { + if (cancelPotentialWork(attachment, imageView)) { + XmppActivity activity = (XmppActivity) conversationFragment.getActivity(); + final Bitmap bm = activity.xmppConnectionService.getFileBackend().getPreviewForUri(attachment, Math.round(activity.getResources().getDimension(R.dimen.media_preview_size)), 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(conversationFragment.getActivity().getResources(), null, task); + imageView.setImageDrawable(asyncDrawable); + try { + task.execute(attachment); + } catch (final RejectedExecutionException ignored) { + } + } + } + } + + @Override + public int getItemCount() { + return mediaPreviews.size(); + } + + public boolean hasAttachments() { + return mediaPreviews.size() > 0; + } + + public List getAttachments() { + return mediaPreviews; + } + + 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 MediaPreviewViewHolder extends RecyclerView.ViewHolder { + + private final MediaPreviewBinding binding; + + MediaPreviewViewHolder(MediaPreviewBinding 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) { + Activity activity = conversationFragment.getActivity(); + if (activity instanceof XmppActivity) { + final XmppActivity xmppActivity = (XmppActivity) activity; + this.attachment = params[0]; + return xmppActivity.xmppConnectionService.getFileBackend().getPreviewForUri(this.attachment, Math.round(xmppActivity.getResources().getDimension(R.dimen.media_preview_size)), false); + } else { + return null; + } + } + + @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/forms/FormFieldWrapper.java b/src/main/java/de/pixart/messenger/ui/forms/FormFieldWrapper.java index adcc11809..0dfd86327 100644 --- a/src/main/java/de/pixart/messenger/ui/forms/FormFieldWrapper.java +++ b/src/main/java/de/pixart/messenger/ui/forms/FormFieldWrapper.java @@ -1,7 +1,6 @@ package de.pixart.messenger.ui.forms; import android.content.Context; -import android.support.v4.content.ContextCompat; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; @@ -11,6 +10,7 @@ import android.view.View; import java.util.List; import de.pixart.messenger.R; +import de.pixart.messenger.ui.util.StyledAttributes; import de.pixart.messenger.xmpp.forms.Field; public abstract class FormFieldWrapper { @@ -18,9 +18,9 @@ public abstract class FormFieldWrapper { protected final Context context; protected final Field field; protected final View view; - protected OnFormFieldValuesEdited onFormFieldValuesEditedListener; + OnFormFieldValuesEdited onFormFieldValuesEditedListener; - protected FormFieldWrapper(Context context, Field field) { + FormFieldWrapper(Context context, Field field) { this.context = context; this.field = field; LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -58,7 +58,7 @@ public abstract class FormFieldWrapper { int start = label.length(); int end = label.length() + 2; spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), start, end, 0); - spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, R.color.accent)), start, end, 0); + spannableString.setSpan(new ForegroundColorSpan(StyledAttributes.getColor(context, R.color.accent)), start, end, 0); } return spannableString; } diff --git a/src/main/java/de/pixart/messenger/ui/util/Attachment.java b/src/main/java/de/pixart/messenger/ui/util/Attachment.java new file mode 100644 index 000000000..8c1d0c75e --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/util/Attachment.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018, Daniel Gultsch All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package de.pixart.messenger.ui.util; + +import android.content.ClipData; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import de.pixart.messenger.Config; +import de.pixart.messenger.utils.MimeUtils; + +public class Attachment { + private final Uri uri; + private final Type type; + private final UUID uuid; + private final String mime; + private Attachment(Uri uri, Type type, String mime) { + this.uri = uri; + this.type = type; + this.mime = mime; + this.uuid = UUID.randomUUID(); + } + + public static List of(final Context context, Uri uri, Type type) { + final String mime = type == Type.LOCATION ? null : MimeUtils.guessMimeTypeFromUri(context, uri); + return Collections.singletonList(new Attachment(uri, type, mime)); + } + + public static List of(final Context context, List uris) { + List attachments = new ArrayList<>(); + for (Uri uri : uris) { + final String mime = MimeUtils.guessMimeTypeFromUri(context, uri); + attachments.add(new Attachment(uri, mime != null && mime.startsWith("image/") ? Type.IMAGE : Type.FILE, mime)); + } + return attachments; + } + + public static List extractAttachments(final Context context, final Intent intent, Type type) { + List uris = new ArrayList<>(); + if (intent == null) { + return uris; + } + final String contentType = intent.getType(); + final Uri data = intent.getData(); + if (data == null) { + final ClipData clipData = intent.getClipData(); + if (clipData != null) { + for (int i = 0; i < clipData.getItemCount(); ++i) { + final Uri uri = clipData.getItemAt(i).getUri(); + Log.d(Config.LOGTAG, "uri=" + uri + " contentType=" + contentType); + final String mime = contentType != null ? contentType : MimeUtils.guessMimeTypeFromUri(context, uri); + Log.d(Config.LOGTAG, "mime=" + mime); + uris.add(new Attachment(uri, type, mime)); + } + } + } else { + final String mime = contentType != null ? contentType : MimeUtils.guessMimeTypeFromUri(context, data); + uris.add(new Attachment(data, type, mime)); + } + return uris; + } + + public String getMime() { + return mime; + } + + public Type getType() { + return type; + } + + public boolean renderThumbnail() { + return type == Type.IMAGE || (type == Type.FILE && mime != null && (mime.startsWith("video/") || mime.startsWith("image/"))); + } + + public Uri getUri() { + return uri; + } + + public UUID getUuid() { + return uuid; + } + + public enum Type { + FILE, IMAGE, LOCATION, RECORDING + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/util/AttachmentTool.java b/src/main/java/de/pixart/messenger/ui/util/AttachmentTool.java deleted file mode 100644 index c56f27ebf..000000000 --- a/src/main/java/de/pixart/messenger/ui/util/AttachmentTool.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2018, Daniel Gultsch All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package de.pixart.messenger.ui.util; - -import android.annotation.SuppressLint; -import android.content.ClipData; -import android.content.Intent; -import android.net.Uri; - -import java.util.ArrayList; -import java.util.List; - -public class AttachmentTool { - @SuppressLint("NewApi") - public static List extractUriFromIntent(final Intent intent) { - List uris = new ArrayList<>(); - if (intent == null) { - return uris; - } - final Uri uri = intent.getData(); - if (uri == null) { - final ClipData clipData = intent.getClipData(); - if (clipData != null) { - for (int i = 0; i < clipData.getItemCount(); ++i) { - uris.add(clipData.getItemAt(i).getUri()); - } - } - } else { - uris.add(uri); - } - return uris; - } -} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/util/Color.java b/src/main/java/de/pixart/messenger/ui/util/Color.java deleted file mode 100644 index 58ce6a465..000000000 --- a/src/main/java/de/pixart/messenger/ui/util/Color.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2018, Daniel Gultsch All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package de.pixart.messenger.ui.util; - - -import android.content.Context; -import android.content.res.TypedArray; -import android.support.annotation.AttrRes; -import android.support.annotation.ColorInt; - -public class Color { - - public static @ColorInt - int get(Context context, @AttrRes int attr) { - TypedArray typedArray = context.obtainStyledAttributes(new int[]{attr}); - int color = typedArray.getColor(0, 0); - typedArray.recycle(); - return color; - } - -} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/util/Drawable.java b/src/main/java/de/pixart/messenger/ui/util/Drawable.java deleted file mode 100644 index 5e0c770d4..000000000 --- a/src/main/java/de/pixart/messenger/ui/util/Drawable.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018, Daniel Gultsch All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package de.pixart.messenger.ui.util; - -import android.content.Context; -import android.content.res.TypedArray; -import android.support.annotation.AttrRes; - -public class Drawable { - public static android.graphics.drawable.Drawable get(Context context, @AttrRes int id) { - TypedArray typedArray = context.obtainStyledAttributes(new int[]{id}); - android.graphics.drawable.Drawable drawable = typedArray.getDrawable(0); - typedArray.recycle(); - return drawable; - } -} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/util/StyledAttributes.java b/src/main/java/de/pixart/messenger/ui/util/StyledAttributes.java new file mode 100644 index 000000000..cd4ad3e49 --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/util/StyledAttributes.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, Daniel Gultsch All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package de.pixart.messenger.ui.util; + + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.AttrRes; +import android.support.annotation.ColorInt; + +public class StyledAttributes { + public static android.graphics.drawable.Drawable getDrawable(Context context, @AttrRes int id) { + TypedArray typedArray = context.obtainStyledAttributes(new int[]{id}); + android.graphics.drawable.Drawable drawable = typedArray.getDrawable(0); + typedArray.recycle(); + return drawable; + } + + public static float getFloat(Context context, @AttrRes int id) { + TypedArray typedArray = context.obtainStyledAttributes(new int[]{id}); + float value = typedArray.getFloat(0, 0f); + typedArray.recycle(); + return value; + } + + public static @ColorInt + int getColor(Context context, @AttrRes int attr) { + TypedArray typedArray = context.obtainStyledAttributes(new int[]{attr}); + int color = typedArray.getColor(0, 0); + typedArray.recycle(); + return color; + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java b/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java index b54f8d074..c0c8ca770 100644 --- a/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java +++ b/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java @@ -50,7 +50,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import de.pixart.messenger.R; -import de.pixart.messenger.ui.util.Color; +import de.pixart.messenger.ui.util.StyledAttributes; import rocks.xmpp.addr.Jid; public class IrregularUnicodeDetector { @@ -73,7 +73,7 @@ public class IrregularUnicodeDetector { } public static Spannable style(Context context, Jid jid) { - return style(jid, Color.get(context, R.attr.color_warning)); + return style(jid, StyledAttributes.get(context, R.attr.color_warning)); } private static Spannable style(Jid jid, @ColorInt int color) { diff --git a/src/main/res/drawable-hdpi/ic_android_black_48dp.png b/src/main/res/drawable-hdpi/ic_android_black_48dp.png new file mode 100644 index 000000000..38f6c05e8 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_android_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_android_white_48dp.png b/src/main/res/drawable-hdpi/ic_android_white_48dp.png new file mode 100644 index 000000000..13108b25b Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_android_white_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_archive_black_48dp.png b/src/main/res/drawable-hdpi/ic_archive_black_48dp.png new file mode 100644 index 000000000..1faf474cd Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_archive_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_archive_white_48dp.png b/src/main/res/drawable-hdpi/ic_archive_white_48dp.png new file mode 100644 index 000000000..462016ade Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_archive_white_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_description_black_48dp.png b/src/main/res/drawable-hdpi/ic_description_black_48dp.png new file mode 100644 index 000000000..193ac1011 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_description_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_description_white_48dp.png b/src/main/res/drawable-hdpi/ic_description_white_48dp.png new file mode 100644 index 000000000..bfb5baa97 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_description_white_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_event_black_48dp.png b/src/main/res/drawable-hdpi/ic_event_black_48dp.png new file mode 100644 index 000000000..5cd32f4c2 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_event_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_event_white_48dp.png b/src/main/res/drawable-hdpi/ic_event_white_48dp.png new file mode 100644 index 000000000..653d15b2b Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_event_white_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_headset_black_48dp.png b/src/main/res/drawable-hdpi/ic_headset_black_48dp.png new file mode 100644 index 000000000..8a97fe7ec Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_headset_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_headset_white_48dp.png b/src/main/res/drawable-hdpi/ic_headset_white_48dp.png new file mode 100644 index 000000000..a4810f277 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_headset_white_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_mic_black_48dp.png b/src/main/res/drawable-hdpi/ic_mic_black_48dp.png new file mode 100644 index 000000000..4ed4168cd Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_mic_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_mic_white_48dp.png b/src/main/res/drawable-hdpi/ic_mic_white_48dp.png new file mode 100644 index 000000000..2d729e773 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_mic_white_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_person_black_48dp.png b/src/main/res/drawable-hdpi/ic_person_black_48dp.png new file mode 100644 index 000000000..7401e00b5 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_person_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_person_white_48dp.png b/src/main/res/drawable-hdpi/ic_person_white_48dp.png new file mode 100644 index 000000000..667c220dd Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_person_white_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_room_black_48dp.png b/src/main/res/drawable-hdpi/ic_room_black_48dp.png new file mode 100644 index 000000000..2ebc54430 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_room_black_48dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_room_white_48dp.png b/src/main/res/drawable-hdpi/ic_room_white_48dp.png new file mode 100644 index 000000000..29d2981b2 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_room_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_android_black_48dp.png b/src/main/res/drawable-mdpi/ic_android_black_48dp.png new file mode 100644 index 000000000..4f25964be Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_android_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_android_white_48dp.png b/src/main/res/drawable-mdpi/ic_android_white_48dp.png new file mode 100644 index 000000000..032fe2781 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_android_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_archive_black_48dp.png b/src/main/res/drawable-mdpi/ic_archive_black_48dp.png new file mode 100644 index 000000000..e9d5ed1b4 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_archive_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_archive_white_48dp.png b/src/main/res/drawable-mdpi/ic_archive_white_48dp.png new file mode 100644 index 000000000..82be16407 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_archive_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_description_black_48dp.png b/src/main/res/drawable-mdpi/ic_description_black_48dp.png new file mode 100644 index 000000000..7bc6a6846 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_description_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_description_white_48dp.png b/src/main/res/drawable-mdpi/ic_description_white_48dp.png new file mode 100644 index 000000000..9759bde29 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_description_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_event_black_48dp.png b/src/main/res/drawable-mdpi/ic_event_black_48dp.png new file mode 100644 index 000000000..8266743b4 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_event_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_event_white_48dp.png b/src/main/res/drawable-mdpi/ic_event_white_48dp.png new file mode 100644 index 000000000..2fb9a7a2c Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_event_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_headset_black_48dp.png b/src/main/res/drawable-mdpi/ic_headset_black_48dp.png new file mode 100644 index 000000000..36b513948 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_headset_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_headset_white_48dp.png b/src/main/res/drawable-mdpi/ic_headset_white_48dp.png new file mode 100644 index 000000000..798e229c7 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_headset_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_mic_black_48dp.png b/src/main/res/drawable-mdpi/ic_mic_black_48dp.png new file mode 100644 index 000000000..9c7caa295 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_mic_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_mic_white_48dp.png b/src/main/res/drawable-mdpi/ic_mic_white_48dp.png new file mode 100644 index 000000000..80d851e95 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_mic_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_person_black_48dp.png b/src/main/res/drawable-mdpi/ic_person_black_48dp.png new file mode 100644 index 000000000..76858f701 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_person_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_person_white_48dp.png b/src/main/res/drawable-mdpi/ic_person_white_48dp.png new file mode 100644 index 000000000..496699985 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_person_white_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_room_black_48dp.png b/src/main/res/drawable-mdpi/ic_room_black_48dp.png new file mode 100644 index 000000000..e60454537 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_room_black_48dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_room_white_48dp.png b/src/main/res/drawable-mdpi/ic_room_white_48dp.png new file mode 100644 index 000000000..8c51d01ad Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_room_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_android_black_48dp.png b/src/main/res/drawable-xhdpi/ic_android_black_48dp.png new file mode 100644 index 000000000..9f85a42bf Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_android_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_android_white_48dp.png b/src/main/res/drawable-xhdpi/ic_android_white_48dp.png new file mode 100644 index 000000000..913ebd69f Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_android_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_archive_black_48dp.png b/src/main/res/drawable-xhdpi/ic_archive_black_48dp.png new file mode 100644 index 000000000..6c383ee81 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_archive_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_archive_white_48dp.png b/src/main/res/drawable-xhdpi/ic_archive_white_48dp.png new file mode 100644 index 000000000..dbbf9f870 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_archive_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_description_black_48dp.png b/src/main/res/drawable-xhdpi/ic_description_black_48dp.png new file mode 100644 index 000000000..0da5f7798 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_description_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_description_white_48dp.png b/src/main/res/drawable-xhdpi/ic_description_white_48dp.png new file mode 100644 index 000000000..e1b8e9aec Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_description_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_event_black_48dp.png b/src/main/res/drawable-xhdpi/ic_event_black_48dp.png new file mode 100644 index 000000000..8e43444b7 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_event_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_event_white_48dp.png b/src/main/res/drawable-xhdpi/ic_event_white_48dp.png new file mode 100644 index 000000000..be533de42 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_event_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_headset_black_48dp.png b/src/main/res/drawable-xhdpi/ic_headset_black_48dp.png new file mode 100644 index 000000000..7f85eb8bb Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_headset_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_headset_white_48dp.png b/src/main/res/drawable-xhdpi/ic_headset_white_48dp.png new file mode 100644 index 000000000..b815a1944 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_headset_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_mic_black_48dp.png b/src/main/res/drawable-xhdpi/ic_mic_black_48dp.png new file mode 100644 index 000000000..e39b8170c Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_mic_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_mic_white_48dp.png b/src/main/res/drawable-xhdpi/ic_mic_white_48dp.png new file mode 100644 index 000000000..ec4405d44 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_mic_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_person_black_48dp.png b/src/main/res/drawable-xhdpi/ic_person_black_48dp.png new file mode 100644 index 000000000..2751da525 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_person_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_person_white_48dp.png b/src/main/res/drawable-xhdpi/ic_person_white_48dp.png new file mode 100644 index 000000000..6a77a6a38 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_person_white_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_room_black_48dp.png b/src/main/res/drawable-xhdpi/ic_room_black_48dp.png new file mode 100644 index 000000000..9d46eb841 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_room_black_48dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_room_white_48dp.png b/src/main/res/drawable-xhdpi/ic_room_white_48dp.png new file mode 100644 index 000000000..b7a61a2f5 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_room_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_android_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_android_black_48dp.png new file mode 100644 index 000000000..61b806d38 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_android_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_android_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_android_white_48dp.png new file mode 100644 index 000000000..c3bf2bdc3 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_android_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_archive_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_archive_black_48dp.png new file mode 100644 index 000000000..0155c8104 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_archive_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_archive_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_archive_white_48dp.png new file mode 100644 index 000000000..5a18abe12 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_archive_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_description_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_description_black_48dp.png new file mode 100644 index 000000000..9ddffa1f3 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_description_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_description_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_description_white_48dp.png new file mode 100644 index 000000000..b42cec8eb Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_description_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_event_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_event_black_48dp.png new file mode 100644 index 000000000..3eb5d3073 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_event_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_event_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_event_white_48dp.png new file mode 100644 index 000000000..44ead726f Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_event_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_headset_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_headset_black_48dp.png new file mode 100644 index 000000000..2a8236f35 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_headset_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_headset_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_headset_white_48dp.png new file mode 100644 index 000000000..2b6b2644f Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_headset_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_mic_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_mic_black_48dp.png new file mode 100644 index 000000000..44ef2fb4a Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_mic_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_mic_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_mic_white_48dp.png new file mode 100644 index 000000000..0fc42bfad Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_mic_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_person_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_person_black_48dp.png new file mode 100644 index 000000000..0001aee6b Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_person_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_person_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_person_white_48dp.png new file mode 100644 index 000000000..32fe521d0 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_person_white_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_room_black_48dp.png b/src/main/res/drawable-xxhdpi/ic_room_black_48dp.png new file mode 100644 index 000000000..e83824a17 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_room_black_48dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_room_white_48dp.png b/src/main/res/drawable-xxhdpi/ic_room_white_48dp.png new file mode 100644 index 000000000..dd8eb11d3 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_room_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_android_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_android_black_48dp.png new file mode 100644 index 000000000..1d1492b08 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_android_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_android_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_android_white_48dp.png new file mode 100644 index 000000000..d040e8639 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_android_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_archive_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_archive_black_48dp.png new file mode 100644 index 000000000..4dd5e44ab Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_archive_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_archive_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_archive_white_48dp.png new file mode 100644 index 000000000..5ac82a8df Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_archive_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_description_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_description_black_48dp.png new file mode 100644 index 000000000..f405b2931 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_description_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_description_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_description_white_48dp.png new file mode 100644 index 000000000..1d32d8841 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_description_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_event_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_event_black_48dp.png new file mode 100644 index 000000000..038df57d5 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_event_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_event_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_event_white_48dp.png new file mode 100644 index 000000000..1937048aa Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_event_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_headset_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_headset_black_48dp.png new file mode 100644 index 000000000..9a9a1b7f6 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_headset_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_headset_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_headset_white_48dp.png new file mode 100644 index 000000000..ba48f28a1 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_headset_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_mic_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_mic_black_48dp.png new file mode 100644 index 000000000..f2247b7ff Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_mic_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_mic_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_mic_white_48dp.png new file mode 100644 index 000000000..e9079bb3b Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_mic_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_person_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_person_black_48dp.png new file mode 100644 index 000000000..6d377123a Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_person_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_person_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_person_white_48dp.png new file mode 100644 index 000000000..5bb65aed1 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_person_white_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_room_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_room_black_48dp.png new file mode 100644 index 000000000..51d418cf7 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_room_black_48dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_room_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_room_white_48dp.png new file mode 100644 index 000000000..0f7de3f5d Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_room_white_48dp.png differ diff --git a/src/main/res/layout/fragment_conversation.xml b/src/main/res/layout/fragment_conversation.xml index 3ddcd69c7..acf42aafe 100644 --- a/src/main/res/layout/fragment_conversation.xml +++ b/src/main/res/layout/fragment_conversation.xml @@ -14,6 +14,7 @@ android:layout_height="match_parent" android:layout_above="@+id/snackbar" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:background="?attr/color_background_tertiary" android:divider="@null" @@ -53,7 +54,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true"> + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true"> + + diff --git a/src/main/res/layout/media_preview.xml b/src/main/res/layout/media_preview.xml new file mode 100644 index 000000000..8849e7b4a --- /dev/null +++ b/src/main/res/layout/media_preview.xml @@ -0,0 +1,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml index e89ed2944..b10a13815 100644 --- a/src/main/res/values/attrs.xml +++ b/src/main/res/values/attrs.xml @@ -42,6 +42,15 @@ + + + + + + + + + @@ -90,6 +99,7 @@ + diff --git a/src/main/res/values/defaults.xml b/src/main/res/values/defaults.xml index 4867a8e95..e213ea773 100644 --- a/src/main/res/values/defaults.xml +++ b/src/main/res/values/defaults.xml @@ -86,7 +86,6 @@ true true recent - false false false 144 diff --git a/src/main/res/values/dimens.xml b/src/main/res/values/dimens.xml index 50f955c89..c420781ea 100644 --- a/src/main/res/values/dimens.xml +++ b/src/main/res/values/dimens.xml @@ -10,6 +10,7 @@ 224dp 16dp + 80dp 4dp 8dp diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index aefe978c0..e5261bb44 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -712,8 +712,6 @@ %s have read up to this point %s has read up to this point %1$s and %2$d more have read up to this point - Quick Sharing - Immediately return to previous activity instead of opening the conversation after sharing something This chat is unencrypted, for security reasons you should activate message encryption by using the lock icon. The preferable encryption is OMEMO. Warn if chat is unencrypted If message encryption is available, you should use it. If you don\'t use message encryption, show a warning message inside the chat. diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 0e58f26a6..628963db2 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -65,6 +65,15 @@ @drawable/ic_send_voice_offline + @drawable/ic_description_black_48dp + @drawable/ic_mic_black_48dp + @drawable/ic_headset_black_48dp + @drawable/ic_room_black_48dp + @drawable/ic_person_black_48dp + @drawable/ic_android_black_48dp + @drawable/ic_event_black_48dp + @drawable/ic_archive_black_48dp + @drawable/ic_group_add_white_24dp @drawable/ic_person_add_white_24dp @drawable/ic_cancel_black_24dp @@ -106,6 +115,7 @@ 16dp 16dp 0.54 + 0.70 @drawable/ic_attach_camera @drawable/ic_attach_document @@ -219,10 +229,20 @@ @color/primary_dark 0.7 + 0.7 24dp 16dp + @drawable/ic_description_white_48dp + @drawable/ic_mic_white_48dp + @drawable/ic_headset_white_48dp + @drawable/ic_room_white_48dp + @drawable/ic_person_white_48dp + @drawable/ic_android_white_48dp + @drawable/ic_event_white_48dp + @drawable/ic_archive_white_48dp + @drawable/ic_group_add_white_24dp @drawable/ic_person_add_white_24dp @drawable/ic_cancel_white_24dp diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index d6241a5ff..819fcded9 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -203,11 +203,6 @@ android:key="video_compression" android:summary="@string/pref_video_compression_summary" android:title="@string/pref_video_compression" /> - Date: Sun, 23 Sep 2018 16:50:55 +0200 Subject: make media previews survive rotations --- .../pixart/messenger/ui/ConversationFragment.java | 97 ++++++++++++---------- .../messenger/ui/adapter/MediaPreviewAdapter.java | 4 +- .../de/pixart/messenger/ui/util/Attachment.java | 34 +++++++- 3 files changed, 89 insertions(+), 46 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 451ac6bde..137fca339 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -146,41 +146,40 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke public static final String RECENTLY_USED_QUICK_ACTION = "recently_used_quick_action"; public static final String STATE_CONVERSATION_UUID = ConversationFragment.class.getName() + ".uuid"; public static final String STATE_SCROLL_POSITION = ConversationFragment.class.getName() + ".scroll_position"; - public static final String STATE_PHOTO_URI = ConversationFragment.class.getName() + ".take_photo_uri"; - public static final String STATE_VIDEO_URI = ConversationFragment.class.getName() + ".take_video_uri"; + public static final String STATE_PHOTO_URI = ConversationFragment.class.getName() + ".media_previews"; + public static final String STATE_VIDEO_URI = ConversationFragment.class.getName() + ".media_previews"; + public static final String STATE_MEDIA_PREVIEWS = ConversationFragment.class.getName() + ".take_photo_uri"; private static final String STATE_LAST_MESSAGE_UUID = "state_last_message_uuid"; private final List messageList = new ArrayList<>(); - final private List mPendingImageUris = new ArrayList<>(); - private String lastMessageUuid = null; - public Uri mPendingEditorContent = null; private final PendingItem postponedActivityResult = new PendingItem<>(); private final PendingItem pendingConversationsUuid = new PendingItem<>(); + private final PendingItem> pendingMediaPreviews = new PendingItem<>(); private final PendingItem pendingExtras = new PendingItem<>(); private final PendingItem pendingTakePhotoUri = new PendingItem<>(); private final PendingItem pendingTakeVideoUri = new PendingItem<>(); private final PendingItem pendingScrollState = new PendingItem<>(); private final PendingItem pendingLastMessageUuid = new PendingItem<>(); private final PendingItem pendingMessage = new PendingItem<>(); - protected MessageAdapter messageListAdapter; - private Conversation conversation; + public Uri mPendingEditorContent = null; public FragmentConversationBinding binding; + protected MessageAdapter messageListAdapter; protected Message lastHistoryMessage = null; SimpleDateFormat sdf = new SimpleDateFormat("EEEE, dd. MMM yyyy", Locale.getDefault()); + private String lastMessageUuid = null; + private Conversation conversation; private Toast messageLoaderToast; private ConversationsActivity activity; - private boolean reInitRequiredOnStart = true; - private MediaPreviewAdapter mediaPreviewAdapter; - - private SimpleFingerGestures gesturesDetector = new SimpleFingerGestures(); - protected OnClickListener clickToVerify = new OnClickListener() { @Override public void onClick(View v) { activity.verifyOtrSessionDialog(conversation, v); } }; + private boolean reInitRequiredOnStart = true; + private MediaPreviewAdapter mediaPreviewAdapter; + private SimpleFingerGestures gesturesDetector = new SimpleFingerGestures(); private OnClickListener clickToMuc = new OnClickListener() { @Override @@ -487,32 +486,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } } }; - - @SuppressLint("RestrictedApi") - private void choose_attachment(View v) { - SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(activity); - final boolean hideVoice = p.getBoolean("show_record_voice_btn", activity.getResources().getBoolean(R.bool.show_record_voice_btn)); - PopupMenu popup = new PopupMenu(activity, v); - popup.inflate(R.menu.choose_attachment); - Menu menu = popup.getMenu(); - ConversationMenuConfigurator.configureQuickShareAttachmentMenu(conversation, menu, hideVoice); - popup.setOnMenuItemClickListener(attachmentItem -> { - switch (attachmentItem.getItemId()) { - case R.id.attach_choose_picture: - case R.id.attach_take_picture: - case R.id.attach_choose_file: - case R.id.attach_record_voice: - case R.id.attach_location: - handleAttachmentSelection(attachmentItem); - default: - return false; - } - }); - MenuPopupHelper menuHelper = new MenuPopupHelper(getActivity(), (MenuBuilder) menu, v); - menuHelper.setForceShowIcon(true); - menuHelper.show(); - } - private View.OnLongClickListener mSendButtonLongListener = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { @@ -644,6 +617,31 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } } + @SuppressLint("RestrictedApi") + private void choose_attachment(View v) { + SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(activity); + final boolean hideVoice = p.getBoolean("show_record_voice_btn", activity.getResources().getBoolean(R.bool.show_record_voice_btn)); + PopupMenu popup = new PopupMenu(activity, v); + popup.inflate(R.menu.choose_attachment); + Menu menu = popup.getMenu(); + ConversationMenuConfigurator.configureQuickShareAttachmentMenu(conversation, menu, hideVoice); + popup.setOnMenuItemClickListener(attachmentItem -> { + switch (attachmentItem.getItemId()) { + case R.id.attach_choose_picture: + case R.id.attach_take_picture: + case R.id.attach_choose_file: + case R.id.attach_record_voice: + case R.id.attach_location: + handleAttachmentSelection(attachmentItem); + default: + return false; + } + }); + MenuPopupHelper menuHelper = new MenuPopupHelper(getActivity(), (MenuBuilder) menu, v); + menuHelper.setForceShowIcon(true); + menuHelper.show(); + } + private void toggleScrollDownButton() { toggleScrollDownButton(binding.messagesView); } @@ -1470,10 +1468,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke clearHistoryDialog(conversation); break; case R.id.action_group_details: - Intent intent = new Intent(activity, ConferenceDetailsActivity.class); - intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC); - intent.putExtra("uuid", conversation.getUuid()); - startActivity(intent); + Intent intent = new Intent(activity, ConferenceDetailsActivity.class); + intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC); + intent.putExtra("uuid", conversation.getUuid()); + startActivity(intent); break; case R.id.action_contact_details: activity.switchToContactDetails(conversation.getContact()); @@ -2034,6 +2032,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke if (scrollState != null) { outState.putParcelable(STATE_SCROLL_POSITION, scrollState); } + final ArrayList attachments = mediaPreviewAdapter.getAttachments(); + if (attachments.size() > 0) { + outState.putParcelableArrayList(STATE_MEDIA_PREVIEWS, attachments); + } } } @@ -2044,10 +2046,14 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke return; } String uuid = savedInstanceState.getString(STATE_CONVERSATION_UUID); + ArrayList attachments = savedInstanceState.getParcelableArrayList(STATE_MEDIA_PREVIEWS); pendingLastMessageUuid.push(savedInstanceState.getString(STATE_LAST_MESSAGE_UUID, null)); if (uuid != null) { QuickLoader.set(uuid); this.pendingConversationsUuid.push(uuid); + if (attachments != null && attachments.size() > 0) { + this.pendingMediaPreviews.push(attachments); + } String takePhotoUri = savedInstanceState.getString(STATE_PHOTO_URI); if (takePhotoUri != null) { pendingTakePhotoUri.push(Uri.parse(takePhotoUri)); @@ -3044,9 +3050,15 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke reInit(conversation); ScrollState scrollState = pendingScrollState.pop(); String lastMessageUuid = pendingLastMessageUuid.pop(); + List attachments = pendingMediaPreviews.pop(); if (scrollState != null) { setScrollPosition(scrollState, lastMessageUuid); } + if (attachments != null && attachments.size() > 0) { + Log.d(Config.LOGTAG, "had attachments on restore"); + mediaPreviewAdapter.addMediaPreviews(attachments); + toggleInputMethod(); + } return true; } @@ -3061,7 +3073,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } - public Conversation getConversation() { return conversation; } 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 bbcaa5dc6..c89ce6216 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java @@ -29,7 +29,7 @@ import de.pixart.messenger.ui.util.StyledAttributes; public class MediaPreviewAdapter extends RecyclerView.Adapter { - private final List mediaPreviews = new ArrayList<>(); + private final ArrayList mediaPreviews = new ArrayList<>(); private final ConversationFragment conversationFragment; @@ -150,7 +150,7 @@ public class MediaPreviewAdapter extends RecyclerView.Adapter 0; } - public List getAttachments() { + public ArrayList getAttachments() { return mediaPreviews; } 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 8c1d0c75e..f11efd0d1 100644 --- a/src/main/java/de/pixart/messenger/ui/util/Attachment.java +++ b/src/main/java/de/pixart/messenger/ui/util/Attachment.java @@ -33,6 +33,8 @@ import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; import android.util.Log; import java.util.ArrayList; @@ -43,11 +45,28 @@ import java.util.UUID; import de.pixart.messenger.Config; import de.pixart.messenger.utils.MimeUtils; -public class Attachment { +public class Attachment implements Parcelable { + public static final Creator CREATOR = new Parcelable.Creator() { + @Override + public Attachment createFromParcel(Parcel in) { + return new Attachment(in); + } + + @Override + public Attachment[] newArray(int size) { + return new Attachment[size]; + } + }; private final Uri uri; 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(Uri uri, Type type, String mime) { this.uri = uri; this.type = type; @@ -94,6 +113,19 @@ public class Attachment { return uris; } + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(uri, flags); + dest.writeString(mime); + dest.writeString(uuid.toString()); + dest.writeString(type.toString()); + } + + @Override + public int describeContents() { + return 0; + } + public String getMime() { return mime; } -- cgit v1.2.3 From 032466bb9936099fa9164dd733bc264739edc7fb Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 23 Sep 2018 16:54:13 +0200 Subject: add icon for unknown file while keeping 'file' icon for documents --- .../messenger/ui/adapter/MediaPreviewAdapter.java | 16 ++++++++++++++-- src/main/res/drawable-hdpi/ic_help_black_48dp.png | Bin 0 -> 1176 bytes src/main/res/drawable-hdpi/ic_help_white_48dp.png | Bin 0 -> 1177 bytes src/main/res/drawable-mdpi/ic_help_black_48dp.png | Bin 0 -> 656 bytes src/main/res/drawable-mdpi/ic_help_white_48dp.png | Bin 0 -> 659 bytes src/main/res/drawable-xhdpi/ic_help_black_48dp.png | Bin 0 -> 1406 bytes src/main/res/drawable-xhdpi/ic_help_white_48dp.png | Bin 0 -> 1426 bytes src/main/res/drawable-xxhdpi/ic_help_black_48dp.png | Bin 0 -> 2613 bytes src/main/res/drawable-xxhdpi/ic_help_white_48dp.png | Bin 0 -> 2702 bytes src/main/res/drawable-xxxhdpi/ic_help_black_48dp.png | Bin 0 -> 2945 bytes src/main/res/drawable-xxxhdpi/ic_help_white_48dp.png | Bin 0 -> 3067 bytes src/main/res/values/attrs.xml | 3 ++- src/main/res/values/themes.xml | 6 ++++-- 13 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 src/main/res/drawable-hdpi/ic_help_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_help_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_help_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_help_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_help_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_help_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_help_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_help_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_help_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_help_white_48dp.png (limited to 'src/main') 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 c89ce6216..3d9bce508 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java @@ -17,6 +17,7 @@ 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; @@ -29,6 +30,15 @@ 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,7 +99,7 @@ public class MediaPreviewAdapter extends RecyclerView.Adapter - + @@ -50,6 +50,7 @@ + diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 628963db2..0d2eab4fe 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -65,7 +65,7 @@ @drawable/ic_send_voice_offline - @drawable/ic_description_black_48dp + @drawable/ic_description_black_48dp @drawable/ic_mic_black_48dp @drawable/ic_headset_black_48dp @drawable/ic_room_black_48dp @@ -73,6 +73,7 @@ @drawable/ic_android_black_48dp @drawable/ic_event_black_48dp @drawable/ic_archive_black_48dp + @drawable/ic_help_black_48dp @drawable/ic_group_add_white_24dp @drawable/ic_person_add_white_24dp @@ -234,7 +235,7 @@ 24dp 16dp - @drawable/ic_description_white_48dp + @drawable/ic_description_white_48dp @drawable/ic_mic_white_48dp @drawable/ic_headset_white_48dp @drawable/ic_room_white_48dp @@ -242,6 +243,7 @@ @drawable/ic_android_white_48dp @drawable/ic_event_white_48dp @drawable/ic_archive_white_48dp + @drawable/ic_help_white_48dp @drawable/ic_group_add_white_24dp @drawable/ic_person_add_white_24dp -- cgit v1.2.3 From 33f7d5cd9a0e6fb1fb8e75fa5410365935ab1af5 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 23 Sep 2018 16:57:47 +0200 Subject: made foreground service logging more meaninful --- .../de/pixart/messenger/services/XmppConnectionService.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index b46c2f606..25d4fb2b8 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -431,7 +431,6 @@ public class XmppConnectionService extends Service { public void stopForcingForegroundNotification() { mForceForegroundService.set(false); toggleForegroundService(); - mNotificationService.dismissForcedForegroundNotification(); } public boolean areMessagesInitialized() { @@ -1233,19 +1232,21 @@ public class XmppConnectionService extends Service { } public void toggleForegroundService() { + final boolean status; if (mForceForegroundService.get() || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) { startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, this.mNotificationService.createForegroundNotification()); - Log.d(Config.LOGTAG, "started foreground service"); + status = true; } else { stopForeground(true); - Log.d(Config.LOGTAG, "stopped foreground service"); + mNotificationService.dismissForcedForegroundNotification(); //if the channel was changed the previous call might fail + status = false; } + Log.d(Config.LOGTAG, "ForegroundService: " + (status ? "on" : "off")); } @Override public void onTaskRemoved(final Intent rootIntent) { super.onTaskRemoved(rootIntent); - //TODO check for accounts enabled if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mForceForegroundService.get()) { Log.d(Config.LOGTAG, "ignoring onTaskRemoved because foreground service is activated"); } else { @@ -2670,7 +2671,7 @@ public class XmppConnectionService extends Service { private boolean hasEnabledAccounts() { if (this.accounts == null) { - return true; // set to true if accounts could not be fetched - used for notifications + return false; // set to false if accounts could not be fetched - used for notifications } for (Account account : this.accounts) { if (account.isEnabled()) { -- cgit v1.2.3 From f873cd2b5f9ea6fdf76bfe6e5b283543ac3d97d7 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 23 Sep 2018 19:58:11 +0200 Subject: show media preview in messagebubble like text messages --- .../java/de/pixart/messenger/ui/ConversationFragment.java | 12 ++++++++++-- src/main/java/de/pixart/messenger/ui/SearchActivity.java | 3 +-- src/main/java/de/pixart/messenger/ui/SettingsActivity.java | 1 + .../java/de/pixart/messenger/ui/adapter/ListItemAdapter.java | 6 +++--- .../messenger/ui/util/ConversationMenuConfigurator.java | 5 +++-- .../java/de/pixart/messenger/ui/util/SendButtonTool.java | 12 ++++++++---- .../de/pixart/messenger/utils/IrregularUnicodeDetector.java | 2 +- src/main/res/layout/fragment_conversation.xml | 1 + 8 files changed, 28 insertions(+), 14 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 137fca339..5f66c4200 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -171,6 +171,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke private Conversation conversation; private Toast messageLoaderToast; private ConversationsActivity activity; + private Menu mOptionsMenu; protected OnClickListener clickToVerify = new OnClickListener() { @Override public void onClick(View v) { @@ -1068,6 +1069,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke boolean hasAttachments = mediaPreviewAdapter.hasAttachments(); binding.textinput.setVisibility(hasAttachments ? View.GONE : View.VISIBLE); binding.mediaPreview.setVisibility(hasAttachments ? View.VISIBLE : View.GONE); + ConversationMenuConfigurator.configureAttachmentMenu(conversation, mOptionsMenu, activity.xmppConnectionService.getAttachmentChoicePreference(), hasAttachments); updateSendButton(); } @@ -1117,6 +1119,8 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke @Override public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { + mOptionsMenu = menu; + boolean hasAttachments = mediaPreviewAdapter != null && mediaPreviewAdapter.hasAttachments(); menuInflater.inflate(R.menu.fragment_conversation, menu); final MenuItem menuInviteContact = menu.findItem(R.id.action_invite); final MenuItem menuNeedHelp = menu.findItem(R.id.action_create_issue); @@ -1139,7 +1143,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } menuNeedHelp.setVisible(true); menuSearchUpdates.setVisible(false); - ConversationMenuConfigurator.configureAttachmentMenu(conversation, menu, activity.xmppConnectionService.getAttachmentChoicePreference()); + ConversationMenuConfigurator.configureAttachmentMenu(conversation, menu, activity.xmppConnectionService.getAttachmentChoicePreference(), hasAttachments); ConversationMenuConfigurator.configureEncryptionMenu(conversation, menu); } else { menuNeedHelp.setVisible(false); @@ -1159,7 +1163,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke binding.textinput.addTextChangedListener(new StylingHelper.MessageEditorStyler(binding.textinput)); binding.textinput.setOnEditorActionListener(mEditorActionListener); binding.textinput.setRichContentListener(new String[]{"image/*"}, mEditorContentListener); - binding.textinput.setBackgroundResource(activity.isDarkTheme() ? R.drawable.message_bubble_sent_blue_dark : R.drawable.message_bubble_sent_blue); + binding.textinput.setBackgroundResource(messageInputBubble()); binding.textSendButton.setOnClickListener(this.mSendButtonListener); binding.textSendButton.setOnLongClickListener(this.mSendButtonLongListener); @@ -1170,6 +1174,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke binding.messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL); mediaPreviewAdapter = new MediaPreviewAdapter(this); binding.mediaPreview.setAdapter(mediaPreviewAdapter); + binding.mediaPreview.setBackgroundResource(messageInputBubble()); messageListAdapter = new MessageAdapter((XmppActivity) getActivity(), this.messageList); messageListAdapter.setOnContactPictureClicked(message -> { String fingerprint; @@ -3072,6 +3077,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } } + private int messageInputBubble() { + return activity.isDarkTheme() ? R.drawable.message_bubble_sent_blue_dark : R.drawable.message_bubble_sent_blue; + } public Conversation getConversation() { return conversation; diff --git a/src/main/java/de/pixart/messenger/ui/SearchActivity.java b/src/main/java/de/pixart/messenger/ui/SearchActivity.java index 9ea9e7592..e9ba1d426 100644 --- a/src/main/java/de/pixart/messenger/ui/SearchActivity.java +++ b/src/main/java/de/pixart/messenger/ui/SearchActivity.java @@ -56,12 +56,11 @@ import de.pixart.messenger.services.MessageSearchTask; import de.pixart.messenger.ui.adapter.MessageAdapter; import de.pixart.messenger.ui.interfaces.OnSearchResultsAvailable; import de.pixart.messenger.ui.util.ChangeWatcher; -import de.pixart.messenger.ui.util.StyledAttributes; import de.pixart.messenger.ui.util.DateSeparator; -import de.pixart.messenger.ui.util.Drawable; import de.pixart.messenger.ui.util.ListViewUtils; import de.pixart.messenger.ui.util.PendingItem; import de.pixart.messenger.ui.util.ShareUtil; +import de.pixart.messenger.ui.util.StyledAttributes; import de.pixart.messenger.utils.FtsUtils; import de.pixart.messenger.utils.MessageUtils; diff --git a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java index c9c6006de..1c0992cf1 100644 --- a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java @@ -38,6 +38,7 @@ import de.pixart.messenger.crypto.OmemoSetting; import de.pixart.messenger.entities.Account; import de.pixart.messenger.services.ExportLogsService; import de.pixart.messenger.services.MemorizingTrustManager; +import de.pixart.messenger.ui.util.StyledAttributes; import de.pixart.messenger.utils.TimeframeUtils; import rocks.xmpp.addr.Jid; diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java index 1f1b2877e..17479cf99 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java @@ -105,16 +105,16 @@ public class ListItemAdapter extends ArrayAdapter { } } if (offline) { - viewHolder.name.setTextColor(StyledAttributes.get(activity, R.attr.text_Color_Main)); + viewHolder.name.setTextColor(StyledAttributes.getColor(activity, R.attr.text_Color_Main)); viewHolder.name.setAlpha(INACTIVE_ALPHA); viewHolder.jid.setAlpha(INACTIVE_ALPHA); viewHolder.avatar.setAlpha(INACTIVE_ALPHA); viewHolder.tags.setAlpha(INACTIVE_ALPHA); } else { if (ShowPresenceColoredNames()) { - viewHolder.name.setTextColor(color != 0 ? color : StyledAttributes.get(activity, R.attr.text_Color_Main)); + viewHolder.name.setTextColor(color != 0 ? color : StyledAttributes.getColor(activity, R.attr.text_Color_Main)); } else { - viewHolder.name.setTextColor(StyledAttributes.get(activity, R.attr.text_Color_Main)); + viewHolder.name.setTextColor(StyledAttributes.getColor(activity, R.attr.text_Color_Main)); } viewHolder.name.setAlpha(ACTIVE_ALPHA); viewHolder.jid.setAlpha(ACTIVE_ALPHA); diff --git a/src/main/java/de/pixart/messenger/ui/util/ConversationMenuConfigurator.java b/src/main/java/de/pixart/messenger/ui/util/ConversationMenuConfigurator.java index 5c86b4a1b..edca88f78 100644 --- a/src/main/java/de/pixart/messenger/ui/util/ConversationMenuConfigurator.java +++ b/src/main/java/de/pixart/messenger/ui/util/ConversationMenuConfigurator.java @@ -65,12 +65,13 @@ public class ConversationMenuConfigurator { menu.findItem(R.id.attach_location).setVisible(locationAvailable); } - public static void configureAttachmentMenu(@NonNull Conversation conversation, Menu menu, Boolean Quick_share_attachment_choice) { + public static void configureAttachmentMenu(@NonNull Conversation conversation, Menu menu, Boolean Quick_share_attachment_choice, boolean hasAttachments) { final MenuItem menuAttach = menu.findItem(R.id.action_attach_file); - if (Quick_share_attachment_choice) { + if (Quick_share_attachment_choice && !hasAttachments) { menuAttach.setVisible(false); return; } + final boolean visible; if (conversation.getMode() == Conversation.MODE_MULTI) { visible = conversation.getAccount().httpUploadAvailable() && conversation.getMucOptions().participating(); diff --git a/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java b/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java index b4b0ecc28..67cd48b6a 100644 --- a/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java +++ b/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java @@ -44,7 +44,6 @@ import de.pixart.messenger.utils.UIHelper; public class SendButtonTool { public static SendButtonAction getAction(Activity activity, Conversation c, String text) { - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); final boolean empty = text.length() == 0; final boolean conference = c.getMode() == Conversation.MODE_MULTI; if (c.getCorrectingMessage() != null && (empty || text.equals(c.getCorrectingMessage().getBody()))) { @@ -57,14 +56,14 @@ public class SendButtonTool { } } else { if (empty) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); if (conference && c.getNextCounterpart() != null) { return SendButtonAction.CANCEL; } else { - boolean quickShareChoice = preferences.getBoolean(SettingsActivity.QUICK_SHARE_ATTACHMENT_CHOICE, activity.getResources().getBoolean(R.bool.quick_share_attachment_choice)); String setting = preferences.getString("quick_action", activity.getResources().getString(R.string.quick_action)); - if (quickShareChoice && AttachmentsVisible(c)) { + if (quickShareChoice(activity) && AttachmentsVisible(c)) { return SendButtonAction.CHOOSE_ATTACHMENT; - } else if (quickShareChoice && !AttachmentsVisible(c)) { + } else if (quickShareChoice(activity) && !AttachmentsVisible(c)) { return SendButtonAction.TEXT; } else { if (!setting.equals("none") && UIHelper.receivedLocationQuestion(c.getLatestMessage())) { @@ -198,4 +197,9 @@ public class SendButtonTool { return res; } + + public static boolean quickShareChoice(Activity activity) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); + return preferences.getBoolean(SettingsActivity.QUICK_SHARE_ATTACHMENT_CHOICE, activity.getResources().getBoolean(R.bool.quick_share_attachment_choice)); + } } \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java b/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java index c0c8ca770..3cd715a4c 100644 --- a/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java +++ b/src/main/java/de/pixart/messenger/utils/IrregularUnicodeDetector.java @@ -73,7 +73,7 @@ public class IrregularUnicodeDetector { } public static Spannable style(Context context, Jid jid) { - return style(jid, StyledAttributes.get(context, R.attr.color_warning)); + return style(jid, StyledAttributes.getColor(context, R.attr.color_warning)); } private static Spannable style(Jid jid, @ColorInt int color) { diff --git a/src/main/res/layout/fragment_conversation.xml b/src/main/res/layout/fragment_conversation.xml index acf42aafe..16f48bde2 100644 --- a/src/main/res/layout/fragment_conversation.xml +++ b/src/main/res/layout/fragment_conversation.xml @@ -86,6 +86,7 @@ android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_toStartOf="@+id/textSendButton" + android:background="@drawable/message_bubble_sent_blue" android:orientation="horizontal" android:paddingTop="8dp" android:requiresFadingEdge="horizontal" -- cgit v1.2.3 From 7e5b0a49e809130b018a5f33d26b8efa28304d6c Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 23 Sep 2018 20:00:37 +0200 Subject: fix media preview in tablet mode --- src/main/java/de/pixart/messenger/ui/ConversationFragment.java | 2 ++ .../java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 5f66c4200..0da5cf69c 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -2131,6 +2131,8 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } updateChatState(this.conversation, msg); messageListAdapter.stopAudioPlayer(); + mediaPreviewAdapter.clearPreviews(); + toggleInputMethod(); } public void reInit(Conversation conversation, Bundle extras) { 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 3d9bce508..9192c6555 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MediaPreviewAdapter.java @@ -179,6 +179,11 @@ public class MediaPreviewAdapter extends RecyclerView.Adapter Date: Sun, 23 Sep 2018 21:16:19 +0200 Subject: use different menu items for record video and take photo --- .../pixart/messenger/ui/ConversationFragment.java | 79 ++++++++------------- .../pixart/messenger/ui/util/SendButtonAction.java | 17 +++-- .../pixart/messenger/ui/util/SendButtonTool.java | 15 +++- src/main/res/drawable-hdpi/ic_attach_videocam.png | Bin 0 -> 222 bytes .../res/drawable-hdpi/ic_send_videocam_away.png | Bin 0 -> 342 bytes .../res/drawable-hdpi/ic_send_videocam_dnd.png | Bin 0 -> 397 bytes .../res/drawable-hdpi/ic_send_videocam_online.png | Bin 0 -> 389 bytes src/main/res/drawable-mdpi/ic_attach_videocam.png | Bin 0 -> 137 bytes .../res/drawable-mdpi/ic_send_videocam_away.png | Bin 0 -> 217 bytes .../res/drawable-mdpi/ic_send_videocam_dnd.png | Bin 0 -> 242 bytes .../res/drawable-mdpi/ic_send_videocam_online.png | Bin 0 -> 245 bytes src/main/res/drawable-xhdpi/ic_attach_videocam.png | Bin 0 -> 202 bytes .../res/drawable-xhdpi/ic_send_videocam_away.png | Bin 0 -> 307 bytes .../res/drawable-xhdpi/ic_send_videocam_dnd.png | Bin 0 -> 325 bytes .../res/drawable-xhdpi/ic_send_videocam_online.png | Bin 0 -> 318 bytes .../res/drawable-xxhdpi/ic_attach_videocam.png | Bin 0 -> 294 bytes .../res/drawable-xxhdpi/ic_send_videocam_away.png | Bin 0 -> 609 bytes .../res/drawable-xxhdpi/ic_send_videocam_dnd.png | Bin 0 -> 667 bytes .../drawable-xxhdpi/ic_send_videocam_online.png | Bin 0 -> 654 bytes .../res/drawable-xxxhdpi/ic_attach_videocam.png | Bin 0 -> 405 bytes .../res/drawable-xxxhdpi/ic_send_videocam_away.png | Bin 0 -> 630 bytes .../res/drawable-xxxhdpi/ic_send_videocam_dnd.png | Bin 0 -> 663 bytes .../drawable-xxxhdpi/ic_send_videocam_online.png | Bin 0 -> 643 bytes src/main/res/menu/choose_attachment.xml | 7 +- src/main/res/menu/fragment_conversation.xml | 36 ++++++---- src/main/res/values/arrays.xml | 6 +- src/main/res/values/attrs.xml | 1 + src/main/res/values/themes.xml | 2 + 28 files changed, 90 insertions(+), 73 deletions(-) create mode 100644 src/main/res/drawable-hdpi/ic_attach_videocam.png create mode 100644 src/main/res/drawable-hdpi/ic_send_videocam_away.png create mode 100644 src/main/res/drawable-hdpi/ic_send_videocam_dnd.png create mode 100644 src/main/res/drawable-hdpi/ic_send_videocam_online.png create mode 100644 src/main/res/drawable-mdpi/ic_attach_videocam.png create mode 100644 src/main/res/drawable-mdpi/ic_send_videocam_away.png create mode 100644 src/main/res/drawable-mdpi/ic_send_videocam_dnd.png create mode 100644 src/main/res/drawable-mdpi/ic_send_videocam_online.png create mode 100644 src/main/res/drawable-xhdpi/ic_attach_videocam.png create mode 100644 src/main/res/drawable-xhdpi/ic_send_videocam_away.png create mode 100644 src/main/res/drawable-xhdpi/ic_send_videocam_dnd.png create mode 100644 src/main/res/drawable-xhdpi/ic_send_videocam_online.png create mode 100644 src/main/res/drawable-xxhdpi/ic_attach_videocam.png create mode 100644 src/main/res/drawable-xxhdpi/ic_send_videocam_away.png create mode 100644 src/main/res/drawable-xxhdpi/ic_send_videocam_dnd.png create mode 100644 src/main/res/drawable-xxhdpi/ic_send_videocam_online.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_attach_videocam.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_send_videocam_away.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_send_videocam_dnd.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_send_videocam_online.png (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 0da5cf69c..94a7871bd 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -136,18 +136,18 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke public static final int REQUEST_ADD_EDITOR_CONTENT = 0x0211; public static final int ATTACHMENT_CHOICE = 0x0300; public static final int ATTACHMENT_CHOICE_CHOOSE_IMAGE = 0x0301; - public static final int ATTACHMENT_CHOICE_TAKE_FROM_CAMERA = 0x0302; + public static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302; public static final int ATTACHMENT_CHOICE_CHOOSE_FILE = 0x0303; public static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x0304; public static final int ATTACHMENT_CHOICE_LOCATION = 0x0305; public static final int ATTACHMENT_CHOICE_CHOOSE_VIDEO = 0x0306; + public static final int ATTACHMENT_CHOICE_RECORD_VIDEO = 0x0307; public static final int ATTACHMENT_CHOICE_INVALID = 0x0399; public static final String RECENTLY_USED_QUICK_ACTION = "recently_used_quick_action"; public static final String STATE_CONVERSATION_UUID = ConversationFragment.class.getName() + ".uuid"; public static final String STATE_SCROLL_POSITION = ConversationFragment.class.getName() + ".scroll_position"; public static final String STATE_PHOTO_URI = ConversationFragment.class.getName() + ".media_previews"; - public static final String STATE_VIDEO_URI = ConversationFragment.class.getName() + ".media_previews"; public static final String STATE_MEDIA_PREVIEWS = ConversationFragment.class.getName() + ".take_photo_uri"; private static final String STATE_LAST_MESSAGE_UUID = "state_last_message_uuid"; @@ -459,7 +459,8 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke switch (action) { case CHOOSE_ATTACHMENT: choose_attachment(v); - case TAKE_FROM_CAMERA: + case TAKE_PHOTO: + case RECORD_VIDEO: case SEND_LOCATION: case RECORD_VOICE: case CHOOSE_PICTURE: @@ -630,6 +631,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke switch (attachmentItem.getItemId()) { case R.id.attach_choose_picture: case R.id.attach_take_picture: + case R.id.attach_record_video: case R.id.attach_choose_file: case R.id.attach_record_voice: case R.id.attach_location: @@ -1005,7 +1007,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke mediaPreviewAdapter.addMediaPreviews(imageUris); toggleInputMethod(); break; - case ATTACHMENT_CHOICE_TAKE_FROM_CAMERA: + case ATTACHMENT_CHOICE_TAKE_PHOTO: final Uri takePhotoUri = pendingTakePhotoUri.pop(); if (takePhotoUri != null) { mediaPreviewAdapter.addMediaPreviews(Attachment.of(getActivity(), takePhotoUri, Attachment.Type.IMAGE)); @@ -1015,6 +1017,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } break; case ATTACHMENT_CHOICE_CHOOSE_FILE: + case ATTACHMENT_CHOICE_RECORD_VIDEO: case ATTACHMENT_CHOICE_RECORD_VOICE: final Attachment.Type type = requestCode == ATTACHMENT_CHOICE_RECORD_VOICE ? Attachment.Type.RECORDING : Attachment.Type.FILE; final List fileUris = Attachment.extractAttachments(getActivity(), data, type); @@ -1444,6 +1447,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke break; case R.id.attach_choose_picture: case R.id.attach_take_picture: + case R.id.attach_record_video: case R.id.attach_choose_file: case R.id.attach_record_voice: case R.id.attach_location: @@ -1500,7 +1504,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke attachFile(ATTACHMENT_CHOICE_CHOOSE_IMAGE); break; case R.id.attach_take_picture: - attachFile(ATTACHMENT_CHOICE_TAKE_FROM_CAMERA); + attachFile(ATTACHMENT_CHOICE_TAKE_PHOTO); + break; + case R.id.attach_record_video: + attachFile(ATTACHMENT_CHOICE_RECORD_VIDEO); break; case R.id.attach_choose_file: attachFile(ATTACHMENT_CHOICE_CHOOSE_FILE); @@ -1560,7 +1567,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke if (!hasPermissions(attachmentChoice, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO)) { return; } - } else if (attachmentChoice == ATTACHMENT_CHOICE_TAKE_FROM_CAMERA) { + } else if (attachmentChoice == ATTACHMENT_CHOICE_TAKE_PHOTO || attachmentChoice == ATTACHMENT_CHOICE_RECORD_VIDEO) { if (!hasPermissions(attachmentChoice, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)) { return; } @@ -1746,7 +1753,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke final int encryption = conversation.getNextEncryption(); final Account account = conversation.getAccount(); final PresenceSelector.OnPresenceSelected callback = () -> { - final Intent intent = new Intent(); + Intent intent = new Intent(); boolean chooser = false; switch (attachmentChoice) { case ATTACHMENT_CHOICE_CHOOSE_IMAGE: @@ -1763,32 +1770,16 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setAction(Intent.ACTION_GET_CONTENT); break; - case ATTACHMENT_CHOICE_TAKE_FROM_CAMERA: - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setTitle(getString(R.string.attach_take_from_camera)); - builder.setNegativeButton(getString(R.string.action_take_photo), - (dialog, which) -> { - final Uri uri = activity.xmppConnectionService.getFileBackend().getTakePhotoUri(); - pendingTakePhotoUri.push(uri); - intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); - startActivityForResult(intent, attachmentChoice); - activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out); - }); - builder.setPositiveButton(getString(R.string.action_take_video), - (dialog, which) -> { - final Uri uri = activity.xmppConnectionService.getFileBackend().getTakeVideoUri(); - pendingTakeVideoUri.push(uri); - intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE); - startActivityForResult(intent, attachmentChoice); - activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out); - }); - builder.create().show(); + case ATTACHMENT_CHOICE_RECORD_VIDEO: + intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE); + break; + case ATTACHMENT_CHOICE_TAKE_PHOTO: + final Uri uri = activity.xmppConnectionService.getFileBackend().getTakePhotoUri(); + pendingTakePhotoUri.push(uri); + intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); break; case ATTACHMENT_CHOICE_CHOOSE_FILE: chooser = true; @@ -1798,12 +1789,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke intent.setAction(Intent.ACTION_GET_CONTENT); break; case ATTACHMENT_CHOICE_RECORD_VOICE: - startActivityForResult(new Intent(getActivity(), RecordingActivity.class), attachmentChoice); - activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out); + intent = new Intent(getActivity(), RecordingActivity.class); break; case ATTACHMENT_CHOICE_LOCATION: - startActivityForResult(new Intent(getActivity(), ShareLocationActivity.class), attachmentChoice); - activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out); + intent = new Intent(getActivity(), ShareLocationActivity.class); break; } if (intent.resolveActivity(getActivity().getPackageManager()) != null) { @@ -1812,8 +1801,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke startActivityForResult( Intent.createChooser(intent, getString(R.string.perform_action_with)), attachmentChoice); + activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out); } else { startActivityForResult(intent, attachmentChoice); + activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out); } } }; @@ -2025,13 +2016,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke if (conversation != null) { outState.putString(STATE_CONVERSATION_UUID, conversation.getUuid()); outState.putString(STATE_LAST_MESSAGE_UUID, lastMessageUuid); - final Uri PhotoUri = pendingTakePhotoUri.peek(); - final Uri VideoUri = pendingTakeVideoUri.peek(); - if (PhotoUri != null) { - outState.putString(STATE_PHOTO_URI, PhotoUri.toString()); - } - if (VideoUri != null) { - outState.putString(STATE_VIDEO_URI, VideoUri.toString()); + final Uri uri = pendingTakePhotoUri.peek(); + if (uri != null) { + outState.putString(STATE_PHOTO_URI, uri.toString()); } final ScrollState scrollState = getScrollPosition(); if (scrollState != null) { @@ -2063,10 +2050,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke if (takePhotoUri != null) { pendingTakePhotoUri.push(Uri.parse(takePhotoUri)); } - String takeVideoUri = savedInstanceState.getString(STATE_VIDEO_URI); - if (takeVideoUri != null) { - pendingTakeVideoUri.push(Uri.parse(takeVideoUri)); - } pendingScrollState.push(savedInstanceState.getParcelable(STATE_SCROLL_POSITION)); } } diff --git a/src/main/java/de/pixart/messenger/ui/util/SendButtonAction.java b/src/main/java/de/pixart/messenger/ui/util/SendButtonAction.java index 9f9fabc5a..c7feb2105 100644 --- a/src/main/java/de/pixart/messenger/ui/util/SendButtonAction.java +++ b/src/main/java/de/pixart/messenger/ui/util/SendButtonAction.java @@ -33,10 +33,11 @@ import static de.pixart.messenger.ui.ConversationFragment.ATTACHMENT_CHOICE; import static de.pixart.messenger.ui.ConversationFragment.ATTACHMENT_CHOICE_CHOOSE_IMAGE; import static de.pixart.messenger.ui.ConversationFragment.ATTACHMENT_CHOICE_LOCATION; import static de.pixart.messenger.ui.ConversationFragment.ATTACHMENT_CHOICE_RECORD_VOICE; -import static de.pixart.messenger.ui.ConversationFragment.ATTACHMENT_CHOICE_TAKE_FROM_CAMERA; +import static de.pixart.messenger.ui.ConversationFragment.ATTACHMENT_CHOICE_RECORD_VIDEO; +import static de.pixart.messenger.ui.ConversationFragment.ATTACHMENT_CHOICE_TAKE_PHOTO; public enum SendButtonAction { - TEXT, TAKE_FROM_CAMERA, SEND_LOCATION, RECORD_VOICE, CANCEL, CHOOSE_PICTURE, CHOOSE_ATTACHMENT; + TEXT, TAKE_PHOTO, SEND_LOCATION, RECORD_VOICE, CANCEL, CHOOSE_PICTURE, RECORD_VIDEO, CHOOSE_ATTACHMENT; public static SendButtonAction valueOfOrDefault(String setting, SendButtonAction text) { try { @@ -52,8 +53,10 @@ public enum SendButtonAction { return SEND_LOCATION; case ATTACHMENT_CHOICE_RECORD_VOICE: return RECORD_VOICE; - case ATTACHMENT_CHOICE_TAKE_FROM_CAMERA: - return TAKE_FROM_CAMERA; + case ATTACHMENT_CHOICE_RECORD_VIDEO: + return RECORD_VIDEO; + case ATTACHMENT_CHOICE_TAKE_PHOTO: + return TAKE_PHOTO; case ATTACHMENT_CHOICE_CHOOSE_IMAGE: return CHOOSE_PICTURE; case ATTACHMENT_CHOICE: @@ -65,8 +68,10 @@ public enum SendButtonAction { public int toChoice() { switch (this) { - case TAKE_FROM_CAMERA: - return ATTACHMENT_CHOICE_TAKE_FROM_CAMERA; + case TAKE_PHOTO: + return ATTACHMENT_CHOICE_TAKE_PHOTO; + case RECORD_VIDEO: + return ATTACHMENT_CHOICE_RECORD_VIDEO; case SEND_LOCATION: return ATTACHMENT_CHOICE_LOCATION; case RECORD_VOICE: diff --git a/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java b/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java index 67cd48b6a..96bcad183 100644 --- a/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java +++ b/src/main/java/de/pixart/messenger/ui/util/SendButtonTool.java @@ -105,7 +105,20 @@ public class SendButtonTool { default: return getThemeResource(activity, R.attr.ic_send_text_offline, R.drawable.ic_send_text_offline); } - case TAKE_FROM_CAMERA: + case RECORD_VIDEO: + switch (status) { + case CHAT: + case ONLINE: + return R.drawable.ic_send_videocam_online; + case AWAY: + return R.drawable.ic_send_videocam_away; + case XA: + case DND: + return R.drawable.ic_send_videocam_dnd; + default: + return getThemeResource(activity, R.attr.ic_send_videocam_offline, R.drawable.ic_send_videocam_offline); + } + case TAKE_PHOTO: switch (status) { case CHAT: case ONLINE: diff --git a/src/main/res/drawable-hdpi/ic_attach_videocam.png b/src/main/res/drawable-hdpi/ic_attach_videocam.png new file mode 100644 index 000000000..f95861633 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_attach_videocam.png differ diff --git a/src/main/res/drawable-hdpi/ic_send_videocam_away.png b/src/main/res/drawable-hdpi/ic_send_videocam_away.png new file mode 100644 index 000000000..950db9d9e Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_send_videocam_away.png differ diff --git a/src/main/res/drawable-hdpi/ic_send_videocam_dnd.png b/src/main/res/drawable-hdpi/ic_send_videocam_dnd.png new file mode 100644 index 000000000..8a3588678 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_send_videocam_dnd.png differ diff --git a/src/main/res/drawable-hdpi/ic_send_videocam_online.png b/src/main/res/drawable-hdpi/ic_send_videocam_online.png new file mode 100644 index 000000000..ac5af607f Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_send_videocam_online.png differ diff --git a/src/main/res/drawable-mdpi/ic_attach_videocam.png b/src/main/res/drawable-mdpi/ic_attach_videocam.png new file mode 100644 index 000000000..66aa2fe49 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_attach_videocam.png differ diff --git a/src/main/res/drawable-mdpi/ic_send_videocam_away.png b/src/main/res/drawable-mdpi/ic_send_videocam_away.png new file mode 100644 index 000000000..55399ac8d Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_send_videocam_away.png differ diff --git a/src/main/res/drawable-mdpi/ic_send_videocam_dnd.png b/src/main/res/drawable-mdpi/ic_send_videocam_dnd.png new file mode 100644 index 000000000..608947d59 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_send_videocam_dnd.png differ diff --git a/src/main/res/drawable-mdpi/ic_send_videocam_online.png b/src/main/res/drawable-mdpi/ic_send_videocam_online.png new file mode 100644 index 000000000..90a152504 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_send_videocam_online.png differ diff --git a/src/main/res/drawable-xhdpi/ic_attach_videocam.png b/src/main/res/drawable-xhdpi/ic_attach_videocam.png new file mode 100644 index 000000000..5f6054b81 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_attach_videocam.png differ diff --git a/src/main/res/drawable-xhdpi/ic_send_videocam_away.png b/src/main/res/drawable-xhdpi/ic_send_videocam_away.png new file mode 100644 index 000000000..69e340800 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_send_videocam_away.png differ diff --git a/src/main/res/drawable-xhdpi/ic_send_videocam_dnd.png b/src/main/res/drawable-xhdpi/ic_send_videocam_dnd.png new file mode 100644 index 000000000..e7f784d8b Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_send_videocam_dnd.png differ diff --git a/src/main/res/drawable-xhdpi/ic_send_videocam_online.png b/src/main/res/drawable-xhdpi/ic_send_videocam_online.png new file mode 100644 index 000000000..7cda9e6f0 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_send_videocam_online.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_attach_videocam.png b/src/main/res/drawable-xxhdpi/ic_attach_videocam.png new file mode 100644 index 000000000..e74d2a776 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_attach_videocam.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_send_videocam_away.png b/src/main/res/drawable-xxhdpi/ic_send_videocam_away.png new file mode 100644 index 000000000..ce04c7790 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_send_videocam_away.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_send_videocam_dnd.png b/src/main/res/drawable-xxhdpi/ic_send_videocam_dnd.png new file mode 100644 index 000000000..24890da09 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_send_videocam_dnd.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_send_videocam_online.png b/src/main/res/drawable-xxhdpi/ic_send_videocam_online.png new file mode 100644 index 000000000..079cdef19 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_send_videocam_online.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_attach_videocam.png b/src/main/res/drawable-xxxhdpi/ic_attach_videocam.png new file mode 100644 index 000000000..02fddb640 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_attach_videocam.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_send_videocam_away.png b/src/main/res/drawable-xxxhdpi/ic_send_videocam_away.png new file mode 100644 index 000000000..7e517e6be Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_send_videocam_away.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_send_videocam_dnd.png b/src/main/res/drawable-xxxhdpi/ic_send_videocam_dnd.png new file mode 100644 index 000000000..3077ee233 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_send_videocam_dnd.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_send_videocam_online.png b/src/main/res/drawable-xxxhdpi/ic_send_videocam_online.png new file mode 100644 index 000000000..0baef17f4 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_send_videocam_online.png differ diff --git a/src/main/res/menu/choose_attachment.xml b/src/main/res/menu/choose_attachment.xml index ae6f47a95..a9a57404d 100644 --- a/src/main/res/menu/choose_attachment.xml +++ b/src/main/res/menu/choose_attachment.xml @@ -14,7 +14,12 @@ + android:title="@string/action_take_photo" /> + + + android:title="@string/action_secure" + app:showAsAction="always"> + android:title="@string/attach_file" + app:showAsAction="always"> + android:title="@string/action_take_photo" /> + + + + android:title="@string/invite_contact" + app:showAsAction="never" /> + android:title="@string/action_clear_history" + app:showAsAction="never" /> + android:title="@string/action_end_conversation" + app:showAsAction="never" /> + android:title="@string/create_issue" + app:showAsAction="never" /> \ No newline at end of file diff --git a/src/main/res/values/arrays.xml b/src/main/res/values/arrays.xml index ff36fe0ae..93da9bac4 100644 --- a/src/main/res/values/arrays.xml +++ b/src/main/res/values/arrays.xml @@ -37,7 +37,8 @@ @string/none @string/recently_used - @string/attach_take_from_camera + @string/action_take_photo + @string/action_take_video @string/attach_choose_picture @string/attach_record_voice @string/send_location @@ -46,7 +47,8 @@ none recent - TAKE_FROM_CAMERA + TAKE_PHOTO + RECORD_VIDEO CHOOSE_PICTURE RECORD_VOICE SEND_LOCATION diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml index c8ccec47a..672cb00fb 100644 --- a/src/main/res/values/attrs.xml +++ b/src/main/res/values/attrs.xml @@ -93,6 +93,7 @@ + diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 0d2eab4fe..50cf8e93a 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -119,6 +119,7 @@ 0.70 @drawable/ic_attach_camera + @drawable/ic_attach_videocam @drawable/ic_attach_document @drawable/ic_attach_location @drawable/ic_attach_photo @@ -221,6 +222,7 @@ @drawable/ic_attach_camera_white + @drawable/ic_attach_videocam_white @drawable/ic_attach_videocam_white @drawable/ic_attach_document_white @drawable/ic_attach_location_white -- cgit v1.2.3 From 3c71297965573ffbd3eb423296790b416dc9ce05 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Mon, 24 Sep 2018 19:45:05 +0200 Subject: catch NPE --- src/main/java/de/pixart/messenger/ui/ConversationFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 94a7871bd..9961e014b 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -1072,7 +1072,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke boolean hasAttachments = mediaPreviewAdapter.hasAttachments(); binding.textinput.setVisibility(hasAttachments ? View.GONE : View.VISIBLE); binding.mediaPreview.setVisibility(hasAttachments ? View.VISIBLE : View.GONE); - ConversationMenuConfigurator.configureAttachmentMenu(conversation, mOptionsMenu, activity.xmppConnectionService.getAttachmentChoicePreference(), hasAttachments); + if (mOptionsMenu != null) { + ConversationMenuConfigurator.configureAttachmentMenu(conversation, mOptionsMenu, activity.xmppConnectionService.getAttachmentChoicePreference(), hasAttachments); + } updateSendButton(); } -- cgit v1.2.3 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/persistance/DatabaseBackend.java | 24 +++ .../pixart/messenger/persistance/FileBackend.java | 77 ++++--- .../messenger/services/ExportLogsService.java | 4 +- .../messenger/services/XmppConnectionService.java | 9 + .../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 +++ src/main/res/layout/activity_contact_details.xml | 54 ++++- src/main/res/layout/activity_muc_details.xml | 46 +++++ src/main/res/layout/media.xml | 16 ++ src/main/res/values/dimens.xml | 3 +- src/main/res/values/strings.xml | 1 + 23 files changed, 651 insertions(+), 122 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 create mode 100644 src/main/res/layout/media.xml (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java index 94710b86e..54d99ec43 100644 --- a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java +++ b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java @@ -35,6 +35,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; import de.pixart.messenger.Config; @@ -787,6 +788,29 @@ public class DatabaseBackend extends SQLiteOpenHelper { }; } + public List getRelativeFilePaths(Account account, Jid jid, int limit) { + SQLiteDatabase db = this.getReadableDatabase(); + final String SQL = "select uuid,relativeFilePath from messages where type in (1,2) and conversationUuid=(select uuid from conversations where accountUuid=? and (contactJid=? or contactJid like ?)) order by timeSent desc"; + final String[] args = {account.getUuid(), jid.asBareJid().toEscapedString(), jid.asBareJid().toEscapedString() + "/%"}; + Cursor cursor = db.rawQuery(SQL + (limit > 0 ? " limit " + String.valueOf(limit) : ""), args); + List filesPaths = new ArrayList<>(); + while (cursor.moveToNext()) { + filesPaths.add(new FilePath(cursor.getString(0), cursor.getString(1))); + } + cursor.close(); + return filesPaths; + } + + public static class FilePath { + public final UUID uuid; + public final String path; + + private FilePath(String uuid, String path) { + this.uuid = UUID.fromString(uuid); + this.path = path; + } + } + public Conversation findConversation(final Account account, final Jid contactJid) { SQLiteDatabase db = this.getReadableDatabase(); String[] selectionArgs = {account.getUuid(), diff --git a/src/main/java/de/pixart/messenger/persistance/FileBackend.java b/src/main/java/de/pixart/messenger/persistance/FileBackend.java index 35967e624..92bb84e33 100644 --- a/src/main/java/de/pixart/messenger/persistance/FileBackend.java +++ b/src/main/java/de/pixart/messenger/persistance/FileBackend.java @@ -46,6 +46,7 @@ import java.security.DigestOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; @@ -81,8 +82,8 @@ public class FileBackend { } private void createNoMedia() { - final File nomedia_files = new File(getConversationsDirectory("Files", true) + ".nomedia"); - final File nomedia_audios = new File(getConversationsDirectory("Audios", true) + ".nomedia"); + final File nomedia_files = new File(getConversationsDirectory("Files") + ".nomedia"); + final File nomedia_audios = new File(getConversationsDirectory("Audios") + ".nomedia"); if (!nomedia_files.exists()) { try { nomedia_files.createNewFile(); @@ -100,8 +101,8 @@ public class FileBackend { } public void updateMediaScanner(File file) { - if (file.getAbsolutePath().startsWith(getConversationsDirectory("Images", true)) - || file.getAbsolutePath().startsWith(getConversationsDirectory("Videos", true))) { + if (file.getAbsolutePath().startsWith(getConversationsDirectory("Images")) + || file.getAbsolutePath().startsWith(getConversationsDirectory("Videos"))) { Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(Uri.fromFile(file)); mXmppConnectionService.sendBroadcast(intent); @@ -130,13 +131,13 @@ public class FileBackend { file = new DownloadableFile(path); } else { if (mime != null && mime.startsWith("image")) { - file = new DownloadableFile(getConversationsDirectory("Images", true) + path); + file = new DownloadableFile(getConversationsDirectory("Images") + path); } else if (mime != null && mime.startsWith("video")) { - file = new DownloadableFile(getConversationsDirectory("Videos", true) + path); + file = new DownloadableFile(getConversationsDirectory("Videos") + path); } else if (mime != null && mime.startsWith("audio")) { - file = new DownloadableFile(getConversationsDirectory("Audios", true) + path); + file = new DownloadableFile(getConversationsDirectory("Audios") + path); } else { - file = new DownloadableFile(getConversationsDirectory("Files", true) + path); + file = new DownloadableFile(getConversationsDirectory("Files") + path); } } return file; @@ -152,7 +153,7 @@ public class FileBackend { } final DownloadableFile file = getFileForPath(path, message.getMimeType()); if (encrypted) { - return new DownloadableFile(getConversationsDirectory("Files", true) + file.getName() + ".pgp"); + return new DownloadableFile(getConversationsDirectory("Files") + file.getName() + ".pgp"); } else { return file; } @@ -202,31 +203,43 @@ public class FileBackend { return true; } - public static String getDirectoryName(final String type, final boolean isMedia) { - String media = ""; - if (isMedia) { - media = "Media/Pix-Art Messenger "; + public List convertToAttachments(List relativeFilePaths) { + List attachments = new ArrayList<>(); + for (DatabaseBackend.FilePath relativeFilePath : relativeFilePaths) { + final String mime = MimeUtils.guessMimeTypeFromExtension(MimeUtils.extractRelevantExtension(relativeFilePath.path)); + Log.d(Config.LOGTAG, "mime=" + mime); + File file = getFileForPath(relativeFilePath.path, mime); + if (file.exists()) { + attachments.add(Attachment.of(relativeFilePath.uuid, file, mime)); + } else { + Log.d(Config.LOGTAG, "file " + file.getAbsolutePath() + " doesn't exist"); + } } - if (type == "null" || type == null) { - return "/Pix-Art Messenger/"; + return attachments; + } + + public static String getConversationsDirectory(final String type) { + if (type.equalsIgnoreCase("null") || type == null) { + return getAppMediaDirectory() + "Pix-Art Messenger" + "/"; } else { - return "/Pix-Art Messenger" + "/" + media + type + "/"; + return getAppMediaDirectory() + "Pix-Art Messenger" + " " + type + "/"; } } - public static String getConversationsDirectory(final String type, final boolean isMedia) { - String DirName = null; - if (type != "null" || type != null) { - DirName = type; - } - String path = Environment.getExternalStorageDirectory().getAbsolutePath() + getDirectoryName(DirName, isMedia); - File createFolders = new File(path); - if (!createFolders.exists()) { - Log.d(Config.LOGTAG, "creating directory " + createFolders); - createFolders.mkdirs(); - } - return path; + public static String getAppMediaDirectory() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "Pix-Art Messenger" + "/Media/"; + } + + public static String getBackupDirectory() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "Pix-Art Messenger" + "/Database/"; + } + + public static String getAppLogsDirectory() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "Pix-Art Messenger" + "/Chats/"; + } + public static String getAppUpdateDirectory() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "Pix-Art Messenger" + "/Update/"; } private Bitmap resize(final Bitmap originalBitmap, int size) throws IOException { @@ -298,7 +311,7 @@ public class FileBackend { Log.d(Config.LOGTAG, "File path = null"); return false; } - if (path.contains(getDirectoryName("null", true))) { + if (path.contains(getConversationsDirectory("null"))) { Log.d(Config.LOGTAG, "File " + path + " is in our directory"); return true; } @@ -1061,12 +1074,12 @@ public class FileBackend { } public Bitmap getPreviewForUri(Attachment attachment, int size, boolean cacheOnly) { + final String key = "attachment_" + attachment.getUuid().toString() + "_" + String.valueOf(size); final LruCache cache = mXmppConnectionService.getBitmapCache(); - Bitmap bitmap = cache.get(attachment.getUuid().toString()); + Bitmap bitmap = cache.get(key); if (bitmap != null || cacheOnly) { return bitmap; } - Log.d(Config.LOGTAG, "attachment mime=" + attachment.getMime()); if (attachment.getMime() != null && attachment.getMime().startsWith("video/")) { bitmap = cropCenterSquareVideo(attachment.getUri(), size); drawOverlay(bitmap, R.drawable.play_video, 0.75f); @@ -1079,7 +1092,7 @@ public class FileBackend { bitmap = withGifOverlay; } } - cache.put(attachment.getUuid().toString(), bitmap); + cache.put(key, bitmap); return bitmap; } diff --git a/src/main/java/de/pixart/messenger/services/ExportLogsService.java b/src/main/java/de/pixart/messenger/services/ExportLogsService.java index b0da108ba..e66873acc 100644 --- a/src/main/java/de/pixart/messenger/services/ExportLogsService.java +++ b/src/main/java/de/pixart/messenger/services/ExportLogsService.java @@ -41,7 +41,7 @@ import static de.pixart.messenger.ui.SettingsActivity.USE_MULTI_ACCOUNTS; public class ExportLogsService extends XmppConnectionService { private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsDirectory("Chats", false) + "%s"; + private static final String DIRECTORY_STRING_FORMAT = FileBackend.getAppLogsDirectory() + "%s"; private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n"; private static AtomicBoolean running = new AtomicBoolean(false); boolean ReadableLogsEnabled = false; @@ -171,7 +171,7 @@ public class ExportLogsService extends XmppConnectionService { // Get hold of the db: FileInputStream InputFile = new FileInputStream(this.getDatabasePath(DatabaseBackend.DATABASE_NAME)); // Set the output folder on the SDcard - File directory = new File(FileBackend.getConversationsDirectory("Database", false)); + File directory = new File(FileBackend.getBackupDirectory()); // Create the folder if it doesn't exist: if (!directory.exists()) { boolean directory_created = directory.mkdirs(); diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index 25d4fb2b8..cd35198dc 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -116,6 +116,7 @@ import de.pixart.messenger.persistance.FileBackend; import de.pixart.messenger.ui.SettingsActivity; import de.pixart.messenger.ui.UiCallback; import de.pixart.messenger.ui.interfaces.OnAvatarPublication; +import de.pixart.messenger.ui.interfaces.OnMediaLoaded; import de.pixart.messenger.ui.interfaces.OnSearchResultsAvailable; import de.pixart.messenger.utils.Compatibility; import de.pixart.messenger.utils.ConversationsFileObserver; @@ -2681,6 +2682,14 @@ public class XmppConnectionService extends Service { return false; } + public void getAttachments(final Conversation conversation, int limit, final OnMediaLoaded onMediaLoaded) { + getAttachments(conversation.getAccount(), conversation.getJid().asBareJid(), limit, onMediaLoaded); + } + + public void getAttachments(final Account account, final Jid jid, final int limit, final OnMediaLoaded onMediaLoaded) { + new Thread(() -> onMediaLoaded.onMediaLoaded(fileBackend.convertToAttachments(databaseBackend.getRelativeFilePaths(account, jid, limit)))).start(); + } + public void persistSelfNick(MucOptions.User self) { final Conversation conversation = self.getConversation(); Jid full = self.getFullJid(); 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 diff --git a/src/main/res/layout/activity_contact_details.xml b/src/main/res/layout/activity_contact_details.xml index dd3ff2c31..64e296c24 100644 --- a/src/main/res/layout/activity_contact_details.xml +++ b/src/main/res/layout/activity_contact_details.xml @@ -1,6 +1,5 @@ - + - + android:orientation="horizontal"> + + + + + + + + +